#! /Usr/bin/perl
# Written by finalbsd at 2008-11-20.
# The netstat Original written by C
# Is expensive to me, so this born.
# As long as you retain this notice you
# Can do whatever you want with this stuff.
# If we meet some day, and you think
# This stuff is worth it, you can
# Buy me a beer in return.
Use strict;
Use warnings;
Use getopt: STD;
My $ TCP = "/proc/NET/tcp ";
My $ tcp6 = "/proc/NET/tcp6 ";
My $ route = "/proc/NET/route ";
My @ tcpstate = (
"Null ",
"Established ",
"Syn_sent ",
"Syn_recv ",
"Fin_wait1 ",
"Fin_wait2 ",
"Time_wait ",
"Close ",
"Close_wait ",
"Last_ack ",
"Listen ",
"Closing"
);
My @ routetype = (
"Null ",
"U", # Up
"G", # Gateway
"Ug" # Up & Gateway
);
My % opts;
Getopts ('nhatsrl',/% opts );
If ($ opts {H }){
& Usage ();
}
If ($ opts {r }){
& Route_info ($ route );
Exit;
}
& Tcp_info ($ TCP );
& Tcp_info ($ tcp6 );
###################### Function Definition ################ ###########
#############################
# Get statistics information
############################
Sub tcp_info ($ ){
My $ file = shift;
Open (FH, $ file) or die ("$! ");
My $ format = "%-30 S %-30 S %-10 s/n ";
Printf ($ format, "Local Address", "foreign address", "State ");
While (<FH> ){
Next if/local_address /;
My @ DATA = split;
My $ state = $ tcpstate [hex ($ data [3])];
# Show listening sockets.
If ($ opts {L }){
Printf ($ format, & hextoint ($ data [1]), & hextoint ($ data [2]), $ state) If $ state = ~ /LIST /;
} Else {
Printf ($ format, & hextoint ($ data [1]), & hextoint ($ data [2]), $ State );
}
}
Close (FH );
}
#############################
# Convert hex to int
############################
Sub hextoint ($ ){
My $ TMP = shift;
My @ data;
My @ IP;
My $ int;
# If have ':', then it's ADDR: Port, else just port.
If ($ TMP = ~ /:/){
If ($ TMP = ~ /FFFF /){
@ DATA = Split/:/, $ TMP;
# Break it and do convert later.
@ IP = $ data [0] = ~ // W {2}/g;
Foreach my $ index (12 .. 15 ){
$ IP [$ Index] = hex ($ IP [$ Index]);
}
$ Int = sprintf ("%-5 S % d. % d. % d. % d: % d "," tcp6 ", $ IP [15], $ IP [14], $ IP [13], $ IP [12], hex ($ data [1]);
} Else {
@ DATA = Split/:/, $ TMP;
@ IP = $ data [0] = ~ // W {2}/g;
Foreach my $ index (0 .. 3 ){
$ IP [$ Index] = hex ($ IP [$ Index]);
}
$ Int = sprintf ("%-S % d. % d. % d. % d: % d "," ", $ IP [3], $ IP [2], $ IP [1], $ IP [0], hex ($ data [1]);
}
} Else {
@ IP = $ TMP = ~ // W {2}/g;
Foreach my $ index (0 .. 3 ){
$ IP [$ Index] = hex ($ IP [$ Index]);
}
$ Int = sprintf ("% d. % d. % d. % d ", Hex ($ IP [3]), Hex ($ IP [2]), Hex ($ IP [1]), hex ($ IP [0]);
}
Return $ int;
}
#############################
# Show kernel route table
############################
Sub route_info ($ ){
My $ routefile = shift;
Open (route, $ routefile) or die ("can't open route file! /N ");
My $ header = "iface destination gateway flags genmask/N ";
Printf ("% s", $ header );
My $ format = "%-5 S %-15 S %-15 S %-5 S %-15 s/n ";
While (<Route> ){
Next if/iface /;
My @ line = split;
My ($ iface, $ DEST, $ GW, $ flags, $ mask) = ($ line [0],
& Hextoint ($ line [1]), & hextoint ($ line [2]), Hex ($ line [3]),
& Hextoint ($ line [7]);
Printf ($ format, $ iface, $ DEST, $ GW, $ routetype [$ flags], $ mask );
}
Close (route );
}
#############################
# Show Help Information
############################
Sub usage {
Printf ("% s/n %-30 s/n %-30 s/n %-30 s/n %-30 s/n %-30 s/n % -30 s/n ",
"Netstat written in Perl by finalbsd. Copyright (c) 2008 .",
"-N show numeric IP and port address .",
"-R display the kernel routing table .",
"-A show both listening and non-listening socktes .",
"-T show only TCP statistics .",
"-L show only listening sockets .",
"-H show help .",
);
Exit;
}