OpenBSD sockstat
This is a little script that emulates (almost) the sockstat util from FreeBSD. Its main purpose is to let system administrators check open sockets on the system,in a quick way. Right now (v0.1) it is only a "frontend" to fstat. It calls fstat and process the output based on some parameters passed by the user on runtime. Nevertheless, it is designed in a modular basis, and you can take a look over the source code to see that you can replace CallFstat?() with another function that check the sockets directly, or another function that uses netstat instead of fstat to gather information from the system.
Download: sockstat.py v0.1 (October 24, 2005) | tar.gz | tar.bz2 | zip |
Source:
#!/usr/bin/env python
# coding: iso-8859-15
# -*- Python -*-
""" This is a simple script which can be used as FreeBSD sockstat:
http://www.freebsd.org/cgi/man.cgi?query=sockstat&apropos=0&sektion=0&manpath=FreeBSD+5.4-stable&format=html
Right now it is only a "frontend" to fstat, from where it gather information."""
import sys, os
def ShowHelp(args):
""" Just show how to use the script and exit. This help is based on the man
page from FreeBSD sockstat."""
HelpString = """
sockstat: Simple Python script to check open sockets
Use:
$ %s [-l[4|6]] [-c[4|6]] [-u] [port ports]
-l[4|6] Show listening sockets. 4 means only IPv4 sockets,
6 means only IPv6 sockets
-c[4|6] Show connected sockets. 4 means only IPv4 sockets,
6 means only IPv6 sockets
-u Show AF_LOCAL (UNIX) sockets.
port ports Only show Internet sockets if either the local or foreign
port number is on the specified list. The ports argument is
a comma-separated list of port numbers and ranges specified
as first and last port separated by a dash.
This option will apply only if the -l argument is used too
(listing listening sockets).
proto protocol
Show only Internet sockets of the protocol set by the
protocol argument. The protocol could be tcp or udp,
and will be used with ipv4 and ipv6 sockets.
user username
Show only sockets opened by the user defined by username.
""" % (args[0])
print HelpString
def CallFstat():
""" Wrapper to call fstat(1) and get the info about the sockets.
This code is here, on a separate function in order to build a
modular script, we could write another function in the future
to get the information from the sockets (like using the socket module)
and call it instead of CallFstat() from GetSocketInfo()
This function returns 5 lists containing information about listening
ipv4 and ipv6 sockets, connections and unix sockets."""
pipe = os.popen('fstat')
ipv4_listen = []
ipv6_listen = []
ipv4_conn = []
ipv6_conn = []
unix_socket = []
pipe=os.popen('fstat')
readed = '1'
header = pipe.readline()
while readed != '':
readed = pipe.readline()
if '* internet ' in readed:
if '*:' in readed:
ipv4_listen.append(readed)
elif ':' in readed and readed.count(':') < 2:
ipv4_listen.append(readed)
else:
ipv4_conn.append(readed)
elif '* internet6 ' in readed:
if '*:' in readed:
ipv6_listen.append(readed)
elif ':' in readed and readed.count(':') < 2:
ipv6_listen.append(readed)
else:
ipv6_conn.append(readed)
elif '* unix ' in readed:
unix_socket.append(readed)
return header, ipv4_listen, ipv6_listen, ipv4_conn, ipv6_conn, unix_socket
def GetSocketInfo(opc):
""" This function retrieves socket information from the system and parses it to
return the result to the main process pre-formatted.
opc is an argument that set the kind of socket information we are asking for.
First we call whichever function that returns the information about the sockets,
Right now there is only one posibility: CallFstat(), which uses fstat() to get
the information from the system."""
header, ipv4_listen, ipv6_listen, ipv4_conn, ipv6_conn, unix_socket = CallFstat()
SocketInfo = header
if opc == '-l':
for i in ipv4_listen:
SocketInfo = SocketInfo + i
for i in ipv6_listen:
SocketInfo = SocketInfo + i
elif opc == '-l4':
for i in ipv4_listen:
SocketInfo = SocketInfo + i
elif opc == '-l6':
for i in ipv6_listen:
SocketInfo = SocketInfo + i
elif opc == '-c':
for i in ipv4_conn:
SocketInfo = SocketInfo + i
for i in ipv6_conn:
SocketInfo = SocketInfo + i
elif opc == '-c4':
for i in ipv4_conn:
SocketInfo = SocketInfo + i
elif opc == '-c6':
for i in ipv6_conn:
SocketInfo = SocketInfo + i
elif opc == '-u':
for i in unix_socket:
SocketInfo = SocketInfo + i
return SocketInfo
def ApplySocketInfoFilters(SocketInfo, Arg, Params):
""" This is a function similar to GetSocketInfo, it receives the SocketInfo string
and parses it depending on the Arg and Params values, which could hold values
for port number or protocol filtering."""
if Arg == 'port':
# port number filtering, from the string gathered from fstat, we will show only
# ports set with port ports.
#
# There are some different posibilities, one port number, multiple port numbers
# separated by commas, or a port number range, being that one 2 port numbers
# separated with a '-' char.
PosiblePorts = Params.split(',')
Ports = []
for i in PosiblePorts:
if '-' in i and i.count('-') < 2:
for j in range(int(i.split('-')[0]), int(i.split('-')[1]) + 1):
Ports.append(str(j))
else:
try:
# check if it is an integer, and add it (as a str) to the list of
# ports
int(i)
Ports.append(i)
except:
# no integer, no problem
pass
# Now we split the SocketInfo string from the '\n' character and rebuilds it with
# the port filter applied.
SocketInfoList = SocketInfo.split('\n')
# We add the header again, to the new string
ModSocketInfo = SocketInfoList[0] + '\n'
for i in SocketInfoList:
for j in Ports:
if ':' in i:
try:
if int(j) == int(i.split(':')[1]):
ModSocketInfo = ModSocketInfo + i + '\n'
except:
# any of the checking elements is not an integer,
# do not crush, simply doesn't add it
pass
elif Arg == 'proto':
# protocol filtering, from the string gathered from fstat, we will show only
# sockets of the given protocol.
#
# The only posibilities are tcp and udp for the ipv4 and ipv6 sockets
ValidProtos = ['tcp', 'udp']
if Params in ValidProtos:
# Now we split the SocketInfo string from the '\n' character and rebuilds it with
# the port filter applied.
SocketInfoList = SocketInfo.split('\n')
# We add the header again, to the new string
ModSocketInfo = SocketInfoList[0] + '\n'
for i in SocketInfoList:
if Params in i.split(' '):
ModSocketInfo = ModSocketInfo + i + '\n'
elif Arg == 'user':
# user filtering, from the string gathered from fstat, we will show only
# sockets owned by this user.
SocketInfoList = SocketInfo.split('\n')
# We add the header again, to the new string
ModSocketInfo = SocketInfoList[0] + '\n'
for i in SocketInfoList:
if Params in i.split(' '):
ModSocketInfo = ModSocketInfo + i + '\n'
return ModSocketInfo
if __name__ == '__main__':
if len(sys.argv) < 2:
# No args, we have to show the use help
ShowHelp(sys.argv)
else:
# Time to work, we will get all the args, and foreach one we call the proper
# function to get the information about the sockets, this info is appended
# to the string we will show at last.
#
# But first we remove the script name from the parameter list.
SocketInfo = ''
ValidArgs = ['-l','-l4','-l6','-c','-c4', '-c6',
'-u', 'port', 'proto', 'user']
# this is a list of arguments that are followed by option parameter,
# like port ports or -f filter
ParameterArgs = ['port', 'proto', 'user']
ProvArgs = []
for i in sys.argv:
ProvArgs.append(i)
ProvArgs.remove(ProvArgs[0])
ProvParamArgs = {}
for i in ProvArgs:
if i in ValidArgs:
if i in ParameterArgs:
# we will apply the filter later, upon the basic string was built
ProvParamArgs[i] = ProvArgs[ProvArgs.index(i)+1]
else:
SocketInfo = SocketInfo + GetSocketInfo(i)
else:
if ProvArgs[ProvArgs.index(i)-1] not in ParameterArgs:
print '%s: Invalid option -- %s' % (sys.argv[0], i)
ShowHelp(sys.argv)
raise SystemExit
# Now we have the initial Information to display, now it is time to
# apply filters, like ports and protocols
if len(ProvParamArgs) > 0:
for i in ProvParamArgs:
SocketInfo = ApplySocketInfoFilters(SocketInfo, i, ProvParamArgs[i])
# print the result and exit
print SocketInfo