#!/usr/bin/env python3

# (c) 2017-2025 by Siegrist(SystemLoesungen) <PSS@ZweierNet.ch>
#
# All Rights reserved.
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#

from scapy.all import *
#import traceback
import pwd
import os
import re
import glob
import sys
import string
import fcntl
import struct
import argparse
if sys.version_info.major == 3:
    try:
        #from dnslib.dns import DNSRecord,DNSHeader,DNSQuestion,DNSError,QTYPE,EDNS0
        from dnslib import DNSRecord
        have_DNSLIB = True
    except:
        have_DNSLIB = False
        #print("Missing 'python3-dnslib': DNS-Payload not available.")

def _to_str(inp):
    if sys.version_info.major == 2:
        return inp
    else:
        return "".join( chr(x) for x in inp)
    

VERSION = "1.7.1"

PROC_TCP4 = "/proc/net/tcp"
PROC_UDP4 = "/proc/net/udp"
PROC_ICMP4 = "/proc/net/icmp"
PROC_TCP6 = "/proc/net/tcp6"
PROC_UDP6 = "/proc/net/udp6"
PROC_PACKET = "/proc/net/packet"

# Services
TSERV = dict((TCP_SERVICES[k], k) for k in TCP_SERVICES.keys())
USERV = dict((UDP_SERVICES[k], k) for k in UDP_SERVICES.keys())

# IP Protocol Numbers (dec)
IPPROTO_ICMP = 1
IPPROTO_TCP = 6
IPROTOP_IGP = 9
IPPROTO_UDP = 17

nostate = set(['04','05','06''07','08','09','0C','0D'])
tcp_payload_hdrs = ['GET|POST|HTTP|HEAD|PUT|PATCH|DELETE|TRACE|OPTIONS|CONNECT']
RCODE={0:'', 1:'FORMERR ', 2:'SERVFAIL ', 3:'NXDomain* ',4:'NOTIMP ', 5:'REFUSED ', 6:'YXDOMAIN ', 7:'YXRRSET ',8:'NXRRSET ', 9:'NOTAUTH ', 10:'NOTZONE '}
DNS_QTYPE={1:'A', 2:'NS', 5:'CNAME', 6:'SOA', 10:'NULL', 12:'PTR', 13:'HINFO',
                    15:'MX', 16:'TXT', 17:'RP', 18:'AFSDB', 24:'SIG', 25:'KEY',
                    28:'AAAA', 29:'LOC', 33:'SRV', 35:'NAPTR', 36:'KX',
                    37:'CERT', 38:'A6', 39:'DNAME', 41:'OPT', 42:'APL',
                    43:'DS', 44:'SSHFP', 45:'IPSECKEY', 46:'RRSIG', 47:'NSEC',
                    48:'DNSKEY', 49:'DHCID', 50:'NSEC3', 51:'NSEC3PARAM',
                    52:'TLSA', 53:'HIP', 55:'HIP', 59:'CDS', 60:'CDNSKEY',
                    61:'OPENPGPKEY', 62:'CSYNC', 63:'ZONEMD', 64:'SVCB',
                    65:'HTTPS', 99:'SPF', 108:'EUI48', 109:'EUI64', 249:'TKEY',
                    250:'TSIG', 251:'IXFR', 252:'AXFR', 255:'ANY', 256:'URI',
                    257:'CAA', 32768:'TA', 32769:'DLV'}
numeric = False
payloadH = False
payloadHl = False
payloadDNS = False
fillter = ""

def get_conn_info(proto,hosts,ports,ipvers):
    ''' returns: pid, exe, uid '''
    uid = 0
    
    line_array = _proc4load(proto,hosts,ports,ipvers)
    
    if line_array == 0:
        return ['?','?','?']
    '''    
    try:
        uid = pwd.getpwuid(int(line_array[7]))[0]       # Get user from UID.
    except:
        uid = line_array[7]
    '''
        
    inode = str(line_array[9])
    if inode == "0":
        return ['.','.','.']
    
    pid = _get_pid_of_inode(inode)          # try get a pid
    
    
    if pid == "NoPid":
        #print(">>>>>>>>>>>NoPID:" + str(hosts) +" "+ str(ports) + "//" + str(line_array))
        return ['-', '-', uid]

    try:                                            # try read the process name.
        exe = os.readlink('/proc/'+pid+'/exe').split('/')[-1]
    except:
        exe = None
    
    #print(str(lhost) +" "+ str(lport) +" "+ inode +" "+ pid)
    return [pid, exe, uid]

    
def _proc4load(proto,hosts,ports,ipvers):
    ''' Read the table of tcp/udp connections
    tcp/udp: "sl,  local_address, rem_address, st, tx_queue rx_queue, tr tm->when, retrnsmt,   uid , timeout, inode ,..."
    ---- TCP states from https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp_states.h?id=HEAD
    enum {
    TCP_ESTABLISHED = 1,
    TCP_SYN_SENT,
    TCP_SYN_RECV,
    TCP_FIN_WAIT1,
    TCP_FIN_WAIT2,
    TCP_TIME_WAIT,
    TCP_CLOSE,
    TCP_CLOSE_WAIT,
    TCP_LAST_ACK,
    TCP_LISTEN,
    TCP_CLOSING,    /* Now a valid state */
    TCP_NEW_SYN_RECV,

    TCP_MAX_STATES  /* Leave at the end! */
    };
    ----------
    '''
    
    #xhosts = _ip_hexrev(hosts)
    xports = _dec2hex(ports)
    
    if proto == IPPROTO_UDP:
        try:
            procv = PROC_UDP4
            if ipvers == 6:
                procv = PROC_UDP6
            with open(procv,'r') as f:               
                next(f)
                for line in f:
                    line_arrayu = _remove_empty(line.split(' '))
                    l_xhost,l_xport = line_arrayu[1].split(':')
                    if l_xhost not in xMYADDRS:
                        continue
                    if l_xport == xports:
                        return line_arrayu
                        
                return 0
        except:
            print("open proc_udp4 error")
            return 0
    elif proto == IPPROTO_TCP:
        try:
            procv = PROC_TCP4
            if ipvers == 6:
                procv = PROC_TCP6
            with open(procv,'r') as f:
                next(f)
                for line in f:
                    line_arrayt = _remove_empty(line.split(' '))
                    if line_arrayt[3] in nostate:        # not some TCP state
                        continue
                    l_xhost,l_xport = line_arrayt[1].split(':')
                    if l_xhost not in xMYADDRS:
                        continue
                    if l_xport == xports:
                        return line_arrayt
                        
                return 0
        except:
            print("open proc_tcp error")
            return 0
    
    elif proto == IPPROTO_ICMP:
        try:
            procv = PROC_ICMP4
            if ipvers == 6:
                procv = PROC_ICMP6
            with open(procv,'r') as f:
                next(f)
                for line in f:
                    line_arrayi = _remove_empty(line.split(' '))
                    l_xhost,l_xport = line_arrayi[1].split(':')
                    if l_xhost not in xMYADDRS:
                        continue
                    if l_xport == xports:
                        return line_arrayi
                        
                return 0
        except:
            print("open proc_icmp4 error")
            return 0
    
    return 0

def _convert_ipv4_port(array):
    host,port = array.split(':')
    return _ip(host),_hex2dec(port)
        
def _hex2dec(s):
    return str(int(s,16))

def _dec2hex(p):
    return hex(int(p)).split('x')[-1].upper()
    
def _ip(s):
    ip = [(_hex2dec(s[6:8])),(_hex2dec(s[4:6])),(_hex2dec(s[2:4])),(_hex2dec(s[0:2]))]
    return '.'.join(ip)

def _ip6(s):
    ip = [s[6:8],s[4:6],s[2:4],s[0:2],s[14:16],s[12:14],s[10:12],s[8:10],s[22:24],s[20:22],s[18:20],s[16:18],s[30:32],s[28:30],s[26:28],s[24:26]]
    return ':'.join(ip)

def _ip_hexrev(ip):
    return ''.join([hex(int(x)+256)[3:] for x in ip.split('.')][::-1]).upper()

# IPv6 /proc/net/tcp6 format from expanded ip-address
def _to_v6_proc(s):
    s = s.replace(":", "")
    ip = [s[6:8],s[4:6],s[2:4],s[0:2],s[14:16],s[12:14],s[10:12],s[8:10],s[22:24],s[20:22],s[18:20],s[16:18],s[30:32],s[28:30],s[26:28],s[24:26]]
    return ''.join(ip).upper()

def expand_v6(ip):
    ipa = ip.split(':')     # liste
    
    if '' in ipa:
        if ipa.count('') > 1:   # korr ::1 or :::
            for i in range(ipa.count('')-1):
                ipa.remove('')
                
        miss = 8 - len(ipa) +1
        for i in range(miss):
            ipa.insert(ipa.index('')+i, '0000')        
        ipa.remove('')
        
        return ':'.join(["%04x" % x for x in [int(x, 16) for x in ipa]])
    else:
        return ':'.join(["%04x" % x for x in [int(x, 16) for x in ipa]])
    

def _remove_empty(array):
    return [x for x in array if x != '']

def _get_pid_of_inode(inode):
    s_term = '['+ inode +']'
    for item in glob.iglob('/proc/[0-9]*/fd/[0-9]*'):
        try:
            searchlnk = os.readlink(item)
        except:
            continue
        try:
            if s_term in searchlnk:
                return item.split('/')[2]
        except:
            pass
    return "NoPid"

def _resolve_ip(host):
    """
    resolve ip und update dictionary res_cache {'ip': 'name'}.
    If resolution for a ip failed, 'name' is n_try ... 0.
    """
    try:
        hname = socket.gethostbyaddr(host)[0]
        res_cache[host] = str(hname)
        return str(hname)
    except:
        res_cache[host] = str(host)
        return str(host)

def check_root():
   if os.getuid() == 0:
       return True
   else:
       return False
        
## Do all the packet actions
def doPackets(packet):
    
    program = "-"
    pid = "-"    
    uid = "-"    
    o_proto = ""
    o_dport = "none"
    o_sport = "none"
    flags = ""
    
    # check for valid IP Layer (FIX: v1.7.1)
    if not packet.haslayer(IP):
        return
    
    # only local addresses
    if packet[0][1].src in MYADDRS:
        conn_addr = packet[0][1].src
        if packet.haslayer(TCP) or packet.haslayer(UDP) or packet.haslayer(ICMP):
            try:
                conn_port = packet[0][2].sport
            except:
                conn_port = 99999
        o_dir = 1
    else:
        conn_addr = packet[0][1].dst
        if packet.haslayer(TCP) or packet.haslayer(UDP) or packet.haslayer(ICMP):
            try:
                conn_port = packet[0][2].dport
            except:
                conn_port = 99999
        o_dir = 0
    
    if packet.haslayer(TCP) or packet.haslayer(UDP) or packet.haslayer(ICMP):        # grrr, no info in /proc/net/icmp so far. or packet.haslayer(ICMP):
        # logemol casch 
        c_hash = conn_addr+'=:='+str(conn_port)
        if not any(x[0] == c_hash for x in conn_cache):
            # get the connection info from packet
            if packet[0][1].version == 4:
                spid,sexe,suid = get_conn_info(packet[0][1].proto, conn_addr, conn_port, packet[0][1].version)
            elif packet[0][1].version == 6:
                spid,sexe,suid = get_conn_info(packet[0][1].nh, conn_addr, conn_port, packet[0][1].version)
            if re.match("[0-9]+$", spid):
                program = sexe
                pid = spid
                uid = suid
                
                # update cache
                if len(conn_cache) >= cc_maxlen:
                    conn_cache.pop(0)
                conn_cache.append([c_hash,program,pid])
            else:
                program = sexe
                pid = spid
                uid = suid
        else:
            # me honds fom casch
            indx = [x[0] for x in conn_cache].index(c_hash)
            program = conn_cache[indx][1]
            pid = conn_cache[indx][2]
            uid = 0
            # cache aktualisieren
            renew = conn_cache.pop(indx)
            conn_cache.append(renew)
    
    try:
        filter_prog
    except:
        pass
    else:
        if have_filter_progn:
            if have_filter_progn1 and re.search(filter_progn[1:-1], program):
                return
            elif have_filter_progn2 and re.search(filter_progn[1:]+'$', program):
                return
            elif have_filter_progn3 and re.match('^'+filter_progn[:-1], program):
                return
            elif have_filter_progn4 and re.match('^'+filter_progn+'$', program):
                return
        else:
            if have_filter_prog1 and not re.search(filter_prog[1:-1], program):
                return
            elif have_filter_prog2 and not re.search(filter_prog[1:]+'$', program):
                return
            elif have_filter_prog3 and not re.match('^'+filter_prog[:-1], program):
                return
            elif have_filter_prog4 and not re.match('^'+filter_prog+'$', program):
                return
    
    o_payload = ""
    
    if packet.haslayer(UDP):
        o_proto = "UDP"
        try:
            o_dport = "\033[1m"+USERV[packet[0][2].dport]+"\033[0m"
        except:
            o_dport = str(packet[0][2].dport)
        try:
            o_sport = "\033[1m"+USERV[packet[0][2].sport]+"\033[0m"
        except:
            o_sport = str(packet[0][2].sport)
        flags = ""
        #o_payload = _to_str(packet[0].sprintf('%10s,UDP.payload%'))
        
        if payloadDNS == True:
            if DNS in packet:
                ppd = packet[0][DNS]
                p_upld = DNSRecord.parse(bytes(packet[0][DNS]))
                if ppd.qdcount > 0 and ppd.qr == 0:
                    o_payload = "DNS -> (" + str(ppd.id) + "): " + RCODE[ppd.rcode] 
                    o_payload += DNS_QTYPE[p_upld.q.qtype] + "? " + str(p_upld.q.qname)
                elif ppd.qdcount > 0 and ppd.qr == 1:
                    o_payload = "DNS <- (" + str(ppd.id) + "): " + RCODE[ppd.rcode]
                    rr_cnt = 0
                    for rr in p_upld.rr:
                        o_payload += f'{rr.rname} {DNS_QTYPE[rr.rtype]} {rr.rdata} | '
                        rr_cnt += 1
                    if rr_cnt > 0:
                        o_payload = o_payload[:-3]
                else:
                    o_payload = "DNS: " + RCODE[ppd.rcode] + str(p_upld)
                
                
    elif packet.haslayer(TCP):
        o_proto = "TCP"
        try:
            o_dport = "\033[1m"+TSERV[packet[0][2].dport]+"\033[0m"
        except:
            o_dport = str(packet[0][2].dport)
        try:
            o_sport = "\033[1m"+TSERV[packet[0][2].sport]+"\033[0m"
        except:
            o_sport = str(packet[0][2].sport)
        flags = packet[0].sprintf('%3s,TCP.flags%')
        if payloadH == True:
            if packet.haslayer(Raw):
                #tpld = packet[0].sprintf('%TCP.payload%')
                tpld = _to_str(packet[0][TCP].load)
                tpldhead = tpld[0:8]
                #print("tpld:" + tpldhead)
                if re.match(r'GET|POST|HTTP|HEAD|PUT|PATCH|DELETE|TRACE|OPTIONS|CONNECT.*', tpldhead):
                    if payloadHl == True:
                        o_payload = str(tpld)
                    else:
                        request_line, gaga = tpld.split('\r\n', 1)
                        o_payload = str(request_line)
                    #o_payload = tpld[0:20]
        if payloadDNS == True:
            if DNS in packet:
                ppd = packet[0][DNS]
                ppd2 = bytes(packet[0][DNS])[2:]    # !!$??@! remove length field (2Byte) from DNS-Record for use with DNSRecord.parse() ??!!!!
                p_tpld = DNSRecord.parse(bytes(ppd2))
                if ppd.qdcount > 0 and ppd.qr == 0:
                    o_payload = "DNS -> (" + str(ppd.id) + "): " + RCODE[ppd.rcode] 
                    o_payload += DNS_QTYPE[p_tpld.q.qtype] + "? " + str(p_tpld.q.qname)
                elif ppd.qdcount > 0 and ppd.qr == 1:
                    o_payload = "DNS <- (" + str(ppd.id) + "): " + RCODE[ppd.rcode]
                    rr_cnt = 0
                    for rr in p_tpld.rr:
                        o_payload += f'{rr.rname} {DNS_QTYPE[rr.rtype]} {rr.rdata} | '
                        rr_cnt += 1
                    if rr_cnt > 0:
                        o_payload = o_payload[:-3]
                else:
                    o_payload = "DNS??: " + RCODE[ppd.rcode] + str(p_tpld)
                
        
    elif packet.haslayer(ICMP):
        o_proto = "ICMP"
        if conn_port == 99999:
            o_dport = "-"
            o_sport = "-"
        else:
            try:
                o_dport = "\033[1m"+USERV[packet[0][2].sport]+"\033[0m"
            except:
                o_dport = str(packet[0][2].sport)
            try:
                o_sport = "\033[1m"+USERV[packet[0][2].dport]+"\033[0m"
            except:
                o_sport = str(packet[0][2].dport)
        flags = "["+packet[0].sprintf('%ICMP.type%') + "/" + packet[0].sprintf('%ICMP.code%')+"]"
    else:
        layerukn = packet[0][1].getlayer(1)
        if layerukn is None:
            o_proto = "UNKNOWN"
        else:
            #print("Layer:", xxl1.name)
            o_proto = layerukn.name
        
        #o_proto = "UNKNOWN"
    
    if packet[0][1].version == 4:
        packlen = str(packet[0][1].len)
    if packet[0][1].version == 6:
        packlen = str(packet[0][1].plen)
    
    trenner = " : " if len(o_payload) > 0 else " "    
    if o_dir == 1:
        if numeric == False:
            #if res_cache.has_key(packet[0][1].dst):
            if packet[0][1].dst in res_cache:
                rem_name = res_cache[packet[0][1].dst]
            else:
                rem_name = _resolve_ip(packet[0][1].dst)
        else:
            rem_name = packet[0][1].dst

        #return "\033[1m "+str(packet[0].time)+" "+str(program)+"\033[0m" +"/"+ str(pid) + " - " + o_proto + ": " + packet[0][1].src + ":" + o_sport + "\033[1m\033[31m  ->>>  \033[0m" + rem_name + ":" + o_dport + " " + flags + " Len:" + str(packet[0][1].len) + " : " + o_payload          
        return "\033[1m"+str(program)+"\033[0m" +"/"+ str(pid) + " - " + o_proto + ": " + packet[0][1].src + ":" + o_sport + "\033[1m\033[31m  ->>>  \033[0m" + rem_name + ":" + o_dport + " " + flags + " Len:" + packlen + trenner + o_payload
    else:
        if numeric == False:
            #if res_cache.has_key(packet[0][1].src):
            if packet[0][1].src in res_cache:
                rem_name = res_cache[packet[0][1].src]
            else:
                rem_name = _resolve_ip(packet[0][1].src)
        else:
            rem_name = packet[0][1].src
            
        return "\033[1m"+str(program)+"\033[0m" +"/"+ str(pid) + " - " + o_proto + ": " + packet[0][1].dst + ":" + o_dport + "\033[1m\033[36m  <<<-  \033[0m" + rem_name + ":" + o_sport + " " + flags + " Len:" + packlen + trenner + o_payload



## -- Ond denn s'Hooptprogramm

# root check
if not check_root():
    print("This program needs root privileges !\nThats because of reading the /proc filesystem and using libpcap functions.\nSo I give up\n")
    conf.sniff_promisc=0
    conf.sniff_promisc=0
    sys.exit()

# get the interfaces
#ifaces = subprocess.getoutput("ls /sys/class/net")
#iface_list = ifaces.split('\n')
iface_list = get_if_list()
iface = conf.route.route("0.0.0.0")[0]

rfilter = "ip or ip6"
print("")
# commandline params
parser = argparse.ArgumentParser(description='sisniff V'+VERSION+"\n2017-2026 by sigi <https://wiki.zweiernet.ch/wiki/sisniff>",
                                   formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-i', help="Interface", choices=iface_list)
parser.add_argument('-n', help="Do not resolve IP-Addresses", action="store_true")
parser.add_argument('-P', help="Don't put interface into promiscuous mode", action="store_true")
parser.add_argument('-p', help='Filter by program name (accepts * for matching) ([not-] negates)', type=str, metavar='program|not-program')
parser.add_argument('-4', dest='v4', help="Only IPv4", action="store_true")
parser.add_argument('-6', dest='v6', help="Only IPv6", action="store_true")
parser.add_argument('-H', help="Show HTTP Payload", action="store_true")
parser.add_argument('-Hl', help="Show HTTP Payload, long output", action="store_true")
parser.add_argument('-D', help="Show DNS Payload", action="store_true")
parser.add_argument('filter', nargs='?', help="Filter (BPF syntax) on top of IP (in dbl-quotes \"...\")", type=str)
args = parser.parse_args()
if args.i:
    iface = args.i
if args.n:
    numeric = True
if args.v4:
    rfilter = "ip"
if args.v6:
    rfilter = "ip6"
if args.H:
    payloadH = True
if args.Hl:
    payloadH = True
    payloadHl = True
if args.D:
    if have_DNSLIB:
        payloadDNS = True
    else:
        print("Missing 'python3-dnslib': DNS-Payload not available.")
if args.filter:
    fillter = " and (" + args.filter + ")"
    print("\033[1m> Applying Filter: \"" + rfilter + fillter + "\"\033[0m") 
if args.p:
    filter_prog = args.p
    have_filter_prog = False
    have_filter_progn = False
    have_filter_progn1 = False
    have_filter_progn2 = False
    have_filter_progn3 = False
    have_filter_progn4 = False
    have_filter_prog1 = False
    have_filter_prog2 = False
    have_filter_prog3 = False
    have_filter_prog4 = False
    if filter_prog.startswith('not-'):
        filter_progn = filter_prog[4:]
        have_filter_progn = True
        if filter_progn.startswith('*') and filter_progn.endswith('*'):
            have_filter_progn1 = True
        elif filter_progn.startswith('*') and not filter_progn.endswith('*'):
            have_filter_progn2 = True
        elif not filter_progn.startswith('*') and filter_progn.endswith('*'):
            have_filter_progn3 = True
        elif not filter_progn.startswith('*') and not filter_progn.endswith('*'):
            have_filter_progn4 = True
    else:
        have_filter_prog = True
        if filter_prog.startswith('*') and filter_prog.endswith('*'):
            have_filter_prog1 = True
        elif filter_prog.startswith('*') and not filter_prog.endswith('*'):
            have_filter_prog2 = True
        elif not filter_prog.startswith('*') and filter_prog.endswith('*'):
            have_filter_prog3 = True
        elif not filter_prog.startswith('*') and not filter_prog.endswith('*'):
            have_filter_prog4 = True
no_promisc = ""
if args.P:
    conf.sniff_promisc = conf.promisc = 0
    no_promisc = " (disabled promiscuous mode)"


# local addresses
if args.v6:
    MYADDRS=[]
    xMYADDRS = []
else:
    MYADDRS = _remove_empty(os.popen("ip addr show " + iface + " | egrep 'inet ' | awk '{{print $2}}' | awk -F'/' '{{print $1}}'").read().split())
    MYADDRS.append('0.0.0.0')
    MYADDRS.append('127.0.0.1')
    xMYADDRS = [_ip_hexrev(x) for x in MYADDRS]  
if args.v4:
    MYADDRS6=[]
else:
    #MYADDRS6 = _remove_empty(os.popen("ip addr show " + iface + " | egrep 'inet6' | grep -vi fe80 | awk '{{print $2}}' | awk -F'/' '{{print $1}}'").read().split())
    MYADDRS6 = _remove_empty(os.popen("ip addr show " + iface + " | egrep 'inet6' | awk '{{print $2}}' | awk -F'/' '{{print $1}}'").read().split())
    MYADDRS6.append(':::')
    MYADDRS6.append('::1')
    MYADDRS = MYADDRS + MYADDRS6
xMYADDRS = xMYADDRS + [_to_v6_proc(expand_v6(x)) for x in MYADDRS6]
print("> My IP-Addresses: " + str(MYADDRS))
print("> Listening on: " + iface + no_promisc)

# confirmed connections cache (ringboffer)
conn_cache = []
cc_maxlen = 20

# resolver cache
res_cache = {}
n_try = 3
print("")
print("Prog/PID mavericks: \033[1m?/?\033[0m = No entry in /proc/net/xxx; \033[1m-/-\033[0m = No PID for Inode found; \033[1m./.\033[0m = Inode=0;")
print("")
print("Program/PID: Local addr:port <<->> Remote addr:port [Flags] Len:length : [Payload]")
print("----------------------------------------------------------------------------------")

# sniff, filtering for IP traffic
try:
    sniff(filter=rfilter+fillter,iface=iface,prn=doPackets, store=0)
except Exception as e:
    print("\n \033[1msniff() Error: " + str(e) + "\033[0m \n")
    traceback.print_exc()

## -- oond denn isch schloss
