From 6d62f4fd7f7af6174f5fcf68f0b016dbf633cc60 Mon Sep 17 00:00:00 2001 From: Paul RASCLE Date: Thu, 15 Mar 2018 18:22:57 +0100 Subject: [PATCH] try a replacement for netstat: problem 'launch failed: 7 (Argument list too long)' on some complex cases --- bin/PortManager.py | 152 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 124 insertions(+), 28 deletions(-) diff --git a/bin/PortManager.py b/bin/PortManager.py index ced2ad296..19d6e2d37 100644 --- a/bin/PortManager.py +++ b/bin/PortManager.py @@ -23,6 +23,9 @@ # import os import sys +import pwd +import re +import glob try: import cPickle as pickle #@UnusedImport @@ -33,10 +36,96 @@ __PORT_MIN_NUMBER = 2810 __PORT_MAX_NUMBER = 2910 import logging + +# ------------------------------------------------------------------------------------- +#see https://stackoverflow.com/questions/3993731/how-do-i-access-netstat-data-in-python + +PROC_TCP = "/proc/net/tcp" +STATE = { + '01':'ESTABLISHED', + '02':'SYN_SENT', + '03':'SYN_RECV', + '04':'FIN_WAIT1', + '05':'FIN_WAIT2', + '06':'TIME_WAIT', + '07':'CLOSE', + '08':'CLOSE_WAIT', + '09':'LAST_ACK', + '0A':'LISTEN', + '0B':'CLOSING' + } + +def _load(): + ''' Read the table of tcp connections & remove header ''' + with open(PROC_TCP,'r') as f: + content = f.readlines() + content.pop(0) + return content + +def _hex2dec(s): + return str(int(s,16)) + +def _ip(s): + ip = [(_hex2dec(s[6:8])),(_hex2dec(s[4:6])),(_hex2dec(s[2:4])),(_hex2dec(s[0:2]))] + return '.'.join(ip) + +def _remove_empty(array): + return [x for x in array if x !=''] + +def _convert_ip_port(array): + host,port = array.split(':') + return _ip(host),_hex2dec(port) + +def _get_pid_of_inode(inode): + ''' + To retrieve the process pid, check every running process and look for one using + the given inode. + ''' + for item in glob.glob('/proc/[0-9]*/fd/[0-9]*'): + try: + if re.search(inode,os.readlink(item)): + return item.split('/')[2] + except: + pass + return None + +def netstatOnPort(port): + ''' + Function to return a list with status of tcp connections at linux systems + To get pid of all network process running on system, you must run this script + as superuser + ''' + + content=_load() + result = [] + for line in content: + line_array = _remove_empty(line.split(' ')) # Split lines and remove empty spaces. + l_host,l_port = _convert_ip_port(line_array[1]) # Convert ipaddress and port from hex to decimal. + r_host,r_port = _convert_ip_port(line_array[2]) + tcp_id = line_array[0] + state = STATE[line_array[3]] + uid = pwd.getpwuid(int(line_array[7]))[0] # Get user from UID. + inode = line_array[9] # Need the inode to get process pid. + pid = _get_pid_of_inode(inode) # Get pid prom inode. + try: # try read the process name. + exe = os.readlink('/proc/'+pid+'/exe') + except: + exe = None + + if ((l_port == port) or (r_port == port)) and (state == 'LISTEN'): + print [tcp_id, uid, l_host+':'+l_port, r_host+':'+r_port, state, pid, exe] + return True + return False + #nline = [tcp_id, uid, l_host+':'+l_port, r_host+':'+r_port, state, pid, exe] + #result.append(nline) + #return result + +# ------------------------------------------------------------------------------------- + def createLogger(): logger = logging.getLogger(__name__) -# logger.setLevel(logging.DEBUG) - logger.setLevel(logging.INFO) + logger.setLevel(logging.DEBUG) + #logger.setLevel(logging.INFO) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter("%(levelname)s:%(threadName)s:%(message)s") @@ -101,35 +190,42 @@ def __isNetworkConnectionActiveOnPort(port): # grep command is unavailable if sys.platform == "win32": cmd = ['netstat','-a','-n','-p tcp'] - else: - cmd = ['netstat','-ant'] - pass - - err = None - try: - from subprocess import Popen, PIPE, STDOUT - p = Popen(cmd, stdout=PIPE, stderr=STDOUT) - out, err = p.communicate() - except: - print "Error when trying to access active network connections." - if err: print err - import traceback - traceback.print_exc() - return False + #else: + #cmd = ['netstat','-ant'] + #pass - import StringIO - buf = StringIO.StringIO(out) - ports = buf.readlines() - # search for TCP - LISTEN connections - import re - regObj = re.compile( ".*tcp.*:([0-9]+).*:.*listen", re.IGNORECASE ); - for item in ports: + err = None try: - p = int(regObj.match(item).group(1)) - if p == port: return True + logger.debug("cmd=%s"%cmd) + #from subprocess import Popen, PIPE, STDOUT + #p = Popen(cmd)#, stdout=PIPE, stderr=STDOUT, shell=True) + #out, err = p.communicate() + import subprocess + out=subprocess.check_output(cmd) except: - pass - return False + print "Error when trying to access active network connections." + if err: print "##%s##"%err + import traceback + traceback.print_exc() + return False + + import StringIO + buf = StringIO.StringIO(out) + ports = buf.readlines() + #print ports + # search for TCP - LISTEN connections + import re + regObj = re.compile( ".*tcp.*:([0-9]+).*:.*listen", re.IGNORECASE ); + for item in ports: + try: + p = int(regObj.match(item).group(1)) + if p == port: return True + except: + pass + return False + + else: # Linux + return netstatOnPort(port) # def getPort(preferedPort=None): -- 2.39.2