scapy/arch/windows/__init__.py
author Dirk Loss <d.loss@infodas.de>
Wed Jan 13 12:16:42 2010 +0100 (2010-01-13)
changeset 1216 f263168cfb0e
parent 1194 bfd7bbdcda5b
child 1236 33f69be3ddcd
permissions -rwxr-xr-x
Fixed console redirection bug in sniff()

This was left-over from the old console handling
code in Scapy-win. Now this caused a NameError:
"global name 'console' is not defined"
phil@1104
     1
## This file is part of Scapy
phil@1104
     2
## See http://www.secdev.org/projects/scapy for more informations
phil@1104
     3
## Copyright (C) Philippe Biondi <phil@secdev.org>
phil@1104
     4
## This program is published under a GPLv2 license
phil@1104
     5
mail@1192
     6
import os,re,sys,socket,time
phil@1104
     7
from glob import glob
phil@1104
     8
from scapy.config import conf,ConfClass
mail@1191
     9
from scapy.error import Scapy_Exception,log_loading,log_runtime
mail@1192
    10
from scapy.utils import atol, inet_aton, inet_ntoa, PcapReader
mail@1192
    11
from scapy.base_classes import Gen, Net, SetGen
mail@1107
    12
import scapy.plist as plist
mail@1192
    13
from scapy.sendrecv import debug, srp1
mail@1192
    14
from scapy.layers.l2 import Ether, ARP
mail@1192
    15
from scapy.data import MTU, ETHER_BROADCAST, ETH_P_ARP
phil@1104
    16
phil@1104
    17
conf.use_pcap = 1
phil@1104
    18
conf.use_dnet = 1
phil@1104
    19
from scapy.arch import pcapdnet
phil@1104
    20
from scapy.arch.pcapdnet import *
phil@1104
    21
phil@1104
    22
LOOPBACK_NAME="lo0"
mail@1192
    23
WINDOWS = True
phil@1104
    24
phil@1104
    25
phil@1104
    26
def _where(filename, dirs=[], env="PATH"):
phil@1104
    27
    """Find file in current dir or system path"""
phil@1104
    28
    if not isinstance(dirs, list):
phil@1104
    29
        dirs = [dirs]
phil@1104
    30
    if glob(filename):
phil@1104
    31
        return filename
phil@1104
    32
    paths = [os.curdir] + os.environ[env].split(os.path.pathsep) + dirs
phil@1104
    33
    for path in paths:
phil@1104
    34
        for match in glob(os.path.join(path, filename)):
phil@1104
    35
            if match:
phil@1104
    36
                return os.path.normpath(match)
phil@1104
    37
    raise IOError("File not found: %s" % filename)
phil@1104
    38
phil@1104
    39
def win_find_exe(filename, installsubdir=None, env="ProgramFiles"):
phil@1104
    40
    """Find executable in current dir, system path or given ProgramFiles subdir"""
phil@1104
    41
    for fn in [filename, filename+".exe"]:
phil@1104
    42
        try:
phil@1104
    43
            if installsubdir is None:
phil@1104
    44
                path = _where(fn)
phil@1104
    45
            else:
phil@1104
    46
                path = _where(fn, dirs=[os.path.join(os.environ[env], installsubdir)])
phil@1104
    47
        except IOError:
phil@1104
    48
            path = filename
phil@1104
    49
        else:
phil@1104
    50
            break        
phil@1104
    51
    return path
phil@1104
    52
phil@1104
    53
phil@1104
    54
class WinProgPath(ConfClass):
phil@1104
    55
    _default = "<System default>"
phil@1104
    56
    # We try some magic to find the appropriate executables
mail@1194
    57
    pdfreader = win_find_exe("AcroRd32") 
mail@1194
    58
    psreader = win_find_exe("gsview32.exe", "Ghostgum/gsview")
phil@1104
    59
    dot = win_find_exe("dot", "ATT/Graphviz/bin")
phil@1104
    60
    tcpdump = win_find_exe("windump")
phil@1104
    61
    tcpreplay = win_find_exe("tcpreplay")
phil@1104
    62
    display = _default
phil@1104
    63
    hexedit = win_find_exe("hexer")
phil@1104
    64
    wireshark = win_find_exe("wireshark", "wireshark")
phil@1104
    65
phil@1104
    66
conf.prog = WinProgPath()
phil@1104
    67
phil@1104
    68
phil@1104
    69
phil@1104
    70
import _winreg
phil@1104
    71
phil@1104
    72
phil@1104
    73
    
phil@1104
    74
class PcapNameNotFoundError(Scapy_Exception):
phil@1104
    75
    pass    
phil@1104
    76
phil@1104
    77
class NetworkInterface(object):
phil@1104
    78
    """A network interface of your local host"""
phil@1104
    79
    
phil@1104
    80
    def __init__(self, dnetdict=None):
phil@1104
    81
        self.name = None
phil@1104
    82
        self.ip = None
phil@1104
    83
        self.mac = None
phil@1104
    84
        self.pcap_name = None
phil@1104
    85
        self.win_name = None
phil@1104
    86
        self.uuid = None
phil@1104
    87
        self.dnetdict = dnetdict
phil@1104
    88
        if dnetdict is not None:
phil@1104
    89
            self.update(dnetdict)
phil@1104
    90
        
phil@1104
    91
    def update(self, dnetdict):
phil@1104
    92
        """Update info about network interface according to given dnet dictionary"""
phil@1104
    93
        self.name = dnetdict["name"]
phil@1104
    94
        # Other attributes are optional
phil@1104
    95
        try:
phil@1104
    96
            self.ip = socket.inet_ntoa(dnetdict["addr"].ip)
phil@1104
    97
        except (KeyError, AttributeError, NameError):
phil@1104
    98
            pass
phil@1104
    99
        try:
phil@1104
   100
            self.mac = dnetdict["link_addr"]
phil@1104
   101
        except KeyError:
phil@1104
   102
            pass
phil@1104
   103
        self._update_pcapdata()
phil@1104
   104
    
phil@1104
   105
    def _update_pcapdata(self):
phil@1104
   106
        """Supplement more info from pypcap and the Windows registry"""
phil@1104
   107
        
mail@1185
   108
        # XXX: We try eth0 - eth29 by bruteforce and match by IP address, 
phil@1104
   109
        # because only the IP is available in both pypcap and dnet.
phil@1104
   110
        # This may not work with unorthodox network configurations and is
phil@1104
   111
        # slow because we have to walk through the Windows registry.
mail@1185
   112
        for n in range(30):
phil@1104
   113
            guess = "eth%s" % n
phil@1104
   114
            win_name = pcapdnet.pcap.ex_name(guess)
phil@1104
   115
            if win_name.endswith("}"):
phil@1104
   116
                try:
phil@1104
   117
                    uuid = win_name[win_name.index("{"):win_name.index("}")+1]
phil@1104
   118
                    keyname = r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\%s" % uuid
phil@1104
   119
                    try:
phil@1104
   120
                        key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname)
phil@1104
   121
                    except WindowsError:
phil@1104
   122
                        log_loading.debug("Couldn't open 'HKEY_LOCAL_MACHINE\\%s' (for guessed pcap iface name '%s')." % (keyname, guess))
phil@1104
   123
                        continue
phil@1104
   124
                    try:    
phil@1104
   125
                        fixed_ip = _winreg.QueryValueEx(key, "IPAddress")[0][0].encode("utf-8")
phil@1104
   126
                    except (WindowsError, UnicodeDecodeError, IndexError):
phil@1104
   127
                        fixed_ip = None
phil@1104
   128
                    try:
phil@1104
   129
                        dhcp_ip = _winreg.QueryValueEx(key, "DhcpIPAddress")[0].encode("utf-8")
phil@1104
   130
                    except (WindowsError, UnicodeDecodeError, IndexError):
phil@1104
   131
                        dhcp_ip = None
phil@1104
   132
                    # "0.0.0.0" or None means the value is not set (at least not correctly).
phil@1104
   133
                    # If both fixed_ip and dhcp_ip are set, fixed_ip takes precedence 
phil@1104
   134
                    if fixed_ip is not None and fixed_ip != "0.0.0.0":
phil@1104
   135
                        ip = fixed_ip
phil@1104
   136
                    elif dhcp_ip is not None and dhcp_ip != "0.0.0.0":
phil@1104
   137
                        ip = dhcp_ip
phil@1104
   138
                    else:
phil@1104
   139
                        continue
phil@1104
   140
                except IOError:
phil@1104
   141
                    continue
phil@1104
   142
                else:
phil@1104
   143
                    if ip == self.ip:
phil@1104
   144
                        self.pcap_name = guess
phil@1104
   145
                        self.win_name = win_name
phil@1104
   146
                        self.uuid = uuid
phil@1104
   147
                        break
phil@1104
   148
        else:
phil@1104
   149
            raise PcapNameNotFoundError
phil@1104
   150
    
phil@1104
   151
    def __repr__(self):
phil@1104
   152
        return "<%s: %s %s %s pcap_name=%s win_name=%s>" % (self.__class__.__name__,
phil@1104
   153
                     self.name, self.ip, self.mac, self.pcap_name, self.win_name)
phil@1104
   154
phil@1104
   155
from UserDict import IterableUserDict
phil@1104
   156
phil@1104
   157
class NetworkInterfaceDict(IterableUserDict):
phil@1104
   158
    """Store information about network interfaces and convert between names""" 
phil@1104
   159
    
phil@1104
   160
    def load_from_dnet(self):
phil@1104
   161
        """Populate interface table via dnet"""
phil@1104
   162
        for i in pcapdnet.dnet.intf():
phil@1104
   163
            try:
phil@1104
   164
                # XXX: Only Ethernet for the moment: localhost is not supported by dnet and pcap
mail@1187
   165
                # We only take interfaces that have an IP address, because the IP
mail@1187
   166
                # is used for the mapping between dnet and pcap interface names
mail@1187
   167
                # and this significantly improves Scapy's startup performance
mail@1187
   168
                if i["name"].startswith("eth") and "addr" in i:
phil@1104
   169
                    self.data[i["name"]] = NetworkInterface(i)
phil@1104
   170
            except (KeyError, PcapNameNotFoundError):
phil@1104
   171
                pass
phil@1104
   172
        if len(self.data) == 0:
phil@1104
   173
            log_loading.warning("No match between your pcap and dnet network interfaces found. "
phil@1104
   174
                                "You probably won't be able to send packets. "
phil@1104
   175
                                "Deactivating unneeded interfaces and restarting Scapy might help.")
phil@1104
   176
    
phil@1104
   177
    def pcap_name(self, devname):
phil@1104
   178
        """Return pypcap device name for given libdnet/Scapy device name
phil@1104
   179
        
phil@1104
   180
        This mapping is necessary because pypcap numbers the devices differently."""
phil@1104
   181
        
phil@1104
   182
        try:
phil@1104
   183
            pcap_name = self.data[devname].pcap_name
phil@1104
   184
        except KeyError:
phil@1104
   185
            raise ValueError("Unknown network interface %r" % devname)
phil@1104
   186
        else:
phil@1104
   187
            return pcap_name
phil@1104
   188
            
phil@1104
   189
    def devname(self, pcap_name):
phil@1104
   190
        """Return libdnet/Scapy device name for given pypcap device name
phil@1104
   191
        
phil@1104
   192
        This mapping is necessary because pypcap numbers the devices differently."""
phil@1104
   193
        
phil@1104
   194
        for devname, iface in self.items():
phil@1104
   195
            if iface.pcap_name == pcap_name:
phil@1104
   196
                return iface.name
phil@1104
   197
        raise ValueError("Unknown pypcap network interface %r" % pcap_name)
phil@1104
   198
    
phil@1104
   199
    def show(self, resolve_mac=True):
phil@1104
   200
        """Print list of available network interfaces in human readable form"""
phil@1104
   201
        print "%s  %s  %s" % ("IFACE".ljust(5), "IP".ljust(15), "MAC")
phil@1104
   202
        for iface_name in sorted(self.data.keys()):
phil@1104
   203
            dev = self.data[iface_name]
phil@1104
   204
            mac = str(dev.mac)
phil@1104
   205
            if resolve_mac:
phil@1104
   206
                mac = conf.manufdb._resolve_MAC(mac)
phil@1104
   207
            print "%s  %s  %s" % (str(dev.name).ljust(5), str(dev.ip).ljust(15), mac)     
phil@1104
   208
            
phil@1104
   209
ifaces = NetworkInterfaceDict()
phil@1104
   210
ifaces.load_from_dnet()
phil@1104
   211
phil@1104
   212
def pcap_name(devname):
phil@1104
   213
    """Return pypcap device name for given libdnet/Scapy device name"""  
phil@1104
   214
    try:
phil@1104
   215
        pcap_name = ifaces.pcap_name(devname)
phil@1104
   216
    except ValueError:
phil@1104
   217
        # pcap.pcap() will choose a sensible default for sniffing if iface=None
phil@1104
   218
        pcap_name = None
phil@1104
   219
    return pcap_name            
phil@1104
   220
phil@1104
   221
def devname(pcap_name):
phil@1104
   222
    """Return libdnet/Scapy device name for given pypcap device name"""
phil@1104
   223
    return ifaces.devname(pcap_name)
phil@1104
   224
    
phil@1104
   225
def show_interfaces(resolve_mac=True):
phil@1104
   226
    """Print list of available network interfaces"""
phil@1104
   227
    return ifaces.show(resolve_mac)
phil@1104
   228
phil@1104
   229
_orig_open_pcap = pcapdnet.open_pcap
phil@1104
   230
pcapdnet.open_pcap = lambda iface,*args,**kargs: _orig_open_pcap(pcap_name(iface),*args,**kargs)
phil@1104
   231
phil@1104
   232
def read_routes():
phil@1104
   233
    ok = 0
phil@1104
   234
    routes = []
mail@1139
   235
    ip = '(\d+\.\d+\.\d+\.\d+)'
mail@1139
   236
    # On Vista and Windows 7 the gateway can be IP or 'On-link'.
mail@1139
   237
    # But the exact 'On-link' string depends on the locale, so we allow any text.
mail@1139
   238
    gw_pattern = '(.+)'
mail@1139
   239
    metric_pattern = "(\d+)"
mail@1139
   240
    delim = "\s+"        # The columns are separated by whitespace
mail@1139
   241
    netstat_line = delim.join([ip, ip, gw_pattern, ip, metric_pattern])
phil@1104
   242
    pattern = re.compile(netstat_line)
phil@1104
   243
    f=os.popen("netstat -rn")
phil@1104
   244
    for l in f.readlines():
phil@1104
   245
        match = re.search(pattern,l)
phil@1104
   246
        if match:
phil@1104
   247
            dest   = match.group(1)
phil@1104
   248
            mask   = match.group(2)
phil@1104
   249
            gw     = match.group(3)
phil@1104
   250
            netif  = match.group(4)
phil@1104
   251
            metric = match.group(5)
mail@1188
   252
            try:
mail@1188
   253
                intf = pcapdnet.dnet.intf().get_dst(pcapdnet.dnet.addr(type=2, addrtxt=dest))
mail@1188
   254
            except OSError:
mail@1188
   255
                log_loading.warning("Building Scapy's routing table: Couldn't get outgoing interface for destination %s" % dest)
mail@1188
   256
                continue               
phil@1104
   257
            if not intf.has_key("addr"):
phil@1104
   258
                break
phil@1104
   259
            addr = str(intf["addr"])
phil@1104
   260
            addr = addr.split("/")[0]
phil@1104
   261
            
phil@1104
   262
            dest = atol(dest)
phil@1104
   263
            mask = atol(mask)
mail@1108
   264
            # If the gateway is no IP we assume it's on-link
mail@1108
   265
            gw_ipmatch = re.search('\d+\.\d+\.\d+\.\d+', gw)
mail@1108
   266
            if gw_ipmatch:
mail@1108
   267
                gw = gw_ipmatch.group(0)
mail@1108
   268
            else:
mail@1108
   269
                gw = netif
phil@1104
   270
            routes.append((dest,mask,gw, str(intf["name"]), addr))
phil@1104
   271
    f.close()
phil@1104
   272
    return routes
phil@1104
   273
phil@1104
   274
def read_routes6():
phil@1104
   275
    return []
phil@1104
   276
phil@1104
   277
def getmacbyip(ip, chainCC=0):
mail@1112
   278
    """Return MAC address corresponding to a given IP address"""
mail@1112
   279
    if isinstance(ip,Net):
mail@1112
   280
        ip = iter(ip).next()
mail@1112
   281
    tmp = map(ord, inet_aton(ip))
mail@1112
   282
    if (tmp[0] & 0xf0) == 0xe0: # mcast @
mail@1112
   283
        return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1]&0x7f,tmp[2],tmp[3])
phil@1104
   284
    iff,a,gw = conf.route.route(ip)
mail@1112
   285
    if ( (iff == LOOPBACK_NAME) or (ip == conf.route.get_if_bcast(iff)) ):
phil@1104
   286
        return "ff:ff:ff:ff:ff:ff"
mail@1112
   287
    # Windows uses local IP instead of 0.0.0.0 to represent locally reachable addresses
phil@1104
   288
    ifip = str(pcapdnet.dnet.intf().get(iff)['addr'])
phil@1104
   289
    if gw != ifip.split('/')[0]:
phil@1104
   290
        ip = gw
mail@1112
   291
mail@1112
   292
    mac = conf.netcache.arp_cache.get(ip)
mail@1112
   293
    if mac:
mail@1112
   294
        return mac
mail@1112
   295
phil@1104
   296
    res = srp1(Ether(dst=ETHER_BROADCAST)/ARP(op="who-has", pdst=ip),
phil@1104
   297
               type=ETH_P_ARP,
phil@1104
   298
               iface = iff,
phil@1104
   299
               timeout=2,
phil@1104
   300
               verbose=0,
phil@1104
   301
               chainCC=chainCC,
phil@1104
   302
               nofilter=1)
phil@1104
   303
    if res is not None:
phil@1104
   304
        mac = res.payload.hwsrc
mail@1112
   305
        conf.netcache.arp_cache[ip] = mac
phil@1104
   306
        return mac
phil@1104
   307
    return None
phil@1104
   308
mail@1186
   309
import scapy.layers.l2
mail@1186
   310
scapy.layers.l2.getmacbyip = getmacbyip
mail@1186
   311
phil@1104
   312
try:
phil@1104
   313
    import readline
phil@1104
   314
    console = readline.GetOutputFile()
phil@1104
   315
except (ImportError, AttributeError):
phil@1104
   316
    log_loading.info("Could not get readline console. Will not interpret ANSI color codes.") 
phil@1104
   317
else:
phil@1105
   318
    conf.readfunc = readline.rl.readline
phil@1104
   319
    orig_stdout = sys.stdout
phil@1104
   320
    sys.stdout = console
phil@1104
   321
phil@1104
   322
phil@1104
   323
phil@1104
   324
phil@1104
   325
phil@1104
   326
def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, multi=0):
phil@1104
   327
    if not isinstance(pkt, Gen):
phil@1104
   328
        pkt = SetGen(pkt)
phil@1104
   329
        
phil@1104
   330
    if verbose is None:
phil@1104
   331
        verbose = conf.verb
phil@1104
   332
    debug.recv = plist.PacketList([],"Unanswered")
phil@1104
   333
    debug.sent = plist.PacketList([],"Sent")
phil@1104
   334
    debug.match = plist.SndRcvList([])
phil@1104
   335
    nbrecv=0
phil@1104
   336
    ans = []
phil@1104
   337
    # do it here to fix random fields, so that parent and child have the same
phil@1104
   338
    all_stimuli = tobesent = [p for p in pkt]
phil@1104
   339
    notans = len(tobesent)
phil@1104
   340
phil@1104
   341
    hsent={}
phil@1104
   342
    for i in tobesent:
phil@1104
   343
        h = i.hashret()
phil@1104
   344
        if h in hsent:
phil@1104
   345
            hsent[h].append(i)
phil@1104
   346
        else:
phil@1104
   347
            hsent[h] = [i]
phil@1104
   348
    if retry < 0:
phil@1104
   349
        retry = -retry
phil@1104
   350
        autostop=retry
phil@1104
   351
    else:
phil@1104
   352
        autostop=0
phil@1104
   353
phil@1104
   354
phil@1104
   355
    while retry >= 0:
phil@1104
   356
        found=0
phil@1104
   357
    
phil@1104
   358
        if timeout < 0:
phil@1104
   359
            timeout = None
phil@1104
   360
phil@1104
   361
        pid=1
phil@1104
   362
        try:
phil@1104
   363
            if WINDOWS or pid == 0:
phil@1104
   364
                try:
phil@1104
   365
                    try:
phil@1104
   366
                        i = 0
phil@1104
   367
                        if verbose:
phil@1104
   368
                            print "Begin emission:"
phil@1104
   369
                        for p in tobesent:
phil@1104
   370
                            pks.send(p)
phil@1104
   371
                            i += 1
phil@1104
   372
                            time.sleep(inter)
phil@1104
   373
                        if verbose:
phil@1104
   374
                            print "Finished to send %i packets." % i
phil@1104
   375
                    except SystemExit:
phil@1104
   376
                        pass
phil@1104
   377
                    except KeyboardInterrupt:
phil@1104
   378
                        pass
phil@1104
   379
                    except:
phil@1104
   380
                        log_runtime.exception("--- Error sending packets")
phil@1104
   381
                        log_runtime.info("--- Error sending packets")
phil@1104
   382
                finally:
phil@1104
   383
                    try:
phil@1104
   384
                        sent_times = [p.sent_time for p in all_stimuli if p.sent_time]
phil@1104
   385
                    except:
phil@1104
   386
                        pass
phil@1104
   387
            if WINDOWS or pid > 0:
phil@1104
   388
                # Timeout starts after last packet is sent (as in Unix version) 
phil@1104
   389
                if timeout:
phil@1104
   390
                    stoptime = time.time()+timeout
phil@1104
   391
                else:
phil@1104
   392
                    stoptime = 0
phil@1104
   393
                remaintime = None
phil@1104
   394
                inmask = [pks.ins.fd]
phil@1104
   395
                try:
phil@1104
   396
                    try:
phil@1104
   397
                        while 1:
phil@1104
   398
                            if stoptime:
phil@1104
   399
                                remaintime = stoptime-time.time()
phil@1104
   400
                                if remaintime <= 0:
phil@1104
   401
                                    break
phil@1104
   402
                            r = pks.recv(MTU)
phil@1104
   403
                            if r is None:
phil@1104
   404
                                continue
phil@1104
   405
                            ok = 0
phil@1104
   406
                            h = r.hashret()
phil@1104
   407
                            if h in hsent:
phil@1104
   408
                                hlst = hsent[h]
phil@1104
   409
                                for i in range(len(hlst)):
phil@1104
   410
                                    if r.answers(hlst[i]):
phil@1104
   411
                                        ans.append((hlst[i],r))
phil@1104
   412
                                        if verbose > 1:
phil@1104
   413
                                            os.write(1, "*")
phil@1104
   414
                                        ok = 1                                
phil@1104
   415
                                        if not multi:
phil@1104
   416
                                            del(hlst[i])
phil@1104
   417
                                            notans -= 1;
phil@1104
   418
                                        else:
phil@1104
   419
                                            if not hasattr(hlst[i], '_answered'):
phil@1104
   420
                                                notans -= 1;
phil@1104
   421
                                            hlst[i]._answered = 1;
phil@1104
   422
                                        break
phil@1104
   423
                            if notans == 0 and not multi:
phil@1104
   424
                                break
phil@1104
   425
                            if not ok:
phil@1104
   426
                                if verbose > 1:
phil@1104
   427
                                    os.write(1, ".")
phil@1104
   428
                                nbrecv += 1
phil@1104
   429
                                if conf.debug_match:
phil@1104
   430
                                    debug.recv.append(r)
phil@1104
   431
                    except KeyboardInterrupt:
phil@1104
   432
                        if chainCC:
phil@1104
   433
                            raise
phil@1104
   434
                finally:
phil@1104
   435
                    if WINDOWS:
phil@1104
   436
                        for p,t in zip(all_stimuli, sent_times):
phil@1104
   437
                            p.sent_time = t
phil@1104
   438
        finally:
phil@1104
   439
            pass
phil@1104
   440
phil@1104
   441
        remain = reduce(list.__add__, hsent.values(), [])
phil@1104
   442
        if multi:
phil@1104
   443
            remain = filter(lambda p: not hasattr(p, '_answered'), remain);
phil@1104
   444
            
phil@1104
   445
        if autostop and len(remain) > 0 and len(remain) != len(tobesent):
phil@1104
   446
            retry = autostop
phil@1104
   447
            
phil@1104
   448
        tobesent = remain
phil@1104
   449
        if len(tobesent) == 0:
phil@1104
   450
            break
phil@1104
   451
        retry -= 1
phil@1104
   452
        
phil@1104
   453
    if conf.debug_match:
phil@1104
   454
        debug.sent=plist.PacketList(remain[:],"Sent")
phil@1104
   455
        debug.match=plist.SndRcvList(ans[:])
phil@1104
   456
phil@1104
   457
    #clean the ans list to delete the field _answered
phil@1104
   458
    if (multi):
phil@1104
   459
        for s,r in ans:
phil@1104
   460
            if hasattr(s, '_answered'):
phil@1104
   461
                del(s._answered)
phil@1104
   462
    
phil@1104
   463
    if verbose:
phil@1104
   464
        print "\nReceived %i packets, got %i answers, remaining %i packets" % (nbrecv+len(ans), len(ans), notans)
mail@1111
   465
    return plist.SndRcvList(ans),plist.PacketList(remain,"Unanswered")
phil@1104
   466
phil@1104
   467
phil@1104
   468
import scapy.sendrecv
phil@1104
   469
scapy.sendrecv.sndrcv = sndrcv
mail@1115
   470
mail@1116
   471
def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None, *arg, **karg):
mail@1116
   472
    """Sniff packets
mail@1116
   473
sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
mail@1116
   474
mail@1116
   475
  count: number of packets to capture. 0 means infinity
mail@1116
   476
  store: wether to store sniffed packets or discard them
mail@1116
   477
    prn: function to apply to each packet. If something is returned,
mail@1116
   478
         it is displayed. Ex:
mail@1116
   479
         ex: prn = lambda x: x.summary()
mail@1116
   480
lfilter: python function applied to each packet to determine
mail@1116
   481
         if further action may be done
mail@1116
   482
         ex: lfilter = lambda x: x.haslayer(Padding)
mail@1116
   483
offline: pcap file to read packets from, instead of sniffing them
mail@1116
   484
timeout: stop sniffing after a given time (default: None)
mail@1116
   485
L2socket: use the provided L2socket
mail@1116
   486
    """
mail@1116
   487
    c = 0
mail@1116
   488
mail@1116
   489
    if offline is None:
mail@1116
   490
        if L2socket is None:
mail@1116
   491
            L2socket = conf.L2listen
mail@1116
   492
        s = L2socket(type=ETH_P_ALL, *arg, **karg)
mail@1116
   493
    else:
mail@1116
   494
        s = PcapReader(offline)
mail@1116
   495
mail@1116
   496
    lst = []
mail@1116
   497
    if timeout is not None:
mail@1116
   498
        stoptime = time.time()+timeout
mail@1116
   499
    remain = None
mail@1116
   500
    while 1:
mail@1116
   501
        try:
mail@1116
   502
            if timeout is not None:
mail@1116
   503
                remain = stoptime-time.time()
mail@1116
   504
                if remain <= 0:
mail@1116
   505
                    break
mail@1116
   506
mail@1116
   507
            try:
mail@1116
   508
                p = s.recv(MTU)
mail@1116
   509
            except PcapTimeoutElapsed:
mail@1116
   510
                continue
mail@1116
   511
            if p is None:
mail@1116
   512
                break
mail@1116
   513
            if lfilter and not lfilter(p):
mail@1116
   514
                continue
mail@1116
   515
            if store:
mail@1116
   516
                lst.append(p)
mail@1116
   517
            c += 1
mail@1116
   518
            if prn:
mail@1116
   519
                r = prn(p)
mail@1116
   520
                if r is not None:
d@1216
   521
                    print r
mail@1116
   522
            if count > 0 and c >= count:
mail@1116
   523
                break
mail@1116
   524
        except KeyboardInterrupt:
mail@1116
   525
            break
mail@1116
   526
    s.close()
mail@1189
   527
    return plist.PacketList(lst,"Sniffed")
mail@1116
   528
mail@1116
   529
import scapy.sendrecv
mail@1116
   530
scapy.sendrecv.sniff = sniff
mail@1116
   531
mail@1115
   532
def get_if_list():
mail@1115
   533
    return sorted(ifaces.keys())
mail@1115
   534
        
mail@1115
   535
def get_working_if():
mail@1115
   536
    try:
mail@1115
   537
        return devname(pcap.lookupdev())
mail@1115
   538
    except Exception:
mail@1115
   539
        return 'lo0'