scapy.py
author Phil <phil@secdev.org>
Fri Mar 07 16:22:27 2008 +0100 (2008-03-07)
changeset 805 c919e540a57b
parent 804 da024ce7805d
child 806 87949e07281c
permissions -rwxr-xr-x
Transform non-string objects into strings in StrFields() (ticket #95)
     1 #! /usr/bin/env python
     2 
     3 #############################################################################
     4 ##                                                                         ##
     5 ## scapy.py --- Interactive packet manipulation tool                       ##
     6 ##              see http://www.secdev.org/projects/scapy/                  ##
     7 ##              for more informations                                      ##
     8 ##                                                                         ##
     9 ## Copyright (C) 2003  Philippe Biondi <phil@secdev.org>                   ##
    10 ##                                                                         ##
    11 ## This program is free software; you can redistribute it and/or modify it ##
    12 ## under the terms of the GNU General Public License version 2 as          ##
    13 ## published by the Free Software Foundation; version 2.                   ##
    14 ##                                                                         ##
    15 ## This program is distributed in the hope that it will be useful, but     ##
    16 ## WITHOUT ANY WARRANTY; without even the implied warranty of              ##
    17 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       ##
    18 ## General Public License for more details.                                ##
    19 ##                                                                         ##
    20 #############################################################################
    21 
    22 
    23 from __future__ import generators
    24 import os
    25 
    26 VERSION = "1.2.0.2"
    27 
    28 DEFAULT_CONFIG_FILE = os.path.join(os.environ["HOME"], ".scapy_startup.py")
    29 
    30 try:
    31     os.stat(DEFAULT_CONFIG_FILE)
    32 except OSError:
    33     DEFAULT_CONFIG_FILE = None
    34 
    35 def usage():
    36     print """Usage: scapy.py [-s sessionfile] [-c new_startup_file] [-C]
    37     -C: do not read startup file"""
    38     sys.exit(0)
    39 
    40 
    41 #############################
    42 ##### Logging subsystem #####
    43 #############################
    44 
    45 class Scapy_Exception(Exception):
    46     pass
    47 
    48 import logging,traceback,time
    49 
    50 class ScapyFreqFilter(logging.Filter):
    51     def __init__(self):
    52         logging.Filter.__init__(self)
    53         self.warning_table = {}
    54     def filter(self, record):        
    55         wt = conf.warning_threshold
    56         if wt > 0:
    57             stk = traceback.extract_stack()
    58             caller=None
    59             for f,l,n,c in stk:
    60                 if n == 'warning':
    61                     break
    62                 caller = l
    63             tm,nb = self.warning_table.get(caller, (0,0))
    64             ltm = time.time()
    65             if ltm-tm > wt:
    66                 tm = ltm
    67                 nb = 0
    68             else:
    69                 if nb < 2:
    70                     nb += 1
    71                     if nb == 2:
    72                         record.msg = "more "+record.msg
    73                 else:
    74                     return 0
    75             self.warning_table[caller] = (tm,nb)
    76         return 1    
    77 
    78 log_scapy = logging.getLogger("scapy")
    79 console_handler = logging.StreamHandler()
    80 console_handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
    81 log_scapy.addHandler(console_handler)
    82 log_runtime = logging.getLogger("scapy.runtime")          # logs at runtime
    83 log_runtime.addFilter(ScapyFreqFilter())
    84 log_interactive = logging.getLogger("scapy.interactive")  # logs in interactive functions
    85 log_loading = logging.getLogger("scapy.loading")          # logs when loading scapy
    86 
    87 if __name__ == "__main__":
    88     log_scapy.setLevel(1)
    89 
    90 
    91 ##################
    92 ##### Module #####
    93 ##################
    94 
    95 import socket, sys, getopt, string, struct, random, code
    96 import cPickle, copy, types, gzip, base64, re, zlib, array
    97 from sets import Set
    98 from select import select
    99 from glob import glob
   100 from fcntl import ioctl
   101 import itertools
   102 import fcntl
   103 import warnings
   104 warnings.filterwarnings("ignore","tempnam",RuntimeWarning, __name__)
   105 
   106 
   107 try:
   108     import Gnuplot
   109     GNUPLOT=1
   110 except ImportError:
   111     log_loading.info("did not find python gnuplot wrapper . Won't be able to plot")
   112     GNUPLOT=0
   113 
   114 try:
   115     import pyx
   116     PYX=1
   117 except ImportError:
   118     log_loading.info("Can't import PyX. Won't be able to use psdump() or pdfdump()")
   119     PYX=0
   120 
   121 
   122 LINUX=sys.platform.startswith("linux")
   123 OPENBSD=sys.platform.startswith("openbsd")
   124 FREEBSD=sys.platform.startswith("freebsd")
   125 DARWIN=sys.platform.startswith("darwin")
   126 BIG_ENDIAN= struct.pack("H",1) == "\x00\x01"
   127 X86_64 = (os.uname()[4] == 'x86_64')
   128 SOLARIS=sys.platform.startswith("sunos")
   129 
   130 
   131 if LINUX:
   132     DNET=PCAP=0
   133 else:
   134     DNET=PCAP=1
   135     
   136 
   137 if PCAP:
   138     try:
   139         import pcap
   140         PCAP = 1
   141     except ImportError:
   142         if LINUX:
   143             log_loading.warning("did not find pcap module. Fallback to linux primitives")
   144             PCAP = 0
   145         else:
   146             if __name__ == "__main__":
   147                 log_loading.error("did not find pcap module")
   148                 raise SystemExit
   149             else:
   150                 raise
   151 
   152 if DNET:
   153     try:
   154         import dnet
   155         DNET = 1
   156     except ImportError:
   157         if LINUX:
   158             log_loading.warning("did not find dnet module. Fallback to linux primitives")
   159             DNET = 0
   160         else:
   161             if __name__ == "__main__":
   162                 log_loading.error("did not find dnet module")
   163                 raise SystemExit
   164             else:
   165                 raise
   166 
   167 if not PCAP:
   168     f = os.popen("tcpdump -V 2> /dev/null")
   169     if f.close() >> 8 == 0x7f:
   170         log_loading.warning("Failed to execute tcpdump. Check it is installed and in the PATH")
   171         TCPDUMP=0
   172     else:
   173         TCPDUMP=1
   174     del(f)
   175         
   176     
   177 
   178 try:
   179     from Crypto.Cipher import ARC4
   180 except ImportError:
   181     log_loading.info("Can't find Crypto python lib. Won't be able to decrypt WEP")
   182 
   183 
   184 # Workarround bug 643005 : https://sourceforge.net/tracker/?func=detail&atid=105470&aid=643005&group_id=5470
   185 try:
   186     socket.inet_aton("255.255.255.255")
   187 except socket.error:
   188     def inet_aton(x):
   189         if x == "255.255.255.255":
   190             return "\xff"*4
   191         else:
   192             return socket.inet_aton(x)
   193 else:
   194     inet_aton = socket.inet_aton
   195 
   196 inet_ntoa = socket.inet_ntoa
   197 try:
   198     inet_ntop = socket.inet_ntop
   199     inet_pton = socket.inet_pton
   200 except AttributeError:
   201     log_loading.info("inet_ntop/pton functions not found. Python IPv6 support not present")
   202 
   203 
   204 if SOLARIS:
   205     # GRE is missing on Solaris
   206     socket.IPPROTO_GRE = 47
   207 
   208 ###############################
   209 ## Direct Access dictionnary ##
   210 ###############################
   211 
   212 def fixname(x):
   213     if x and x[0] in "0123456789":
   214         x = "n_"+x
   215     return x.translate("________________________________________________0123456789_______ABCDEFGHIJKLMNOPQRSTUVWXYZ______abcdefghijklmnopqrstuvwxyz_____________________________________________________________________________________________________________________________________")
   216 
   217 
   218 class DADict_Exception(Scapy_Exception):
   219     pass
   220 
   221 class DADict:
   222     def __init__(self, _name="DADict", **kargs):
   223         self._name=_name
   224         self.__dict__.update(kargs)
   225     def fixname(self,val):
   226         return fixname(val)
   227     def __contains__(self, val):
   228         return val in self.__dict__
   229     def __getitem__(self, attr):
   230         return getattr(self, attr)
   231     def __setitem__(self, attr, val):        
   232         return setattr(self, self.fixname(attr), val)
   233     def __iter__(self):
   234         return iter(map(lambda (x,y):y,filter(lambda (x,y):x and x[0]!="_", self.__dict__.items())))
   235     def _show(self):
   236         for k in self.__dict__.keys():
   237             if k and k[0] != "_":
   238                 print "%10s = %r" % (k,getattr(self,k))
   239     def __repr__(self):
   240         return "<%s/ %s>" % (self._name," ".join(filter(lambda x:x and x[0]!="_",self.__dict__.keys())))
   241 
   242     def _branch(self, br, uniq=0):
   243         if uniq and br._name in self:
   244             raise DADict_Exception("DADict: [%s] already branched in [%s]" % (br._name, self._name))
   245         self[br._name] = br
   246 
   247     def _my_find(self, *args, **kargs):
   248         if args and self._name not in args:
   249             return False
   250         for k in kargs:
   251             if k not in self or self[k] != kargs[k]:
   252                 return False
   253         return True
   254     
   255     def _find(self, *args, **kargs):
   256          return self._recurs_find((), *args, **kargs)
   257     def _recurs_find(self, path, *args, **kargs):
   258         if self in path:
   259             return None
   260         if self._my_find(*args, **kargs):
   261             return self
   262         for o in self:
   263             if isinstance(o, DADict):
   264                 p = o._recurs_find(path+(self,), *args, **kargs)
   265                 if p is not None:
   266                     return p
   267         return None
   268     def _find_all(self, *args, **kargs):
   269         return self._recurs_find_all((), *args, **kargs)
   270     def _recurs_find_all(self, path, *args, **kargs):
   271         r = []
   272         if self in path:
   273             return r
   274         if self._my_find(*args, **kargs):
   275             r.append(self)
   276         for o in self:
   277             if isinstance(o, DADict):
   278                 p = o._recurs_find_all(path+(self,), *args, **kargs)
   279                 r += p
   280         return r
   281     def keys(self):
   282         return filter(lambda x:x and x[0]!="_", self.__dict__.keys())
   283         
   284 
   285 
   286 ############
   287 ## Consts ##
   288 ############
   289 
   290 ETHER_ANY = "\x00"*6
   291 ETHER_BROADCAST = "\xff"*6
   292 
   293 ETH_P_ALL = 3
   294 ETH_P_IP = 0x800
   295 ETH_P_ARP = 0x806
   296 
   297 # From net/if_arp.h
   298 ARPHDR_ETHER = 1
   299 ARPHDR_METRICOM = 23
   300 ARPHDR_PPP = 512
   301 ARPHDR_LOOPBACK = 772
   302 ARPHDR_TUN = 65534
   303 
   304 # From bits/ioctls.h
   305 SIOCGIFHWADDR  = 0x8927          # Get hardware address    
   306 SIOCGIFADDR    = 0x8915          # get PA address          
   307 SIOCGIFNETMASK = 0x891b          # get network PA mask     
   308 SIOCGIFNAME    = 0x8910          # get iface name          
   309 SIOCSIFLINK    = 0x8911          # set iface channel       
   310 SIOCGIFCONF    = 0x8912          # get iface list          
   311 SIOCGIFFLAGS   = 0x8913          # get flags               
   312 SIOCSIFFLAGS   = 0x8914          # set flags               
   313 SIOCGIFINDEX   = 0x8933          # name -> if_index mapping
   314 SIOCGIFCOUNT   = 0x8938          # get number of devices
   315 SIOCGSTAMP     = 0x8906          # get packet timestamp (as a timeval)
   316 
   317 
   318 # From if.h
   319 IFF_UP = 0x1               # Interface is up.
   320 IFF_BROADCAST = 0x2        # Broadcast address valid.
   321 IFF_DEBUG = 0x4            # Turn on debugging.
   322 IFF_LOOPBACK = 0x8         # Is a loopback net.
   323 IFF_POINTOPOINT = 0x10     # Interface is point-to-point link.
   324 IFF_NOTRAILERS = 0x20      # Avoid use of trailers.
   325 IFF_RUNNING = 0x40         # Resources allocated.
   326 IFF_NOARP = 0x80           # No address resolution protocol.
   327 IFF_PROMISC = 0x100        # Receive all packets.
   328 
   329 
   330 
   331 # From netpacket/packet.h
   332 PACKET_ADD_MEMBERSHIP  = 1
   333 PACKET_DROP_MEMBERSHIP = 2
   334 PACKET_RECV_OUTPUT     = 3
   335 PACKET_RX_RING         = 5
   336 PACKET_STATISTICS      = 6
   337 PACKET_MR_MULTICAST    = 0
   338 PACKET_MR_PROMISC      = 1
   339 PACKET_MR_ALLMULTI     = 2
   340 
   341 
   342 # From bits/socket.h
   343 SOL_PACKET = 263
   344 # From asm/socket.h
   345 SO_ATTACH_FILTER = 26
   346 SOL_SOCKET = 1
   347 
   348 # From net/route.h
   349 RTF_UP = 0x0001  # Route usable
   350 RTF_REJECT = 0x0200
   351 
   352 # From BSD net/bpf.h
   353 #BIOCIMMEDIATE=0x80044270
   354 BIOCIMMEDIATE=-2147204496
   355 
   356 MTU = 1600
   357 
   358  
   359 # file parsing to get some values :
   360 
   361 def load_protocols(filename):
   362     spaces = re.compile("[ \t]+|\n")
   363     dct = DADict(_name=filename)
   364     try:
   365         for l in open(filename):
   366             try:
   367                 shrp = l.find("#")
   368                 if  shrp >= 0:
   369                     l = l[:shrp]
   370                 l = l.strip()
   371                 if not l:
   372                     continue
   373                 lt = tuple(re.split(spaces, l))
   374                 if len(lt) < 2 or not lt[0]:
   375                     continue
   376                 dct[lt[0]] = int(lt[1])
   377             except Exception,e:
   378                 log_loading.info("Couldn't parse file [%s]: line [%r] (%s)" % (filename,l,e))
   379     except IOError:
   380         log_loading.info("Can't open /etc/protocols file")
   381     return dct
   382 
   383 IP_PROTOS=load_protocols("/etc/protocols")
   384 
   385 def load_ethertypes(filename):
   386     spaces = re.compile("[ \t]+|\n")
   387     dct = DADict(_name=filename)
   388     try:
   389         f=open(filename)
   390         for l in f:
   391             try:
   392                 shrp = l.find("#")
   393                 if  shrp >= 0:
   394                     l = l[:shrp]
   395                 l = l.strip()
   396                 if not l:
   397                     continue
   398                 lt = tuple(re.split(spaces, l))
   399                 if len(lt) < 2 or not lt[0]:
   400                     continue
   401                 dct[lt[0]] = int(lt[1], 16)
   402             except Exception,e:
   403                 log_loading.info("Couldn't parse file [%s]: line [%r] (%s)" % (filename,l,e))
   404         f.close()
   405     except IOError,msg:
   406         pass
   407     return dct
   408 
   409 ETHER_TYPES=load_ethertypes("/etc/ethertypes")
   410 
   411 def load_services(filename):
   412     spaces = re.compile("[ \t]+|\n")
   413     tdct=DADict(_name="%s-tcp"%filename)
   414     udct=DADict(_name="%s-udp"%filename)
   415     try:
   416         f=open(filename)
   417         for l in f:
   418             try:
   419                 shrp = l.find("#")
   420                 if  shrp >= 0:
   421                     l = l[:shrp]
   422                 l = l.strip()
   423                 if not l:
   424                     continue
   425                 lt = tuple(re.split(spaces, l))
   426                 if len(lt) < 2 or not lt[0]:
   427                     continue
   428                 if lt[1].endswith("/tcp"):
   429                     tdct[lt[0]] = int(lt[1].split('/')[0])
   430                 elif lt[1].endswith("/udp"):
   431                     udct[lt[0]] = int(lt[1].split('/')[0])
   432             except Exception,e:
   433                 log_loading.warning("Couldn't file [%s]: line [%r] (%s)" % (filename,l,e))
   434         f.close()
   435     except IOError:
   436         log_loading.info("Can't open /etc/services file")
   437     return tdct,udct
   438 
   439 TCP_SERVICES,UDP_SERVICES=load_services("/etc/services")
   440 
   441 class ManufDA(DADict):
   442     def fixname(self, val):
   443         return val
   444     def _get_manuf_couple(self, mac):
   445         oui = ":".join(mac.split(":")[:3]).upper()
   446         return self.__dict__.get(oui,(mac,mac))
   447     def _get_manuf(self, mac):
   448         return self._get_manuf_couple(mac)[1]
   449     def _get_short_manuf(self, mac):
   450         return self._get_manuf_couple(mac)[0]
   451     def _resolve_MAC(self, mac):
   452         oui = ":".join(mac.split(":")[:3]).upper()
   453         if oui in self:
   454             return ":".join([self[oui][0]]+ mac.split(":")[3:])
   455         return mac
   456         
   457         
   458         
   459 
   460 def load_manuf(filename):
   461     try:
   462         manufdb=ManufDA(_name=filename)
   463         for l in open(filename):
   464             try:
   465                 l = l.strip()
   466                 if not l or l.startswith("#"):
   467                     continue
   468                 oui,shrt=l.split()[:2]
   469                 i = l.find("#")
   470                 if i < 0:
   471                     lng=shrt
   472                 else:
   473                     lng = l[i+2:]
   474                 manufdb[oui] = shrt,lng
   475             except Exception,e:
   476                 log_loading.warning("Couldn't parse one line from [%s] [%r] (%s)" % (filename, l, e))
   477     except IOError:
   478         #log_loading.warning("Couldn't open [%s] file" % filename)
   479         pass
   480     return manufdb
   481     
   482 MANUFDB = load_manuf("/usr/share/wireshark/wireshark/manuf")
   483 
   484 
   485 
   486 
   487 ###########
   488 ## Tools ##
   489 ###########
   490 
   491 def sane_color(x):
   492     r=""
   493     for i in x:
   494         j = ord(i)
   495         if (j < 32) or (j >= 127):
   496             r=r+conf.color_theme.not_printable(".")
   497         else:
   498             r=r+i
   499     return r
   500 
   501 def sane(x):
   502     r=""
   503     for i in x:
   504         j = ord(i)
   505         if (j < 32) or (j >= 127):
   506             r=r+"."
   507         else:
   508             r=r+i
   509     return r
   510 
   511 def lhex(x):
   512     if type(x) in (int,long):
   513         return hex(x)
   514     elif type(x) is tuple:
   515         return "(%s)" % ", ".join(map(lhex, x))
   516     elif type(x) is list:
   517         return "[%s]" % ", ".join(map(lhex, x))
   518     else:
   519         return x
   520 
   521 def hexdump(x):
   522     x=str(x)
   523     l = len(x)
   524     i = 0
   525     while i < l:
   526         print "%04x  " % i,
   527         for j in range(16):
   528             if i+j < l:
   529                 print "%02X" % ord(x[i+j]),
   530             else:
   531                 print "  ",
   532             if j%16 == 7:
   533                 print "",
   534         print " ",
   535         print sane_color(x[i:i+16])
   536         i += 16
   537 
   538 def linehexdump(x, onlyasc=0, onlyhex=0):
   539     x = str(x)
   540     l = len(x)
   541     if not onlyasc:
   542         for i in range(l):
   543             print "%02X" % ord(x[i]),
   544         print "",
   545     if not onlyhex:
   546         print sane_color(x)
   547 
   548 def chexdump(x):
   549     x=str(x)
   550     print ", ".join(map(lambda x: "%#04x"%ord(x), x))
   551     
   552 def hexstr(x, onlyasc=0, onlyhex=0):
   553     s = []
   554     if not onlyasc:
   555         s.append(" ".join(map(lambda x:"%02x"%ord(x), x)))
   556     if not onlyhex:
   557         s.append(sane(x)) 
   558     return "  ".join(s)
   559 
   560 
   561 def hexdiff(x,y):
   562     x=str(x)[::-1]
   563     y=str(y)[::-1]
   564     SUBST=1
   565     INSERT=1
   566     d={}
   567     d[-1,-1] = 0,(-1,-1)
   568     for j in range(len(y)):
   569         d[-1,j] = d[-1,j-1][0]+INSERT, (-1,j-1)
   570     for i in range(len(x)):
   571         d[i,-1] = d[i-1,-1][0]+INSERT, (i-1,-1)
   572 
   573     for j in range(len(y)):
   574         for i in range(len(x)):
   575             d[i,j] = min( ( d[i-1,j-1][0]+SUBST*(x[i] != y[j]), (i-1,j-1) ),
   576                           ( d[i-1,j][0]+INSERT, (i-1,j) ),
   577                           ( d[i,j-1][0]+INSERT, (i,j-1) ) )
   578                           
   579 
   580     backtrackx = []
   581     backtracky = []
   582     i=len(x)-1
   583     j=len(y)-1
   584     while not (i == j == -1):
   585         i2,j2 = d[i,j][1]
   586         backtrackx.append(x[i2+1:i+1])
   587         backtracky.append(y[j2+1:j+1])
   588         i,j = i2,j2
   589 
   590         
   591 
   592     x = y = i = 0
   593     colorize = { 0: lambda x:x,
   594                 -1: conf.color_theme.left,
   595                  1: conf.color_theme.right }
   596     
   597     dox=1
   598     doy=0
   599     l = len(backtrackx)
   600     while i < l:
   601         separate=0
   602         linex = backtrackx[i:i+16]
   603         liney = backtracky[i:i+16]
   604         xx = sum(len(k) for k in linex)
   605         yy = sum(len(k) for k in liney)
   606         if dox and not xx:
   607             dox = 0
   608             doy = 1
   609         if dox and linex == liney:
   610             doy=1
   611             
   612         if dox:
   613             xd = y
   614             j = 0
   615             while not linex[j]:
   616                 j += 1
   617                 xd -= 1
   618             print colorize[doy-dox]("%04x" % xd),
   619             x += xx
   620             line=linex
   621         else:
   622             print "    ",
   623         if doy:
   624             yd = y
   625             j = 0
   626             while not liney[j]:
   627                 j += 1
   628                 yd -= 1
   629             print colorize[doy-dox]("%04x" % yd),
   630             y += yy
   631             line=liney
   632         else:
   633             print "    ",
   634             
   635         print " ",
   636         
   637         cl = ""
   638         for j in range(16):
   639             if i+j < l:
   640                 if line[j]:
   641                     col = colorize[(linex[j]!=liney[j])*(doy-dox)]
   642                     print col("%02X" % ord(line[j])),
   643                     if linex[j]==liney[j]:
   644                         cl += sane_color(line[j])
   645                     else:
   646                         cl += col(sane(line[j]))
   647                 else:
   648                     print "  ",
   649                     cl += " "
   650             else:
   651                 print "  ",
   652             if j == 7:
   653                 print "",
   654 
   655 
   656         print " ",cl
   657 
   658         if doy or not yy:
   659             doy=0
   660             dox=1
   661             i += 16
   662         else:
   663             if yy:
   664                 dox=0
   665                 doy=1
   666             else:
   667                 i += 16
   668 
   669     
   670 crc32 = zlib.crc32
   671 
   672 if BIG_ENDIAN:
   673     def checksum(pkt):
   674         if len(pkt) % 2 == 1:
   675             pkt += "\0"
   676         s = sum(array.array("H", pkt))
   677         s = (s >> 16) + (s & 0xffff)
   678         s += s >> 16
   679         s = ~s
   680         return s & 0xffff
   681 else:
   682     def checksum(pkt):
   683         if len(pkt) % 2 == 1:
   684             pkt += "\0"
   685         s = sum(array.array("H", pkt))
   686         s = (s >> 16) + (s & 0xffff)
   687         s += s >> 16
   688         s = ~s
   689         return (((s>>8)&0xff)|s<<8) & 0xffff
   690 
   691 def warning(x):
   692     log_runtime.warning(x)
   693 
   694 def mac2str(mac):
   695     return "".join(map(lambda x: chr(int(x,16)), mac.split(":")))
   696 
   697 def str2mac(s):
   698     return ("%02x:"*6)[:-1] % tuple(map(ord, s)) 
   699 
   700 def strxor(x,y):
   701     return "".join(map(lambda x,y:chr(ord(x)^ord(y)),x,y))
   702 
   703 def atol(x):
   704     try:
   705         ip = inet_aton(x)
   706     except socket.error:
   707         ip = inet_aton(socket.gethostbyname(x))
   708     return struct.unpack("!I", ip)[0]
   709 def ltoa(x):
   710     return inet_ntoa(struct.pack("!I", x))
   711 
   712 def itom(x):
   713     return (0xffffffff00000000L>>x)&0xffffffffL
   714 
   715 def do_graph(graph,prog=None,format="svg",target=None, type=None,string=None,options=None):
   716     """do_graph(graph, prog=conf.prog.dot, format="svg",
   717          target="| conf.prog.display", options=None, [string=1]):
   718     string: if not None, simply return the graph string
   719     graph: GraphViz graph description
   720     format: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
   721     target: filename or redirect. Defaults pipe to Imagemagick's display program
   722     prog: which graphviz program to use
   723     options: options to be passed to prog"""
   724         
   725 
   726     if string:
   727         return graph
   728     if type is not None:
   729         format=type
   730     if prog is None:
   731         prog = conf.prog.dot
   732     if target is None:
   733         target = "| %s" % conf.prog.display
   734     if format is not None:
   735         format = "-T %s" % format
   736     w,r = os.popen2("%s %s %s %s" % (prog,options or "", format or "", target))
   737     w.write(graph)
   738     w.close()
   739 
   740 _TEX_TR = {
   741     "{":"{\\tt\\char123}",
   742     "}":"{\\tt\\char125}",
   743     "\\":"{\\tt\\char92}",
   744     "^":"\\^{}",
   745     "$":"\\$",
   746     "#":"\\#",
   747     "~":"\\~",
   748     "_":"\\_",
   749     "&":"\\&",
   750     "%":"\\%",
   751     "|":"{\\tt\\char124}",
   752     "~":"{\\tt\\char126}",
   753     "<":"{\\tt\\char60}",
   754     ">":"{\\tt\\char62}",
   755     }
   756     
   757 def tex_escape(x):
   758     s = ""
   759     for c in x:
   760         s += _TEX_TR.get(c,c)
   761     return s
   762 
   763 def colgen(*lstcol,**kargs):
   764     """Returns a generator that mixes provided quantities forever
   765     trans: a function to convert the three arguments into a color. lambda x,y,z:(x,y,z) by default"""
   766     if len(lstcol) < 2:
   767         lstcol *= 2
   768     trans = kargs.get("trans", lambda x,y,z: (x,y,z))
   769     while 1:
   770         for i in range(len(lstcol)):
   771             for j in range(len(lstcol)):
   772                 for k in range(len(lstcol)):
   773                     if i != j or j != k or k != i:
   774                         yield trans(lstcol[(i+j)%len(lstcol)],lstcol[(j+k)%len(lstcol)],lstcol[(k+i)%len(lstcol)])
   775 
   776 def incremental_label(label="tag%05i", start=0):
   777     while True:
   778         yield label % start
   779         start += 1
   780 
   781 #########################
   782 #### Enum management ####
   783 #########################
   784 
   785 class EnumElement:
   786     _value=None
   787     def __init__(self, key, value):
   788         self._key = key
   789         self._value = value
   790     def __repr__(self):
   791         return "<%s %s[%r]>" % (self.__dict__.get("_name", self.__class__.__name__), self._key, self._value)
   792     def __getattr__(self, attr):
   793         return getattr(self._value, attr)
   794     def __str__(self):
   795         return self._key
   796     def __eq__(self, other):
   797         return self._value == int(other)
   798 
   799 
   800 class Enum_metaclass(type):
   801     element_class = EnumElement
   802     def __new__(cls, name, bases, dct):
   803         rdict={}
   804         for k,v in dct.iteritems():
   805             if type(v) is int:
   806                 v = cls.element_class(k,v)
   807                 dct[k] = v
   808                 rdict[v] = k
   809         dct["__rdict__"] = rdict
   810         return super(Enum_metaclass, cls).__new__(cls, name, bases, dct)
   811     def __getitem__(self, attr):
   812         return self.__rdict__[attr]
   813     def __contains__(self, val):
   814         return val in self.__rdict__
   815     def get(self, attr, val=None):
   816         return self._rdict__.get(attr, val)
   817     def __repr__(self):
   818         return "<%s>" % self.__dict__.get("name", self.__name__)
   819 
   820 
   821 
   822 
   823 ##############################
   824 ## Session saving/restoring ##
   825 ##############################
   826 
   827 
   828 def save_session(fname, session=None, pickleProto=-1):
   829     if session is None:
   830         session = scapy_session
   831 
   832     to_be_saved = session.copy()
   833         
   834     if to_be_saved.has_key("__builtins__"):
   835         del(to_be_saved["__builtins__"])
   836 
   837     for k in to_be_saved.keys():
   838         if type(to_be_saved[k]) in [types.TypeType, types.ClassType, types.ModuleType]:
   839              log_interactive.error("[%s] (%s) can't be saved." % (k, type(to_be_saved[k])))
   840              del(to_be_saved[k])
   841 
   842     try:
   843         os.rename(fname, fname+".bak")
   844     except OSError:
   845         pass
   846     f=gzip.open(fname,"wb")
   847     cPickle.dump(to_be_saved, f, pickleProto)
   848     f.close()
   849 
   850 def load_session(fname):
   851     try:
   852         s = cPickle.load(gzip.open(fname,"rb"))
   853     except IOError:
   854         s = cPickle.load(open(fname,"rb"))
   855     scapy_session.clear()
   856     scapy_session.update(s)
   857 
   858 def update_session(fname):
   859     try:
   860         s = cPickle.load(gzip.open(fname,"rb"))
   861     except IOError:
   862         s = cPickle.load(open(fname,"rb"))
   863     scapy_session.update(s)
   864 
   865 
   866 def export_object(obj):
   867     print base64.encodestring(gzip.zlib.compress(cPickle.dumps(obj,2),9))
   868 
   869 def import_object(obj=None):
   870     if obj is None:
   871         obj = sys.stdin.read()
   872     return cPickle.loads(gzip.zlib.decompress(base64.decodestring(obj.strip())))
   873 
   874 
   875 def save_object(fname, obj):
   876     cPickle.dump(obj,gzip.open(fname,"wb"))
   877 
   878 def load_object(fname):
   879     return cPickle.load(gzip.open(fname,"rb"))
   880 
   881 
   882 ######################
   883 ## Extension system ##
   884 ######################
   885 
   886 
   887 def load_extension(filename):
   888     import imp
   889     paths = conf.extensions_paths
   890     if type(paths) is not list:
   891         paths = [paths]
   892 
   893     name = os.path.realpath(os.path.expanduser(filename))
   894     thepath = os.path.dirname(name)
   895     thename = os.path.basename(name)
   896     if thename.endswith(".py"):
   897         thename = thename[:-3]
   898 
   899     paths.insert(0, thepath)
   900     cwd=syspath=None
   901     try:
   902         cwd = os.getcwd()
   903         os.chdir(thepath)
   904         syspath = sys.path[:]
   905         sys.path += paths
   906         try:
   907             extf = imp.find_module(thename, paths)
   908         except ImportError:
   909             log_runtime.error("Module [%s] not found. Check conf.extensions_paths ?" % filename)
   910         else:
   911             ext = imp.load_module(thename, *extf)
   912             import __builtin__
   913             __builtin__.__dict__.update(ext.__dict__)
   914     finally:
   915         if syspath:
   916             sys.path=syspath
   917         if cwd:
   918             os.chdir(cwd)
   919     
   920 
   921 
   922 #################
   923 ## Debug class ##
   924 #################
   925 
   926 class debug:
   927     recv=[]
   928     sent=[]
   929     match=[]
   930 
   931 
   932 ####################
   933 ## IP Tools class ##
   934 ####################
   935 
   936 class IPTools:
   937     """Add more powers to a class that have a "src" attribute."""
   938     def whois(self):
   939         os.system("whois %s" % self.src)
   940     def ottl(self):
   941         t = [32,64,128,255]+[self.ttl]
   942         t.sort()
   943         return t[t.index(self.ttl)+1]
   944     def hops(self):
   945         return self.ottl()-self.ttl-1 
   946 
   947 
   948 ##############################
   949 ## Routing/Interfaces stuff ##
   950 ##############################
   951 
   952 class Route:
   953     def __init__(self):
   954         self.resync()
   955         self.s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
   956         self.cache = {}
   957 
   958     def invalidate_cache(self):
   959         self.cache = {}
   960 
   961     def resync(self):
   962         self.invalidate_cache()
   963         self.routes = read_routes()
   964 
   965     def __repr__(self):
   966         rt = "Network         Netmask         Gateway         Iface           Output IP\n"
   967         for net,msk,gw,iface,addr in self.routes:
   968             rt += "%-15s %-15s %-15s %-15s %-15s\n" % (ltoa(net),
   969                                               ltoa(msk),
   970                                               gw,
   971                                               iface,
   972                                               addr)
   973         return rt
   974 
   975     def make_route(self, host=None, net=None, gw=None, dev=None):
   976         if host is not None:
   977             thenet,msk = host,32
   978         elif net is not None:
   979             thenet,msk = net.split("/")
   980             msk = int(msk)
   981         else:
   982             raise Scapy_Exception("make_route: Incorrect parameters. You should specify a host or a net")
   983         if gw is None:
   984             gw="0.0.0.0"
   985         if dev is None:
   986             if gw:
   987                 nhop = gw
   988             else:
   989                 nhop = thenet
   990             dev,ifaddr,x = self.route(nhop)
   991         else:
   992             ifaddr = get_if_addr(dev)
   993         return (atol(thenet), itom(msk), gw, dev, ifaddr)
   994 
   995     def add(self, *args, **kargs):
   996         """Ex:
   997         add(net="192.168.1.0/24",gw="1.2.3.4")
   998         """
   999         self.invalidate_cache()
  1000         self.routes.append(self.make_route(*args,**kargs))
  1001 
  1002         
  1003     def delt(self,  *args, **kargs):
  1004         """delt(host|net, gw|dev)"""
  1005         self.invalidate_cache()
  1006         route = self.make_route(*args,**kargs)
  1007         try:
  1008             i=self.routes.index(route)
  1009             del(self.routes[i])
  1010         except ValueError:
  1011             warning("no matching route found")
  1012              
  1013     def ifchange(self, iff, addr):
  1014         self.invalidate_cache()
  1015         the_addr,the_msk = (addr.split("/")+["32"])[:2]
  1016         the_msk = itom(int(the_msk))
  1017         the_rawaddr = atol(the_addr)
  1018         the_net = the_rawaddr & the_msk
  1019         
  1020         
  1021         for i in range(len(self.routes)):
  1022             net,msk,gw,iface,addr = self.routes[i]
  1023             if iface != iff:
  1024                 continue
  1025             if gw == '0.0.0.0':
  1026                 self.routes[i] = (the_net,the_msk,gw,iface,the_addr)
  1027             else:
  1028                 self.routes[i] = (net,msk,gw,iface,the_addr)
  1029         for i in arp_cache.keys():
  1030             del(arp_cache[i])
  1031         
  1032                 
  1033 
  1034     def ifdel(self, iff):
  1035         self.invalidate_cache()
  1036         new_routes=[]
  1037         for rt in self.routes:
  1038             if rt[3] != iff:
  1039                 new_routes.append(rt)
  1040         self.routes=new_routes
  1041         
  1042     def ifadd(self, iff, addr):
  1043         self.invalidate_cache()
  1044         the_addr,the_msk = (addr.split("/")+["32"])[:2]
  1045         the_msk = itom(int(the_msk))
  1046         the_rawaddr = atol(the_addr)
  1047         the_net = the_rawaddr & the_msk
  1048         self.routes.append((the_net,the_msk,'0.0.0.0',iff,the_addr))
  1049 
  1050 
  1051     def route(self,dest,verbose=None):
  1052         if dest in self.cache:
  1053             return self.cache[dest]
  1054         if verbose is None:
  1055             verbose=conf.verb
  1056         # Transform "192.168.*.1-5" to one IP of the set
  1057         dst = dest.split("/")[0]
  1058         dst = dst.replace("*","0") 
  1059         while 1:
  1060             l = dst.find("-")
  1061             if l < 0:
  1062                 break
  1063             m = (dst[l:]+".").find(".")
  1064             dst = dst[:l]+dst[l+m:]
  1065 
  1066             
  1067         dst = atol(dst)
  1068         pathes=[]
  1069         for d,m,gw,i,a in self.routes:
  1070             aa = atol(a)
  1071             if aa == dst:
  1072                 pathes.append((0xffffffffL,("lo",a,"0.0.0.0")))
  1073             if (dst & m) == (d & m):
  1074                 pathes.append((m,(i,a,gw)))
  1075         if not pathes:
  1076             if verbose:
  1077                 warning("No route found (no default route?)")
  1078             return "lo","0.0.0.0","0.0.0.0" #XXX linux specific!
  1079         # Choose the more specific route (greatest netmask).
  1080         # XXX: we don't care about metrics
  1081         pathes.sort()
  1082         ret = pathes[-1][1]
  1083         self.cache[dest] = ret
  1084         return ret
  1085             
  1086     def get_if_bcast(self, iff):
  1087         for net, msk, gw, iface, addr in self.routes:
  1088             if (iff == iface and net != 0L):
  1089                 bcast = atol(addr)|(~msk&0xffffffffL); # FIXME: check error in atol()
  1090                 return ltoa(bcast);
  1091         warning("No broadcast address found for iface %s\n" % iff);
  1092 
  1093 if DNET:
  1094     def get_if_raw_hwaddr(iff):
  1095         if iff[:2] == "lo":
  1096             return (772, '\x00'*6)
  1097         try:
  1098             l = dnet.intf().get(iff)
  1099             l = l["link_addr"]
  1100         except:
  1101             raise Scapy_Exception("Error in attempting to get hw address for interface [%s]" % iff)
  1102         return l.type,l.data
  1103     def get_if_raw_addr(ifname):
  1104         i = dnet.intf()
  1105         return i.get(ifname)["addr"].data
  1106 else:
  1107     def get_if_raw_hwaddr(iff):
  1108         return struct.unpack("16xh6s8x",get_if(iff,SIOCGIFHWADDR))
  1109 
  1110     def get_if_raw_addr(iff):
  1111         try:
  1112             return get_if(iff, SIOCGIFADDR)[20:24]
  1113         except IOError:
  1114             return "\0\0\0\0"
  1115 
  1116 
  1117 if PCAP:
  1118     def get_if_list():
  1119         # remove 'any' interface
  1120         return map(lambda x:x[0],filter(lambda x:x[1] is None,pcap.findalldevs()))
  1121     def get_working_if():
  1122         try:
  1123             return pcap.lookupdev()
  1124         except Exception:
  1125             return 'lo'
  1126 
  1127     def attach_filter(s, filter):
  1128         warning("attach_filter() should not be called in PCAP mode")
  1129     def set_promisc(s,iff,val=1):
  1130         warning("set_promisc() should not be called in DNET/PCAP mode")
  1131     
  1132 else:
  1133     def get_if_list():
  1134         f=open("/proc/net/dev","r")
  1135         lst = []
  1136         f.readline()
  1137         f.readline()
  1138         for l in f:
  1139             lst.append(l.split(":")[0].strip())
  1140         return lst
  1141     def get_working_if():
  1142         for i in get_if_list():
  1143             if i == 'lo':                
  1144                 continue
  1145             ifflags = struct.unpack("16xH14x",get_if(i,SIOCGIFFLAGS))[0]
  1146             if ifflags & IFF_UP:
  1147                 return i
  1148         return "lo"
  1149     def attach_filter(s, filter):
  1150         # XXX We generate the filter on the interface conf.iface 
  1151         # because tcpdump open the "any" interface and ppp interfaces
  1152         # in cooked mode. As we use them in raw mode, the filter will not
  1153         # work... one solution could be to use "any" interface and translate
  1154         # the filter from cooked mode to raw mode
  1155         # mode
  1156         if not TCPDUMP:
  1157             return
  1158         try:
  1159             f = os.popen("%s -i %s -ddd -s 1600 '%s'" % (conf.prog.tcpdump,conf.iface,filter))
  1160         except OSError,msg:
  1161             log_interactive.warning("Failed to execute tcpdump: (%s)")
  1162             return
  1163         lines = f.readlines()
  1164         if f.close():
  1165             raise Scapy_Exception("Filter parse error")
  1166         nb = int(lines[0])
  1167         bpf = ""
  1168         for l in lines[1:]:
  1169             bpf += struct.pack("HBBI",*map(long,l.split()))
  1170     
  1171         # XXX. Argl! We need to give the kernel a pointer on the BPF,
  1172         # python object header seems to be 20 bytes. 36 bytes for x86 64bits arch.
  1173         if X86_64:
  1174             bpfh = struct.pack("HL", nb, id(bpf)+36)
  1175         else:
  1176             bpfh = struct.pack("HI", nb, id(bpf)+20)  
  1177         s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bpfh)
  1178 
  1179     def set_promisc(s,iff,val=1):
  1180         mreq = struct.pack("IHH8s", get_if_index(iff), PACKET_MR_PROMISC, 0, "")
  1181         if val:
  1182             cmd = PACKET_ADD_MEMBERSHIP
  1183         else:
  1184             cmd = PACKET_DROP_MEMBERSHIP
  1185         s.setsockopt(SOL_PACKET, cmd, mreq)
  1186 
  1187 
  1188 if not LINUX:
  1189 
  1190     def new_read_routes():
  1191 
  1192         rtlst = []
  1193         def addrt(rt,lst):
  1194             dst,gw = rt
  1195             lst.append(rt)
  1196 
  1197         r = dnet.route()
  1198         print r.loop(addrt, rtlst)
  1199         return rtlst
  1200 
  1201     def read_routes():
  1202         if SOLARIS:
  1203             f=os.popen("netstat -rvn") # -f inet
  1204         elif FREEBSD:
  1205             f=os.popen("netstat -rnW") # -W to handle long interface names
  1206         else:
  1207             f=os.popen("netstat -rn") # -f inet
  1208         ok = 0
  1209         mtu_present = False
  1210         routes = []
  1211         for l in f.readlines():
  1212             if not l:
  1213                 break
  1214             l = l.strip()
  1215             if l.find("----") >= 0: # a separation line
  1216                 continue
  1217             if l.find("Destination") >= 0:
  1218                 ok = 1
  1219                 if l.find("Mtu") >= 0:
  1220                     mtu_present = True
  1221                 continue
  1222             if ok == 0:
  1223                 continue
  1224             if not l:
  1225                 break
  1226             if SOLARIS:
  1227                 dest,mask,gw,netif,mxfrg,rtt,ref,flg = l.split()[:8]
  1228             else:
  1229                 if mtu_present:
  1230                     dest,gw,flg,ref,use,mtu,netif = l.split()[:7]
  1231                 else:
  1232                     dest,gw,flg,ref,use,netif = l.split()[:6]
  1233             if flg.find("Lc") >= 0:
  1234                 continue                
  1235             if dest == "default":
  1236                 dest = 0L
  1237                 netmask = 0L
  1238             else:
  1239                 if SOLARIS:
  1240                     netmask = atol(mask)
  1241                 elif "/" in dest:
  1242                     dest,netmask = dest.split("/")
  1243                     netmask = itom(int(netmask))
  1244                 else:
  1245                     netmask = itom((dest.count(".") + 1) * 8)
  1246                 dest += ".0"*(3-dest.count("."))
  1247                 dest = atol(dest)
  1248             if not "G" in flg:
  1249                 gw = '0.0.0.0'
  1250             ifaddr = get_if_addr(netif)
  1251             routes.append((dest,netmask,gw,netif,ifaddr))
  1252         f.close()
  1253         return routes
  1254 
  1255     def read_interfaces():
  1256         i = dnet.intf()
  1257         ifflist = {}
  1258         def addif(iff,lst):
  1259             if not iff.has_key("addr"):
  1260                 return
  1261             if not iff.has_key("link_addr"):
  1262                 return
  1263             rawip = iff["addr"].data
  1264             ip = inet_ntoa(rawip)
  1265             rawll = iff["link_addr"].data
  1266             ll = str2mac(rawll)
  1267             lst[iff["name"]] = (rawll,ll,rawip,ip)
  1268         i.loop(addif, ifflist)
  1269         return ifflist
  1270 
  1271             
  1272 else:
  1273 
  1274     def read_routes():
  1275         f=open("/proc/net/route","r")
  1276         routes = []
  1277         s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  1278         ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x","lo"))
  1279         addrfamily = struct.unpack("h",ifreq[16:18])[0]
  1280         if addrfamily == socket.AF_INET:
  1281             ifreq2 = ioctl(s, SIOCGIFNETMASK,struct.pack("16s16x","lo"))
  1282             msk = socket.ntohl(struct.unpack("I",ifreq2[20:24])[0])
  1283             dst = socket.ntohl(struct.unpack("I",ifreq[20:24])[0]) & msk
  1284             ifaddr = inet_ntoa(ifreq[20:24])
  1285             routes.append((dst, msk, "0.0.0.0", "lo", ifaddr))
  1286         else:
  1287             warning("Interface lo: unkown address family (%i)"% addrfamily)
  1288     
  1289         for l in f.readlines()[1:]:
  1290             iff,dst,gw,flags,x,x,x,msk,x,x,x = l.split()
  1291             flags = int(flags,16)
  1292             if flags & RTF_UP == 0:
  1293                 continue
  1294             if flags & RTF_REJECT:
  1295                 continue
  1296             try:
  1297                 ifreq = ioctl(s, SIOCGIFADDR,struct.pack("16s16x",iff))
  1298             except IOError: # interface is present in routing tables but does not have any assigned IP
  1299                 ifaddr="0.0.0.0"
  1300             else:
  1301                 addrfamily = struct.unpack("h",ifreq[16:18])[0]
  1302                 if addrfamily == socket.AF_INET:
  1303                     ifaddr = inet_ntoa(ifreq[20:24])
  1304                 else:
  1305                     warning("Interface %s: unkown address family (%i)"%(iff, addrfamily))
  1306                     continue
  1307             routes.append((socket.htonl(long(dst,16))&0xffffffffL,
  1308                            socket.htonl(long(msk,16))&0xffffffffL,
  1309                            inet_ntoa(struct.pack("I",long(gw,16))),
  1310                            iff, ifaddr))
  1311         
  1312         f.close()
  1313         return routes
  1314 
  1315     def get_if(iff,cmd):
  1316         s=socket.socket()
  1317         ifreq = ioctl(s, cmd, struct.pack("16s16x",iff))
  1318         s.close()
  1319         return ifreq
  1320 
  1321 
  1322     def get_if_index(iff):
  1323         return int(struct.unpack("I",get_if(iff, SIOCGIFINDEX)[16:20])[0])
  1324 
  1325     def get_last_packet_timestamp(sock):
  1326         ts = ioctl(sock, SIOCGSTAMP, "12345678")
  1327         s,us = struct.unpack("II",ts)
  1328         return s+us/1000000.0
  1329 
  1330     
  1331 def get_if_addr(iff):
  1332     return inet_ntoa(get_if_raw_addr(iff))
  1333     
  1334 def get_if_hwaddr(iff):
  1335     addrfamily, mac = get_if_raw_hwaddr(iff)
  1336     if addrfamily in [ARPHDR_ETHER,ARPHDR_LOOPBACK]:
  1337         return str2mac(mac)
  1338     else:
  1339         raise Scapy_Exception("Unsupported address family (%i) for interface [%s]" % (addrfamily,iff))
  1340 
  1341 
  1342 
  1343 #####################
  1344 ## ARP cache stuff ##
  1345 #####################
  1346 
  1347 ARPTIMEOUT=120
  1348 
  1349 # XXX Fill arp_cache with /etc/ether and arp cache
  1350 arp_cache={}
  1351 
  1352 if 0 and DNET: ## XXX Can't use this because it does not resolve IPs not in cache
  1353     dnet_arp_object = dnet.arp()
  1354     def getmacbyip(ip, chainCC=0):
  1355         tmp = map(ord, inet_aton(ip))
  1356         if (tmp[0] & 0xf0) == 0xe0: # mcast @
  1357             return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1]&0x7f,tmp[2],tmp[3])
  1358         iff,a,gw = conf.route.route(ip)
  1359         if iff == "lo":
  1360             return "ff:ff:ff:ff:ff:ff"
  1361         if gw != "0.0.0.0":
  1362             ip = gw
  1363         res = dnet_arp_object.get(dnet.addr(ip))
  1364         if res is None:
  1365             return None
  1366         else:
  1367             return res.ntoa()
  1368 else:
  1369     def getmacbyip(ip, chainCC=0):
  1370         tmp = map(ord, inet_aton(ip))
  1371         if (tmp[0] & 0xf0) == 0xe0: # mcast @
  1372             return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1]&0x7f,tmp[2],tmp[3])
  1373         iff,a,gw = conf.route.route(ip)
  1374         if ( (iff == "lo") or (ip == conf.route.get_if_bcast(iff)) ):
  1375             return "ff:ff:ff:ff:ff:ff"
  1376         if gw != "0.0.0.0":
  1377             ip = gw
  1378     
  1379         if arp_cache.has_key(ip):
  1380             mac, timeout = arp_cache[ip]
  1381             if not timeout or (time.time()-timeout < ARPTIMEOUT):
  1382                 return mac
  1383 
  1384         res = srp1(Ether(dst=ETHER_BROADCAST)/ARP(op="who-has", pdst=ip),
  1385                    type=ETH_P_ARP,
  1386                    iface = iff,
  1387                    timeout=2,
  1388                    verbose=0,
  1389                    chainCC=chainCC,
  1390                    nofilter=1)
  1391         if res is not None:
  1392             mac = res.payload.hwsrc
  1393             arp_cache[ip] = (mac,time.time())
  1394             return mac
  1395         return None
  1396     
  1397 
  1398 ####################
  1399 ## Random numbers ##
  1400 ####################
  1401 
  1402 def randseq(inf, sup, seed=None, forever=1, renewkeys=0):
  1403     """iterate through a sequence in random order.
  1404        When all the values have been drawn, if forever=1, the drawing is done again.
  1405        If renewkeys=0, the draw will be in the same order, guaranteeing that the same
  1406        number will be drawn in not less than the number of integers of the sequence"""
  1407     rnd = random.Random(seed)
  1408     sbox_size = 256
  1409 
  1410     top = sup-inf+1
  1411     
  1412     n=0
  1413     while (1<<n) < top:
  1414         n += 1
  1415 
  1416     fs = min(3,(n+1)/2)
  1417     fsmask = 2**fs-1
  1418     rounds = max(n,3)
  1419     turns = 0
  1420 
  1421     while 1:
  1422         if turns == 0 or renewkeys:
  1423             sbox = [rnd.randint(0,fsmask) for k in xrange(sbox_size)]
  1424         turns += 1
  1425         i = 0
  1426         while i < 2**n:
  1427             ct = i
  1428             i += 1
  1429             for k in range(rounds): # Unbalanced Feistel Network
  1430                 lsb = ct & fsmask
  1431                 ct >>= fs
  1432                 lsb ^= sbox[ct%sbox_size]
  1433                 ct |= lsb << (n-fs)
  1434             
  1435             if ct < top:
  1436                 yield inf+ct
  1437         if not forever:
  1438             break
  1439 
  1440 
  1441 class VolatileValue:
  1442     def __repr__(self):
  1443         return "<%s>" % self.__class__.__name__
  1444     def __getattr__(self, attr):
  1445         if attr == "__setstate__":
  1446             raise AttributeError(attr)
  1447         return getattr(self._fix(),attr)
  1448     def _fix(self):
  1449         return None
  1450 
  1451 
  1452 class RandField(VolatileValue):
  1453     pass
  1454 
  1455 
  1456 class RandNum(RandField):
  1457     min = 0
  1458     max = 0
  1459     def __init__(self, min, max):
  1460         self.seq = randseq(min,max)
  1461     def _fix(self):
  1462         return self.seq.next()
  1463 
  1464 class RandNumGamma(RandField):
  1465     def __init__(self, alpha, beta):
  1466         self.alpha = alpha
  1467         self.beta = beta
  1468     def _fix(self):
  1469         return int(round(random.gammavariate(self.alpha, self.beta)))
  1470 
  1471 class RandNumGauss(RandField):
  1472     def __init__(self, mu, sigma):
  1473         self.mu = mu
  1474         self.sigma = sigma
  1475     def _fix(self):
  1476         return int(round(random.gauss(self.mu, self.sigma)))
  1477 
  1478 class RandNumExpo(RandField):
  1479     def __init__(self, lambd):
  1480         self.lambd = lambd
  1481     def _fix(self):
  1482         return int(round(random.expovariate(self.lambd)))
  1483 
  1484 class RandByte(RandNum):
  1485     def __init__(self):
  1486         RandNum.__init__(self, 0, 2L**8-1)
  1487 
  1488 class RandShort(RandNum):
  1489     def __init__(self):
  1490         RandNum.__init__(self, 0, 2L**16-1)
  1491 
  1492 class RandInt(RandNum):
  1493     def __init__(self):
  1494         RandNum.__init__(self, 0, 2L**32-1)
  1495 
  1496 class RandSInt(RandNum):
  1497     def __init__(self):
  1498         RandNum.__init__(self, -2L**31, 2L**31-1)
  1499 
  1500 class RandLong(RandNum):
  1501     def __init__(self):
  1502         RandNum.__init__(self, 0, 2L**64-1)
  1503 
  1504 class RandSLong(RandNum):
  1505     def __init__(self):
  1506         RandNum.__init__(self, -2L**63, 2L**63-1)
  1507 
  1508 class RandChoice(RandField):
  1509     def __init__(self, *args):
  1510         if not args:
  1511             raise TypeError("RandChoice needs at least one choice")
  1512         self._choice = args
  1513     def _fix(self):
  1514         return random.choice(self._choice)
  1515     
  1516 class RandString(RandField):
  1517     def __init__(self, size, chars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"):
  1518         self.chars = chars
  1519         self.size = size
  1520     def _fix(self):
  1521         s = ""
  1522         for i in range(self.size):
  1523             s += random.choice(self.chars)
  1524         return s
  1525 
  1526 class RandBin(RandString):
  1527     def __init__(self, size):
  1528         RandString.__init__(self, size, "".join(map(chr,range(256))))
  1529 
  1530 
  1531 class RandTermString(RandString):
  1532     def __init__(self, size, term):
  1533         RandString.__init__(self, size, "".join(map(chr,range(1,256))))
  1534         self.term = term
  1535     def _fix(self):
  1536         return RandString._fix(self)+self.term
  1537     
  1538     
  1539 
  1540 class RandIP(RandString):
  1541     def __init__(self, iptemplate="0.0.0.0/0"):
  1542         self.ip = Net(iptemplate)
  1543     def _fix(self):
  1544         return self.ip.choice()
  1545 
  1546 class RandMAC(RandString):
  1547     def __init__(self, template="*"):
  1548         template += ":*:*:*:*:*"
  1549         template = template.split(":")
  1550         self.mac = ()
  1551         for i in range(6):
  1552             if template[i] == "*":
  1553                 v = RandByte()
  1554             elif "-" in template[i]:
  1555                 x,y = template[i].split("-")
  1556                 v = RandNum(int(x,16), int(y,16))
  1557             else:
  1558                 v = int(template[i],16)
  1559             self.mac += (v,)
  1560     def _fix(self):
  1561         return "%02x:%02x:%02x:%02x:%02x:%02x" % self.mac
  1562     
  1563 
  1564 class RandOID(RandString):
  1565     def __init__(self, fmt=None, depth=RandNumExpo(0.1), idnum=RandNumExpo(0.01)):
  1566         self.ori_fmt = fmt
  1567         if fmt is not None:
  1568             fmt = fmt.split(".")
  1569             for i in range(len(fmt)):
  1570                 if "-" in fmt[i]:
  1571                     fmt[i] = tuple(map(int, fmt[i].split("-")))
  1572         self.fmt = fmt
  1573         self.depth = depth
  1574         self.idnum = idnum
  1575     def __repr__(self):
  1576         if self.ori_fmt is None:
  1577             return "<%s>" % self.__class__.__name__
  1578         else:
  1579             return "<%s [%s]>" % (self.__class__.__name__, self.ori_fmt)
  1580     def _fix(self):
  1581         if self.fmt is None:
  1582             return ".".join(map(str, [self.idnum for i in xrange(1+self.depth)]))
  1583         else:
  1584             oid = []
  1585             for i in self.fmt:
  1586                 if i == "*":
  1587                     oid.append(str(self.idnum))
  1588                 elif i == "**":
  1589                     oid += map(str, [self.idnum for i in xrange(1+self.depth)])
  1590                 elif type(i) is tuple:
  1591                     oid.append(str(random.randrange(*i)))
  1592                 else:
  1593                     oid.append(i)
  1594             return ".".join(oid)
  1595             
  1596 
  1597 
  1598 class RandASN1Object(RandField):
  1599     def __init__(self, objlist=None):
  1600         if objlist is None:
  1601             objlist = map(lambda x:x._asn1_obj,
  1602                           filter(lambda x:hasattr(x,"_asn1_obj"), ASN1_Class_UNIVERSAL.__rdict__.values()))
  1603         self.objlist = objlist
  1604         self.chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
  1605     def _fix(self, n=0):
  1606         o = random.choice(self.objlist)
  1607         if issubclass(o, ASN1_INTEGER):
  1608             return o(int(random.gauss(0,1000)))
  1609         elif issubclass(o, ASN1_STRING):
  1610             z = int(random.expovariate(0.05)+1)
  1611             return o("".join([random.choice(self.chars) for i in range(z)]))
  1612         elif issubclass(o, ASN1_SEQUENCE) and (n < 10):
  1613             z = int(random.expovariate(0.08)+1)
  1614             return o(map(lambda x:x._fix(n+1), [self.__class__(objlist=self.objlist)]*z))
  1615         return ASN1_INTEGER(int(random.gauss(0,1000)))
  1616 
  1617 class RandDHCPOptions(RandField):
  1618     def __init__(self, size=None, rndstr=None):
  1619         if size is None:
  1620             size = RandNumExpo(0.05)
  1621         self.size = size
  1622         if rndstr is None:
  1623             rndstr = RandBin(RandNum(0,255))
  1624         self.rndstr=rndstr
  1625         self._opts = DHCPOptions.values()
  1626         self._opts.remove("pad")
  1627         self._opts.remove("end")
  1628     def _fix(self):
  1629         op = []
  1630         for k in range(self.size):
  1631             o = random.choice(self._opts)
  1632             if type(o) is str:
  1633                 op.append((o,self.rndstr*1))
  1634             else:
  1635                 op.append((o.name, o.randval()._fix()))
  1636         return op
  1637             
  1638 
  1639 # Automatic timestamp
  1640 
  1641 class AutoTime(VolatileValue):
  1642     def __init__(self, base=None):
  1643         if base == None:
  1644             self.diff = 0
  1645         else:
  1646             self.diff = time.time()-base
  1647     def _fix(self):
  1648         return time.time()-self.diff
  1649             
  1650 class IntAutoTime(AutoTime):
  1651     def _fix(self):
  1652         return int(time.time()-self.diff)
  1653 
  1654 
  1655 class ZuluTime(AutoTime):
  1656     def __init__(self, diff=None):
  1657         self.diff=diff
  1658     def _fix(self):
  1659         return time.strftime("%y%m%d%H%M%SZ",time.gmtime(time.time()+self.diff))
  1660 
  1661 
  1662 class DelayedEval(VolatileValue):
  1663     """ Exemple of usage: DelayedEval("time.time()") """
  1664     def __init__(self, expr):
  1665         self.expr = expr
  1666     def _fix(self):
  1667         return eval(self.expr)
  1668 
  1669 
  1670 class IncrementalValue(VolatileValue):
  1671     def __init__(self, start=0, step=1, restart=-1):
  1672         self.start = self.val = start
  1673         self.step = step
  1674         self.restart = restart
  1675     def _fix(self):
  1676         v = self.val
  1677         if self.val == self.restart :
  1678             self.val = self.start
  1679         else:
  1680             self.val += self.step
  1681         return v
  1682 
  1683 def corrupt_bytes(s, p=0.01, n=None):
  1684     s = array.array("B",str(s))
  1685     l = len(s)
  1686     if n is None:
  1687         n = max(1,int(l*p))
  1688     for i in random.sample(xrange(l), n):
  1689         s[i] = random.randint(0,255)
  1690     return s.tostring()
  1691 
  1692 def corrupt_bits(s, p=0.01, n=None):
  1693     s = array.array("B",str(s))
  1694     l = len(s)*8
  1695     if n is None:
  1696         n = max(1,int(l*p))
  1697     for i in random.sample(xrange(l), n):
  1698         s[i/8] ^= 1 << (i%8)
  1699     return s.tostring()
  1700 
  1701     
  1702 class CorruptedBytes(VolatileValue):
  1703     def __init__(self, s, p=0.01, n=None):
  1704         self.s = s
  1705         self.p = p
  1706         self.n = n
  1707     def _fix(self):
  1708         return corrupt_bytes(self.s, self.p, self.n)
  1709 
  1710 class CorruptedBits(CorruptedBytes):
  1711     def _fix(self):
  1712         return corrupt_bits(self.s, self.p, self.n)
  1713 
  1714 ##############
  1715 #### ASN1 ####
  1716 ##############
  1717 
  1718 class ASN1_Error(Exception):
  1719     pass
  1720 
  1721 class ASN1_Encoding_Error(ASN1_Error):
  1722     pass
  1723 
  1724 class ASN1_Decoding_Error(ASN1_Error):
  1725     pass
  1726 
  1727 class ASN1_BadTag_Decoding_Error(ASN1_Decoding_Error):
  1728     pass
  1729 
  1730 
  1731 
  1732 class ASN1Codec(EnumElement):
  1733     def register_stem(cls, stem):
  1734         cls._stem = stem
  1735     def dec(cls, s, context=None):
  1736         return cls._stem.dec(s, context=context)
  1737     def safedec(cls, s, context=None):
  1738         return cls._stem.safedec(s, context=context)
  1739     def get_stem(cls):
  1740         return cls.stem
  1741     
  1742 
  1743 class ASN1_Codecs_metaclass(Enum_metaclass):
  1744     element_class = ASN1Codec
  1745 
  1746 class ASN1_Codecs:
  1747     __metaclass__ = ASN1_Codecs_metaclass
  1748     BER = 1
  1749     DER = 2
  1750     PER = 3
  1751     CER = 4
  1752     LWER = 5
  1753     BACnet = 6
  1754     OER = 7
  1755     SER = 8
  1756     XER = 9
  1757 
  1758 class ASN1Tag(EnumElement):
  1759     def __init__(self, key, value, context=None, codec=None):
  1760         EnumElement.__init__(self, key, value)
  1761         self._context = context
  1762         if codec == None:
  1763             codec = {}
  1764         self._codec = codec
  1765     def clone(self): # /!\ not a real deep copy. self.codec is shared
  1766         return self.__class__(self._key, self._value, self._context, self._codec)
  1767     def register_asn1_object(self, asn1obj):
  1768         self._asn1_obj = asn1obj
  1769     def asn1_object(self, val):
  1770         if hasattr(self,"_asn1_obj"):
  1771             return self._asn1_obj(val)
  1772         raise ASN1_Error("%r does not have any assigned ASN1 object" % self)
  1773     def register(self, codecnum, codec):
  1774         self._codec[codecnum] = codec
  1775     def get_codec(self, codec):
  1776         try:
  1777             c = self._codec[codec]
  1778         except KeyError,msg:
  1779             raise ASN1_Error("Codec %r not found for tag %r" % (codec, self))
  1780         return c
  1781 
  1782 class ASN1_Class_metaclass(Enum_metaclass):
  1783     element_class = ASN1Tag
  1784     def __new__(cls, name, bases, dct): # XXX factorise a bit with Enum_metaclass.__new__()
  1785         for b in bases:
  1786             for k,v in b.__dict__.iteritems():
  1787                 if k not in dct and isinstance(v,ASN1Tag):
  1788                     dct[k] = v.clone()
  1789 
  1790         rdict = {}
  1791         for k,v in dct.iteritems():
  1792             if type(v) is int:
  1793                 v = ASN1Tag(k,v) 
  1794                 dct[k] = v
  1795                 rdict[v] = v
  1796             elif isinstance(v, ASN1Tag):
  1797                 rdict[v] = v
  1798         dct["__rdict__"] = rdict
  1799 
  1800         cls = type.__new__(cls, name, bases, dct)
  1801         for v in cls.__dict__.values():
  1802             if isinstance(v, ASN1Tag): 
  1803                 v.context = cls # overwrite ASN1Tag contexts, even cloned ones
  1804         return cls
  1805             
  1806 
  1807 class ASN1_Class:
  1808     __metaclass__ = ASN1_Class_metaclass
  1809 
  1810 class ASN1_Class_UNIVERSAL(ASN1_Class):
  1811     name = "UNIVERSAL"
  1812     ERROR = -3
  1813     RAW = -2
  1814     NONE = -1
  1815     ANY = 0
  1816     BOOLEAN = 1
  1817     INTEGER = 2
  1818     BIT_STRING = 3
  1819     STRING = 4
  1820     NULL = 5
  1821     OID = 6
  1822     OBJECT_DESCRIPTOR = 7
  1823     EXTERNAL = 8
  1824     REAL = 9
  1825     ENUMERATED = 10
  1826     EMBEDDED_PDF = 11
  1827     UTF8_STRING = 12
  1828     RELATIVE_OID = 13
  1829     SEQUENCE = 0x30#XXX 16 ??
  1830     SET = 0x31 #XXX 17 ??
  1831     NUMERIC_STRING = 18
  1832     PRINTABLE_STRING = 19
  1833     T61_STRING = 20
  1834     VIDEOTEX_STRING = 21
  1835     IA5_STRING = 22
  1836     UTC_TIME = 23
  1837     GENERALIZED_TIME = 24
  1838     GRAPHIC_STRING = 25
  1839     ISO646_STRING = 26
  1840     GENERAL_STRING = 27
  1841     UNIVERSAL_STRING = 28
  1842     CHAR_STRING = 29
  1843     BMP_STRING = 30
  1844     COUNTER32 = 0x41
  1845     TIME_TICKS = 0x43
  1846 
  1847 class ASN1_Object_metaclass(type):
  1848     def __new__(cls, name, bases, dct):
  1849         c = super(ASN1_Object_metaclass, cls).__new__(cls, name, bases, dct)
  1850         try:
  1851             c.tag.register_asn1_object(c)
  1852         except:
  1853             warning("Error registering %r for %r" % (c.tag, c.codec))
  1854         return c
  1855 
  1856 
  1857 class ASN1_Object:
  1858     __metaclass__ = ASN1_Object_metaclass
  1859     tag = ASN1_Class_UNIVERSAL.ANY
  1860     def __init__(self, val):
  1861         self.val = val
  1862     def enc(self, codec):
  1863         return self.tag.get_codec(codec).enc(self.val)
  1864     def __repr__(self):
  1865         return "<%s[%r]>" % (self.__dict__.get("name", self.__class__.__name__), self.val)
  1866     def __str__(self):
  1867         return self.enc(conf.ASN1_default_codec)
  1868     def strshow(self, lvl=0):
  1869         return ("  "*lvl)+repr(self)+"\n"
  1870     def show(self, lvl=0):
  1871         print self.strshow(lvl)
  1872     def __eq__(self, other):
  1873         return self.val == other
  1874     def __cmp__(self, other):
  1875         return cmp(self.val, other)
  1876 
  1877 class ASN1_DECODING_ERROR(ASN1_Object):
  1878     tag = ASN1_Class_UNIVERSAL.ERROR
  1879     def __init__(self, val, exc=None):
  1880         ASN1_Object.__init__(self, val)
  1881         self.exc = exc
  1882     def __repr__(self):
  1883         return "<%s[%r]{{%s}}>" % (self.__dict__.get("name", self.__class__.__name__),
  1884                                    self.val, self.exc.args[0])
  1885     def enc(self, codec):
  1886         if isinstance(self.val, ASN1_Object):
  1887             return self.val.enc(codec)
  1888         return self.val
  1889 
  1890 class ASN1_force(ASN1_Object):
  1891     tag = ASN1_Class_UNIVERSAL.RAW
  1892     def enc(self, codec):
  1893         if isinstance(self.val, ASN1_Object):
  1894             return self.val.enc(codec)
  1895         return self.val
  1896 
  1897 class ASN1_BADTAG(ASN1_force):
  1898     pass
  1899 
  1900 class ASN1_INTEGER(ASN1_Object):
  1901     tag = ASN1_Class_UNIVERSAL.INTEGER
  1902 
  1903 class ASN1_STRING(ASN1_Object):
  1904     tag = ASN1_Class_UNIVERSAL.STRING
  1905 
  1906 class ASN1_BIT_STRING(ASN1_STRING):
  1907     tag = ASN1_Class_UNIVERSAL.BIT_STRING
  1908 
  1909 class ASN1_PRINTABLE_STRING(ASN1_STRING):
  1910     tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
  1911 
  1912 class ASN1_T61_STRING(ASN1_STRING):
  1913     tag = ASN1_Class_UNIVERSAL.T61_STRING
  1914 
  1915 class ASN1_IA5_STRING(ASN1_STRING):
  1916     tag = ASN1_Class_UNIVERSAL.IA5_STRING
  1917 
  1918 class ASN1_NUMERIC_STRING(ASN1_STRING):
  1919     tag = ASN1_Class_UNIVERSAL.NUMERIC_STRING
  1920 
  1921 class ASN1_VIDEOTEX_STRING(ASN1_STRING):
  1922     tag = ASN1_Class_UNIVERSAL.VIDEOTEX_STRING
  1923 
  1924 class ASN1_UTC_TIME(ASN1_STRING):
  1925     tag = ASN1_Class_UNIVERSAL.UTC_TIME
  1926 
  1927 class ASN1_TIME_TICKS(ASN1_INTEGER):
  1928     tag = ASN1_Class_UNIVERSAL.TIME_TICKS
  1929 
  1930 class ASN1_BOOLEAN(ASN1_INTEGER):
  1931     tag = ASN1_Class_UNIVERSAL.BOOLEAN
  1932     
  1933 class ASN1_NULL(ASN1_INTEGER):
  1934     tag = ASN1_Class_UNIVERSAL.NULL
  1935 
  1936 class ASN1_COUNTER32(ASN1_INTEGER):
  1937     tag = ASN1_Class_UNIVERSAL.COUNTER32
  1938     
  1939 class ASN1_SEQUENCE(ASN1_Object):
  1940     tag = ASN1_Class_UNIVERSAL.SEQUENCE
  1941     def strshow(self, lvl=0):
  1942         s = ("  "*lvl)+("# %s:" % self.__class__.__name__)+"\n"
  1943         for o in self.val:
  1944             s += o.strshow(lvl=lvl+1)
  1945         return s
  1946     
  1947 class ASN1_SET(ASN1_SEQUENCE):
  1948     tag = ASN1_Class_UNIVERSAL.SET
  1949     
  1950 class ASN1_OID(ASN1_Object):
  1951     tag = ASN1_Class_UNIVERSAL.OID
  1952     def __init__(self, val):
  1953         val = conf.mib._oid(val)
  1954         ASN1_Object.__init__(self, val)
  1955     def __repr__(self):
  1956         return "<%s[%r]>" % (self.__dict__.get("name", self.__class__.__name__), conf.mib._oidname(self.val))
  1957     
  1958 
  1959 
  1960 ##################
  1961 ## BER encoding ##
  1962 ##################
  1963 
  1964 
  1965 
  1966 #####[ BER tools ]#####
  1967 
  1968 
  1969 class BER_Exception(Exception):
  1970     pass
  1971 
  1972 class BER_Decoding_Error(ASN1_Decoding_Error):
  1973     def __init__(self, msg, decoded=None, remaining=None):
  1974         Exception.__init__(self, msg)
  1975         self.remaining = remaining
  1976         self.decoded = decoded
  1977     def __str__(self):
  1978         s = Exception.__str__(self)
  1979         if isinstance(self.decoded, BERcodec_Object):
  1980             s+="\n### Already decoded ###\n%s" % self.decoded.strshow()
  1981         else:
  1982             s+="\n### Already decoded ###\n%r" % self.decoded
  1983         s+="\n### Remaining ###\n%r" % self.remaining
  1984         return s
  1985 
  1986 class BER_BadTag_Decoding_Error(BER_Decoding_Error, ASN1_BadTag_Decoding_Error):
  1987     pass
  1988 
  1989 def BER_len_enc(l, size=0):
  1990         if l <= 127 and size==0:
  1991             return chr(l)
  1992         s = ""
  1993         while l or size>0:
  1994             s = chr(l&0xff)+s
  1995             l >>= 8L
  1996             size -= 1
  1997         if len(s) > 127:
  1998             raise BER_Exception("BER_len_enc: Length too long (%i) to be encoded [%r]" % (len(s),s))
  1999         return chr(len(s)|0x80)+s
  2000 def BER_len_dec(s):
  2001         l = ord(s[0])
  2002         if not l & 0x80:
  2003             return l,s[1:]
  2004         l &= 0x7f
  2005         if len(s) <= l:
  2006             raise BER_Decoding_Error("BER_len_dec: Got %i bytes while expecting %i" % (len(s)-1, l),remaining=s)
  2007         ll = 0L
  2008         for c in s[1:l+1]:
  2009             ll <<= 8L
  2010             ll |= ord(c)
  2011         return ll,s[l+1:]
  2012         
  2013 def BER_num_enc(l, size=1):
  2014         x=[]
  2015         while l or size>0:
  2016             x.insert(0, l & 0x7f)
  2017             if len(x) > 1:
  2018                 x[0] |= 0x80
  2019             l >>= 7
  2020             size -= 1
  2021         return "".join([chr(k) for k in x])
  2022 def BER_num_dec(s):
  2023         x = 0
  2024         for i in range(len(s)):
  2025             c = ord(s[i])
  2026             x <<= 7
  2027             x |= c&0x7f
  2028             if not c&0x80:
  2029                 break
  2030         if c&0x80:
  2031             raise BER_Decoding_Error("BER_num_dec: unfinished number description", remaining=s)
  2032         return x, s[i+1:]
  2033 
  2034 #####[ BER classes ]#####
  2035 
  2036 class BERcodec_metaclass(type):
  2037     def __new__(cls, name, bases, dct):
  2038         c = super(BERcodec_metaclass, cls).__new__(cls, name, bases, dct)
  2039         try:
  2040             c.tag.register(c.codec, c)
  2041         except:
  2042             warning("Error registering %r for %r" % (c.tag, c.codec))
  2043         return c
  2044 
  2045 
  2046 class BERcodec_Object:
  2047     __metaclass__ = BERcodec_metaclass
  2048     codec = ASN1_Codecs.BER
  2049     tag = ASN1_Class_UNIVERSAL.ANY
  2050 
  2051     @classmethod
  2052     def asn1_object(cls, val):
  2053         return cls.tag.asn1_object(val)
  2054 
  2055     @classmethod
  2056     def check_string(cls, s):
  2057         if not s:
  2058             raise BER_Decoding_Error("%s: Got empty object while expecting tag %r" %
  2059                                      (cls.__name__,cls.tag), remaining=s)        
  2060     @classmethod
  2061     def check_type(cls, s):
  2062         cls.check_string(s)
  2063         if cls.tag != ord(s[0]):
  2064             raise BER_BadTag_Decoding_Error("%s: Got tag [%i/%#x] while expecting %r" %
  2065                                             (cls.__name__, ord(s[0]), ord(s[0]),cls.tag), remaining=s)
  2066         return s[1:]
  2067     @classmethod
  2068     def check_type_get_len(cls, s):
  2069         s2 = cls.check_type(s)
  2070         if not s2:
  2071             raise BER_Decoding_Error("%s: No bytes while expecting a length" %
  2072                                      cls.__name__, remaining=s)
  2073         return BER_len_dec(s2)
  2074     @classmethod
  2075     def check_type_check_len(cls, s):
  2076         l,s3 = cls.check_type_get_len(s)
  2077         if len(s3) < l:
  2078             raise BER_Decoding_Error("%s: Got %i bytes while expecting %i" %
  2079                                      (cls.__name__, len(s3), l), remaining=s)
  2080         return l,s3[:l],s3[l:]
  2081 
  2082     @classmethod
  2083     def do_dec(cls, s, context=None, safe=False):
  2084         if context is None:
  2085             context = cls.tag.context
  2086         cls.check_string(s)
  2087         p = ord(s[0])
  2088         if p not in context:
  2089             t = s
  2090             if len(t) > 18:
  2091                 t = t[:15]+"..."
  2092             raise BER_Decoding_Error("Unknown prefix [%02x] for [%r]" % (p,t), remaining=s)
  2093         codec = context[p].get_codec(ASN1_Codecs.BER)
  2094         return codec.dec(s,context,safe)
  2095 
  2096     @classmethod
  2097     def dec(cls, s, context=None, safe=False):
  2098         if not safe:
  2099             return cls.do_dec(s, context, safe)
  2100         try:
  2101             return cls.do_dec(s, context, safe)
  2102         except BER_BadTag_Decoding_Error,e:
  2103             o,remain = BERcodec_Object.dec(e.remaining, context, safe)
  2104             return ASN1_BADTAG(o),remain
  2105         except BER_Decoding_Error, e:
  2106             return ASN1_DECODING_ERROR(s, exc=e),""
  2107         except ASN1_Error, e:
  2108             return ASN1_DECODING_ERROR(s, exc=e),""
  2109 
  2110     @classmethod
  2111     def safedec(cls, s, context=None):
  2112         return cls.dec(s, context, safe=True)
  2113 
  2114 
  2115     @classmethod
  2116     def enc(cls, s):
  2117         if type(s) is str:
  2118             return BERcodec_STRING.enc(s)
  2119         else:
  2120             return BERcodec_INTEGER.enc(int(s))
  2121 
  2122             
  2123 
  2124 ASN1_Codecs.BER.register_stem(BERcodec_Object)
  2125 
  2126 
  2127 class BERcodec_INTEGER(BERcodec_Object):
  2128     tag = ASN1_Class_UNIVERSAL.INTEGER
  2129     @classmethod
  2130     def enc(cls, i):
  2131         s = []
  2132         while 1:
  2133             s.append(i&0xff)
  2134             if -127 <= i < 0:
  2135                 break
  2136             if 128 <= i <= 255:
  2137                 s.append(0)
  2138             i >>= 8
  2139             if not i:
  2140                 break
  2141         s = map(chr, s)
  2142         s.append(BER_len_enc(len(s)))
  2143         s.append(chr(cls.tag))
  2144         s.reverse()
  2145         return "".join(s)
  2146     @classmethod
  2147     def do_dec(cls, s, context=None, safe=False):
  2148         l,s,t = cls.check_type_check_len(s)
  2149         x = 0L
  2150         if s:
  2151             if ord(s[0])&0x80: # negative int
  2152                 x = -1L
  2153             for c in s:
  2154                 x <<= 8
  2155                 x |= ord(c)
  2156         return cls.asn1_object(x),t
  2157     
  2158 
  2159 class BERcodec_BOOLEAN(BERcodec_INTEGER):
  2160     tag = ASN1_Class_UNIVERSAL.BOOLEAN
  2161 
  2162 class BERcodec_NULL(BERcodec_INTEGER):
  2163     tag = ASN1_Class_UNIVERSAL.NULL
  2164     @classmethod
  2165     def enc(cls, i):
  2166         if i == 0:
  2167             return chr(cls.tag)+"\0"
  2168         else:
  2169             return super(cls,cls).enc(i)
  2170 
  2171 class BERcodec_STRING(BERcodec_Object):
  2172     tag = ASN1_Class_UNIVERSAL.STRING
  2173     @classmethod
  2174     def enc(cls,s):
  2175         return chr(cls.tag)+BER_len_enc(len(s))+s
  2176     @classmethod
  2177     def do_dec(cls, s, context=None, safe=False):
  2178         l,s,t = cls.check_type_check_len(s)
  2179         return cls.tag.asn1_object(s),t
  2180 
  2181 class BERcodec_BIT_STRING(BERcodec_STRING):
  2182     tag = ASN1_Class_UNIVERSAL.BIT_STRING
  2183 
  2184 class BERcodec_PRINTABLE_STRING(BERcodec_STRING):
  2185     tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
  2186 
  2187 class BERcodec_T61_STRING (BERcodec_STRING):
  2188     tag = ASN1_Class_UNIVERSAL.T61_STRING
  2189 
  2190 class BERcodec_IA5_STRING(BERcodec_STRING):
  2191     tag = ASN1_Class_UNIVERSAL.IA5_STRING
  2192 
  2193 class BERcodec_UTC_TIME(BERcodec_STRING):
  2194     tag = ASN1_Class_UNIVERSAL.UTC_TIME
  2195 
  2196 class BERcodec_TIME_TICKS(BERcodec_INTEGER):
  2197     tag = ASN1_Class_UNIVERSAL.TIME_TICKS
  2198 
  2199 class BERcodec_COUNTER32(BERcodec_INTEGER):
  2200     tag = ASN1_Class_UNIVERSAL.COUNTER32
  2201 
  2202 class BERcodec_SEQUENCE(BERcodec_Object):
  2203     tag = ASN1_Class_UNIVERSAL.SEQUENCE
  2204     @classmethod
  2205     def enc(cls, l):
  2206         if type(l) is not str:
  2207             l = "".join(map(lambda x: x.enc(cls.codec), l))
  2208         return chr(cls.tag)+BER_len_enc(len(l))+l
  2209     @classmethod
  2210     def do_dec(cls, s, context=None, safe=False):
  2211         if context is None:
  2212             context = cls.tag.context
  2213         l,st = cls.check_type_get_len(s) # we may have len(s) < l
  2214         s,t = st[:l],st[l:]
  2215         obj = []
  2216         while s:
  2217             try:
  2218                 o,s = BERcodec_Object.dec(s, context, safe)
  2219             except BER_Decoding_Error, err:
  2220                 err.remaining += t
  2221                 if err.decoded is not None:
  2222                     obj.append(err.decoded)
  2223                 err.decoded = obj
  2224                 raise 
  2225             obj.append(o)
  2226         if len(st) < l:
  2227             raise BER_Decoding_Error("Not enough bytes to decode sequence", decoded=obj)
  2228         return cls.asn1_object(obj),t
  2229 
  2230 class BERcodec_SET(BERcodec_SEQUENCE):
  2231     tag = ASN1_Class_UNIVERSAL.SET
  2232 
  2233 
  2234 class BERcodec_OID(BERcodec_Object):
  2235     tag = ASN1_Class_UNIVERSAL.OID
  2236 
  2237     @classmethod
  2238     def enc(cls, oid):
  2239         lst = [int(x) for x in oid.strip(".").split(".")]
  2240         if len(lst) >= 2:
  2241             lst[1] += 40*lst[0]
  2242             del(lst[0])
  2243         s = "".join([BER_num_enc(k) for k in lst])
  2244         return chr(cls.tag)+BER_len_enc(len(s))+s
  2245     @classmethod
  2246     def do_dec(cls, s, context=None, safe=False):
  2247         l,s,t = cls.check_type_check_len(s)
  2248         lst = []
  2249         while s:
  2250             l,s = BER_num_dec(s)
  2251             lst.append(l)
  2252         if (len(lst) > 0):
  2253             lst.insert(0,lst[0]/40)
  2254             lst[1] %= 40
  2255         return cls.asn1_object(".".join([str(k) for k in lst])), t
  2256 
  2257 
  2258 #################
  2259 ## MIB parsing ##
  2260 #################
  2261 
  2262 _mib_re_integer = re.compile("^[0-9]+$")
  2263 _mib_re_both = re.compile("^([a-zA-Z_][a-zA-Z0-9_-]*)\(([0-9]+)\)$")
  2264 _mib_re_oiddecl = re.compile("$\s*([a-zA-Z0-9_-]+)\s+OBJECT[^:]+::=\s*\{([^\}]+)\}",re.M)
  2265 _mib_re_strings = re.compile('"[^"]*"')
  2266 _mib_re_comments = re.compile('--.*(\r|\n)')
  2267 
  2268 class MIBDict(DADict):
  2269     def _findroot(self, x):
  2270         if x.startswith("."):
  2271             x = x[1:]
  2272         if not x.endswith("."):
  2273             x += "."
  2274         max=0
  2275         root="."
  2276         for k in self.keys():
  2277             if x.startswith(self[k]+"."):
  2278                 if max < len(self[k]):
  2279                     max = len(self[k])
  2280                     root = k
  2281         return root, x[max:-1]
  2282     def _oidname(self, x):
  2283         root,remainder = self._findroot(x)
  2284         return root+remainder
  2285     def _oid(self, x):
  2286         xl = x.strip(".").split(".")
  2287         p = len(xl)-1
  2288         while p >= 0 and _mib_re_integer.match(xl[p]):
  2289             p -= 1
  2290         if p != 0 or xl[p] not in self:
  2291             return x
  2292         xl[p] = self[xl[p]] 
  2293         return ".".join(xl[p:])
  2294     def _make_graph(self, other_keys=[], **kargs):
  2295         nodes = [(k,self[k]) for k in self.keys()]
  2296         oids = [self[k] for k in self.keys()]
  2297         for k in other_keys:
  2298             if k not in oids:
  2299                 nodes.append(self.oidname(k),k)
  2300         s = 'digraph "mib" {\n\trankdir=LR;\n\n'
  2301         for k,o in nodes:
  2302             s += '\t"%s" [ label="%s"  ];\n' % (o,k)
  2303         s += "\n"
  2304         for k,o in nodes:
  2305             parent,remainder = self._findroot(o[:-1])
  2306             remainder = remainder[1:]+o[-1]
  2307             if parent != ".":
  2308                 parent = self[parent]
  2309             s += '\t"%s" -> "%s" [label="%s"];\n' % (parent, o,remainder)
  2310         s += "}\n"
  2311         do_graph(s, **kargs)
  2312 
  2313 
  2314 def mib_register(ident, value, the_mib, unresolved):
  2315     if ident in the_mib or ident in unresolved:
  2316         return ident in the_mib
  2317     resval = []
  2318     not_resolved = 0
  2319     for v in value:
  2320         if _mib_re_integer.match(v):
  2321             resval.append(v)
  2322         else:
  2323             v = fixname(v)
  2324             if v not in the_mib:
  2325                 not_resolved = 1
  2326             if v in the_mib:
  2327                 v = the_mib[v]
  2328             elif v in unresolved:
  2329                 v = unresolved[v]
  2330             if type(v) is list:
  2331                 resval += v
  2332             else:
  2333                 resval.append(v)
  2334     if not_resolved:
  2335         unresolved[ident] = resval
  2336         return False
  2337     else:
  2338         the_mib[ident] = resval
  2339         keys = unresolved.keys()
  2340         i = 0
  2341         while i < len(keys):
  2342             k = keys[i]
  2343             if mib_register(k,unresolved[k], the_mib, {}):
  2344                 del(unresolved[k])
  2345                 del(keys[i])
  2346                 i = 0
  2347             else:
  2348                 i += 1
  2349                     
  2350         return True
  2351 
  2352 
  2353 def load_mib(filenames):
  2354     the_mib = {'iso': ['1']}
  2355     unresolved = {}
  2356     for k in conf.mib.keys():
  2357         mib_register(k, conf.mib[k].split("."), the_mib, unresolved)
  2358 
  2359     if type(filenames) is str:
  2360         filenames = [filenames]
  2361     for fnames in filenames:
  2362         for fname in glob(fnames):
  2363             f = open(fname)
  2364             text = f.read()
  2365             cleantext = " ".join(_mib_re_strings.split(" ".join(_mib_re_comments.split(text))))
  2366             for m in _mib_re_oiddecl.finditer(cleantext):
  2367                 ident,oid = m.groups()
  2368                 ident=fixname(ident)
  2369                 oid = oid.split()
  2370                 for i in range(len(oid)):
  2371                     m = _mib_re_both.match(oid[i])
  2372                     if m:
  2373                         oid[i] = m.groups()[1]
  2374                 mib_register(ident, oid, the_mib, unresolved)
  2375 
  2376     newmib = MIBDict(_name="MIB")
  2377     for k,o in the_mib.iteritems():
  2378         newmib[k]=".".join(o)
  2379     for k,o in unresolved.iteritems():
  2380         newmib[k]=".".join(o)
  2381 
  2382     conf.mib=newmib
  2383 
  2384 
  2385 
  2386 ################
  2387 ## Generators ##
  2388 ################
  2389 
  2390 class Gen(object):
  2391     def __iter__(self):
  2392         return iter([])
  2393     
  2394 class SetGen(Gen):
  2395     def __init__(self, set, _iterpacket=1):
  2396         self._iterpacket=_iterpacket
  2397         if type(set) is list:
  2398             self.set = set
  2399         elif isinstance(set, PacketList):
  2400             self.set = list(set)
  2401         else:
  2402             self.set = [set]
  2403     def transf(self, element):
  2404         return element
  2405     def __iter__(self):
  2406         for i in self.set:
  2407             if (type(i) is tuple) and (len(i) == 2) and type(i[0]) is int and type(i[1]) is int:
  2408                 if  (i[0] <= i[1]):
  2409                     j=i[0]
  2410                     while j <= i[1]:
  2411                         yield j
  2412                         j += 1
  2413             elif isinstance(i, Gen) and (self._iterpacket or not isinstance(i,Packet)):
  2414                 for j in i:
  2415                     yield j
  2416             else:
  2417                 yield i
  2418     def __repr__(self):
  2419         return "<SetGen %s>" % self.set.__repr__()
  2420 
  2421 class Net(Gen):
  2422     """Generate a list of IPs from a network address or a name"""
  2423     name = "ip"
  2424     ipaddress = re.compile(r"^(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)\.(\*|[0-2]?[0-9]?[0-9](-[0-2]?[0-9]?[0-9])?)(/[0-3]?[0-9])?$")
  2425     def __init__(self, net):
  2426         self.repr=net
  2427 
  2428         tmp=net.split('/')+["32"]
  2429         if not self.ipaddress.match(net):
  2430             tmp[0]=socket.gethostbyname(tmp[0])
  2431         netmask = int(tmp[1])
  2432 
  2433         def parse_digit(a,netmask):
  2434             netmask = min(8,max(netmask,0))
  2435             if a == "*":
  2436                 a = (0,256)
  2437             elif a.find("-") >= 0:
  2438                 x,y = map(int,a.split("-"))
  2439                 if x > y:
  2440                     y = x
  2441                 a = (x &  (0xffL<<netmask) , max(y, (x | (0xffL>>(8-netmask))))+1)
  2442             else:
  2443                 a = (int(a) & (0xffL<<netmask),(int(a) | (0xffL>>(8-netmask)))+1)
  2444             return a
  2445 
  2446         self.parsed = map(lambda x,y: parse_digit(x,y), tmp[0].split("."), map(lambda x,nm=netmask: x-nm, (8,16,24,32)))
  2447                                                                                                
  2448     def __iter__(self):
  2449         for d in xrange(*self.parsed[3]):
  2450             for c in xrange(*self.parsed[2]):
  2451                 for b in xrange(*self.parsed[1]):
  2452                     for a in xrange(*self.parsed[0]):
  2453                         yield "%i.%i.%i.%i" % (a,b,c,d)
  2454     def choice(self):
  2455         ip = []
  2456         for v in self.parsed:
  2457             ip.append(str(random.randint(v[0],v[1]-1)))
  2458         return ".".join(ip) 
  2459                           
  2460     def __repr__(self):
  2461         return "Net(%r)" % self.repr
  2462 
  2463 class OID(Gen):
  2464     name = "OID"
  2465     def __init__(self, oid):
  2466         self.oid = oid        
  2467         self.cmpt = []
  2468         fmt = []        
  2469         for i in oid.split("."):
  2470             if "-" in i:
  2471                 fmt.append("%i")
  2472                 self.cmpt.append(tuple(map(int, i.split("-"))))
  2473             else:
  2474                 fmt.append(i)
  2475         self.fmt = ".".join(fmt)
  2476     def __repr__(self):
  2477         return "OID(%r)" % self.oid
  2478     def __iter__(self):        
  2479         ii = [k[0] for k in self.cmpt]
  2480         while 1:
  2481             yield self.fmt % tuple(ii)
  2482             i = 0
  2483             while 1:
  2484                 if i >= len(ii):
  2485                     raise StopIteration
  2486                 if ii[i] < self.cmpt[i][1]:
  2487                     ii[i]+=1
  2488                     break
  2489                 else:
  2490                     ii[i] = self.cmpt[i][0]
  2491                 i += 1
  2492  
  2493 
  2494 #############
  2495 ## Results ##
  2496 #############
  2497 
  2498 class PacketList:
  2499     res = []
  2500     def __init__(self, res=None, name="PacketList", stats=None):
  2501         """create a packet list from a list of packets
  2502            res: the list of packets
  2503            stats: a list of classes that will appear in the stats (defaults to [TCP,UDP,ICMP])"""
  2504         if stats is None:
  2505             stats = [ TCP,UDP,ICMP ]
  2506         self.stats = stats
  2507         if res is None:
  2508             res = []
  2509         if isinstance(res, PacketList):
  2510             res = res.res
  2511         self.res = res
  2512         self.listname = name
  2513     def _elt2pkt(self, elt):
  2514         return elt
  2515     def _elt2sum(self, elt):
  2516         return elt.summary()
  2517     def _elt2show(self, elt):
  2518         return self._elt2sum(elt)
  2519     def __repr__(self):
  2520 #        stats=dict.fromkeys(self.stats,0) ## needs python >= 2.3  :(
  2521         stats = dict(map(lambda x: (x,0), self.stats))
  2522         other = 0
  2523         for r in self.res:
  2524             f = 0
  2525             for p in stats:
  2526                 if self._elt2pkt(r).haslayer(p):
  2527                     stats[p] += 1
  2528                     f = 1
  2529                     break
  2530             if not f:
  2531                 other += 1
  2532         s = ""
  2533         ct = conf.color_theme
  2534         for p in self.stats:
  2535             s += " %s%s%s" % (ct.packetlist_proto(p.name),
  2536                               ct.punct(":"),
  2537                               ct.packetlist_value(stats[p]))
  2538         s += " %s%s%s" % (ct.packetlist_proto("Other"),
  2539                           ct.punct(":"),
  2540                           ct.packetlist_value(other))
  2541         return "%s%s%s%s%s" % (ct.punct("<"),
  2542                                ct.packetlist_name(self.listname),
  2543                                ct.punct(":"),
  2544                                s,
  2545                                ct.punct(">"))
  2546     def __getattr__(self, attr):
  2547         return getattr(self.res, attr)
  2548     def __getitem__(self, item):
  2549         if isinstance(item,type) and issubclass(item,Packet):
  2550             return self.__class__(filter(lambda x: item in self._elt2pkt(x),self.res),
  2551                                   name="%s from %s"%(item.__name__,self.listname))
  2552         if type(item) is slice:
  2553             return self.__class__(self.res.__getitem__(item),
  2554                                   name = "mod %s" % self.listname)
  2555         return self.res.__getitem__(item)
  2556     def __getslice__(self, *args, **kargs):
  2557         return self.__class__(self.res.__getslice__(*args, **kargs),
  2558                               name="mod %s"%self.listname)
  2559     def __add__(self, other):
  2560         return self.__class__(self.res+other.res,
  2561                               name="%s+%s"%(self.listname,other.listname))
  2562     def summary(self, prn=None, lfilter=None):
  2563         """prints a summary of each packet
  2564 prn:     function to apply to each packet instead of lambda x:x.summary()
  2565 lfilter: truth function to apply to each packet to decide whether it will be displayed"""
  2566         for r in self.res:
  2567             if lfilter is not None:
  2568                 if not lfilter(r):
  2569                     continue
  2570             if prn is None:
  2571                 print self._elt2sum(r)
  2572             else:
  2573                 print prn(r)
  2574     def nsummary(self,prn=None, lfilter=None):
  2575         """prints a summary of each packet with the packet's number
  2576 prn:     function to apply to each packet instead of lambda x:x.summary()
  2577 lfilter: truth function to apply to each packet to decide whether it will be displayed"""
  2578         for i in range(len(self.res)):
  2579             if lfilter is not None:
  2580                 if not lfilter(self.res[i]):
  2581                     continue
  2582             print conf.color_theme.id(i,"%04i"),
  2583             if prn is None:
  2584                 print self._elt2sum(self.res[i])
  2585             else:
  2586                 print prn(self.res[i])
  2587     def display(self): # Deprecated. Use show()
  2588         """deprecated. is show()"""
  2589         self.show()
  2590     def show(self, *args, **kargs):
  2591         """Best way to display the packet list. Defaults to nsummary() method"""
  2592         return self.nsummary(*args, **kargs)
  2593     
  2594     def filter(self, func):
  2595         """Returns a packet list filtered by a truth function"""
  2596         return self.__class__(filter(func,self.res),
  2597                               name="filtered %s"%self.listname)
  2598     def make_table(self, *args, **kargs):
  2599         """Prints a table using a function that returs for each packet its head column value, head row value and displayed value
  2600         ex: p.make_table(lambda x:(x[IP].dst, x[TCP].dport, x[TCP].sprintf("%flags%")) """
  2601         return make_table(self.res, *args, **kargs)
  2602     def make_lined_table(self, *args, **kargs):
  2603         """Same as make_table, but print a table with lines"""
  2604         return make_lined_table(self.res, *args, **kargs)
  2605     def make_tex_table(self, *args, **kargs):
  2606         """Same as make_table, but print a table with LaTeX syntax"""
  2607         return make_tex_table(self.res, *args, **kargs)
  2608 
  2609     def plot(self, f, lfilter=None,**kargs):
  2610         """Applies a function to each packet to get a value that will be plotted with GnuPlot. A gnuplot object is returned
  2611         lfilter: a truth function that decides whether a packet must be ploted"""
  2612         g=Gnuplot.Gnuplot()
  2613         l = self.res
  2614         if lfilter is not None:
  2615             l = filter(lfilter, l)
  2616         l = map(f,l)
  2617         g.plot(Gnuplot.Data(l, **kargs))
  2618         return g
  2619 
  2620     def diffplot(self, f, delay=1, lfilter=None, **kargs):
  2621         """diffplot(f, delay=1, lfilter=None)
  2622         Applies a function to couples (l[i],l[i+delay])"""
  2623         g = Gnuplot.Gnuplot()
  2624         l = self.res
  2625         if lfilter is not None:
  2626             l = filter(lfilter, l)
  2627         l = map(f,l[:-delay],l[delay:])
  2628         g.plot(Gnuplot.Data(l, **kargs))
  2629         return g
  2630 
  2631     def multiplot(self, f, lfilter=None, **kargs):
  2632         """Uses a function that returns a label and a value for this label, then plots all the values label by label"""
  2633         g=Gnuplot.Gnuplot()
  2634         l = self.res
  2635         if lfilter is not None:
  2636             l = filter(lfilter, l)
  2637 
  2638         d={}
  2639         for e in l:
  2640             k,v = f(e)
  2641             if k in d:
  2642                 d[k].append(v)
  2643             else:
  2644                 d[k] = [v]
  2645         data=[]
  2646         for k in d:
  2647             data.append(Gnuplot.Data(d[k], title=k, **kargs))
  2648 
  2649         g.plot(*data)
  2650         return g
  2651         
  2652 
  2653     def rawhexdump(self):
  2654         """Prints an hexadecimal dump of each packet in the list"""
  2655         for p in self:
  2656             hexdump(self._elt2pkt(p))
  2657 
  2658     def hexraw(self, lfilter=None):
  2659         """Same as nsummary(), except that if a packet has a Raw layer, it will be hexdumped
  2660         lfilter: a truth function that decides whether a packet must be displayed"""
  2661         for i in range(len(self.res)):
  2662             p = self._elt2pkt(self.res[i])
  2663             if lfilter is not None and not lfilter(p):
  2664                 continue
  2665             print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2666                                 p.sprintf("%.time%"),
  2667                                 self._elt2sum(self.res[i]))
  2668             if p.haslayer(Raw):
  2669                 hexdump(p.getlayer(Raw).load)
  2670 
  2671     def hexdump(self, lfilter=None):
  2672         """Same as nsummary(), except that packets are also hexdumped
  2673         lfilter: a truth function that decides whether a packet must be displayed"""
  2674         for i in range(len(self.res)):
  2675             p = self._elt2pkt(self.res[i])
  2676             if lfilter is not None and not lfilter(p):
  2677                 continue
  2678             print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2679                                 p.sprintf("%.time%"),
  2680                                 self._elt2sum(self.res[i]))
  2681             hexdump(p)
  2682 
  2683     def padding(self, lfilter=None):
  2684         """Same as hexraw(), for Padding layer"""
  2685         for i in range(len(self.res)):
  2686             p = self._elt2pkt(self.res[i])
  2687             if p.haslayer(Padding):
  2688                 if lfilter is None or lfilter(p):
  2689                     print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2690                                         p.sprintf("%.time%"),
  2691                                         self._elt2sum(self.res[i]))
  2692                     hexdump(p.getlayer(Padding).load)
  2693 
  2694     def nzpadding(self, lfilter=None):
  2695         """Same as padding() but only non null padding"""
  2696         for i in range(len(self.res)):
  2697             p = self._elt2pkt(self.res[i])
  2698             if p.haslayer(Padding):
  2699                 pad = p.getlayer(Padding).load
  2700                 if pad == pad[0]*len(pad):
  2701                     continue
  2702                 if lfilter is None or lfilter(p):
  2703                     print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2704                                         p.sprintf("%.time%"),
  2705                                         self._elt2sum(self.res[i]))
  2706                     hexdump(p.getlayer(Padding).load)
  2707         
  2708 
  2709     def conversations(self, getsrcdst=None,**kargs):
  2710         """Graphes a conversations between sources and destinations and display it
  2711         (using graphviz and imagemagick)
  2712         getsrcdst: a function that takes an element of the list and return the source and dest
  2713                    by defaults, return source and destination IP
  2714         type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
  2715         target: filename or redirect. Defaults pipe to Imagemagick's display program
  2716         prog: which graphviz program to use"""
  2717         if getsrcdst is None:
  2718             getsrcdst = lambda x:(x[IP].src, x[IP].dst)
  2719         conv = {}
  2720         for p in self.res:
  2721             p = self._elt2pkt(p)
  2722             try:
  2723                 c = getsrcdst(p)
  2724             except:
  2725                 #XXX warning()
  2726                 continue
  2727             conv[c] = conv.get(c,0)+1
  2728         gr = 'digraph "conv" {\n'
  2729         for s,d in conv:
  2730             gr += '\t "%s" -> "%s"\n' % (s,d)
  2731         gr += "}\n"        
  2732         return do_graph(gr, **kargs)
  2733 
  2734     def afterglow(self, src=None, event=None, dst=None, **kargs):
  2735         """Experimental clone attempt of http://sourceforge.net/projects/afterglow
  2736         each datum is reduced as src -> event -> dst and the data are graphed.
  2737         by default we have IP.src -> IP.dport -> IP.dst"""
  2738         if src is None:
  2739             src = lambda x: x[IP].src
  2740         if event is None:
  2741             event = lambda x: x[IP].dport
  2742         if dst is None:
  2743             dst = lambda x: x[IP].dst
  2744         sl = {}
  2745         el = {}
  2746         dl = {}
  2747         for i in self.res:
  2748             try:
  2749                 s,e,d = src(i),event(i),dst(i)
  2750                 if s in sl:
  2751                     n,l = sl[s]
  2752                     n += 1
  2753                     if e not in l:
  2754                         l.append(e)
  2755                     sl[s] = (n,l)
  2756                 else:
  2757                     sl[s] = (1,[e])
  2758                 if e in el:
  2759                     n,l = el[e]
  2760                     n+=1
  2761                     if d not in l:
  2762                         l.append(d)
  2763                     el[e] = (n,l)
  2764                 else:
  2765                     el[e] = (1,[d])
  2766                 dl[d] = dl.get(d,0)+1
  2767             except:
  2768                 continue
  2769 
  2770         import math
  2771         def normalize(n):
  2772             return 2+math.log(n)/4.0
  2773 
  2774         def minmax(x):
  2775             m,M = min(x),max(x)
  2776             if m == M:
  2777                 m = 0
  2778             if M == 0:
  2779                 M = 1
  2780             return m,M
  2781 
  2782         mins,maxs = minmax(map(lambda (x,y): x, sl.values()))
  2783         mine,maxe = minmax(map(lambda (x,y): x, el.values()))
  2784         mind,maxd = minmax(dl.values())
  2785     
  2786         gr = 'digraph "afterglow" {\n\tedge [len=2.5];\n'
  2787 
  2788         gr += "# src nodes\n"
  2789         for s in sl:
  2790             n,l = sl[s]; n = 1+float(n-mins)/(maxs-mins)
  2791             gr += '"src.%s" [label = "%s", shape=box, fillcolor="#FF0000", style=filled, fixedsize=1, height=%.2f,width=%.2f];\n' % (`s`,`s`,n,n)
  2792         gr += "# event nodes\n"
  2793         for e in el:
  2794             n,l = el[e]; n = n = 1+float(n-mine)/(maxe-mine)
  2795             gr += '"evt.%s" [label = "%s", shape=circle, fillcolor="#00FFFF", style=filled, fixedsize=1, height=%.2f, width=%.2f];\n' % (`e`,`e`,n,n)
  2796         for d in dl:
  2797             n = dl[d]; n = n = 1+float(n-mind)/(maxd-mind)
  2798             gr += '"dst.%s" [label = "%s", shape=triangle, fillcolor="#0000ff", style=filled, fixedsize=1, height=%.2f, width=%.2f];\n' % (`d`,`d`,n,n)
  2799 
  2800         gr += "###\n"
  2801         for s in sl:
  2802             n,l = sl[s]
  2803             for e in l:
  2804                 gr += ' "src.%s" -> "evt.%s";\n' % (`s`,`e`) 
  2805         for e in el:
  2806             n,l = el[e]
  2807             for d in l:
  2808                 gr += ' "evt.%s" -> "dst.%s";\n' % (`e`,`d`) 
  2809             
  2810         gr += "}"
  2811         open("/tmp/aze","w").write(gr)
  2812         return do_graph(gr, **kargs)
  2813         
  2814 
  2815         
  2816     def timeskew_graph(self, ip, **kargs):
  2817         """Tries to graph the timeskew between the timestamps and real time for a given ip"""
  2818         res = map(lambda x: self._elt2pkt(x), self.res)
  2819         b = filter(lambda x:x.haslayer(IP) and x.getlayer(IP).src == ip and x.haslayer(TCP), res)
  2820         c = []
  2821         for p in b:
  2822             opts = p.getlayer(TCP).options
  2823             for o in opts:
  2824                 if o[0] == "Timestamp":
  2825                     c.append((p.time,o[1][0]))
  2826         if not c:
  2827             warning("No timestamps found in packet list")
  2828             return
  2829         d = map(lambda (x,y): (x%2000,((x-c[0][0])-((y-c[0][1])/1000.0))),c)
  2830         g = Gnuplot.Gnuplot()
  2831         g.plot(Gnuplot.Data(d,**kargs))
  2832         return g
  2833         
  2834     def _dump_document(self, **kargs):
  2835         d = pyx.document.document()
  2836         l = len(self.res)
  2837         for i in range(len(self.res)):
  2838             elt = self.res[i]
  2839             c = self._elt2pkt(elt).canvas_dump(**kargs)
  2840             cbb = c.bbox()
  2841             c.text(cbb.left(),cbb.top()+1,r"\font\cmssfont=cmss12\cmssfont{Frame %i/%i}" % (i,l),[pyx.text.size.LARGE])
  2842             if conf.verb >= 2:
  2843                 os.write(1,".")
  2844             d.append(pyx.document.page(c, paperformat=pyx.document.paperformat.A4,
  2845                                        margin=1*pyx.unit.t_cm,
  2846                                        fittosize=1))
  2847         return d
  2848                      
  2849                  
  2850 
  2851     def psdump(self, filename = None, **kargs):
  2852         """Creates a multipage poscript file with a psdump of every packet
  2853         filename: name of the file to write to. If empty, a temporary file is used and
  2854                   conf.prog.psreader is called"""
  2855         d = self._dump_document(**kargs)
  2856         if filename is None:
  2857             filename = "/tmp/scapy.psd.%i" % os.getpid()
  2858             d.writePSfile(filename)
  2859             os.system("%s %s.ps &" % (conf.prog.psreader,filename))
  2860         else:
  2861             d.writePSfile(filename)
  2862         print
  2863         
  2864     def pdfdump(self, filename = None, **kargs):
  2865         """Creates a PDF file with a psdump of every packet
  2866         filename: name of the file to write to. If empty, a temporary file is used and
  2867                   conf.prog.pdfreader is called"""
  2868         d = self._dump_document(**kargs)
  2869         if filename is None:
  2870             filename = "/tmp/scapy.psd.%i" % os.getpid()
  2871             d.writePDFfile(filename)
  2872             os.system("%s %s.pdf &" % (conf.prog.pdfreader,filename))
  2873         else:
  2874             d.writePDFfile(filename)
  2875         print
  2876 
  2877     def sr(self,multi=0):
  2878         """sr([multi=1]) -> (SndRcvList, PacketList)
  2879         Matches packets in the list and return ( (matched couples), (unmatched packets) )"""
  2880         remain = self.res[:]
  2881         sr = []
  2882         i = 0
  2883         while i < len(remain):
  2884             s = remain[i]
  2885             j = i
  2886             while j < len(remain)-1:
  2887                 j += 1
  2888                 r = remain[j]
  2889                 if r.answers(s):
  2890                     sr.append((s,r))
  2891                     if multi:
  2892                         remain[i]._answered=1
  2893                         remain[j]._answered=2
  2894                         continue
  2895                     del(remain[j])
  2896                     del(remain[i])
  2897                     i -= 1
  2898                     break
  2899             i += 1
  2900         if multi:
  2901             remain = filter(lambda x:not hasattr(x,"_answered"), remain)
  2902         return SndRcvList(sr),PacketList(remain)
  2903         
  2904 
  2905 
  2906         
  2907 
  2908 
  2909 class Dot11PacketList(PacketList):
  2910     def __init__(self, res=None, name="Dot11List", stats=None):
  2911         if stats is None:
  2912             stats = [Dot11WEP, Dot11Beacon, UDP, ICMP, TCP]
  2913 
  2914         PacketList.__init__(self, res, name, stats)
  2915     def toEthernet(self):
  2916         data = map(lambda x:x.getlayer(Dot11), filter(lambda x : x.haslayer(Dot11) and x.type == 2, self.res))
  2917         r2 = []
  2918         for p in data:
  2919             q = p.copy()
  2920             q.unwep()
  2921             r2.append(Ether()/q.payload.payload.payload) #Dot11/LLC/SNAP/IP
  2922         return PacketList(r2,name="Ether from %s"%self.listname)
  2923         
  2924         
  2925 
  2926 class SndRcvList(PacketList):
  2927     def __init__(self, res=None, name="Results", stats=None):
  2928         PacketList.__init__(self, res, name, stats)
  2929     def _elt2pkt(self, elt):
  2930         return elt[1]
  2931     def _elt2sum(self, elt):
  2932         return "%s ==> %s" % (elt[0].summary(),elt[1].summary()) 
  2933 
  2934 
  2935 class ARPingResult(SndRcvList):
  2936     def __init__(self, res=None, name="ARPing", stats=None):
  2937         PacketList.__init__(self, res, name, stats)
  2938 
  2939     def show(self):
  2940         for s,r in self.res:
  2941             print r.sprintf("%Ether.src% %ARP.psrc%")
  2942 
  2943 
  2944 class AS_resolver:
  2945     server = None
  2946     options = "-k" 
  2947     def __init__(self, server=None, port=43, options=None):
  2948         if server is not None:
  2949             self.server = server
  2950         self.port = port
  2951         if options is not None:
  2952             self.options = options
  2953         
  2954     def _start(self):
  2955         self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  2956         self.s.connect((self.server,self.port))
  2957         if self.options:
  2958             self.s.send(self.options+"\n")
  2959             self.s.recv(8192)
  2960     def _stop(self):
  2961         self.s.close()
  2962         
  2963     def _parse_whois(self, txt):
  2964         asn,desc = None,""
  2965         for l in txt.splitlines():
  2966             if not asn and l.startswith("origin:"):
  2967                 asn = l[7:].strip()
  2968             if l.startswith("descr:"):
  2969                 if desc:
  2970                     desc += r"\n"
  2971                 desc += l[6:].strip()
  2972             if asn is not None and desc:
  2973                 break
  2974         return asn,desc.strip()
  2975 
  2976     def _resolve_one(self, ip):
  2977         self.s.send("%s\n" % ip)
  2978         x = ""
  2979         while not ("%" in x  or "source" in x):
  2980             x += self.s.recv(8192)
  2981         asn, desc = self._parse_whois(x)
  2982         return ip,asn,desc
  2983     def resolve(self, *ips):
  2984         self._start()
  2985         ret = []
  2986         for ip in ips:
  2987             ip,asn,desc = self._resolve_one(ip)
  2988             if asn is not None:
  2989                 ret.append((ip,asn,desc))
  2990         self._stop()
  2991         return ret
  2992 
  2993 class AS_resolver_riswhois(AS_resolver):
  2994     server = "riswhois.ripe.net"
  2995     options = "-k -M -1"
  2996 
  2997 
  2998 class AS_resolver_radb(AS_resolver):
  2999     server = "whois.ra.net"
  3000     options = "-k -M"
  3001     
  3002 
  3003 class AS_resolver_cymru(AS_resolver):
  3004     server = "whois.cymru.com"
  3005     options = None
  3006     def resolve(self, *ips):
  3007         ASNlist = []
  3008         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  3009         s.connect((self.server,self.port))
  3010         s.send("begin\r\n"+"\r\n".join(ips)+"\r\nend\r\n")
  3011         r = ""
  3012         while 1:
  3013             l = s.recv(8192)
  3014             if l == "":
  3015                 break
  3016             r += l
  3017         s.close()
  3018         for l in r.splitlines()[1:]:
  3019             if "|" not in l:
  3020                 continue
  3021             asn,ip,desc = map(str.strip, l.split("|"))
  3022             if asn == "NA":
  3023                 continue
  3024             asn = int(asn)
  3025             ASNlist.append((ip,asn,desc))
  3026         return ASNlist
  3027 
  3028 class AS_resolver_multi(AS_resolver):
  3029     resolvers_list = ( AS_resolver_cymru(),AS_resolver_riswhois(),AS_resolver_radb() )
  3030     def __init__(self, *reslist):
  3031         if reslist:
  3032             self.resolvers_list = reslist
  3033     def resolve(self, *ips):
  3034         todo = ips
  3035         ret = []
  3036         for ASres in self.resolvers_list:
  3037             res = ASres.resolve(*todo)
  3038             resolved = [ ip for ip,asn,desc in res ]
  3039             todo = [ ip for ip in todo if ip not in resolved ]
  3040             ret += res
  3041         return ret
  3042     
  3043     
  3044 
  3045 class TracerouteResult(SndRcvList):
  3046     def __init__(self, res=None, name="Traceroute", stats=None):
  3047         PacketList.__init__(self, res, name, stats)
  3048         self.graphdef = None
  3049         self.graphASres = 0
  3050         self.padding = 0
  3051         self.hloc = None
  3052         self.nloc = None
  3053 
  3054     def show(self):
  3055         return self.make_table(lambda (s,r): (s.sprintf("%IP.dst%:{TCP:tcp%ir,TCP.dport%}{UDP:udp%ir,UDP.dport%}{ICMP:ICMP}"),
  3056                                               s.ttl,
  3057                                               r.sprintf("%-15s,IP.src% {TCP:%TCP.flags%}{ICMP:%ir,ICMP.type%}")))
  3058 
  3059 
  3060     def get_trace(self):
  3061         trace = {}
  3062         for s,r in self.res:
  3063             if IP not in s:
  3064                 continue
  3065             d = s[IP].dst
  3066             if d not in trace:
  3067                 trace[d] = {}
  3068             trace[d][s[IP].ttl] = r[IP].src, ICMP not in r
  3069         for k in trace.values():
  3070             m = filter(lambda x:k[x][1], k.keys())
  3071             if not m:
  3072                 continue
  3073             m = min(m)
  3074             for l in k.keys():
  3075                 if l > m:
  3076                     del(k[l])
  3077         return trace
  3078 
  3079     def trace3D(self):
  3080         """Give a 3D representation of the traceroute.
  3081         right button: rotate the scene
  3082         middle button: zoom
  3083         left button: move the scene
  3084         left button on a ball: toggle IP displaying
  3085         ctrl-left button on a ball: scan ports 21,22,23,25,80 and 443 and display the result"""
  3086         trace = self.get_trace()
  3087         import visual
  3088 
  3089         class IPsphere(visual.sphere):
  3090             def __init__(self, ip, **kargs):
  3091                 visual.sphere.__init__(self, **kargs)
  3092                 self.ip=ip
  3093                 self.label=None
  3094                 self.setlabel(self.ip)
  3095             def setlabel(self, txt,visible=None):
  3096                 if self.label is not None:
  3097                     if visible is None:
  3098                         visible = self.label.visible
  3099                     self.label.visible = 0
  3100                 elif visible is None:
  3101                     visible=0
  3102                 self.label=visual.label(text=txt, pos=self.pos, space=self.radius, xoffset=10, yoffset=20, visible=visible)
  3103             def action(self):
  3104                 self.label.visible ^= 1
  3105 
  3106         visual.scene = visual.display()
  3107         visual.scene.exit_on_close(0)
  3108         start = visual.box()
  3109         rings={}
  3110         tr3d = {}
  3111         for i in trace:
  3112             tr = trace[i]
  3113             tr3d[i] = []
  3114             ttl = tr.keys()
  3115             for t in range(1,max(ttl)+1):
  3116                 if t not in rings:
  3117                     rings[t] = []
  3118                 if t in tr:
  3119                     if tr[t] not in rings[t]:
  3120                         rings[t].append(tr[t])
  3121                     tr3d[i].append(rings[t].index(tr[t]))
  3122                 else:
  3123                     rings[t].append(("unk",-1))
  3124                     tr3d[i].append(len(rings[t])-1)
  3125         for t in rings:
  3126             r = rings[t]
  3127             l = len(r)
  3128             for i in range(l):
  3129                 if r[i][1] == -1:
  3130                     col = (0.75,0.75,0.75)
  3131                 elif r[i][1]:
  3132                     col = visual.color.green
  3133                 else:
  3134                     col = visual.color.blue
  3135                 
  3136                 s = IPsphere(pos=((l-1)*visual.cos(2*i*visual.pi/l),(l-1)*visual.sin(2*i*visual.pi/l),2*t),
  3137                              ip = r[i][0],
  3138                              color = col)
  3139                 for trlst in tr3d.values():
  3140                     if t <= len(trlst):
  3141                         if trlst[t-1] == i:
  3142                             trlst[t-1] = s
  3143         forecol = colgen(0.625, 0.4375, 0.25, 0.125)
  3144         for trlst in tr3d.values():
  3145             col = forecol.next()
  3146             start = (0,0,0)
  3147             for ip in trlst:
  3148                 visual.cylinder(pos=start,axis=ip.pos-start,color=col,radius=0.2)
  3149                 start = ip.pos
  3150         
  3151         movcenter=None
  3152         while 1:
  3153             if visual.scene.kb.keys:
  3154                 k = visual.scene.kb.getkey()
  3155                 if k == "esc":
  3156                     break
  3157             if visual.scene.mouse.events:
  3158                 ev = visual.scene.mouse.getevent()
  3159                 if ev.press == "left":
  3160                     o = ev.pick
  3161                     if o:
  3162                         if ev.ctrl:
  3163                             if o.ip == "unk":
  3164                                 continue
  3165                             savcolor = o.color
  3166                             o.color = (1,0,0)
  3167                             a,b=sr(IP(dst=o.ip)/TCP(dport=[21,22,23,25,80,443]),timeout=2)
  3168                             o.color = savcolor
  3169                             if len(a) == 0:
  3170                                 txt = "%s:\nno results" % o.ip
  3171                             else:
  3172                                 txt = "%s:\n" % o.ip
  3173                                 for s,r in a:
  3174                                     txt += r.sprintf("{TCP:%IP.src%:%TCP.sport% %TCP.flags%}{TCPerror:%IPerror.dst%:%TCPerror.dport% %IP.src% %ir,ICMP.type%}\n")
  3175                             o.setlabel(txt, visible=1)
  3176                         else:
  3177                             if hasattr(o, "action"):
  3178                                 o.action()
  3179                 elif ev.drag == "left":
  3180                     movcenter = ev.pos
  3181                 elif ev.drop == "left":
  3182                     movcenter = None
  3183             if movcenter:
  3184                 visual.scene.center -= visual.scene.mouse.pos-movcenter
  3185                 movcenter = visual.scene.mouse.pos
  3186                 
  3187                 
  3188     def world_trace(self):
  3189         ips = {}
  3190         rt = {}
  3191         ports_done = {}
  3192         for s,r in self.res:
  3193             ips[r.src] = None
  3194             if s.haslayer(TCP) or s.haslayer(UDP):
  3195                 trace_id = (s.src,s.dst,s.proto,s.dport)
  3196             elif s.haslayer(ICMP):
  3197                 trace_id = (s.src,s.dst,s.proto,s.type)
  3198             else:
  3199                 trace_id = (s.src,s.dst,s.proto,0)
  3200             trace = rt.get(trace_id,{})
  3201             if not r.haslayer(ICMP) or r.type != 11:
  3202                 if ports_done.has_key(trace_id):
  3203                     continue
  3204                 ports_done[trace_id] = None
  3205             trace[s.ttl] = r.src
  3206             rt[trace_id] = trace
  3207 
  3208         trt = {}
  3209         for trace_id in rt:
  3210             trace = rt[trace_id]
  3211             loctrace = []
  3212             for i in range(max(trace.keys())):
  3213                 ip = trace.get(i,None)
  3214                 if ip is None:
  3215                     continue
  3216                 loc = locate_ip(ip)
  3217                 if loc is None:
  3218                     continue
  3219 #                loctrace.append((ip,loc)) # no labels yet
  3220                 loctrace.append(loc)
  3221             if loctrace:
  3222                 trt[trace_id] = loctrace
  3223 
  3224         tr = map(lambda x: Gnuplot.Data(x,with="lines"), trt.values())
  3225         g = Gnuplot.Gnuplot()
  3226         world = Gnuplot.File(conf.gnuplot_world,with="lines")
  3227         g.plot(world,*tr)
  3228         return g
  3229 
  3230     def make_graph(self,ASres=None,padding=0):
  3231         if ASres is None:
  3232             ASres = conf.AS_resolver
  3233         self.graphASres = ASres
  3234         self.graphpadding = padding
  3235         ips = {}
  3236         rt = {}
  3237         ports = {}
  3238         ports_done = {}
  3239         for s,r in self.res:
  3240             r = r[IP] or r[IPv6] or r
  3241             s = s[IP] or s[IPv6] or s
  3242             ips[r.src] = None
  3243             if TCP in s:
  3244                 trace_id = (s.src,s.dst,6,s.dport)
  3245             elif UDP in s:
  3246                 trace_id = (s.src,s.dst,17,s.dport)
  3247             elif ICMP in s:
  3248                 trace_id = (s.src,s.dst,1,s.type)
  3249             else:
  3250                 trace_id = (s.src,s.dst,s.proto,0)
  3251             trace = rt.get(trace_id,{})
  3252             ttl = IPv6 in s and s.hlim or s.ttl
  3253             if not (ICMP in r and r[ICMP].type == 11) and not (IPv6 in r and ICMPv6TimeExceeded in r):
  3254                 if trace_id in ports_done:
  3255                     continue
  3256                 ports_done[trace_id] = None
  3257                 p = ports.get(r.src,[])
  3258                 if TCP in r:
  3259                     p.append(r.sprintf("<T%ir,TCP.sport%> %TCP.sport% %TCP.flags%"))
  3260                     trace[ttl] = r.sprintf('"%r,src%":T%ir,TCP.sport%')
  3261                 elif UDP in r:
  3262                     p.append(r.sprintf("<U%ir,UDP.sport%> %UDP.sport%"))
  3263                     trace[ttl] = r.sprintf('"%r,src%":U%ir,UDP.sport%')
  3264                 elif ICMP in r:
  3265                     p.append(r.sprintf("<I%ir,ICMP.type%> ICMP %ICMP.type%"))
  3266                     trace[ttl] = r.sprintf('"%r,src%":I%ir,ICMP.type%')
  3267                 else:
  3268                     p.append(r.sprintf("{IP:<P%ir,proto%> IP %proto%}{IPv6:<P%ir,nh%> IPv6 %nh%}"))
  3269                     trace[ttl] = r.sprintf('"%r,src%":{IP:P%ir,proto%}{IPv6:P%ir,nh%}')
  3270                 ports[r.src] = p
  3271             else:
  3272                 trace[ttl] = r.sprintf('"%r,src%"')
  3273             rt[trace_id] = trace
  3274     
  3275         # Fill holes with unk%i nodes
  3276         unknown_label = incremental_label("unk%i")
  3277         blackholes = []
  3278         bhip = {}
  3279         for rtk in rt:
  3280             trace = rt[rtk]
  3281             k = trace.keys()
  3282             for n in range(min(k), max(k)):
  3283                 if not trace.has_key(n):
  3284                     trace[n] = unknown_label.next()
  3285             if not ports_done.has_key(rtk):
  3286                 if rtk[2] == 1: #ICMP
  3287                     bh = "%s %i/icmp" % (rtk[1],rtk[3])
  3288                 elif rtk[2] == 6: #TCP
  3289                     bh = "%s %i/tcp" % (rtk[1],rtk[3])
  3290                 elif rtk[2] == 17: #UDP                    
  3291                     bh = '%s %i/udp' % (rtk[1],rtk[3])
  3292                 else:
  3293                     bh = '%s %i/proto' % (rtk[1],rtk[2]) 
  3294                 ips[bh] = None
  3295                 bhip[rtk[1]] = bh
  3296                 bh = '"%s"' % bh
  3297                 trace[max(k)+1] = bh
  3298                 blackholes.append(bh)
  3299     
  3300         # Find AS numbers
  3301         ASN_query_list = dict.fromkeys(map(lambda x:x.rsplit(" ",1)[0],ips)).keys()
  3302         if ASres is None:            
  3303             ASNlist = []
  3304         else:
  3305             ASNlist = ASres.resolve(*ASN_query_list)            
  3306     
  3307         ASNs = {}
  3308         ASDs = {}
  3309         for ip,asn,desc, in ASNlist:
  3310             if asn is None:
  3311                 continue
  3312             iplist = ASNs.get(asn,[])
  3313             if ip in bhip:
  3314                 if ip in ports:
  3315                     iplist.append(ip)
  3316                 iplist.append(bhip[ip])
  3317             else:
  3318                 iplist.append(ip)
  3319             ASNs[asn] = iplist
  3320             ASDs[asn] = desc
  3321     
  3322     
  3323         backcolorlist=colgen("60","86","ba","ff")
  3324         forecolorlist=colgen("a0","70","40","20")
  3325     
  3326         s = "digraph trace {\n"
  3327     
  3328         s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n"
  3329     
  3330         s += "\n#ASN clustering\n"
  3331         for asn in ASNs:
  3332             s += '\tsubgraph cluster_%s {\n' % asn
  3333             col = backcolorlist.next()
  3334             s += '\t\tcolor="#%s%s%s";' % col
  3335             s += '\t\tnode [fillcolor="#%s%s%s",style=filled];' % col
  3336             s += '\t\tfontsize = 10;'
  3337             s += '\t\tlabel = "%s\\n[%s]"\n' % (asn,ASDs[asn])
  3338             for ip in ASNs[asn]:
  3339     
  3340                 s += '\t\t"%s";\n'%ip
  3341             s += "\t}\n"
  3342     
  3343     
  3344     
  3345     
  3346         s += "#endpoints\n"
  3347         for p in ports:
  3348             s += '\t"%s" [shape=record,color=black,fillcolor=green,style=filled,label="%s|%s"];\n' % (p,p,"|".join(ports[p]))
  3349     
  3350         s += "\n#Blackholes\n"
  3351         for bh in blackholes:
  3352             s += '\t%s [shape=octagon,color=black,fillcolor=red,style=filled];\n' % bh
  3353 
  3354         if padding:
  3355             s += "\n#Padding\n"
  3356             pad={}
  3357             for snd,rcv in self.res:
  3358                 if rcv.src not in ports and rcv.haslayer(Padding):
  3359                     p = rcv.getlayer(Padding).load
  3360                     if p != "\x00"*len(p):
  3361                         pad[rcv.src]=None
  3362             for rcv in pad:
  3363                 s += '\t"%s" [shape=triangle,color=black,fillcolor=red,style=filled];\n' % rcv
  3364     
  3365     
  3366             
  3367         s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n"
  3368     
  3369     
  3370         for rtk in rt:
  3371             s += "#---[%s\n" % `rtk`
  3372             s += '\t\tedge [color="#%s%s%s"];\n' % forecolorlist.next()
  3373             trace = rt[rtk]
  3374             k = trace.keys()
  3375             for n in range(min(k), max(k)):
  3376                 s += '\t%s ->\n' % trace[n]
  3377             s += '\t%s;\n' % trace[max(k)]
  3378     
  3379         s += "}\n";
  3380         self.graphdef = s
  3381     
  3382     def graph(self, ASres=None, padding=0, **kargs):
  3383         """x.graph(ASres=conf.AS_resolver, other args):
  3384         ASres=None          : no AS resolver => no clustering
  3385         ASres=AS_resolver() : default whois AS resolver (riswhois.ripe.net)
  3386         ASres=AS_resolver_cymru(): use whois.cymru.com whois database
  3387         ASres=AS_resolver(server="whois.ra.net")
  3388         type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
  3389         target: filename or redirect. Defaults pipe to Imagemagick's display program
  3390         prog: which graphviz program to use"""
  3391         if ASres is None:
  3392             ASres = conf.AS_resolver
  3393         if (self.graphdef is None or
  3394             self.graphASres != ASres or
  3395             self.graphpadding != padding):
  3396             self.make_graph(ASres,padding)
  3397 
  3398         return do_graph(self.graphdef, **kargs)
  3399 
  3400 
  3401         
  3402     
  3403 ############
  3404 ## Fields ##
  3405 ############
  3406 
  3407 class Field:
  3408     """For more informations on how this work, please refer to
  3409        http://www.secdev.org/projects/scapy/files/scapydoc.pdf
  3410        chapter ``Adding a New Field''"""
  3411     islist=0
  3412     holds_packets=0
  3413     def __init__(self, name, default, fmt="H"):
  3414         self.name = name
  3415         if fmt[0] in "@=<>!":
  3416             self.fmt = fmt
  3417         else:
  3418             self.fmt = "!"+fmt
  3419         self.default = self.any2i(None,default)
  3420         self.sz = struct.calcsize(self.fmt)
  3421         self.owners = []
  3422 
  3423     def register_owner(self, cls):
  3424         self.owners.append(cls)
  3425 
  3426     def i2len(self, pkt, x):
  3427         """Convert internal value to a length usable by a FieldLenField"""
  3428         return self.sz
  3429     def i2count(self, pkt, x):
  3430         """Convert internal value to a number of elements usable by a FieldLenField.
  3431         Always 1 except for list fields"""
  3432         return 1
  3433     def h2i(self, pkt, x):
  3434         """Convert human value to internal value"""
  3435         return x
  3436     def i2h(self, pkt, x):
  3437         """Convert internal value to human value"""
  3438         return x
  3439     def m2i(self, pkt, x):
  3440         """Convert machine value to internal value"""
  3441         return x
  3442     def i2m(self, pkt, x):
  3443         """Convert internal value to machine value"""
  3444         if x is None:
  3445             x = 0
  3446         return x
  3447     def any2i(self, pkt, x):
  3448         """Try to understand the most input values possible and make an internal value from them"""
  3449         return self.h2i(pkt, x)
  3450     def i2repr(self, pkt, x):
  3451         """Convert internal value to a nice representation"""
  3452         if x is None:
  3453             x = 0
  3454         return repr(self.i2h(pkt,x))
  3455     def addfield(self, pkt, s, val):
  3456         """Add an internal value  to a string"""
  3457         return s+struct.pack(self.fmt, self.i2m(pkt,val))
  3458     def getfield(self, pkt, s):
  3459         """Extract an internal value from a string"""
  3460         return  s[self.sz:], self.m2i(pkt, struct.unpack(self.fmt, s[:self.sz])[0])
  3461     def do_copy(self, x):
  3462         if hasattr(x, "copy"):
  3463             return x.copy()
  3464         if type(x) is list:
  3465             x = x[:]
  3466             for i in xrange(len(x)):
  3467                 if isinstance(x[i], Packet):
  3468                     x[i] = x[i].copy()
  3469         return x
  3470     def __repr__(self):
  3471         return "<Field (%s).%s>" % (",".join(x.__name__ for x in self.owners),self.name)
  3472     def copy(self):
  3473         return copy.deepcopy(self)
  3474     def randval(self):
  3475         """Return a volatile object whose value is both random and suitable for this field"""
  3476         fmtt = self.fmt[-1]
  3477         if fmtt in "BHIQ":
  3478             return {"B":RandByte,"H":RandShort,"I":RandInt, "Q":RandLong}[fmtt]()
  3479         elif fmtt == "s":
  3480             if self.fmt[0] in "0123456789":
  3481                 l = int(self.fmt[:-1])
  3482             else:
  3483                 l = int(self.fmt[1:-1])
  3484             return RandBin(l)
  3485         else:
  3486             warning("no random class for [%s] (fmt=%s)." % (self.name, self.fmt))
  3487             
  3488 
  3489 
  3490 
  3491 class Emph:
  3492     fld = ""
  3493     def __init__(self, fld):
  3494         self.fld = fld
  3495     def __getattr__(self, attr):
  3496         return getattr(self.fld,attr)
  3497     def __hash__(self):
  3498         return hash(self.fld)
  3499     def __eq__(self, other):
  3500         return self.fld == other
  3501     
  3502 
  3503 class ActionField:
  3504     _fld = None
  3505     def __init__(self, fld, action_method, **kargs):
  3506         self._fld = fld
  3507         self._action_method = action_method
  3508         self._privdata = kargs
  3509     def any2i(self, pkt, val):
  3510         getattr(pkt, self._action_method)(val, self._fld, **self._privdata)
  3511         return getattr(self._fld, "any2i")(pkt, val)
  3512     def __getattr__(self, attr):
  3513         return getattr(self._fld,attr)
  3514 
  3515 
  3516 class ConditionalField:
  3517     fld = None
  3518     def __init__(self, fld, cond):
  3519         self.fld = fld
  3520         self.cond = cond
  3521     def _evalcond(self,pkt):
  3522         return self.cond(pkt)
  3523         
  3524     def getfield(self, pkt, s):
  3525         if self._evalcond(pkt):
  3526             return self.fld.getfield(pkt,s)
  3527         else:
  3528             return s,None
  3529         
  3530     def addfield(self, pkt, s, val):
  3531         if self._evalcond(pkt):
  3532             return self.fld.addfield(pkt,s,val)
  3533         else:
  3534             return s
  3535     def __getattr__(self, attr):
  3536         return getattr(self.fld,attr)
  3537         
  3538 
  3539 class PadField:
  3540     """Add bytes after the proxified field so that it ends at the specified
  3541        alignment from its begining"""
  3542     _fld = None
  3543     def __init__(self, fld, align, padwith=None):
  3544         self._fld = fld
  3545         self._align = align
  3546         self._padwith = padwith or ""
  3547 
  3548     def addfield(self, pkt, s, val):
  3549         sval = self._fld.addfield(pkt, "", val)
  3550         return s+sval+struct.pack("%is" % (-len(sval)%self._align), self._padwith)
  3551     
  3552     def __getattr__(self, attr):
  3553         return getattr(self._fld,attr)
  3554         
  3555 
  3556 class MACField(Field):
  3557     def __init__(self, name, default):
  3558         Field.__init__(self, name, default, "6s")
  3559     def i2m(self, pkt, x):
  3560         if x is None:
  3561             return "\0\0\0\0\0\0"
  3562         return mac2str(x)
  3563     def m2i(self, pkt, x):
  3564         return str2mac(x)
  3565     def any2i(self, pkt, x):
  3566         if type(x) is str and len(x) is 6:
  3567             x = self.m2i(pkt, x)
  3568         return x
  3569     def i2repr(self, pkt, x):
  3570         x = self.i2h(pkt, x)
  3571         if self in conf.resolve:
  3572             x = conf.manufdb._resolve_MAC(x)
  3573         return x
  3574     def randval(self):
  3575         return RandMAC()
  3576 
  3577 class DestMACField(MACField):
  3578     def __init__(self, name):
  3579         MACField.__init__(self, name, None)
  3580     def i2h(self, pkt, x):
  3581         if x is None:
  3582             dstip = None
  3583             if isinstance(pkt.payload, IPv6):
  3584                 dstip = pkt.payload.dst            
  3585             elif isinstance(pkt.payload, IP):
  3586                 dstip = pkt.payload.dst
  3587             elif isinstance(pkt.payload, ARP):
  3588                 dstip = pkt.payload.pdst
  3589             if isinstance(dstip, Gen):
  3590                 dstip = dstip.__iter__().next()
  3591             if dstip is not None:
  3592                 if isinstance(pkt.payload, IPv6):
  3593                     x = getmacbyip6(dstip, chainCC=1)
  3594                 else:    
  3595                     x = getmacbyip(dstip, chainCC=1)
  3596             if x is None:
  3597                 x = "ff:ff:ff:ff:ff:ff"
  3598                 warning("Mac address to reach %s not found\n"%dstip)
  3599         return MACField.i2h(self, pkt, x)
  3600     def i2m(self, pkt, x):
  3601         return MACField.i2m(self, pkt, self.i2h(pkt, x))
  3602         
  3603 class SourceMACField(MACField):
  3604     def __init__(self, name):
  3605         MACField.__init__(self, name, None)
  3606     def i2h(self, pkt, x):
  3607         if x is None:
  3608             dstip = None
  3609             if isinstance(pkt.payload, IPv6):
  3610                 dstip = pkt.payload.dst
  3611             elif isinstance(pkt.payload, IP):
  3612                 dstip = pkt.payload.dst
  3613             elif isinstance(pkt.payload, ARP):
  3614                 dstip = pkt.payload.pdst
  3615             if isinstance(dstip, Gen):
  3616                 dstip = dstip.__iter__().next()
  3617             if dstip is not None:
  3618                 if isinstance(pkt.payload, IPv6):
  3619                     iff,a,nh = conf.route6.route(dstip)
  3620                 else:
  3621                     iff,a,gw = conf.route.route(dstip)
  3622                 try:
  3623                     x = get_if_hwaddr(iff)
  3624                 except:
  3625                     pass
  3626                 if x is None:
  3627                     x = "00:00:00:00:00:00"
  3628         return MACField.i2h(self, pkt, x)
  3629     def i2m(self, pkt, x):
  3630         return MACField.i2m(self, pkt, self.i2h(pkt, x))
  3631         
  3632 class ARPSourceMACField(MACField):
  3633     def __init__(self, name):
  3634         MACField.__init__(self, name, None)
  3635     def i2h(self, pkt, x):
  3636         if x is None:
  3637             dstip = pkt.pdst
  3638             if isinstance(dstip, Gen):
  3639                 dstip = dstip.__iter__().next()
  3640             if dstip is not None:
  3641                 iff,a,gw = conf.route.route(dstip)
  3642                 try:
  3643                     x = get_if_hwaddr(iff)
  3644                 except:
  3645                     pass
  3646                 if x is None:
  3647                     x = "00:00:00:00:00:00"
  3648         return MACField.i2h(self, pkt, x)
  3649     def i2m(self, pkt, x):
  3650         return MACField.i2m(self, pkt, self.i2h(pkt, x))
  3651 
  3652 class Dot11AddrMACField(MACField):
  3653     def is_applicable(self, pkt):
  3654         return 1
  3655     def addfield(self, pkt, s, val):
  3656         if self.is_applicable(pkt):
  3657             return MACField.addfield(self, pkt, s, val)
  3658         else:
  3659             return s        
  3660     def getfield(self, pkt, s):
  3661         if self.is_applicable(pkt):
  3662             return MACField.getfield(self, pkt, s)
  3663         else:
  3664             return s,None
  3665 
  3666 class Dot11Addr2MACField(Dot11AddrMACField):
  3667     def is_applicable(self, pkt):
  3668         if pkt.type == 1:
  3669             return pkt.subtype in [ 0xb, 0xa, 0xe, 0xf] # RTS, PS-Poll, CF-End, CF-End+CF-Ack
  3670         return 1
  3671 
  3672 class Dot11Addr3MACField(Dot11AddrMACField):
  3673     def is_applicable(self, pkt):
  3674         if pkt.type in [0,2]:
  3675             return 1
  3676         return 0
  3677 
  3678 class Dot11Addr4MACField(Dot11AddrMACField):
  3679     def is_applicable(self, pkt):
  3680         if pkt.type == 2:
  3681             if pkt.FCfield & 0x3 == 0x3: # To-DS and From-DS are set
  3682                 return 1
  3683         return 0
  3684     
  3685 class IPField(Field):
  3686     def __init__(self, name, default):
  3687         Field.__init__(self, name, default, "4s")
  3688     def h2i(self, pkt, x):
  3689         if type(x) is str:
  3690             try:
  3691                 inet_aton(x)
  3692             except socket.error:
  3693                 x = Net(x)
  3694         elif type(x) is list:
  3695             x = [self.h2i(pkt, n) for n in x] 
  3696         return x
  3697     def resolve(self, x):
  3698         if self in conf.resolve:
  3699             try:
  3700                 ret = socket.gethostbyaddr(x)[0]
  3701             except:
  3702                 pass
  3703             else:
  3704                 if ret:
  3705                     return ret
  3706         return x
  3707     def i2m(self, pkt, x):
  3708         return inet_aton(x)
  3709     def m2i(self, pkt, x):
  3710         return inet_ntoa(x)
  3711     def any2i(self, pkt, x):
  3712         return self.h2i(pkt,x)
  3713     def i2repr(self, pkt, x):
  3714         return self.resolve(self.i2h(pkt, x))
  3715     def randval(self):
  3716         return RandIP()
  3717 
  3718 class SourceIPField(IPField):
  3719     def __init__(self, name, dstname):
  3720         IPField.__init__(self, name, None)
  3721         self.dstname = dstname
  3722     def i2m(self, pkt, x):
  3723         if x is None:
  3724             iff,x,gw = conf.route.route(getattr(pkt,self.dstname))
  3725         return IPField.i2m(self, pkt, x)
  3726     def i2h(self, pkt, x):
  3727         if x is None:
  3728             dst=getattr(pkt,self.dstname)
  3729             if isinstance(dst,Gen):
  3730                 r = map(conf.route.route, dst)
  3731                 r.sort()
  3732                 if r[0] == r[-1]:
  3733                     x=r[0][1]
  3734                 else:
  3735                     warning("More than one possible route for %s"%repr(dst))
  3736                     return None
  3737             else:
  3738                 iff,x,gw = conf.route.route(dst)
  3739         return IPField.i2h(self, pkt, x)
  3740 
  3741     
  3742 
  3743 
  3744 class ByteField(Field):
  3745     def __init__(self, name, default):
  3746         Field.__init__(self, name, default, "B")
  3747         
  3748 class XByteField(ByteField):
  3749     def i2repr(self, pkt, x):
  3750         if x is None:
  3751             x = 0
  3752         return lhex(self.i2h(pkt, x))
  3753 
  3754 class X3BytesField(XByteField):
  3755     def __init__(self, name, default):
  3756         Field.__init__(self, name, default, "!I")
  3757     def addfield(self, pkt, s, val):
  3758         return s+struct.pack(self.fmt, self.i2m(pkt,val))[1:4]
  3759     def getfield(self, pkt, s):
  3760         return  s[3:], self.m2i(pkt, struct.unpack(self.fmt, "\x00"+s[:3])[0])
  3761 
  3762 
  3763 class ShortField(Field):
  3764     def __init__(self, name, default):
  3765         Field.__init__(self, name, default, "H")
  3766 
  3767 class LEShortField(Field):
  3768     def __init__(self, name, default):
  3769         Field.__init__(self, name, default, "<H")
  3770 
  3771 class XShortField(ShortField):
  3772     def i2repr(self, pkt, x):
  3773         if x is None:
  3774             x = 0
  3775         return lhex(self.i2h(pkt, x))
  3776 
  3777 
  3778 class IntField(Field):
  3779     def __init__(self, name, default):
  3780         Field.__init__(self, name, default, "I")
  3781 
  3782 class SignedIntField(Field):
  3783     def __init__(self, name, default):
  3784         Field.__init__(self, name, default, "i")
  3785     def randval(self):
  3786         return RandSInt()
  3787 
  3788 class LEIntField(Field):
  3789     def __init__(self, name, default):
  3790         Field.__init__(self, name, default, "<I")
  3791 
  3792 class LESignedIntField(Field):
  3793     def __init__(self, name, default):
  3794         Field.__init__(self, name, default, "<i")
  3795     def randval(self):
  3796         return RandSInt()
  3797 
  3798 class XIntField(IntField):
  3799     def i2repr(self, pkt, x):
  3800         if x is None:
  3801             x = 0
  3802         return lhex(self.i2h(pkt, x))
  3803 
  3804 
  3805 class LongField(Field):
  3806     def __init__(self, name, default):
  3807         Field.__init__(self, name, default, "Q")
  3808 
  3809 class XLongField(LongField):
  3810     def i2repr(self, pkt, x):
  3811         if x is None:
  3812             x = 0
  3813         return lhex(self.i2h(pkt, x))
  3814 
  3815 class IEEEFloatField(Field):
  3816     def __init__(self, name, default):
  3817         Field.__init__(self, name, default, "f")
  3818 
  3819 class IEEEDoubleField(Field):
  3820     def __init__(self, name, default):
  3821         Field.__init__(self, name, default, "d")
  3822 
  3823 
  3824 def FIELD_LENGTH_MANAGEMENT_DEPRECATION(x):
  3825     try:
  3826         for tb in traceback.extract_stack()+[("??",-1,None,"")]:
  3827             f,l,_,line = tb
  3828             if line.startswith("fields_desc"):
  3829                 break
  3830     except:
  3831         f,l="??",-1
  3832     log_loading.warning("Deprecated use of %s (%s l. %i). See http://trac.secdev.org/scapy/wiki/LengthFields" % (x,f,l))
  3833 
  3834 class StrField(Field):
  3835     def __init__(self, name, default, fmt="H", remain=0, shift=0):
  3836         Field.__init__(self,name,default,fmt)
  3837         self.remain = remain        
  3838         self.shift = shift
  3839         if shift != 0:
  3840             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  3841     def i2len(self, pkt, i):
  3842         return len(i)+self.shift
  3843     def i2m(self, pkt, x):
  3844         if x is None:
  3845             x = ""
  3846         elif type(x) is not str:
  3847             x=str(x)
  3848         return x
  3849     def addfield(self, pkt, s, val):
  3850         return s+self.i2m(pkt, val)
  3851     def getfield(self, pkt, s):
  3852         if self.remain == 0:
  3853             return "",self.m2i(pkt, s)
  3854         else:
  3855             return s[-self.remain:],self.m2i(pkt, s[:-self.remain])
  3856     def randval(self):
  3857         return RandBin(RandNum(0,1200))
  3858 
  3859 class PacketField(StrField):
  3860     holds_packets=1
  3861     def __init__(self, name, default, cls, remain=0, shift=0):
  3862         StrField.__init__(self, name, default, remain=remain, shift=shift)
  3863         self.cls = cls
  3864     def i2m(self, pkt, i):
  3865         return str(i)
  3866     def m2i(self, pkt, m):
  3867         return self.cls(m)
  3868     def getfield(self, pkt, s):
  3869         i = self.m2i(pkt, s)
  3870         remain = ""
  3871         if i.haslayer(Padding):
  3872             r = i.getlayer(Padding)
  3873             del(r.underlayer.payload)
  3874             remain = r.load
  3875         return remain,i
  3876     
  3877 class PacketLenField(PacketField):
  3878     holds_packets=1
  3879     def __init__(self, name, default, cls, fld=None, length_from=None, shift=0):
  3880         PacketField.__init__(self, name, default, cls, shift=shift)
  3881         self.length_from = length_from
  3882         if fld is not None or shift != 0:
  3883             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  3884             self.count_from = lambda pkt,fld=fld,shift=shift: getattr(pkt,fld)-shift
  3885     def getfield(self, pkt, s):
  3886         l = self.length_from(pkt)
  3887         i = self.m2i(pkt, s[:l])
  3888         return s[l:],i
  3889 
  3890 
  3891 class PacketListField(PacketField):
  3892     islist = 1
  3893     holds_packets=1
  3894     def __init__(self, name, default, cls, fld=None, count_from=None, length_from=None, shift=0):
  3895         if default is None:
  3896             default = []  # Create a new list for each instance
  3897         PacketField.__init__(self, name, default, cls, shift=shift)
  3898         self.count_from = count_from
  3899         self.length_from = length_from
  3900 
  3901         if fld is not None or shift != 0:
  3902             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  3903         if fld is not None:
  3904             self.count_from = lambda pkt,fld=fld,shift=shift: getattr(pkt,fld)-shift
  3905 
  3906     def any2i(self, pkt, x):
  3907         if type(x) is not list:
  3908             return [x]
  3909         else:
  3910             return x
  3911     def i2count(self, pkt, val):
  3912         if type(val) is list:
  3913             return len(val)
  3914         return 1
  3915     def i2len(self, pkt, val):
  3916         return sum( len(p) for p in val )
  3917     def do_copy(self, x):
  3918         return map(lambda p:p.copy(), x)
  3919     def getfield(self, pkt, s):
  3920         c = l = None
  3921         if self.length_from is not None:
  3922             l = self.length_from(pkt)
  3923         elif self.count_from is not None:
  3924             c = self.count_from(pkt)
  3925             
  3926         lst = []
  3927         ret = ""
  3928         remain = s
  3929         if l is not None:
  3930             remain,ret = s[:l],s[l:]
  3931         while remain:
  3932             if c is not None:
  3933                 if c <= 0:
  3934                     break
  3935                 c -= 1
  3936             p = self.m2i(pkt,remain)
  3937             if Padding in p:
  3938                 pad = p[Padding]
  3939                 remain = pad.load
  3940                 del(pad.underlayer.payload)
  3941             else:
  3942                 remain = ""
  3943             lst.append(p)
  3944         return remain+ret,lst
  3945     def addfield(self, pkt, s, val):
  3946         return s+"".join(map(str, val))
  3947 
  3948 
  3949 class StrFixedLenField(StrField):
  3950     def __init__(self, name, default, length=None, length_from=None, shift=0):
  3951         StrField.__init__(self, name, default, shift=shift)
  3952         self.length_from  = length_from
  3953         if length is not None:
  3954             self.length_from = lambda pkt,length=length: length
  3955     def getfield(self, pkt, s):
  3956         l = self.length_from(pkt)
  3957         return s[l:], self.m2i(pkt,s[:l])
  3958     def addfield(self, pkt, s, val):
  3959         l = self.length_from(pkt)
  3960         return s+struct.pack("%is"%l,self.i2m(pkt, val))
  3961     def randval(self):
  3962         try:
  3963             l = self.length_from(None)
  3964         except:
  3965             l = RandNum(0,200)
  3966         return RandBin(l)
  3967 
  3968 class NetBIOSNameField(StrFixedLenField):
  3969     def __init__(self, name, default, length=31, shift=0):
  3970         StrFixedLenField.__init__(self, name, default, length, shift=shift)
  3971     def i2m(self, pkt, x):
  3972         l = self.length_from(pkt)/2
  3973         if x is None:
  3974             x = ""
  3975         x += " "*(l)
  3976         x = x[:l]
  3977         x = "".join(map(lambda x: chr(0x41+(ord(x)>>4))+chr(0x41+(ord(x)&0xf)), x))
  3978         x = " "+x
  3979         return x
  3980     def m2i(self, pkt, x):
  3981         x = x.strip("\x00").strip(" ")
  3982         return "".join(map(lambda x,y: chr((((ord(x)-1)&0xf)<<4)+((ord(y)-1)&0xf)), x[::2],x[1::2]))
  3983 
  3984 class StrLenField(StrField):
  3985     def __init__(self, name, default, fld=None, length_from=None, shift=0):
  3986         StrField.__init__(self, name, default, shift=shift)
  3987         self.length_from = length_from
  3988         if fld is not None or shift != 0:
  3989             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  3990             self.length_from = lambda pkt,fld=fld,shift=shift: getattr(pkt,fld)-shift
  3991     def getfield(self, pkt, s):
  3992         l = self.length_from(pkt)
  3993         return s[l:], self.m2i(pkt,s[:l])
  3994 
  3995 class FieldListField(Field):
  3996     islist=1
  3997     def __init__(self, name, default, field, fld=None, shift=0, length_from=None, count_from=None):
  3998         if default is None:
  3999             default = []  # Create a new list for each instance
  4000         Field.__init__(self, name, default)
  4001         self.count_from = count_from
  4002         self.length_from = length_from
  4003         self.field = field
  4004         if fld is not None or shift != 0:
  4005             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  4006             self.count_from = lambda pkt,fld=fld,shift=shift: getattr(pkt,fld)-shift
  4007             
  4008             
  4009     def i2count(self, pkt, val):
  4010         if type(val) is list:
  4011             return len(val)
  4012         return 1
  4013     def i2len(self, pkt, val):
  4014         return sum( self.field.i2len(pkt,v) for v in val )
  4015     
  4016     def i2m(self, pkt, val):
  4017         if val is None:
  4018             val = []
  4019         return val
  4020     def any2i(self, pkt, x):
  4021         if type(x) is not list:
  4022             return [x]
  4023         else:
  4024             return x
  4025     def addfield(self, pkt, s, val):
  4026         val = self.i2m(pkt, val)
  4027         for v in val:
  4028             s = self.field.addfield(pkt, s, v)
  4029         return s
  4030     def getfield(self, pkt, s):
  4031         c = l = None
  4032         if self.length_from is not None:
  4033             l = self.length_from(pkt)
  4034         elif self.count_from is not None:
  4035             c = self.count_from(pkt)
  4036 
  4037         val = []
  4038         ret=""
  4039         if l is not None:
  4040             s,ret = s[:l],s[l:]
  4041             
  4042         while s:
  4043             if c is not None:
  4044                 if c <= 0:
  4045                     break
  4046                 c -= 1
  4047             s,v = self.field.getfield(pkt, s)
  4048             val.append(v)
  4049         return s+ret, val
  4050 
  4051 class FieldLenField(Field):
  4052     def __init__(self, name, default,  length_of=None, fmt = "H", count_of=None, adjust=lambda pkt,x:x, fld=None):
  4053         Field.__init__(self, name, default, fmt)
  4054         self.length_of=length_of
  4055         self.count_of=count_of
  4056         self.adjust=adjust
  4057         if fld is not None:
  4058             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  4059             self.length_of = fld
  4060     def i2m(self, pkt, x):
  4061         if x is None:
  4062             if self.length_of is not None:
  4063                 fld,fval = pkt.getfield_and_val(self.length_of)
  4064                 f = fld.i2len(pkt, fval)
  4065             else:
  4066                 fld,fval = pkt.getfield_and_val(self.count_of)
  4067                 f = fld.i2count(pkt, fval)
  4068             x = self.adjust(pkt,f)
  4069         return x
  4070 
  4071 # see http://www.iana.org/assignments/ipsec-registry for details
  4072 ISAKMPAttributeTypes= { "Encryption":    (1, { "DES-CBC"  : 1,
  4073                                                 "IDEA-CBC" : 2,
  4074                                                 "Blowfish-CBC" : 3,
  4075                                                 "RC5-R16-B64-CBC" : 4,
  4076                                                 "3DES-CBC" : 5, 
  4077                                                 "CAST-CBC" : 6, 
  4078                                                 "AES-CBC" : 7, 
  4079                                                 "CAMELLIA-CBC" : 8, }, 0),
  4080                          "Hash":          (2, { "MD5": 1,
  4081                                                 "SHA": 2,
  4082                                                 "Tiger": 3,
  4083                                                 "SHA2-256": 4,
  4084                                                 "SHA2-384": 5,
  4085                                                 "SHA2-512": 6,}, 0),
  4086                          "Authentication":(3, { "PSK": 1, 
  4087                                                 "DSS": 2,
  4088                                                 "RSA Sig": 3,
  4089                                                 "RSA Encryption": 4,
  4090                                                 "RSA Encryption Revised": 5,
  4091                                                 "ElGamal Encryption": 6,
  4092                                                 "ElGamal Encryption Revised": 7,
  4093                                                 "ECDSA Sig": 8,
  4094                                                 "HybridInitRSA": 64221,
  4095                                                 "HybridRespRSA": 64222,
  4096                                                 "HybridInitDSS": 64223,
  4097                                                 "HybridRespDSS": 64224,
  4098                                                 "XAUTHInitPreShared": 65001,
  4099                                                 "XAUTHRespPreShared": 65002,
  4100                                                 "XAUTHInitDSS": 65003,
  4101                                                 "XAUTHRespDSS": 65004,
  4102                                                 "XAUTHInitRSA": 65005,
  4103                                                 "XAUTHRespRSA": 65006,
  4104                                                 "XAUTHInitRSAEncryption": 65007,
  4105                                                 "XAUTHRespRSAEncryption": 65008,
  4106                                                 "XAUTHInitRSARevisedEncryption": 65009,
  4107                                                 "XAUTHRespRSARevisedEncryptio": 65010, }, 0),
  4108                          "GroupDesc":     (4, { "768MODPgr"  : 1,
  4109                                                 "1024MODPgr" : 2, 
  4110                                                 "EC2Ngr155"  : 3,
  4111                                                 "EC2Ngr185"  : 4,
  4112                                                 "1536MODPgr" : 5, 
  4113                                                 "2048MODPgr" : 14, 
  4114                                                 "3072MODPgr" : 15, 
  4115                                                 "4096MODPgr" : 16, 
  4116                                                 "6144MODPgr" : 17, 
  4117                                                 "8192MODPgr" : 18, }, 0),
  4118                          "GroupType":      (5,  {"MODP":       1,
  4119                                                  "ECP":        2,
  4120                                                  "EC2N":       3}, 0),
  4121                          "GroupPrime":     (6,  {}, 1),
  4122                          "GroupGenerator1":(7,  {}, 1),
  4123                          "GroupGenerator2":(8,  {}, 1),
  4124                          "GroupCurveA":    (9,  {}, 1),
  4125                          "GroupCurveB":    (10, {}, 1),
  4126                          "LifeType":       (11, {"Seconds":     1,
  4127                                                  "Kilobytes":   2,  }, 0),
  4128                          "LifeDuration":   (12, {}, 1),
  4129                          "PRF":            (13, {}, 0),
  4130                          "KeyLength":      (14, {}, 0),
  4131                          "FieldSize":      (15, {}, 0),
  4132                          "GroupOrder":     (16, {}, 1),
  4133                          }
  4134 
  4135 # the name 'ISAKMPTransformTypes' is actually a misnomer (since the table 
  4136 # holds info for all ISAKMP Attribute types, not just transforms, but we'll 
  4137 # keep it for backwards compatibility... for now at least
  4138 ISAKMPTransformTypes = ISAKMPAttributeTypes
  4139 
  4140 ISAKMPTransformNum = {}
  4141 for n in ISAKMPTransformTypes:
  4142     val = ISAKMPTransformTypes[n]
  4143     tmp = {}
  4144     for e in val[1]:
  4145         tmp[val[1][e]] = e
  4146     ISAKMPTransformNum[val[0]] = (n,tmp, val[2])
  4147 del(n)
  4148 del(e)
  4149 del(tmp)
  4150 del(val)
  4151 
  4152 
  4153 class ISAKMPTransformSetField(StrLenField):
  4154     islist=1
  4155     def type2num(self, (typ,val)):
  4156         type_val,enc_dict,tlv = ISAKMPTransformTypes.get(typ, (typ,{},0))
  4157         val = enc_dict.get(val, val)
  4158         s = ""
  4159         if (val & ~0xffff):
  4160             if not tlv:
  4161                 warning("%r should not be TLV but is too big => using TLV encoding" % typ)
  4162             n = 0
  4163             while val:
  4164                 s = chr(val&0xff)+s
  4165                 val >>= 8
  4166                 n += 1
  4167             val = n
  4168         else:
  4169             type_val |= 0x8000
  4170         return struct.pack("!HH",type_val, val)+s
  4171     def num2type(self, typ, enc):
  4172         val = ISAKMPTransformNum.get(typ,(typ,{}))
  4173         enc = val[1].get(enc,enc)
  4174         return (val[0],enc)
  4175     def i2m(self, pkt, i):
  4176         if i is None:
  4177             return ""
  4178         i = map(self.type2num, i)
  4179         return "".join(i)
  4180     def m2i(self, pkt, m):
  4181         # I try to ensure that we don't read off the end of our packet based
  4182         # on bad length fields we're provided in the packet. There are still
  4183         # conditions where struct.unpack() may not get enough packet data, but
  4184         # worst case that should result in broken attributes (which would
  4185         # be expected). (wam)
  4186         lst = []
  4187         while len(m) >= 4:
  4188             trans_type, = struct.unpack("!H", m[:2])
  4189             is_tlv = not (trans_type & 0x8000)
  4190             if is_tlv:
  4191                 # We should probably check to make sure the attribute type we
  4192                 # are looking at is allowed to have a TLV format and issue a 
  4193                 # warning if we're given an TLV on a basic attribute.
  4194                 value_len, = struct.unpack("!H", m[2:4])
  4195                 if value_len+4 > len(m):
  4196                     warning("Bad length for ISAKMP tranform type=%#6x" % trans_type)
  4197                 value = m[4:4+value_len]
  4198                 value = reduce(lambda x,y: (x<<8L)|y, struct.unpack("!%s" % ("B"*len(value),), value),0)
  4199             else:
  4200                 trans_type &= 0x7fff
  4201                 value_len=0
  4202                 value, = struct.unpack("!H", m[2:4])
  4203             m=m[4+value_len:]
  4204             lst.append(self.num2type(trans_type, value))
  4205         if len(m) > 0:
  4206             warning("Extra bytes after ISAKMP transform dissection [%r]" % m)
  4207         return lst
  4208 
  4209 class StrNullField(StrField):
  4210     def addfield(self, pkt, s, val):
  4211         return s+self.i2m(pkt, val)+"\x00"
  4212     def getfield(self, pkt, s):
  4213         l = s.find("\x00")
  4214         if l < 0:
  4215             #XXX \x00 not found
  4216             return "",s
  4217         return s[l+1:],self.m2i(pkt, s[:l])
  4218     def randval(self):
  4219         return RandTermString(RandNum(0,1200),"\x00")
  4220 
  4221 class StrStopField(StrField):
  4222     def __init__(self, name, default, stop, additionnal=0):
  4223         Field.__init__(self, name, default)
  4224         self.stop=stop
  4225         self.additionnal=additionnal
  4226     def getfield(self, pkt, s):
  4227         l = s.find(self.stop)
  4228         if l < 0:
  4229             return "",s
  4230 #            raise Scapy_Exception,"StrStopField: stop value [%s] not found" %stop
  4231         l += len(self.stop)+self.additionnal
  4232         return s[l:],s[:l]
  4233     def randval(self):
  4234         return RandTermString(RandNum(0,1200),self.stop)
  4235 
  4236 class LenField(Field):
  4237     def i2m(self, pkt, x):
  4238         if x is None:
  4239             x = len(pkt.payload)
  4240         return x
  4241 
  4242 class BCDFloatField(Field):
  4243     def i2m(self, pkt, x):
  4244         return int(256*x)
  4245     def m2i(self, pkt, x):
  4246         return x/256.0
  4247 
  4248 class BitField(Field):
  4249     def __init__(self, name, default, size):
  4250         Field.__init__(self, name, default)
  4251         self.rev = size < 0 
  4252         self.size = abs(size)
  4253     def reverse(self, val):
  4254         if self.size == 16:
  4255             val = socket.ntohs(val)
  4256         elif self.size == 32:
  4257             val = socket.ntohl(val)
  4258         return val
  4259         
  4260     def addfield(self, pkt, s, val):
  4261         val = self.i2m(pkt, val)
  4262         if type(s) is tuple:
  4263             s,bitsdone,v = s
  4264         else:
  4265             bitsdone = 0
  4266             v = 0
  4267         if self.rev:
  4268             val = self.reverse(val)
  4269         v <<= self.size
  4270         v |= val & ((1L<<self.size) - 1)
  4271         bitsdone += self.size
  4272         while bitsdone >= 8:
  4273             bitsdone -= 8
  4274             s = s+struct.pack("!B", v >> bitsdone)
  4275             v &= (1L<<bitsdone)-1
  4276         if bitsdone:
  4277             return s,bitsdone,v
  4278         else:
  4279             return s
  4280     def getfield(self, pkt, s):
  4281         if type(s) is tuple:
  4282             s,bn = s
  4283         else:
  4284             bn = 0
  4285         # we don't want to process all the string
  4286         nb_bytes = (self.size+bn-1)/8 + 1
  4287         w = s[:nb_bytes]
  4288 
  4289         # split the substring byte by byte
  4290         bytes = struct.unpack('!%dB' % nb_bytes , w)
  4291 
  4292         b = 0L
  4293         for c in range(nb_bytes):
  4294             b |= long(bytes[c]) << (nb_bytes-c-1)*8
  4295 
  4296         # get rid of high order bits
  4297         b &= (1L << (nb_bytes*8-bn)) - 1
  4298 
  4299         # remove low order bits
  4300         b = b >> (nb_bytes*8 - self.size - bn)
  4301 
  4302         if self.rev:
  4303             b = self.reverse(b)
  4304 
  4305         bn += self.size
  4306         s = s[bn/8:]
  4307         bn = bn%8
  4308         b = self.m2i(pkt, b)
  4309         if bn:
  4310             return (s,bn),b
  4311         else:
  4312             return s,b
  4313     def randval(self):
  4314         return RandNum(0,2**self.size-1)
  4315 
  4316 
  4317 class BitFieldLenField(BitField):
  4318     def __init__(self, name, default, size, length_of=None, count_of=None, adjust=lambda pkt,x:x):
  4319         BitField.__init__(self, name, default, size)
  4320         self.length_of=length_of
  4321         self.count_of=count_of
  4322         self.adjust=adjust
  4323     def i2m(self, pkt, x):
  4324         return FieldLenField.i2m.im_func(self, pkt, x)
  4325 
  4326 
  4327 class XBitField(BitField):
  4328     def i2repr(self, pkt, x):
  4329         return lhex(self.i2h(pkt,x))
  4330 
  4331 
  4332 class EnumField(Field):
  4333     def __init__(self, name, default, enum, fmt = "H"):
  4334         i2s = self.i2s = {}
  4335         s2i = self.s2i = {}
  4336         if type(enum) is list:
  4337             keys = xrange(len(enum))
  4338         else:
  4339             keys = enum.keys()
  4340         if filter(lambda x: type(x) is str, keys):
  4341             i2s,s2i = s2i,i2s
  4342         for k in keys:
  4343             i2s[k] = enum[k]
  4344             s2i[enum[k]] = k
  4345         Field.__init__(self, name, default, fmt)
  4346     def any2i_one(self, pkt, x):
  4347         if type(x) is str:
  4348             x = self.s2i[x]
  4349         return x
  4350     def i2repr_one(self, pkt, x):
  4351         if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s:
  4352             return self.i2s[x]
  4353         return repr(x)
  4354     
  4355     def any2i(self, pkt, x):
  4356         if type(x) is list:
  4357             return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x)
  4358         else:
  4359             return self.any2i_one(pkt,x)        
  4360     def i2repr(self, pkt, x):
  4361         if type(x) is list:
  4362             return map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x)
  4363         else:
  4364             return self.i2repr_one(pkt,x)
  4365 
  4366 class CharEnumField(EnumField):
  4367     def __init__(self, name, default, enum, fmt = "1s"):
  4368         EnumField.__init__(self, name, default, enum, fmt)
  4369         k = self.i2s.keys()
  4370         if k and len(k[0]) != 1:
  4371             self.i2s,self.s2i = self.s2i,self.i2s
  4372     def any2i_one(self, pkt, x):
  4373         if len(x) != 1:
  4374             x = self.s2i[x]
  4375         return x
  4376 
  4377 class BitEnumField(BitField,EnumField):
  4378     def __init__(self, name, default, size, enum):
  4379         EnumField.__init__(self, name, default, enum)
  4380         self.rev = size < 0
  4381         self.size = abs(size)
  4382     def any2i(self, pkt, x):
  4383         return EnumField.any2i(self, pkt, x)
  4384     def i2repr(self, pkt, x):
  4385         return EnumField.i2repr(self, pkt, x)
  4386 
  4387 class ShortEnumField(EnumField):
  4388     def __init__(self, name, default, enum):
  4389         EnumField.__init__(self, name, default, enum, "H")
  4390 
  4391 class LEShortEnumField(EnumField):
  4392     def __init__(self, name, default, enum):
  4393         EnumField.__init__(self, name, default, enum, "<H")
  4394 
  4395 class ByteEnumField(EnumField):
  4396     def __init__(self, name, default, enum):
  4397         EnumField.__init__(self, name, default, enum, "B")
  4398 
  4399 class IntEnumField(EnumField):
  4400     def __init__(self, name, default, enum):
  4401         EnumField.__init__(self, name, default, enum, "I")
  4402 
  4403 class SignedIntEnumField(EnumField):
  4404     def __init__(self, name, default, enum):
  4405         EnumField.__init__(self, name, default, enum, "i")
  4406     def randval(self):
  4407         return RandSInt()
  4408 
  4409 class LEIntEnumField(EnumField):
  4410     def __init__(self, name, default, enum):
  4411         EnumField.__init__(self, name, default, enum, "<I")
  4412 
  4413 class XShortEnumField(ShortEnumField):
  4414     def i2repr_one(self, pkt, x):
  4415         if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s:
  4416             return self.i2s[x]
  4417         return lhex(x)
  4418 
  4419 # Little endian long field
  4420 class LELongField(Field):
  4421     def __init__(self, name, default):
  4422         Field.__init__(self, name, default, "<Q")
  4423 
  4424 # Little endian fixed length field
  4425 class LEFieldLenField(FieldLenField):
  4426     def __init__(self, name, default,  length_of=None, fmt = "<H", count_of=None, adjust=lambda pkt,x:x, fld=None):
  4427         FieldLenField.__init__(self, name, default, length_of=length_of, fmt=fmt, fld=fld, adjust=adjust)
  4428 
  4429 
  4430 class FlagsField(BitField):
  4431     def __init__(self, name, default, size, names):
  4432         BitField.__init__(self, name, default, size)
  4433         self.multi = type(names) is list
  4434         if self.multi:
  4435             self.names = map(lambda x:[x], names)
  4436         else:
  4437             self.names = names
  4438     def any2i(self, pkt, x):
  4439         if type(x) is str:
  4440             if self.multi:
  4441                 x = map(lambda y:[y], x.split("+"))
  4442             y = 0
  4443             for i in x:
  4444                 y |= 1 << self.names.index(i)
  4445             x = y
  4446         return x
  4447     def i2repr(self, pkt, x):
  4448         if type(x) is list or type(x) is tuple:
  4449             return repr(x)
  4450         if self.multi:
  4451             r = []
  4452         else:
  4453             r = ""
  4454         i=0
  4455         while x:
  4456             if x & 1:
  4457                 r += self.names[i]
  4458             i += 1
  4459             x >>= 1
  4460         if self.multi:
  4461             r = "+".join(r)
  4462         return r
  4463 
  4464             
  4465 
  4466 
  4467 
  4468 class IPoptionsField(StrField):
  4469     def i2m(self, pkt, x):
  4470         return x+"\x00"*(3-((len(x)+3)%4))
  4471     def getfield(self, pkt, s):
  4472         opsz = (pkt.ihl-5)*4
  4473         if opsz < 0:
  4474             warning("bad ihl (%i). Assuming ihl=5"%pkt.ihl)
  4475             opsz = 0
  4476         return s[opsz:],s[:opsz]
  4477     def randval(self):
  4478         return RandBin(RandNum(0,39))
  4479 
  4480 
  4481 TCPOptions = (
  4482               { 0 : ("EOL",None),
  4483                 1 : ("NOP",None),
  4484                 2 : ("MSS","!H"),
  4485                 3 : ("WScale","!B"),
  4486                 4 : ("SAckOK",None),
  4487                 5 : ("SAck","!"),
  4488                 8 : ("Timestamp","!II"),
  4489                 14 : ("AltChkSum","!BH"),
  4490                 15 : ("AltChkSumOpt",None)
  4491                 },
  4492               { "EOL":0,
  4493                 "NOP":1,
  4494                 "MSS":2,
  4495                 "WScale":3,
  4496                 "SAckOK":4,
  4497                 "SAck":5,
  4498                 "Timestamp":8,
  4499                 "AltChkSum":14,
  4500                 "AltChkSumOpt":15,
  4501                 } )
  4502 
  4503 class TCPOptionsField(StrField):
  4504     islist=1
  4505     def getfield(self, pkt, s):
  4506         opsz = (pkt.dataofs-5)*4
  4507         if opsz < 0:
  4508             warning("bad dataofs (%i). Assuming dataofs=5"%pkt.dataofs)
  4509             opsz = 0
  4510         return s[opsz:],self.m2i(pkt,s[:opsz])
  4511     def m2i(self, pkt, x):
  4512         opt = []
  4513         while x:
  4514             onum = ord(x[0])
  4515             if onum == 0:
  4516                 opt.append(("EOL",None))
  4517                 x=x[1:]
  4518                 break
  4519             if onum == 1:
  4520                 opt.append(("NOP",None))
  4521                 x=x[1:]
  4522                 continue
  4523             olen = ord(x[1])
  4524             if olen < 2:
  4525                 warning("Malformed TCP option (announced length is %i)" % olen)
  4526                 olen = 2
  4527             oval = x[2:olen]
  4528             if TCPOptions[0].has_key(onum):
  4529                 oname, ofmt = TCPOptions[0][onum]
  4530                 if onum == 5: #SAck
  4531                     ofmt += "%iI" % (len(oval)/4)
  4532                 if ofmt and struct.calcsize(ofmt) == len(oval):
  4533                     oval = struct.unpack(ofmt, oval)
  4534                     if len(oval) == 1:
  4535                         oval = oval[0]
  4536                 opt.append((oname, oval))
  4537             else:
  4538                 opt.append((onum, oval))
  4539             x = x[olen:]
  4540         return opt
  4541     
  4542     def i2m(self, pkt, x):
  4543         opt = ""
  4544         for oname,oval in x:
  4545             if type(oname) is str:
  4546                 if oname == "NOP":
  4547                     opt += "\x01"
  4548                     continue
  4549                 elif oname == "EOL":
  4550                     opt += "\x00"
  4551                     continue
  4552                 elif TCPOptions[1].has_key(oname):
  4553                     onum = TCPOptions[1][oname]
  4554                     ofmt = TCPOptions[0][onum][1]
  4555                     if onum == 5: #SAck
  4556                         ofmt += "%iI" % len(oval)
  4557                     if ofmt is not None and (type(oval) is not str or "s" in ofmt):
  4558                         if type(oval) is not tuple:
  4559                             oval = (oval,)
  4560                         oval = struct.pack(ofmt, *oval)
  4561                 else:
  4562                     warning("option [%s] unknown. Skipped."%oname)
  4563                     continue
  4564             else:
  4565                 onum = oname
  4566                 if type(oval) is not str:
  4567                     warning("option [%i] is not string."%onum)
  4568                     continue
  4569             opt += chr(onum)+chr(2+len(oval))+oval
  4570         return opt+"\x00"*(3-((len(opt)+3)%4))
  4571     def randval(self):
  4572         return [] # XXX
  4573     
  4574 
  4575 class DNSStrField(StrField):
  4576     def i2m(self, pkt, x):
  4577         x = [k[:63] for k in x.split(".")] # Truncate chunks that cannont be encoded (more than 63 bytes..)
  4578         x = map(lambda y: chr(len(y))+y, x)
  4579         x = "".join(x)
  4580         if x[-1] != "\x00":
  4581             x += "\x00"
  4582         return x
  4583     def getfield(self, pkt, s):
  4584         n = ""
  4585         while 1:
  4586             l = ord(s[0])
  4587             s = s[1:]
  4588             if not l:
  4589                 break
  4590             if l & 0xc0:
  4591                 raise Scapy_Exception("DNS message can't be compressed at this point!")
  4592             else:
  4593                 n += s[:l]+"."
  4594                 s = s[l:]
  4595         return s, n
  4596 
  4597 
  4598 class DNSRRCountField(ShortField):
  4599     holds_packets=1
  4600     def __init__(self, name, default, rr):
  4601         ShortField.__init__(self, name, default)
  4602         self.rr = rr
  4603     def _countRR(self, pkt):
  4604         x = getattr(pkt,self.rr)
  4605         i = 0
  4606         while isinstance(x, DNSRR) or isinstance(x, DNSQR):
  4607             x = x.payload
  4608             i += 1
  4609         return i
  4610         
  4611     def i2m(self, pkt, x):
  4612         if x is None:
  4613             x = self._countRR(pkt)
  4614         return x
  4615     def i2h(self, pkt, x):
  4616         if x is None:
  4617             x = self._countRR(pkt)
  4618         return x
  4619     
  4620 
  4621 def DNSgetstr(s,p):
  4622     name = ""
  4623     q = 0
  4624     jpath = [p]
  4625     while 1:
  4626         if p >= len(s):
  4627             warning("DNS RR prematured end (ofs=%i, len=%i)"%(p,len(s)))
  4628             break
  4629         l = ord(s[p])
  4630         p += 1
  4631         if l & 0xc0:
  4632             if not q:
  4633                 q = p+1
  4634             if p >= len(s):
  4635                 warning("DNS incomplete jump token at (ofs=%i)" % p)
  4636                 break
  4637             p = ((l & 0x3f) << 8) + ord(s[p]) - 12
  4638             if p in jpath:
  4639                 warning("DNS decompression loop detected")
  4640                 break
  4641             jpath.append(p)
  4642             continue
  4643         elif l > 0:
  4644             name += s[p:p+l]+"."
  4645             p += l
  4646             continue
  4647         break
  4648     if q:
  4649         p = q
  4650     return name,p
  4651         
  4652 
  4653 class DNSRRField(StrField):
  4654     holds_packets=1
  4655     def __init__(self, name, countfld, passon=1):
  4656         StrField.__init__(self, name, None)
  4657         self.countfld = countfld
  4658         self.passon = passon
  4659     def i2m(self, pkt, x):
  4660         if x is None:
  4661             return ""
  4662         return str(x)
  4663     def decodeRR(self, name, s, p):
  4664         ret = s[p:p+10]
  4665         type,cls,ttl,rdlen = struct.unpack("!HHIH", ret)
  4666         p += 10
  4667         rr = DNSRR("\x00"+ret+s[p:p+rdlen])
  4668         if rr.type in [2, 3, 4, 5]:
  4669             rr.rdata = DNSgetstr(s,p)[0]
  4670         del(rr.rdlen)
  4671         
  4672         p += rdlen
  4673         
  4674         rr.rrname = name
  4675         return rr,p
  4676     def getfield(self, pkt, s):
  4677         if type(s) is tuple :
  4678             s,p = s
  4679         else:
  4680             p = 0
  4681         ret = None
  4682         c = getattr(pkt, self.countfld)
  4683         if c > len(s):
  4684             warning("wrong value: DNS.%s=%i" % (self.countfld,c))
  4685             return s,""
  4686         while c:
  4687             c -= 1
  4688             name,p = DNSgetstr(s,p)
  4689             rr,p = self.decodeRR(name, s, p)
  4690             if ret is None:
  4691                 ret = rr
  4692             else:
  4693                 ret.add_payload(rr)
  4694         if self.passon:
  4695             return (s,p),ret
  4696         else:
  4697             return s[p:],ret
  4698             
  4699             
  4700 class DNSQRField(DNSRRField):
  4701     holds_packets=1
  4702     def decodeRR(self, name, s, p):
  4703         ret = s[p:p+4]
  4704         p += 4
  4705         rr = DNSQR("\x00"+ret)
  4706         rr.qname = name
  4707         return rr,p
  4708         
  4709         
  4710 
  4711 class RDataField(StrLenField):
  4712     def m2i(self, pkt, s):
  4713         family = None
  4714         if pkt.type == 1:
  4715             family = socket.AF_INET
  4716         elif pkt.type == 28:
  4717             family = socket.AF_INET6
  4718         elif pkt.type == 12:
  4719             s = DNSgetstr(s, 0)[0]
  4720         if family is not None:    
  4721             s = inet_ntop(family, s)
  4722         return s
  4723     def i2m(self, pkt, s):
  4724         if pkt.type == 1:
  4725             if s:
  4726                 s = inet_aton(s)
  4727         elif pkt.type == 28:
  4728             if s:
  4729                 s = inet_pton(socket.AF_INET6, s)
  4730         elif pkt.type in [2,3,4,5]:
  4731             s = "".join(map(lambda x: chr(len(x))+x, s.split(".")))
  4732             if ord(s[-1]):
  4733                 s += "\x00"
  4734         return s
  4735 
  4736 class RDLenField(Field):
  4737     def __init__(self, name):
  4738         Field.__init__(self, name, None, "H")
  4739     def i2m(self, pkt, x):
  4740         if x is None:
  4741             rdataf = pkt.get_field("rdata")
  4742             x = len(rdataf.i2m(pkt, pkt.rdata))
  4743         return x
  4744     def i2h(self, pkt, x):
  4745         if x is None:
  4746             rdataf = pkt.get_field("rdata")
  4747             x = len(rdataf.i2m(pkt, pkt.rdata))
  4748         return x
  4749     
  4750 # seconds between 01-01-1900 and 01-01-1970
  4751 ntp_basetime = 2208988800
  4752 
  4753 class TimeStampField(BitField):
  4754     def __init__(self, name, default, size):
  4755         BitField.__init__(self, name, default, size)
  4756         self.size  = size
  4757     def getfield(self, pkt, s):
  4758         s,timestamp = BitField.getfield(self, pkt, s)
  4759 
  4760         if timestamp:
  4761             # timestamp is a 64 bits field :
  4762             #  + first 32 bits : number of seconds since 1900
  4763             #  + last 32 bits  : fraction part
  4764             timestamp >>= 32
  4765             timestamp -= ntp_basetime
  4766             
  4767             from time import gmtime, strftime
  4768             b = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime(timestamp))
  4769         else:
  4770             b = 'None'
  4771         
  4772         return s, b
  4773     def addfield(self, pkt, s, val):
  4774         t = -1
  4775         if type(val) is str:
  4776             from time import strptime, mktime
  4777             t = int(mktime(strptime(val))) + ntp_basetime + 3600
  4778         else:
  4779             if val == -1:
  4780                 from time import time
  4781                 t = int(time()) + ntp_basetime
  4782             else:
  4783                 t = val
  4784         t <<= 32
  4785         return BitField.addfield(self,pkt,s, t)
  4786 
  4787 class ICMPTimeStampField(IntField):
  4788     re_hmsm = re.compile("([0-2]?[0-9])[Hh:](([0-5]?[0-9])([Mm:]([0-5]?[0-9])([sS:.]([0-9]{0,3}))?)?)?$")
  4789     def i2repr(self, pkt, val):
  4790         if val is None:
  4791             return "--"
  4792         else:
  4793             sec, milli = divmod(val, 1000)
  4794             min, sec = divmod(sec, 60)
  4795             hour, min = divmod(min, 60)
  4796             return "%d:%d:%d.%d" %(hour, min, sec, int(milli))
  4797     def any2i(self, pkt, val):
  4798         if type(val) is str:
  4799             hmsms = self.re_hmsm.match(val)
  4800             if hmsms:
  4801                 h,_,m,_,s,_,ms = hmsms = hmsms.groups()
  4802                 ms = int(((ms or "")+"000")[:3])
  4803                 val = ((int(h)*60+int(m or 0))*60+int(s or 0))*1000+ms
  4804             else:
  4805                 val = 0
  4806         elif val is None:
  4807             val = int((time.time()%(24*60*60))*1000)
  4808         return val
  4809 
  4810 class FloatField(BitField):
  4811     def getfield(self, pkt, s):
  4812         s,b = BitField.getfield(self, pkt, s)
  4813         
  4814         # fraction point between bits 15 and 16.
  4815         sec = b >> 16
  4816         frac = b & (1L << (32+1)) - 1
  4817         frac /= 65536.0
  4818         b = sec+frac
  4819         return s,b    
  4820 
  4821 class Dot11SCField(LEShortField):
  4822     def is_applicable(self, pkt):
  4823         return pkt.type != 1 # control frame
  4824     def addfield(self, pkt, s, val):
  4825         if self.is_applicable(pkt):
  4826             return LEShortField.addfield(self, pkt, s, val)
  4827         else:
  4828             return s
  4829     def getfield(self, pkt, s):
  4830         if self.is_applicable(pkt):
  4831             return LEShortField.getfield(self, pkt, s)
  4832         else:
  4833             return s,None
  4834 
  4835 #####################
  4836 #### ASN1 Fields ####
  4837 #####################
  4838 
  4839 class ASN1F_badsequence(Exception):
  4840     pass
  4841 
  4842 class ASN1F_element:
  4843     pass
  4844 
  4845 class ASN1F_optionnal(ASN1F_element):
  4846     def __init__(self, field):
  4847         self._field=field
  4848     def __getattr__(self, attr):
  4849         return getattr(self._field,attr)
  4850     def dissect(self,pkt,s):
  4851         try:
  4852             return self._field.dissect(pkt,s)
  4853         except ASN1F_badsequence:
  4854             self._field.set_val(pkt,None)
  4855             return s
  4856         except BER_Decoding_Error:
  4857             self._field.set_val(pkt,None)
  4858             return s
  4859     def build(self, pkt):
  4860         if self._field.is_empty(pkt):
  4861             return ""
  4862         return self._field.build(pkt)
  4863 
  4864 class ASN1F_field(ASN1F_element):
  4865     holds_packets=0
  4866     islist=0
  4867 
  4868     ASN1_tag = ASN1_Class_UNIVERSAL.ANY
  4869     context=ASN1_Class_UNIVERSAL
  4870     
  4871     def __init__(self, name, default, context=None):
  4872         if context is not None:
  4873             self.context = context
  4874         self.name = name
  4875         self.default = default
  4876 
  4877     def i2repr(self, pkt, x):
  4878         if x is None:
  4879             x = 0
  4880         return repr(x)
  4881     def i2h(self, pkt, x):
  4882         return x
  4883     def any2i(self, pkt, x):
  4884         return x
  4885     def m2i(self, pkt, x):
  4886         return self.ASN1_tag.get_codec(pkt.ASN1_codec).safedec(x, context=self.context)
  4887     def i2m(self, pkt, x):
  4888         if x is None:
  4889             x = 0
  4890         if isinstance(x, ASN1_Object):
  4891             if ( self.ASN1_tag == ASN1_Class_UNIVERSAL.ANY
  4892                  or x.tag == ASN1_Class_UNIVERSAL.RAW
  4893                  or x.tag == ASN1_Class_UNIVERSAL.ERROR
  4894                  or self.ASN1_tag == x.tag ):
  4895                 return x.enc(pkt.ASN1_codec)
  4896             else:
  4897                 raise ASN1_Error("Encoding Error: got %r instead of an %r for field [%s]" % (x, self.ASN1_tag, self.name))
  4898         return self.ASN1_tag.get_codec(pkt.ASN1_codec).enc(x)
  4899 
  4900     def do_copy(self, x):
  4901         if hasattr(x, "copy"):
  4902             return x.copy()
  4903         if type(x) is list:
  4904             x = x[:]
  4905             for i in xrange(len(x)):
  4906                 if isinstance(x[i], Packet):
  4907                     x[i] = x[i].copy()
  4908         return x
  4909 
  4910     def build(self, pkt):
  4911         return self.i2m(pkt, getattr(pkt, self.name))
  4912 
  4913     def set_val(self, pkt, val):
  4914         setattr(pkt, self.name, val)
  4915     def is_empty(self, pkt):
  4916         return getattr(pkt,self.name) is None
  4917     
  4918     def dissect(self, pkt, s):
  4919         v,s = self.m2i(pkt, s)
  4920         self.set_val(pkt, v)
  4921         return s
  4922 
  4923     def get_fields_list(self):
  4924         return [self]
  4925 
  4926     def __hash__(self):
  4927         return hash(self.name)
  4928     def __str__(self):
  4929         return self.name
  4930     def __eq__(self, other):
  4931         return self.name == other
  4932     def __repr__(self):
  4933         return self.name
  4934     def randval(self):
  4935         return RandInt()
  4936 
  4937 
  4938 class ASN1F_INTEGER(ASN1F_field):
  4939     ASN1_tag= ASN1_Class_UNIVERSAL.INTEGER
  4940     def randval(self):
  4941         return RandNum(-2**64, 2**64-1)
  4942 
  4943 class ASN1F_NULL(ASN1F_INTEGER):
  4944     ASN1_tag= ASN1_Class_UNIVERSAL.NULL
  4945 
  4946 class ASN1F_enum_INTEGER(ASN1F_INTEGER):
  4947     def __init__(self, name, default, enum):
  4948         ASN1F_INTEGER.__init__(self, name, default)
  4949         i2s = self.i2s = {}
  4950         s2i = self.s2i = {}
  4951         if type(enum) is list:
  4952             keys = xrange(len(enum))
  4953         else:
  4954             keys = enum.keys()
  4955         if filter(lambda x: type(x) is str, keys):
  4956             i2s,s2i = s2i,i2s
  4957         for k in keys:
  4958             i2s[k] = enum[k]
  4959             s2i[enum[k]] = k
  4960     def any2i_one(self, pkt, x):
  4961         if type(x) is str:
  4962             x = self.s2i[x]
  4963         return x
  4964     def i2repr_one(self, pkt, x):
  4965         return self.i2s.get(x, repr(x))
  4966     
  4967     def any2i(self, pkt, x):
  4968         if type(x) is list:
  4969             return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x)
  4970         else:
  4971             return self.any2i_one(pkt,x)        
  4972     def i2repr(self, pkt, x):
  4973         if type(x) is list:
  4974             return map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x)
  4975         else:
  4976             return self.i2repr_one(pkt,x)
  4977 
  4978 class ASN1F_STRING(ASN1F_field):
  4979     ASN1_tag = ASN1_Class_UNIVERSAL.STRING
  4980     def randval(self):
  4981         return RandString(RandNum(0, 1000))
  4982 
  4983 class ASN1F_PRINTABLE_STRING(ASN1F_STRING):
  4984     ASN1_tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
  4985 
  4986 class ASN1F_BIT_STRING(ASN1F_STRING):
  4987     ASN1_tag = ASN1_Class_UNIVERSAL.BIT_STRING
  4988 
  4989 class ASN1F_UTC_TIME(ASN1F_STRING):
  4990     ASN1_tag = ASN1_Class_UNIVERSAL.UTC_TIME
  4991 
  4992 class ASN1F_OID(ASN1F_field):
  4993     ASN1_tag = ASN1_Class_UNIVERSAL.OID
  4994     def randval(self):
  4995         return RandOID()
  4996 
  4997 class ASN1F_SEQUENCE(ASN1F_field):
  4998     ASN1_tag = ASN1_Class_UNIVERSAL.SEQUENCE
  4999     def __init__(self, *seq, **kargs):
  5000         if "ASN1_tag" in kargs:
  5001             self.ASN1_tag = kargs["ASN1_tag"]
  5002         self.seq = seq
  5003     def __repr__(self):
  5004         return "<%s%r>" % (self.__class__.__name__,self.seq,)
  5005     def set_val(self, pkt, val):
  5006         for f in self.seq:
  5007             f.set_val(pkt,val)
  5008     def is_empty(self, pkt):
  5009         for f in self.seq:
  5010             if not f.is_empty(pkt):
  5011                 return False
  5012         return True
  5013     def get_fields_list(self):
  5014         return reduce(lambda x,y: x+y.get_fields_list(), self.seq, [])
  5015     def build(self, pkt):
  5016         s = reduce(lambda x,y: x+y.build(pkt), self.seq, "")
  5017         return self.i2m(pkt, s)
  5018     def dissect(self, pkt, s):
  5019         codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
  5020         try:
  5021             i,s,remain = codec.check_type_check_len(s)
  5022             for obj in self.seq:
  5023                 s = obj.dissect(pkt,s)
  5024             if s:
  5025                 warning("Too many bytes to decode sequence: [%r]" % s) # XXX not reversible!
  5026             return remain
  5027         except ASN1_Error,e:
  5028             raise ASN1F_badsequence(e)
  5029 
  5030 class ASN1F_SET(ASN1F_SEQUENCE):
  5031     ASN1_tag = ASN1_Class_UNIVERSAL.SET
  5032 
  5033 class ASN1F_SEQUENCE_OF(ASN1F_SEQUENCE):
  5034     holds_packets = 1
  5035     islist = 1
  5036     def __init__(self, name, default, asn1pkt, ASN1_tag=0x30):
  5037         self.asn1pkt = asn1pkt
  5038         self.tag = chr(ASN1_tag)
  5039         self.name = name
  5040         self.default = default
  5041     def i2repr(self, pkt, i):
  5042         if i is None:
  5043             return []
  5044         return i
  5045     def get_fields_list(self):
  5046         return [self]
  5047     def set_val(self, pkt, val):
  5048         ASN1F_field.set_val(self, pkt, val)
  5049     def is_empty(self, pkt):
  5050         return ASN1F_field.is_empty(self, pkt)
  5051     def build(self, pkt):
  5052         val = getattr(pkt, self.name)
  5053         if isinstance(val, ASN1_Object) and val.tag == ASN1_Class_UNIVERSAL.RAW:
  5054             s = val
  5055         elif val is None:
  5056             s = ""
  5057         else:
  5058             s = "".join(map(str, val ))
  5059         return self.i2m(pkt, s)
  5060     def set_val(self, pkt, val):
  5061         ASN1F_field.set_val(self, pkt, val)
  5062     def dissect(self, pkt, s):
  5063         codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
  5064         i,s1,remain = codec.check_type_check_len(s)
  5065         lst = []
  5066         while s1:
  5067             try:
  5068                 p = self.asn1pkt(s1)
  5069             except ASN1F_badsequence,e:
  5070                 lst.append(Raw(s1))
  5071                 break
  5072             lst.append(p)
  5073             if Raw in p:
  5074                 s1 = p[Raw].load
  5075                 del(p[Raw].underlayer.payload)
  5076             else:
  5077                 break
  5078         self.set_val(pkt, lst)
  5079         return remain
  5080     def randval(self):
  5081         return fuzz(self.asn1pkt())
  5082     def __repr__(self):
  5083         return "<%s %s>" % (self.__class__.__name__,self.name)
  5084 
  5085 class ASN1F_PACKET(ASN1F_field):
  5086     holds_packets = 1
  5087     def __init__(self, name, default, cls):
  5088         ASN1_field.__init__(self, name, default)
  5089         self.cls = cls
  5090     def i2m(self, pkt, x):
  5091         if x is None:
  5092             x = ""
  5093         return str(x)
  5094     def extract_packet(self, cls, x):
  5095         try:
  5096             c = cls(x)
  5097         except ASN1F_badsequence:
  5098             c = Raw(x)
  5099         cpad = c[Padding]
  5100         x = ""
  5101         if cpad is not None:
  5102             x = cpad.load
  5103             del(cpad.underlayer.payload)
  5104         return c,x
  5105     def m2i(self, pkt, x):
  5106         return self.extract_packet(self.cls, x)
  5107 
  5108 
  5109 class ASN1F_CHOICE(ASN1F_PACKET):
  5110     ASN1_tag = ASN1_Class_UNIVERSAL.NONE
  5111     def __init__(self, name, default, *args):
  5112         self.name=name
  5113         self.choice = {}
  5114         for p in args:
  5115             self.choice[p.ASN1_root.ASN1_tag] = p
  5116 #        self.context=context
  5117         self.default=default
  5118     def m2i(self, pkt, x):
  5119         if len(x) == 0:
  5120             return Raw(),""
  5121             raise ASN1_Error("ASN1F_CHOICE: got empty string")
  5122         if ord(x[0]) not in self.choice:
  5123             return Raw(x),"" # XXX return RawASN1 packet ? Raise error 
  5124             raise ASN1_Error("Decoding Error: choice [%i] not found in %r" % (ord(x[0]), self.choice.keys()))
  5125 
  5126         z = ASN1F_PACKET.extract_packet(self, self.choice[ord(x[0])], x)
  5127         return z
  5128     def randval(self):
  5129         return RandChoice(*map(lambda x:fuzz(x()), self.choice.values()))
  5130             
  5131     
  5132 
  5133 ###########################
  5134 ## Packet abstract class ##
  5135 ###########################
  5136 
  5137 class Packet_metaclass(type):
  5138     def __new__(cls, name, bases, dct):
  5139         newcls = super(Packet_metaclass, cls).__new__(cls, name, bases, dct)
  5140         for f in newcls.fields_desc:
  5141             f.register_owner(newcls)
  5142         return newcls
  5143     def __getattr__(self, attr):
  5144         for k in self.fields_desc:
  5145             if k.name == attr:
  5146                 return k
  5147         raise AttributeError(attr)
  5148 
  5149 class NewDefaultValues(Packet_metaclass):
  5150     """NewDefaultValues metaclass. Example usage:
  5151     class MyPacket(Packet):
  5152         fields_desc = [ StrField("my_field", "my default value"),  ]
  5153         
  5154     class MyPacket_variant(MyPacket):
  5155         __metaclass__ = NewDefaultValues
  5156         my_field = "my new default value"
  5157     """    
  5158     def __new__(cls, name, bases, dct):
  5159         fields = None
  5160         for b in bases:
  5161             if hasattr(b,"fields_desc"):
  5162                 fields = b.fields_desc
  5163                 break
  5164         if fields is None:
  5165             raise Scapy_Exception("No fields_desc in superclasses")
  5166 
  5167         new_fields = []
  5168         for f in fields:
  5169             if f.name in dct:
  5170                 f = f.copy()
  5171                 f.default = dct[f.name]
  5172                 del(dct[f.name])
  5173             new_fields.append(f)
  5174         dct["fields_desc"] = new_fields
  5175         return super(NewDefaultValues, cls).__new__(cls, name, bases, dct)
  5176 
  5177 class Packet(Gen):
  5178     __metaclass__ = Packet_metaclass
  5179     name=None
  5180 
  5181     fields_desc = []
  5182 
  5183     aliastypes = []
  5184     overload_fields = {}
  5185 
  5186     underlayer = None
  5187 
  5188     payload_guess = []
  5189     initialized = 0
  5190     show_indent=1
  5191     explicit = 0
  5192 
  5193     @classmethod
  5194     def from_hexcap(cls):
  5195         return cls(import_hexcap())
  5196 
  5197     @classmethod
  5198     def upper_bonds(self):
  5199         for fval,upper in self.payload_guess:
  5200             print "%-20s  %s" % (upper.__name__, ", ".join("%-12s" % ("%s=%r"%i) for i in fval.iteritems()))
  5201 
  5202     @classmethod
  5203     def lower_bonds(self):
  5204         for lower,fval in self.overload_fields.iteritems():
  5205             print "%-20s  %s" % (lower.__name__, ", ".join("%-12s" % ("%s=%r"%i) for i in fval.iteritems()))
  5206 
  5207     def __init__(self, _pkt="", post_transform=None, _internal=0, _underlayer=None, **fields):
  5208         self.time  = time.time()
  5209         self.sent_time = 0
  5210         if self.name is None:
  5211             self.name = self.__class__.__name__
  5212         self.aliastypes = [ self.__class__ ] + self.aliastypes
  5213         self.default_fields = {}
  5214         self.overloaded_fields = {}
  5215         self.fields={}
  5216         self.fieldtype={}
  5217         self.packetfields=[]
  5218         self.__dict__["payload"] = NoPayload()
  5219         self.init_fields()
  5220         self.underlayer = _underlayer
  5221         self.initialized = 1
  5222         if _pkt:
  5223             self.dissect(_pkt)
  5224             if not _internal:
  5225                 self.dissection_done(self)
  5226         for f in fields.keys():
  5227             self.fields[f] = self.get_field(f).any2i(self,fields[f])
  5228         if type(post_transform) is list:
  5229             self.post_transforms = post_transform
  5230         elif post_transform is None:
  5231             self.post_transforms = []
  5232         else:
  5233             self.post_transforms = [post_transform]
  5234 
  5235     def init_fields(self):
  5236         self.do_init_fields(self.fields_desc)
  5237 
  5238     def do_init_fields(self, flist):
  5239         for f in flist:
  5240             self.default_fields[f.name] = f.default
  5241             self.fieldtype[f.name] = f
  5242             if f.holds_packets:
  5243                 self.packetfields.append(f)
  5244             
  5245     def dissection_done(self,pkt):
  5246         """DEV: will be called after a dissection is completed"""
  5247         self.post_dissection(pkt)
  5248         self.payload.dissection_done(pkt)
  5249         
  5250     def post_dissection(self, pkt):
  5251         """DEV: is called after the dissection of the whole packet"""
  5252         pass
  5253 
  5254     def get_field(self, fld):
  5255         """DEV: returns the field instance from the name of the field"""
  5256         return self.fieldtype[fld]
  5257         
  5258     def add_payload(self, payload):
  5259         if payload is None:
  5260             return
  5261         elif not isinstance(self.payload, NoPayload):
  5262             self.payload.add_payload(payload)
  5263         else:
  5264             if isinstance(payload, Packet):
  5265                 self.__dict__["payload"] = payload
  5266                 payload.add_underlayer(self)
  5267                 for t in self.aliastypes:
  5268                     if payload.overload_fields.has_key(t):
  5269                         self.overloaded_fields = payload.overload_fields[t]
  5270                         break
  5271             elif type(payload) is str:
  5272                 self.__dict__["payload"] = Raw(load=payload)
  5273             else:
  5274                 raise TypeError("payload must be either 'Packet' or 'str', not [%s]" % repr(payload))
  5275     def remove_payload(self):
  5276         self.payload.remove_underlayer(self)
  5277         self.__dict__["payload"] = NoPayload()
  5278         self.overloaded_fields = {}
  5279     def add_underlayer(self, underlayer):
  5280         self.underlayer = underlayer
  5281     def remove_underlayer(self,other):
  5282         self.underlayer = None
  5283     def copy(self):
  5284         """Returns a deep copy of the instance."""
  5285         clone = self.__class__()
  5286         clone.fields = self.fields.copy()
  5287         for k in clone.fields:
  5288             clone.fields[k]=self.get_field(k).do_copy(clone.fields[k])
  5289         clone.default_fields = self.default_fields.copy()
  5290         clone.overloaded_fields = self.overloaded_fields.copy()
  5291         clone.overload_fields = self.overload_fields.copy()
  5292         clone.underlayer=self.underlayer
  5293         clone.explicit=self.explicit
  5294         clone.post_transforms=self.post_transforms[:]
  5295         clone.__dict__["payload"] = self.payload.copy()
  5296         clone.payload.add_underlayer(clone)
  5297         return clone
  5298 
  5299     def getfieldval(self, attr):
  5300         if attr in self.fields:
  5301             return self.fields[attr]
  5302         if attr in self.overloaded_fields:
  5303             return self.overloaded_fields[attr]
  5304         if attr in self.default_fields:
  5305             return self.default_fields[attr]
  5306         return self.payload.getfieldval(attr)
  5307     
  5308     def getfield_and_val(self, attr):
  5309         if attr in self.fields:
  5310             return self.get_field(attr),self.fields[attr]
  5311         if attr in self.overloaded_fields:
  5312             return self.get_field(attr),self.overloaded_fields[attr]
  5313         if attr in self.default_fields:
  5314             return self.get_field(attr),self.default_fields[attr]
  5315         return self.payload.getfield_and_val(attr)
  5316     
  5317     def __getattr__(self, attr):
  5318         if self.initialized:
  5319             fld,v = self.getfield_and_val(attr)
  5320             if fld is not None:
  5321                 return fld.i2h(self, v)
  5322             return v
  5323         raise AttributeError(attr)
  5324 
  5325     def setfieldval(self, attr, val):
  5326         if self.default_fields.has_key(attr):
  5327             fld = self.get_field(attr)
  5328             if fld is None:
  5329                 any2i = lambda x,y: y
  5330             else:
  5331                 any2i = fld.any2i
  5332             self.fields[attr] = any2i(self, val)
  5333             self.explicit=0
  5334         elif attr == "payload":
  5335             self.remove_payload()
  5336             self.add_payload(val)
  5337         else:
  5338             self.payload.setfieldval(attr,val)
  5339 
  5340     def __setattr__(self, attr, val):
  5341         if self.initialized:
  5342             try:
  5343                 self.setfieldval(attr,val)
  5344             except AttributeError:
  5345                 pass
  5346             else:
  5347                 return
  5348         self.__dict__[attr] = val
  5349 
  5350     def delfieldval(self, attr):
  5351         if self.fields.has_key(attr):
  5352             del(self.fields[attr])
  5353             self.explicit=0 # in case a default value must be explicited
  5354         elif self.default_fields.has_key(attr):
  5355             pass
  5356         elif attr == "payload":
  5357             self.remove_payload()
  5358         else:
  5359             self.payload.delfieldval(attr)
  5360 
  5361     def __delattr__(self, attr):
  5362         if self.initialized:
  5363             try:
  5364                 self.delfieldval(attr)
  5365             except AttributeError:
  5366                 pass
  5367             else:
  5368                 return
  5369         if self.__dict__.has_key(attr):
  5370             del(self.__dict__[attr])
  5371         else:
  5372             raise AttributeError(attr)
  5373             
  5374     def __repr__(self):
  5375         s = ""
  5376         ct = conf.color_theme
  5377         for f in self.fields_desc:
  5378             if isinstance(f, ConditionalField) and not f._evalcond(self):
  5379                 continue
  5380             if f.name in self.fields:
  5381                 val = f.i2repr(self, self.fields[f.name])
  5382             elif f.name in self.overloaded_fields:
  5383                 val =  f.i2repr(self, self.overloaded_fields[f.name])
  5384             else:
  5385                 continue
  5386             if isinstance(f, Emph):
  5387                 ncol = ct.emph_field_name
  5388                 vcol = ct.emph_field_value
  5389             else:
  5390                 ncol = ct.field_name
  5391                 vcol = ct.field_value
  5392 
  5393                 
  5394             s += " %s%s%s" % (ncol(f.name),
  5395                               ct.punct("="),
  5396                               vcol(val))
  5397         return "%s%s %s %s%s%s"% (ct.punct("<"),
  5398                                   ct.layer_name(self.__class__.__name__),
  5399                                   s,
  5400                                   ct.punct("|"),
  5401                                   repr(self.payload),
  5402                                   ct.punct(">"))
  5403     def __str__(self):
  5404         return self.build()
  5405     def __div__(self, other):
  5406         if isinstance(other, Packet):
  5407             cloneA = self.copy()
  5408             cloneB = other.copy()
  5409             cloneA.add_payload(cloneB)
  5410             return cloneA
  5411         elif type(other) is str:
  5412             return self/Raw(load=other)
  5413         else:
  5414             return other.__rdiv__(self)
  5415     def __rdiv__(self, other):
  5416         if type(other) is str:
  5417             return Raw(load=other)/self
  5418         else:
  5419             raise TypeError
  5420     def __mul__(self, other):
  5421         if type(other) is int:
  5422             return  [self]*other
  5423         else:
  5424             raise TypeError
  5425     def __rmul__(self,other):
  5426         return self.__mul__(other)
  5427     
  5428     def __nonzero__(self):
  5429         return True
  5430     def __len__(self):
  5431         return len(self.__str__())
  5432     def do_build(self):
  5433         p=""
  5434         for f in self.fields_desc:
  5435             p = f.addfield(self, p, self.getfieldval(f.name))
  5436         return p
  5437     
  5438     def post_build(self, pkt, pay):
  5439         """DEV: called right after the current layer is build."""
  5440         return pkt+pay
  5441 
  5442     def build_payload(self):
  5443         return self.payload.build(internal=1)
  5444 
  5445     def build(self,internal=0):
  5446         if not self.explicit:
  5447             self = self.__iter__().next()
  5448         pkt = self.do_build()
  5449         for t in self.post_transforms:
  5450             pkt = t(pkt)
  5451         pay = self.build_payload()
  5452         try:
  5453             p = self.post_build(pkt,pay)
  5454         except TypeError:
  5455             log_runtime.error("API changed! post_build() now takes 2 arguments. Compatibility is only assured for a short transition time")
  5456             p = self.post_build(pkt+pay)
  5457         if not internal:
  5458             pad = self.payload.getlayer(Padding) 
  5459             if pad: 
  5460                 p += pad.build()
  5461             p = self.build_done(p)
  5462         return p
  5463 
  5464     def build_done(self, p):
  5465         return self.payload.build_done(p)
  5466 
  5467     def do_build_ps(self):
  5468         p=""
  5469         pl = []
  5470         q=""
  5471         for f in self.fields_desc:
  5472             p = f.addfield(self, p, self.getfieldval(f.name) )
  5473             if type(p) is str:
  5474                 r = p[len(q):]
  5475                 q = p
  5476             else:
  5477                 r = ""
  5478             pl.append( (f, f.i2repr(self,self.getfieldval(f.name)), r) )
  5479             
  5480         pkt,lst = self.payload.build_ps(internal=1)
  5481         p += pkt
  5482         lst.append( (self, pl) )
  5483         
  5484         return p,lst
  5485     
  5486     def build_ps(self,internal=0):
  5487         p,lst = self.do_build_ps()
  5488 #        if not internal:
  5489 #            pkt = self
  5490 #            while pkt.haslayer(Padding):
  5491 #                pkt = pkt.getlayer(Padding)
  5492 #                lst.append( (pkt, [ ("loakjkjd", pkt.load, pkt.load) ] ) )
  5493 #                p += pkt.load
  5494 #                pkt = pkt.payload
  5495         return p,lst
  5496 
  5497 
  5498     def psdump(self, filename=None, **kargs):
  5499         """psdump(filename=None, layer_shift=0, rebuild=1)
  5500 Creates an EPS file describing a packet. If filename is not provided a temporary file is created and gs is called."""
  5501         canvas = self.canvas_dump(**kargs)
  5502         if filename is None:
  5503             fname = "/tmp/scapy.%i"%os.getpid()
  5504             canvas.writeEPSfile(fname)
  5505             os.system("%s '%s.eps' &" % (conf.prog.psreader,fname))
  5506         else:
  5507             canvas.writeEPSfile(filename)
  5508 
  5509     def pdfdump(self, filename=None, **kargs):
  5510         """pdfdump(filename=None, layer_shift=0, rebuild=1)
  5511         Creates a PDF file describing a packet. If filename is not provided a temporary file is created and xpdf is called."""
  5512         canvas = self.canvas_dump(**kargs)
  5513         if filename is None:
  5514             fname = "/tmp/scapy.%i"%os.getpid()
  5515             canvas.writePDFfile(fname)
  5516             os.system("%s '%s.pdf' &" % (conf.prog.pdfreader,fname))
  5517         else:
  5518             canvas.writePDFfile(filename)
  5519 
  5520         
  5521     def canvas_dump(self, layer_shift=0, rebuild=1):
  5522         canvas = pyx.canvas.canvas()
  5523         if rebuild:
  5524             p,t = self.__class__(str(self)).build_ps()
  5525         else:
  5526             p,t = self.build_ps()
  5527         YTXT=len(t)
  5528         for n,l in t:
  5529             YTXT += len(l)
  5530         YTXT = float(YTXT)
  5531         YDUMP=YTXT
  5532 
  5533         XSTART = 1
  5534         XDSTART = 10
  5535         y = 0.0
  5536         yd = 0.0
  5537         xd = 0 
  5538         XMUL= 0.55
  5539         YMUL = 0.4
  5540     
  5541         backcolor=colgen(0.6, 0.8, 1.0, trans=pyx.color.rgb)
  5542         forecolor=colgen(0.2, 0.5, 0.8, trans=pyx.color.rgb)
  5543 #        backcolor=makecol(0.376, 0.729, 0.525, 1.0)
  5544         
  5545         
  5546         def hexstr(x):
  5547             s = []
  5548             for c in x:
  5549                 s.append("%02x" % ord(c))
  5550             return " ".join(s)
  5551 
  5552                 
  5553         def make_dump_txt(x,y,txt):
  5554             return pyx.text.text(XDSTART+x*XMUL, (YDUMP-y)*YMUL, r"\tt{%s}"%hexstr(txt), [pyx.text.size.Large])
  5555 
  5556         def make_box(o):
  5557             return pyx.box.rect(o.left(), o.bottom(), o.width(), o.height(), relcenter=(0.5,0.5))
  5558 
  5559         def make_frame(lst):
  5560             if len(lst) == 1:
  5561                 b = lst[0].bbox()
  5562                 b.enlarge(pyx.unit.u_pt)
  5563                 return b.path()
  5564             else:
  5565                 fb = lst[0].bbox()
  5566                 fb.enlarge(pyx.unit.u_pt)
  5567                 lb = lst[-1].bbox()
  5568                 lb.enlarge(pyx.unit.u_pt)
  5569                 if len(lst) == 2 and fb.left() > lb.right():
  5570                     return pyx.path.path(pyx.path.moveto(fb.right(), fb.top()),
  5571                                          pyx.path.lineto(fb.left(), fb.top()),
  5572                                          pyx.path.lineto(fb.left(), fb.bottom()),
  5573                                          pyx.path.lineto(fb.right(), fb.bottom()),
  5574                                          pyx.path.moveto(lb.left(), lb.top()),
  5575                                          pyx.path.lineto(lb.right(), lb.top()),
  5576                                          pyx.path.lineto(lb.right(), lb.bottom()),
  5577                                          pyx.path.lineto(lb.left(), lb.bottom()))
  5578                 else:
  5579                     # XXX
  5580                     gb = lst[1].bbox()
  5581                     if gb != lb:
  5582                         gb.enlarge(pyx.unit.u_pt)
  5583                     kb = lst[-2].bbox()
  5584                     if kb != gb and kb != lb:
  5585                         kb.enlarge(pyx.unit.u_pt)
  5586                     return pyx.path.path(pyx.path.moveto(fb.left(), fb.top()),
  5587                                          pyx.path.lineto(fb.right(), fb.top()),
  5588                                          pyx.path.lineto(fb.right(), kb.bottom()),
  5589                                          pyx.path.lineto(lb.right(), kb.bottom()),
  5590                                          pyx.path.lineto(lb.right(), lb.bottom()),
  5591                                          pyx.path.lineto(lb.left(), lb.bottom()),
  5592                                          pyx.path.lineto(lb.left(), gb.top()),
  5593                                          pyx.path.lineto(fb.left(), gb.top()),
  5594                                          pyx.path.closepath(),)
  5595                                          
  5596 
  5597         def make_dump(s, shift=0, y=0, col=None, bkcol=None, larg=16):
  5598             c = pyx.canvas.canvas()
  5599             tlist = []
  5600             while s:
  5601                 dmp,s = s[:larg-shift],s[larg-shift:]
  5602                 txt = make_dump_txt(shift, y, dmp)
  5603                 tlist.append(txt)
  5604                 shift += len(dmp)
  5605                 if shift >= 16:
  5606                     shift = 0
  5607                     y += 1
  5608             if col is None:
  5609                 col = pyx.color.rgb.red
  5610             if bkcol is None:
  5611                 col = pyx.color.rgb.white
  5612             c.stroke(make_frame(tlist),[col,pyx.deco.filled([bkcol]),pyx.style.linewidth.Thick])
  5613             for txt in tlist:
  5614                 c.insert(txt)
  5615             return c, tlist[-1].bbox(), shift, y
  5616                             
  5617 
  5618         last_shift,last_y=0,0.0
  5619         while t:
  5620             bkcol = backcolor.next()
  5621             proto,fields = t.pop()
  5622             y += 0.5
  5623             pt = pyx.text.text(XSTART, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % proto.name, [ pyx.text.size.Large])
  5624             y += 1
  5625             ptbb=pt.bbox()
  5626             ptbb.enlarge(pyx.unit.u_pt*2)
  5627             canvas.stroke(ptbb.path(),[pyx.color.rgb.black, pyx.deco.filled([bkcol])])
  5628             canvas.insert(pt)
  5629             for fname, fval, fdump in fields:
  5630                 col = forecolor.next()
  5631                 ft = pyx.text.text(XSTART, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(fname.name))
  5632                 if fval is not None:
  5633                     if len(fval) > 18:
  5634                         fval = fval[:18]+"[...]"
  5635                 else:
  5636                     fval=""
  5637                 vt = pyx.text.text(XSTART+3, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(fval))
  5638                 y += 1.0
  5639                 if fdump:
  5640                     dt,target,last_shift,last_y = make_dump(fdump, last_shift, last_y, col, bkcol)
  5641 
  5642                     dtb = dt.bbox()
  5643                     dtb=target
  5644                     vtb = vt.bbox()
  5645                     bxvt = make_box(vtb)
  5646                     bxdt = make_box(dtb)
  5647                     dtb.enlarge(pyx.unit.u_pt)
  5648                     try:
  5649                         if yd < 0:
  5650                             cnx = pyx.connector.curve(bxvt,bxdt,absangle1=0, absangle2=-90)
  5651                         else:
  5652                             cnx = pyx.connector.curve(bxvt,bxdt,absangle1=0, absangle2=90)
  5653                     except:
  5654                         pass
  5655                     else:
  5656                         canvas.stroke(cnx,[pyx.style.linewidth.thin,pyx.deco.earrow.small,col])
  5657                         
  5658                     canvas.insert(dt)
  5659                 
  5660                 canvas.insert(ft)
  5661                 canvas.insert(vt)
  5662             last_y += layer_shift
  5663     
  5664         return canvas
  5665 
  5666 
  5667 
  5668     def extract_padding(self, s):
  5669         """DEV: to be overloaded to extract current layer's padding. Return a couple of strings (actual layer, padding)"""
  5670         return s,None
  5671 
  5672     def post_dissect(self, s):
  5673         """DEV: is called right after the current layer has been dissected"""
  5674         return s
  5675 
  5676     def pre_dissect(self, s):
  5677         """DEV: is called right before the current layer is dissected"""
  5678         return s
  5679 
  5680     def do_dissect(self, s):
  5681         flist = self.fields_desc[:]
  5682         flist.reverse()
  5683         while s and flist:
  5684             f = flist.pop()
  5685             s,fval = f.getfield(self, s)
  5686             self.fields[f.name] = fval
  5687             
  5688         return s
  5689 
  5690     def do_dissect_payload(self, s):
  5691         if s:
  5692             cls = self.guess_payload_class(s)
  5693             try:
  5694                 p = cls(s, _internal=1, _underlayer=self)
  5695             except KeyboardInterrupt:
  5696                 raise
  5697             except:
  5698                 if conf.debug_dissector:
  5699                     if isinstance(cls,type) and issubclass(cls,Packet):
  5700                         log_runtime.error("%s dissector failed" % cls.name)
  5701                     else:
  5702                         log_runtime.error("%s.guess_payload_class() returned [%s]" % (self.__class__.__name__,repr(cls)))
  5703                     if cls is not None:
  5704                         raise
  5705                 p = Raw(s, _internal=1, _underlayer=self)
  5706             self.add_payload(p)
  5707 
  5708     def dissect(self, s):
  5709         s = self.pre_dissect(s)
  5710 
  5711         s = self.do_dissect(s)
  5712 
  5713         s = self.post_dissect(s)
  5714             
  5715         payl,pad = self.extract_padding(s)
  5716         self.do_dissect_payload(payl)
  5717         if pad and conf.padding:
  5718             self.add_payload(Padding(pad))
  5719 
  5720 
  5721     def guess_payload_class(self, payload):
  5722         """DEV: Guesses the next payload class from layer bonds. Can be overloaded to use a different mechanism."""
  5723         for t in self.aliastypes:
  5724             for fval, cls in t.payload_guess:
  5725                 ok = 1
  5726                 for k in fval.keys():
  5727                     if not hasattr(self, k) or fval[k] != self.getfieldval(k):
  5728                         ok = 0
  5729                         break
  5730                 if ok:
  5731                     return cls
  5732         return self.default_payload_class(payload)
  5733     
  5734     def default_payload_class(self, payload):
  5735         """DEV: Returns the default payload class if nothing has been found by the guess_payload_class() method."""
  5736         return Raw
  5737 
  5738     def hide_defaults(self):
  5739         """Removes fields' values that are the same as default values."""
  5740         for k in self.fields.keys():
  5741             if self.default_fields.has_key(k):
  5742                 if self.default_fields[k] == self.fields[k]:
  5743                     del(self.fields[k])
  5744         self.payload.hide_defaults()
  5745             
  5746     def clone_with(self, payload=None, **kargs):
  5747         pkt = self.__class__()
  5748         pkt.explicit = 1
  5749         pkt.fields = kargs
  5750         pkt.time = self.time
  5751         pkt.underlayer = self.underlayer
  5752         pkt.overload_fields = self.overload_fields.copy()
  5753         pkt.post_transforms = self.post_transforms
  5754         if payload is not None:
  5755             pkt.add_payload(payload)
  5756         return pkt
  5757         
  5758 
  5759     def __iter__(self):
  5760         def loop(todo, done, self=self):
  5761             if todo:
  5762                 eltname = todo.pop()
  5763                 elt = self.getfieldval(eltname)
  5764                 if not isinstance(elt, Gen):
  5765                     if self.get_field(eltname).islist:
  5766                         elt = SetGen([elt])
  5767                     else:
  5768                         elt = SetGen(elt)
  5769                 for e in elt:
  5770                     done[eltname]=e
  5771                     for x in loop(todo[:], done):
  5772                         yield x
  5773             else:
  5774                 if isinstance(self.payload,NoPayload):
  5775                     payloads = [None]
  5776                 else:
  5777                     payloads = self.payload
  5778                 for payl in payloads:
  5779                     done2=done.copy()
  5780                     for k in done2:
  5781                         if isinstance(done2[k], VolatileValue):
  5782                             done2[k] = done2[k]._fix()
  5783                     pkt = self.clone_with(payload=payl, **done2)
  5784                     yield pkt
  5785 
  5786         if self.explicit:
  5787             todo = []
  5788             done = self.fields
  5789         else:
  5790             todo = [ k for (k,v) in itertools.chain(self.default_fields.iteritems(),
  5791                                                     self.overloaded_fields.iteritems())
  5792                      if isinstance(v, VolatileValue) ] + self.fields.keys()
  5793             done = {}
  5794         return loop(todo, done)
  5795 
  5796     def __gt__(self, other):
  5797         """True if other is an answer from self (self ==> other)."""
  5798         if isinstance(other, Packet):
  5799             return other < self
  5800         elif type(other) is str:
  5801             return 1
  5802         else:
  5803             raise TypeError((self, other))
  5804     def __lt__(self, other):
  5805         """True if self is an answer from other (other ==> self)."""
  5806         if isinstance(other, Packet):
  5807             return self.answers(other)
  5808         elif type(other) is str:
  5809             return 1
  5810         else:
  5811             raise TypeError((self, other))
  5812 
  5813     def __eq__(self, other):
  5814         if not isinstance(other, self.__class__):
  5815             return False
  5816         for f in self.fields_desc:
  5817             if f not in other.fields_desc:
  5818                 return False
  5819             if self.getfieldval(f.name) != other.getfieldval(f.name):
  5820                 return False
  5821         return self.payload == other.payload
  5822 
  5823     def __ne__(self, other):
  5824         return not self.__eq__(other)
  5825 
  5826     def hashret(self):
  5827         """DEV: returns a string that has the same value for a request and its answer."""
  5828         return self.payload.hashret()
  5829     def answers(self, other):
  5830         """DEV: true if self is an answer from other"""
  5831         if other.__class__ == self.__class__:
  5832             return self.payload.answers(other.payload)
  5833         return 0
  5834 
  5835     def haslayer(self, cls):
  5836         """true if self has a layer that is an instance of cls. Superseded by "cls in self" syntax."""
  5837         if self.__class__ == cls or self.__class__.__name__ == cls:
  5838             return 1
  5839         for f in self.packetfields:
  5840             fvalue_gen = self.getfieldval(f.name)
  5841             if fvalue_gen is None:
  5842                 continue
  5843             if not f.islist:
  5844                 fvalue_gen = SetGen(fvalue_gen,_iterpacket=0)
  5845             for fvalue in fvalue_gen:
  5846                 if isinstance(fvalue, Packet):
  5847                     ret = fvalue.haslayer(cls)
  5848                     if ret:
  5849                         return ret
  5850         return self.payload.haslayer(cls)
  5851     def getlayer(self, cls, nb=1, _track=None):
  5852         """Return the nb^th layer that is an instance of cls."""
  5853         if type(cls) is str and "." in cls:
  5854             ccls,fld = cls.split(".",1)
  5855         else:
  5856             ccls,fld = cls,None
  5857         if self.__class__ == cls or self.__class__.name == ccls:
  5858             if nb == 1:
  5859                 if fld is None:
  5860                     return self
  5861                 else:
  5862                     return self.getfieldval(fld)
  5863             else:
  5864                 nb -=1
  5865         for f in self.packetfields:
  5866             fvalue_gen = self.getfieldval(f.name)
  5867             if fvalue_gen is None:
  5868                 continue
  5869             if not f.islist:
  5870                 fvalue_gen = SetGen(fvalue_gen,_iterpacket=0)
  5871             for fvalue in fvalue_gen:
  5872                 if isinstance(fvalue, Packet):
  5873                     track=[]
  5874                     ret = fvalue.getlayer(cls, nb, _track=track)
  5875                     if ret is not None:
  5876                         return ret
  5877                     nb = track[0]
  5878         return self.payload.getlayer(cls,nb,_track=_track)
  5879 
  5880     def __getitem__(self, cls):
  5881         if type(cls) is slice:
  5882             if cls.stop:
  5883                 ret = self.getlayer(cls.start, cls.stop)
  5884             else:
  5885                 ret = self.getlayer(cls.start)
  5886             if ret is None and cls.step is not None:
  5887                 ret = cls.step
  5888             return ret
  5889         else:
  5890             return self.getlayer(cls)
  5891         
  5892     def __contains__(self, cls):
  5893         """"cls in self" returns true if self has a layer which is an instance of cls."""
  5894         return self.haslayer(cls)
  5895         
  5896     
  5897 
  5898     def display(self,*args,**kargs):  # Deprecated. Use show()
  5899         """Deprecated. Use show() method."""
  5900         self.show(*args,**kargs)
  5901     def show(self, indent=3, lvl="", label_lvl=""):
  5902         """Prints a hierarchical view of the packet. "indent" gives the size of indentation for each layer."""
  5903         ct = conf.color_theme
  5904         print "%s%s %s %s" % (label_lvl,
  5905                               ct.punct("###["),
  5906                               ct.layer_name(self.name),
  5907                               ct.punct("]###"))
  5908         for f in self.fields_desc:
  5909             if isinstance(f, ConditionalField) and not f._evalcond(self):
  5910                 continue
  5911             if isinstance(f, Emph):
  5912                 ncol = ct.emph_field_name
  5913                 vcol = ct.emph_field_value
  5914             else:
  5915                 ncol = ct.field_name
  5916                 vcol = ct.field_value
  5917             fvalue = self.getfieldval(f.name)
  5918             if isinstance(fvalue, Packet) or (f.islist and f.holds_packets and type(fvalue) is list):
  5919                 print "%s  \\%-10s\\" % (label_lvl+lvl, ncol(f.name))
  5920                 fvalue_gen = SetGen(fvalue,_iterpacket=0)
  5921                 for fvalue in fvalue_gen:
  5922                     fvalue.show(indent=indent, label_lvl=label_lvl+lvl+"   |")
  5923             else:
  5924                 print "%s  %-10s%s %s" % (label_lvl+lvl,
  5925                                           ncol(f.name),
  5926                                           ct.punct("="),
  5927                                           vcol(f.i2repr(self,fvalue)))
  5928         self.payload.show(indent=indent, lvl=lvl+(" "*indent*self.show_indent), label_lvl=label_lvl)
  5929     def show2(self):
  5930         """Prints a hierarchical view of an assembled version of the packet, so that automatic fields are calculated (checksums, etc.)"""
  5931         self.__class__(str(self)).show()
  5932 
  5933     def sprintf(self, fmt, relax=1):
  5934         """sprintf(format, [relax=1]) -> str
  5935 where format is a string that can include directives. A directive begins and
  5936 ends by % and has the following format %[fmt[r],][cls[:nb].]field%.
  5937 
  5938 fmt is a classic printf directive, "r" can be appended for raw substitution
  5939 (ex: IP.flags=0x18 instead of SA), nb is the number of the layer we want
  5940 (ex: for IP/IP packets, IP:2.src is the src of the upper IP layer).
  5941 Special case : "%.time%" is the creation time.
  5942 Ex : p.sprintf("%.time% %-15s,IP.src% -> %-15s,IP.dst% %IP.chksum% "
  5943                "%03xr,IP.proto% %r,TCP.flags%")
  5944 
  5945 Moreover, the format string can include conditionnal statements. A conditionnal
  5946 statement looks like : {layer:string} where layer is a layer name, and string
  5947 is the string to insert in place of the condition if it is true, i.e. if layer
  5948 is present. If layer is preceded by a "!", the result si inverted. Conditions
  5949 can be imbricated. A valid statement can be :
  5950   p.sprintf("This is a{TCP: TCP}{UDP: UDP}{ICMP:n ICMP} packet")
  5951   p.sprintf("{IP:%IP.dst% {ICMP:%ICMP.type%}{TCP:%TCP.dport%}}")
  5952 
  5953 A side effect is that, to obtain "{" and "}" characters, you must use
  5954 "%(" and "%)".
  5955 """
  5956 
  5957         escape = { "%": "%",
  5958                    "(": "{",
  5959                    ")": "}" }
  5960 
  5961 
  5962         # Evaluate conditions 
  5963         while "{" in fmt:
  5964             i = fmt.rindex("{")
  5965             j = fmt[i+1:].index("}")
  5966             cond = fmt[i+1:i+j+1]
  5967             k = cond.find(":")
  5968             if k < 0:
  5969                 raise Scapy_Exception("Bad condition in format string: [%s] (read sprintf doc!)"%cond)
  5970             cond,format = cond[:k],cond[k+1:]
  5971             res = False
  5972             if cond[0] == "!":
  5973                 res = True
  5974                 cond = cond[1:]
  5975             if self.haslayer(cond):
  5976                 res = not res
  5977             if not res:
  5978                 format = ""
  5979             fmt = fmt[:i]+format+fmt[i+j+2:]
  5980 
  5981         # Evaluate directives
  5982         s = ""
  5983         while "%" in fmt:
  5984             i = fmt.index("%")
  5985             s += fmt[:i]
  5986             fmt = fmt[i+1:]
  5987             if fmt and fmt[0] in escape:
  5988                 s += escape[fmt[0]]
  5989                 fmt = fmt[1:]
  5990                 continue
  5991             try:
  5992                 i = fmt.index("%")
  5993                 sfclsfld = fmt[:i]
  5994                 fclsfld = sfclsfld.split(",")
  5995                 if len(fclsfld) == 1:
  5996                     f = "s"
  5997                     clsfld = fclsfld[0]
  5998                 elif len(fclsfld) == 2:
  5999                     f,clsfld = fclsfld
  6000                 else:
  6001                     raise Scapy_Exception
  6002                 if "." in clsfld:
  6003                     cls,fld = clsfld.split(".")
  6004                 else:
  6005                     cls = self.__class__.__name__
  6006                     fld = clsfld
  6007                 num = 1
  6008                 if ":" in cls:
  6009                     cls,num = cls.split(":")
  6010                     num = int(num)
  6011                 fmt = fmt[i+1:]
  6012             except:
  6013                 raise Scapy_Exception("Bad format string [%%%s%s]" % (fmt[:25], fmt[25:] and "..."))
  6014             else:
  6015                 if fld == "time":
  6016                     val = time.strftime("%H:%M:%S.%%06i", time.localtime(self.time)) % int((self.time-int(self.time))*1000000)
  6017                 elif cls == self.__class__.__name__ and hasattr(self, fld):
  6018                     if num > 1:
  6019                         val = self.payload.sprintf("%%%s,%s:%s.%s%%" % (f,cls,num-1,fld), relax)
  6020                         f = "s"
  6021                     elif f[-1] == "r":  # Raw field value
  6022                         val = getattr(self,fld)
  6023                         f = f[:-1]
  6024                         if not f:
  6025                             f = "s"
  6026                     else:
  6027                         val = getattr(self,fld)
  6028                         if fld in self.fieldtype:
  6029                             val = self.fieldtype[fld].i2repr(self,val)
  6030                 else:
  6031                     val = self.payload.sprintf("%%%s%%" % sfclsfld, relax)
  6032                     f = "s"
  6033                 s += ("%"+f) % val
  6034             
  6035         s += fmt
  6036         return s
  6037 
  6038     def mysummary(self):
  6039         """DEV: can be overloaded to return a string that summarizes the layer.
  6040            Only one mysummary() is used in a whole packet summary: the one of the upper layer,
  6041            except if a mysummary() also returns (as a couple) a list of layers whose
  6042            mysummary() must be called if they are present."""
  6043         return ""
  6044 
  6045     def summary(self, intern=0):
  6046         """Prints a one line summary of a packet."""
  6047         found,s,needed = self.payload.summary(intern=1)
  6048         if s:
  6049             s = " / "+s
  6050         ret = ""
  6051         if not found or self.__class__ in needed:
  6052             ret = self.mysummary()
  6053             if type(ret) is tuple:
  6054                 ret,n = ret
  6055                 needed += n
  6056         if ret or needed:
  6057             found = 1
  6058         if not ret:
  6059             ret = self.__class__.__name__
  6060         ret = "%s%s" % (ret,s)
  6061         if intern:
  6062             return found,ret,needed
  6063         else:
  6064             return ret
  6065     
  6066     def lastlayer(self,layer=None):
  6067         """Returns the uppest layer of the packet"""
  6068         return self.payload.lastlayer(self)
  6069 
  6070     def decode_payload_as(self,cls):
  6071         """Reassembles the payload and decode it using another packet class"""
  6072         s = str(self.payload)
  6073         self.payload = cls(s)
  6074 
  6075     def libnet(self):
  6076         """Not ready yet. Should give the necessary C code that interfaces with libnet to recreate the packet"""
  6077         print "libnet_build_%s(" % self.__class__.name.lower()
  6078         det = self.__class__(str(self))
  6079         for f in self.fields_desc:
  6080             val = det.getfieldval(f.name)
  6081             if val is None:
  6082                 val = 0
  6083             elif type(val) is int:
  6084                 val = str(val)
  6085             else:
  6086                 val = '"%s"' % str(val)
  6087             print "\t%s, \t\t/* %s */" % (val,f.name)
  6088         print ");"
  6089     def command(self):
  6090         """Returns a string representing the command you have to type to obtain the same packet"""
  6091         f = []
  6092         for fn,fv in self.fields.items():
  6093             fld = self.get_field(fn)
  6094             if isinstance(fv, Packet):
  6095                 fv = fv.command()
  6096             elif fld.islist and fld.holds_packets and type(fv) is list:
  6097                 fv = "[%s]" % ",".join( map(Packet.command, fv))
  6098             else:
  6099                 fv = repr(fv)
  6100             f.append("%s=%s" % (fn, fv))
  6101         c = "%s(%s)" % (self.__class__.__name__, ", ".join(f))
  6102         pc = self.payload.command()
  6103         if pc:
  6104             c += "/"+pc
  6105         return c                    
  6106 
  6107 
  6108 class ASN1_Packet(Packet):
  6109     ASN1_root = None
  6110     ASN1_codec = None    
  6111     def init_fields(self):
  6112         flist = self.ASN1_root.get_fields_list()
  6113         self.do_init_fields(flist)
  6114         self.fields_desc = flist    
  6115     def do_build(self):
  6116         return self.ASN1_root.build(self)    
  6117     def do_dissect(self, x):
  6118         return self.ASN1_root.dissect(self, x)
  6119         
  6120 
  6121 class NoPayload(Packet,object):
  6122     def __new__(cls, *args, **kargs):
  6123         singl = cls.__dict__.get("__singl__")
  6124         if singl is None:
  6125             cls.__singl__ = singl = object.__new__(cls)
  6126             Packet.__init__(singl, *args, **kargs)
  6127         return singl
  6128     def __init__(self, *args, **kargs):
  6129         pass
  6130     def dissection_done(self,pkt):
  6131         return
  6132     def add_payload(self, payload):
  6133         raise Scapy_Exception("Can't add payload to NoPayload instance")
  6134     def remove_payload(self):
  6135         pass
  6136     def add_underlayer(self,underlayer):
  6137         pass
  6138     def remove_underlayer(self,other):
  6139         pass
  6140     def copy(self):
  6141         return self
  6142     def __repr__(self):
  6143         return ""
  6144     def __str__(self):
  6145         return ""
  6146     def __nonzero__(self):
  6147         return False
  6148     def build(self, internal=0):
  6149         return ""    
  6150     def build_done(self, p):
  6151         return p
  6152     def build_ps(self, internal=0):
  6153         return "",[]
  6154     def getfieldval(self, attr):
  6155         raise AttributeError(attr)
  6156     def getfield_and_val(self, attr):
  6157         raise AttributeError(attr)
  6158     def setfieldval(self, attr, val):
  6159         raise AttributeError(attr)
  6160     def delfieldval(self, attr):
  6161         raise AttributeError(attr)
  6162     def __getattr__(self, attr):
  6163         if attr in self.__dict__:
  6164             return self.__dict__[attr]
  6165         elif attr in self.__class__.__dict__:
  6166             return self.__class__.__dict__[attr]
  6167         else:
  6168             raise AttributeError, attr
  6169     def hide_defaults(self):
  6170         pass
  6171     def __iter__(self):
  6172         return iter([])
  6173     def __eq__(self, other):
  6174         if isinstance(other, NoPayload):
  6175             return True
  6176         return False
  6177     def hashret(self):
  6178         return ""
  6179     def answers(self, other):
  6180         return isinstance(other, NoPayload) or isinstance(other, Padding)
  6181     def haslayer(self, cls):
  6182         return 0
  6183     def getlayer(self, cls, nb=1, _track=None):
  6184         if _track is not None:
  6185             _track.append(nb)
  6186         return None
  6187     def show(self, indent=3, lvl="", label_lvl=""):
  6188         pass
  6189     def sprintf(self, fmt, relax):
  6190         if relax:
  6191             return "??"
  6192         else:
  6193             raise Scapy_Exception("Format not found [%s]"%fmt)
  6194     def summary(self, intern=0):
  6195         return 0,"",[]
  6196     def lastlayer(self,layer):
  6197         return layer
  6198     def command(self):
  6199         return ""
  6200     
  6201 
  6202 ####################
  6203 ## packet classes ##
  6204 ####################
  6205     
  6206             
  6207 class Raw(Packet):
  6208     name = "Raw"
  6209     fields_desc = [ StrField("load", "") ]
  6210     def answers(self, other):
  6211         return 1
  6212 #        s = str(other)
  6213 #        t = self.load
  6214 #        l = min(len(s), len(t))
  6215 #        return  s[:l] == t[:l]
  6216         
  6217 class Padding(Raw):
  6218     name = "Padding"
  6219     def build(self, internal=0):
  6220         if internal:
  6221             return ""
  6222         else:
  6223             return Raw.build(self)
  6224 
  6225 class Ether(Packet):
  6226     name = "Ethernet"
  6227     fields_desc = [ DestMACField("dst"),
  6228                     SourceMACField("src"),
  6229                     XShortEnumField("type", 0x0000, ETHER_TYPES) ]
  6230     def hashret(self):
  6231         return struct.pack("H",self.type)+self.payload.hashret()
  6232     def answers(self, other):
  6233         if isinstance(other,Ether):
  6234             if self.type == other.type:
  6235                 return self.payload.answers(other.payload)
  6236         return 0
  6237     def mysummary(self):
  6238         return self.sprintf("%src% > %dst% (%type%)")
  6239 
  6240 class PPPoE(Packet):
  6241     name = "PPP over Ethernet"
  6242     fields_desc = [ BitField("version", 1, 4),
  6243                     BitField("type", 1, 4),
  6244                     ByteEnumField("code", 0, {0:"Session"}),
  6245                     XShortField("sessionid", 0x0),
  6246                     ShortField("len", None) ]
  6247 
  6248     def post_build(self, p, pay):
  6249         p += pay
  6250         if self.len is None:
  6251             l = len(p)-6
  6252             p = p[:4]+struct.pack("!H", l)+p[6:]
  6253         return p
  6254 
  6255 class PPPoED(PPPoE):
  6256     name = "PPP over Ethernet Discovery"
  6257     fields_desc = [ BitField("version", 1, 4),
  6258                     BitField("type", 1, 4),
  6259                     ByteEnumField("code", 0x09, {0x09:"PADI",0x07:"PADO",0x19:"PADR",0x65:"PADS",0xa7:"PADT"}),
  6260                     XShortField("sessionid", 0x0),
  6261                     ShortField("len", None) ]
  6262 
  6263 class Dot3(Packet):
  6264     name = "802.3"
  6265     fields_desc = [ MACField("dst", ETHER_BROADCAST),
  6266                     MACField("src", ETHER_ANY),
  6267                     LenField("len", None, "H") ]
  6268     def extract_padding(self,s):
  6269         l = self.len
  6270         return s[:l],s[l:]
  6271     def answers(self, other):
  6272         if isinstance(other,Dot3):
  6273             return self.payload.answers(other.payload)
  6274         return 0
  6275     def mysummary(self):
  6276         return "802.3 %s > %s" % (self.src, self.dst)
  6277 
  6278 
  6279 class LLC(Packet):
  6280     name = "LLC"
  6281     fields_desc = [ XByteField("dsap", 0x00),
  6282                     XByteField("ssap", 0x00),
  6283                     ByteField("ctrl", 0) ]
  6284 
  6285 
  6286 class CookedLinux(Packet):
  6287     name = "cooked linux"
  6288     fields_desc = [ ShortEnumField("pkttype",0, {0: "unicast",
  6289                                                  4:"sent-by-us"}), #XXX incomplete
  6290                     XShortField("lladdrtype",512),
  6291                     ShortField("lladdrlen",0),
  6292                     StrFixedLenField("src","",8),
  6293                     XShortEnumField("proto",0x800,ETHER_TYPES) ]
  6294                     
  6295                                    
  6296 
  6297 class SNAP(Packet):
  6298     name = "SNAP"
  6299     fields_desc = [ X3BytesField("OUI",0x000000),
  6300                     XShortEnumField("code", 0x000, ETHER_TYPES) ]
  6301 
  6302 
  6303 class Dot1Q(Packet):
  6304     name = "802.1Q"
  6305     aliastypes = [ Ether ]
  6306     fields_desc =  [ BitField("prio", 0, 3),
  6307                      BitField("id", 0, 1),
  6308                      BitField("vlan", 1, 12),
  6309                      XShortEnumField("type", 0x0000, ETHER_TYPES) ]
  6310     def answers(self, other):
  6311         if isinstance(other,Dot1Q):
  6312             if ( (self.type == other.type) and
  6313                  (self.vlan == other.vlan) ):
  6314                 return self.payload.answers(other.payload)
  6315         else:
  6316             return self.payload.answers(other)
  6317         return 0
  6318     def default_payload_class(self, pay):
  6319         if self.type <= 1500:
  6320             return LLC
  6321         return Raw
  6322     def extract_padding(self,s):
  6323         if self.type <= 1500:
  6324             return s[:self.type],s[self.type:]
  6325         return s,None
  6326     def mysummary(self):
  6327         if isinstance(self.underlayer, Ether):
  6328             return self.underlayer.sprintf("802.1q %Ether.src% > %Ether.dst% (%Dot1Q.type%) vlan %Dot1Q.vlan%")
  6329         else:
  6330             return self.sprintf("802.1q (%Dot1Q.type%) vlan %Dot1Q.vlan%")
  6331 
  6332             
  6333 
  6334 
  6335 class RadioTap(Packet):
  6336     name = "RadioTap dummy"
  6337     fields_desc = [ ByteField('version', 0),
  6338                     ByteField('pad', 0),
  6339                     FieldLenField('len', None, 'notdecoded', '@H', adjust=lambda pkt,x:x+8),
  6340                     FlagsField('present', None, -32, ['TSFT','Flags','Rate','Channel','FHSS','dBm_AntSignal',
  6341                                                      'dBm_AntNoise','Lock_Quality','TX_Attenuation','dB_TX_Attenuation',
  6342                                                       'dBm_TX_Power', 'Antenna', 'dB_AntSignal', 'dB_AntNoise',
  6343                                                      'b14', 'b15','b16','b17','b18','b19','b20','b21','b22','b23',
  6344                                                      'b24','b25','b26','b27','b28','b29','b30','Ext']),
  6345                     StrLenField('notdecoded', "", length_from= lambda pkt:pkt.len-8) ]
  6346 
  6347 class STP(Packet):
  6348     name = "Spanning Tree Protocol"
  6349     fields_desc = [ ShortField("proto", 0),
  6350                     ByteField("version", 0),
  6351                     ByteField("bpdutype", 0),
  6352                     ByteField("bpduflags", 0),
  6353                     ShortField("rootid", 0),
  6354                     MACField("rootmac", ETHER_ANY),
  6355                     IntField("pathcost", 0),
  6356                     ShortField("bridgeid", 0),
  6357                     MACField("bridgemac", ETHER_ANY),
  6358                     ShortField("portid", 0),
  6359                     BCDFloatField("age", 1),
  6360                     BCDFloatField("maxage", 20),
  6361                     BCDFloatField("hellotime", 2),
  6362                     BCDFloatField("fwddelay", 15) ]
  6363 
  6364 
  6365 class EAPOL(Packet):
  6366     name = "EAPOL"
  6367     fields_desc = [ ByteField("version", 1),
  6368                     ByteEnumField("type", 0, ["EAP_PACKET", "START", "LOGOFF", "KEY", "ASF"]),
  6369                     LenField("len", None, "H") ]
  6370     
  6371     EAP_PACKET= 0
  6372     START = 1
  6373     LOGOFF = 2
  6374     KEY = 3
  6375     ASF = 4
  6376     def extract_padding(self, s):
  6377         l = self.len
  6378         return s[:l],s[l:]
  6379     def hashret(self):
  6380         return chr(self.type)+self.payload.hashret()
  6381     def answers(self, other):
  6382         if isinstance(other,EAPOL):
  6383             if ( (self.type == self.EAP_PACKET) and
  6384                  (other.type == self.EAP_PACKET) ):
  6385                 return self.payload.answers(other.payload)
  6386         return 0
  6387     def mysummary(self):
  6388         return self.sprintf("EAPOL %EAPOL.type%")
  6389              
  6390 
  6391 class EAP(Packet):
  6392     name = "EAP"
  6393     fields_desc = [ ByteEnumField("code", 4, {1:"REQUEST",2:"RESPONSE",3:"SUCCESS",4:"FAILURE"}),
  6394                     ByteField("id", 0),
  6395                     ShortField("len",None),
  6396                     ConditionalField(ByteEnumField("type",0, {1:"ID",4:"MD5"}), lambda pkt:pkt.code not in [EAP.SUCCESS, EAP.FAILURE])
  6397 
  6398                                      ]
  6399     
  6400     REQUEST = 1
  6401     RESPONSE = 2
  6402     SUCCESS = 3
  6403     FAILURE = 4
  6404     TYPE_ID = 1
  6405     TYPE_MD5 = 4
  6406     def answers(self, other):
  6407         if isinstance(other,EAP):
  6408             if self.code == self.REQUEST:
  6409                 return 0
  6410             elif self.code == self.RESPONSE:
  6411                 if ( (other.code == self.REQUEST) and
  6412                      (other.type == self.type) ):
  6413                     return 1
  6414             elif other.code == self.RESPONSE:
  6415                 return 1
  6416         return 0
  6417     
  6418     def post_build(self, p, pay):
  6419         if self.len is None:
  6420             l = len(p)+len(pay)
  6421             p = p[:2]+chr((l>>8)&0xff)+chr(l&0xff)+p[4:]
  6422         return p+pay
  6423              
  6424 
  6425 class ARP(Packet):
  6426     name = "ARP"
  6427     fields_desc = [ XShortField("hwtype", 0x0001),
  6428                     XShortEnumField("ptype",  0x0800, ETHER_TYPES),
  6429                     ByteField("hwlen", 6),
  6430                     ByteField("plen", 4),
  6431                     ShortEnumField("op", 1, {"who-has":1, "is-at":2, "RARP-req":3, "RARP-rep":4, "Dyn-RARP-req":5, "Dyn-RAR-rep":6, "Dyn-RARP-err":7, "InARP-req":8, "InARP-rep":9}),
  6432                     ARPSourceMACField("hwsrc"),
  6433                     SourceIPField("psrc","pdst"),
  6434                     MACField("hwdst", ETHER_ANY),
  6435                     IPField("pdst", "0.0.0.0") ]
  6436     who_has = 1
  6437     is_at = 2
  6438     def answers(self, other):
  6439         if isinstance(other,ARP):
  6440             if ( (self.op == self.is_at) and
  6441                  (other.op == self.who_has) and
  6442                  (self.psrc == other.pdst) ):
  6443                 return 1
  6444         return 0
  6445     def extract_padding(self, s):
  6446         return "",s
  6447     def mysummary(self):
  6448         if self.op == self.is_at:
  6449             return "ARP is at %s says %s" % (self.hwsrc, self.psrc)
  6450         elif self.op == self.who_has:
  6451             return "ARP who has %s says %s" % (self.pdst, self.psrc)
  6452         else:
  6453             return "ARP %ARP.op% %ARP.psrc% > %ARP.pdst%"
  6454                  
  6455 
  6456 class IP(Packet, IPTools):
  6457     name = "IP"
  6458     fields_desc = [ BitField("version" , 4 , 4),
  6459                     BitField("ihl", None, 4),
  6460                     XByteField("tos", 0),
  6461                     ShortField("len", None),
  6462                     ShortField("id", 1),
  6463                     FlagsField("flags", 0, 3, ["MF","DF","evil"]),
  6464                     BitField("frag", 0, 13),
  6465                     ByteField("ttl", 64),
  6466                     ByteEnumField("proto", 0, IP_PROTOS),
  6467                     XShortField("chksum", None),
  6468                     #IPField("src", "127.0.0.1"),
  6469                     Emph(SourceIPField("src","dst")),
  6470                     Emph(IPField("dst", "127.0.0.1")),
  6471                     IPoptionsField("options", "") ]
  6472     def post_build(self, p, pay):
  6473         ihl = self.ihl
  6474         if ihl is None:
  6475             ihl = len(p)/4
  6476             p = chr(((self.version&0xf)<<4) | ihl&0x0f)+p[1:]
  6477         if self.len is None:
  6478             l = len(p)+len(pay)
  6479             p = p[:2]+struct.pack("!H", l)+p[4:]
  6480         if self.chksum is None:
  6481             ck = checksum(p)
  6482             p = p[:10]+chr(ck>>8)+chr(ck&0xff)+p[12:]
  6483         return p+pay
  6484 
  6485     def extract_padding(self, s):
  6486         l = self.len - (self.ihl << 2)
  6487         return s[:l],s[l:]
  6488 
  6489     def send(self, s, slp=0):
  6490         for p in self:
  6491             try:
  6492                 s.sendto(str(p), (p.dst,0))
  6493             except socket.error, msg:
  6494                 log_runtime.error(msg)
  6495             if slp:
  6496                 time.sleep(slp)
  6497     def hashret(self):
  6498         if ( (self.proto == socket.IPPROTO_ICMP)
  6499              and (isinstance(self.payload, ICMP))
  6500              and (self.payload.type in [3,4,5,11,12]) ):
  6501             return self.payload.payload.hashret()
  6502         else:
  6503             if conf.checkIPsrc and conf.checkIPaddr:
  6504                 return strxor(inet_aton(self.src),inet_aton(self.dst))+struct.pack("B",self.proto)+self.payload.hashret()
  6505             else:
  6506                 return struct.pack("B", self.proto)+self.payload.hashret()
  6507     def answers(self, other):
  6508         if not isinstance(other,IP):
  6509             return 0
  6510         if conf.checkIPaddr and (self.dst != other.src):
  6511             return 0
  6512         if ( (self.proto == socket.IPPROTO_ICMP) and
  6513              (isinstance(self.payload, ICMP)) and
  6514              (self.payload.type in [3,4,5,11,12]) ):
  6515             # ICMP error message
  6516             return self.payload.payload.answers(other)
  6517 
  6518         else:
  6519             if ( (conf.checkIPaddr and (self.src != other.dst)) or
  6520                  (self.proto != other.proto) ):
  6521                 return 0
  6522             return self.payload.answers(other.payload)
  6523     def mysummary(self):
  6524         s = self.sprintf("%IP.src% > %IP.dst% %IP.proto%")
  6525         if self.frag:
  6526             s += " frag:%i" % self.frag
  6527         return s
  6528                  
  6529     
  6530 
  6531 class TCP(Packet):
  6532     name = "TCP"
  6533     fields_desc = [ ShortEnumField("sport", 20, TCP_SERVICES),
  6534                     ShortEnumField("dport", 80, TCP_SERVICES),
  6535                     IntField("seq", 0),
  6536                     IntField("ack", 0),
  6537                     BitField("dataofs", None, 4),
  6538                     BitField("reserved", 0, 4),
  6539                     FlagsField("flags", 0x2, 8, "FSRPAUEC"),
  6540                     ShortField("window", 8192),
  6541                     XShortField("chksum", None),
  6542                     ShortField("urgptr", 0),
  6543                     TCPOptionsField("options", {}) ]
  6544     def post_build(self, p, pay):
  6545         p += pay
  6546         dataofs = self.dataofs
  6547         if dataofs is None:
  6548             dataofs = 5+((len(self.get_field("options").i2m(self,self.options))+3)/4)
  6549             p = p[:12]+chr((dataofs << 4) | ord(p[12])&0x0f)+p[13:]
  6550         if self.chksum is None:
  6551             if isinstance(self.underlayer, IP):
  6552                 if self.underlayer.len is not None:
  6553                     ln = self.underlayer.len-20
  6554                 else:
  6555                     ln = len(p)
  6556                 psdhdr = struct.pack("!4s4sHH",
  6557                                      inet_aton(self.underlayer.src),
  6558                                      inet_aton(self.underlayer.dst),
  6559                                      self.underlayer.proto,
  6560                                      ln)
  6561                 ck=checksum(psdhdr+p)
  6562                 p = p[:16]+struct.pack("!H", ck)+p[18:]
  6563             elif isinstance(self.underlayer, IPv6) or isinstance(self.underlayer, _IPv6OptionHeader):
  6564                 ck = in6_chksum(socket.IPPROTO_TCP, self.underlayer, p)
  6565                 p = p[:16]+struct.pack("!H", ck)+p[18:]
  6566             else:
  6567                 warning("No IP underlayer to compute checksum. Leaving null.")
  6568         return p
  6569     def hashret(self):
  6570         if conf.checkIPsrc:
  6571             return struct.pack("H",self.sport ^ self.dport)+self.payload.hashret()
  6572         else:
  6573             return self.payload.hashret()
  6574     def answers(self, other):
  6575         if not isinstance(other, TCP):
  6576             return 0
  6577         if conf.checkIPsrc:
  6578             if not ((self.sport == other.dport) and
  6579                     (self.dport == other.sport)):
  6580                 return 0
  6581         if (abs(other.seq-self.ack) > 2+len(other.payload)):
  6582             return 0
  6583         return 1
  6584     def mysummary(self):
  6585         if isinstance(self.underlayer, IP):
  6586             return self.underlayer.sprintf("TCP %IP.src%:%TCP.sport% > %IP.dst%:%TCP.dport% %TCP.flags%")
  6587         elif isinstance(self.underlayer, IPv6):
  6588             return self.underlayer.sprintf("TCP %IPv6.src%:%TCP.sport% > %IPv6.dst%:%TCP.dport% %TCP.flags%")
  6589         else:
  6590             return self.sprintf("TCP %TCP.sport% > %TCP.dport% %TCP.flags%")
  6591 
  6592 class UDP(Packet):
  6593     name = "UDP"
  6594     fields_desc = [ ShortEnumField("sport", 53, UDP_SERVICES),
  6595                     ShortEnumField("dport", 53, UDP_SERVICES),
  6596                     ShortField("len", None),
  6597                     XShortField("chksum", None), ]
  6598     def post_build(self, p, pay):
  6599         p += pay
  6600         l = self.len
  6601         if l is None:
  6602             l = len(p)
  6603             p = p[:4]+struct.pack("!H",l)+p[6:]
  6604         if self.chksum is None:
  6605             if isinstance(self.underlayer, IP):
  6606                 if self.underlayer.len is not None:
  6607                     ln = self.underlayer.len-20
  6608                 else:
  6609                     ln = len(p)
  6610                 psdhdr = struct.pack("!4s4sHH",
  6611                                      inet_aton(self.underlayer.src),
  6612                                      inet_aton(self.underlayer.dst),
  6613                                      self.underlayer.proto,
  6614                                      ln)
  6615                 ck=checksum(psdhdr+p)
  6616                 p = p[:6]+struct.pack("!H", ck)+p[8:]
  6617             elif isinstance(self.underlayer, IPv6) or isinstance(self.underlayer, _IPv6OptionHeader):
  6618                 ck = in6_chksum(socket.IPPROTO_UDP, self.underlayer, p)
  6619                 p = p[:6]+struct.pack("!H", ck)+p[8:]
  6620             else:
  6621                 warning("No IP underlayer to compute checksum. Leaving null.")
  6622         return p
  6623     def extract_padding(self, s):
  6624         l = self.len - 8
  6625         return s[:l],s[l:]
  6626     def hashret(self):
  6627         return self.payload.hashret()
  6628     def answers(self, other):
  6629         if not isinstance(other, UDP):
  6630             return 0
  6631         if conf.checkIPsrc:
  6632             if self.dport != other.sport:
  6633                 return 0
  6634         return self.payload.answers(other.payload)
  6635     def mysummary(self):
  6636         if isinstance(self.underlayer, IP):
  6637             return self.underlayer.sprintf("UDP %IP.src%:%UDP.sport% > %IP.dst%:%UDP.dport%")
  6638         elif isinstance(self.underlayer, IPv6):
  6639             return self.underlayer.sprintf("UDP %IPv6.src%:%UDP.sport% > %IPv6.dst%:%UDP.dport%")
  6640         else:
  6641             return self.sprintf("UDP %UDP.sport% > %UDP.dport%")    
  6642 
  6643 icmptypes = { 0 : "echo-reply",
  6644               3 : "dest-unreach",
  6645               4 : "source-quench",
  6646               5 : "redirect",
  6647               8 : "echo-request",
  6648               9 : "router-advertisement",
  6649               10 : "router-solicitation",
  6650               11 : "time-exceeded",
  6651               12 : "parameter-problem",
  6652               13 : "timestamp-request",
  6653               14 : "timestamp-reply",
  6654               15 : "information-request",
  6655               16 : "information-response",
  6656               17 : "address-mask-request",
  6657               18 : "address-mask-reply" }
  6658 
  6659 class ICMP(Packet):
  6660     name = "ICMP"
  6661     fields_desc = [ ByteEnumField("type",8, icmptypes),
  6662                     ByteField("code",0),
  6663                     XShortField("chksum", None),
  6664                     ConditionalField(XShortField("id",0),  lambda pkt:pkt.type in [0,8,13,14,15,16]),
  6665                     ConditionalField(XShortField("seq",0), lambda pkt:pkt.type in [0,8,13,14,15,16]),
  6666                     ConditionalField(ICMPTimeStampField("ts_ori", None), lambda pkt:pkt.type in [13,14]),
  6667                     ConditionalField(ICMPTimeStampField("ts_rx", None), lambda pkt:pkt.type in [13,14]),
  6668                     ConditionalField(ICMPTimeStampField("ts_tx", None), lambda pkt:pkt.type in [13,14]),
  6669                     ConditionalField(IPField("gw","0.0.0.0"),  lambda pkt:pkt.type==5),
  6670                     ConditionalField(ByteField("ptr",0),   lambda pkt:pkt.type==12),
  6671                     ConditionalField(X3BytesField("reserved",0), lambda pkt:pkt.type==12),
  6672                     ConditionalField(IntField("unused",0), lambda pkt:pkt.type not in [0,5,8,12,13,14,15,16]),
  6673                     ]
  6674     def post_build(self, p, pay):
  6675         p += pay
  6676         if self.chksum is None:
  6677             ck = checksum(p)
  6678             p = p[:2]+chr(ck>>8)+chr(ck&0xff)+p[4:]
  6679         return p
  6680     
  6681     def hashret(self):
  6682         return struct.pack("HH",self.id,self.seq)+self.payload.hashret()
  6683     def answers(self, other):
  6684         if not isinstance(other,ICMP):
  6685             return 0
  6686         if ( (other.type,self.type) in [(8,0),(13,14),(15,16),(17,18)] and
  6687              self.id == other.id and
  6688              self.seq == other.seq ):
  6689             return 1
  6690         return 0
  6691 
  6692     def guess_payload_class(self, payload):
  6693         if self.type in [3,4,5,11,12]:
  6694             return IPerror
  6695         else:
  6696             return None
  6697     def mysummary(self):
  6698         if isinstance(self.underlayer, IP):
  6699             return self.underlayer.sprintf("ICMP %IP.src% > %IP.dst% %ICMP.type% %ICMP.code%")
  6700         else:
  6701             return self.sprintf("ICMP %ICMP.type% %ICMP.code%")
  6702     
  6703         
  6704 
  6705 
  6706 
  6707 class IPerror(IP):
  6708     name = "IP in ICMP"
  6709     def answers(self, other):
  6710         if not isinstance(other, IP):
  6711             return 0
  6712         if not ( ((conf.checkIPsrc == 0) or (self.dst == other.dst)) and
  6713                  (self.src == other.src) and
  6714                  ( ((conf.checkIPID == 0)
  6715                     or (self.id == other.id)
  6716                     or (conf.checkIPID == 1 and self.id == socket.htons(other.id)))) and
  6717                  (self.proto == other.proto) ):
  6718             return 0
  6719         return self.payload.answers(other.payload)
  6720     def mysummary(self):
  6721         return Packet.mysummary(self)
  6722 
  6723 
  6724 class TCPerror(TCP):
  6725     name = "TCP in ICMP"
  6726     def answers(self, other):
  6727         if not isinstance(other, TCP):
  6728             return 0
  6729         if conf.checkIPsrc:
  6730             if not ((self.sport == other.sport) and
  6731                     (self.dport == other.dport)):
  6732                 return 0
  6733         if conf.check_TCPerror_seqack:
  6734             if self.seq is not None:
  6735                 if self.seq != other.seq:
  6736                     return 0
  6737             if self.ack is not None:
  6738                 if self.ack != other.ack:
  6739                     return 0
  6740         return 1
  6741     def mysummary(self):
  6742         return Packet.mysummary(self)
  6743 
  6744 
  6745 class UDPerror(UDP):
  6746     name = "UDP in ICMP"
  6747     def answers(self, other):
  6748         if not isinstance(other, UDP):
  6749             return 0
  6750         if conf.checkIPsrc:
  6751             if not ((self.sport == other.sport) and
  6752                     (self.dport == other.dport)):
  6753                 return 0
  6754         return 1
  6755     def mysummary(self):
  6756         return Packet.mysummary(self)
  6757 
  6758                     
  6759 
  6760 class ICMPerror(ICMP):
  6761     name = "ICMP in ICMP"
  6762     def answers(self, other):
  6763         if not isinstance(other,ICMP):
  6764             return 0
  6765         if not ((self.type == other.type) and
  6766                 (self.code == other.code)):
  6767             return 0
  6768         if self.code in [0,8,13,14,17,18]:
  6769             if (self.id == other.id and
  6770                 self.seq == other.seq):
  6771                 return 1
  6772             else:
  6773                 return 0
  6774         else:
  6775             return 1
  6776     def mysummary(self):
  6777         return Packet.mysummary(self)
  6778 
  6779 class IPv6(Packet):
  6780     """See http://namabiiru.hongo.wide.ad.jp/scapy6"""
  6781     name = "IPv6 not implemented here." 
  6782     def __init__(self, *args, **kargs):
  6783         log_interactive.error(self.name)
  6784     def __repr__(self):
  6785         return "<IPv6: ERROR not implemented>"
  6786     
  6787 class _IPv6OptionHeader(Packet):
  6788     """See http://namabiiru.hongo.wide.ad.jp/scapy6"""
  6789     name = "IPv6 not implemented here."
  6790     def __init__(self, *args, **kargs):
  6791         log_interactive.error(self.name)
  6792     def __repr__(self):
  6793         return "<IPv6: ERROR not implemented>"
  6794 
  6795 
  6796 class L2TP(Packet):
  6797     fields_desc = [ ShortEnumField("pkt_type",2,{2:"data"}),
  6798                     ShortField("len", None),
  6799                     ShortField("tunnel_id", 0),
  6800                     ShortField("session_id", 0),
  6801                     ShortField("ns", 0),
  6802                     ShortField("nr", 0),
  6803                     ShortField("offset", 0) ]
  6804 
  6805     def post_build(self, pkt, pay):
  6806         if self.len is None:
  6807             l = len(pkt)+len(pay)
  6808             pkt = pkt[:2]+struct.pack("!H", l)+pkt[4:]
  6809         return pkt+pay
  6810 
  6811 
  6812 _PPP_proto = { 0x0001: "Padding Protocol",
  6813                0x0003: "ROHC small-CID [RFC3095]",
  6814                0x0005: "ROHC large-CID [RFC3095]",
  6815                0x0021: "Internet Protocol version 4",
  6816                0x0023: "OSI Network Layer",
  6817                0x0025: "Xerox NS IDP",
  6818                0x0027: "DECnet Phase IV",
  6819                0x0029: "Appletalk",
  6820                0x002b: "Novell IPX",
  6821                0x002d: "Van Jacobson Compressed TCP/IP",
  6822                0x002f: "Van Jacobson Uncompressed TCP/IP",
  6823                0x0031: "Bridging PDU",
  6824                0x0033: "Stream Protocol (ST-II)",
  6825                0x0035: "Banyan Vines",
  6826                0x0037: "reserved (until 1993) [Typo in RFC1172]",
  6827                0x0039: "AppleTalk EDDP",
  6828                0x003b: "AppleTalk SmartBuffered",
  6829                0x003d: "Multi-Link [RFC1717]",
  6830                0x003f: "NETBIOS Framing",
  6831                0x0041: "Cisco Systems",
  6832                0x0043: "Ascom Timeplex",
  6833                0x0045: "Fujitsu Link Backup and Load Balancing (LBLB)",
  6834                0x0047: "DCA Remote Lan",
  6835                0x0049: "Serial Data Transport Protocol (PPP-SDTP)",
  6836                0x004b: "SNA over 802.2",
  6837                0x004d: "SNA",
  6838                0x004f: "IPv6 Header Compression",
  6839                0x0051: "KNX Bridging Data [ianp]",
  6840                0x0053: "Encryption [Meyer]",
  6841                0x0055: "Individual Link Encryption [Meyer]",
  6842                0x0057: "Internet Protocol version 6 [Hinden]",
  6843                0x0059: "PPP Muxing [RFC3153]",
  6844                0x005b: "Vendor-Specific Network Protocol (VSNP) [RFC3772]",
  6845                0x0061: "RTP IPHC Full Header [RFC3544]",
  6846                0x0063: "RTP IPHC Compressed TCP [RFC3544]",
  6847                0x0065: "RTP IPHC Compressed Non TCP [RFC3544]",
  6848                0x0067: "RTP IPHC Compressed UDP 8 [RFC3544]",
  6849                0x0069: "RTP IPHC Compressed RTP 8 [RFC3544]",
  6850                0x006f: "Stampede Bridging",
  6851                0x0071: "Reserved [Fox]",
  6852                0x0073: "MP+ Protocol [Smith]",
  6853                0x007d: "reserved (Control Escape) [RFC1661]",
  6854                0x007f: "reserved (compression inefficient [RFC1662]",
  6855                0x0081: "Reserved Until 20-Oct-2000 [IANA]",
  6856                0x0083: "Reserved Until 20-Oct-2000 [IANA]",
  6857                0x00c1: "NTCITS IPI [Ungar]",
  6858                0x00cf: "reserved (PPP NLID)",
  6859                0x00fb: "single link compression in multilink [RFC1962]",
  6860                0x00fd: "compressed datagram [RFC1962]",
  6861                0x00ff: "reserved (compression inefficient)",
  6862                0x0201: "802.1d Hello Packets",
  6863                0x0203: "IBM Source Routing BPDU",
  6864                0x0205: "DEC LANBridge100 Spanning Tree",
  6865                0x0207: "Cisco Discovery Protocol [Sastry]",
  6866                0x0209: "Netcs Twin Routing [Korfmacher]",
  6867                0x020b: "STP - Scheduled Transfer Protocol [Segal]",
  6868                0x020d: "EDP - Extreme Discovery Protocol [Grosser]",
  6869                0x0211: "Optical Supervisory Channel Protocol (OSCP)[Prasad]",
  6870                0x0213: "Optical Supervisory Channel Protocol (OSCP)[Prasad]",
  6871                0x0231: "Luxcom",
  6872                0x0233: "Sigma Network Systems",
  6873                0x0235: "Apple Client Server Protocol [Ridenour]",
  6874                0x0281: "MPLS Unicast [RFC3032]  ",
  6875                0x0283: "MPLS Multicast [RFC3032]",
  6876                0x0285: "IEEE p1284.4 standard - data packets [Batchelder]",
  6877                0x0287: "ETSI TETRA Network Protocol Type 1 [Nieminen]",
  6878                0x0289: "Multichannel Flow Treatment Protocol [McCann]",
  6879                0x2063: "RTP IPHC Compressed TCP No Delta [RFC3544]",
  6880                0x2065: "RTP IPHC Context State [RFC3544]",
  6881                0x2067: "RTP IPHC Compressed UDP 16 [RFC3544]",
  6882                0x2069: "RTP IPHC Compressed RTP 16 [RFC3544]",
  6883                0x4001: "Cray Communications Control Protocol [Stage]",
  6884                0x4003: "CDPD Mobile Network Registration Protocol [Quick]",
  6885                0x4005: "Expand accelerator protocol [Rachmani]",
  6886                0x4007: "ODSICP NCP [Arvind]",
  6887                0x4009: "DOCSIS DLL [Gaedtke]",
  6888                0x400B: "Cetacean Network Detection Protocol [Siller]",
  6889                0x4021: "Stacker LZS [Simpson]",
  6890                0x4023: "RefTek Protocol [Banfill]",
  6891                0x4025: "Fibre Channel [Rajagopal]",
  6892                0x4027: "EMIT Protocols [Eastham]",
  6893                0x405b: "Vendor-Specific Protocol (VSP) [RFC3772]",
  6894                0x8021: "Internet Protocol Control Protocol",
  6895                0x8023: "OSI Network Layer Control Protocol",
  6896                0x8025: "Xerox NS IDP Control Protocol",
  6897                0x8027: "DECnet Phase IV Control Protocol",
  6898                0x8029: "Appletalk Control Protocol",
  6899                0x802b: "Novell IPX Control Protocol",
  6900                0x802d: "reserved",
  6901                0x802f: "reserved",
  6902                0x8031: "Bridging NCP",
  6903                0x8033: "Stream Protocol Control Protocol",
  6904                0x8035: "Banyan Vines Control Protocol",
  6905                0x8037: "reserved (until 1993)",
  6906                0x8039: "reserved",
  6907                0x803b: "reserved",
  6908                0x803d: "Multi-Link Control Protocol",
  6909                0x803f: "NETBIOS Framing Control Protocol",
  6910                0x8041: "Cisco Systems Control Protocol",
  6911                0x8043: "Ascom Timeplex",
  6912                0x8045: "Fujitsu LBLB Control Protocol",
  6913                0x8047: "DCA Remote Lan Network Control Protocol (RLNCP)",
  6914                0x8049: "Serial Data Control Protocol (PPP-SDCP)",
  6915                0x804b: "SNA over 802.2 Control Protocol",
  6916                0x804d: "SNA Control Protocol",
  6917                0x804f: "IP6 Header Compression Control Protocol",
  6918                0x8051: "KNX Bridging Control Protocol [ianp]",
  6919                0x8053: "Encryption Control Protocol [Meyer]",
  6920                0x8055: "Individual Link Encryption Control Protocol [Meyer]",
  6921                0x8057: "IPv6 Control Protovol [Hinden]",
  6922                0x8059: "PPP Muxing Control Protocol [RFC3153]",
  6923                0x805b: "Vendor-Specific Network Control Protocol (VSNCP) [RFC3772]",
  6924                0x806f: "Stampede Bridging Control Protocol",
  6925                0x8073: "MP+ Control Protocol [Smith]",
  6926                0x8071: "Reserved [Fox]",
  6927                0x807d: "Not Used - reserved [RFC1661]",
  6928                0x8081: "Reserved Until 20-Oct-2000 [IANA]",
  6929                0x8083: "Reserved Until 20-Oct-2000 [IANA]",
  6930                0x80c1: "NTCITS IPI Control Protocol [Ungar]",
  6931                0x80cf: "Not Used - reserved [RFC1661]",
  6932                0x80fb: "single link compression in multilink control [RFC1962]",
  6933                0x80fd: "Compression Control Protocol [RFC1962]",
  6934                0x80ff: "Not Used - reserved [RFC1661]",
  6935                0x8207: "Cisco Discovery Protocol Control [Sastry]",
  6936                0x8209: "Netcs Twin Routing [Korfmacher]",
  6937                0x820b: "STP - Control Protocol [Segal]",
  6938                0x820d: "EDPCP - Extreme Discovery Protocol Ctrl Prtcl [Grosser]",
  6939                0x8235: "Apple Client Server Protocol Control [Ridenour]",
  6940                0x8281: "MPLSCP [RFC3032]",
  6941                0x8285: "IEEE p1284.4 standard - Protocol Control [Batchelder]",
  6942                0x8287: "ETSI TETRA TNP1 Control Protocol [Nieminen]",
  6943                0x8289: "Multichannel Flow Treatment Protocol [McCann]",
  6944                0xc021: "Link Control Protocol",
  6945                0xc023: "Password Authentication Protocol",
  6946                0xc025: "Link Quality Report",
  6947                0xc027: "Shiva Password Authentication Protocol",
  6948                0xc029: "CallBack Control Protocol (CBCP)",
  6949                0xc02b: "BACP Bandwidth Allocation Control Protocol [RFC2125]",
  6950                0xc02d: "BAP [RFC2125]",
  6951                0xc05b: "Vendor-Specific Authentication Protocol (VSAP) [RFC3772]",
  6952                0xc081: "Container Control Protocol [KEN]",
  6953                0xc223: "Challenge Handshake Authentication Protocol",
  6954                0xc225: "RSA Authentication Protocol [Narayana]",
  6955                0xc227: "Extensible Authentication Protocol [RFC2284]",
  6956                0xc229: "Mitsubishi Security Info Exch Ptcl (SIEP) [Seno]",
  6957                0xc26f: "Stampede Bridging Authorization Protocol",
  6958                0xc281: "Proprietary Authentication Protocol [KEN]",
  6959                0xc283: "Proprietary Authentication Protocol [Tackabury]",
  6960                0xc481: "Proprietary Node ID Authentication Protocol [KEN]"}
  6961 
  6962 
  6963 class HDLC(Packet):
  6964     fields_desc = [ XByteField("address",0xff),
  6965                     XByteField("control",0x03)  ]
  6966 
  6967 class PPP_metaclass(Packet_metaclass):
  6968     def __call__(self, _pkt=None, *args, **kargs):
  6969         cls = self
  6970         if _pkt and _pkt[0] == '\xff':
  6971             cls = HDLC
  6972         i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)
  6973         i.__init__(_pkt=_pkt, *args, **kargs)
  6974         return i
  6975     
  6976 
  6977 class PPP(Packet):
  6978     __metaclass__ = PPP_metaclass
  6979     name = "PPP Link Layer"
  6980     fields_desc = [ ShortEnumField("proto", 0x0021, _PPP_proto) ]
  6981 
  6982 _PPP_conftypes = { 1:"Configure-Request",
  6983                    2:"Configure-Ack",
  6984                    3:"Configure-Nak",
  6985                    4:"Configure-Reject",
  6986                    5:"Terminate-Request",
  6987                    6:"Terminate-Ack",
  6988                    7:"Code-Reject",
  6989                    8:"Protocol-Reject",
  6990                    9:"Echo-Request",
  6991                    10:"Echo-Reply",
  6992                    11:"Discard-Request",
  6993                    14:"Reset-Request",
  6994                    15:"Reset-Ack",
  6995                    }
  6996 
  6997 class PPP_Option_metaclass(Packet_metaclass):
  6998     _known_options={}
  6999     def __call__(self, _pkt=None, *args, **kargs):
  7000         cls = self
  7001         if _pkt:
  7002             t = ord(_pkt[0])
  7003             cls = self._known_options.get(t,self)
  7004         i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)
  7005         i.__init__(_pkt=_pkt, *args, **kargs)
  7006         return i
  7007     def _register(self, cls):
  7008         self._known_options[cls.fields_desc[0].default] = cls
  7009 
  7010 
  7011 ### PPP IPCP stuff (RFC 1332)
  7012 
  7013 # All IPCP options are defined below (names and associated classes) 
  7014 _PPP_ipcpopttypes = {     1:"IP-Addresses (Deprecated)",
  7015                           2:"IP-Compression-Protocol",
  7016                           3:"IP-Address",
  7017                           4:"Mobile-IPv4", # not implemented, present for completeness
  7018                           129:"Primary-DNS-Address",
  7019                           130:"Primary-NBNS-Address",
  7020                           131:"Secondary-DNS-Address",
  7021                           132:"Secondary-NBNS-Address"}
  7022 
  7023 
  7024 
  7025 class PPP_IPCP_Option_metaclass(PPP_Option_metaclass):
  7026     _known_options={}
  7027 
  7028 
  7029 class PPP_IPCP_Option(Packet):
  7030     __metaclass__=PPP_IPCP_Option_metaclass
  7031     name = "PPP IPCP Option"
  7032     fields_desc = [ ByteEnumField("type" , None , _PPP_ipcpopttypes),
  7033                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
  7034                     StrLenField("data", "", length_from=lambda p:max(0,p.len-2)) ]
  7035     def extract_padding(self, pay):
  7036         return "",pay
  7037 
  7038 class PPP_IPCP_Specific_Option_metaclass(PPP_IPCP_Option_metaclass):
  7039     def __new__(cls, name, bases, dct):
  7040         newcls = super(PPP_IPCP_Specific_Option_metaclass, cls).__new__(cls, name, bases, dct)
  7041         PPP_IPCP_Option._register(newcls)
  7042         
  7043 
  7044 class PPP_IPCP_Option_IPAddress(PPP_IPCP_Option):
  7045     __metaclass__=PPP_IPCP_Specific_Option_metaclass
  7046     name = "PPP IPCP Option: IP Address"
  7047     fields_desc = [ ByteEnumField("type" , 3 , _PPP_ipcpopttypes),
  7048                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
  7049                     IPField("data","0.0.0.0"),
  7050                     ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
  7051 
  7052 class PPP_IPCP_Option_DNS1(PPP_IPCP_Option):
  7053     __metaclass__=PPP_IPCP_Specific_Option_metaclass
  7054     name = "PPP IPCP Option: DNS1 Address"
  7055     fields_desc = [ ByteEnumField("type" , 129 , _PPP_ipcpopttypes),
  7056                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
  7057                     IPField("data","0.0.0.0"),
  7058                     ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
  7059 
  7060 class PPP_IPCP_Option_DNS2(PPP_IPCP_Option):
  7061     __metaclass__=PPP_IPCP_Specific_Option_metaclass
  7062     name = "PPP IPCP Option: DNS2 Address"
  7063     fields_desc = [ ByteEnumField("type" , 131 , _PPP_ipcpopttypes),
  7064                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
  7065                     IPField("data","0.0.0.0"),
  7066                     ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
  7067 
  7068 class PPP_IPCP_Option_NBNS1(PPP_IPCP_Option):
  7069     __metaclass__=PPP_IPCP_Specific_Option_metaclass
  7070     name = "PPP IPCP Option: NBNS1 Address"
  7071     fields_desc = [ ByteEnumField("type" , 130 , _PPP_ipcpopttypes),
  7072                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
  7073                     IPField("data","0.0.0.0"),
  7074                     ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
  7075 
  7076 class PPP_IPCP_Option_NBNS2(PPP_IPCP_Option):
  7077     __metaclass__=PPP_IPCP_Specific_Option_metaclass
  7078     name = "PPP IPCP Option: NBNS2 Address"
  7079     fields_desc = [ ByteEnumField("type" , 132 , _PPP_ipcpopttypes),
  7080                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
  7081                     IPField("data","0.0.0.0"),
  7082                     ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
  7083 
  7084 
  7085 
  7086 
  7087 class PPP_IPCP(Packet):
  7088     fields_desc = [ ByteEnumField("code" , 1, _PPP_conftypes),
  7089 		    XByteField("id", 0 ),
  7090                     FieldLenField("len" , None, fmt="H", length_of="options", adjust=lambda p,x:x+4 ),
  7091                     PacketListField("options", [],  PPP_IPCP_Option, length_from=lambda p:p.len-4,) ]
  7092 
  7093 
  7094 ### ECP
  7095 
  7096 _PPP_ecpopttypes = { 0:"OUI",
  7097                      1:"DESE", }
  7098 
  7099 class PPP_ECP_Option_metaclass(PPP_Option_metaclass):
  7100     _known_options={}
  7101 
  7102 
  7103 
  7104 class PPP_ECP_Option(Packet):
  7105     __metaclass__=PPP_ECP_Option_metaclass
  7106     name = "PPP ECP Option"
  7107     fields_desc = [ ByteEnumField("type" , None , _PPP_ecpopttypes),
  7108                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
  7109                     StrLenField("data", "", length_from=lambda p:max(0,p.len-2)) ]
  7110     def extract_padding(self, pay):
  7111         return "",pay
  7112 
  7113 class PPP_ECP_Specific_Option_metaclass(PPP_ECP_Option_metaclass):
  7114     def __new__(cls, name, bases, dct):
  7115         newcls = super(PPP_ECP_Specific_Option_metaclass, cls).__new__(cls, name, bases, dct)
  7116         PPP_ECP_Option._register(newcls)
  7117         
  7118 
  7119 class PPP_ECP_Option_OUI(PPP_ECP_Option):
  7120     __metaclass__=PPP_ECP_Specific_Option_metaclass
  7121     fields_desc = [ ByteEnumField("type" , 0 , _PPP_ecpopttypes),
  7122                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
  7123                     StrFixedLenField("oui","",3),
  7124                     ByteField("subtype",0),
  7125                     StrLenField("data", "", length_from=lambda p:p.len-6) ]
  7126                     
  7127 
  7128 
  7129 class PPP_ECP(Packet):
  7130     fields_desc = [ ByteEnumField("code" , 1, _PPP_conftypes),
  7131 		    XByteField("id", 0 ),
  7132                     FieldLenField("len" , None, fmt="H", length_of="options", adjust=lambda p,x:x+4 ),
  7133                     PacketListField("options", [],  PPP_ECP_Option, length_from=lambda p:p.len-4,) ]
  7134 
  7135 
  7136 
  7137 
  7138 class DNS(Packet):
  7139     name = "DNS"
  7140     fields_desc = [ ShortField("id",0),
  7141                     BitField("qr",0, 1),
  7142                     BitEnumField("opcode", 0, 4, {0:"QUERY",1:"IQUERY",2:"STATUS"}),
  7143                     BitField("aa", 0, 1),
  7144                     BitField("tc", 0, 1),
  7145                     BitField("rd", 0, 1),
  7146                     BitField("ra", 0 ,1),
  7147                     BitField("z", 0, 3),
  7148                     BitEnumField("rcode", 0, 4, {0:"ok", 1:"format-error", 2:"server-failure", 3:"name-error", 4:"not-implemented", 5:"refused"}),
  7149                     DNSRRCountField("qdcount", None, "qd"),
  7150                     DNSRRCountField("ancount", None, "an"),
  7151                     DNSRRCountField("nscount", None, "ns"),
  7152                     DNSRRCountField("arcount", None, "ar"),
  7153                     DNSQRField("qd", "qdcount"),
  7154                     DNSRRField("an", "ancount"),
  7155                     DNSRRField("ns", "nscount"),
  7156                     DNSRRField("ar", "arcount",0) ]
  7157     def answers(self, other):
  7158         return (isinstance(other, DNS)
  7159                 and self.id == other.id
  7160                 and self.qr == 1
  7161                 and other.qr == 0)
  7162         
  7163     def mysummary(self):
  7164         type = ["Qry","Ans"][self.qr]
  7165         name = ""
  7166         if self.qr:
  7167             type = "Ans"
  7168             if self.ancount > 0 and isinstance(self.an, DNSRR):
  7169                 name = ' "%s"' % self.an.rdata
  7170         else:
  7171             type = "Qry"
  7172             if self.qdcount > 0 and isinstance(self.qd, DNSQR):
  7173                 name = ' "%s"' % self.qd.qname
  7174         return 'DNS %s%s ' % (type, name)
  7175 
  7176 dnstypes = { 0:"ANY", 255:"ALL",
  7177              1:"A", 2:"NS", 3:"MD", 4:"MD", 5:"CNAME", 6:"SOA", 7: "MB", 8:"MG",
  7178              9:"MR",10:"NULL",11:"WKS",12:"PTR",13:"HINFO",14:"MINFO",15:"MX",16:"TXT",
  7179              17:"RP",18:"AFSDB",28:"AAAA", 33:"SRV",38:"A6",39:"DNAME"}
  7180 
  7181 dnsqtypes = {251:"IXFR",252:"AXFR",253:"MAILB",254:"MAILA",255:"ALL"}
  7182 dnsqtypes.update(dnstypes)
  7183 dnsclasses =  {1: 'IN',  2: 'CS',  3: 'CH',  4: 'HS',  255: 'ANY'}
  7184 
  7185 
  7186 class DNSQR(Packet):
  7187     name = "DNS Question Record"
  7188     show_indent=0
  7189     fields_desc = [ DNSStrField("qname",""),
  7190                     ShortEnumField("qtype", 1, dnsqtypes),
  7191                     ShortEnumField("qclass", 1, dnsclasses) ]
  7192                     
  7193                     
  7194 
  7195 class DNSRR(Packet):
  7196     name = "DNS Resource Record"
  7197     show_indent=0
  7198     fields_desc = [ DNSStrField("rrname",""),
  7199                     ShortEnumField("type", 1, dnstypes),
  7200                     ShortEnumField("rclass", 1, dnsclasses),
  7201                     IntField("ttl", 0),
  7202                     RDLenField("rdlen"),
  7203                     RDataField("rdata", "", length_from=lambda pkt:pkt.rdlen) ]
  7204 
  7205 dhcpmagic="c\x82Sc"
  7206 
  7207 
  7208 class BOOTP(Packet):
  7209     name = "BOOTP"
  7210     fields_desc = [ ByteEnumField("op",1, {1:"BOOTREQUEST", 2:"BOOTREPLY"}),
  7211                     ByteField("htype",1),
  7212                     ByteField("hlen",6),
  7213                     ByteField("hops",0),
  7214                     IntField("xid",0),
  7215                     ShortField("secs",0),
  7216                     FlagsField("flags", 0, 16, "???????????????B"),
  7217                     IPField("ciaddr","0.0.0.0"),
  7218                     IPField("yiaddr","0.0.0.0"),
  7219                     IPField("siaddr","0.0.0.0"),
  7220                     IPField("giaddr","0.0.0.0"),
  7221                     Field("chaddr","", "16s"),
  7222                     Field("sname","","64s"),
  7223                     Field("file","","128s"),
  7224                     StrField("options","") ]
  7225     def guess_payload_class(self, payload):
  7226         if self.options[:len(dhcpmagic)] == dhcpmagic:
  7227             return DHCP
  7228         else:
  7229             return Packet.guess_payload_class(self, payload)
  7230     def extract_padding(self,s):
  7231         if self.options[:len(dhcpmagic)] == dhcpmagic:
  7232             # set BOOTP options to DHCP magic cookie and make rest a payload of DHCP options
  7233             payload = self.options[len(dhcpmagic):]
  7234             self.options = self.options[:len(dhcpmagic)]
  7235             return payload, None
  7236         else:
  7237             return "", None
  7238     def hashret(self):
  7239         return struct.pack("L", self.xid)
  7240     def answers(self, other):
  7241         if not isinstance(other, BOOTP):
  7242             return 0
  7243         return self.xid == other.xid
  7244 
  7245 
  7246 
  7247 #DHCP_UNKNOWN, DHCP_IP, DHCP_IPLIST, DHCP_TYPE \
  7248 #= range(4)
  7249 #
  7250 
  7251 DHCPTypes = {
  7252                 1: "discover",
  7253                 2: "offer",
  7254                 3: "request",
  7255                 4: "decline",
  7256                 5: "ack",
  7257                 6: "nak",
  7258                 7: "release",
  7259                 8: "inform",
  7260                 9: "force_renew",
  7261                 10:"lease_query",
  7262                 11:"lease_unassigned",
  7263                 12:"lease_unknown",
  7264                 13:"lease_active",
  7265                 }
  7266 
  7267 DHCPOptions = {
  7268     0: "pad",
  7269     1: IPField("subnet_mask", "0.0.0.0"),
  7270     2: "time_zone",
  7271     3: IPField("router","0.0.0.0"),
  7272     4: IPField("time_server","0.0.0.0"),
  7273     5: IPField("IEN_name_server","0.0.0.0"),
  7274     6: IPField("name_server","0.0.0.0"),
  7275     7: IPField("log_server","0.0.0.0"),
  7276     8: IPField("cookie_server","0.0.0.0"),
  7277     9: IPField("lpr_server","0.0.0.0"),
  7278     12: "hostname",
  7279     14: "dump_path",
  7280     15: "domain",
  7281     17: "root_disk_path",
  7282     22: "max_dgram_reass_size",
  7283     23: "default_ttl",
  7284     24: "pmtu_timeout",
  7285     28: IPField("broadcast_address","0.0.0.0"),
  7286     35: "arp_cache_timeout",
  7287     36: "ether_or_dot3",
  7288     37: "tcp_ttl",
  7289     38: "tcp_keepalive_interval",
  7290     39: "tcp_keepalive_garbage",
  7291     40: "NIS_domain",
  7292     41: IPField("NIS_server","0.0.0.0"),
  7293     42: IPField("NTP_server","0.0.0.0"),
  7294     43: "vendor_specific",
  7295     44: IPField("NetBIOS_server","0.0.0.0"),
  7296     45: IPField("NetBIOS_dist_server","0.0.0.0"),
  7297     50: IPField("requested_addr","0.0.0.0"),
  7298     51: IntField("lease_time", 43200),
  7299     54: IPField("server_id","0.0.0.0"),
  7300     55: "param_req_list",
  7301     57: ShortField("max_dhcp_size", 1500),
  7302     58: IntField("renewal_time", 21600),
  7303     59: IntField("rebinding_time", 37800),
  7304     60: "vendor_class_id",
  7305     61: "client_id",
  7306     
  7307     64: "NISplus_domain",
  7308     65: IPField("NISplus_server","0.0.0.0"),
  7309     69: IPField("SMTP_server","0.0.0.0"),
  7310     70: IPField("POP3_server","0.0.0.0"),
  7311     71: IPField("NNTP_server","0.0.0.0"),
  7312     72: IPField("WWW_server","0.0.0.0"),
  7313     73: IPField("Finger_server","0.0.0.0"),
  7314     74: IPField("IRC_server","0.0.0.0"),
  7315     75: IPField("StreetTalk_server","0.0.0.0"),
  7316     76: "StreetTalk_Dir_Assistance",
  7317     82: "relay_agent_Information",
  7318     53: ByteEnumField("message-type", 1, DHCPTypes),
  7319     #             55: DHCPRequestListField("request-list"),
  7320     255: "end"
  7321     }
  7322 
  7323 DHCPRevOptions = {}
  7324 
  7325 for k,v in DHCPOptions.iteritems():
  7326     if type(v) is str:
  7327         n = v
  7328         v = None
  7329     else:
  7330         n = v.name
  7331     DHCPRevOptions[n] = (k,v)
  7332 del(n)
  7333 del(v)
  7334 del(k)
  7335     
  7336     
  7337 
  7338 
  7339 
  7340 class DHCPOptionsField(StrField):
  7341     islist=1
  7342     def i2repr(self,pkt,x):
  7343         s = []
  7344         for v in x:
  7345             if type(v) is tuple and len(v) in [2,3]:
  7346                 if  DHCPRevOptions.has_key(v[0]) and isinstance(DHCPRevOptions[v[0]][1],Field):
  7347                     f = DHCPRevOptions[v[0]][1]
  7348                     vv = f.i2repr(pkt,v[1])
  7349                 else:
  7350                     vv = repr(v[1])
  7351                 r = "%s=%s" % (v[0],vv)
  7352                 if len(v) > 2:
  7353                     r += " (garbage=%r)" % v[2]
  7354                 s.append(r)
  7355             else:
  7356                 s.append(sane(v))
  7357         return "[%s]" % (" ".join(s))
  7358         
  7359     def getfield(self, pkt, s):
  7360         return "", self.m2i(pkt, s)
  7361     def m2i(self, pkt, x):
  7362         opt = []
  7363         while x:
  7364             o = ord(x[0])
  7365             if o == 255:
  7366                 opt.append("end")
  7367                 x = x[1:]
  7368                 continue
  7369             if o == 0:
  7370                 opt.append("pad")
  7371                 x = x[1:]
  7372                 continue
  7373             if len(x) < 2 or len(x) < ord(x[1])+2:
  7374                 opt.append(x)
  7375                 break
  7376             elif DHCPOptions.has_key(o):
  7377                 f = DHCPOptions[o]
  7378 
  7379                 if isinstance(f, str):
  7380                     olen = ord(x[1])
  7381                     opt.append( (f,x[2:olen+2]) )
  7382                     x = x[olen+2:]
  7383                 else:
  7384                     olen = ord(x[1])
  7385                     try:
  7386                         left, val = f.getfield(pkt,x[2:olen+2])
  7387                     except:
  7388                         opt.append(x)
  7389                         break
  7390                     if left:
  7391                         otuple = (f.name, val, left)
  7392                     else:
  7393                         otuple = (f.name, val)
  7394                     opt.append(otuple)
  7395                     x = x[olen+2:]
  7396             else:
  7397                 olen = ord(x[1])
  7398                 opt.append((o, x[2:olen+2]))
  7399                 x = x[olen+2:]
  7400         return opt
  7401     def i2m(self, pkt, x):
  7402         if type(x) is str:
  7403             return x
  7404         s = ""
  7405         for o in x:
  7406             if type(o) is tuple and len(o) in [2,3]:
  7407                 name, val = o[:2]
  7408 
  7409                 if isinstance(name, int):
  7410                     onum, oval = name, val
  7411                 elif DHCPRevOptions.has_key(name):
  7412                     onum, f = DHCPRevOptions[name]
  7413                     if  f is None:
  7414                         oval = val
  7415                     else:
  7416                         oval = f.addfield(pkt,"",f.any2i(pkt,val))
  7417                 else:
  7418                     warning("Unknown field option %s" % name)
  7419                     continue
  7420                 if len(o) > 2:
  7421                     oval += o[2]
  7422 
  7423                 s += chr(onum)
  7424                 s += chr(len(oval))
  7425                 s += oval
  7426 
  7427             elif (type(o) is str and DHCPRevOptions.has_key(o) and 
  7428                   DHCPRevOptions[o][1] == None):
  7429                 s += chr(DHCPRevOptions[o][0])
  7430             elif type(o) is int:
  7431                 s += chr(o)+"\0"
  7432             elif type(o) is str:
  7433                 s += o
  7434             else:
  7435                 warning("Malformed option %s" % o)
  7436         return s
  7437 
  7438 
  7439 class DHCP(Packet):
  7440     name = "DHCP options"
  7441     fields_desc = [ DHCPOptionsField("options","") ]
  7442 
  7443 
  7444 class Dot11(Packet):
  7445     name = "802.11"
  7446     fields_desc = [
  7447                     BitField("subtype", 0, 4),
  7448                     BitEnumField("type", 0, 2, ["Management", "Control", "Data", "Reserved"]),
  7449                     BitField("proto", 0, 2),
  7450                     FlagsField("FCfield", 0, 8, ["to-DS", "from-DS", "MF", "retry", "pw-mgt", "MD", "wep", "order"]),
  7451                     ShortField("ID",0),
  7452                     MACField("addr1", ETHER_ANY),
  7453                     Dot11Addr2MACField("addr2", ETHER_ANY),
  7454                     Dot11Addr3MACField("addr3", ETHER_ANY),
  7455                     Dot11SCField("SC", 0),
  7456                     Dot11Addr4MACField("addr4", ETHER_ANY) 
  7457                     ]
  7458     def mysummary(self):
  7459         return self.sprintf("802.11 %Dot11.type% %Dot11.subtype% %Dot11.addr2% > %Dot11.addr1%")
  7460     def guess_payload_class(self, payload):
  7461         if self.type == 0x02 and (self.subtype >= 0x08 and self.subtype <=0xF and self.subtype != 0xD):
  7462             return Dot11QoS
  7463 	elif self.FCfield & 0x40:
  7464             return Dot11WEP
  7465         else:
  7466             return Packet.guess_payload_class(self, payload)
  7467     def answers(self, other):
  7468         if isinstance(other,Dot11):
  7469             if self.type == 0: # management
  7470                 if self.addr1.lower() != other.addr2.lower(): # check resp DA w/ req SA
  7471                     return 0
  7472                 if (other.subtype,self.subtype) in [(0,1),(2,3),(4,5)]:
  7473                     return 1
  7474                 if self.subtype == other.subtype == 11: # auth
  7475                     return self.payload.answers(other.payload)
  7476             elif self.type == 1: # control
  7477                 return 0
  7478             elif self.type == 2: # data
  7479                 return self.payload.answers(other.payload)
  7480             elif self.type == 3: # reserved
  7481                 return 0
  7482         return 0
  7483     def unwep(self, key=None, warn=1):
  7484         if self.FCfield & 0x40 == 0:
  7485             if warn:
  7486                 warning("No WEP to remove")
  7487             return
  7488         if  isinstance(self.payload.payload, NoPayload):
  7489             if key or conf.wepkey:
  7490                 self.payload.decrypt(key)
  7491             if isinstance(self.payload.payload, NoPayload):
  7492                 if warn:
  7493                     warning("Dot11 can't be decrypted. Check conf.wepkey.")
  7494                 return
  7495         self.FCfield &= ~0x40
  7496         self.payload=self.payload.payload
  7497 
  7498 
  7499 class Dot11QoS(Packet):
  7500     name = "802.11 QoS"
  7501     fields_desc = [ BitField("TID",None,4),
  7502                     BitField("EOSP",None,1),
  7503                     BitField("Ack Policy",None,2),
  7504                     BitField("Reserved",None,1),
  7505                     ByteField("TXOP",None) ]
  7506     def guess_payload_class(self, payload):
  7507         if isinstance(self.underlayer, Dot11):
  7508             if self.underlayer.FCfield & 0x40:
  7509                 return Dot11WEP
  7510         return Packet.guess_payload_class(self, payload)
  7511 
  7512 
  7513 capability_list = [ "res8", "res9", "short-slot", "res11",
  7514                     "res12", "DSSS-OFDM", "res14", "res15",
  7515                    "ESS", "IBSS", "CFP", "CFP-req",
  7516                    "privacy", "short-preamble", "PBCC", "agility"]
  7517 
  7518 reason_code = {0:"reserved",1:"unspec", 2:"auth-expired",
  7519                3:"deauth-ST-leaving",
  7520                4:"inactivity", 5:"AP-full", 6:"class2-from-nonauth",
  7521                7:"class3-from-nonass", 8:"disas-ST-leaving",
  7522                9:"ST-not-auth"}
  7523 
  7524 status_code = {0:"success", 1:"failure", 10:"cannot-support-all-cap",
  7525                11:"inexist-asso", 12:"asso-denied", 13:"algo-unsupported",
  7526                14:"bad-seq-num", 15:"challenge-failure",
  7527                16:"timeout", 17:"AP-full",18:"rate-unsupported" }
  7528 
  7529 class Dot11Beacon(Packet):
  7530     name = "802.11 Beacon"
  7531     fields_desc = [ LELongField("timestamp", 0),
  7532                     LEShortField("beacon_interval", 0x0064),
  7533                     FlagsField("cap", 0, 16, capability_list) ]
  7534     
  7535 
  7536 class Dot11Elt(Packet):
  7537     name = "802.11 Information Element"
  7538     fields_desc = [ ByteEnumField("ID", 0, {0:"SSID", 1:"Rates", 2: "FHset", 3:"DSset", 4:"CFset", 5:"TIM", 6:"IBSSset", 16:"challenge",
  7539                                             42:"ERPinfo", 46:"QoS Capability", 47:"ERPinfo", 48:"RSNinfo", 50:"ESRates",221:"vendor",68:"reserved"}),
  7540                     FieldLenField("len", None, "info", "B"),
  7541                     StrLenField("info", "", length_from=lambda x:x.len) ]
  7542     def mysummary(self):
  7543         if self.ID == 0:
  7544             return "SSID=%s"%repr(self.info),[Dot11]
  7545         else:
  7546             return ""
  7547 
  7548 class Dot11ATIM(Packet):
  7549     name = "802.11 ATIM"
  7550 
  7551 class Dot11Disas(Packet):
  7552     name = "802.11 Disassociation"
  7553     fields_desc = [ LEShortEnumField("reason", 1, reason_code) ]
  7554 
  7555 class Dot11AssoReq(Packet):
  7556     name = "802.11 Association Request"
  7557     fields_desc = [ FlagsField("cap", 0, 16, capability_list),
  7558                     LEShortField("listen_interval", 0x00c8) ]
  7559 
  7560 
  7561 class Dot11AssoResp(Packet):
  7562     name = "802.11 Association Response"
  7563     fields_desc = [ FlagsField("cap", 0, 16, capability_list),
  7564                     LEShortField("status", 0),
  7565                     LEShortField("AID", 0) ]
  7566 
  7567 class Dot11ReassoReq(Packet):
  7568     name = "802.11 Reassociation Request"
  7569     fields_desc = [ FlagsField("cap", 0, 16, capability_list),
  7570                     MACField("current_AP", ETHER_ANY),
  7571                     LEShortField("listen_interval", 0x00c8) ]
  7572 
  7573 
  7574 class Dot11ReassoResp(Dot11AssoResp):
  7575     name = "802.11 Reassociation Response"
  7576 
  7577 class Dot11ProbeReq(Packet):
  7578     name = "802.11 Probe Request"
  7579     
  7580 class Dot11ProbeResp(Packet):
  7581     name = "802.11 Probe Response"
  7582     fields_desc = [ LELongField("timestamp", 0),
  7583                     LEShortField("beacon_interval", 0x0064),
  7584                     FlagsField("cap", 0, 16, capability_list) ]
  7585     
  7586 class Dot11Auth(Packet):
  7587     name = "802.11 Authentication"
  7588     fields_desc = [ LEShortEnumField("algo", 0, ["open", "sharedkey"]),
  7589                     LEShortField("seqnum", 0),
  7590                     LEShortEnumField("status", 0, status_code) ]
  7591     def answers(self, other):
  7592         if self.seqnum == other.seqnum+1:
  7593             return 1
  7594         return 0
  7595 
  7596 class Dot11Deauth(Packet):
  7597     name = "802.11 Deauthentication"
  7598     fields_desc = [ LEShortEnumField("reason", 1, reason_code) ]
  7599 
  7600 
  7601 
  7602 class Dot11WEP(Packet):
  7603     name = "802.11 WEP packet"
  7604     fields_desc = [ StrFixedLenField("iv", "\0\0\0", 3),
  7605                     ByteField("keyid", 0),
  7606                     StrField("wepdata",None,remain=4),
  7607                     IntField("icv",None) ]
  7608 
  7609     def post_dissect(self, s):
  7610 #        self.icv, = struct.unpack("!I",self.wepdata[-4:])
  7611 #        self.wepdata = self.wepdata[:-4]
  7612         self.decrypt()
  7613 
  7614     def build_payload(self):
  7615         if self.wepdata is None:
  7616             return Packet.build_payload(self)
  7617         return ""
  7618 
  7619     def post_build(self, p, pay):
  7620         if self.wepdata is None:
  7621             key = conf.wepkey
  7622             if key:
  7623                 if self.icv is None:
  7624                     pay += struct.pack("<I",crc32(pay))
  7625                     icv = ""
  7626                 else:
  7627                     icv = p[4:8]
  7628                 c = ARC4.new(self.iv+key)
  7629                 p = p[:4]+c.encrypt(pay)+icv
  7630             else:
  7631                 warning("No WEP key set (conf.wepkey).. strange results expected..")
  7632         return p
  7633             
  7634 
  7635     def decrypt(self,key=None):
  7636         if key is None:
  7637             key = conf.wepkey
  7638         if key:
  7639             c = ARC4.new(self.iv+key)
  7640             self.add_payload(LLC(c.decrypt(self.wepdata)))
  7641                     
  7642 
  7643 
  7644 class PrismHeader(Packet):
  7645     """ iwpriv wlan0 monitor 3 """
  7646     name = "Prism header"
  7647     fields_desc = [ LEIntField("msgcode",68),
  7648                     LEIntField("len",144),
  7649                     StrFixedLenField("dev","",16),
  7650                     LEIntField("hosttime_did",0),
  7651                   LEShortField("hosttime_status",0),
  7652                   LEShortField("hosttime_len",0),
  7653                     LEIntField("hosttime",0),
  7654                     LEIntField("mactime_did",0),
  7655                   LEShortField("mactime_status",0),
  7656                   LEShortField("mactime_len",0),
  7657                     LEIntField("mactime",0),
  7658                     LEIntField("channel_did",0),
  7659                   LEShortField("channel_status",0),
  7660                   LEShortField("channel_len",0),
  7661                     LEIntField("channel",0),
  7662                     LEIntField("rssi_did",0),
  7663                   LEShortField("rssi_status",0),
  7664                   LEShortField("rssi_len",0),
  7665                     LEIntField("rssi",0),
  7666                     LEIntField("sq_did",0),
  7667                   LEShortField("sq_status",0),
  7668                   LEShortField("sq_len",0),
  7669                     LEIntField("sq",0),
  7670                     LEIntField("signal_did",0),
  7671                   LEShortField("signal_status",0),
  7672                   LEShortField("signal_len",0),
  7673               LESignedIntField("signal",0),
  7674                     LEIntField("noise_did",0),
  7675                   LEShortField("noise_status",0),
  7676                   LEShortField("noise_len",0),
  7677                     LEIntField("noise",0),
  7678                     LEIntField("rate_did",0),
  7679                   LEShortField("rate_status",0),
  7680                   LEShortField("rate_len",0),
  7681                     LEIntField("rate",0),
  7682                     LEIntField("istx_did",0),
  7683                   LEShortField("istx_status",0),
  7684                   LEShortField("istx_len",0),
  7685                     LEIntField("istx",0),
  7686                     LEIntField("frmlen_did",0),
  7687                   LEShortField("frmlen_status",0),
  7688                   LEShortField("frmlen_len",0),
  7689                     LEIntField("frmlen",0),
  7690                     ]
  7691     def answers(self, other):
  7692         if isinstance(other, PrismHeader):
  7693             return self.payload.answers(other.payload)
  7694         else:
  7695             return self.payload.answers(other)
  7696 
  7697 
  7698 
  7699 class HSRP(Packet):
  7700     name = "HSRP"
  7701     fields_desc = [
  7702         ByteField("version", 0),
  7703         ByteEnumField("opcode", 0, { 0:"Hello"}),
  7704         ByteEnumField("state", 16, { 16:"Active"}),
  7705         ByteField("hellotime", 3),
  7706         ByteField("holdtime", 10),
  7707         ByteField("priority", 120),
  7708         ByteField("group", 1),
  7709         ByteField("reserved", 0),
  7710         StrFixedLenField("auth","cisco",8),
  7711         IPField("virtualIP","192.168.1.1") ]
  7712         
  7713 
  7714 
  7715         
  7716         
  7717 
  7718 
  7719 class NTP(Packet):
  7720     # RFC 1769
  7721     name = "NTP"
  7722     fields_desc = [ 
  7723          BitEnumField('leap', 0, 2,
  7724                       { 0: 'nowarning',
  7725                         1: 'longminute',
  7726                         2: 'shortminute',
  7727                         3: 'notsync'}),
  7728          BitField('version', 3, 3),
  7729          BitEnumField('mode', 3, 3,
  7730                       { 0: 'reserved',
  7731                         1: 'sym_active',
  7732                         2: 'sym_passive',
  7733                         3: 'client',
  7734                         4: 'server',
  7735                         5: 'broadcast',
  7736                         6: 'control',
  7737                         7: 'private'}),
  7738          BitField('stratum', 2, 8),
  7739          BitField('poll', 0xa, 8),          ### XXX : it's a signed int
  7740          BitField('precision', 0, 8),       ### XXX : it's a signed int
  7741          FloatField('delay', 0, 32),
  7742          FloatField('dispersion', 0, 32),
  7743          IPField('id', "127.0.0.1"),
  7744          TimeStampField('ref', 0, 64),
  7745          TimeStampField('orig', -1, 64),  # -1 means current time
  7746          TimeStampField('recv', 0, 64),
  7747          TimeStampField('sent', -1, 64) 
  7748          ]
  7749     def mysummary(self):
  7750         return self.sprintf("NTP v%ir,NTP.version%, %NTP.mode%")
  7751 
  7752 
  7753 class GRE(Packet):
  7754     name = "GRE"
  7755     fields_desc = [ BitField("chksumpresent",0,1),
  7756                     BitField("reserved0",0,12),
  7757                     BitField("version",0,3),
  7758                     XShortEnumField("proto", 0x0000, ETHER_TYPES),
  7759                     ConditionalField(XShortField("chksum",None),lambda pkt:pkt.chksumpresent==1),
  7760                     ConditionalField(XShortField("reserved1",None),lambda pkt:pkt.chksumpresent==1),
  7761                     ]
  7762     def post_build(self, p, pay):
  7763         p += pay
  7764         if self.chksumpresent and self.chksum is None:
  7765             c = checksum(p)
  7766             p = p[:4]+chr((c>>8)&0xff)+chr(c&0xff)+p[6:]
  7767         return p
  7768             
  7769 
  7770 class Radius(Packet):
  7771     name = "Radius"
  7772     fields_desc = [ ByteEnumField("code", 1, {1: "Access-Request",
  7773                                               2: "Access-Accept",
  7774                                               3: "Access-Reject",
  7775                                               4: "Accounting-Request",
  7776                                               5: "Accounting-Accept",
  7777                                               6: "Accounting-Status",
  7778                                               7: "Password-Request",
  7779                                               8: "Password-Ack",
  7780                                               9: "Password-Reject",
  7781                                               10: "Accounting-Message",
  7782                                               11: "Access-Challenge",
  7783                                               12: "Status-Server",
  7784                                               13: "Status-Client",
  7785                                               21: "Resource-Free-Request",
  7786                                               22: "Resource-Free-Response",
  7787                                               23: "Resource-Query-Request",
  7788                                               24: "Resource-Query-Response",
  7789                                               25: "Alternate-Resource-Reclaim-Request",
  7790                                               26: "NAS-Reboot-Request",
  7791                                               27: "NAS-Reboot-Response",
  7792                                               29: "Next-Passcode",
  7793                                               30: "New-Pin",
  7794                                               31: "Terminate-Session",
  7795                                               32: "Password-Expired",
  7796                                               33: "Event-Request",
  7797                                               34: "Event-Response",
  7798                                               40: "Disconnect-Request",
  7799                                               41: "Disconnect-ACK",
  7800                                               42: "Disconnect-NAK",
  7801                                               43: "CoA-Request",
  7802                                               44: "CoA-ACK",
  7803                                               45: "CoA-NAK",
  7804                                               50: "IP-Address-Allocate",
  7805                                               51: "IP-Address-Release",
  7806                                               253: "Experimental-use",
  7807                                               254: "Reserved",
  7808                                               255: "Reserved"} ),
  7809                     ByteField("id", 0),
  7810                     ShortField("len", None),
  7811                     StrFixedLenField("authenticator","",16) ]
  7812     def post_build(self, p, pay):
  7813         p += pay
  7814         l = self.len
  7815         if l is None:
  7816             l = len(p)
  7817             p = p[:2]+struct.pack("!H",l)+p[4:]
  7818         return p
  7819 
  7820 
  7821 
  7822 
  7823 class RIP(Packet):
  7824     name = "RIP header"
  7825     fields_desc = [
  7826         ByteEnumField("command",1,{1:"req",2:"resp",3:"traceOn",4:"traceOff",5:"sun",
  7827                                    6:"trigReq",7:"trigResp",8:"trigAck",9:"updateReq",
  7828                                    10:"updateResp",11:"updateAck"}),
  7829         ByteField("version",1),
  7830         ShortField("null",0),
  7831         ]
  7832 
  7833 class RIPEntry(Packet):
  7834     name = "RIP entry"
  7835     fields_desc = [
  7836         ShortEnumField("AF",2,{2:"IP"}),
  7837         ShortField("RouteTag",0),
  7838         IPField("addr","0.0.0.0"),
  7839         IPField("mask","0.0.0.0"),
  7840         IPField("nextHop","0.0.0.0"),
  7841         IntEnumField("metric",1,{16:"Unreach"}),
  7842         ]
  7843         
  7844 
  7845 
  7846 
  7847 ISAKMP_payload_type = ["None","SA","Proposal","Transform","KE","ID","CERT","CR","Hash",
  7848                        "SIG","Nonce","Notification","Delete","VendorID"]
  7849 
  7850 ISAKMP_exchange_type = ["None","base","identity prot.",
  7851                         "auth only", "aggressive", "info"]
  7852 
  7853 
  7854 class ISAKMP_class(Packet):
  7855     def guess_payload_class(self, payload):
  7856         np = self.next_payload
  7857         if np == 0:
  7858             return Raw
  7859         elif np < len(ISAKMP_payload_type):
  7860             pt = ISAKMP_payload_type[np]
  7861             return globals().get("ISAKMP_payload_%s" % pt, ISAKMP_payload)
  7862         else:
  7863             return ISAKMP_payload
  7864 
  7865 
  7866 class ISAKMP(ISAKMP_class): # rfc2408
  7867     name = "ISAKMP"
  7868     fields_desc = [
  7869         StrFixedLenField("init_cookie","",8),
  7870         StrFixedLenField("resp_cookie","",8),
  7871         ByteEnumField("next_payload",0,ISAKMP_payload_type),
  7872         XByteField("version",0x10),
  7873         ByteEnumField("exch_type",0,ISAKMP_exchange_type),
  7874         FlagsField("flags",0, 8, ["encryption","commit","auth_only","res3","res4","res5","res6","res7"]), # XXX use a Flag field
  7875         IntField("id",0),
  7876         IntField("length",None)
  7877         ]
  7878 
  7879     def guess_payload_class(self, payload):
  7880         if self.flags & 1:
  7881             return Raw
  7882         return ISAKMP_class.guess_payload_class(self, payload)
  7883 
  7884     def answers(self, other):
  7885         if isinstance(other, ISAKMP):
  7886             if other.init_cookie == self.init_cookie:
  7887                 return 1
  7888         return 0
  7889     def post_build(self, p, pay):
  7890         p += pay
  7891         if self.length is None:
  7892             p = p[:24]+struct.pack("!I",len(p))+p[28:]
  7893         return p
  7894        
  7895 
  7896 
  7897 
  7898 class ISAKMP_payload_Transform(ISAKMP_class):
  7899     name = "IKE Transform"
  7900     fields_desc = [
  7901         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7902         ByteField("res",0),
  7903 #        ShortField("len",None),
  7904         ShortField("length",None),
  7905         ByteField("num",None),
  7906         ByteEnumField("id",1,{1:"KEY_IKE"}),
  7907         ShortField("res2",0),
  7908         ISAKMPTransformSetField("transforms",None,length_from=lambda x:x.length-8)
  7909 #        XIntField("enc",0x80010005L),
  7910 #        XIntField("hash",0x80020002L),
  7911 #        XIntField("auth",0x80030001L),
  7912 #        XIntField("group",0x80040002L),
  7913 #        XIntField("life_type",0x800b0001L),
  7914 #        XIntField("durationh",0x000c0004L),
  7915 #        XIntField("durationl",0x00007080L),
  7916         ]
  7917     def post_build(self, p, pay):
  7918         if self.length is None:
  7919             l = len(p)
  7920             p = p[:2]+chr((l>>8)&0xff)+chr(l&0xff)+p[4:]
  7921         p += pay
  7922         return p
  7923             
  7924 
  7925 
  7926         
  7927 class ISAKMP_payload_Proposal(ISAKMP_class):
  7928     name = "IKE proposal"
  7929 #    ISAKMP_payload_type = 0
  7930     fields_desc = [
  7931         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7932         ByteField("res",0),
  7933         FieldLenField("length",None,"trans","H", adjust=lambda pkt,x:x+8),
  7934         ByteField("proposal",1),
  7935         ByteEnumField("proto",1,{1:"ISAKMP"}),
  7936         FieldLenField("SPIsize",None,"SPI","B"),
  7937         ByteField("trans_nb",None),
  7938         StrLenField("SPI","",length_from=lambda x:x.SPIsize),
  7939         PacketLenField("trans",Raw(),ISAKMP_payload_Transform,length_from=lambda x:x.length-8),
  7940         ]
  7941 
  7942 
  7943 class ISAKMP_payload(ISAKMP_class):
  7944     name = "ISAKMP payload"
  7945     fields_desc = [
  7946         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7947         ByteField("res",0),
  7948         FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
  7949         StrLenField("load","",length_from=lambda x:x.length-4),
  7950         ]
  7951 
  7952 
  7953 class ISAKMP_payload_VendorID(ISAKMP_class):
  7954     name = "ISAKMP Vendor ID"
  7955     overload_fields = { ISAKMP: { "next_payload":13 }}
  7956     fields_desc = [
  7957         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7958         ByteField("res",0),
  7959         FieldLenField("length",None,"vendorID","H", adjust=lambda pkt,x:x+4),
  7960         StrLenField("vendorID","",length_from=lambda x:x.length-4),
  7961         ]
  7962 
  7963 class ISAKMP_payload_SA(ISAKMP_class):
  7964     name = "ISAKMP SA"
  7965     overload_fields = { ISAKMP: { "next_payload":1 }}
  7966     fields_desc = [
  7967         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7968         ByteField("res",0),
  7969         FieldLenField("length",None,"prop","H", adjust=lambda pkt,x:x+12),
  7970         IntEnumField("DOI",1,{1:"IPSEC"}),
  7971         IntEnumField("situation",1,{1:"identity"}),
  7972         PacketLenField("prop",Raw(),ISAKMP_payload_Proposal,length_from=lambda x:x.length-12),
  7973         ]
  7974 
  7975 class ISAKMP_payload_Nonce(ISAKMP_class):
  7976     name = "ISAKMP Nonce"
  7977     overload_fields = { ISAKMP: { "next_payload":10 }}
  7978     fields_desc = [
  7979         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7980         ByteField("res",0),
  7981         FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
  7982         StrLenField("load","",length_from=lambda x:x.length-4),
  7983         ]
  7984 
  7985 class ISAKMP_payload_KE(ISAKMP_class):
  7986     name = "ISAKMP Key Exchange"
  7987     overload_fields = { ISAKMP: { "next_payload":4 }}
  7988     fields_desc = [
  7989         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7990         ByteField("res",0),
  7991         FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
  7992         StrLenField("load","",length_from=lambda x:x.length-4),
  7993         ]
  7994 
  7995 class ISAKMP_payload_ID(ISAKMP_class):
  7996     name = "ISAKMP Identification"
  7997     overload_fields = { ISAKMP: { "next_payload":5 }}
  7998     fields_desc = [
  7999         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  8000         ByteField("res",0),
  8001         FieldLenField("length",None,"load","H",adjust=lambda pkt,x:x+8),
  8002         ByteEnumField("IDtype",1,{1:"IPv4_addr", 11:"Key"}),
  8003         ByteEnumField("ProtoID",0,{0:"Unused"}),
  8004         ShortEnumField("Port",0,{0:"Unused"}),
  8005 #        IPField("IdentData","127.0.0.1"),
  8006         StrLenField("load","",length_from=lambda x:x.length-8),
  8007         ]
  8008 
  8009 
  8010 
  8011 class ISAKMP_payload_Hash(ISAKMP_class):
  8012     name = "ISAKMP Hash"
  8013     overload_fields = { ISAKMP: { "next_payload":8 }}
  8014     fields_desc = [
  8015         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  8016         ByteField("res",0),
  8017         FieldLenField("length",None,"load","H",adjust=lambda pkt,x:x+4),
  8018         StrLenField("load","",length_from=lambda x:x.length-4),
  8019         ]
  8020 
  8021 
  8022 
  8023 ISAKMP_payload_type_overload = {}
  8024 for i in range(len(ISAKMP_payload_type)):
  8025     name = "ISAKMP_payload_%s" % ISAKMP_payload_type[i]
  8026     if name in globals():
  8027         ISAKMP_payload_type_overload[globals()[name]] = {"next_payload":i}
  8028 
  8029 del(i)
  8030 del(name)
  8031 ISAKMP_class.overload_fields = ISAKMP_payload_type_overload.copy()
  8032 
  8033 
  8034         
  8035 
  8036 # Cisco Skinny protocol
  8037 
  8038 # shamelessly ripped from Ethereal dissector
  8039 skinny_messages = { 
  8040 # Station -> Callmanager
  8041   0x0000: "KeepAliveMessage",
  8042   0x0001: "RegisterMessage",
  8043   0x0002: "IpPortMessage",
  8044   0x0003: "KeypadButtonMessage",
  8045   0x0004: "EnblocCallMessage",
  8046   0x0005: "StimulusMessage",
  8047   0x0006: "OffHookMessage",
  8048   0x0007: "OnHookMessage",
  8049   0x0008: "HookFlashMessage",
  8050   0x0009: "ForwardStatReqMessage",
  8051   0x000A: "SpeedDialStatReqMessage",
  8052   0x000B: "LineStatReqMessage",
  8053   0x000C: "ConfigStatReqMessage",
  8054   0x000D: "TimeDateReqMessage",
  8055   0x000E: "ButtonTemplateReqMessage",
  8056   0x000F: "VersionReqMessage",
  8057   0x0010: "CapabilitiesResMessage",
  8058   0x0011: "MediaPortListMessage",
  8059   0x0012: "ServerReqMessage",
  8060   0x0020: "AlarmMessage",
  8061   0x0021: "MulticastMediaReceptionAck",
  8062   0x0022: "OpenReceiveChannelAck",
  8063   0x0023: "ConnectionStatisticsRes",
  8064   0x0024: "OffHookWithCgpnMessage",
  8065   0x0025: "SoftKeySetReqMessage",
  8066   0x0026: "SoftKeyEventMessage",
  8067   0x0027: "UnregisterMessage",
  8068   0x0028: "SoftKeyTemplateReqMessage",
  8069   0x0029: "RegisterTokenReq",
  8070   0x002A: "MediaTransmissionFailure",
  8071   0x002B: "HeadsetStatusMessage",
  8072   0x002C: "MediaResourceNotification",
  8073   0x002D: "RegisterAvailableLinesMessage",
  8074   0x002E: "DeviceToUserDataMessage",
  8075   0x002F: "DeviceToUserDataResponseMessage",
  8076   0x0030: "UpdateCapabilitiesMessage",
  8077   0x0031: "OpenMultiMediaReceiveChannelAckMessage",
  8078   0x0032: "ClearConferenceMessage",
  8079   0x0033: "ServiceURLStatReqMessage",
  8080   0x0034: "FeatureStatReqMessage",
  8081   0x0035: "CreateConferenceResMessage",
  8082   0x0036: "DeleteConferenceResMessage",
  8083   0x0037: "ModifyConferenceResMessage",
  8084   0x0038: "AddParticipantResMessage",
  8085   0x0039: "AuditConferenceResMessage",
  8086   0x0040: "AuditParticipantResMessage",
  8087   0x0041: "DeviceToUserDataVersion1Message",
  8088 # Callmanager -> Station */
  8089   0x0081: "RegisterAckMessage",
  8090   0x0082: "StartToneMessage",
  8091   0x0083: "StopToneMessage",
  8092   0x0085: "SetRingerMessage",
  8093   0x0086: "SetLampMessage",
  8094   0x0087: "SetHkFDetectMessage",
  8095   0x0088: "SetSpeakerModeMessage",
  8096   0x0089: "SetMicroModeMessage",
  8097   0x008A: "StartMediaTransmission",
  8098   0x008B: "StopMediaTransmission",
  8099   0x008C: "StartMediaReception",
  8100   0x008D: "StopMediaReception",
  8101   0x008F: "CallInfoMessage",
  8102   0x0090: "ForwardStatMessage",
  8103   0x0091: "SpeedDialStatMessage",
  8104   0x0092: "LineStatMessage",
  8105   0x0093: "ConfigStatMessage",
  8106   0x0094: "DefineTimeDate",
  8107   0x0095: "StartSessionTransmission",
  8108   0x0096: "StopSessionTransmission",
  8109   0x0097: "ButtonTemplateMessage",
  8110   0x0098: "VersionMessage",
  8111   0x0099: "DisplayTextMessage",
  8112   0x009A: "ClearDisplay",
  8113   0x009B: "CapabilitiesReqMessage",
  8114   0x009C: "EnunciatorCommandMessage",
  8115   0x009D: "RegisterRejectMessage",
  8116   0x009E: "ServerResMessage",
  8117   0x009F: "Reset",
  8118   0x0100: "KeepAliveAckMessage",
  8119   0x0101: "StartMulticastMediaReception",
  8120   0x0102: "StartMulticastMediaTransmission",
  8121   0x0103: "StopMulticastMediaReception",
  8122   0x0104: "StopMulticastMediaTransmission",
  8123   0x0105: "OpenReceiveChannel",
  8124   0x0106: "CloseReceiveChannel",
  8125   0x0107: "ConnectionStatisticsReq",
  8126   0x0108: "SoftKeyTemplateResMessage",
  8127   0x0109: "SoftKeySetResMessage",
  8128   0x0110: "SelectSoftKeysMessage",
  8129   0x0111: "CallStateMessage",
  8130   0x0112: "DisplayPromptStatusMessage",
  8131   0x0113: "ClearPromptStatusMessage",
  8132   0x0114: "DisplayNotifyMessage",
  8133   0x0115: "ClearNotifyMessage",
  8134   0x0116: "ActivateCallPlaneMessage",
  8135   0x0117: "DeactivateCallPlaneMessage",
  8136   0x0118: "UnregisterAckMessage",
  8137   0x0119: "BackSpaceReqMessage",
  8138   0x011A: "RegisterTokenAck",
  8139   0x011B: "RegisterTokenReject",
  8140   0x0042: "DeviceToUserDataResponseVersion1Message",
  8141   0x011C: "StartMediaFailureDetection",
  8142   0x011D: "DialedNumberMessage",
  8143   0x011E: "UserToDeviceDataMessage",
  8144   0x011F: "FeatureStatMessage",
  8145   0x0120: "DisplayPriNotifyMessage",
  8146   0x0121: "ClearPriNotifyMessage",
  8147   0x0122: "StartAnnouncementMessage",
  8148   0x0123: "StopAnnouncementMessage",
  8149   0x0124: "AnnouncementFinishMessage",
  8150   0x0127: "NotifyDtmfToneMessage",
  8151   0x0128: "SendDtmfToneMessage",
  8152   0x0129: "SubscribeDtmfPayloadReqMessage",
  8153   0x012A: "SubscribeDtmfPayloadResMessage",
  8154   0x012B: "SubscribeDtmfPayloadErrMessage",
  8155   0x012C: "UnSubscribeDtmfPayloadReqMessage",
  8156   0x012D: "UnSubscribeDtmfPayloadResMessage",
  8157   0x012E: "UnSubscribeDtmfPayloadErrMessage",
  8158   0x012F: "ServiceURLStatMessage",
  8159   0x0130: "CallSelectStatMessage",
  8160   0x0131: "OpenMultiMediaChannelMessage",
  8161   0x0132: "StartMultiMediaTransmission",
  8162   0x0133: "StopMultiMediaTransmission",
  8163   0x0134: "MiscellaneousCommandMessage",
  8164   0x0135: "FlowControlCommandMessage",
  8165   0x0136: "CloseMultiMediaReceiveChannel",
  8166   0x0137: "CreateConferenceReqMessage",
  8167   0x0138: "DeleteConferenceReqMessage",
  8168   0x0139: "ModifyConferenceReqMessage",
  8169   0x013A: "AddParticipantReqMessage",
  8170   0x013B: "DropParticipantReqMessage",
  8171   0x013C: "AuditConferenceReqMessage",
  8172   0x013D: "AuditParticipantReqMessage",
  8173   0x013F: "UserToDeviceDataVersion1Message",
  8174   }
  8175 
  8176 
  8177         
  8178 class Skinny(Packet):
  8179     name="Skinny"
  8180     fields_desc = [ LEIntField("len",0),
  8181                     LEIntField("res",0),
  8182                     LEIntEnumField("msg",0,skinny_messages) ]
  8183 
  8184 _rtp_payload_types = {
  8185     # http://www.iana.org/assignments/rtp-parameters
  8186     0:  'G.711 PCMU',    3:  'GSM',
  8187     4:  'G723',    5:  'DVI4',
  8188     6:  'DVI4',    7:  'LPC',
  8189     8:  'PCMA',    9:  'G722',
  8190     10: 'L16',     11: 'L16',
  8191     12: 'QCELP',   13: 'CN',
  8192     14: 'MPA',     15: 'G728',
  8193     16: 'DVI4',    17: 'DVI4',
  8194     18: 'G729',    25: 'CelB',
  8195     26: 'JPEG',    28: 'nv',
  8196     31: 'H261',    32: 'MPV',
  8197     33: 'MP2T',    34: 'H263' }
  8198 
  8199 class RTP(Packet):
  8200     name="RTP"
  8201     fields_desc = [ BitField('version', 2, 2),
  8202                     BitField('padding', 0, 1),
  8203                     BitField('extension', 0, 1),
  8204                     BitFieldLenField('numsync', None, 4, count_of='sync'),
  8205                     BitField('marker', 0, 1),
  8206                     BitEnumField('payload', 0, 7, _rtp_payload_types),
  8207                     ShortField('sequence', 0),
  8208                     IntField('timestamp', 0),
  8209                     IntField('sourcesync', 0),
  8210                     FieldListField('sync', [], IntField("id",0), count_from=lambda pkt:pkt.numsync) ]
  8211     
  8212 ### SEBEK
  8213 
  8214 
  8215 class SebekHead(Packet):
  8216     name = "Sebek header"
  8217     fields_desc = [ XIntField("magic", 0xd0d0d0),
  8218                     ShortField("version", 1),
  8219                     ShortEnumField("type", 0, {"read":0, "write":1,
  8220                                              "socket":2, "open":3}),
  8221                     IntField("counter", 0),
  8222                     IntField("time_sec", 0),
  8223                     IntField("time_usec", 0) ]
  8224     def mysummary(self):
  8225         return self.sprintf("Sebek Header v%SebekHead.version% %SebekHead.type%")
  8226 
  8227 # we need this because Sebek headers differ between v1 and v3, and
  8228 # between v3 type socket and v3 others
  8229 
  8230 class SebekV1(Packet):
  8231     name = "Sebek v1"
  8232     fields_desc = [ IntField("pid", 0),
  8233                     IntField("uid", 0),
  8234                     IntField("fd", 0),
  8235                     StrFixedLenField("command", "", 12),
  8236                     FieldLenField("data_length", None, "data",fmt="I"),
  8237                     StrLenField("data", "", length_from=lambda x:x.data_length) ]
  8238     def mysummary(self):
  8239         if isinstance(self.underlayer, SebekHead):
  8240             return self.underlayer.sprintf("Sebek v1 %SebekHead.type% (%SebekV1.command%)")
  8241         else:
  8242             return self.sprintf("Sebek v1 (%SebekV1.command%)")
  8243 
  8244 class SebekV3(Packet):
  8245     name = "Sebek v3"
  8246     fields_desc = [ IntField("parent_pid", 0),
  8247                     IntField("pid", 0),
  8248                     IntField("uid", 0),
  8249                     IntField("fd", 0),
  8250                     IntField("inode", 0),
  8251                     StrFixedLenField("command", "", 12),
  8252                     FieldLenField("data_length", None, "data",fmt="I"),
  8253                     StrLenField("data", "", length_from=lambda x:x.data_length) ]
  8254     def mysummary(self):
  8255         if isinstance(self.underlayer, SebekHead):
  8256             return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3.command%)")
  8257         else:
  8258             return self.sprintf("Sebek v3 (%SebekV3.command%)")
  8259 
  8260 class SebekV2(SebekV3):
  8261     def mysummary(self):
  8262         if isinstance(self.underlayer, SebekHead):
  8263             return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2.command%)")
  8264         else:
  8265             return self.sprintf("Sebek v2 (%SebekV2.command%)")
  8266 
  8267 class SebekV3Sock(Packet):
  8268     name = "Sebek v2 socket"
  8269     fields_desc = [ IntField("parent_pid", 0),
  8270                     IntField("pid", 0),
  8271                     IntField("uid", 0),
  8272                     IntField("fd", 0),
  8273                     IntField("inode", 0),
  8274                     StrFixedLenField("command", "", 12),
  8275                     IntField("data_length", 15),
  8276                     IPField("dip", "127.0.0.1"),
  8277                     ShortField("dport", 0),
  8278                     IPField("sip", "127.0.0.1"),
  8279                     ShortField("sport", 0),
  8280                     ShortEnumField("call", 0, { "bind":2,
  8281                                                 "connect":3, "listen":4,
  8282                                                "accept":5, "sendmsg":16,
  8283                                                "recvmsg":17, "sendto":11,
  8284                                                "recvfrom":12}),
  8285                     ByteEnumField("proto", 0, IP_PROTOS) ]
  8286     def mysummary(self):
  8287         if isinstance(self.underlayer, SebekHead):
  8288             return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3Sock.command%)")
  8289         else:
  8290             return self.sprintf("Sebek v3 socket (%SebekV3Sock.command%)")
  8291 
  8292 class SebekV2Sock(SebekV3Sock):
  8293     def mysummary(self):
  8294         if isinstance(self.underlayer, SebekHead):
  8295             return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2Sock.command%)")
  8296         else:
  8297             return self.sprintf("Sebek v2 socket (%SebekV2Sock.command%)")
  8298 
  8299 class MGCP(Packet):
  8300     name = "MGCP"
  8301     longname = "Media Gateway Control Protocol"
  8302     fields_desc = [ StrStopField("verb","AUEP"," ", -1),
  8303                     StrFixedLenField("sep1"," ",1),
  8304                     StrStopField("transaction_id","1234567"," ", -1),
  8305                     StrFixedLenField("sep2"," ",1),
  8306                     StrStopField("endpoint","dummy@dummy.net"," ", -1),
  8307                     StrFixedLenField("sep3"," ",1),
  8308                     StrStopField("version","MGCP 1.0 NCS 1.0","\x0a", -1),
  8309                     StrFixedLenField("sep4","\x0a",1),
  8310                     ]
  8311                     
  8312     
  8313 #class MGCP(Packet):
  8314 #    name = "MGCP"
  8315 #    longname = "Media Gateway Control Protocol"
  8316 #    fields_desc = [ ByteEnumField("type",0, ["request","response","others"]),
  8317 #                    ByteField("code0",0),
  8318 #                    ByteField("code1",0),
  8319 #                    ByteField("code2",0),
  8320 #                    ByteField("code3",0),
  8321 #                    ByteField("code4",0),
  8322 #                    IntField("trasid",0),
  8323 #                    IntField("req_time",0),
  8324 #                    ByteField("is_duplicate",0),
  8325 #                    ByteField("req_available",0) ]
  8326 #
  8327 class GPRS(Packet):
  8328     name = "GPRSdummy"
  8329     fields_desc = [
  8330         StrStopField("dummy","","\x65\x00\x00",1)
  8331         ]
  8332 
  8333 
  8334 class HCI_Hdr(Packet):
  8335     name = "HCI header"
  8336     fields_desc = [ ByteEnumField("type",2,{1:"command",2:"ACLdata",3:"SCOdata",4:"event",5:"vendor"}),]
  8337 
  8338     def mysummary(self):
  8339         return self.sprintf("HCI %type%")
  8340 
  8341 class HCI_ACL_Hdr(Packet):
  8342     name = "HCI ACL header"
  8343     fields_desc = [ ByteField("handle",0), # Actually, handle is 12 bits and flags is 4.
  8344                     ByteField("flags",0),  # I wait to write a LEBitField
  8345                     LEShortField("len",None), ]
  8346     def post_build(self, p, pay):
  8347         p += pay
  8348         if self.len is None:
  8349             l = len(p)-4
  8350             p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
  8351         return p
  8352                     
  8353 
  8354 class L2CAP_Hdr(Packet):
  8355     name = "L2CAP header"
  8356     fields_desc = [ LEShortField("len",None),
  8357                     LEShortEnumField("cid",0,{1:"control"}),]
  8358     
  8359     def post_build(self, p, pay):
  8360         p += pay
  8361         if self.len is None:
  8362             l = len(p)-4
  8363             p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
  8364         return p
  8365                     
  8366                 
  8367 
  8368 class L2CAP_CmdHdr(Packet):
  8369     name = "L2CAP command header"
  8370     fields_desc = [
  8371         ByteEnumField("code",8,{1:"rej",2:"conn_req",3:"conn_resp",
  8372                                 4:"conf_req",5:"conf_resp",6:"disconn_req",
  8373                                 7:"disconn_resp",8:"echo_req",9:"echo_resp",
  8374                                 10:"info_req",11:"info_resp"}),
  8375         ByteField("id",0),
  8376         LEShortField("len",None) ]
  8377     def post_build(self, p, pay):
  8378         p += pay
  8379         if self.len is None:
  8380             l = len(p)-4
  8381             p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
  8382         return p
  8383     def answers(self, other):
  8384         if other.id == self.id:
  8385             if self.code == 1:
  8386                 return 1
  8387             if other.code in [2,4,6,8,10] and self.code == other.code+1:
  8388                 if other.code == 8:
  8389                     return 1
  8390                 return self.payload.answers(other.payload)
  8391         return 0
  8392 
  8393 class L2CAP_ConnReq(Packet):
  8394     name = "L2CAP Conn Req"
  8395     fields_desc = [ LEShortEnumField("psm",0,{1:"SDP",3:"RFCOMM",5:"telephony control"}),
  8396                     LEShortField("scid",0),
  8397                     ]
  8398 
  8399 class L2CAP_ConnResp(Packet):
  8400     name = "L2CAP Conn Resp"
  8401     fields_desc = [ LEShortField("dcid",0),
  8402                     LEShortField("scid",0),
  8403                     LEShortEnumField("result",0,["no_info","authen_pend","author_pend"]),
  8404                     LEShortEnumField("status",0,["success","pend","bad_psm",
  8405                                                "cr_sec_block","cr_no_mem"]),
  8406                     ]
  8407     def answers(self, other):
  8408         return self.scid == other.scid
  8409 
  8410 class L2CAP_CmdRej(Packet):
  8411     name = "L2CAP Command Rej"
  8412     fields_desc = [ LEShortField("reason",0),
  8413                     ]
  8414     
  8415 
  8416 class L2CAP_ConfReq(Packet):
  8417     name = "L2CAP Conf Req"
  8418     fields_desc = [ LEShortField("dcid",0),
  8419                     LEShortField("flags",0),
  8420                     ]
  8421 
  8422 class L2CAP_ConfResp(Packet):
  8423     name = "L2CAP Conf Resp"
  8424     fields_desc = [ LEShortField("scid",0),
  8425                     LEShortField("flags",0),
  8426                     LEShortEnumField("result",0,["success","unaccept","reject","unknown"]),
  8427                     ]
  8428     def answers(self, other):
  8429         return self.scid == other.scid
  8430 
  8431 
  8432 class L2CAP_DisconnReq(Packet):
  8433     name = "L2CAP Disconn Req"
  8434     fields_desc = [ LEShortField("dcid",0),
  8435                     LEShortField("scid",0), ]
  8436 
  8437 class L2CAP_DisconnResp(Packet):
  8438     name = "L2CAP Disconn Resp"
  8439     fields_desc = [ LEShortField("dcid",0),
  8440                     LEShortField("scid",0), ]
  8441     def answers(self, other):
  8442         return self.scid == other.scid
  8443 
  8444     
  8445 
  8446 class L2CAP_InfoReq(Packet):
  8447     name = "L2CAP Info Req"
  8448     fields_desc = [ LEShortEnumField("type",0,{1:"CL_MTU",2:"FEAT_MASK"}),
  8449                     StrField("data","")
  8450                     ]
  8451 
  8452 
  8453 class L2CAP_InfoResp(Packet):
  8454     name = "L2CAP Info Resp"
  8455     fields_desc = [ LEShortField("type",0),
  8456                     LEShortEnumField("result",0,["success","not_supp"]),
  8457                     StrField("data",""), ]
  8458     def answers(self, other):
  8459         return self.type == other.type
  8460 
  8461 
  8462 
  8463 
  8464 class NetBIOS_DS(Packet):
  8465     name = "NetBIOS datagram service"
  8466     fields_desc = [
  8467         ByteEnumField("type",17, {17:"direct_group"}),
  8468         ByteField("flags",0),
  8469         XShortField("id",0),
  8470         IPField("src","127.0.0.1"),
  8471         ShortField("sport",138),
  8472         ShortField("len",None),
  8473         ShortField("ofs",0),
  8474         NetBIOSNameField("srcname",""),
  8475         NetBIOSNameField("dstname",""),
  8476         ]
  8477     def post_build(self, p, pay):
  8478         p += pay
  8479         if self.len is None:
  8480             l = len(p)-14
  8481             p = p[:10]+struct.pack("!H", l)+p[12:]
  8482         return p
  8483         
  8484 #        ShortField("length",0),
  8485 #        ShortField("Delimitor",0),
  8486 #        ByteField("command",0),
  8487 #        ByteField("data1",0),
  8488 #        ShortField("data2",0),
  8489 #        ShortField("XMIt",0),
  8490 #        ShortField("RSPCor",0),
  8491 #        StrFixedLenField("dest","",16),
  8492 #        StrFixedLenField("source","",16),
  8493 #        
  8494 #        ]
  8495 #
  8496 
  8497 # IR
  8498 
  8499 class IrLAPHead(Packet):
  8500     name = "IrDA Link Access Protocol Header"
  8501     fields_desc = [ XBitField("Address", 0x7f, 7),
  8502                     BitEnumField("Type", 1, 1, {"Response":0,
  8503                                                 "Command":1})]
  8504 
  8505 class IrLAPCommand(Packet):
  8506     name = "IrDA Link Access Protocol Command"
  8507     fields_desc = [ XByteField("Control", 0),
  8508                     XByteField("Format identifier", 0),
  8509                     XIntField("Source address", 0),
  8510                     XIntField("Destination address", 0xffffffffL),
  8511                     XByteField("Discovery flags", 0x1),
  8512                     ByteEnumField("Slot number", 255, {"final":255}),
  8513                     XByteField("Version", 0)]
  8514 
  8515 
  8516 class IrLMP(Packet):
  8517     name = "IrDA Link Management Protocol"
  8518     fields_desc = [ XShortField("Service hints", 0),
  8519                     XByteField("Character set", 0),
  8520                     StrField("Device name", "") ]
  8521 
  8522 
  8523 #NetBIOS
  8524 
  8525 
  8526 # Name Query Request
  8527 # Node Status Request
  8528 class NBNSQueryRequest(Packet):
  8529     name="NBNS query request"
  8530     fields_desc = [ShortField("NAME_TRN_ID",0),
  8531                    ShortField("FLAGS", 0x0110),
  8532                    ShortField("QDCOUNT",1),
  8533                    ShortField("ANCOUNT",0),
  8534                    ShortField("NSCOUNT",0),
  8535                    ShortField("ARCOUNT",0),
  8536                    NetBIOSNameField("QUESTION_NAME","windows"),
  8537                    ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  8538                    ByteField("NULL",0),
  8539                    ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8540                    ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"})]
  8541 
  8542 # Name Registration Request
  8543 # Name Refresh Request
  8544 # Name Release Request or Demand
  8545 class NBNSRequest(Packet):
  8546     name="NBNS request"
  8547     fields_desc = [ShortField("NAME_TRN_ID",0),
  8548                    ShortField("FLAGS", 0x2910),
  8549                    ShortField("QDCOUNT",1),
  8550                    ShortField("ANCOUNT",0),
  8551                    ShortField("NSCOUNT",0),
  8552                    ShortField("ARCOUNT",1),
  8553                    NetBIOSNameField("QUESTION_NAME","windows"),
  8554                    ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  8555                    ByteField("NULL",0),
  8556                    ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8557                    ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"}),
  8558                    ShortEnumField("RR_NAME",0xC00C,{0xC00C:"Label String Pointer to QUESTION_NAME"}),
  8559                    ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8560                    ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  8561                    IntField("TTL", 0),
  8562                    ShortField("RDLENGTH", 6),
  8563                    BitEnumField("G",0,1,{0:"Unique name",1:"Group name"}),
  8564                    BitEnumField("OWNER NODE TYPE",00,2,{00:"B node",01:"P node",02:"M node",03:"H node"}),
  8565                    BitEnumField("UNUSED",0,13,{0:"Unused"}),
  8566                    IPField("NB_ADDRESS", "127.0.0.1")]
  8567 
  8568 # Name Query Response
  8569 # Name Registration Response
  8570 class NBNSQueryResponse(Packet):
  8571     name="NBNS query response"
  8572     fields_desc = [ShortField("NAME_TRN_ID",0),
  8573                    ShortField("FLAGS", 0x8500),
  8574                    ShortField("QDCOUNT",0),
  8575                    ShortField("ANCOUNT",1),
  8576                    ShortField("NSCOUNT",0),
  8577                    ShortField("ARCOUNT",0),
  8578                    NetBIOSNameField("RR_NAME","windows"),
  8579                    ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  8580                    ByteField("NULL",0),
  8581                    ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8582                    ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"}),
  8583                    IntField("TTL", 0x493e0),
  8584                    ShortField("RDLENGTH", 6),
  8585                    ShortField("NB_FLAGS", 0),
  8586                    IPField("NB_ADDRESS", "127.0.0.1")]
  8587 
  8588 # Name Query Response (negative)
  8589 # Name Release Response
  8590 class NBNSQueryResponseNegative(Packet):
  8591     name="NBNS query response (negative)"
  8592     fields_desc = [ShortField("NAME_TRN_ID",0), 
  8593                    ShortField("FLAGS", 0x8506),
  8594                    ShortField("QDCOUNT",0),
  8595                    ShortField("ANCOUNT",1),
  8596                    ShortField("NSCOUNT",0),
  8597                    ShortField("ARCOUNT",0),
  8598                    NetBIOSNameField("RR_NAME","windows"),
  8599                    ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  8600                    ByteField("NULL",0),
  8601                    ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8602                    ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  8603                    IntField("TTL",0),
  8604                    ShortField("RDLENGTH",6),
  8605                    BitEnumField("G",0,1,{0:"Unique name",1:"Group name"}),
  8606                    BitEnumField("OWNER NODE TYPE",00,2,{00:"B node",01:"P node",02:"M node",03:"H node"}),
  8607                    BitEnumField("UNUSED",0,13,{0:"Unused"}),
  8608                    IPField("NB_ADDRESS", "127.0.0.1")]
  8609     
  8610 # Node Status Response
  8611 class NBNSNodeStatusResponse(Packet):
  8612     name="NBNS Node Status Response"
  8613     fields_desc = [ShortField("NAME_TRN_ID",0), 
  8614                    ShortField("FLAGS", 0x8500),
  8615                    ShortField("QDCOUNT",0),
  8616                    ShortField("ANCOUNT",1),
  8617                    ShortField("NSCOUNT",0),
  8618                    ShortField("ARCOUNT",0),
  8619                    NetBIOSNameField("RR_NAME","windows"),
  8620                    ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  8621                    ByteField("NULL",0),
  8622                    ShortEnumField("RR_TYPE",0x21, {0x20:"NB",0x21:"NBSTAT"}),
  8623                    ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  8624                    IntField("TTL",0),
  8625                    ShortField("RDLENGTH",83),
  8626                    ByteField("NUM_NAMES",1)]
  8627 
  8628 # Service for Node Status Response
  8629 class NBNSNodeStatusResponseService(Packet):
  8630     name="NBNS Node Status Response Service"
  8631     fields_desc = [StrFixedLenField("NETBIOS_NAME","WINDOWS         ",15),
  8632                    ByteEnumField("SUFFIX",0,{0:"workstation",0x03:"messenger service",0x20:"file server service",0x1b:"domain master browser",0x1c:"domain controller", 0x1e:"browser election service"}),
  8633                    ByteField("NAME_FLAGS",0x4),
  8634                    ByteEnumField("UNUSED",0,{0:"unused"})]
  8635 
  8636 # End of Node Status Response packet
  8637 class NBNSNodeStatusResponseEnd(Packet):
  8638     name="NBNS Node Status Response"
  8639     fields_desc = [SourceMACField("MAC_ADDRESS"),
  8640                    BitField("STATISTICS",0,57*8)]
  8641 
  8642 # Wait for Acknowledgement Response
  8643 class NBNSWackResponse(Packet):
  8644     name="NBNS Wait for Acknowledgement Response"
  8645     fields_desc = [ShortField("NAME_TRN_ID",0),
  8646                    ShortField("FLAGS", 0xBC07),
  8647                    ShortField("QDCOUNT",0),
  8648                    ShortField("ANCOUNT",1),
  8649                    ShortField("NSCOUNT",0),
  8650                    ShortField("ARCOUNT",0),
  8651                    NetBIOSNameField("RR_NAME","windows"),
  8652                    ShortEnumField("SUFFIX",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  8653                    ByteField("NULL",0),
  8654                    ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8655                    ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  8656                    IntField("TTL", 2),
  8657                    ShortField("RDLENGTH",2),
  8658                    BitField("RDATA",10512,16)] #10512=0010100100010000
  8659 
  8660 class NBTDatagram(Packet):
  8661     name="NBT Datagram Packet"
  8662     fields_desc= [ByteField("Type", 0x10),
  8663                   ByteField("Flags", 0x02),
  8664                   ShortField("ID", 0),
  8665                   IPField("SourceIP", "127.0.0.1"),
  8666                   ShortField("SourcePort", 138),
  8667                   ShortField("Length", 272),
  8668                   ShortField("Offset", 0),
  8669                   NetBIOSNameField("SourceName","windows"),
  8670                   ShortEnumField("SUFFIX1",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  8671                   ByteField("NULL",0),
  8672                   NetBIOSNameField("DestinationName","windows"),
  8673                   ShortEnumField("SUFFIX2",0x4141,{0x4141:"workstation",0x4141+0x03:"messenger service",0x4141+0x200:"file server service",0x4141+0x10b:"domain master browser",0x4141+0x10c:"domain controller", 0x4141+0x10e:"browser election service"}),
  8674                   ByteField("NULL",0)]
  8675     
  8676 
  8677 class NBTSession(Packet):
  8678     name="NBT Session Packet"
  8679     fields_desc= [ByteEnumField("TYPE",0,{0x00:"Session Message",0x81:"Session Request",0x82:"Positive Session Response",0x83:"Negative Session Response",0x84:"Retarget Session Response",0x85:"Session Keepalive"}),
  8680                   BitField("RESERVED",0x00,7),
  8681                   BitField("LENGTH",0,17)]
  8682 
  8683 
  8684 # SMB NetLogon Response Header
  8685 class SMBNetlogon_Protocol_Response_Header(Packet):
  8686     name="SMBNetlogon Protocol Response Header"
  8687     fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  8688                    ByteEnumField("Command",0x25,{0x25:"Trans"}),
  8689                    ByteField("Error_Class",0x02),
  8690                    ByteField("Reserved",0),
  8691                    LEShortField("Error_code",4),
  8692                    ByteField("Flags",0),
  8693                    LEShortField("Flags2",0x0000),
  8694                    LEShortField("PIDHigh",0x0000),
  8695                    LELongField("Signature",0x0),
  8696                    LEShortField("Unused",0x0),
  8697                    LEShortField("TID",0),
  8698                    LEShortField("PID",0),
  8699                    LEShortField("UID",0),
  8700                    LEShortField("MID",0),
  8701                    ByteField("WordCount",17),
  8702                    LEShortField("TotalParamCount",0),
  8703                    LEShortField("TotalDataCount",112),
  8704                    LEShortField("MaxParamCount",0),
  8705                    LEShortField("MaxDataCount",0),
  8706                    ByteField("MaxSetupCount",0),
  8707                    ByteField("unused2",0),
  8708                    LEShortField("Flags3",0),
  8709                    ByteField("TimeOut1",0xe8),
  8710                    ByteField("TimeOut2",0x03),
  8711                    LEShortField("unused3",0),
  8712                    LEShortField("unused4",0),
  8713                    LEShortField("ParamCount2",0),
  8714                    LEShortField("ParamOffset",0),
  8715                    LEShortField("DataCount",112),
  8716                    LEShortField("DataOffset",92),
  8717                    ByteField("SetupCount", 3),
  8718                    ByteField("unused5", 0)]
  8719 
  8720 # SMB MailSlot Protocol
  8721 class SMBMailSlot(Packet):
  8722     name = "SMB Mail Slot Protocol"
  8723     fields_desc = [LEShortField("opcode", 1),
  8724                    LEShortField("priority", 1),
  8725                    LEShortField("class", 2),
  8726                    LEShortField("size", 135),
  8727                    StrNullField("name","\MAILSLOT\NET\GETDC660")]
  8728 
  8729 # SMB NetLogon Protocol Response Tail SAM
  8730 class SMBNetlogon_Protocol_Response_Tail_SAM(Packet):
  8731     name = "SMB Netlogon Protocol Response Tail SAM"
  8732     fields_desc = [ByteEnumField("Command", 0x17, {0x12:"SAM logon request", 0x17:"SAM Active directory Response"}),
  8733                    ByteField("unused", 0),
  8734                    ShortField("Data1", 0),
  8735                    ShortField("Data2", 0xfd01),
  8736                    ShortField("Data3", 0),
  8737                    ShortField("Data4", 0xacde),
  8738                    ShortField("Data5", 0x0fe5),
  8739                    ShortField("Data6", 0xd10a),
  8740                    ShortField("Data7", 0x374c),
  8741                    ShortField("Data8", 0x83e2),
  8742                    ShortField("Data9", 0x7dd9),
  8743                    ShortField("Data10", 0x3a16),
  8744                    ShortField("Data11", 0x73ff),
  8745                    ByteField("Data12", 0x04),
  8746                    StrFixedLenField("Data13", "rmff", 4),
  8747                    ByteField("Data14", 0x0),
  8748                    ShortField("Data16", 0xc018),
  8749                    ByteField("Data18", 0x0a),
  8750                    StrFixedLenField("Data20", "rmff-win2k", 10),
  8751                    ByteField("Data21", 0xc0),
  8752                    ShortField("Data22", 0x18c0),
  8753                    ShortField("Data23", 0x180a),
  8754                    StrFixedLenField("Data24", "RMFF-WIN2K", 10),
  8755                    ShortField("Data25", 0),
  8756                    ByteField("Data26", 0x17),
  8757                    StrFixedLenField("Data27", "Default-First-Site-Name", 23),
  8758                    ShortField("Data28", 0x00c0),
  8759                    ShortField("Data29", 0x3c10),
  8760                    ShortField("Data30", 0x00c0),
  8761                    ShortField("Data31", 0x0200),
  8762                    ShortField("Data32", 0x0),
  8763                    ShortField("Data33", 0xac14),
  8764                    ShortField("Data34", 0x0064),
  8765                    ShortField("Data35", 0x0),
  8766                    ShortField("Data36", 0x0),
  8767                    ShortField("Data37", 0x0),
  8768                    ShortField("Data38", 0x0),
  8769                    ShortField("Data39", 0x0d00),
  8770                    ShortField("Data40", 0x0),
  8771                    ShortField("Data41", 0xffff)]                   
  8772 
  8773 # SMB NetLogon Protocol Response Tail LM2.0
  8774 class SMBNetlogon_Protocol_Response_Tail_LM20(Packet):
  8775     name = "SMB Netlogon Protocol Response Tail LM20"
  8776     fields_desc = [ByteEnumField("Command",0x06,{0x06:"LM 2.0 Response to logon request"}),
  8777                    ByteField("unused", 0),
  8778                    StrFixedLenField("DblSlash", "\\\\", 2),
  8779                    StrNullField("ServerName","WIN"),
  8780                    LEShortField("LM20Token", 0xffff)]
  8781 
  8782 # SMBNegociate Protocol Request Header
  8783 class SMBNegociate_Protocol_Request_Header(Packet):
  8784     name="SMBNegociate Protocol Request Header"
  8785     fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  8786                    ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  8787                    ByteField("Error_Class",0),
  8788                    ByteField("Reserved",0),
  8789                    LEShortField("Error_code",0),
  8790                    ByteField("Flags",0x18),
  8791                    LEShortField("Flags2",0x0000),
  8792                    LEShortField("PIDHigh",0x0000),
  8793                    LELongField("Signature",0x0),
  8794                    LEShortField("Unused",0x0),
  8795                    LEShortField("TID",0),
  8796                    LEShortField("PID",1),
  8797                    LEShortField("UID",0),
  8798                    LEShortField("MID",2),
  8799                    ByteField("WordCount",0),
  8800                    LEShortField("ByteCount",12)]
  8801 
  8802 # SMB Negociate Protocol Request Tail
  8803 class SMBNegociate_Protocol_Request_Tail(Packet):
  8804     name="SMB Negociate Protocol Request Tail"
  8805     fields_desc=[ByteField("BufferFormat",0x02),
  8806                  StrNullField("BufferData","NT LM 0.12")]
  8807 
  8808 # SMBNegociate Protocol Response Advanced Security
  8809 class SMBNegociate_Protocol_Response_Advanced_Security(Packet):
  8810     name="SMBNegociate Protocol Response Advanced Security"
  8811     fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  8812                    ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  8813                    ByteField("Error_Class",0),
  8814                    ByteField("Reserved",0),
  8815                    LEShortField("Error_Code",0),
  8816                    ByteField("Flags",0x98),
  8817                    LEShortField("Flags2",0x0000),
  8818                    LEShortField("PIDHigh",0x0000),
  8819                    LELongField("Signature",0x0),
  8820                    LEShortField("Unused",0x0),
  8821                    LEShortField("TID",0),
  8822                    LEShortField("PID",1),
  8823                    LEShortField("UID",0),
  8824                    LEShortField("MID",2),
  8825                    ByteField("WordCount",17),
  8826                    LEShortField("DialectIndex",7),
  8827                    ByteField("SecurityMode",0x03),
  8828                    LEShortField("MaxMpxCount",50),
  8829                    LEShortField("MaxNumberVC",1),
  8830                    LEIntField("MaxBufferSize",16144),
  8831                    LEIntField("MaxRawSize",65536),
  8832                    LEIntField("SessionKey",0x0000),
  8833                    LEShortField("ServerCapabilities",0xf3f9),
  8834                    BitField("UnixExtensions",0,1),
  8835                    BitField("Reserved2",0,7),
  8836                    BitField("ExtendedSecurity",1,1),
  8837                    BitField("CompBulk",0,2),
  8838                    BitField("Reserved3",0,5),
  8839 # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
  8840                    LEIntField("ServerTimeHigh",0xD6228000L),
  8841                    LEIntField("ServerTimeLow",0x1C4EF94),
  8842                    LEShortField("ServerTimeZone",0x3c),
  8843                    ByteField("EncryptionKeyLength",0),
  8844                    LEFieldLenField("ByteCount", None, "SecurityBlob", adjust=lambda pkt,x:x-16),
  8845                    BitField("GUID",0,128),
  8846                    StrLenField("SecurityBlob", "", length_from=lambda x:x.ByteCount+16)]
  8847 
  8848 # SMBNegociate Protocol Response No Security
  8849 # When using no security, with EncryptionKeyLength=8, you must have an EncryptionKey before the DomainName
  8850 class SMBNegociate_Protocol_Response_No_Security(Packet):
  8851     name="SMBNegociate Protocol Response No Security"
  8852     fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  8853                    ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  8854                    ByteField("Error_Class",0),
  8855                    ByteField("Reserved",0),
  8856                    LEShortField("Error_Code",0),
  8857                    ByteField("Flags",0x98),
  8858                    LEShortField("Flags2",0x0000),
  8859                    LEShortField("PIDHigh",0x0000),
  8860                    LELongField("Signature",0x0),
  8861                    LEShortField("Unused",0x0),
  8862                    LEShortField("TID",0),
  8863                    LEShortField("PID",1),
  8864                    LEShortField("UID",0),
  8865                    LEShortField("MID",2),
  8866                    ByteField("WordCount",17),
  8867                    LEShortField("DialectIndex",7),
  8868                    ByteField("SecurityMode",0x03),
  8869                    LEShortField("MaxMpxCount",50),
  8870                    LEShortField("MaxNumberVC",1),
  8871                    LEIntField("MaxBufferSize",16144),
  8872                    LEIntField("MaxRawSize",65536),
  8873                    LEIntField("SessionKey",0x0000),
  8874                    LEShortField("ServerCapabilities",0xf3f9),
  8875                    BitField("UnixExtensions",0,1),
  8876                    BitField("Reserved2",0,7),
  8877                    BitField("ExtendedSecurity",0,1),
  8878                    FlagsField("CompBulk",0,2,"CB"),
  8879                    BitField("Reserved3",0,5),
  8880                    # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
  8881                    LEIntField("ServerTimeHigh",0xD6228000L),
  8882                    LEIntField("ServerTimeLow",0x1C4EF94),
  8883                    LEShortField("ServerTimeZone",0x3c),
  8884                    ByteField("EncryptionKeyLength",8),
  8885                    LEShortField("ByteCount",24),
  8886                    BitField("EncryptionKey",0,64),
  8887                    StrNullField("DomainName","WORKGROUP"),
  8888                    StrNullField("ServerName","RMFF1")]
  8889     
  8890 # SMBNegociate Protocol Response No Security No Key
  8891 class SMBNegociate_Protocol_Response_No_Security_No_Key(Packet):
  8892     namez="SMBNegociate Protocol Response No Security No Key"
  8893     fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  8894                    ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  8895                    ByteField("Error_Class",0),
  8896                    ByteField("Reserved",0),
  8897                    LEShortField("Error_Code",0),
  8898                    ByteField("Flags",0x98),
  8899                    LEShortField("Flags2",0x0000),
  8900                    LEShortField("PIDHigh",0x0000),
  8901                    LELongField("Signature",0x0),
  8902                    LEShortField("Unused",0x0),
  8903                    LEShortField("TID",0),
  8904                    LEShortField("PID",1),
  8905                    LEShortField("UID",0),
  8906                    LEShortField("MID",2),
  8907                    ByteField("WordCount",17),
  8908                    LEShortField("DialectIndex",7),
  8909                    ByteField("SecurityMode",0x03),
  8910                    LEShortField("MaxMpxCount",50),
  8911                    LEShortField("MaxNumberVC",1),
  8912                    LEIntField("MaxBufferSize",16144),
  8913                    LEIntField("MaxRawSize",65536),
  8914                    LEIntField("SessionKey",0x0000),
  8915                    LEShortField("ServerCapabilities",0xf3f9),
  8916                    BitField("UnixExtensions",0,1),
  8917                    BitField("Reserved2",0,7),
  8918                    BitField("ExtendedSecurity",0,1),
  8919                    FlagsField("CompBulk",0,2,"CB"),
  8920                    BitField("Reserved3",0,5),
  8921                    # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
  8922                    LEIntField("ServerTimeHigh",0xD6228000L),
  8923                    LEIntField("ServerTimeLow",0x1C4EF94),
  8924                    LEShortField("ServerTimeZone",0x3c),
  8925                    ByteField("EncryptionKeyLength",0),
  8926                    LEShortField("ByteCount",16),
  8927                    StrNullField("DomainName","WORKGROUP"),
  8928                    StrNullField("ServerName","RMFF1")]
  8929     
  8930 # Session Setup AndX Request
  8931 class SMBSession_Setup_AndX_Request(Packet):
  8932     name="Session Setup AndX Request"
  8933     fields_desc=[StrFixedLenField("Start","\xffSMB",4),
  8934                 ByteEnumField("Command",0x73,{0x73:"SMB_COM_SESSION_SETUP_ANDX"}),
  8935                  ByteField("Error_Class",0),
  8936                  ByteField("Reserved",0),
  8937                  LEShortField("Error_Code",0),
  8938                  ByteField("Flags",0x18),
  8939                  LEShortField("Flags2",0x0001),
  8940                  LEShortField("PIDHigh",0x0000),
  8941                  LELongField("Signature",0x0),
  8942                  LEShortField("Unused",0x0),
  8943                  LEShortField("TID",0),
  8944                  LEShortField("PID",1),
  8945                  LEShortField("UID",0),
  8946                  LEShortField("MID",2),
  8947                  ByteField("WordCount",13),
  8948                  ByteEnumField("AndXCommand",0x75,{0x75:"SMB_COM_TREE_CONNECT_ANDX"}),
  8949                  ByteField("Reserved2",0),
  8950                  LEShortField("AndXOffset",96),
  8951                  LEShortField("MaxBufferS",2920),
  8952                  LEShortField("MaxMPXCount",50),
  8953                  LEShortField("VCNumber",0),
  8954                  LEIntField("SessionKey",0),
  8955                  LEFieldLenField("ANSIPasswordLength",None,"ANSIPassword"),
  8956                  LEShortField("UnicodePasswordLength",0),
  8957                  LEIntField("Reserved3",0),
  8958                  LEShortField("ServerCapabilities",0x05),
  8959                  BitField("UnixExtensions",0,1),
  8960                  BitField("Reserved4",0,7),
  8961                  BitField("ExtendedSecurity",0,1),
  8962                  BitField("CompBulk",0,2),
  8963                  BitField("Reserved5",0,5),
  8964                  LEShortField("ByteCount",35),
  8965                  StrLenField("ANSIPassword", "Pass",length_from=lambda x:x.ANSIPasswordLength),
  8966                  StrNullField("Account","GUEST"),
  8967                  StrNullField("PrimaryDomain",  ""),
  8968                  StrNullField("NativeOS","Windows 4.0"),
  8969                  StrNullField("NativeLanManager","Windows 4.0"),
  8970                  ByteField("WordCount2",4),
  8971                  ByteEnumField("AndXCommand2",0xFF,{0xFF:"SMB_COM_NONE"}),
  8972                  ByteField("Reserved6",0),
  8973                  LEShortField("AndXOffset2",0),
  8974                  LEShortField("Flags3",0x2),
  8975                  LEShortField("PasswordLength",0x1),
  8976                  LEShortField("ByteCount2",18),
  8977                  ByteField("Password",0),
  8978                  StrNullField("Path","\\\\WIN2K\\IPC$"),
  8979                  StrNullField("Service","IPC")]
  8980 
  8981 # Session Setup AndX Response
  8982 class SMBSession_Setup_AndX_Response(Packet):
  8983     name="Session Setup AndX Response"
  8984     fields_desc=[StrFixedLenField("Start","\xffSMB",4),
  8985                  ByteEnumField("Command",0x73,{0x73:"SMB_COM_SESSION_SETUP_ANDX"}),
  8986                  ByteField("Error_Class",0),
  8987                  ByteField("Reserved",0),
  8988                  LEShortField("Error_Code",0),
  8989                  ByteField("Flags",0x90),
  8990                  LEShortField("Flags2",0x1001),
  8991                  LEShortField("PIDHigh",0x0000),
  8992                  LELongField("Signature",0x0),
  8993                  LEShortField("Unused",0x0),
  8994                  LEShortField("TID",0),
  8995                  LEShortField("PID",1),
  8996                  LEShortField("UID",0),
  8997                  LEShortField("MID",2),
  8998                  ByteField("WordCount",3),
  8999                  ByteEnumField("AndXCommand",0x75,{0x75:"SMB_COM_TREE_CONNECT_ANDX"}),
  9000                  ByteField("Reserved2",0),
  9001                  LEShortField("AndXOffset",66),
  9002                  LEShortField("Action",0),
  9003                  LEShortField("ByteCount",25),
  9004                  StrNullField("NativeOS","Windows 4.0"),
  9005                  StrNullField("NativeLanManager","Windows 4.0"),
  9006                  StrNullField("PrimaryDomain",""),
  9007                  ByteField("WordCount2",3),
  9008                  ByteEnumField("AndXCommand2",0xFF,{0xFF:"SMB_COM_NONE"}),
  9009                  ByteField("Reserved3",0),
  9010                  LEShortField("AndXOffset2",80),
  9011                  LEShortField("OptionalSupport",0x01),
  9012                  LEShortField("ByteCount2",5),
  9013                  StrNullField("Service","IPC"),
  9014                  StrNullField("NativeFileSystem","")]
  9015 
  9016 class MobileIP(Packet):
  9017     name = "Mobile IP (RFC3344)"
  9018     fields_desc = [ ByteEnumField("type", 1, {1:"RRQ", 3:"RRP"}) ]
  9019 
  9020 class MobileIPRRQ(Packet):
  9021     name = "Mobile IP Registration Request (RFC3344)"
  9022     fields_desc = [ XByteField("flags", 0),
  9023                     ShortField("lifetime", 180),
  9024                     IPField("homeaddr", "0.0.0.0"),
  9025                     IPField("haaddr", "0.0.0.0"),
  9026                     IPField("coaddr", "0.0.0.0"),
  9027                     Field("id", "", "64s") ]
  9028 
  9029 class MobileIPRRP(Packet):
  9030     name = "Mobile IP Registration Reply (RFC3344)"
  9031     fields_desc = [ ByteField("code", 0),
  9032                     ShortField("lifetime", 180),
  9033                     IPField("homeaddr", "0.0.0.0"),
  9034                     IPField("haaddr", "0.0.0.0"),
  9035                     Field("id", "", "64s") ]
  9036 
  9037 class MobileIPTunnelData(Packet):
  9038     name = "Mobile IP Tunnel Data Message (RFC3519)"
  9039     fields_desc = [ ByteField("nexthdr", 4),
  9040                     ShortField("res", 0) ]
  9041 
  9042 
  9043 # Cisco Netflow Protocol version 1
  9044 class NetflowHeader(Packet):
  9045     name = "Netflow Header"
  9046     fields_desc = [ ShortField("version", 1) ]
  9047     
  9048 class NetflowHeaderV1(Packet):
  9049     name = "Netflow Header V1"
  9050     fields_desc = [ ShortField("count", 0),
  9051                     IntField("sysUptime", 0),
  9052                     IntField("unixSecs", 0),
  9053                     IntField("unixNanoSeconds", 0) ]
  9054 
  9055 
  9056 class NetflowRecordV1(Packet):
  9057     name = "Netflow Record"
  9058     fields_desc = [ IPField("ipsrc", "0.0.0.0"),
  9059                     IPField("ipdst", "0.0.0.0"),
  9060                     IPField("nexthop", "0.0.0.0"),
  9061                     ShortField("inputIfIndex", 0),
  9062                     ShortField("outpuIfIndex", 0),
  9063                     IntField("dpkts", 0),
  9064                     IntField("dbytes", 0),
  9065                     IntField("starttime", 0),
  9066                     IntField("endtime", 0),
  9067                     ShortField("srcport", 0),
  9068                     ShortField("dstport", 0),
  9069                     ShortField("padding", 0),
  9070                     ByteField("proto", 0),
  9071                     ByteField("tos", 0),
  9072                     IntField("padding1", 0),
  9073                     IntField("padding2", 0) ]
  9074 
  9075 
  9076 TFTP_operations = { 1:"RRQ",2:"WRQ",3:"DATA",4:"ACK",5:"ERROR",6:"OACK" }
  9077 
  9078 
  9079 class TFTP(Packet):
  9080     name = "TFTP opcode"
  9081     fields_desc = [ ShortEnumField("op", 1, TFTP_operations), ]
  9082     
  9083 
  9084 
  9085 class TFTP_RRQ(Packet):
  9086     name = "TFTP Read Request"
  9087     fields_desc = [ StrNullField("filename", ""),
  9088                     StrNullField("mode", "octet") ]
  9089     def answers(self, other):
  9090         return 0
  9091     def mysummary(self):
  9092         return self.sprintf("RRQ %filename%"),[UDP]
  9093         
  9094 
  9095 class TFTP_WRQ(Packet):
  9096     name = "TFTP Write Request"
  9097     fields_desc = [ StrNullField("filename", ""),
  9098                     StrNullField("mode", "octet") ]
  9099     def answers(self, other):
  9100         return 0
  9101     def mysummary(self):
  9102         return self.sprintf("WRQ %filename%"),[UDP]
  9103 
  9104 class TFTP_DATA(Packet):
  9105     name = "TFTP Data"
  9106     fields_desc = [ ShortField("block", 0) ]
  9107     def answers(self, other):
  9108         return  self.block == 1 and isinstance(other, TFTP_RRQ)
  9109     def mysummary(self):
  9110         return self.sprintf("DATA %block%"),[UDP]
  9111 
  9112 class TFTP_Option(Packet):
  9113     fields_desc = [ StrNullField("oname",""),
  9114                     StrNullField("value","") ]
  9115     def extract_padding(self, pkt):
  9116         return "",pkt
  9117 
  9118 class TFTP_Options(Packet):
  9119     fields_desc = [ PacketListField("options", [], TFTP_Option, length_from=lambda x:None) ]
  9120 
  9121     
  9122 class TFTP_ACK(Packet):
  9123     name = "TFTP Ack"
  9124     fields_desc = [ ShortField("block", 0) ]
  9125     def answers(self, other):
  9126         if isinstance(other, TFTP_DATA):
  9127             return self.block == other.block
  9128         elif isinstance(other, TFTP_RRQ) or isinstance(other, TFTP_WRQ) or isinstance(other, TFTP_OACK):
  9129             return self.block == 0
  9130         return 0
  9131     def mysummary(self):
  9132         return self.sprintf("ACK %block%"),[UDP]
  9133 
  9134 TFTP_Error_Codes = {  0: "Not defined",
  9135                       1: "File not found",
  9136                       2: "Access violation",
  9137                       3: "Disk full or allocation exceeded",
  9138                       4: "Illegal TFTP operation",
  9139                       5: "Unknown transfer ID",
  9140                       6: "File already exists",
  9141                       7: "No such user",
  9142                       8: "Terminate transfer due to option negotiation",
  9143                       }
  9144     
  9145 class TFTP_ERROR(Packet):
  9146     name = "TFTP Error"
  9147     fields_desc = [ ShortEnumField("errorcode", 0, TFTP_Error_Codes),
  9148                     StrNullField("errormsg", "")]
  9149     def answers(self, other):
  9150         return (isinstance(other, TFTP_DATA) or
  9151                 isinstance(other, TFTP_RRQ) or
  9152                 isinstance(other, TFTP_WRQ) or 
  9153                 isinstance(other, TFTP_ACK))
  9154     def mysummary(self):
  9155         return self.sprintf("ERROR %errorcode%: %errormsg%"),[UDP]
  9156 
  9157 
  9158 class TFTP_OACK(Packet):
  9159     name = "TFTP Option Ack"
  9160     fields_desc = [  ]
  9161     def answers(self, other):
  9162         return isinstance(other, TFTP_WRQ) or isinstance(other, TFTP_RRQ)
  9163 
  9164 
  9165 ##########
  9166 ## SNMP ##
  9167 ##########
  9168 
  9169 ######[ ASN1 class ]######
  9170 
  9171 class ASN1_Class_SNMP(ASN1_Class_UNIVERSAL):
  9172     name="SNMP"
  9173     PDU_GET = 0xa0
  9174     PDU_NEXT = 0xa1
  9175     PDU_RESPONSE = 0xa2
  9176     PDU_SET = 0xa3
  9177     PDU_TRAPv1 = 0xa4
  9178     PDU_BULK = 0xa5
  9179     PDU_INFORM = 0xa6
  9180     PDU_TRAPv2 = 0xa7
  9181 
  9182 
  9183 class ASN1_SNMP_PDU_GET(ASN1_SEQUENCE):
  9184     tag = ASN1_Class_SNMP.PDU_GET
  9185 
  9186 class ASN1_SNMP_PDU_NEXT(ASN1_SEQUENCE):
  9187     tag = ASN1_Class_SNMP.PDU_NEXT
  9188 
  9189 class ASN1_SNMP_PDU_RESPONSE(ASN1_SEQUENCE):
  9190     tag = ASN1_Class_SNMP.PDU_RESPONSE
  9191 
  9192 class ASN1_SNMP_PDU_SET(ASN1_SEQUENCE):
  9193     tag = ASN1_Class_SNMP.PDU_SET
  9194 
  9195 class ASN1_SNMP_PDU_TRAPv1(ASN1_SEQUENCE):
  9196     tag = ASN1_Class_SNMP.PDU_TRAPv1
  9197 
  9198 class ASN1_SNMP_PDU_BULK(ASN1_SEQUENCE):
  9199     tag = ASN1_Class_SNMP.PDU_BULK
  9200 
  9201 class ASN1_SNMP_PDU_INFORM(ASN1_SEQUENCE):
  9202     tag = ASN1_Class_SNMP.PDU_INFORM
  9203 
  9204 class ASN1_SNMP_PDU_TRAPv2(ASN1_SEQUENCE):
  9205     tag = ASN1_Class_SNMP.PDU_TRAPv2
  9206 
  9207 
  9208 ######[ BER codecs ]#######
  9209 
  9210 class BERcodec_SNMP_PDU_GET(BERcodec_SEQUENCE):
  9211     tag = ASN1_Class_SNMP.PDU_GET
  9212 
  9213 class BERcodec_SNMP_PDU_NEXT(BERcodec_SEQUENCE):
  9214     tag = ASN1_Class_SNMP.PDU_NEXT
  9215 
  9216 class BERcodec_SNMP_PDU_RESPONSE(BERcodec_SEQUENCE):
  9217     tag = ASN1_Class_SNMP.PDU_RESPONSE
  9218 
  9219 class BERcodec_SNMP_PDU_SET(BERcodec_SEQUENCE):
  9220     tag = ASN1_Class_SNMP.PDU_SET
  9221 
  9222 class BERcodec_SNMP_PDU_TRAPv1(BERcodec_SEQUENCE):
  9223     tag = ASN1_Class_SNMP.PDU_TRAPv1
  9224 
  9225 class BERcodec_SNMP_PDU_BULK(BERcodec_SEQUENCE):
  9226     tag = ASN1_Class_SNMP.PDU_BULK
  9227 
  9228 class BERcodec_SNMP_PDU_INFORM(BERcodec_SEQUENCE):
  9229     tag = ASN1_Class_SNMP.PDU_INFORM
  9230 
  9231 class BERcodec_SNMP_PDU_TRAPv2(BERcodec_SEQUENCE):
  9232     tag = ASN1_Class_SNMP.PDU_TRAPv2
  9233 
  9234 
  9235 
  9236 ######[ ASN1 fields ]######
  9237 
  9238 class ASN1F_SNMP_PDU_GET(ASN1F_SEQUENCE):
  9239     ASN1_tag = ASN1_Class_SNMP.PDU_GET
  9240 
  9241 class ASN1F_SNMP_PDU_NEXT(ASN1F_SEQUENCE):
  9242     ASN1_tag = ASN1_Class_SNMP.PDU_NEXT
  9243 
  9244 class ASN1F_SNMP_PDU_RESPONSE(ASN1F_SEQUENCE):
  9245     ASN1_tag = ASN1_Class_SNMP.PDU_RESPONSE
  9246 
  9247 class ASN1F_SNMP_PDU_SET(ASN1F_SEQUENCE):
  9248     ASN1_tag = ASN1_Class_SNMP.PDU_SET
  9249 
  9250 class ASN1F_SNMP_PDU_TRAPv1(ASN1F_SEQUENCE):
  9251     ASN1_tag = ASN1_Class_SNMP.PDU_TRAPv1
  9252 
  9253 class ASN1F_SNMP_PDU_BULK(ASN1F_SEQUENCE):
  9254     ASN1_tag = ASN1_Class_SNMP.PDU_BULK
  9255 
  9256 class ASN1F_SNMP_PDU_INFORM(ASN1F_SEQUENCE):
  9257     ASN1_tag = ASN1_Class_SNMP.PDU_INFORM
  9258 
  9259 class ASN1F_SNMP_PDU_TRAPv2(ASN1F_SEQUENCE):
  9260     ASN1_tag = ASN1_Class_SNMP.PDU_TRAPv2
  9261 
  9262 
  9263 
  9264 ######[ SNMP Packet ]######
  9265 
  9266 SNMP_error = { 0: "no_error",
  9267                1: "too_big",
  9268                2: "no_such_name",
  9269                3: "bad_value",
  9270                4: "read_only",
  9271                5: "generic_error",
  9272                6: "no_access",
  9273                7: "wrong_type",
  9274                8: "wrong_length",
  9275                9: "wrong_encoding",
  9276               10: "wrong_value",
  9277               11: "no_creation",
  9278               12: "inconsistent_value",
  9279               13: "ressource_unavailable",
  9280               14: "commit_failed",
  9281               15: "undo_failed",
  9282               16: "authorization_error",
  9283               17: "not_writable",
  9284               18: "inconsistent_name",
  9285                }
  9286 
  9287 SNMP_trap_types = { 0: "cold_start",
  9288                     1: "warm_start",
  9289                     2: "link_down",
  9290                     3: "link_up",
  9291                     4: "auth_failure",
  9292                     5: "egp_neigh_loss",
  9293                     6: "enterprise_specific",
  9294                     }
  9295 
  9296 class SNMPvarbind(ASN1_Packet):
  9297     ASN1_codec = ASN1_Codecs.BER
  9298     ASN1_root = ASN1F_SEQUENCE( ASN1F_OID("oid","1.3"),
  9299                                 ASN1F_field("value",ASN1_NULL(0))
  9300                                 )
  9301 
  9302 
  9303 class SNMPget(ASN1_Packet):
  9304     ASN1_codec = ASN1_Codecs.BER
  9305     ASN1_root = ASN1F_SNMP_PDU_GET( ASN1F_INTEGER("id",0),
  9306                                     ASN1F_enum_INTEGER("error",0, SNMP_error),
  9307                                     ASN1F_INTEGER("error_index",0),
  9308                                     ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9309                                     )
  9310 
  9311 class SNMPnext(ASN1_Packet):
  9312     ASN1_codec = ASN1_Codecs.BER
  9313     ASN1_root = ASN1F_SNMP_PDU_NEXT( ASN1F_INTEGER("id",0),
  9314                                      ASN1F_enum_INTEGER("error",0, SNMP_error),
  9315                                      ASN1F_INTEGER("error_index",0),
  9316                                      ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9317                                      )
  9318 
  9319 class SNMPresponse(ASN1_Packet):
  9320     ASN1_codec = ASN1_Codecs.BER
  9321     ASN1_root = ASN1F_SNMP_PDU_RESPONSE( ASN1F_INTEGER("id",0),
  9322                                          ASN1F_enum_INTEGER("error",0, SNMP_error),
  9323                                          ASN1F_INTEGER("error_index",0),
  9324                                          ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9325                                          )
  9326 
  9327 class SNMPset(ASN1_Packet):
  9328     ASN1_codec = ASN1_Codecs.BER
  9329     ASN1_root = ASN1F_SNMP_PDU_SET( ASN1F_INTEGER("id",0),
  9330                                     ASN1F_enum_INTEGER("error",0, SNMP_error),
  9331                                     ASN1F_INTEGER("error_index",0),
  9332                                     ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9333                                     )
  9334     
  9335 class SNMPtrapv1(ASN1_Packet):
  9336     ASN1_codec = ASN1_Codecs.BER
  9337     ASN1_root = ASN1F_SNMP_PDU_TRAPv1( ASN1F_INTEGER("id",0),
  9338                                        ASN1F_OID("enterprise", "1.3"),
  9339                                        ASN1F_STRING("agent_addr",""),
  9340                                        ASN1F_enum_INTEGER("generic_trap", 0, SNMP_trap_types),
  9341                                        ASN1F_INTEGER("specific_trap", 0),
  9342                                        ASN1F_INTEGER("time_stamp", IntAutoTime()),
  9343                                        ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9344                                        )
  9345 
  9346 class SNMPbulk(ASN1_Packet):
  9347     ASN1_codec = ASN1_Codecs.BER
  9348     ASN1_root = ASN1F_SNMP_PDU_BULK( ASN1F_INTEGER("id",0),
  9349                                      ASN1F_INTEGER("non_repeaters",0),
  9350                                      ASN1F_INTEGER("max_repetitions",0),
  9351                                      ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9352                                      )
  9353     
  9354 class SNMPinform(ASN1_Packet):
  9355     ASN1_codec = ASN1_Codecs.BER
  9356     ASN1_root = ASN1F_SNMP_PDU_INFORM( ASN1F_INTEGER("id",0),
  9357                                        ASN1F_enum_INTEGER("error",0, SNMP_error),
  9358                                        ASN1F_INTEGER("error_index",0),
  9359                                        ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9360                                        )
  9361     
  9362 class SNMPtrapv2(ASN1_Packet):
  9363     ASN1_codec = ASN1_Codecs.BER
  9364     ASN1_root = ASN1F_SNMP_PDU_TRAPv2( ASN1F_INTEGER("id",0),
  9365                                        ASN1F_enum_INTEGER("error",0, SNMP_error),
  9366                                        ASN1F_INTEGER("error_index",0),
  9367                                        ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9368                                        )
  9369     
  9370 
  9371 class SNMP(ASN1_Packet):
  9372     ASN1_codec = ASN1_Codecs.BER
  9373     ASN1_root = ASN1F_SEQUENCE(
  9374         ASN1F_enum_INTEGER("version", 1, {0:"v1", 1:"v2c", 2:"v2", 3:"v3"}),
  9375         ASN1F_STRING("community","public"),
  9376         ASN1F_CHOICE("PDU", SNMPget(),
  9377                      SNMPget, SNMPnext, SNMPresponse, SNMPset,
  9378                      SNMPtrapv1, SNMPbulk, SNMPinform, SNMPtrapv2)
  9379         )
  9380     def answers(self, other):
  9381         return ( isinstance(self.PDU, SNMPresponse)    and
  9382                  ( isinstance(other.PDU, SNMPget) or
  9383                    isinstance(other.PDU, SNMPnext) or
  9384                    isinstance(other.PDU, SNMPset)    ) and
  9385                  self.PDU.id == other.PDU.id )
  9386 
  9387 
  9388 ##########
  9389 ## X509 ##
  9390 ##########
  9391 
  9392 ######[ ASN1 class ]######
  9393 
  9394 class ASN1_Class_X509(ASN1_Class_UNIVERSAL):
  9395     name="X509"
  9396     CONT0 = 0xa0
  9397     CONT1 = 0xa1
  9398     CONT2 = 0xa2
  9399     CONT3 = 0xa3
  9400 
  9401 class ASN1_X509_CONT0(ASN1_SEQUENCE):
  9402     tag = ASN1_Class_X509.CONT0
  9403 
  9404 class ASN1_X509_CONT1(ASN1_SEQUENCE):
  9405     tag = ASN1_Class_X509.CONT1
  9406 
  9407 class ASN1_X509_CONT2(ASN1_SEQUENCE):
  9408     tag = ASN1_Class_X509.CONT2
  9409 
  9410 class ASN1_X509_CONT3(ASN1_SEQUENCE):
  9411     tag = ASN1_Class_X509.CONT3
  9412 
  9413 ######[ BER codecs ]#######
  9414 
  9415 class BERcodec_X509_CONT0(BERcodec_SEQUENCE):
  9416     tag = ASN1_Class_X509.CONT0
  9417 
  9418 class BERcodec_X509_CONT1(BERcodec_SEQUENCE):
  9419     tag = ASN1_Class_X509.CONT1
  9420     
  9421 class BERcodec_X509_CONT2(BERcodec_SEQUENCE):
  9422     tag = ASN1_Class_X509.CONT2
  9423     
  9424 class BERcodec_X509_CONT3(BERcodec_SEQUENCE):
  9425     tag = ASN1_Class_X509.CONT3
  9426 
  9427 ######[ ASN1 fields ]######
  9428 
  9429 class ASN1F_X509_CONT0(ASN1F_SEQUENCE):
  9430     ASN1_tag = ASN1_Class_X509.CONT0
  9431     
  9432 class ASN1F_X509_CONT1(ASN1F_SEQUENCE):
  9433     ASN1_tag = ASN1_Class_X509.CONT1
  9434     
  9435 class ASN1F_X509_CONT2(ASN1F_SEQUENCE):
  9436     ASN1_tag = ASN1_Class_X509.CONT2
  9437     
  9438 class ASN1F_X509_CONT3(ASN1F_SEQUENCE):
  9439     ASN1_tag = ASN1_Class_X509.CONT3
  9440 
  9441 ######[ X509 packets ]######
  9442 
  9443 class X509RDN(ASN1_Packet):
  9444     ASN1_codec = ASN1_Codecs.BER
  9445     ASN1_root = ASN1F_SET(
  9446                   ASN1F_SEQUENCE( ASN1F_OID("oid","2.5.4.6"),
  9447                                   ASN1F_PRINTABLE_STRING("value","")
  9448                                   )
  9449                   )
  9450 
  9451 class X509v3Ext(ASN1_Packet):
  9452     ASN1_codec = ASN1_Codecs.BER
  9453     ASN1_root = ASN1F_field("val",ASN1_NULL(0))
  9454     
  9455 
  9456 class X509Cert(ASN1_Packet):
  9457     ASN1_codec = ASN1_Codecs.BER
  9458     ASN1_root = ASN1F_SEQUENCE(
  9459         ASN1F_SEQUENCE(
  9460             ASN1F_optionnal(ASN1F_X509_CONT0(ASN1F_INTEGER("version",3))),
  9461             ASN1F_INTEGER("sn",1),
  9462             ASN1F_SEQUENCE(ASN1F_OID("sign_algo","1.2.840.113549.1.1.5"),
  9463                            ASN1F_field("sa_value",ASN1_NULL(0))),
  9464             ASN1F_SEQUENCE_OF("issuer",[],X509RDN),
  9465             ASN1F_SEQUENCE(ASN1F_UTC_TIME("not_before",ZuluTime(-600)),  # ten minutes ago
  9466                            ASN1F_UTC_TIME("not_after",ZuluTime(+86400))), # for 24h
  9467             ASN1F_SEQUENCE_OF("subject",[],X509RDN),
  9468             ASN1F_SEQUENCE(
  9469                 ASN1F_SEQUENCE(ASN1F_OID("pubkey_algo","1.2.840.113549.1.1.1"),
  9470                                ASN1F_field("pk_value",ASN1_NULL(0))),
  9471                 ASN1F_BIT_STRING("pubkey","")
  9472                 ),
  9473             ASN1F_optionnal(ASN1F_X509_CONT3(ASN1F_SEQUENCE_OF("x509v3ext",[],X509v3Ext))),
  9474             
  9475         ),
  9476         ASN1F_SEQUENCE(ASN1F_OID("sign_algo2","1.2.840.113549.1.1.5"),
  9477                        ASN1F_field("sa2_value",ASN1_NULL(0))),
  9478         ASN1F_BIT_STRING("signature","")
  9479         )
  9480 
  9481 
  9482 
  9483 
  9484 #################
  9485 ## Bind layers ##
  9486 #################
  9487 
  9488 
  9489 def bind_bottom_up(lower, upper, __fval=None, **fval):
  9490     if __fval is not None:
  9491         fval.update(__fval)
  9492     lower.payload_guess = lower.payload_guess[:]
  9493     lower.payload_guess.append((fval, upper))
  9494     
  9495 
  9496 def bind_top_down(lower, upper, __fval=None, **fval):
  9497     if __fval is not None:
  9498         fval.update(__fval)
  9499     upper.overload_fields = upper.overload_fields.copy()
  9500     upper.overload_fields[lower] = fval
  9501     
  9502 def bind_layers(lower, upper, __fval=None, **fval):
  9503     if __fval is not None:
  9504         fval.update(__fval)
  9505     bind_top_down(lower, upper, **fval)
  9506     bind_bottom_up(lower, upper, **fval)
  9507 
  9508 def split_bottom_up(lower, upper, __fval=None, **fval):
  9509     if __fval is not None:
  9510         fval.update(__fval)
  9511     def do_filter((f,u),upper=upper,fval=fval):
  9512         if u != upper:
  9513             return True
  9514         for k in fval:
  9515             if k not in f or f[k] != fval[k]:
  9516                 return True
  9517         return False
  9518     lower.payload_guess = filter(do_filter, lower.payload_guess)
  9519         
  9520 def split_top_down(lower, upper, __fval=None, **fval):
  9521     if __fval is not None:
  9522         fval.update(__fval)
  9523     if lower in upper.overload_fields:
  9524         ofval = upper.overload_fields[lower]
  9525         for k in fval:
  9526             if k not in ofval or ofval[k] != fval[k]:
  9527                 return
  9528         upper.overload_fields = upper.overload_fields.copy()
  9529         del(upper.overload_fields[lower])
  9530 
  9531 def split_layers(lower, upper, __fval=None, **fval):
  9532     if __fval is not None:
  9533         fval.update(__fval)
  9534     split_bottom_up(lower, upper, **fval)
  9535     split_top_down(lower, upper, **fval)
  9536 
  9537 
  9538 bind_layers( Dot3,          LLC,           )
  9539 bind_layers( GPRS,          IP,            )
  9540 bind_layers( PrismHeader,   Dot11,         )
  9541 bind_layers( RadioTap,      Dot11,         )
  9542 bind_layers( Dot11,         LLC,           type=2)
  9543 bind_layers( Dot11QoS,      LLC,           )
  9544 bind_layers( L2TP,          PPP,           )
  9545 bind_layers( HDLC,          PPP,           )
  9546 bind_layers( PPP,           IP,            proto=33)
  9547 bind_layers( PPP,           PPP_IPCP,      proto=0x8021)
  9548 bind_layers( PPP,           PPP_ECP,       proto=0x8053)
  9549 bind_layers( Ether,         LLC,           type=122)
  9550 bind_layers( Ether,         Dot1Q,         type=33024)
  9551 bind_layers( Ether,         Ether,         type=1)
  9552 bind_layers( Ether,         ARP,           type=2054)
  9553 bind_layers( Ether,         IP,            type=2048)
  9554 bind_layers( Ether,         EAPOL,         type=34958)
  9555 bind_layers( Ether,         EAPOL,         dst='01:80:c2:00:00:03', type=34958)
  9556 bind_layers( Ether,         PPPoED,        type=34915)
  9557 bind_layers( Ether,         PPPoE,         type=34916)
  9558 bind_layers( CookedLinux,   LLC,           proto=122)
  9559 bind_layers( CookedLinux,   Dot1Q,         proto=33024)
  9560 bind_layers( CookedLinux,   Ether,         proto=1)
  9561 bind_layers( CookedLinux,   ARP,           proto=2054)
  9562 bind_layers( CookedLinux,   IP,            proto=2048)
  9563 bind_layers( CookedLinux,   EAPOL,         proto=34958)
  9564 bind_layers( CookedLinux,   PPPoED,        proto=34915)
  9565 bind_layers( CookedLinux,   PPPoE,         proto=34916)
  9566 bind_layers( GRE,           LLC,           proto=122)
  9567 bind_layers( GRE,           Dot1Q,         proto=33024)
  9568 bind_layers( GRE,           Ether,         proto=1)
  9569 bind_layers( GRE,           ARP,           proto=2054)
  9570 bind_layers( GRE,           IP,            proto=2048)
  9571 bind_layers( GRE,           EAPOL,         proto=34958)
  9572 bind_layers( PPPoE,         PPP,           code=0)
  9573 bind_layers( EAPOL,         EAP,           type=0)
  9574 bind_layers( LLC,           STP,           dsap=66, ssap=66, ctrl=3)
  9575 bind_layers( LLC,           SNAP,          dsap=170, ssap=170, ctrl=3)
  9576 bind_layers( SNAP,          Dot1Q,         code=33024)
  9577 bind_layers( SNAP,          Ether,         code=1)
  9578 bind_layers( SNAP,          ARP,           code=2054)
  9579 bind_layers( SNAP,          IP,            code=2048)
  9580 bind_layers( SNAP,          EAPOL,         code=34958)
  9581 bind_layers( SNAP,          STP,           code=267)
  9582 bind_layers( IPerror,       IPerror,       frag=0, proto=4)
  9583 bind_layers( IPerror,       ICMPerror,     frag=0, proto=1)
  9584 bind_layers( IPerror,       TCPerror,      frag=0, proto=6)
  9585 bind_layers( IPerror,       UDPerror,      frag=0, proto=17)
  9586 bind_layers( IP,            IP,            frag=0, proto=4)
  9587 bind_layers( IP,            ICMP,          frag=0, proto=1)
  9588 bind_layers( IP,            TCP,           frag=0, proto=6)
  9589 bind_layers( IP,            UDP,           frag=0, proto=17)
  9590 bind_layers( IP,            GRE,           frag=0, proto=47)
  9591 bind_layers( UDP,           L2TP,          sport=1701, dport=1701)
  9592 bind_layers( UDP,           SNMP,          sport=161)
  9593 bind_layers( UDP,           SNMP,          dport=161)
  9594 bind_layers( UDP,           MGCP,          dport=2727)
  9595 bind_layers( UDP,           MGCP,          sport=2727)
  9596 bind_layers( UDP,           DNS,           dport=53)
  9597 bind_layers( UDP,           DNS,           sport=53)
  9598 bind_layers( UDP,           ISAKMP,        dport=500, sport=500)
  9599 bind_layers( UDP,           HSRP,          dport=1985, sport=1985)
  9600 bind_layers( UDP,           NTP,           dport=123, sport=123)
  9601 bind_layers( UDP,           BOOTP,         dport=67, sport=68)
  9602 bind_layers( UDP,           BOOTP,         dport=68, sport=67)
  9603 bind_layers( BOOTP,         DHCP,          options='c\x82Sc')
  9604 bind_layers( UDP,           RIP,           sport=520)
  9605 bind_layers( UDP,           RIP,           dport=520)
  9606 bind_layers( RIP,           RIPEntry,      )
  9607 bind_layers( RIPEntry,      RIPEntry,      )
  9608 bind_layers( Dot11,         Dot11AssoReq,    subtype=0, type=0)
  9609 bind_layers( Dot11,         Dot11AssoResp,   subtype=1, type=0)
  9610 bind_layers( Dot11,         Dot11ReassoReq,  subtype=2, type=0)
  9611 bind_layers( Dot11,         Dot11ReassoResp, subtype=3, type=0)
  9612 bind_layers( Dot11,         Dot11ProbeReq,   subtype=4, type=0)
  9613 bind_layers( Dot11,         Dot11ProbeResp,  subtype=5, type=0)
  9614 bind_layers( Dot11,         Dot11Beacon,     subtype=8, type=0)
  9615 bind_layers( Dot11,         Dot11ATIM,       subtype=9, type=0)
  9616 bind_layers( Dot11,         Dot11Disas,      subtype=10, type=0)
  9617 bind_layers( Dot11,         Dot11Auth,       subtype=11, type=0)
  9618 bind_layers( Dot11,         Dot11Deauth,     subtype=12, type=0)
  9619 bind_layers( Dot11Beacon,     Dot11Elt,    )
  9620 bind_layers( Dot11AssoReq,    Dot11Elt,    )
  9621 bind_layers( Dot11AssoResp,   Dot11Elt,    )
  9622 bind_layers( Dot11ReassoReq,  Dot11Elt,    )
  9623 bind_layers( Dot11ReassoResp, Dot11Elt,    )
  9624 bind_layers( Dot11ProbeReq,   Dot11Elt,    )
  9625 bind_layers( Dot11ProbeResp,  Dot11Elt,    )
  9626 bind_layers( Dot11Auth,       Dot11Elt,    )
  9627 bind_layers( Dot11Elt,        Dot11Elt,    )
  9628 bind_layers( TCP,           Skinny,        dport=2000)
  9629 bind_layers( TCP,           Skinny,        sport=2000)
  9630 bind_layers( UDP,           SebekHead,     sport=1101)
  9631 bind_layers( UDP,           SebekHead,     dport=1101)
  9632 bind_layers( UDP,           SebekHead,     dport=1101, sport=1101)
  9633 bind_layers( SebekHead,     SebekV1,       version=1)
  9634 bind_layers( SebekHead,     SebekV2Sock,   version=2, type=2)
  9635 bind_layers( SebekHead,     SebekV2,       version=2)
  9636 bind_layers( SebekHead,     SebekV3Sock,   version=3, type=2)
  9637 bind_layers( SebekHead,     SebekV3,       version=3)
  9638 bind_layers( CookedLinux,   IrLAPHead,     proto=23)
  9639 bind_layers( IrLAPHead,     IrLAPCommand,  Type=1)
  9640 bind_layers( IrLAPCommand,  IrLMP,         )
  9641 bind_layers( UDP,           NBNSQueryRequest,  dport=137)
  9642 bind_layers( UDP,           NBNSRequest,       dport=137)
  9643 bind_layers( UDP,           NBNSQueryResponse, sport=137)
  9644 bind_layers( UDP,           NBNSQueryResponseNegative, sport=137)
  9645 bind_layers( UDP,           NBNSNodeStatusResponse,    sport=137)
  9646 bind_layers( NBNSNodeStatusResponse,        NBNSNodeStatusResponseService, )
  9647 bind_layers( NBNSNodeStatusResponse,        NBNSNodeStatusResponseService, )
  9648 bind_layers( NBNSNodeStatusResponseService, NBNSNodeStatusResponseService, )
  9649 bind_layers( NBNSNodeStatusResponseService, NBNSNodeStatusResponseEnd, )
  9650 bind_layers( UDP,           NBNSWackResponse, sport=137)
  9651 bind_layers( UDP,           NBTDatagram,      dport=138)
  9652 bind_layers( TCP,           NBTSession,       dport=139)
  9653 bind_layers( NBTSession,                           SMBNegociate_Protocol_Request_Header, )
  9654 bind_layers( SMBNegociate_Protocol_Request_Header, SMBNegociate_Protocol_Request_Tail, )
  9655 bind_layers( SMBNegociate_Protocol_Request_Tail,   SMBNegociate_Protocol_Request_Tail, )
  9656 bind_layers( NBTSession,    SMBNegociate_Protocol_Response_Advanced_Security,  ExtendedSecurity=1)
  9657 bind_layers( NBTSession,    SMBNegociate_Protocol_Response_No_Security,        ExtendedSecurity=0, EncryptionKeyLength=8)
  9658 bind_layers( NBTSession,    SMBNegociate_Protocol_Response_No_Security_No_Key, ExtendedSecurity=0, EncryptionKeyLength=0)
  9659 bind_layers( NBTSession,    SMBSession_Setup_AndX_Request, )
  9660 bind_layers( NBTSession,    SMBSession_Setup_AndX_Response, )
  9661 bind_layers( HCI_Hdr,       HCI_ACL_Hdr,   type=2)
  9662 bind_layers( HCI_Hdr,       Raw,           )
  9663 bind_layers( HCI_ACL_Hdr,   L2CAP_Hdr,     )
  9664 bind_layers( L2CAP_Hdr,     L2CAP_CmdHdr,      cid=1)
  9665 bind_layers( L2CAP_CmdHdr,  L2CAP_CmdRej,      code=1)
  9666 bind_layers( L2CAP_CmdHdr,  L2CAP_ConnReq,     code=2)
  9667 bind_layers( L2CAP_CmdHdr,  L2CAP_ConnResp,    code=3)
  9668 bind_layers( L2CAP_CmdHdr,  L2CAP_ConfReq,     code=4)
  9669 bind_layers( L2CAP_CmdHdr,  L2CAP_ConfResp,    code=5)
  9670 bind_layers( L2CAP_CmdHdr,  L2CAP_DisconnReq,  code=6)
  9671 bind_layers( L2CAP_CmdHdr,  L2CAP_DisconnResp, code=7)
  9672 bind_layers( L2CAP_CmdHdr,  L2CAP_InfoReq,     code=10)
  9673 bind_layers( L2CAP_CmdHdr,  L2CAP_InfoResp,    code=11)
  9674 bind_layers( UDP,           MobileIP,           sport=434)
  9675 bind_layers( UDP,           MobileIP,           dport=434)
  9676 bind_layers( MobileIP,      MobileIPRRQ,        type=1)
  9677 bind_layers( MobileIP,      MobileIPRRP,        type=3)
  9678 bind_layers( MobileIP,      MobileIPTunnelData, type=4)
  9679 bind_layers( MobileIPTunnelData, IP,           nexthdr=4)
  9680 bind_layers( NetflowHeader,   NetflowHeaderV1, version=1)
  9681 bind_layers( NetflowHeaderV1, NetflowRecordV1, )
  9682 
  9683 bind_layers(UDP, TFTP, dport=69)
  9684 bind_layers(TFTP, TFTP_RRQ, op=1)
  9685 bind_layers(TFTP, TFTP_WRQ, op=2)
  9686 bind_layers(TFTP, TFTP_DATA, op=3)
  9687 bind_layers(TFTP, TFTP_ACK, op=4)
  9688 bind_layers(TFTP, TFTP_ERROR, op=5)
  9689 bind_layers(TFTP, TFTP_OACK, op=6)
  9690 bind_layers(TFTP_RRQ, TFTP_Options)
  9691 bind_layers(TFTP_WRQ, TFTP_Options)
  9692 bind_layers(TFTP_OACK, TFTP_Options)
  9693 
  9694 
  9695 ###################
  9696 ## Fragmentation ##
  9697 ###################
  9698 
  9699 def fragment(pkt, fragsize=1480):
  9700     fragsize = (fragsize+7)/8*8
  9701     lst = []
  9702     for p in pkt:
  9703         s = str(p[IP].payload)
  9704         nb = (len(s)+fragsize-1)/fragsize
  9705         for i in range(nb):            
  9706             q = p.copy()
  9707             del(q[IP].payload)
  9708             del(q[IP].chksum)
  9709             del(q[IP].len)
  9710             if i == nb-1:
  9711                 q[IP].flags &= ~1
  9712             else:
  9713                 q[IP].flags |= 1 
  9714             q[IP].frag = i*fragsize/8
  9715             r = Raw(load=s[i*fragsize:(i+1)*fragsize])
  9716             r.overload_fields = p[IP].payload.overload_fields.copy()
  9717             q.add_payload(r)
  9718             lst.append(q)
  9719     return lst
  9720 
  9721 def overlap_frag(p, overlap, fragsize=8, overlap_fragsize=None):
  9722     if overlap_fragsize is None:
  9723         overlap_fragsize = fragsize
  9724     q = p.copy()
  9725     del(q[IP].payload)
  9726     q[IP].add_payload(overlap)
  9727 
  9728     qfrag = fragment(q, overlap_fragsize)
  9729     qfrag[-1][IP].flags |= 1
  9730     return qfrag+fragment(p, fragsize)
  9731 
  9732 def defrag(plist):
  9733     """defrag(plist) -> ([not fragmented], [defragmented],
  9734                   [ [bad fragments], [bad fragments], ... ])"""
  9735     frags = {}
  9736     nofrag = PacketList()
  9737     for p in plist:
  9738         ip = p[IP]
  9739         if IP not in p:
  9740             nofrag.append(p)
  9741             continue
  9742         if ip.frag == 0 and ip.flags & 1 == 0:
  9743             nofrag.append(p)
  9744             continue
  9745         uniq = (ip.id,ip.src,ip.dst,ip.proto)
  9746         if uniq in frags:
  9747             frags[uniq].append(p)
  9748         else:
  9749             frags[uniq] = PacketList([p])
  9750     defrag = []
  9751     missfrag = []
  9752     for lst in frags.itervalues():
  9753         lst.sort(lambda x,y:cmp(x.frag, y.frag))
  9754         p = lst[0]
  9755         if p.frag > 0:
  9756             missfrag.append(lst)
  9757             continue
  9758         p = p.copy()
  9759         if Padding in p:
  9760             del(p[Padding].underlayer.payload)
  9761         ip = p[IP]
  9762         if ip.len is None or ip.ihl is None:
  9763             clen = len(ip.payload)
  9764         else:
  9765             clen = ip.len - (ip.ihl<<2)
  9766         txt = Raw()
  9767         for q in lst[1:]:
  9768             if clen != q.frag<<3:
  9769                 if clen > q.frag<<3:
  9770                     warning("Fragment overlap (%i > %i) %r || %r ||  %r" % (clen, q.frag<<3, p,txt,q))
  9771                 missfrag.append(lst)
  9772                 txt = None
  9773                 break
  9774             if q[IP].len is None or q[IP].ihl is None:
  9775                 clen += len(q[IP].payload)
  9776             else:
  9777                 clen += q[IP].len - (q[IP].ihl<<2)
  9778             if Padding in q:
  9779                 del(q[Padding].underlayer.payload)
  9780             txt.add_payload(q[IP].payload.copy())
  9781             
  9782         if txt is None:
  9783             continue
  9784 
  9785         ip.flags &= ~1 # !MF
  9786         del(ip.chksum)
  9787         del(ip.len)
  9788         p = p/txt
  9789         defrag.append(p)
  9790     defrag2=PacketList()
  9791     for p in defrag:
  9792         defrag2.append(p.__class__(str(p)))
  9793     return nofrag,defrag2,missfrag
  9794             
  9795 def defragment(plist):
  9796     """defrag(plist) -> plist defragmented as much as possible """
  9797     frags = {}
  9798     final = []
  9799 
  9800     pos = 0
  9801     for p in plist:
  9802         p._defrag_pos = pos
  9803         pos += 1
  9804         if IP in p:
  9805             ip = p[IP]
  9806             if ip.frag != 0 or ip.flags & 1:
  9807                 ip = p[IP]
  9808                 uniq = (ip.id,ip.src,ip.dst,ip.proto)
  9809                 if uniq in frags:
  9810                     frags[uniq].append(p)
  9811                 else:
  9812                     frags[uniq] = [p]
  9813                 continue
  9814         final.append(p)
  9815 
  9816     defrag = []
  9817     missfrag = []
  9818     for lst in frags.itervalues():
  9819         lst.sort(lambda x,y:cmp(x.frag, y.frag))
  9820         p = lst[0]
  9821         if p.frag > 0:
  9822             missfrag += lst
  9823             continue
  9824         p = p.copy()
  9825         if Padding in p:
  9826             del(p[Padding].underlayer.payload)
  9827         ip = p[IP]
  9828         if ip.len is None or ip.ihl is None:
  9829             clen = len(ip.payload)
  9830         else:
  9831             clen = ip.len - (ip.ihl<<2)
  9832         txt = Raw()
  9833         for q in lst[1:]:
  9834             if clen != q.frag<<3:
  9835                 if clen > q.frag<<3:
  9836                     warning("Fragment overlap (%i > %i) %r || %r ||  %r" % (clen, q.frag<<3, p,txt,q))
  9837                 missfrag += lst
  9838                 txt = None
  9839                 break
  9840             if q[IP].len is None or q[IP].ihl is None:
  9841                 clen += len(q[IP].payload)
  9842             else:
  9843                 clen += q[IP].len - (q[IP].ihl<<2)
  9844             if Padding in q:
  9845                 del(q[Padding].underlayer.payload)
  9846             txt.add_payload(q[IP].payload.copy())
  9847             
  9848         if txt is None:
  9849             continue
  9850 
  9851         ip.flags &= ~1 # !MF
  9852         del(ip.chksum)
  9853         del(ip.len)
  9854         p = p/txt
  9855         p._defrag_pos = lst[-1]._defrag_pos
  9856         defrag.append(p)
  9857     defrag2=[]
  9858     for p in defrag:
  9859         q = p.__class__(str(p))
  9860         q._defrag_pos = p._defrag_pos
  9861         defrag2.append(q)
  9862     final += defrag2
  9863     final += missfrag
  9864     final.sort(lambda x,y: cmp(x._defrag_pos, y._defrag_pos))
  9865     for p in final:
  9866         del(p._defrag_pos)
  9867 
  9868     if hasattr(plist, "listname"):
  9869         name = "Defragmented %s" % plist.listname
  9870     else:
  9871         name = "Defragmented"
  9872         
  9873     
  9874     return PacketList(final, name=name)
  9875             
  9876             
  9877         
  9878     
  9879 
  9880 
  9881 ###################
  9882 ## Super sockets ##
  9883 ###################
  9884 
  9885 def Ether_Dot3_Dispatcher(pkt=None, **kargs):
  9886     if type(pkt) is str and len(pkt) >= 14 and struct.unpack("!H", pkt[12:14])[0] <= 1500:
  9887         return Dot3(pkt, **kargs)
  9888     return Ether(pkt, **kargs)
  9889 
  9890 # According to libdnet
  9891 LLTypes = { ARPHDR_ETHER : Ether_Dot3_Dispatcher,
  9892             ARPHDR_METRICOM : Ether_Dot3_Dispatcher,
  9893             ARPHDR_LOOPBACK : Ether_Dot3_Dispatcher,
  9894             9: PPP,
  9895             12 : IP,
  9896             101 : IP,
  9897             801 : Dot11,
  9898             802 : PrismHeader,
  9899             803 : RadioTap,
  9900             105 : Dot11,
  9901             113 : CookedLinux,
  9902             119 : PrismHeader, # for atheros
  9903             127 : RadioTap,
  9904             144 : CookedLinux, # called LINUX_IRDA, similar to CookedLinux
  9905             783 : IrLAPHead,
  9906             0xB1E70073L : HCI_Hdr, # I invented this one
  9907             }
  9908 
  9909 LLNumTypes = { Ether : ARPHDR_ETHER,
  9910                PPP: 9,
  9911                IP  : 12,
  9912                IP  : 101,
  9913                Dot11  : 801,
  9914                PrismHeader : 802,
  9915                RadioTap    : 803,
  9916                RadioTap    : 127,
  9917                Dot11 : 105,
  9918                CookedLinux : 113,
  9919                CookedLinux : 144,
  9920                IrLAPHead : 783
  9921             }
  9922 
  9923 L3Types = { ETH_P_IP : IP,
  9924             ETH_P_ARP : ARP,
  9925             ETH_P_ALL : IP
  9926             }
  9927 
  9928 
  9929 def flush_fd(fd):
  9930     if type(fd) is not int:
  9931         fd = fd.fileno()
  9932     while 1:
  9933         r,w,e = select([fd],[],[],0)
  9934         if r:
  9935             os.read(fd,MTU)
  9936         else:
  9937             break
  9938 
  9939 class SuperSocket:
  9940     closed=0
  9941     def __init__(self, family=socket.AF_INET,type=socket.SOCK_STREAM, proto=0):
  9942         self.ins = socket.socket(family, type, proto)
  9943         self.outs = self.ins
  9944         self.promisc=None
  9945     def send(self, x):
  9946         sx = str(x)
  9947         x.sent_time = time.time()
  9948         return self.outs.send(sx)
  9949     def recv(self, x):
  9950         return Raw(self.ins.recv(x))
  9951     def fileno(self):
  9952         return self.ins.fileno()
  9953     def close(self):
  9954         if self.closed:
  9955             return
  9956         self.closed=1
  9957         if self.ins != self.outs:
  9958             if self.outs and self.outs.fileno() != -1:
  9959                 self.outs.close()
  9960         if self.ins and self.ins.fileno() != -1:
  9961             self.ins.close()
  9962     def bind_in(self, addr):
  9963         self.ins.bind(addr)
  9964     def bind_out(self, addr):
  9965         self.outs.bind(addr)
  9966 
  9967 
  9968 class L3RawSocket(SuperSocket):
  9969     def __init__(self, type = ETH_P_IP, filter=None, iface=None, promisc=None, nofilter=0):
  9970         self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
  9971         self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
  9972         self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
  9973     def recv(self, x):
  9974         return Ether(self.ins.recv(x)).payload
  9975     def send(self, x):
  9976         try:
  9977             sx = str(x)
  9978             x.sent_time = time.time()
  9979             self.outs.sendto(sx,(x.dst,0))
  9980         except socket.error,msg:
  9981             log_runtime.error(msg)
  9982         
  9983 
  9984 
  9985 class L3PacketSocket(SuperSocket):
  9986     def __init__(self, type = ETH_P_ALL, filter=None, promisc=None, iface=None, nofilter=0):
  9987         self.type = type
  9988         self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
  9989         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
  9990         flush_fd(self.ins)
  9991         if iface:
  9992             self.ins.bind((iface, type))
  9993         if not nofilter:
  9994             if conf.except_filter:
  9995                 if filter:
  9996                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
  9997                 else:
  9998                     filter = "not (%s)" % conf.except_filter
  9999             if filter is not None:
 10000                 attach_filter(self.ins, filter)
 10001         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
 10002         self.outs = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
 10003         self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30)
 10004         if promisc is None:
 10005             promisc = conf.promisc
 10006         self.promisc = promisc
 10007         if self.promisc:
 10008             if iface is None:
 10009                 self.iff = get_if_list()
 10010             else:
 10011                 if iface.__class__ is list:
 10012                     self.iff = iface
 10013                 else:
 10014                     self.iff = [iface]
 10015             for i in self.iff:
 10016                 set_promisc(self.ins, i)
 10017     def close(self):
 10018         if self.closed:
 10019             return
 10020         self.closed=1
 10021         if self.promisc:
 10022             for i in self.iff:
 10023                 set_promisc(self.ins, i, 0)
 10024         SuperSocket.close(self)
 10025     def recv(self, x):
 10026         pkt, sa_ll = self.ins.recvfrom(x)
 10027         if sa_ll[2] == socket.PACKET_OUTGOING:
 10028             return None
 10029         if LLTypes.has_key(sa_ll[3]):
 10030             cls = LLTypes[sa_ll[3]]
 10031             lvl = 2
 10032         elif L3Types.has_key(sa_ll[1]):
 10033             cls = L3Types[sa_ll[1]]
 10034             lvl = 3
 10035         else:
 10036             warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using Ethernet" % (sa_ll[0],sa_ll[1],sa_ll[3]))
 10037             cls = Ether
 10038             lvl = 2
 10039 
 10040         try:
 10041             pkt = cls(pkt)
 10042         except KeyboardInterrupt:
 10043             raise
 10044         except:
 10045             if conf.debug_dissector:
 10046                 raise
 10047             pkt = Raw(pkt)
 10048         if lvl == 2:
 10049             pkt = pkt.payload
 10050             
 10051         if pkt is not None:
 10052             pkt.time = get_last_packet_timestamp(self.ins)
 10053         return pkt
 10054     
 10055     def send(self, x):
 10056         if isinstance(x, IPv6):
 10057             iff,a,gw = conf.route6.route(x.dst)
 10058         elif hasattr(x,"dst"):
 10059             iff,a,gw = conf.route.route(x.dst)
 10060         else:
 10061             iff = conf.iface
 10062         sdto = (iff, self.type)
 10063         self.outs.bind(sdto)
 10064         sn = self.outs.getsockname()
 10065         ll = lambda x:x
 10066         if sn[3] in (ARPHDR_PPP,ARPHDR_TUN):
 10067             sdto = (iff, ETH_P_IP)
 10068         if LLTypes.has_key(sn[3]):
 10069             ll = lambda x:LLTypes[sn[3]]()/x
 10070         try:
 10071             sx = str(ll(x))
 10072             x.sent_time = time.time()
 10073             self.outs.sendto(sx, sdto)
 10074         except socket.error,msg:
 10075             x.sent_time = time.time()  # bad approximation
 10076             if conf.auto_fragment and msg[0] == 90:
 10077                 for p in fragment(x):
 10078                     self.outs.sendto(str(ll(p)), sdto)
 10079             else:
 10080                 raise
 10081                     
 10082 
 10083 
 10084 
 10085 class L2Socket(SuperSocket):
 10086     def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
 10087         if iface is None:
 10088             iface = conf.iface
 10089         self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
 10090         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
 10091         flush_fd(self.ins)
 10092         if not nofilter: 
 10093             if conf.except_filter:
 10094                 if filter:
 10095                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
 10096                 else:
 10097                     filter = "not (%s)" % conf.except_filter
 10098             if filter is not None:
 10099                 attach_filter(self.ins, filter)
 10100         self.ins.bind((iface, type))
 10101         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
 10102         self.outs = self.ins
 10103         self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30)
 10104         sa_ll = self.outs.getsockname()
 10105         if LLTypes.has_key(sa_ll[3]):
 10106             self.LL = LLTypes[sa_ll[3]]
 10107         elif L3Types.has_key(sa_ll[1]):
 10108             self.LL = L3Types[sa_ll[1]]
 10109         else:
 10110             warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using Ethernet" % (sa_ll[0],sa_ll[1],sa_ll[3]))
 10111             self.LL = Ether
 10112             
 10113     def recv(self, x):
 10114         pkt, sa_ll = self.ins.recvfrom(x)
 10115         if sa_ll[2] == socket.PACKET_OUTGOING:
 10116             return None
 10117         try:
 10118             q = self.LL(pkt)
 10119         except KeyboardInterrupt:
 10120             raise
 10121         except:
 10122             if conf.debug_dissector:
 10123                 raise
 10124             q = Raw(pkt)
 10125         q.time = get_last_packet_timestamp(self.ins)
 10126         return q
 10127 
 10128 
 10129 class L2ListenSocket(SuperSocket):
 10130     def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None, nofilter=0):
 10131         self.type = type
 10132         self.outs = None
 10133         self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
 10134         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
 10135         flush_fd(self.ins)
 10136         if iface is not None:
 10137             self.ins.bind((iface, type))
 10138         if not nofilter:
 10139             if conf.except_filter:
 10140                 if filter:
 10141                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
 10142                 else:
 10143                     filter = "not (%s)" % conf.except_filter
 10144             if filter is not None:
 10145                 attach_filter(self.ins, filter)
 10146         if promisc is None:
 10147             promisc = conf.sniff_promisc
 10148         self.promisc = promisc
 10149         if iface is None:
 10150             self.iff = get_if_list()
 10151         else:
 10152             if iface.__class__ is list:
 10153                 self.iff = iface
 10154             else:
 10155                 self.iff = [iface]
 10156         if self.promisc:
 10157             for i in self.iff:
 10158                 set_promisc(self.ins, i)
 10159         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
 10160     def close(self):
 10161         if self.promisc:
 10162             for i in self.iff:
 10163                 set_promisc(self.ins, i, 0)
 10164         SuperSocket.close(self)
 10165 
 10166     def recv(self, x):
 10167         pkt, sa_ll = self.ins.recvfrom(x)
 10168         if LLTypes.has_key(sa_ll[3]):
 10169             cls = LLTypes[sa_ll[3]]
 10170         elif L3Types.has_key(sa_ll[1]):
 10171             cls = L3Types[sa_ll[1]]
 10172         else:
 10173             warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using Ethernet" % (sa_ll[0],sa_ll[1],sa_ll[3]))
 10174             cls = Ether
 10175 
 10176         try:
 10177             pkt = cls(pkt)
 10178         except KeyboardInterrupt:
 10179             raise
 10180         except:
 10181             if conf.debug_dissector:
 10182                 raise
 10183             pkt = Raw(pkt)
 10184         pkt.time = get_last_packet_timestamp(self.ins)
 10185         return pkt
 10186     
 10187     def send(self, x):
 10188         raise Scapy_Exception("Can't send anything with L2ListenSocket")
 10189 
 10190 
 10191 
 10192 class L3dnetSocket(SuperSocket):
 10193     def __init__(self, type = ETH_P_ALL, filter=None, promisc=None, iface=None, nofilter=0):
 10194         self.iflist = {}
 10195         self.ins = pcap.pcapObject()
 10196         if iface is None:
 10197             iface = conf.iface
 10198         self.iface = iface
 10199         self.ins.open_live(iface, 1600, 0, 100)
 10200         try:
 10201             ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
 10202         except:
 10203             pass
 10204         if nofilter:
 10205             if type != ETH_P_ALL:  # PF_PACKET stuff. Need to emulate this for pcap
 10206                 filter = "ether proto %i" % type
 10207             else:
 10208                 filter = None
 10209         else:
 10210             if conf.except_filter:
 10211                 if filter:
 10212                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
 10213                 else:
 10214                     filter = "not (%s)" % conf.except_filter
 10215             if type != ETH_P_ALL:  # PF_PACKET stuff. Need to emulate this for pcap
 10216                 if filter:
 10217                     filter = "(ether proto %i) and (%s)" % (type,filter)
 10218                 else:
 10219                     filter = "ether proto %i" % type
 10220         if filter:
 10221             self.ins.setfilter(filter, 0, 0)
 10222     def send(self, x):
 10223         if isinstance(x, IPv6):
 10224             iff,a,gw = conf.route6.route(x.dst)
 10225         elif hasattr(x,"dst"):
 10226             iff,a,gw = conf.route.route(x.dst)
 10227         else:
 10228             iff = conf.iface
 10229         ifs = self.iflist.get(iff)
 10230         if ifs is None:
 10231             self.iflist[iff] = ifs = dnet.eth(iff)
 10232         sx = str(Ether()/x)
 10233         x.sent_time = time.time()
 10234         ifs.send(sx)
 10235     def recv(self,x=MTU):
 10236         ll = self.ins.datalink()
 10237         if LLTypes.has_key(ll):
 10238             cls = LLTypes[ll]
 10239         else:
 10240             warning("Unable to guess datalink type (interface=%s linktype=%i). Using Ethernet" % (self.iface, ll))
 10241             cls = Ether
 10242 
 10243         pkt = self.ins.next()
 10244         if pkt is not None:
 10245             l,pkt,ts = pkt
 10246         if pkt is None:
 10247             return
 10248 
 10249         try:
 10250             pkt = cls(pkt)
 10251         except KeyboardInterrupt:
 10252             raise
 10253         except:
 10254             if conf.debug_dissector:
 10255                 raise
 10256             pkt = Raw(pkt)
 10257         pkt.time = ts
 10258         return pkt.payload
 10259 
 10260     def nonblock_recv(self):
 10261         self.ins.setnonblock(1)
 10262         p = self.recv()
 10263         self.ins.setnonblock(0)
 10264         return p
 10265 
 10266     def close(self):
 10267         if hasattr(self, "ins"):
 10268             del(self.ins)
 10269         if hasattr(self, "outs"):
 10270             del(self.outs)
 10271 
 10272 class L2dnetSocket(SuperSocket):
 10273     def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
 10274         if iface is None:
 10275             iface = conf.iface
 10276         self.iface = iface
 10277         self.ins = pcap.pcapObject()
 10278         self.ins.open_live(iface, 1600, 0, 100)
 10279         try:
 10280             ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
 10281         except:
 10282             pass
 10283         if nofilter:
 10284             if type != ETH_P_ALL:  # PF_PACKET stuff. Need to emulate this for pcap
 10285                 filter = "ether proto %i" % type
 10286             else:
 10287                 filter = None
 10288         else:
 10289             if conf.except_filter:
 10290                 if filter:
 10291                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
 10292                 else:
 10293                     filter = "not (%s)" % conf.except_filter
 10294             if type != ETH_P_ALL:  # PF_PACKET stuff. Need to emulate this for pcap
 10295                 if filter:
 10296                     filter = "(ether proto %i) and (%s)" % (type,filter)
 10297                 else:
 10298                     filter = "ether proto %i" % type
 10299         if filter:
 10300             self.ins.setfilter(filter, 0, 0)
 10301         self.outs = dnet.eth(iface)
 10302     def recv(self,x):
 10303         ll = self.ins.datalink()
 10304         if LLTypes.has_key(ll):
 10305             cls = LLTypes[ll]
 10306         else:
 10307             warning("Unable to guess datalink type (interface=%s linktype=%i). Using Ethernet" % (self.iface, ll))
 10308             cls = Ether
 10309 
 10310         pkt = self.ins.next()
 10311         if pkt is not None:
 10312             l,pkt,ts = pkt
 10313         if pkt is None:
 10314             return
 10315         
 10316         try:
 10317             pkt = cls(pkt)
 10318         except KeyboardInterrupt:
 10319             raise
 10320         except:
 10321             if conf.debug_dissector:
 10322                 raise
 10323             pkt = Raw(pkt)
 10324         pkt.time = ts
 10325         return pkt
 10326 
 10327     def nonblock_recv(self):
 10328         self.ins.setnonblock(1)
 10329         p = self.recv(MTU)
 10330         self.ins.setnonblock(0)
 10331         return p
 10332 
 10333     def close(self):
 10334         if hasattr(self, "ins"):
 10335             del(self.ins)
 10336         if hasattr(self, "outs"):
 10337             del(self.outs)
 10338     
 10339     
 10340     
 10341 
 10342 
 10343 class L2pcapListenSocket(SuperSocket):
 10344     def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None):
 10345         self.type = type
 10346         self.outs = None
 10347         self.ins = pcap.pcapObject()
 10348         self.iface = iface
 10349         if iface is None:
 10350             iface = conf.iface
 10351         if promisc is None:
 10352             promisc = conf.sniff_promisc
 10353         self.promisc = promisc
 10354         self.ins.open_live(iface, 1600, self.promisc, 100)
 10355         try:
 10356             ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
 10357         except:
 10358             pass
 10359         if type == ETH_P_ALL: # Do not apply any filter if Ethernet type is given
 10360             if conf.except_filter:
 10361                 if filter:
 10362                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
 10363                 else:
 10364                     filter = "not (%s)" % conf.except_filter
 10365             if filter:
 10366                 self.ins.setfilter(filter, 0, 0)
 10367 
 10368     def close(self):
 10369         del(self.ins)
 10370         
 10371     def recv(self, x):
 10372         ll = self.ins.datalink()
 10373         if LLTypes.has_key(ll):
 10374             cls = LLTypes[ll]
 10375         else:
 10376             warning("Unable to guess datalink type (interface=%s linktype=%i). Using Ethernet" % (self.iface, ll))
 10377             cls = Ether
 10378 
 10379         pkt = None
 10380         while pkt is None:
 10381             pkt = self.ins.next()
 10382             if pkt is not None:
 10383                 l,pkt,ts = pkt
 10384         
 10385         try:
 10386             pkt = cls(pkt)
 10387         except KeyboardInterrupt:
 10388             raise
 10389         except:
 10390             if conf.debug_dissector:
 10391                 raise
 10392             pkt = Raw(pkt)
 10393         pkt.time = ts
 10394         return pkt
 10395 
 10396     def send(self, x):
 10397         raise Scapy_Exception("Can't send anything with L2pcapListenSocket")
 10398 
 10399 
 10400 class SimpleSocket(SuperSocket):
 10401     def __init__(self, sock):
 10402         self.ins = sock
 10403         self.outs = sock
 10404 
 10405 
 10406 class StreamSocket(SimpleSocket):
 10407     def __init__(self, sock, basecls=Raw):
 10408         SimpleSocket.__init__(self, sock)
 10409         self.basecls = basecls
 10410         
 10411     def recv(self, x=MTU):
 10412         pkt = self.ins.recv(x, socket.MSG_PEEK)
 10413         x = len(pkt)
 10414         pkt = self.basecls(pkt)
 10415         pad = pkt[Padding]
 10416         if pad is not None and pad.underlayer is not None:
 10417             del(pad.underlayer.payload)
 10418         while pad is not None and not isinstance(pad, NoPayload):
 10419             x -= len(pad.load)
 10420             pad = pad.payload
 10421         self.ins.recv(x)
 10422         return pkt
 10423         
 10424         
 10425 class BluetoothL2CAPSocket(SuperSocket):
 10426     def __init__(self, peer):
 10427         s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
 10428                           socket.BTPROTO_L2CAP)
 10429         s.connect((peer,0))
 10430         
 10431         self.ins = self.outs = s
 10432 
 10433     def recv(self, x):
 10434         return L2CAP_CmdHdr(self.ins.recv(x))
 10435     
 10436 
 10437 class BluetoothHCISocket(SuperSocket):
 10438     def __init__(self, iface=0x10000, type=None):
 10439         s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI)
 10440         s.setsockopt(socket.SOL_HCI, socket.HCI_DATA_DIR,1)
 10441         s.setsockopt(socket.SOL_HCI, socket.HCI_TIME_STAMP,1)
 10442         s.setsockopt(socket.SOL_HCI, socket.HCI_FILTER, struct.pack("IIIh2x", 0xffffffffL,0xffffffffL,0xffffffffL,0)) #type mask, event mask, event mask, opcode
 10443         s.bind((iface,))
 10444         self.ins = self.outs = s
 10445 #        s.connect((peer,0))
 10446         
 10447 
 10448     def recv(self, x):
 10449         return HCI_Hdr(self.ins.recv(x))
 10450     
 10451 
 10452 
 10453 ####################
 10454 ## Send / Receive ##
 10455 ####################
 10456 
 10457 
 10458 
 10459 
 10460 def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, multi=0):
 10461     if not isinstance(pkt, Gen):
 10462         pkt = SetGen(pkt)
 10463         
 10464     if verbose is None:
 10465         verbose = conf.verb
 10466     debug.recv = PacketList([],"Unanswered")
 10467     debug.sent = PacketList([],"Sent")
 10468     debug.match = SndRcvList([])
 10469     nbrecv=0
 10470     ans = []
 10471     # do it here to fix random fields, so that parent and child have the same
 10472     all_stimuli = tobesent = [p for p in pkt]
 10473     notans = len(tobesent)
 10474 
 10475     hsent={}
 10476     for i in tobesent:
 10477         h = i.hashret()
 10478         if h in hsent:
 10479             hsent[h].append(i)
 10480         else:
 10481             hsent[h] = [i]
 10482     if retry < 0:
 10483         retry = -retry
 10484         autostop=retry
 10485     else:
 10486         autostop=0
 10487 
 10488 
 10489     while retry >= 0:
 10490         found=0
 10491     
 10492         if timeout < 0:
 10493             timeout = None
 10494             
 10495         rdpipe,wrpipe = os.pipe()
 10496         rdpipe=os.fdopen(rdpipe)
 10497         wrpipe=os.fdopen(wrpipe,"w")
 10498 
 10499         pid=1
 10500         try:
 10501             pid = os.fork()
 10502             if pid == 0:
 10503                 try:
 10504                     sys.stdin.close()
 10505                     rdpipe.close()
 10506                     try:
 10507                         i = 0
 10508                         if verbose:
 10509                             print "Begin emission:"
 10510                         for p in tobesent:
 10511                             pks.send(p)
 10512                             i += 1
 10513                             time.sleep(inter)
 10514                         if verbose:
 10515                             print "Finished to send %i packets." % i
 10516                     except SystemExit:
 10517                         pass
 10518                     except KeyboardInterrupt:
 10519                         pass
 10520                     except:
 10521                         log_runtime.exception("--- Error in child %i" % os.getpid())
 10522                         log_runtime.info("--- Error in child %i" % os.getpid())
 10523                 finally:
 10524                     try:
 10525                         os.setpgrp() # Chance process group to avoid ctrl-C
 10526                         sent_times = [p.sent_time for p in all_stimuli if p.sent_time]
 10527                         cPickle.dump( (arp_cache,sent_times), wrpipe )
 10528                         wrpipe.close()
 10529                     except:
 10530                         pass
 10531             elif pid < 0:
 10532                 log_runtime.error("fork error")
 10533             else:
 10534                 wrpipe.close()
 10535                 stoptime = 0
 10536                 remaintime = None
 10537                 inmask = [rdpipe,pks]
 10538                 try:
 10539                     try:
 10540                         while 1:
 10541                             if stoptime:
 10542                                 remaintime = stoptime-time.time()
 10543                                 if remaintime <= 0:
 10544                                     break
 10545                             r = None
 10546                             if FREEBSD or DARWIN:
 10547                                 inp, out, err = select(inmask,[],[], 0.05)
 10548                                 if len(inp) == 0 or pks in inp:
 10549                                     r = pks.nonblock_recv()
 10550                             else:
 10551                                 inp, out, err = select(inmask,[],[], remaintime)
 10552                                 if len(inp) == 0:
 10553                                     break
 10554                                 if pks in inp:
 10555                                     r = pks.recv(MTU)
 10556                             if rdpipe in inp:
 10557                                 if timeout:
 10558                                     stoptime = time.time()+timeout
 10559                                 del(inmask[inmask.index(rdpipe)])
 10560                             if r is None:
 10561                                 continue
 10562                             ok = 0
 10563                             h = r.hashret()
 10564                             if h in hsent:
 10565                                 hlst = hsent[h]
 10566                                 for i in range(len(hlst)):
 10567                                     if r.answers(hlst[i]):
 10568                                         ans.append((hlst[i],r))
 10569                                         if verbose > 1:
 10570                                             os.write(1, "*")
 10571                                         ok = 1                                
 10572                                         if not multi:
 10573                                             del(hlst[i])
 10574                                             notans -= 1;
 10575                                         else:
 10576                                             if not hasattr(hlst[i], '_answered'):
 10577                                                 notans -= 1;
 10578                                             hlst[i]._answered = 1;
 10579                                         break
 10580                             if notans == 0 and not multi:
 10581                                 break
 10582                             if not ok:
 10583                                 if verbose > 1:
 10584                                     os.write(1, ".")
 10585                                 nbrecv += 1
 10586                                 if conf.debug_match:
 10587                                     debug.recv.append(r)
 10588                     except KeyboardInterrupt:
 10589                         if chainCC:
 10590                             raise
 10591                 finally:
 10592                     try:
 10593                         ac,sent_times = cPickle.load(rdpipe)
 10594                     except EOFError:
 10595                         warning("Child died unexpectedly. Packets may have not been sent %i"%os.getpid())
 10596                     else:
 10597                         arp_cache.update(ac)
 10598                         for p,t in zip(all_stimuli, sent_times):
 10599                             p.sent_time = t
 10600                     os.waitpid(pid,0)
 10601         finally:
 10602             if pid == 0:
 10603                 os._exit(0)
 10604 
 10605         remain = reduce(list.__add__, hsent.values(), [])
 10606         if multi:
 10607             remain = filter(lambda p: not hasattr(p, '_answered'), remain);
 10608             
 10609         if autostop and len(remain) > 0 and len(remain) != len(tobesent):
 10610             retry = autostop
 10611             
 10612         tobesent = remain
 10613         if len(tobesent) == 0:
 10614             break
 10615         retry -= 1
 10616         
 10617     if conf.debug_match:
 10618         debug.sent=PacketList(remain[:],"Sent")
 10619         debug.match=SndRcvList(ans[:])
 10620 
 10621     #clean the ans list to delete the field _answered
 10622     if (multi):
 10623         for s,r in ans:
 10624             if hasattr(s, '_answered'):
 10625                 del(s._answered)
 10626     
 10627     if verbose:
 10628         print "\nReceived %i packets, got %i answers, remaining %i packets" % (nbrecv+len(ans), len(ans), notans)
 10629     return SndRcvList(ans),PacketList(remain,"Unanswered"),debug.recv
 10630 
 10631 
 10632 def __gen_send(s, x, inter=0, loop=0, count=None, verbose=None, *args, **kargs):
 10633     if not isinstance(x, Gen):
 10634         x = SetGen(x)
 10635     if verbose is None:
 10636         verbose = conf.verb
 10637     n = 0
 10638     if count is not None:
 10639         loop = -count
 10640     elif not loop:
 10641         loop=-1
 10642     try:
 10643         while loop:
 10644             for p in x:
 10645                 s.send(p)
 10646                 n += 1
 10647                 if verbose:
 10648                     os.write(1,".")
 10649                 time.sleep(inter)
 10650             if loop < 0:
 10651                 loop += 1
 10652     except KeyboardInterrupt:
 10653         pass
 10654     s.close()
 10655     if verbose:
 10656         print "\nSent %i packets." % n
 10657 
 10658 def send(x, inter=0, loop=0, count=None, verbose=None, *args, **kargs):
 10659     """Send packets at layer 3
 10660 send(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
 10661     __gen_send(conf.L3socket(*args, **kargs), x, inter=inter, loop=loop, count=count,verbose=verbose)
 10662 
 10663 def sendp(x, inter=0, loop=0, iface=None, iface_hint=None, count=None, verbose=None, *args, **kargs):
 10664     """Send packets at layer 2
 10665 sendp(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
 10666     if iface is None and iface_hint is not None:
 10667         iface = conf.route.route(iface_hint)[0]
 10668     __gen_send(conf.L2socket(iface=iface, *args, **kargs), x, inter=inter, loop=loop, count=count, verbose=verbose)
 10669 
 10670 def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, iface=None):
 10671     """Send packets at layer 2 using tcpreplay for performance
 10672     pps:  packets per second
 10673     mpbs: MBits per second
 10674     realtime: use packet's timestamp, bending time with realtime value
 10675     loop: number of times to process the packet list
 10676     iface: output interface """
 10677     if iface is None:
 10678         iface = conf.iface
 10679     options = ["--intf1=%s" % iface ]
 10680     if pps is not None:
 10681         options.append("--pps=%i" % pps)
 10682     elif mbps is not None:
 10683         options.append("--mbps=%i" % mbps)
 10684     elif realtime is not None:
 10685         options.append("--multiplier=%i" % realtime)
 10686     else:
 10687         options.append("--topspeed")
 10688 
 10689     if loop:
 10690         options.append("--loop=%i" % loop)
 10691 
 10692     f = os.tempnam("scapy")
 10693     options.append(f)
 10694     wrpcap(f, x)
 10695     try:
 10696         try:
 10697             os.spawnlp(os.P_WAIT, conf.prog.tcpreplay, conf.prog.tcpreplay, *options)
 10698         except KeyboardInterrupt:
 10699             log_interactive.info("Interrupted by user")
 10700     finally:
 10701         os.unlink(f)
 10702 
 10703         
 10704 
 10705         
 10706     
 10707 def sr(x,filter=None, iface=None, nofilter=0, *args,**kargs):
 10708     """Send and receive packets at layer 3
 10709 nofilter: put 1 to avoid use of bpf filters
 10710 retry:    if positive, how many times to resend unanswered packets
 10711           if negative, how many times to retry when no more packets are answered
 10712 timeout:  how much time to wait after the last packet has been sent
 10713 verbose:  set verbosity level
 10714 multi:    whether to accept multiple answers for the same stimulus
 10715 filter:   provide a BPF filter
 10716 iface:    listen answers only on the given interface"""
 10717     if not kargs.has_key("timeout"):
 10718         kargs["timeout"] = -1
 10719     s = conf.L3socket(filter=filter, iface=iface, nofilter=nofilter)
 10720     a,b,c=sndrcv(s,x,*args,**kargs)
 10721     s.close()
 10722     return a,b
 10723 
 10724 def sr1(x,filter=None,iface=None, nofilter=0, *args,**kargs):
 10725     """Send packets at layer 3 and return only the first answer
 10726 nofilter: put 1 to avoid use of bpf filters
 10727 retry:    if positive, how many times to resend unanswered packets
 10728           if negative, how many times to retry when no more packets are answered
 10729 timeout:  how much time to wait after the last packet has been sent
 10730 verbose:  set verbosity level
 10731 multi:    whether to accept multiple answers for the same stimulus
 10732 filter:   provide a BPF filter
 10733 iface:    listen answers only on the given interface"""
 10734     if not kargs.has_key("timeout"):
 10735         kargs["timeout"] = -1
 10736     s=conf.L3socket(filter=filter, nofilter=nofilter, iface=iface)
 10737     a,b,c=sndrcv(s,x,*args,**kargs)
 10738     s.close()
 10739     if len(a) > 0:
 10740         return a[0][1]
 10741     else:
 10742         return None
 10743 
 10744 def srp(x,iface=None, iface_hint=None, filter=None, nofilter=0, type=ETH_P_ALL, *args,**kargs):
 10745     """Send and receive packets at layer 2
 10746 nofilter: put 1 to avoid use of bpf filters
 10747 retry:    if positive, how many times to resend unanswered packets
 10748           if negative, how many times to retry when no more packets are answered
 10749 timeout:  how much time to wait after the last packet has been sent
 10750 verbose:  set verbosity level
 10751 multi:    whether to accept multiple answers for the same stimulus
 10752 filter:   provide a BPF filter
 10753 iface:    work only on the given interface"""
 10754     if not kargs.has_key("timeout"):
 10755         kargs["timeout"] = -1
 10756     if iface is None and iface_hint is not None:
 10757         iface = conf.route.route(iface_hint)[0]
 10758     s = conf.L2socket(iface=iface, filter=filter, nofilter=nofilter, type=type)
 10759     a,b,c=sndrcv(s ,x,*args,**kargs)
 10760     s.close()
 10761     return a,b
 10762 
 10763 def srp1(*args,**kargs):
 10764     """Send and receive packets at layer 2 and return only the first answer
 10765 nofilter: put 1 to avoid use of bpf filters
 10766 retry:    if positive, how many times to resend unanswered packets
 10767           if negative, how many times to retry when no more packets are answered
 10768 timeout:  how much time to wait after the last packet has been sent
 10769 verbose:  set verbosity level
 10770 multi:    whether to accept multiple answers for the same stimulus
 10771 filter:   provide a BPF filter
 10772 iface:    work only on the given interface"""
 10773     if not kargs.has_key("timeout"):
 10774         kargs["timeout"] = -1
 10775     a,b=srp(*args,**kargs)
 10776     if len(a) > 0:
 10777         return a[0][1]
 10778     else:
 10779         return None
 10780 
 10781 def __sr_loop(srfunc, pkts, prn=lambda x:x[1].summary(), prnfail=lambda x:x.summary(), inter=1, timeout=None, count=None, verbose=None, store=1, *args, **kargs):
 10782     n = 0
 10783     r = 0
 10784     ct = conf.color_theme
 10785     if verbose is None:
 10786         verbose = conf.verb
 10787     parity = 0
 10788     ans=[]
 10789     unans=[]
 10790     if timeout is None:
 10791         timeout = min(2*inter, 5)
 10792     try:
 10793         while 1:
 10794             parity ^= 1
 10795             col = [ct.even,ct.odd][parity]
 10796             if count is not None:
 10797                 if count == 0:
 10798                     break
 10799                 count -= 1
 10800             start = time.time()
 10801             print "\rsend...\r",
 10802             res = srfunc(pkts, timeout=timeout, verbose=0, chainCC=1, *args, **kargs)
 10803             n += len(res[0])+len(res[1])
 10804             r += len(res[0])
 10805             if verbose > 1 and prn and len(res[0]) > 0:
 10806                 msg = "RECV %i:" % len(res[0])
 10807                 print  "\r"+ct.success(msg),
 10808                 for p in res[0]:
 10809                     print col(prn(p))
 10810                     print " "*len(msg),
 10811             if verbose > 1 and prnfail and len(res[1]) > 0:
 10812                 msg = "fail %i:" % len(res[1])
 10813                 print "\r"+ct.fail(msg),
 10814                 for p in res[1]:
 10815                     print col(prnfail(p))
 10816                     print " "*len(msg),
 10817             if verbose > 1 and not (prn or prnfail):
 10818                 print "recv:%i  fail:%i" % tuple(map(len, res[:2]))
 10819             if store:
 10820                 ans += res[0]
 10821                 unans += res[1]
 10822             end=time.time()
 10823             if end-start < inter:
 10824                 time.sleep(inter+start-end)
 10825     except KeyboardInterrupt:
 10826         pass
 10827  
 10828     if verbose and n>0:
 10829         print ct.normal("\nSent %i packets, received %i packets. %3.1f%% hits." % (n,r,100.0*r/n))
 10830     return SndRcvList(ans),PacketList(unans)
 10831 
 10832 def srloop(pkts, *args, **kargs):
 10833     """Send a packet at layer 3 in loop and print the answer each time
 10834 srloop(pkts, [prn], [inter], [count], ...) --> None"""
 10835     return __sr_loop(sr, pkts, *args, **kargs)
 10836 
 10837 def srploop(pkts, *args, **kargs):
 10838     """Send a packet at layer 2 in loop and print the answer each time
 10839 srloop(pkts, [prn], [inter], [count], ...) --> None"""
 10840     return __sr_loop(srp, pkts, *args, **kargs)
 10841 
 10842 
 10843 def sndrcvflood(pks, pkt, prn=lambda (s,r):r.summary(), chainCC=0, store=1, unique=0):
 10844     if not isinstance(pkt, Gen):
 10845         pkt = SetGen(pkt)
 10846     tobesent = [p for p in pkt]
 10847     received = SndRcvList()
 10848     seen = {}
 10849 
 10850     hsent={}
 10851     for i in tobesent:
 10852         h = i.hashret()
 10853         if h in hsent:
 10854             hsent[h].append(i)
 10855         else:
 10856             hsent[h] = [i]
 10857 
 10858     def send_in_loop(tobesent):
 10859         while 1:
 10860             for p in tobesent:
 10861                 yield p
 10862 
 10863     packets_to_send = send_in_loop(tobesent)
 10864 
 10865     ssock = rsock = pks.fileno()
 10866 
 10867     try:
 10868         while 1:
 10869             readyr,readys,_ = select([rsock],[ssock],[])
 10870             if ssock in readys:
 10871                 pks.send(packets_to_send.next())
 10872                 
 10873             if rsock in readyr:
 10874                 p = pks.recv(MTU)
 10875                 if p is None:
 10876                     continue
 10877                 h = p.hashret()
 10878                 if h in hsent:
 10879                     hlst = hsent[h]
 10880                     for i in hlst:
 10881                         if p.answers(i):
 10882                             res = prn((i,p))
 10883                             if unique:
 10884                                 if res in seen:
 10885                                     continue
 10886                                 seen[res] = None
 10887                             if res is not None:
 10888                                 print res
 10889                             if store:
 10890                                 received.append((i,p))
 10891     except KeyboardInterrupt:
 10892         if chainCC:
 10893             raise
 10894     return received
 10895 
 10896 def srflood(x,filter=None, iface=None, nofilter=None, *args,**kargs):
 10897     """Flood and receive packets at layer 3
 10898 prn:      function applied to packets received. Ret val is printed if not None
 10899 store:    if 1 (default), store answers and return them
 10900 unique:   only consider packets whose print 
 10901 nofilter: put 1 to avoid use of bpf filters
 10902 filter:   provide a BPF filter
 10903 iface:    listen answers only on the given interface"""
 10904     s = conf.L3socket(filter=filter, iface=iface, nofilter=nofilter)
 10905     r=sndrcvflood(s,x,*args,**kargs)
 10906     s.close()
 10907     return r
 10908 
 10909 def srpflood(x,filter=None, iface=None, iface_hint=None, nofilter=None, *args,**kargs):
 10910     """Flood and receive packets at layer 2
 10911 prn:      function applied to packets received. Ret val is printed if not None
 10912 store:    if 1 (default), store answers and return them
 10913 unique:   only consider packets whose print 
 10914 nofilter: put 1 to avoid use of bpf filters
 10915 filter:   provide a BPF filter
 10916 iface:    listen answers only on the given interface"""
 10917     if iface is None and iface_hint is not None:
 10918         iface = conf.route.route(iface_hint)[0]    
 10919     s = conf.L2socket(filter=filter, iface=iface, nofilter=nofilter)
 10920     r=sndrcvflood(s,x,*args,**kargs)
 10921     s.close()
 10922     return r
 10923 
 10924            
 10925 ## Bluetooth
 10926 
 10927 
 10928 def srbt(peer, pkts, inter=0.1, *args, **kargs):
 10929     s = conf.BTsocket(peer=peer)
 10930     a,b,c=sndrcv(s,pkts,inter=inter,*args,**kargs)
 10931     s.close()
 10932     return a,b
 10933 
 10934 def srbt1(peer, pkts, *args, **kargs):
 10935     a,b = srbt(peer, pkts, *args, **kargs)
 10936     if len(a) > 0:
 10937         return a[0][1]
 10938         
 10939     
 10940 
 10941 
 10942 
 10943 #############################
 10944 ## pcap capture file stuff ##
 10945 #############################
 10946 
 10947 def wrpcap(filename, pkt, *args, **kargs):
 10948     """Write a list of packets to a pcap file
 10949 gz: set to 1 to save a gzipped capture
 10950 linktype: force linktype value
 10951 endianness: "<" or ">", force endianness"""
 10952     PcapWriter(filename, *args, **kargs).write(pkt)
 10953 
 10954 def rdpcap(filename, count=-1):
 10955     """Read a pcap file and return a packet list
 10956 count: read only <count> packets"""
 10957     return PcapReader(filename).read_all(count=count)
 10958 
 10959 class PcapReader:
 10960     """A stateful pcap reader
 10961     
 10962     Based entirely on scapy.rdpcap(), this class allows for packets
 10963     to be dispatched without having to be loaded into memory all at
 10964     once
 10965     """
 10966 
 10967     def __init__(self, filename):
 10968         self.filename = filename
 10969         try:
 10970             self.f = gzip.open(filename,"rb")
 10971             magic = self.f.read(4)
 10972         except IOError:
 10973             self.f = open(filename,"rb")
 10974             magic = self.f.read(4)
 10975         if magic == "\xa1\xb2\xc3\xd4": #big endian
 10976             self.endian = ">"
 10977         elif  magic == "\xd4\xc3\xb2\xa1": #little endian
 10978             self.endian = "<"
 10979         else:
 10980             raise RuntimeWarning, "Not a pcap capture file (bad magic)"
 10981         hdr = self.f.read(20)
 10982         if len(hdr)<20:
 10983             raise RuntimeWarning, "Invalid pcap file (too short)"
 10984         vermaj,vermin,tz,sig,snaplen,linktype = struct.unpack(self.endian+"HHIIII",hdr)
 10985         self.LLcls = LLTypes.get(linktype, Raw)
 10986         if self.LLcls == Raw:
 10987             warning("PcapReader: unkonwon LL type [%i]/[%#x]. Using Raw packets" % (linktype,linktype))
 10988 
 10989     def __iter__(self):
 10990         return self
 10991 
 10992     def next(self):
 10993         """impliment the iterator protocol on a set of packets in a
 10994         pcap file
 10995         """
 10996         pkt = self.read_packet()
 10997         if pkt == None:
 10998             raise StopIteration
 10999         return pkt
 11000 
 11001 
 11002     def read_packet(self):
 11003         """return a single packet read from the file
 11004         
 11005         returns None when no more packets are available
 11006         """
 11007         hdr = self.f.read(16)
 11008         if len(hdr) < 16:
 11009             return None
 11010         sec,usec,caplen,olen = struct.unpack(self.endian+"IIII", hdr)
 11011         s = self.f.read(caplen)
 11012         try:
 11013             p = self.LLcls(s)
 11014         except KeyboardInterrupt:
 11015             raise
 11016         except:
 11017             if conf.debug_dissector:
 11018                 raise
 11019             p = Raw(s)
 11020         p.time = sec+0.000001*usec
 11021         return p
 11022 
 11023     def dispatch(self, callback):
 11024         """call the specified callback routine for each packet read
 11025         
 11026         This is just a convienience function for the main loop
 11027         that allows for easy launching of packet processing in a 
 11028         thread.
 11029         """
 11030         p = self.read_packet()
 11031         while p != None:
 11032             callback(p)
 11033             p = self.read_packet()
 11034 
 11035     def read_all(self,count=-1):
 11036         """return a list of all packets in the pcap file
 11037         """
 11038         res=[]
 11039         while count != 0:
 11040             count -= 1
 11041             p = self.read_packet()
 11042             if p is None:
 11043                 break
 11044             res.append(p)
 11045         return PacketList(res,name = os.path.basename(self.filename))
 11046 
 11047     def recv(self, size):
 11048         """ Emulate a socket
 11049         """
 11050         return self.read_packet()
 11051 
 11052     def fileno(self):
 11053         return self.f.fileno()
 11054         
 11055 
 11056 
 11057 class PcapWriter:
 11058     """A stream PCAP writer with more control than wrpcap()"""
 11059     def __init__(self, filename, linktype=None, gz=False, endianness="", append=False, sync=False):
 11060         """
 11061         linktype: force linktype to a given value. If None, linktype is taken
 11062                   from the first writter packet
 11063         gz: compress the capture on the fly
 11064         endianness: force an endianness (little:"<", big:">"). Default is native
 11065         append: append packets to the capture file instead of truncating it
 11066         sync: do not bufferize writes to the capture file
 11067         """
 11068         
 11069         self.linktype = linktype
 11070         self.header_present = 0
 11071         self.append=append
 11072         self.gz = gz
 11073         self.endian = endianness
 11074         self.filename=filename
 11075         self.sync=sync
 11076         bufsz=4096
 11077         if sync:
 11078             bufsz=0
 11079 
 11080         self.f = [open,gzip.open][gz](filename,append and "ab" or "wb", gz and 9 or bufsz)
 11081         
 11082             
 11083 
 11084     def fileno(self):
 11085         return self.f.fileno()
 11086 
 11087     def _write_header(self, pkt):
 11088         self.header_present=1
 11089 
 11090         if self.linktype == None:
 11091             if type(pkt) is list or type(pkt) is tuple:
 11092                 pkt = pkt[0]
 11093             self.linktype = LLNumTypes.get(pkt.__class__,1)
 11094 
 11095         if self.append:
 11096             # Even if prone to race conditions, this seems to be
 11097             # safest way to tell whether the header is already present
 11098             # because we have to handle compressed streams that
 11099             # are not as flexible as basic files
 11100             g = [open,gzip.open][self.gz](self.filename,"rb")
 11101             if g.read(16):
 11102                 return
 11103             
 11104         self.f.write(struct.pack(self.endian+"IHHIIII", 0xa1b2c3d4L,
 11105                                  2, 4, 0, 0, MTU, self.linktype))
 11106         self.f.flush()
 11107     
 11108 
 11109     def write(self, pkt):
 11110         """accepts a either a single packet or a list of packets
 11111         to be written to the dumpfile
 11112         """
 11113         if not self.header_present:
 11114             self._write_header(pkt)
 11115         for p in pkt:
 11116             self._write_packet(p)
 11117 
 11118     def _write_packet(self, packet):
 11119         """writes a single packet to the pcap file
 11120         """
 11121         s = str(packet)
 11122         l = len(s)
 11123         sec = int(packet.time)
 11124         usec = int((packet.time-sec)*1000000)
 11125         self.f.write(struct.pack(self.endian+"IIII", sec, usec, l, l))
 11126         self.f.write(s)
 11127         if self.gz and self.sync:
 11128             self.f.flush()
 11129 
 11130     def flush(self):
 11131         return self.f.flush()
 11132     def close(self):
 11133         return self.f.close()
 11134                 
 11135 
 11136 re_extract_hexcap = re.compile("^(0x[0-9a-fA-F]{2,}[ :\t]|(0x)?[0-9a-fA-F]{2,}:|(0x)?[0-9a-fA-F]{3,}[: \t]|) *(([0-9a-fA-F]{2} {,2}){,16})")
 11137 
 11138 def import_hexcap():
 11139     p = ""
 11140     try:
 11141         while 1:
 11142             l = raw_input().strip()
 11143             try:
 11144                 p += re_extract_hexcap.match(l).groups()[3]
 11145             except:
 11146                 warning("Parsing error during hexcap")
 11147                 continue
 11148     except EOFError:
 11149         pass
 11150     
 11151     p = p.replace(" ","")
 11152     p2=""
 11153     for i in range(len(p)/2):
 11154         p2 += chr(int(p[2*i:2*i+2],16))
 11155     return p2
 11156         
 11157 
 11158 
 11159 def wireshark(pktlist):
 11160     f = os.tempnam("scapy")
 11161     wrpcap(f, pktlist)
 11162     os.spawnlp(os.P_NOWAIT, conf.prog.wireshark, conf.prog.wireshark, "-r", f)
 11163 
 11164 def hexedit(x):
 11165     x = str(x)
 11166     f = os.tempnam("scapy")
 11167     open(f,"w").write(x)
 11168     os.spawnlp(os.P_WAIT, conf.prog.hexedit, conf.prog.hexedit, f)
 11169     x = open(f).read()
 11170     os.unlink(f)
 11171     return x
 11172 
 11173 
 11174 #####################
 11175 ## knowledge bases ##
 11176 #####################
 11177 
 11178 class KnowledgeBase:
 11179     def __init__(self, filename):
 11180         self.filename = filename
 11181         self.base = None
 11182 
 11183     def lazy_init(self):
 11184         self.base = ""
 11185 
 11186     def reload(self, filename = None):
 11187         if filename is not None:
 11188             self.filename = filename
 11189         oldbase = self.base
 11190         self.base = None
 11191         self.lazy_init()
 11192         if self.base is None:
 11193             self.base = oldbase
 11194 
 11195     def get_base(self):
 11196         if self.base is None:
 11197             self.lazy_init()
 11198         return self.base
 11199     
 11200 
 11201 
 11202 ##########################
 11203 ## IP location database ##
 11204 ##########################
 11205 
 11206 class IPCountryKnowledgeBase(KnowledgeBase):
 11207     """
 11208 How to generate the base :
 11209 db = []
 11210 for l in open("GeoIPCountryWhois.csv").readlines():
 11211     s,e,c = l.split(",")[2:5]
 11212     db.append((int(s[1:-1]),int(e[1:-1]),c[1:-1]))
 11213 cPickle.dump(gzip.open("xxx","w"),db)
 11214 """
 11215     def lazy_init(self):
 11216         self.base = load_object(self.filename)
 11217 
 11218 
 11219 class CountryLocKnowledgeBase(KnowledgeBase):
 11220     def lazy_init(self):
 11221         f=open(self.filename)
 11222         self.base = {}
 11223         while 1:
 11224             l = f.readline()
 11225             if not l:
 11226                 break
 11227             l = l.strip().split(",")
 11228             if len(l) != 3:
 11229                 continue
 11230             c,lat,long = l
 11231             
 11232             self.base[c] = (float(long),float(lat))
 11233         f.close()
 11234             
 11235         
 11236 
 11237 
 11238 def locate_ip(ip):
 11239     ip=map(int,ip.split("."))
 11240     ip = ip[3]+(ip[2]<<8L)+(ip[1]<<16L)+(ip[0]<<24L)
 11241 
 11242     cloc = country_loc_kdb.get_base()
 11243     db = IP_country_kdb.get_base()
 11244 
 11245     d=0
 11246     f=len(db)-1
 11247     while (f-d) > 1:
 11248         guess = (d+f)/2
 11249         if ip > db[guess][0]:
 11250             d = guess
 11251         else:
 11252             f = guess
 11253     s,e,c = db[guess]
 11254     if  s <= ip and ip <= e:
 11255         return cloc.get(c,None)
 11256 
 11257 
 11258     
 11259 
 11260 ###############
 11261 ## p0f stuff ##
 11262 ###############
 11263 
 11264 # File format (according to p0f.fp) :
 11265 #
 11266 # wwww:ttt:D:ss:OOO...:QQ:OS:Details
 11267 #
 11268 # wwww    - window size
 11269 # ttt     - initial TTL
 11270 # D       - don't fragment bit  (0=unset, 1=set) 
 11271 # ss      - overall SYN packet size
 11272 # OOO     - option value and order specification
 11273 # QQ      - quirks list
 11274 # OS      - OS genre
 11275 # details - OS description
 11276 
 11277 
 11278 
 11279 class p0fKnowledgeBase(KnowledgeBase):
 11280     def __init__(self, filename):
 11281         KnowledgeBase.__init__(self, filename)
 11282         #self.ttl_range=[255]
 11283     def lazy_init(self):
 11284         try:
 11285             f=open(self.filename)
 11286         except IOError:
 11287             warning("Can't open base %s" % self.filename)
 11288             return
 11289         try:
 11290             self.base = []
 11291             for l in f:
 11292                 if l[0] in ["#","\n"]:
 11293                     continue
 11294                 l = tuple(l.split(":"))
 11295                 if len(l) < 8:
 11296                     continue
 11297                 li = map(int,l[1:4])
 11298                 #if li[0] not in self.ttl_range:
 11299                 #    self.ttl_range.append(li[0])
 11300                 #    self.ttl_range.sort()
 11301                 self.base.append((l[0], li[0], li[1], li[2], l[4], l[5], l[6], l[7][:-1]))
 11302         except:
 11303             warning("Can't parse p0f database (new p0f version ?)")
 11304             self.base = None
 11305         f.close()
 11306 
 11307 
 11308 def packet2p0f(pkt):
 11309     while pkt.haslayer(IP) and pkt.haslayer(TCP):
 11310         pkt = pkt.getlayer(IP)
 11311         if isinstance(pkt.payload, TCP):
 11312             break
 11313         pkt = pkt.payload
 11314 
 11315     if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
 11316         raise TypeError("Not a TCP/IP packet")
 11317     if pkt.payload.flags & 0x13 != 0x02: #S,!A,!F
 11318         raise TypeError("Not a syn packet")
 11319     
 11320     #t = p0f_kdb.ttl_range[:]
 11321     #t += [pkt.ttl]
 11322     #t.sort()
 11323     #ttl=t[t.index(pkt.ttl)+1]
 11324     ttl = pkt.ttl
 11325 
 11326     df = (pkt.flags & 2) / 2
 11327     ss = len(pkt)
 11328     # from p0f/config.h : PACKET_BIG = 100
 11329     if ss > 100:
 11330         ss = 0
 11331 
 11332     ooo = ""
 11333     mss = -1
 11334     qqT = False
 11335     qqP = False
 11336     #qqBroken = False
 11337     ilen = (pkt[TCP].dataofs << 2) - 20 # from p0f.c
 11338     for option in pkt.payload.options:
 11339         ilen -= 1
 11340         if option[0] == "MSS":
 11341             ooo += "M" + str(option[1]) + ","
 11342             mss = option[1]
 11343             # FIXME: qqBroken
 11344             ilen -= 3
 11345         elif option[0] == "WScale":
 11346             ooo += "W" + str(option[1]) + ","
 11347             # FIXME: qqBroken
 11348             ilen -= 2
 11349         elif option[0] == "Timestamp":
 11350             if option[1][0] == 0:
 11351                 ooo += "T0,"
 11352             else:
 11353                 ooo += "T,"
 11354             if option[1][1] != 0:
 11355                 qqT = True
 11356             ilen -= 9
 11357         elif option[0] == "SAckOK":
 11358             ooo += "S,"
 11359             ilen -= 1
 11360         elif option[0] == "NOP":
 11361             ooo += "N,"
 11362         elif option[0] == "EOL":
 11363             ooo += "E,"
 11364             if ilen > 0:
 11365                 qqP = True
 11366         else:
 11367             ooo += "?,"
 11368             # FIXME: ilen
 11369     ooo = ooo[:-1]
 11370     if ooo == "": ooo = "."
 11371 
 11372     win = pkt.payload.window
 11373     if mss != -1:
 11374         if win % mss == 0:
 11375             win = "S" + str(win/mss)
 11376         elif win % (mss + 40) == 0:
 11377             win = "T" + str(win/(mss+40))
 11378         win = str(win)
 11379 
 11380     qq = ""
 11381 
 11382     if qqP:
 11383         qq += "P"
 11384     if pkt[IP].id == 0:
 11385         qq += "Z"
 11386     if pkt[IP].options != '':
 11387         qq += "I"
 11388     if pkt[TCP].urgptr != 0:
 11389         qq += "U"
 11390     if pkt[TCP].reserved != 0:
 11391         qq += "X"
 11392     if pkt[TCP].ack != 0:
 11393         qq += "A"
 11394     if qqT:
 11395         qq += "T"
 11396     if pkt[TCP].flags & 40 != 0:
 11397         # U or P
 11398         qq += "F"
 11399     if not isinstance(pkt[TCP].payload, NoPayload):
 11400         qq += "D"
 11401     # FIXME : "!" - broken options segment
 11402 
 11403     if qq == "":
 11404         qq = "."
 11405 
 11406     return (win,
 11407             ttl,
 11408             df,
 11409             ss,
 11410             ooo,
 11411             qq)
 11412 
 11413 def p0f_correl(x,y):
 11414     d = 0
 11415     # wwww can be "*" or "%nn"
 11416     d += (x[0] == y[0] or y[0] == "*" or (y[0][0] == "%" and x[0].isdigit() and (int(x[0]) % int(y[0][1:])) == 0))
 11417     # ttl
 11418     d += (y[1] >= x[1] and y[1] - x[1] < 32)
 11419     for i in [2, 3, 5]:
 11420         d += (x[i] == y[i])
 11421     xopt = x[4].split(",")
 11422     yopt = y[4].split(",")
 11423     if len(xopt) == len(yopt):
 11424         same = True
 11425         for i in range(len(xopt)):
 11426             if not (xopt[i] == yopt[i] or
 11427                     (len(yopt[i]) == 2 and len(xopt[i]) > 1 and
 11428                      yopt[i][1] == "*" and xopt[i][0] == yopt[i][0]) or
 11429                     (len(yopt[i]) > 2 and len(xopt[i]) > 1 and
 11430                      yopt[i][1] == "%" and xopt[i][0] == yopt[i][0] and
 11431                      int(xopt[i][1:]) % int(yopt[i][2:]) == 0)):
 11432                 same = False
 11433                 break
 11434         if same:
 11435             d += len(xopt)
 11436     return d
 11437 
 11438 
 11439 def p0f(pkt):
 11440     """Passive OS fingerprinting: which OS emitted this TCP SYN ?
 11441 p0f(packet) -> accuracy, [list of guesses]
 11442 """
 11443     pb = p0f_kdb.get_base()
 11444     if not pb:
 11445         warning("p0f base empty.")
 11446         return []
 11447     s = len(pb[0][0])
 11448     r = []
 11449     sig = packet2p0f(pkt)
 11450     max = len(sig[4].split(",")) + 5
 11451     for b in pb:
 11452         d = p0f_correl(sig,b)
 11453         if d == max:
 11454             r.append((b[6], b[7], b[1] - pkt[IP].ttl))
 11455     return r
 11456             
 11457 
 11458 def prnp0f(pkt):
 11459     try:
 11460         r = p0f(pkt)
 11461     except:
 11462         return
 11463     if r == []:
 11464         r = ("UNKNOWN", "[" + ":".join(map(str, packet2p0f(pkt))) + ":?:?]", None)
 11465     else:
 11466         r = r[0]
 11467     uptime = None
 11468     try:
 11469         uptime = pkt2uptime(pkt)
 11470     except:
 11471         pass
 11472     if uptime == 0:
 11473         uptime = None
 11474     res = pkt.sprintf("%IP.src%:%TCP.sport% - " + r[0] + " " + r[1])
 11475     if uptime is not None:
 11476         res += pkt.sprintf(" (up: " + str(uptime/3600) + " hrs)\n  -> %IP.dst%:%TCP.dport%")
 11477     else:
 11478         res += pkt.sprintf("\n  -> %IP.dst%:%TCP.dport%")
 11479     if r[2] is not None:
 11480         res += " (distance " + str(r[2]) + ")"
 11481     print res
 11482 
 11483 
 11484 def pkt2uptime(pkt, HZ=100):
 11485     """Calculate the date the machine which emitted the packet booted using TCP timestamp
 11486 pkt2uptime(pkt, [HZ=100])"""
 11487     if not isinstance(pkt, Packet):
 11488         raise TypeError("Not a TCP packet")
 11489     if isinstance(pkt,NoPayload):
 11490         raise TypeError("Not a TCP packet")
 11491     if not isinstance(pkt, TCP):
 11492         return pkt2uptime(pkt.payload)
 11493     for opt in pkt.options:
 11494         if opt[0] == "Timestamp":
 11495             #t = pkt.time - opt[1][0] * 1.0/HZ
 11496             #return time.ctime(t)
 11497             t = opt[1][0] / HZ
 11498             return t
 11499     raise TypeError("No timestamp option")
 11500 
 11501 
 11502 
 11503 #################
 11504 ## Queso stuff ##
 11505 #################
 11506 
 11507 
 11508 def quesoTCPflags(flags):
 11509     if flags == "-":
 11510         return "-"
 11511     flv = "FSRPAUXY"
 11512     v = 0
 11513     for i in flags:
 11514         v |= 2**flv.index(i)
 11515     return "%x" % v
 11516 
 11517 class QuesoKnowledgeBase(KnowledgeBase):
 11518     def lazy_init(self):
 11519         try:
 11520             f = open(self.filename)
 11521         except IOError:
 11522             return
 11523         self.base = {}
 11524         p = None
 11525         try:
 11526             for l in f:
 11527                 l = l.strip()
 11528                 if not l or l[0] == ';':
 11529                     continue
 11530                 if l[0] == '*':
 11531                     if p is not None:
 11532                         p[""] = name
 11533                     name = l[1:].strip()
 11534                     p = self.base
 11535                     continue
 11536                 if l[0] not in list("0123456"):
 11537                     continue
 11538                 res = l[2:].split()
 11539                 res[-1] = quesoTCPflags(res[-1])
 11540                 res = " ".join(res)
 11541                 if not p.has_key(res):
 11542                     p[res] = {}
 11543                 p = p[res]
 11544             if p is not None:
 11545                 p[""] = name
 11546         except:
 11547             self.base = None
 11548             warning("Can't load queso base [%s]", self.filename)
 11549         f.close()
 11550             
 11551         
 11552 
 11553     
 11554 def queso_sig(target, dport=80, timeout=3):
 11555     p = queso_kdb.get_base()
 11556     ret = []
 11557     for flags in ["S", "SA", "F", "FA", "SF", "P", "SEC"]:
 11558         ans, unans = sr(IP(dst=target)/TCP(dport=dport,flags=flags,seq=RandInt()),
 11559                         timeout=timeout, verbose=0)
 11560         if len(ans) == 0:
 11561             rs = "- - - -"
 11562         else:
 11563             s,r = ans[0]
 11564             rs = "%i" % (r.seq != 0)
 11565             if not r.ack:
 11566                 r += " 0"
 11567             elif r.ack-s.seq > 666:
 11568                 rs += " R" % 0
 11569             else:
 11570                 rs += " +%i" % (r.ack-s.seq)
 11571             rs += " %X" % r.window
 11572             rs += " %x" % r.payload.flags
 11573         ret.append(rs)
 11574     return ret
 11575             
 11576 def queso_search(sig):
 11577     p = queso_kdb.get_base()
 11578     sig.reverse()
 11579     ret = []
 11580     try:
 11581         while sig:
 11582             s = sig.pop()
 11583             p = p[s]
 11584             if p.has_key(""):
 11585                 ret.append(p[""])
 11586     except KeyError:
 11587         pass
 11588     return ret
 11589         
 11590 
 11591 def queso(*args,**kargs):
 11592     """Queso OS fingerprinting
 11593 queso(target, dport=80, timeout=3)"""
 11594     return queso_search(queso_sig(*args, **kargs))
 11595 
 11596 
 11597 
 11598 ######################
 11599 ## nmap OS fp stuff ##
 11600 ######################
 11601 
 11602 
 11603 class NmapKnowledgeBase(KnowledgeBase):
 11604     def lazy_init(self):
 11605         try:
 11606             f=open(self.filename)
 11607         except IOError:
 11608             return
 11609 
 11610         self.base = []
 11611         name = None
 11612         try:
 11613             for l in f:
 11614                 l = l.strip()
 11615                 if not l or l[0] == "#":
 11616                     continue
 11617                 if l[:12] == "Fingerprint ":
 11618                     if name is not None:
 11619                         self.base.append((name,sig))
 11620                     name = l[12:].strip()
 11621                     sig={}
 11622                     p = self.base
 11623                     continue
 11624                 elif l[:6] == "Class ":
 11625                     continue
 11626                 op = l.find("(")
 11627                 cl = l.find(")")
 11628                 if op < 0 or cl < 0:
 11629                     warning("error reading nmap os fp base file")
 11630                     continue
 11631                 test = l[:op]
 11632                 s = map(lambda x: x.split("="), l[op+1:cl].split("%"))
 11633                 si = {}
 11634                 for n,v in s:
 11635                     si[n] = v
 11636                 sig[test]=si
 11637             if name is not None:
 11638                 self.base.append((name,sig))
 11639         except:
 11640             self.base = None
 11641             warning("Can't read nmap database [%s](new nmap version ?)" % self.filename)
 11642         f.close()
 11643         
 11644 def TCPflags2str(f):
 11645     fl="FSRPAUEC"
 11646     s=""
 11647     for i in range(len(fl)):
 11648         if f & 1:
 11649             s = fl[i]+s
 11650         f >>= 1
 11651     return s
 11652 
 11653 def nmap_tcppacket_sig(pkt):
 11654     r = {}
 11655     if pkt is not None:
 11656 #        r["Resp"] = "Y"
 11657         r["DF"] = (pkt.flags & 2) and "Y" or "N"
 11658         r["W"] = "%X" % pkt.window
 11659         r["ACK"] = pkt.ack==2 and "S++" or pkt.ack==1 and "S" or "O"
 11660         r["Flags"] = TCPflags2str(pkt.payload.flags)
 11661         r["Ops"] = "".join(map(lambda x: x[0][0],pkt.payload.options))
 11662     else:
 11663         r["Resp"] = "N"
 11664     return r
 11665 
 11666 
 11667 def nmap_udppacket_sig(S,T):
 11668     r={}
 11669     if T is None:
 11670         r["Resp"] = "N"
 11671     else:
 11672         r["DF"] = (T.flags & 2) and "Y" or "N"
 11673         r["TOS"] = "%X" % T.tos
 11674         r["IPLEN"] = "%X" % T.len
 11675         r["RIPTL"] = "%X" % T.payload.payload.len
 11676         r["RID"] = S.id == T.payload.payload.id and "E" or "F"
 11677         r["RIPCK"] = S.chksum == T.getlayer(IPerror).chksum and "E" or T.getlayer(IPerror).chksum == 0 and "0" or "F"
 11678         r["UCK"] = S.payload.chksum == T.getlayer(UDPerror).chksum and "E" or T.getlayer(UDPerror).chksum ==0 and "0" or "F"
 11679         r["ULEN"] = "%X" % T.getlayer(UDPerror).len
 11680         r["DAT"] = T.getlayer(Raw) is None and "E" or S.getlayer(Raw).load == T.getlayer(Raw).load and "E" or "F"
 11681     return r
 11682     
 11683 
 11684 
 11685 def nmap_match_one_sig(seen, ref):
 11686     c = 0
 11687     for k in seen.keys():
 11688         if ref.has_key(k):
 11689             if seen[k] in ref[k].split("|"):
 11690                 c += 1
 11691     if c == 0 and seen.get("Resp") == "N":
 11692         return 0.7
 11693     else:
 11694         return 1.0*c/len(seen.keys())
 11695         
 11696         
 11697 
 11698 def nmap_sig(target, oport=80, cport=81, ucport=1):
 11699     res = {}
 11700 
 11701     tcpopt = [ ("WScale", 10),
 11702                ("NOP",None),
 11703                ("MSS", 256),
 11704                ("Timestamp",(123,0)) ]
 11705     tests = [ IP(dst=target, id=1)/TCP(seq=1, sport=5001, dport=oport, options=tcpopt, flags="CS"),
 11706               IP(dst=target, id=1)/TCP(seq=1, sport=5002, dport=oport, options=tcpopt, flags=0),
 11707               IP(dst=target, id=1)/TCP(seq=1, sport=5003, dport=oport, options=tcpopt, flags="SFUP"),
 11708               IP(dst=target, id=1)/TCP(seq=1, sport=5004, dport=oport, options=tcpopt, flags="A"),
 11709               IP(dst=target, id=1)/TCP(seq=1, sport=5005, dport=cport, options=tcpopt, flags="S"),
 11710               IP(dst=target, id=1)/TCP(seq=1, sport=5006, dport=cport, options=tcpopt, flags="A"),
 11711               IP(dst=target, id=1)/TCP(seq=1, sport=5007, dport=cport, options=tcpopt, flags="FPU"),
 11712               IP(str(IP(dst=target)/UDP(sport=5008,dport=ucport)/(300*"i"))) ]
 11713 
 11714     ans, unans = sr(tests, timeout=2)
 11715     ans += map(lambda x: (x,None), unans)
 11716 
 11717     for S,T in ans:
 11718         if S.sport == 5008:
 11719             res["PU"] = nmap_udppacket_sig(S,T)
 11720         else:
 11721             t = "T%i" % (S.sport-5000)
 11722             if T is not None and T.haslayer(ICMP):
 11723                 warning("Test %s answered by an ICMP" % t)
 11724                 T=None
 11725             res[t] = nmap_tcppacket_sig(T)
 11726 
 11727     return res
 11728 
 11729 def nmap_probes2sig(tests):
 11730     tests=tests.copy()
 11731     res = {}
 11732     if "PU" in tests:
 11733         res["PU"] = nmap_udppacket_sig(*tests["PU"])
 11734         del(tests["PU"])
 11735     for k in tests:
 11736         res[k] = nmap_tcppacket_sig(tests[k])
 11737     return res
 11738         
 11739 
 11740 def nmap_search(sigs):
 11741     guess = 0,[]
 11742     for os,fp in nmap_kdb.get_base():
 11743         c = 0.0
 11744         for t in sigs.keys():
 11745             if t in fp:
 11746                 c += nmap_match_one_sig(sigs[t], fp[t])
 11747         c /= len(sigs.keys())
 11748         if c > guess[0]:
 11749             guess = c,[ os ]
 11750         elif c == guess[0]:
 11751             guess[1].append(os)
 11752     return guess
 11753     
 11754     
 11755 def nmap_fp(target, oport=80, cport=81):
 11756     """nmap fingerprinting
 11757 nmap_fp(target, [oport=80,] [cport=81,]) -> list of best guesses with accuracy
 11758 """
 11759     sigs = nmap_sig(target, oport, cport)
 11760     return nmap_search(sigs)
 11761         
 11762 
 11763 def nmap_sig2txt(sig):
 11764     torder = ["TSeq","T1","T2","T3","T4","T5","T6","T7","PU"]
 11765     korder = ["Class", "gcd", "SI", "IPID", "TS",
 11766               "Resp", "DF", "W", "ACK", "Flags", "Ops",
 11767               "TOS", "IPLEN", "RIPTL", "RID", "RIPCK", "UCK", "ULEN", "DAT" ]
 11768     txt=[]
 11769     for i in sig.keys():
 11770         if i not in torder:
 11771             torder.append(i)
 11772     for t in torder:
 11773         sl = sig.get(t)
 11774         if sl is None:
 11775             continue
 11776         s = []
 11777         for k in korder:
 11778             v = sl.get(k)
 11779             if v is None:
 11780                 continue
 11781             s.append("%s=%s"%(k,v))
 11782         txt.append("%s(%s)" % (t, "%".join(s)))
 11783     return "\n".join(txt)
 11784             
 11785         
 11786 
 11787 
 11788 
 11789 ###################
 11790 ## User commands ##
 11791 ###################
 11792 
 11793 
 11794 def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None, *arg, **karg):
 11795     """Sniff packets
 11796 sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
 11797 
 11798   count: number of packets to capture. 0 means infinity
 11799   store: wether to store sniffed packets or discard them
 11800     prn: function to apply to each packet. If something is returned,
 11801          it is displayed. Ex:
 11802          ex: prn = lambda x: x.summary()
 11803 lfilter: python function applied to each packet to determine
 11804          if further action may be done
 11805          ex: lfilter = lambda x: x.haslayer(Padding)
 11806 offline: pcap file to read packets from, instead of sniffing them
 11807 timeout: stop sniffing after a given time (default: None)
 11808 L2socket: use the provided L2socket
 11809     """
 11810     c = 0
 11811 
 11812     if offline is None:
 11813         if L2socket is None:
 11814             L2socket = conf.L2listen
 11815         s = L2socket(type=ETH_P_ALL, *arg, **karg)
 11816     else:
 11817         s = PcapReader(offline)
 11818 
 11819     lst = []
 11820     if timeout is not None:
 11821         stoptime = time.time()+timeout
 11822     remain = None
 11823     while 1:
 11824         try:
 11825             if timeout is not None:
 11826                 remain = stoptime-time.time()
 11827                 if remain <= 0:
 11828                     break
 11829             sel = select([s],[],[],remain)
 11830             if s in sel[0]:
 11831                 p = s.recv(MTU)
 11832                 if p is None:
 11833                     break
 11834                 if lfilter and not lfilter(p):
 11835                     continue
 11836                 if store:
 11837                     lst.append(p)
 11838                 c += 1
 11839                 if prn:
 11840                     r = prn(p)
 11841                     if r is not None:
 11842                         print r
 11843                 if count > 0 and c >= count:
 11844                     break
 11845         except KeyboardInterrupt:
 11846             break
 11847     s.close()
 11848     return PacketList(lst,"Sniffed")
 11849 
 11850 
 11851 
 11852 def arpcachepoison(target, victim, interval=60):
 11853     """Poison target's cache with (your MAC,victim's IP) couple
 11854 arpcachepoison(target, victim, [interval=60]) -> None
 11855 """
 11856     tmac = getmacbyip(target)
 11857     p = Ether(dst=tmac)/ARP(op="who-has", psrc=victim, pdst=target)
 11858     try:
 11859         while 1:
 11860             sendp(p, iface_hint=target)
 11861             if conf.verb > 1:
 11862                 os.write(1,".")
 11863             time.sleep(interval)
 11864     except KeyboardInterrupt:
 11865         pass
 11866 
 11867 def traceroute(target, dport=80, minttl=1, maxttl=30, sport=RandShort(), l4 = None, filter=None, timeout=2, verbose=None, **kargs):
 11868     """Instant TCP traceroute
 11869 traceroute(target, [maxttl=30,] [dport=80,] [sport=80,] [verbose=conf.verb]) -> None
 11870 """
 11871     if verbose is None:
 11872         verbose = conf.verb
 11873     if filter is None:
 11874         # we only consider ICMP error packets and TCP packets with at
 11875         # least the ACK flag set *and* either the SYN or the RST flag
 11876         # set
 11877         filter="(icmp and (icmp[0]=3 or icmp[0]=4 or icmp[0]=5 or icmp[0]=11 or icmp[0]=12)) or (tcp and (tcp[13] & 0x16 > 0x10))"
 11878     if l4 is None:
 11879         a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
 11880                  timeout=timeout, filter=filter, verbose=verbose, **kargs)
 11881     else:
 11882         # this should always work
 11883         filter="ip"
 11884         a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/l4,
 11885                  timeout=timeout, filter=filter, verbose=verbose, **kargs)
 11886 
 11887     a = TracerouteResult(a.res)
 11888     if verbose:
 11889         a.show()
 11890     return a,b
 11891 
 11892 
 11893 
 11894 
 11895 def arping(net, timeout=2, cache=0, verbose=None, **kargs):
 11896     """Send ARP who-has requests to determine which hosts are up
 11897 arping(net, [cache=0,] [iface=conf.iface,] [verbose=conf.verb]) -> None
 11898 Set cache=True if you want arping to modify internal ARP-Cache"""
 11899     if verbose is None:
 11900         verbose = conf.verb
 11901     ans,unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=net), verbose=verbose,
 11902                     filter="arp and arp[7] = 2", timeout=timeout, iface_hint=net, **kargs)
 11903     ans = ARPingResult(ans.res)
 11904 
 11905     if cache and ans is not None:
 11906         for pair in ans:
 11907             arp_cache[pair[1].psrc] = (pair[1].hwsrc, time.time())
 11908     if verbose:
 11909         ans.show()
 11910     return ans,unans
 11911 
 11912 def dyndns_add(nameserver, name, rdata, type="A", ttl=10):
 11913     """Send a DNS add message to a nameserver for "name" to have a new "rdata"
 11914 dyndns_add(nameserver, name, rdata, type="A", ttl=10) -> result code (0=ok)
 11915 
 11916 example: dyndns_add("ns1.toto.com", "dyn.toto.com", "127.0.0.1")
 11917 RFC2136
 11918 """
 11919     zone = name[name.find(".")+1:]
 11920     r=sr1(IP(dst=nameserver)/UDP()/DNS(opcode=5,
 11921                                        qd=[DNSQR(qname=zone, qtype="SOA")],
 11922                                        ns=[DNSRR(rrname=name, type="A",
 11923                                                  ttl=ttl, rdata=rdata)]),
 11924           verbose=0, timeout=5)
 11925     if r and r.haslayer(DNS):
 11926         return r.getlayer(DNS).rcode
 11927     else:
 11928         return -1
 11929     
 11930     
 11931     
 11932 
 11933 def dyndns_del(nameserver, name, type="ALL", ttl=10):
 11934     """Send a DNS delete message to a nameserver for "name"
 11935 dyndns_del(nameserver, name, type="ANY", ttl=10) -> result code (0=ok)
 11936 
 11937 example: dyndns_del("ns1.toto.com", "dyn.toto.com")
 11938 RFC2136
 11939 """
 11940     zone = name[name.find(".")+1:]
 11941     r=sr1(IP(dst=nameserver)/UDP()/DNS(opcode=5,
 11942                                        qd=[DNSQR(qname=zone, qtype="SOA")],
 11943                                        ns=[DNSRR(rrname=name, type=type,
 11944                                                  rclass="ANY", ttl=0, rdata="")]),
 11945           verbose=0, timeout=5)
 11946     if r and r.haslayer(DNS):
 11947         return r.getlayer(DNS).rcode
 11948     else:
 11949         return -1
 11950     
 11951 
 11952 def is_promisc(ip, fake_bcast="ff:ff:00:00:00:00",**kargs):
 11953     """Try to guess if target is in Promisc mode. The target is provided by its ip."""
 11954 
 11955     responses = srp1(Ether(dst=fake_bcast) / ARP(op="who-has", pdst=ip),type=ETH_P_ARP, iface_hint=ip, timeout=1, verbose=0,**kargs)
 11956 
 11957     return responses is not None
 11958 
 11959 def promiscping(net, timeout=2, fake_bcast="ff:ff:ff:ff:ff:fe", **kargs):
 11960     """Send ARP who-has requests to determine which hosts are in promiscuous mode
 11961     promiscping(net, iface=conf.iface)"""
 11962     ans,unans = srp(Ether(dst=fake_bcast)/ARP(pdst=net),
 11963                     filter="arp and arp[7] = 2", timeout=timeout, iface_hint=net, **kargs)
 11964     ans = ARPingResult(ans.res, name="PROMISCPing")
 11965 
 11966     ans.display()
 11967     return ans,unans
 11968 
 11969 def ikescan(ip):
 11970     return sr(IP(dst=ip)/UDP()/ISAKMP(init_cookie=RandString(8),
 11971                                       exch_type=2)/ISAKMP_payload_SA(prop=ISAKMP_payload_Proposal()))
 11972 
 11973 
 11974 def dhcp_request(iface=None,**kargs):
 11975     if conf.checkIPaddr != 0:
 11976         warning("conf.checkIPaddr is not 0, I may not be able to match the answer")
 11977     if iface is None:
 11978         iface = conf.iface
 11979     fam,hw = get_if_raw_hwaddr(iface)
 11980     return srp1(Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)
 11981                  /BOOTP(chaddr=hw)/DHCP(options=[("message-type","discover"),"end"]),iface=iface,**kargs)
 11982 
 11983 def snmpwalk(dst, oid="1", community="public"):
 11984     try:
 11985         while 1:
 11986             r = sr1(IP(dst=dst)/UDP(sport=RandShort())/SNMP(community=community, PDU=SNMPnext(varbindlist=[SNMPvarbind(oid=oid)])),timeout=2, chainCC=1, verbose=0, retry=2)
 11987             if ICMP in r:
 11988                 print repr(r)
 11989                 break
 11990             if r is None:
 11991                 print "No answers"
 11992                 break
 11993             print "%-40s: %r" % (r[SNMPvarbind].oid.val,r[SNMPvarbind].value)
 11994             oid = r[SNMPvarbind].oid
 11995             
 11996     except KeyboardInterrupt:
 11997         pass
 11998 
 11999 
 12000 #####################
 12001 ## Reporting stuff ##
 12002 #####################
 12003 
 12004 def report_ports(target, ports):
 12005     """portscan a target and output a LaTeX table
 12006 report_ports(target, ports) -> string"""
 12007     ans,unans = sr(IP(dst=target)/TCP(dport=ports),timeout=5)
 12008     rep = "\\begin{tabular}{|r|l|l|}\n\\hline\n"
 12009     for s,r in ans:
 12010         if not r.haslayer(ICMP):
 12011             if r.payload.flags == 0x12:
 12012                 rep += r.sprintf("%TCP.sport% & open & SA \\\\\n")
 12013     rep += "\\hline\n"
 12014     for s,r in ans:
 12015         if r.haslayer(ICMP):
 12016             rep += r.sprintf("%TCPerror.dport% & closed & ICMP type %ICMP.type%/%ICMP.code% from %IP.src% \\\\\n")
 12017         elif r.payload.flags != 0x12:
 12018             rep += r.sprintf("%TCP.sport% & closed & TCP %TCP.flags% \\\\\n")
 12019     rep += "\\hline\n"
 12020     for i in unans:
 12021         rep += i.sprintf("%TCP.dport% & ? & unanswered \\\\\n")
 12022     rep += "\\hline\n\\end{tabular}\n"
 12023     return rep
 12024 
 12025 
 12026 def __make_table(yfmtfunc, fmtfunc, endline, list, fxyz, sortx=None, sorty=None, seplinefunc=None):
 12027     vx = {} 
 12028     vy = {} 
 12029     vz = {}
 12030     vxf = {}
 12031     vyf = {}
 12032     l = 0
 12033     for e in list:
 12034         xx,yy,zz = map(str, fxyz(e))
 12035         l = max(len(yy),l)
 12036         vx[xx] = max(vx.get(xx,0), len(xx), len(zz))
 12037         vy[yy] = None
 12038         vz[(xx,yy)] = zz
 12039 
 12040     vxk = vx.keys()
 12041     vyk = vy.keys()
 12042     if sortx:
 12043         vxk.sort(sortx)
 12044     else:
 12045         try:
 12046             vxk.sort(lambda x,y:int(x)-int(y))
 12047         except:
 12048             try:
 12049                 vxk.sort(lambda x,y: cmp(atol(x),atol(y)))
 12050             except:
 12051                 vxk.sort()
 12052     if sorty:
 12053         vyk.sort(sorty)
 12054     else:
 12055         try:
 12056             vyk.sort(lambda x,y:int(x)-int(y))
 12057         except:
 12058             try:
 12059                 vyk.sort(lambda x,y: cmp(atol(x),atol(y)))
 12060             except:
 12061                 vyk.sort()
 12062 
 12063 
 12064     if seplinefunc:
 12065         sepline = seplinefunc(l, map(lambda x:vx[x],vxk))
 12066         print sepline
 12067 
 12068     fmt = yfmtfunc(l)
 12069     print fmt % "",
 12070     for x in vxk:
 12071         vxf[x] = fmtfunc(vx[x])
 12072         print vxf[x] % x,
 12073     print endline
 12074     if seplinefunc:
 12075         print sepline
 12076     for y in vyk:
 12077         print fmt % y,
 12078         for x in vxk:
 12079             print vxf[x] % vz.get((x,y), "-"),
 12080         print endline
 12081     if seplinefunc:
 12082         print sepline
 12083 
 12084 def make_table(*args, **kargs):
 12085     __make_table(lambda l:"%%-%is" % l, lambda l:"%%-%is" % l, "", *args, **kargs)
 12086     
 12087 def make_lined_table(*args, **kargs):
 12088     __make_table(lambda l:"%%-%is |" % l, lambda l:"%%-%is |" % l, "",
 12089                  seplinefunc=lambda a,x:"+".join(map(lambda y:"-"*(y+2), [a-1]+x+[-2])),
 12090                  *args, **kargs)
 12091 
 12092 def make_tex_table(*args, **kargs):
 12093     __make_table(lambda l: "%s", lambda l: "& %s", "\\\\", seplinefunc=lambda a,x:"\\hline", *args, **kargs)
 12094     
 12095 
 12096 ######################
 12097 ## Online doc stuff ##
 12098 ######################
 12099 
 12100 
 12101 def lsc(cmd=None):
 12102     """List user commands"""
 12103     if cmd is None:
 12104         for c in user_commands:
 12105             doc = "No doc. available"
 12106             if c.__doc__:
 12107                 doc = c.__doc__.split("\n")[0]
 12108             
 12109             print "%-16s : %s" % (c.__name__, doc)
 12110     else:
 12111         print cmd.__doc__
 12112 
 12113 def ls(obj=None):
 12114     """List  available layers, or infos on a given layer"""
 12115     if obj is None:
 12116         import __builtin__
 12117         all = __builtin__.__dict__.copy()
 12118         all.update(globals())
 12119         objlst = filter(lambda (n,o): isinstance(o,type) and issubclass(o,Packet), all.items())
 12120         objlst.sort(lambda x,y:cmp(x[0],y[0]))
 12121         for n,o in objlst:
 12122             print "%-10s : %s" %(n,o.name)
 12123     else:
 12124         if isinstance(obj, type) and issubclass(obj, Packet):
 12125             for f in obj.fields_desc:
 12126                 print "%-10s : %-20s = (%s)" % (f.name, f.__class__.__name__,  repr(f.default))
 12127         elif isinstance(obj, Packet):
 12128             for f in obj.fields_desc:
 12129                 print "%-10s : %-20s = %-15s (%s)" % (f.name, f.__class__.__name__, repr(getattr(obj,f.name)), repr(f.default))
 12130             if not isinstance(obj.payload, NoPayload):
 12131                 print "--"
 12132                 ls(obj.payload)
 12133                 
 12134 
 12135         else:
 12136             print "Not a packet class. Type 'ls()' to list packet classes."
 12137 
 12138 
 12139     
 12140 
 12141 
 12142 user_commands = [ sr, sr1, srp, srp1, srloop, srploop, sniff, p0f, arpcachepoison, send, sendp, traceroute, arping, ls, lsc, queso, nmap_fp, report_ports, dyndns_add, dyndns_del, is_promisc, promiscping ]
 12143 
 12144 
 12145 ##############
 12146 ## Automata ##
 12147 ##############
 12148 
 12149 class ATMT:
 12150     STATE = "State"
 12151     ACTION = "Action"
 12152     CONDITION = "Condition"
 12153     RECV = "Receive condition"
 12154     TIMEOUT = "Timeout condition"
 12155 
 12156     class NewStateRequested(Exception):
 12157         def __init__(self, state_func, automaton, *args, **kargs):
 12158             self.func = state_func
 12159             self.state = state_func.atmt_state
 12160             self.initial = state_func.atmt_initial
 12161             self.error = state_func.atmt_error
 12162             self.final = state_func.atmt_final
 12163             Exception.__init__(self, "Request state [%s]" % self.state)
 12164             self.automaton = automaton
 12165             self.args = args
 12166             self.kargs = kargs
 12167             self.action_parameters() # init action parameters
 12168         def action_parameters(self, *args, **kargs):
 12169             self.action_args = args
 12170             self.action_kargs = kargs
 12171             return self
 12172         def run(self):
 12173             return self.func(self.automaton, *self.args, **self.kargs)
 12174 
 12175     @staticmethod
 12176     def state(initial=0,final=0,error=0):
 12177         def deco(f,initial=initial, final=final):
 12178             f.atmt_type = ATMT.STATE
 12179             f.atmt_state = f.func_name
 12180             f.atmt_initial = initial
 12181             f.atmt_final = final
 12182             f.atmt_error = error
 12183             def state_wrapper(self, *args, **kargs):
 12184                 return ATMT.NewStateRequested(f, self, *args, **kargs)
 12185 
 12186             state_wrapper.func_name = "%s_wrapper" % f.func_name
 12187             state_wrapper.atmt_type = ATMT.STATE
 12188             state_wrapper.atmt_state = f.func_name
 12189             state_wrapper.atmt_initial = initial
 12190             state_wrapper.atmt_final = final
 12191             state_wrapper.atmt_error = error
 12192             state_wrapper.atmt_origfunc = f
 12193             return state_wrapper
 12194         return deco
 12195     @staticmethod
 12196     def action(cond, prio=0):
 12197         def deco(f,cond=cond):
 12198             if not hasattr(f,"atmt_type"):
 12199                 f.atmt_cond = {}
 12200             f.atmt_type = ATMT.ACTION
 12201             f.atmt_cond[cond.atmt_condname] = prio
 12202             return f
 12203         return deco
 12204     @staticmethod
 12205     def condition(state, prio=0):
 12206         def deco(f, state=state):
 12207             f.atmt_type = ATMT.CONDITION
 12208             f.atmt_state = state.atmt_state
 12209             f.atmt_condname = f.func_name
 12210             f.atmt_prio = prio
 12211             return f
 12212         return deco
 12213     @staticmethod
 12214     def receive_condition(state, prio=0):
 12215         def deco(f, state=state):
 12216             f.atmt_type = ATMT.RECV
 12217             f.atmt_state = state.atmt_state
 12218             f.atmt_condname = f.func_name
 12219             f.atmt_prio = prio
 12220             return f
 12221         return deco
 12222     @staticmethod
 12223     def timeout(state, timeout):
 12224         def deco(f, state=state, timeout=timeout):
 12225             f.atmt_type = ATMT.TIMEOUT
 12226             f.atmt_state = state.atmt_state
 12227             f.atmt_timeout = timeout
 12228             f.atmt_condname = f.func_name
 12229             return f
 12230         return deco
 12231 
 12232 
 12233 class Automaton_metaclass(type):
 12234     def __new__(cls, name, bases, dct):
 12235         cls = super(Automaton_metaclass, cls).__new__(cls, name, bases, dct)
 12236         cls.states={}
 12237         cls.state = None
 12238         cls.recv_conditions={}
 12239         cls.conditions={}
 12240         cls.timeout={}
 12241         cls.actions={}
 12242         cls.initial_states=[]
 12243 
 12244         members = {}
 12245         classes = [cls]
 12246         while classes:
 12247             c = classes.pop(0) # order is important to avoid breaking method overloading
 12248             classes += list(c.__bases__)
 12249             for k,v in c.__dict__.iteritems():
 12250                 if k not in members:
 12251                     members[k] = v
 12252 
 12253         decorated = [v for v in members.itervalues()
 12254                      if type(v) is types.FunctionType and hasattr(v, "atmt_type")]
 12255         
 12256         for m in decorated:
 12257             if m.atmt_type == ATMT.STATE:
 12258                 s = m.atmt_state
 12259                 cls.states[s] = m
 12260                 cls.recv_conditions[s]=[]
 12261                 cls.conditions[s]=[]
 12262                 cls.timeout[s]=[]
 12263                 if m.atmt_initial:
 12264                     cls.initial_states.append(m)
 12265             elif m.atmt_type in [ATMT.CONDITION, ATMT.RECV, ATMT.TIMEOUT]:
 12266                 cls.actions[m.atmt_condname] = []
 12267     
 12268         for m in decorated:
 12269             if m.atmt_type == ATMT.CONDITION:
 12270                 cls.conditions[m.atmt_state].append(m)
 12271             elif m.atmt_type == ATMT.RECV:
 12272                 cls.recv_conditions[m.atmt_state].append(m)
 12273             elif m.atmt_type == ATMT.TIMEOUT:
 12274                 cls.timeout[m.atmt_state].append((m.atmt_timeout, m))
 12275             elif m.atmt_type == ATMT.ACTION:
 12276                 for c in m.atmt_cond:
 12277                     cls.actions[c].append(m)
 12278             
 12279 
 12280         for v in cls.timeout.itervalues():
 12281             v.sort(lambda (t1,f1),(t2,f2): cmp(t1,t2))
 12282             v.append((None, None))
 12283         for v in itertools.chain(cls.conditions.itervalues(),
 12284                                  cls.recv_conditions.itervalues()):
 12285             v.sort(lambda c1,c2: cmp(c1.atmt_prio,c2.atmt_prio))
 12286         for condname,actlst in cls.actions.iteritems():
 12287             actlst.sort(lambda c1,c2: cmp(c1.atmt_cond[condname], c2.atmt_cond[condname]))
 12288 
 12289         return cls
 12290 
 12291         
 12292     def graph(self, **kargs):
 12293         s = 'digraph "%s" {\n'  % self.__class__.__name__
 12294         
 12295         se = "" # Keep initial nodes at the begining for better rendering
 12296         for st in self.states.itervalues():
 12297             if st.atmt_initial:
 12298                 se = ('\t"%s" [ style=filled, fillcolor=blue, shape=box, root=true];\n' % st.atmt_state)+se
 12299             elif st.atmt_final:
 12300                 se += '\t"%s" [ style=filled, fillcolor=green, shape=octagon ];\n' % st.atmt_state
 12301             elif st.atmt_error:
 12302                 se += '\t"%s" [ style=filled, fillcolor=red, shape=octagon ];\n' % st.atmt_state
 12303         s += se
 12304 
 12305         for st in self.states.values():
 12306             for n in st.atmt_origfunc.func_code.co_names+st.atmt_origfunc.func_code.co_consts:
 12307                 if n in self.states:
 12308                     s += '\t"%s" -> "%s" [ color=green ];\n' % (st.atmt_state,n)
 12309             
 12310 
 12311         for c,k,v in [("purple",k,v) for k,v in self.conditions.items()]+[("red",k,v) for k,v in self.recv_conditions.items()]:
 12312             for f in v:
 12313                 for n in f.func_code.co_names+f.func_code.co_consts:
 12314                     if n in self.states:
 12315                         l = f.atmt_condname
 12316                         for x in self.actions[f.atmt_condname]:
 12317                             l += "\\l>[%s]" % x.func_name
 12318                         s += '\t"%s" -> "%s" [label="%s", color=%s];\n' % (k,n,l,c)
 12319         for k,v in self.timeout.iteritems():
 12320             for t,f in v:
 12321                 if f is None:
 12322                     continue
 12323                 for n in f.func_code.co_names+f.func_code.co_consts:
 12324                     if n in self.states:
 12325                         l = "%s/%.1fs" % (f.atmt_condname,t)                        
 12326                         for x in self.actions[f.atmt_condname]:
 12327                             l += "\\l>[%s]" % x.func_name
 12328                         s += '\t"%s" -> "%s" [label="%s",color=blue];\n' % (k,n,l)
 12329         s += "}\n"
 12330         return do_graph(s, **kargs)
 12331         
 12332 
 12333 
 12334 class Automaton:
 12335     __metaclass__ = Automaton_metaclass
 12336 
 12337     def __init__(self, *args, **kargs):
 12338         self.debug_level=0
 12339         self.init_args=args
 12340         self.init_kargs=kargs
 12341         self.parse_args(*args, **kargs)
 12342 
 12343     def debug(self, lvl, msg):
 12344         if self.debug_level >= lvl:
 12345             log_interactive.debug(msg)
 12346             
 12347 
 12348 
 12349 
 12350     class ErrorState(Exception):
 12351         def __init__(self, msg, result=None):
 12352             Exception.__init__(self, msg)
 12353             self.result = result
 12354     class Stuck(ErrorState):
 12355         pass
 12356 
 12357     def parse_args(self, debug=0, store=1, **kargs):
 12358         self.debug_level=debug
 12359         self.socket_kargs = kargs
 12360         self.store_packets = store
 12361         
 12362 
 12363     def master_filter(self, pkt):
 12364         return True
 12365 
 12366     def run_condition(self, cond, *args, **kargs):
 12367         try:
 12368             cond(self,*args, **kargs)
 12369         except ATMT.NewStateRequested, state_req:
 12370             self.debug(2, "%s [%s] taken to state [%s]" % (cond.atmt_type, cond.atmt_condname, state_req.state))
 12371             if cond.atmt_type == ATMT.RECV:
 12372                 self.packets.append(args[0])
 12373             for action in self.actions[cond.atmt_condname]:
 12374                 self.debug(2, "   + Running action [%s]" % action.func_name)
 12375                 action(self, *state_req.action_args, **state_req.action_kargs)
 12376             raise
 12377         else:
 12378             self.debug(2, "%s [%s] not taken" % (cond.atmt_type, cond.atmt_condname))
 12379             
 12380 
 12381     def run(self, *args, **kargs):
 12382         # Update default parameters
 12383         a = args+self.init_args[len(args):]
 12384         k = self.init_kargs
 12385         k.update(kargs)
 12386         self.parse_args(*a,**k)
 12387 
 12388         # Start the automaton
 12389         self.state=self.initial_states[0](self)
 12390         self.send_sock = conf.L3socket()
 12391         l = conf.L2listen(**self.socket_kargs)
 12392         self.packets = PacketList(name="session[%s]"%self.__class__.__name__)
 12393         while 1:
 12394             try:
 12395                 self.debug(1, "## state=[%s]" % self.state.state)
 12396 
 12397                 # Entering a new state. First, call new state function
 12398                 state_output = self.state.run()
 12399                 if self.state.error:
 12400                     raise self.ErrorState("Reached %s: [%r]" % (self.state.state, state_output), result=state_output)
 12401                 if self.state.final:
 12402                     return state_output
 12403 
 12404                 if state_output is None:
 12405                     state_output = ()
 12406                 elif type(state_output) is not list:
 12407                     state_output = state_output,
 12408                 
 12409                 # Then check immediate conditions
 12410                 for cond in self.conditions[self.state.state]:
 12411                     self.run_condition(cond, *state_output)
 12412 
 12413                 # If still there and no conditions left, we are stuck!
 12414                 if ( len(self.recv_conditions[self.state.state]) == 0
 12415                      and len(self.timeout[self.state.state]) == 1 ):
 12416                     raise self.Stuck("stuck in [%s]" % self.state.state,result=state_output)
 12417 
 12418                 # Finally listen and pay attention to timeouts
 12419                 expirations = iter(self.timeout[self.state.state])
 12420                 next_timeout,timeout_func = expirations.next()
 12421                 t0 = time.time()
 12422                 
 12423                 while 1:
 12424                     t = time.time()-t0
 12425                     if next_timeout is not None:
 12426                         if next_timeout <= t:
 12427                             self.run_condition(timeout_func, *state_output)
 12428                             next_timeout,timeout_func = expirations.next()
 12429                     if next_timeout is None:
 12430                         remain = None
 12431                     else:
 12432                         remain = next_timeout-t
 12433     
 12434                     r,_,_ = select([l],[],[],remain)
 12435                     if l in r:
 12436                         pkt = l.recv(MTU)
 12437                         if pkt is not None:
 12438                             if self.master_filter(pkt):
 12439                                 self.debug(3, "RECVD: %s" % pkt.summary())
 12440                                 for rcvcond in self.recv_conditions[self.state.state]:
 12441                                     self.run_condition(rcvcond, pkt, *state_output)
 12442                             else:
 12443                                 self.debug(4, "FILTR: %s" % pkt.summary())
 12444 
 12445             except ATMT.NewStateRequested,state_req:
 12446                 self.debug(2, "switching from [%s] to [%s]" % (self.state.state,state_req.state))
 12447                 self.state = state_req
 12448             except KeyboardInterrupt:
 12449                 self.debug(1,"Interrupted by user")
 12450                 break
 12451 
 12452     def my_send(self, pkt):
 12453         self.send_sock.send(pkt)
 12454 
 12455     def send(self, pkt):
 12456         self.my_send(pkt)
 12457         self.debug(3,"SENT : %s" % pkt.summary())
 12458         self.packets.append(pkt.copy())
 12459 
 12460 
 12461         
 12462 
 12463     
 12464 
 12465 class TFTP_read(Automaton):
 12466     def parse_args(self, filename, server, sport = None, port=69, **kargs):
 12467         Automaton.parse_args(self, **kargs)
 12468         self.filename = filename
 12469         self.server = server
 12470         self.port = port
 12471         self.sport = sport
 12472 
 12473 
 12474     def master_filter(self, pkt):
 12475         return ( IP in pkt and pkt[IP].src == self.server and UDP in pkt
 12476                  and pkt[UDP].dport == self.my_tid
 12477                  and (self.server_tid is None or pkt[UDP].sport == self.server_tid) )
 12478         
 12479     # BEGIN
 12480     @ATMT.state(initial=1)
 12481     def BEGIN(self):
 12482         self.blocksize=512
 12483         self.my_tid = self.sport or RandShort()._fix()
 12484         bind_bottom_up(UDP, TFTP, dport=self.my_tid)
 12485         self.server_tid = None
 12486         self.res = ""
 12487 
 12488         self.l3 = IP(dst=self.server)/UDP(sport=self.my_tid, dport=self.port)/TFTP()
 12489         self.last_packet = self.l3/TFTP_RRQ(filename=self.filename, mode="octet")
 12490         self.send(self.last_packet)
 12491         self.awaiting=1
 12492         
 12493         raise self.WAITING()
 12494         
 12495     # WAITING
 12496     @ATMT.state()
 12497     def WAITING(self):
 12498         pass
 12499 
 12500 
 12501     @ATMT.receive_condition(WAITING)
 12502     def receive_data(self, pkt):
 12503         if TFTP_DATA in pkt and pkt[TFTP_DATA].block == self.awaiting:
 12504             if self.server_tid is None:
 12505                 self.server_tid = pkt[UDP].sport
 12506                 self.l3[UDP].dport = self.server_tid
 12507             raise self.RECEIVING(pkt)
 12508 
 12509     @ATMT.receive_condition(WAITING, prio=1)
 12510     def receive_error(self, pkt):
 12511         if TFTP_ERROR in pkt:
 12512             raise self.ERROR(pkt)
 12513     
 12514         
 12515     @ATMT.timeout(WAITING, 3)
 12516     def timeout_waiting(self):
 12517         raise self.WAITING()
 12518     @ATMT.action(timeout_waiting)
 12519     def retransmit_last_packet(self):
 12520         self.send(self.last_packet)
 12521 
 12522     @ATMT.action(receive_data)
 12523 #    @ATMT.action(receive_error)
 12524     def send_ack(self):
 12525         self.last_packet = self.l3 / TFTP_ACK(block = self.awaiting)
 12526         self.send(self.last_packet)
 12527     
 12528 
 12529     # RECEIVED
 12530     @ATMT.state()
 12531     def RECEIVING(self, pkt):
 12532         if Raw in pkt:
 12533             recvd = pkt[Raw].load
 12534         else:
 12535             recvd = ""
 12536         self.res += recvd
 12537         self.awaiting += 1
 12538         if len(recvd) == self.blocksize:
 12539             raise self.WAITING()
 12540         raise self.END()
 12541 
 12542     # ERROR
 12543     @ATMT.state(error=1)
 12544     def ERROR(self,pkt):
 12545         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12546         return pkt[TFTP_ERROR].summary()
 12547     
 12548     #END
 12549     @ATMT.state(final=1)
 12550     def END(self):
 12551         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12552         return self.res
 12553 
 12554 
 12555 
 12556 
 12557 class TFTP_write(Automaton):
 12558     def parse_args(self, filename, data, server, sport=None, port=69,**kargs):
 12559         Automaton.parse_args(self, **kargs)
 12560         self.filename = filename
 12561         self.server = server
 12562         self.port = port
 12563         self.sport = sport
 12564         self.blocksize = 512
 12565         self.origdata = data
 12566 
 12567     def master_filter(self, pkt):
 12568         return ( IP in pkt and pkt[IP].src == self.server and UDP in pkt
 12569                  and pkt[UDP].dport == self.my_tid
 12570                  and (self.server_tid is None or pkt[UDP].sport == self.server_tid) )
 12571         
 12572 
 12573     # BEGIN
 12574     @ATMT.state(initial=1)
 12575     def BEGIN(self):
 12576         self.data = [ self.origdata[i*self.blocksize:(i+1)*self.blocksize]
 12577                       for i in range( len(self.origdata)/self.blocksize+1) ] 
 12578         self.my_tid = self.sport or RandShort()._fix()
 12579         bind_bottom_up(UDP, TFTP, dport=self.my_tid)
 12580         self.server_tid = None
 12581         
 12582         self.l3 = IP(dst=self.server)/UDP(sport=self.my_tid, dport=self.port)/TFTP()
 12583         self.last_packet = self.l3/TFTP_WRQ(filename=self.filename, mode="octet")
 12584         self.send(self.last_packet)
 12585         self.res = ""
 12586         self.awaiting=0
 12587 
 12588         raise self.WAITING_ACK()
 12589         
 12590     # WAITING_ACK
 12591     @ATMT.state()
 12592     def WAITING_ACK(self):
 12593         pass
 12594 
 12595     @ATMT.receive_condition(WAITING_ACK)    
 12596     def received_ack(self,pkt):
 12597         if TFTP_ACK in pkt and pkt[TFTP_ACK].block == self.awaiting:
 12598             if self.server_tid is None:
 12599                 self.server_tid = pkt[UDP].sport
 12600                 self.l3[UDP].dport = self.server_tid
 12601             raise self.SEND_DATA()
 12602 
 12603     @ATMT.receive_condition(WAITING_ACK)
 12604     def received_error(self, pkt):
 12605         if TFTP_ERROR in pkt:
 12606             raise self.ERROR(pkt)
 12607 
 12608     @ATMT.timeout(WAITING_ACK, 3)
 12609     def timeout_waiting(self):
 12610         raise self.WAITING_ACK()
 12611     @ATMT.action(timeout_waiting)
 12612     def retransmit_last_packet(self):
 12613         self.send(self.last_packet)
 12614     
 12615     # SEND_DATA
 12616     @ATMT.state()
 12617     def SEND_DATA(self):
 12618         self.awaiting += 1
 12619         self.last_packet = self.l3/TFTP_DATA(block=self.awaiting)/self.data.pop(0)
 12620         self.send(self.last_packet)
 12621         if self.data:
 12622             raise self.WAITING_ACK()
 12623         raise self.END()
 12624     
 12625 
 12626     # ERROR
 12627     @ATMT.state(error=1)
 12628     def ERROR(self,pkt):
 12629         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12630         return pkt[TFTP_ERROR].summary()
 12631 
 12632     # END
 12633     @ATMT.state(final=1)
 12634     def END(self):
 12635         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12636 
 12637 
 12638 class TFTP_WRQ_server(Automaton):
 12639 
 12640     def parse_args(self, ip=None, sport=None, *args, **kargs):
 12641         Automaton.parse_args(self, *args, **kargs)
 12642         self.ip = ip
 12643         self.sport = sport
 12644 
 12645     def master_filter(self, pkt):
 12646         return TFTP in pkt and (not self.ip or pkt[IP].dst == self.ip)
 12647 
 12648     @ATMT.state(initial=1)
 12649     def BEGIN(self):
 12650         self.blksize=512
 12651         self.blk=1
 12652         self.filedata=""
 12653         self.my_tid = self.sport or random.randint(10000,65500)
 12654         bind_bottom_up(UDP, TFTP, dport=self.my_tid)
 12655 
 12656     @ATMT.receive_condition(BEGIN)
 12657     def receive_WRQ(self,pkt):
 12658         if TFTP_WRQ in pkt:
 12659             raise self.WAIT_DATA().action_parameters(pkt)
 12660         
 12661     @ATMT.action(receive_WRQ)
 12662     def ack_WRQ(self, pkt):
 12663         ip = pkt[IP]
 12664         self.ip = ip.dst
 12665         self.dst = ip.src
 12666         self.filename = pkt[TFTP_WRQ].filename
 12667         options = pkt[TFTP_Options]
 12668         self.l3 = IP(src=ip.dst, dst=ip.src)/UDP(sport=self.my_tid, dport=pkt.sport)/TFTP()
 12669         if options is None:
 12670             self.last_packet = self.l3/TFTP_ACK(block=0)
 12671             self.send(self.last_packet)
 12672         else:
 12673             opt = [x for x in options.options if x.oname.upper() == "BLKSIZE"]
 12674             if opt:
 12675                 self.blksize = int(opt[0].value)
 12676                 self.debug(2,"Negotiated new blksize at %i" % self.blksize)
 12677             self.last_packet = self.l3/TFTP_OACK()/TFTP_Options(options=opt)
 12678             self.send(self.last_packet)
 12679 
 12680     @ATMT.state()
 12681     def WAIT_DATA(self):
 12682         pass
 12683 
 12684     @ATMT.timeout(WAIT_DATA, 1)
 12685     def resend_ack(self):
 12686         self.send(self.last_packet)
 12687         raise self.WAIT_DATA()
 12688         
 12689     @ATMT.receive_condition(WAIT_DATA)
 12690     def receive_data(self, pkt):
 12691         if TFTP_DATA in pkt:
 12692             data = pkt[TFTP_DATA]
 12693             if data.block == self.blk:
 12694                 raise self.DATA(data)
 12695 
 12696     @ATMT.action(receive_data)
 12697     def ack_data(self):
 12698         self.last_packet = self.l3/TFTP_ACK(block = self.blk)
 12699         self.send(self.last_packet)
 12700 
 12701     @ATMT.state()
 12702     def DATA(self, data):
 12703         self.filedata += data.load
 12704         if len(data.load) < self.blksize:
 12705             raise self.END()
 12706         self.blk += 1
 12707         raise self.WAIT_DATA()
 12708 
 12709     @ATMT.state(final=1)
 12710     def END(self):
 12711         return self.filename,self.filedata
 12712         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12713         
 12714 
 12715 class TFTP_RRQ_server(Automaton):
 12716     def parse_args(self, store=None, joker=None, dir=None, ip=None, sport=None, serve_one=False, **kargs):
 12717         Automaton.parse_args(self,**kargs)
 12718         if store is None:
 12719             store = {}
 12720         if dir is not None:
 12721             self.dir = os.path.join(os.path.abspath(dir),"")
 12722         else:
 12723             self.dir = None
 12724         self.store = store
 12725         self.joker = joker
 12726         self.ip = ip
 12727         self.sport = sport
 12728         self.serve_one = serve_one
 12729         self.my_tid = self.sport or random.randint(10000,65500)
 12730         bind_bottom_up(UDP, TFTP, dport=self.my_tid)
 12731         
 12732     def master_filter(self, pkt):
 12733         return TFTP in pkt and (not self.ip or pkt[IP].dst == self.ip)
 12734 
 12735     @ATMT.state(initial=1)
 12736     def WAIT_RRQ(self):
 12737         self.blksize=512
 12738         self.blk=0
 12739 
 12740     @ATMT.receive_condition(WAIT_RRQ)
 12741     def receive_rrq(self, pkt):
 12742         if TFTP_RRQ in pkt:
 12743             raise self.RECEIVED_RRQ(pkt)
 12744 
 12745 
 12746     @ATMT.state()
 12747     def RECEIVED_RRQ(self, pkt):
 12748         ip = pkt[IP]
 12749         options = pkt[TFTP_Options]
 12750         self.l3 = IP(src=ip.dst, dst=ip.src)/UDP(sport=self.my_tid, dport=ip.sport)/TFTP()
 12751         self.filename = pkt[TFTP_RRQ].filename
 12752         self.blk=1
 12753         self.data = None
 12754         if self.filename in self.store:
 12755             self.data = self.store[self.filename]
 12756         elif self.dir is not None:
 12757             fn = os.path.abspath(os.path.join(self.dir, self.filename))
 12758             if fn.startswith(self.dir): # Check we're still in the server's directory
 12759                 try:
 12760                     self.data=open(fn).read()
 12761                 except IOError:
 12762                     pass
 12763         if self.data is None:
 12764             self.data = self.joker
 12765 
 12766         if options:
 12767             opt = [x for x in options.options if x.oname.upper() == "BLKSIZE"]
 12768             if opt:
 12769                 self.blksize = int(opt[0].value)
 12770                 self.debug(2,"Negotiated new blksize at %i" % self.blksize)
 12771             self.last_packet = self.l3/TFTP_OACK()/TFTP_Options(options=opt)
 12772             self.send(self.last_packet)
 12773                 
 12774 
 12775             
 12776 
 12777     @ATMT.condition(RECEIVED_RRQ)
 12778     def file_in_store(self):
 12779         if self.data is not None:
 12780             self.blknb = len(self.data)/self.blksize+1
 12781             raise self.SEND_FILE()
 12782 
 12783     @ATMT.condition(RECEIVED_RRQ)
 12784     def file_not_found(self):
 12785         if self.data is None:
 12786             raise self.WAIT_RRQ()
 12787     @ATMT.action(file_not_found)
 12788     def send_error(self):
 12789         self.send(self.l3/TFTP_ERROR(errorcode=1, errormsg=TFTP_Error_Codes[1]))
 12790 
 12791     @ATMT.state()
 12792     def SEND_FILE(self):
 12793         self.send(self.l3/TFTP_DATA(block=self.blk)/self.data[(self.blk-1)*self.blksize:self.blk*self.blksize])
 12794         
 12795     @ATMT.timeout(SEND_FILE, 3)
 12796     def timeout_waiting_ack(self):
 12797         raise self.SEND_FILE()
 12798             
 12799     @ATMT.receive_condition(SEND_FILE)
 12800     def received_ack(self, pkt):
 12801         if TFTP_ACK in pkt and pkt[TFTP_ACK].block == self.blk:
 12802             raise self.RECEIVED_ACK()
 12803     @ATMT.state()
 12804     def RECEIVED_ACK(self):
 12805         self.blk += 1
 12806 
 12807     @ATMT.condition(RECEIVED_ACK)
 12808     def no_more_data(self):
 12809         if self.blk > self.blknb:
 12810             if self.serve_one:
 12811                 raise self.END()
 12812             raise self.WAIT_RRQ()
 12813     @ATMT.condition(RECEIVED_ACK, prio=2)
 12814     def data_remaining(self):
 12815         raise self.SEND_FILE()
 12816 
 12817     @ATMT.state(final=1)
 12818     def END(self):
 12819         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12820     
 12821 
 12822         
 12823 
 12824 ########################
 12825 ## Answering machines ##
 12826 ########################
 12827 
 12828 class ReferenceAM(type):
 12829     def __new__(cls, name, bases, dct):
 12830         o = super(ReferenceAM, cls).__new__(cls, name, bases, dct)
 12831         if o.function_name:
 12832             globals()[o.function_name] = lambda o=o,*args,**kargs: o(*args,**kargs)()
 12833         return o
 12834 
 12835 
 12836 class AnsweringMachine(object):
 12837     __metaclass__ = ReferenceAM
 12838     function_name = ""
 12839     filter = None
 12840     sniff_options = { "store":0 }
 12841<