scapy.py
author Phil <phil@secdev.org>
Sat May 03 11:03:00 2008 +0200 (2008-05-03)
changeset 807 19df3f1cd92b
parent 806 87949e07281c
permissions -rwxr-xr-x
fix wifi_am.pare_opions() prototype
     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                 gr = m.groups()
  2368                 ident,oid = gr[0],gr[-1]
  2369                 ident=fixname(ident)
  2370                 oid = oid.split()
  2371                 for i in range(len(oid)):
  2372                     m = _mib_re_both.match(oid[i])
  2373                     if m:
  2374                         oid[i] = m.groups()[1]
  2375                 mib_register(ident, oid, the_mib, unresolved)
  2376 
  2377     newmib = MIBDict(_name="MIB")
  2378     for k,o in the_mib.iteritems():
  2379         newmib[k]=".".join(o)
  2380     for k,o in unresolved.iteritems():
  2381         newmib[k]=".".join(o)
  2382 
  2383     conf.mib=newmib
  2384 
  2385 
  2386 
  2387 ################
  2388 ## Generators ##
  2389 ################
  2390 
  2391 class Gen(object):
  2392     def __iter__(self):
  2393         return iter([])
  2394     
  2395 class SetGen(Gen):
  2396     def __init__(self, set, _iterpacket=1):
  2397         self._iterpacket=_iterpacket
  2398         if type(set) is list:
  2399             self.set = set
  2400         elif isinstance(set, PacketList):
  2401             self.set = list(set)
  2402         else:
  2403             self.set = [set]
  2404     def transf(self, element):
  2405         return element
  2406     def __iter__(self):
  2407         for i in self.set:
  2408             if (type(i) is tuple) and (len(i) == 2) and type(i[0]) is int and type(i[1]) is int:
  2409                 if  (i[0] <= i[1]):
  2410                     j=i[0]
  2411                     while j <= i[1]:
  2412                         yield j
  2413                         j += 1
  2414             elif isinstance(i, Gen) and (self._iterpacket or not isinstance(i,Packet)):
  2415                 for j in i:
  2416                     yield j
  2417             else:
  2418                 yield i
  2419     def __repr__(self):
  2420         return "<SetGen %s>" % self.set.__repr__()
  2421 
  2422 class Net(Gen):
  2423     """Generate a list of IPs from a network address or a name"""
  2424     name = "ip"
  2425     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])?$")
  2426     def __init__(self, net):
  2427         self.repr=net
  2428 
  2429         tmp=net.split('/')+["32"]
  2430         if not self.ipaddress.match(net):
  2431             tmp[0]=socket.gethostbyname(tmp[0])
  2432         netmask = int(tmp[1])
  2433 
  2434         def parse_digit(a,netmask):
  2435             netmask = min(8,max(netmask,0))
  2436             if a == "*":
  2437                 a = (0,256)
  2438             elif a.find("-") >= 0:
  2439                 x,y = map(int,a.split("-"))
  2440                 if x > y:
  2441                     y = x
  2442                 a = (x &  (0xffL<<netmask) , max(y, (x | (0xffL>>(8-netmask))))+1)
  2443             else:
  2444                 a = (int(a) & (0xffL<<netmask),(int(a) | (0xffL>>(8-netmask)))+1)
  2445             return a
  2446 
  2447         self.parsed = map(lambda x,y: parse_digit(x,y), tmp[0].split("."), map(lambda x,nm=netmask: x-nm, (8,16,24,32)))
  2448                                                                                                
  2449     def __iter__(self):
  2450         for d in xrange(*self.parsed[3]):
  2451             for c in xrange(*self.parsed[2]):
  2452                 for b in xrange(*self.parsed[1]):
  2453                     for a in xrange(*self.parsed[0]):
  2454                         yield "%i.%i.%i.%i" % (a,b,c,d)
  2455     def choice(self):
  2456         ip = []
  2457         for v in self.parsed:
  2458             ip.append(str(random.randint(v[0],v[1]-1)))
  2459         return ".".join(ip) 
  2460                           
  2461     def __repr__(self):
  2462         return "Net(%r)" % self.repr
  2463 
  2464 class OID(Gen):
  2465     name = "OID"
  2466     def __init__(self, oid):
  2467         self.oid = oid        
  2468         self.cmpt = []
  2469         fmt = []        
  2470         for i in oid.split("."):
  2471             if "-" in i:
  2472                 fmt.append("%i")
  2473                 self.cmpt.append(tuple(map(int, i.split("-"))))
  2474             else:
  2475                 fmt.append(i)
  2476         self.fmt = ".".join(fmt)
  2477     def __repr__(self):
  2478         return "OID(%r)" % self.oid
  2479     def __iter__(self):        
  2480         ii = [k[0] for k in self.cmpt]
  2481         while 1:
  2482             yield self.fmt % tuple(ii)
  2483             i = 0
  2484             while 1:
  2485                 if i >= len(ii):
  2486                     raise StopIteration
  2487                 if ii[i] < self.cmpt[i][1]:
  2488                     ii[i]+=1
  2489                     break
  2490                 else:
  2491                     ii[i] = self.cmpt[i][0]
  2492                 i += 1
  2493  
  2494 
  2495 #############
  2496 ## Results ##
  2497 #############
  2498 
  2499 class PacketList:
  2500     res = []
  2501     def __init__(self, res=None, name="PacketList", stats=None):
  2502         """create a packet list from a list of packets
  2503            res: the list of packets
  2504            stats: a list of classes that will appear in the stats (defaults to [TCP,UDP,ICMP])"""
  2505         if stats is None:
  2506             stats = [ TCP,UDP,ICMP ]
  2507         self.stats = stats
  2508         if res is None:
  2509             res = []
  2510         if isinstance(res, PacketList):
  2511             res = res.res
  2512         self.res = res
  2513         self.listname = name
  2514     def _elt2pkt(self, elt):
  2515         return elt
  2516     def _elt2sum(self, elt):
  2517         return elt.summary()
  2518     def _elt2show(self, elt):
  2519         return self._elt2sum(elt)
  2520     def __repr__(self):
  2521 #        stats=dict.fromkeys(self.stats,0) ## needs python >= 2.3  :(
  2522         stats = dict(map(lambda x: (x,0), self.stats))
  2523         other = 0
  2524         for r in self.res:
  2525             f = 0
  2526             for p in stats:
  2527                 if self._elt2pkt(r).haslayer(p):
  2528                     stats[p] += 1
  2529                     f = 1
  2530                     break
  2531             if not f:
  2532                 other += 1
  2533         s = ""
  2534         ct = conf.color_theme
  2535         for p in self.stats:
  2536             s += " %s%s%s" % (ct.packetlist_proto(p.name),
  2537                               ct.punct(":"),
  2538                               ct.packetlist_value(stats[p]))
  2539         s += " %s%s%s" % (ct.packetlist_proto("Other"),
  2540                           ct.punct(":"),
  2541                           ct.packetlist_value(other))
  2542         return "%s%s%s%s%s" % (ct.punct("<"),
  2543                                ct.packetlist_name(self.listname),
  2544                                ct.punct(":"),
  2545                                s,
  2546                                ct.punct(">"))
  2547     def __getattr__(self, attr):
  2548         return getattr(self.res, attr)
  2549     def __getitem__(self, item):
  2550         if isinstance(item,type) and issubclass(item,Packet):
  2551             return self.__class__(filter(lambda x: item in self._elt2pkt(x),self.res),
  2552                                   name="%s from %s"%(item.__name__,self.listname))
  2553         if type(item) is slice:
  2554             return self.__class__(self.res.__getitem__(item),
  2555                                   name = "mod %s" % self.listname)
  2556         return self.res.__getitem__(item)
  2557     def __getslice__(self, *args, **kargs):
  2558         return self.__class__(self.res.__getslice__(*args, **kargs),
  2559                               name="mod %s"%self.listname)
  2560     def __add__(self, other):
  2561         return self.__class__(self.res+other.res,
  2562                               name="%s+%s"%(self.listname,other.listname))
  2563     def summary(self, prn=None, lfilter=None):
  2564         """prints a summary of each packet
  2565 prn:     function to apply to each packet instead of lambda x:x.summary()
  2566 lfilter: truth function to apply to each packet to decide whether it will be displayed"""
  2567         for r in self.res:
  2568             if lfilter is not None:
  2569                 if not lfilter(r):
  2570                     continue
  2571             if prn is None:
  2572                 print self._elt2sum(r)
  2573             else:
  2574                 print prn(r)
  2575     def nsummary(self,prn=None, lfilter=None):
  2576         """prints a summary of each packet with the packet's number
  2577 prn:     function to apply to each packet instead of lambda x:x.summary()
  2578 lfilter: truth function to apply to each packet to decide whether it will be displayed"""
  2579         for i in range(len(self.res)):
  2580             if lfilter is not None:
  2581                 if not lfilter(self.res[i]):
  2582                     continue
  2583             print conf.color_theme.id(i,"%04i"),
  2584             if prn is None:
  2585                 print self._elt2sum(self.res[i])
  2586             else:
  2587                 print prn(self.res[i])
  2588     def display(self): # Deprecated. Use show()
  2589         """deprecated. is show()"""
  2590         self.show()
  2591     def show(self, *args, **kargs):
  2592         """Best way to display the packet list. Defaults to nsummary() method"""
  2593         return self.nsummary(*args, **kargs)
  2594     
  2595     def filter(self, func):
  2596         """Returns a packet list filtered by a truth function"""
  2597         return self.__class__(filter(func,self.res),
  2598                               name="filtered %s"%self.listname)
  2599     def make_table(self, *args, **kargs):
  2600         """Prints a table using a function that returs for each packet its head column value, head row value and displayed value
  2601         ex: p.make_table(lambda x:(x[IP].dst, x[TCP].dport, x[TCP].sprintf("%flags%")) """
  2602         return make_table(self.res, *args, **kargs)
  2603     def make_lined_table(self, *args, **kargs):
  2604         """Same as make_table, but print a table with lines"""
  2605         return make_lined_table(self.res, *args, **kargs)
  2606     def make_tex_table(self, *args, **kargs):
  2607         """Same as make_table, but print a table with LaTeX syntax"""
  2608         return make_tex_table(self.res, *args, **kargs)
  2609 
  2610     def plot(self, f, lfilter=None,**kargs):
  2611         """Applies a function to each packet to get a value that will be plotted with GnuPlot. A gnuplot object is returned
  2612         lfilter: a truth function that decides whether a packet must be ploted"""
  2613         g=Gnuplot.Gnuplot()
  2614         l = self.res
  2615         if lfilter is not None:
  2616             l = filter(lfilter, l)
  2617         l = map(f,l)
  2618         g.plot(Gnuplot.Data(l, **kargs))
  2619         return g
  2620 
  2621     def diffplot(self, f, delay=1, lfilter=None, **kargs):
  2622         """diffplot(f, delay=1, lfilter=None)
  2623         Applies a function to couples (l[i],l[i+delay])"""
  2624         g = Gnuplot.Gnuplot()
  2625         l = self.res
  2626         if lfilter is not None:
  2627             l = filter(lfilter, l)
  2628         l = map(f,l[:-delay],l[delay:])
  2629         g.plot(Gnuplot.Data(l, **kargs))
  2630         return g
  2631 
  2632     def multiplot(self, f, lfilter=None, **kargs):
  2633         """Uses a function that returns a label and a value for this label, then plots all the values label by label"""
  2634         g=Gnuplot.Gnuplot()
  2635         l = self.res
  2636         if lfilter is not None:
  2637             l = filter(lfilter, l)
  2638 
  2639         d={}
  2640         for e in l:
  2641             k,v = f(e)
  2642             if k in d:
  2643                 d[k].append(v)
  2644             else:
  2645                 d[k] = [v]
  2646         data=[]
  2647         for k in d:
  2648             data.append(Gnuplot.Data(d[k], title=k, **kargs))
  2649 
  2650         g.plot(*data)
  2651         return g
  2652         
  2653 
  2654     def rawhexdump(self):
  2655         """Prints an hexadecimal dump of each packet in the list"""
  2656         for p in self:
  2657             hexdump(self._elt2pkt(p))
  2658 
  2659     def hexraw(self, lfilter=None):
  2660         """Same as nsummary(), except that if a packet has a Raw layer, it will be hexdumped
  2661         lfilter: a truth function that decides whether a packet must be displayed"""
  2662         for i in range(len(self.res)):
  2663             p = self._elt2pkt(self.res[i])
  2664             if lfilter is not None and not lfilter(p):
  2665                 continue
  2666             print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2667                                 p.sprintf("%.time%"),
  2668                                 self._elt2sum(self.res[i]))
  2669             if p.haslayer(Raw):
  2670                 hexdump(p.getlayer(Raw).load)
  2671 
  2672     def hexdump(self, lfilter=None):
  2673         """Same as nsummary(), except that packets are also hexdumped
  2674         lfilter: a truth function that decides whether a packet must be displayed"""
  2675         for i in range(len(self.res)):
  2676             p = self._elt2pkt(self.res[i])
  2677             if lfilter is not None and not lfilter(p):
  2678                 continue
  2679             print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2680                                 p.sprintf("%.time%"),
  2681                                 self._elt2sum(self.res[i]))
  2682             hexdump(p)
  2683 
  2684     def padding(self, lfilter=None):
  2685         """Same as hexraw(), for Padding layer"""
  2686         for i in range(len(self.res)):
  2687             p = self._elt2pkt(self.res[i])
  2688             if p.haslayer(Padding):
  2689                 if lfilter is None or lfilter(p):
  2690                     print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2691                                         p.sprintf("%.time%"),
  2692                                         self._elt2sum(self.res[i]))
  2693                     hexdump(p.getlayer(Padding).load)
  2694 
  2695     def nzpadding(self, lfilter=None):
  2696         """Same as padding() but only non null padding"""
  2697         for i in range(len(self.res)):
  2698             p = self._elt2pkt(self.res[i])
  2699             if p.haslayer(Padding):
  2700                 pad = p.getlayer(Padding).load
  2701                 if pad == pad[0]*len(pad):
  2702                     continue
  2703                 if lfilter is None or lfilter(p):
  2704                     print "%s %s %s" % (conf.color_theme.id(i,"%04i"),
  2705                                         p.sprintf("%.time%"),
  2706                                         self._elt2sum(self.res[i]))
  2707                     hexdump(p.getlayer(Padding).load)
  2708         
  2709 
  2710     def conversations(self, getsrcdst=None,**kargs):
  2711         """Graphes a conversations between sources and destinations and display it
  2712         (using graphviz and imagemagick)
  2713         getsrcdst: a function that takes an element of the list and return the source and dest
  2714                    by defaults, return source and destination IP
  2715         type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
  2716         target: filename or redirect. Defaults pipe to Imagemagick's display program
  2717         prog: which graphviz program to use"""
  2718         if getsrcdst is None:
  2719             getsrcdst = lambda x:(x[IP].src, x[IP].dst)
  2720         conv = {}
  2721         for p in self.res:
  2722             p = self._elt2pkt(p)
  2723             try:
  2724                 c = getsrcdst(p)
  2725             except:
  2726                 #XXX warning()
  2727                 continue
  2728             conv[c] = conv.get(c,0)+1
  2729         gr = 'digraph "conv" {\n'
  2730         for s,d in conv:
  2731             gr += '\t "%s" -> "%s"\n' % (s,d)
  2732         gr += "}\n"        
  2733         return do_graph(gr, **kargs)
  2734 
  2735     def afterglow(self, src=None, event=None, dst=None, **kargs):
  2736         """Experimental clone attempt of http://sourceforge.net/projects/afterglow
  2737         each datum is reduced as src -> event -> dst and the data are graphed.
  2738         by default we have IP.src -> IP.dport -> IP.dst"""
  2739         if src is None:
  2740             src = lambda x: x[IP].src
  2741         if event is None:
  2742             event = lambda x: x[IP].dport
  2743         if dst is None:
  2744             dst = lambda x: x[IP].dst
  2745         sl = {}
  2746         el = {}
  2747         dl = {}
  2748         for i in self.res:
  2749             try:
  2750                 s,e,d = src(i),event(i),dst(i)
  2751                 if s in sl:
  2752                     n,l = sl[s]
  2753                     n += 1
  2754                     if e not in l:
  2755                         l.append(e)
  2756                     sl[s] = (n,l)
  2757                 else:
  2758                     sl[s] = (1,[e])
  2759                 if e in el:
  2760                     n,l = el[e]
  2761                     n+=1
  2762                     if d not in l:
  2763                         l.append(d)
  2764                     el[e] = (n,l)
  2765                 else:
  2766                     el[e] = (1,[d])
  2767                 dl[d] = dl.get(d,0)+1
  2768             except:
  2769                 continue
  2770 
  2771         import math
  2772         def normalize(n):
  2773             return 2+math.log(n)/4.0
  2774 
  2775         def minmax(x):
  2776             m,M = min(x),max(x)
  2777             if m == M:
  2778                 m = 0
  2779             if M == 0:
  2780                 M = 1
  2781             return m,M
  2782 
  2783         mins,maxs = minmax(map(lambda (x,y): x, sl.values()))
  2784         mine,maxe = minmax(map(lambda (x,y): x, el.values()))
  2785         mind,maxd = minmax(dl.values())
  2786     
  2787         gr = 'digraph "afterglow" {\n\tedge [len=2.5];\n'
  2788 
  2789         gr += "# src nodes\n"
  2790         for s in sl:
  2791             n,l = sl[s]; n = 1+float(n-mins)/(maxs-mins)
  2792             gr += '"src.%s" [label = "%s", shape=box, fillcolor="#FF0000", style=filled, fixedsize=1, height=%.2f,width=%.2f];\n' % (`s`,`s`,n,n)
  2793         gr += "# event nodes\n"
  2794         for e in el:
  2795             n,l = el[e]; n = n = 1+float(n-mine)/(maxe-mine)
  2796             gr += '"evt.%s" [label = "%s", shape=circle, fillcolor="#00FFFF", style=filled, fixedsize=1, height=%.2f, width=%.2f];\n' % (`e`,`e`,n,n)
  2797         for d in dl:
  2798             n = dl[d]; n = n = 1+float(n-mind)/(maxd-mind)
  2799             gr += '"dst.%s" [label = "%s", shape=triangle, fillcolor="#0000ff", style=filled, fixedsize=1, height=%.2f, width=%.2f];\n' % (`d`,`d`,n,n)
  2800 
  2801         gr += "###\n"
  2802         for s in sl:
  2803             n,l = sl[s]
  2804             for e in l:
  2805                 gr += ' "src.%s" -> "evt.%s";\n' % (`s`,`e`) 
  2806         for e in el:
  2807             n,l = el[e]
  2808             for d in l:
  2809                 gr += ' "evt.%s" -> "dst.%s";\n' % (`e`,`d`) 
  2810             
  2811         gr += "}"
  2812         open("/tmp/aze","w").write(gr)
  2813         return do_graph(gr, **kargs)
  2814         
  2815 
  2816         
  2817     def timeskew_graph(self, ip, **kargs):
  2818         """Tries to graph the timeskew between the timestamps and real time for a given ip"""
  2819         res = map(lambda x: self._elt2pkt(x), self.res)
  2820         b = filter(lambda x:x.haslayer(IP) and x.getlayer(IP).src == ip and x.haslayer(TCP), res)
  2821         c = []
  2822         for p in b:
  2823             opts = p.getlayer(TCP).options
  2824             for o in opts:
  2825                 if o[0] == "Timestamp":
  2826                     c.append((p.time,o[1][0]))
  2827         if not c:
  2828             warning("No timestamps found in packet list")
  2829             return
  2830         d = map(lambda (x,y): (x%2000,((x-c[0][0])-((y-c[0][1])/1000.0))),c)
  2831         g = Gnuplot.Gnuplot()
  2832         g.plot(Gnuplot.Data(d,**kargs))
  2833         return g
  2834         
  2835     def _dump_document(self, **kargs):
  2836         d = pyx.document.document()
  2837         l = len(self.res)
  2838         for i in range(len(self.res)):
  2839             elt = self.res[i]
  2840             c = self._elt2pkt(elt).canvas_dump(**kargs)
  2841             cbb = c.bbox()
  2842             c.text(cbb.left(),cbb.top()+1,r"\font\cmssfont=cmss12\cmssfont{Frame %i/%i}" % (i,l),[pyx.text.size.LARGE])
  2843             if conf.verb >= 2:
  2844                 os.write(1,".")
  2845             d.append(pyx.document.page(c, paperformat=pyx.document.paperformat.A4,
  2846                                        margin=1*pyx.unit.t_cm,
  2847                                        fittosize=1))
  2848         return d
  2849                      
  2850                  
  2851 
  2852     def psdump(self, filename = None, **kargs):
  2853         """Creates a multipage poscript file with a psdump of every packet
  2854         filename: name of the file to write to. If empty, a temporary file is used and
  2855                   conf.prog.psreader is called"""
  2856         d = self._dump_document(**kargs)
  2857         if filename is None:
  2858             filename = "/tmp/scapy.psd.%i" % os.getpid()
  2859             d.writePSfile(filename)
  2860             os.system("%s %s.ps &" % (conf.prog.psreader,filename))
  2861         else:
  2862             d.writePSfile(filename)
  2863         print
  2864         
  2865     def pdfdump(self, filename = None, **kargs):
  2866         """Creates a PDF file with a psdump of every packet
  2867         filename: name of the file to write to. If empty, a temporary file is used and
  2868                   conf.prog.pdfreader is called"""
  2869         d = self._dump_document(**kargs)
  2870         if filename is None:
  2871             filename = "/tmp/scapy.psd.%i" % os.getpid()
  2872             d.writePDFfile(filename)
  2873             os.system("%s %s.pdf &" % (conf.prog.pdfreader,filename))
  2874         else:
  2875             d.writePDFfile(filename)
  2876         print
  2877 
  2878     def sr(self,multi=0):
  2879         """sr([multi=1]) -> (SndRcvList, PacketList)
  2880         Matches packets in the list and return ( (matched couples), (unmatched packets) )"""
  2881         remain = self.res[:]
  2882         sr = []
  2883         i = 0
  2884         while i < len(remain):
  2885             s = remain[i]
  2886             j = i
  2887             while j < len(remain)-1:
  2888                 j += 1
  2889                 r = remain[j]
  2890                 if r.answers(s):
  2891                     sr.append((s,r))
  2892                     if multi:
  2893                         remain[i]._answered=1
  2894                         remain[j]._answered=2
  2895                         continue
  2896                     del(remain[j])
  2897                     del(remain[i])
  2898                     i -= 1
  2899                     break
  2900             i += 1
  2901         if multi:
  2902             remain = filter(lambda x:not hasattr(x,"_answered"), remain)
  2903         return SndRcvList(sr),PacketList(remain)
  2904         
  2905 
  2906 
  2907         
  2908 
  2909 
  2910 class Dot11PacketList(PacketList):
  2911     def __init__(self, res=None, name="Dot11List", stats=None):
  2912         if stats is None:
  2913             stats = [Dot11WEP, Dot11Beacon, UDP, ICMP, TCP]
  2914 
  2915         PacketList.__init__(self, res, name, stats)
  2916     def toEthernet(self):
  2917         data = map(lambda x:x.getlayer(Dot11), filter(lambda x : x.haslayer(Dot11) and x.type == 2, self.res))
  2918         r2 = []
  2919         for p in data:
  2920             q = p.copy()
  2921             q.unwep()
  2922             r2.append(Ether()/q.payload.payload.payload) #Dot11/LLC/SNAP/IP
  2923         return PacketList(r2,name="Ether from %s"%self.listname)
  2924         
  2925         
  2926 
  2927 class SndRcvList(PacketList):
  2928     def __init__(self, res=None, name="Results", stats=None):
  2929         PacketList.__init__(self, res, name, stats)
  2930     def _elt2pkt(self, elt):
  2931         return elt[1]
  2932     def _elt2sum(self, elt):
  2933         return "%s ==> %s" % (elt[0].summary(),elt[1].summary()) 
  2934 
  2935 
  2936 class ARPingResult(SndRcvList):
  2937     def __init__(self, res=None, name="ARPing", stats=None):
  2938         PacketList.__init__(self, res, name, stats)
  2939 
  2940     def show(self):
  2941         for s,r in self.res:
  2942             print r.sprintf("%Ether.src% %ARP.psrc%")
  2943 
  2944 
  2945 class AS_resolver:
  2946     server = None
  2947     options = "-k" 
  2948     def __init__(self, server=None, port=43, options=None):
  2949         if server is not None:
  2950             self.server = server
  2951         self.port = port
  2952         if options is not None:
  2953             self.options = options
  2954         
  2955     def _start(self):
  2956         self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  2957         self.s.connect((self.server,self.port))
  2958         if self.options:
  2959             self.s.send(self.options+"\n")
  2960             self.s.recv(8192)
  2961     def _stop(self):
  2962         self.s.close()
  2963         
  2964     def _parse_whois(self, txt):
  2965         asn,desc = None,""
  2966         for l in txt.splitlines():
  2967             if not asn and l.startswith("origin:"):
  2968                 asn = l[7:].strip()
  2969             if l.startswith("descr:"):
  2970                 if desc:
  2971                     desc += r"\n"
  2972                 desc += l[6:].strip()
  2973             if asn is not None and desc:
  2974                 break
  2975         return asn,desc.strip()
  2976 
  2977     def _resolve_one(self, ip):
  2978         self.s.send("%s\n" % ip)
  2979         x = ""
  2980         while not ("%" in x  or "source" in x):
  2981             x += self.s.recv(8192)
  2982         asn, desc = self._parse_whois(x)
  2983         return ip,asn,desc
  2984     def resolve(self, *ips):
  2985         self._start()
  2986         ret = []
  2987         for ip in ips:
  2988             ip,asn,desc = self._resolve_one(ip)
  2989             if asn is not None:
  2990                 ret.append((ip,asn,desc))
  2991         self._stop()
  2992         return ret
  2993 
  2994 class AS_resolver_riswhois(AS_resolver):
  2995     server = "riswhois.ripe.net"
  2996     options = "-k -M -1"
  2997 
  2998 
  2999 class AS_resolver_radb(AS_resolver):
  3000     server = "whois.ra.net"
  3001     options = "-k -M"
  3002     
  3003 
  3004 class AS_resolver_cymru(AS_resolver):
  3005     server = "whois.cymru.com"
  3006     options = None
  3007     def resolve(self, *ips):
  3008         ASNlist = []
  3009         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  3010         s.connect((self.server,self.port))
  3011         s.send("begin\r\n"+"\r\n".join(ips)+"\r\nend\r\n")
  3012         r = ""
  3013         while 1:
  3014             l = s.recv(8192)
  3015             if l == "":
  3016                 break
  3017             r += l
  3018         s.close()
  3019         for l in r.splitlines()[1:]:
  3020             if "|" not in l:
  3021                 continue
  3022             asn,ip,desc = map(str.strip, l.split("|"))
  3023             if asn == "NA":
  3024                 continue
  3025             asn = int(asn)
  3026             ASNlist.append((ip,asn,desc))
  3027         return ASNlist
  3028 
  3029 class AS_resolver_multi(AS_resolver):
  3030     resolvers_list = ( AS_resolver_cymru(),AS_resolver_riswhois(),AS_resolver_radb() )
  3031     def __init__(self, *reslist):
  3032         if reslist:
  3033             self.resolvers_list = reslist
  3034     def resolve(self, *ips):
  3035         todo = ips
  3036         ret = []
  3037         for ASres in self.resolvers_list:
  3038             res = ASres.resolve(*todo)
  3039             resolved = [ ip for ip,asn,desc in res ]
  3040             todo = [ ip for ip in todo if ip not in resolved ]
  3041             ret += res
  3042         return ret
  3043     
  3044     
  3045 
  3046 class TracerouteResult(SndRcvList):
  3047     def __init__(self, res=None, name="Traceroute", stats=None):
  3048         PacketList.__init__(self, res, name, stats)
  3049         self.graphdef = None
  3050         self.graphASres = 0
  3051         self.padding = 0
  3052         self.hloc = None
  3053         self.nloc = None
  3054 
  3055     def show(self):
  3056         return self.make_table(lambda (s,r): (s.sprintf("%IP.dst%:{TCP:tcp%ir,TCP.dport%}{UDP:udp%ir,UDP.dport%}{ICMP:ICMP}"),
  3057                                               s.ttl,
  3058                                               r.sprintf("%-15s,IP.src% {TCP:%TCP.flags%}{ICMP:%ir,ICMP.type%}")))
  3059 
  3060 
  3061     def get_trace(self):
  3062         trace = {}
  3063         for s,r in self.res:
  3064             if IP not in s:
  3065                 continue
  3066             d = s[IP].dst
  3067             if d not in trace:
  3068                 trace[d] = {}
  3069             trace[d][s[IP].ttl] = r[IP].src, ICMP not in r
  3070         for k in trace.values():
  3071             m = filter(lambda x:k[x][1], k.keys())
  3072             if not m:
  3073                 continue
  3074             m = min(m)
  3075             for l in k.keys():
  3076                 if l > m:
  3077                     del(k[l])
  3078         return trace
  3079 
  3080     def trace3D(self):
  3081         """Give a 3D representation of the traceroute.
  3082         right button: rotate the scene
  3083         middle button: zoom
  3084         left button: move the scene
  3085         left button on a ball: toggle IP displaying
  3086         ctrl-left button on a ball: scan ports 21,22,23,25,80 and 443 and display the result"""
  3087         trace = self.get_trace()
  3088         import visual
  3089 
  3090         class IPsphere(visual.sphere):
  3091             def __init__(self, ip, **kargs):
  3092                 visual.sphere.__init__(self, **kargs)
  3093                 self.ip=ip
  3094                 self.label=None
  3095                 self.setlabel(self.ip)
  3096             def setlabel(self, txt,visible=None):
  3097                 if self.label is not None:
  3098                     if visible is None:
  3099                         visible = self.label.visible
  3100                     self.label.visible = 0
  3101                 elif visible is None:
  3102                     visible=0
  3103                 self.label=visual.label(text=txt, pos=self.pos, space=self.radius, xoffset=10, yoffset=20, visible=visible)
  3104             def action(self):
  3105                 self.label.visible ^= 1
  3106 
  3107         visual.scene = visual.display()
  3108         visual.scene.exit_on_close(0)
  3109         start = visual.box()
  3110         rings={}
  3111         tr3d = {}
  3112         for i in trace:
  3113             tr = trace[i]
  3114             tr3d[i] = []
  3115             ttl = tr.keys()
  3116             for t in range(1,max(ttl)+1):
  3117                 if t not in rings:
  3118                     rings[t] = []
  3119                 if t in tr:
  3120                     if tr[t] not in rings[t]:
  3121                         rings[t].append(tr[t])
  3122                     tr3d[i].append(rings[t].index(tr[t]))
  3123                 else:
  3124                     rings[t].append(("unk",-1))
  3125                     tr3d[i].append(len(rings[t])-1)
  3126         for t in rings:
  3127             r = rings[t]
  3128             l = len(r)
  3129             for i in range(l):
  3130                 if r[i][1] == -1:
  3131                     col = (0.75,0.75,0.75)
  3132                 elif r[i][1]:
  3133                     col = visual.color.green
  3134                 else:
  3135                     col = visual.color.blue
  3136                 
  3137                 s = IPsphere(pos=((l-1)*visual.cos(2*i*visual.pi/l),(l-1)*visual.sin(2*i*visual.pi/l),2*t),
  3138                              ip = r[i][0],
  3139                              color = col)
  3140                 for trlst in tr3d.values():
  3141                     if t <= len(trlst):
  3142                         if trlst[t-1] == i:
  3143                             trlst[t-1] = s
  3144         forecol = colgen(0.625, 0.4375, 0.25, 0.125)
  3145         for trlst in tr3d.values():
  3146             col = forecol.next()
  3147             start = (0,0,0)
  3148             for ip in trlst:
  3149                 visual.cylinder(pos=start,axis=ip.pos-start,color=col,radius=0.2)
  3150                 start = ip.pos
  3151         
  3152         movcenter=None
  3153         while 1:
  3154             if visual.scene.kb.keys:
  3155                 k = visual.scene.kb.getkey()
  3156                 if k == "esc":
  3157                     break
  3158             if visual.scene.mouse.events:
  3159                 ev = visual.scene.mouse.getevent()
  3160                 if ev.press == "left":
  3161                     o = ev.pick
  3162                     if o:
  3163                         if ev.ctrl:
  3164                             if o.ip == "unk":
  3165                                 continue
  3166                             savcolor = o.color
  3167                             o.color = (1,0,0)
  3168                             a,b=sr(IP(dst=o.ip)/TCP(dport=[21,22,23,25,80,443]),timeout=2)
  3169                             o.color = savcolor
  3170                             if len(a) == 0:
  3171                                 txt = "%s:\nno results" % o.ip
  3172                             else:
  3173                                 txt = "%s:\n" % o.ip
  3174                                 for s,r in a:
  3175                                     txt += r.sprintf("{TCP:%IP.src%:%TCP.sport% %TCP.flags%}{TCPerror:%IPerror.dst%:%TCPerror.dport% %IP.src% %ir,ICMP.type%}\n")
  3176                             o.setlabel(txt, visible=1)
  3177                         else:
  3178                             if hasattr(o, "action"):
  3179                                 o.action()
  3180                 elif ev.drag == "left":
  3181                     movcenter = ev.pos
  3182                 elif ev.drop == "left":
  3183                     movcenter = None
  3184             if movcenter:
  3185                 visual.scene.center -= visual.scene.mouse.pos-movcenter
  3186                 movcenter = visual.scene.mouse.pos
  3187                 
  3188                 
  3189     def world_trace(self):
  3190         ips = {}
  3191         rt = {}
  3192         ports_done = {}
  3193         for s,r in self.res:
  3194             ips[r.src] = None
  3195             if s.haslayer(TCP) or s.haslayer(UDP):
  3196                 trace_id = (s.src,s.dst,s.proto,s.dport)
  3197             elif s.haslayer(ICMP):
  3198                 trace_id = (s.src,s.dst,s.proto,s.type)
  3199             else:
  3200                 trace_id = (s.src,s.dst,s.proto,0)
  3201             trace = rt.get(trace_id,{})
  3202             if not r.haslayer(ICMP) or r.type != 11:
  3203                 if ports_done.has_key(trace_id):
  3204                     continue
  3205                 ports_done[trace_id] = None
  3206             trace[s.ttl] = r.src
  3207             rt[trace_id] = trace
  3208 
  3209         trt = {}
  3210         for trace_id in rt:
  3211             trace = rt[trace_id]
  3212             loctrace = []
  3213             for i in range(max(trace.keys())):
  3214                 ip = trace.get(i,None)
  3215                 if ip is None:
  3216                     continue
  3217                 loc = locate_ip(ip)
  3218                 if loc is None:
  3219                     continue
  3220 #                loctrace.append((ip,loc)) # no labels yet
  3221                 loctrace.append(loc)
  3222             if loctrace:
  3223                 trt[trace_id] = loctrace
  3224 
  3225         tr = map(lambda x: Gnuplot.Data(x,with="lines"), trt.values())
  3226         g = Gnuplot.Gnuplot()
  3227         world = Gnuplot.File(conf.gnuplot_world,with="lines")
  3228         g.plot(world,*tr)
  3229         return g
  3230 
  3231     def make_graph(self,ASres=None,padding=0):
  3232         if ASres is None:
  3233             ASres = conf.AS_resolver
  3234         self.graphASres = ASres
  3235         self.graphpadding = padding
  3236         ips = {}
  3237         rt = {}
  3238         ports = {}
  3239         ports_done = {}
  3240         for s,r in self.res:
  3241             r = r[IP] or r[IPv6] or r
  3242             s = s[IP] or s[IPv6] or s
  3243             ips[r.src] = None
  3244             if TCP in s:
  3245                 trace_id = (s.src,s.dst,6,s.dport)
  3246             elif UDP in s:
  3247                 trace_id = (s.src,s.dst,17,s.dport)
  3248             elif ICMP in s:
  3249                 trace_id = (s.src,s.dst,1,s.type)
  3250             else:
  3251                 trace_id = (s.src,s.dst,s.proto,0)
  3252             trace = rt.get(trace_id,{})
  3253             ttl = IPv6 in s and s.hlim or s.ttl
  3254             if not (ICMP in r and r[ICMP].type == 11) and not (IPv6 in r and ICMPv6TimeExceeded in r):
  3255                 if trace_id in ports_done:
  3256                     continue
  3257                 ports_done[trace_id] = None
  3258                 p = ports.get(r.src,[])
  3259                 if TCP in r:
  3260                     p.append(r.sprintf("<T%ir,TCP.sport%> %TCP.sport% %TCP.flags%"))
  3261                     trace[ttl] = r.sprintf('"%r,src%":T%ir,TCP.sport%')
  3262                 elif UDP in r:
  3263                     p.append(r.sprintf("<U%ir,UDP.sport%> %UDP.sport%"))
  3264                     trace[ttl] = r.sprintf('"%r,src%":U%ir,UDP.sport%')
  3265                 elif ICMP in r:
  3266                     p.append(r.sprintf("<I%ir,ICMP.type%> ICMP %ICMP.type%"))
  3267                     trace[ttl] = r.sprintf('"%r,src%":I%ir,ICMP.type%')
  3268                 else:
  3269                     p.append(r.sprintf("{IP:<P%ir,proto%> IP %proto%}{IPv6:<P%ir,nh%> IPv6 %nh%}"))
  3270                     trace[ttl] = r.sprintf('"%r,src%":{IP:P%ir,proto%}{IPv6:P%ir,nh%}')
  3271                 ports[r.src] = p
  3272             else:
  3273                 trace[ttl] = r.sprintf('"%r,src%"')
  3274             rt[trace_id] = trace
  3275     
  3276         # Fill holes with unk%i nodes
  3277         unknown_label = incremental_label("unk%i")
  3278         blackholes = []
  3279         bhip = {}
  3280         for rtk in rt:
  3281             trace = rt[rtk]
  3282             k = trace.keys()
  3283             for n in range(min(k), max(k)):
  3284                 if not trace.has_key(n):
  3285                     trace[n] = unknown_label.next()
  3286             if not ports_done.has_key(rtk):
  3287                 if rtk[2] == 1: #ICMP
  3288                     bh = "%s %i/icmp" % (rtk[1],rtk[3])
  3289                 elif rtk[2] == 6: #TCP
  3290                     bh = "%s %i/tcp" % (rtk[1],rtk[3])
  3291                 elif rtk[2] == 17: #UDP                    
  3292                     bh = '%s %i/udp' % (rtk[1],rtk[3])
  3293                 else:
  3294                     bh = '%s %i/proto' % (rtk[1],rtk[2]) 
  3295                 ips[bh] = None
  3296                 bhip[rtk[1]] = bh
  3297                 bh = '"%s"' % bh
  3298                 trace[max(k)+1] = bh
  3299                 blackholes.append(bh)
  3300     
  3301         # Find AS numbers
  3302         ASN_query_list = dict.fromkeys(map(lambda x:x.rsplit(" ",1)[0],ips)).keys()
  3303         if ASres is None:            
  3304             ASNlist = []
  3305         else:
  3306             ASNlist = ASres.resolve(*ASN_query_list)            
  3307     
  3308         ASNs = {}
  3309         ASDs = {}
  3310         for ip,asn,desc, in ASNlist:
  3311             if asn is None:
  3312                 continue
  3313             iplist = ASNs.get(asn,[])
  3314             if ip in bhip:
  3315                 if ip in ports:
  3316                     iplist.append(ip)
  3317                 iplist.append(bhip[ip])
  3318             else:
  3319                 iplist.append(ip)
  3320             ASNs[asn] = iplist
  3321             ASDs[asn] = desc
  3322     
  3323     
  3324         backcolorlist=colgen("60","86","ba","ff")
  3325         forecolorlist=colgen("a0","70","40","20")
  3326     
  3327         s = "digraph trace {\n"
  3328     
  3329         s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n"
  3330     
  3331         s += "\n#ASN clustering\n"
  3332         for asn in ASNs:
  3333             s += '\tsubgraph cluster_%s {\n' % asn
  3334             col = backcolorlist.next()
  3335             s += '\t\tcolor="#%s%s%s";' % col
  3336             s += '\t\tnode [fillcolor="#%s%s%s",style=filled];' % col
  3337             s += '\t\tfontsize = 10;'
  3338             s += '\t\tlabel = "%s\\n[%s]"\n' % (asn,ASDs[asn])
  3339             for ip in ASNs[asn]:
  3340     
  3341                 s += '\t\t"%s";\n'%ip
  3342             s += "\t}\n"
  3343     
  3344     
  3345     
  3346     
  3347         s += "#endpoints\n"
  3348         for p in ports:
  3349             s += '\t"%s" [shape=record,color=black,fillcolor=green,style=filled,label="%s|%s"];\n' % (p,p,"|".join(ports[p]))
  3350     
  3351         s += "\n#Blackholes\n"
  3352         for bh in blackholes:
  3353             s += '\t%s [shape=octagon,color=black,fillcolor=red,style=filled];\n' % bh
  3354 
  3355         if padding:
  3356             s += "\n#Padding\n"
  3357             pad={}
  3358             for snd,rcv in self.res:
  3359                 if rcv.src not in ports and rcv.haslayer(Padding):
  3360                     p = rcv.getlayer(Padding).load
  3361                     if p != "\x00"*len(p):
  3362                         pad[rcv.src]=None
  3363             for rcv in pad:
  3364                 s += '\t"%s" [shape=triangle,color=black,fillcolor=red,style=filled];\n' % rcv
  3365     
  3366     
  3367             
  3368         s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n"
  3369     
  3370     
  3371         for rtk in rt:
  3372             s += "#---[%s\n" % `rtk`
  3373             s += '\t\tedge [color="#%s%s%s"];\n' % forecolorlist.next()
  3374             trace = rt[rtk]
  3375             k = trace.keys()
  3376             for n in range(min(k), max(k)):
  3377                 s += '\t%s ->\n' % trace[n]
  3378             s += '\t%s;\n' % trace[max(k)]
  3379     
  3380         s += "}\n";
  3381         self.graphdef = s
  3382     
  3383     def graph(self, ASres=None, padding=0, **kargs):
  3384         """x.graph(ASres=conf.AS_resolver, other args):
  3385         ASres=None          : no AS resolver => no clustering
  3386         ASres=AS_resolver() : default whois AS resolver (riswhois.ripe.net)
  3387         ASres=AS_resolver_cymru(): use whois.cymru.com whois database
  3388         ASres=AS_resolver(server="whois.ra.net")
  3389         type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option
  3390         target: filename or redirect. Defaults pipe to Imagemagick's display program
  3391         prog: which graphviz program to use"""
  3392         if ASres is None:
  3393             ASres = conf.AS_resolver
  3394         if (self.graphdef is None or
  3395             self.graphASres != ASres or
  3396             self.graphpadding != padding):
  3397             self.make_graph(ASres,padding)
  3398 
  3399         return do_graph(self.graphdef, **kargs)
  3400 
  3401 
  3402         
  3403     
  3404 ############
  3405 ## Fields ##
  3406 ############
  3407 
  3408 class Field:
  3409     """For more informations on how this work, please refer to
  3410        http://www.secdev.org/projects/scapy/files/scapydoc.pdf
  3411        chapter ``Adding a New Field''"""
  3412     islist=0
  3413     holds_packets=0
  3414     def __init__(self, name, default, fmt="H"):
  3415         self.name = name
  3416         if fmt[0] in "@=<>!":
  3417             self.fmt = fmt
  3418         else:
  3419             self.fmt = "!"+fmt
  3420         self.default = self.any2i(None,default)
  3421         self.sz = struct.calcsize(self.fmt)
  3422         self.owners = []
  3423 
  3424     def register_owner(self, cls):
  3425         self.owners.append(cls)
  3426 
  3427     def i2len(self, pkt, x):
  3428         """Convert internal value to a length usable by a FieldLenField"""
  3429         return self.sz
  3430     def i2count(self, pkt, x):
  3431         """Convert internal value to a number of elements usable by a FieldLenField.
  3432         Always 1 except for list fields"""
  3433         return 1
  3434     def h2i(self, pkt, x):
  3435         """Convert human value to internal value"""
  3436         return x
  3437     def i2h(self, pkt, x):
  3438         """Convert internal value to human value"""
  3439         return x
  3440     def m2i(self, pkt, x):
  3441         """Convert machine value to internal value"""
  3442         return x
  3443     def i2m(self, pkt, x):
  3444         """Convert internal value to machine value"""
  3445         if x is None:
  3446             x = 0
  3447         return x
  3448     def any2i(self, pkt, x):
  3449         """Try to understand the most input values possible and make an internal value from them"""
  3450         return self.h2i(pkt, x)
  3451     def i2repr(self, pkt, x):
  3452         """Convert internal value to a nice representation"""
  3453         if x is None:
  3454             x = 0
  3455         return repr(self.i2h(pkt,x))
  3456     def addfield(self, pkt, s, val):
  3457         """Add an internal value  to a string"""
  3458         return s+struct.pack(self.fmt, self.i2m(pkt,val))
  3459     def getfield(self, pkt, s):
  3460         """Extract an internal value from a string"""
  3461         return  s[self.sz:], self.m2i(pkt, struct.unpack(self.fmt, s[:self.sz])[0])
  3462     def do_copy(self, x):
  3463         if hasattr(x, "copy"):
  3464             return x.copy()
  3465         if type(x) is list:
  3466             x = x[:]
  3467             for i in xrange(len(x)):
  3468                 if isinstance(x[i], Packet):
  3469                     x[i] = x[i].copy()
  3470         return x
  3471     def __repr__(self):
  3472         return "<Field (%s).%s>" % (",".join(x.__name__ for x in self.owners),self.name)
  3473     def copy(self):
  3474         return copy.deepcopy(self)
  3475     def randval(self):
  3476         """Return a volatile object whose value is both random and suitable for this field"""
  3477         fmtt = self.fmt[-1]
  3478         if fmtt in "BHIQ":
  3479             return {"B":RandByte,"H":RandShort,"I":RandInt, "Q":RandLong}[fmtt]()
  3480         elif fmtt == "s":
  3481             if self.fmt[0] in "0123456789":
  3482                 l = int(self.fmt[:-1])
  3483             else:
  3484                 l = int(self.fmt[1:-1])
  3485             return RandBin(l)
  3486         else:
  3487             warning("no random class for [%s] (fmt=%s)." % (self.name, self.fmt))
  3488             
  3489 
  3490 
  3491 
  3492 class Emph:
  3493     fld = ""
  3494     def __init__(self, fld):
  3495         self.fld = fld
  3496     def __getattr__(self, attr):
  3497         return getattr(self.fld,attr)
  3498     def __hash__(self):
  3499         return hash(self.fld)
  3500     def __eq__(self, other):
  3501         return self.fld == other
  3502     
  3503 
  3504 class ActionField:
  3505     _fld = None
  3506     def __init__(self, fld, action_method, **kargs):
  3507         self._fld = fld
  3508         self._action_method = action_method
  3509         self._privdata = kargs
  3510     def any2i(self, pkt, val):
  3511         getattr(pkt, self._action_method)(val, self._fld, **self._privdata)
  3512         return getattr(self._fld, "any2i")(pkt, val)
  3513     def __getattr__(self, attr):
  3514         return getattr(self._fld,attr)
  3515 
  3516 
  3517 class ConditionalField:
  3518     fld = None
  3519     def __init__(self, fld, cond):
  3520         self.fld = fld
  3521         self.cond = cond
  3522     def _evalcond(self,pkt):
  3523         return self.cond(pkt)
  3524         
  3525     def getfield(self, pkt, s):
  3526         if self._evalcond(pkt):
  3527             return self.fld.getfield(pkt,s)
  3528         else:
  3529             return s,None
  3530         
  3531     def addfield(self, pkt, s, val):
  3532         if self._evalcond(pkt):
  3533             return self.fld.addfield(pkt,s,val)
  3534         else:
  3535             return s
  3536     def __getattr__(self, attr):
  3537         return getattr(self.fld,attr)
  3538         
  3539 
  3540 class PadField:
  3541     """Add bytes after the proxified field so that it ends at the specified
  3542        alignment from its begining"""
  3543     _fld = None
  3544     def __init__(self, fld, align, padwith=None):
  3545         self._fld = fld
  3546         self._align = align
  3547         self._padwith = padwith or ""
  3548 
  3549     def addfield(self, pkt, s, val):
  3550         sval = self._fld.addfield(pkt, "", val)
  3551         return s+sval+struct.pack("%is" % (-len(sval)%self._align), self._padwith)
  3552     
  3553     def __getattr__(self, attr):
  3554         return getattr(self._fld,attr)
  3555         
  3556 
  3557 class MACField(Field):
  3558     def __init__(self, name, default):
  3559         Field.__init__(self, name, default, "6s")
  3560     def i2m(self, pkt, x):
  3561         if x is None:
  3562             return "\0\0\0\0\0\0"
  3563         return mac2str(x)
  3564     def m2i(self, pkt, x):
  3565         return str2mac(x)
  3566     def any2i(self, pkt, x):
  3567         if type(x) is str and len(x) is 6:
  3568             x = self.m2i(pkt, x)
  3569         return x
  3570     def i2repr(self, pkt, x):
  3571         x = self.i2h(pkt, x)
  3572         if self in conf.resolve:
  3573             x = conf.manufdb._resolve_MAC(x)
  3574         return x
  3575     def randval(self):
  3576         return RandMAC()
  3577 
  3578 class DestMACField(MACField):
  3579     def __init__(self, name):
  3580         MACField.__init__(self, name, None)
  3581     def i2h(self, pkt, x):
  3582         if x is None:
  3583             dstip = None
  3584             if isinstance(pkt.payload, IPv6):
  3585                 dstip = pkt.payload.dst            
  3586             elif isinstance(pkt.payload, IP):
  3587                 dstip = pkt.payload.dst
  3588             elif isinstance(pkt.payload, ARP):
  3589                 dstip = pkt.payload.pdst
  3590             if isinstance(dstip, Gen):
  3591                 dstip = dstip.__iter__().next()
  3592             if dstip is not None:
  3593                 if isinstance(pkt.payload, IPv6):
  3594                     x = getmacbyip6(dstip, chainCC=1)
  3595                 else:    
  3596                     x = getmacbyip(dstip, chainCC=1)
  3597             if x is None:
  3598                 x = "ff:ff:ff:ff:ff:ff"
  3599                 warning("Mac address to reach %s not found\n"%dstip)
  3600         return MACField.i2h(self, pkt, x)
  3601     def i2m(self, pkt, x):
  3602         return MACField.i2m(self, pkt, self.i2h(pkt, x))
  3603         
  3604 class SourceMACField(MACField):
  3605     def __init__(self, name):
  3606         MACField.__init__(self, name, None)
  3607     def i2h(self, pkt, x):
  3608         if x is None:
  3609             dstip = None
  3610             if isinstance(pkt.payload, IPv6):
  3611                 dstip = pkt.payload.dst
  3612             elif isinstance(pkt.payload, IP):
  3613                 dstip = pkt.payload.dst
  3614             elif isinstance(pkt.payload, ARP):
  3615                 dstip = pkt.payload.pdst
  3616             if isinstance(dstip, Gen):
  3617                 dstip = dstip.__iter__().next()
  3618             if dstip is not None:
  3619                 if isinstance(pkt.payload, IPv6):
  3620                     iff,a,nh = conf.route6.route(dstip)
  3621                 else:
  3622                     iff,a,gw = conf.route.route(dstip)
  3623                 try:
  3624                     x = get_if_hwaddr(iff)
  3625                 except:
  3626                     pass
  3627                 if x is None:
  3628                     x = "00:00:00:00:00:00"
  3629         return MACField.i2h(self, pkt, x)
  3630     def i2m(self, pkt, x):
  3631         return MACField.i2m(self, pkt, self.i2h(pkt, x))
  3632         
  3633 class ARPSourceMACField(MACField):
  3634     def __init__(self, name):
  3635         MACField.__init__(self, name, None)
  3636     def i2h(self, pkt, x):
  3637         if x is None:
  3638             dstip = pkt.pdst
  3639             if isinstance(dstip, Gen):
  3640                 dstip = dstip.__iter__().next()
  3641             if dstip is not None:
  3642                 iff,a,gw = conf.route.route(dstip)
  3643                 try:
  3644                     x = get_if_hwaddr(iff)
  3645                 except:
  3646                     pass
  3647                 if x is None:
  3648                     x = "00:00:00:00:00:00"
  3649         return MACField.i2h(self, pkt, x)
  3650     def i2m(self, pkt, x):
  3651         return MACField.i2m(self, pkt, self.i2h(pkt, x))
  3652 
  3653 class Dot11AddrMACField(MACField):
  3654     def is_applicable(self, pkt):
  3655         return 1
  3656     def addfield(self, pkt, s, val):
  3657         if self.is_applicable(pkt):
  3658             return MACField.addfield(self, pkt, s, val)
  3659         else:
  3660             return s        
  3661     def getfield(self, pkt, s):
  3662         if self.is_applicable(pkt):
  3663             return MACField.getfield(self, pkt, s)
  3664         else:
  3665             return s,None
  3666 
  3667 class Dot11Addr2MACField(Dot11AddrMACField):
  3668     def is_applicable(self, pkt):
  3669         if pkt.type == 1:
  3670             return pkt.subtype in [ 0xb, 0xa, 0xe, 0xf] # RTS, PS-Poll, CF-End, CF-End+CF-Ack
  3671         return 1
  3672 
  3673 class Dot11Addr3MACField(Dot11AddrMACField):
  3674     def is_applicable(self, pkt):
  3675         if pkt.type in [0,2]:
  3676             return 1
  3677         return 0
  3678 
  3679 class Dot11Addr4MACField(Dot11AddrMACField):
  3680     def is_applicable(self, pkt):
  3681         if pkt.type == 2:
  3682             if pkt.FCfield & 0x3 == 0x3: # To-DS and From-DS are set
  3683                 return 1
  3684         return 0
  3685     
  3686 class IPField(Field):
  3687     def __init__(self, name, default):
  3688         Field.__init__(self, name, default, "4s")
  3689     def h2i(self, pkt, x):
  3690         if type(x) is str:
  3691             try:
  3692                 inet_aton(x)
  3693             except socket.error:
  3694                 x = Net(x)
  3695         elif type(x) is list:
  3696             x = [self.h2i(pkt, n) for n in x] 
  3697         return x
  3698     def resolve(self, x):
  3699         if self in conf.resolve:
  3700             try:
  3701                 ret = socket.gethostbyaddr(x)[0]
  3702             except:
  3703                 pass
  3704             else:
  3705                 if ret:
  3706                     return ret
  3707         return x
  3708     def i2m(self, pkt, x):
  3709         return inet_aton(x)
  3710     def m2i(self, pkt, x):
  3711         return inet_ntoa(x)
  3712     def any2i(self, pkt, x):
  3713         return self.h2i(pkt,x)
  3714     def i2repr(self, pkt, x):
  3715         return self.resolve(self.i2h(pkt, x))
  3716     def randval(self):
  3717         return RandIP()
  3718 
  3719 class SourceIPField(IPField):
  3720     def __init__(self, name, dstname):
  3721         IPField.__init__(self, name, None)
  3722         self.dstname = dstname
  3723     def i2m(self, pkt, x):
  3724         if x is None:
  3725             iff,x,gw = conf.route.route(getattr(pkt,self.dstname))
  3726         return IPField.i2m(self, pkt, x)
  3727     def i2h(self, pkt, x):
  3728         if x is None:
  3729             dst=getattr(pkt,self.dstname)
  3730             if isinstance(dst,Gen):
  3731                 r = map(conf.route.route, dst)
  3732                 r.sort()
  3733                 if r[0] == r[-1]:
  3734                     x=r[0][1]
  3735                 else:
  3736                     warning("More than one possible route for %s"%repr(dst))
  3737                     return None
  3738             else:
  3739                 iff,x,gw = conf.route.route(dst)
  3740         return IPField.i2h(self, pkt, x)
  3741 
  3742     
  3743 
  3744 
  3745 class ByteField(Field):
  3746     def __init__(self, name, default):
  3747         Field.__init__(self, name, default, "B")
  3748         
  3749 class XByteField(ByteField):
  3750     def i2repr(self, pkt, x):
  3751         if x is None:
  3752             x = 0
  3753         return lhex(self.i2h(pkt, x))
  3754 
  3755 class X3BytesField(XByteField):
  3756     def __init__(self, name, default):
  3757         Field.__init__(self, name, default, "!I")
  3758     def addfield(self, pkt, s, val):
  3759         return s+struct.pack(self.fmt, self.i2m(pkt,val))[1:4]
  3760     def getfield(self, pkt, s):
  3761         return  s[3:], self.m2i(pkt, struct.unpack(self.fmt, "\x00"+s[:3])[0])
  3762 
  3763 
  3764 class ShortField(Field):
  3765     def __init__(self, name, default):
  3766         Field.__init__(self, name, default, "H")
  3767 
  3768 class LEShortField(Field):
  3769     def __init__(self, name, default):
  3770         Field.__init__(self, name, default, "<H")
  3771 
  3772 class XShortField(ShortField):
  3773     def i2repr(self, pkt, x):
  3774         if x is None:
  3775             x = 0
  3776         return lhex(self.i2h(pkt, x))
  3777 
  3778 
  3779 class IntField(Field):
  3780     def __init__(self, name, default):
  3781         Field.__init__(self, name, default, "I")
  3782 
  3783 class SignedIntField(Field):
  3784     def __init__(self, name, default):
  3785         Field.__init__(self, name, default, "i")
  3786     def randval(self):
  3787         return RandSInt()
  3788 
  3789 class LEIntField(Field):
  3790     def __init__(self, name, default):
  3791         Field.__init__(self, name, default, "<I")
  3792 
  3793 class LESignedIntField(Field):
  3794     def __init__(self, name, default):
  3795         Field.__init__(self, name, default, "<i")
  3796     def randval(self):
  3797         return RandSInt()
  3798 
  3799 class XIntField(IntField):
  3800     def i2repr(self, pkt, x):
  3801         if x is None:
  3802             x = 0
  3803         return lhex(self.i2h(pkt, x))
  3804 
  3805 
  3806 class LongField(Field):
  3807     def __init__(self, name, default):
  3808         Field.__init__(self, name, default, "Q")
  3809 
  3810 class XLongField(LongField):
  3811     def i2repr(self, pkt, x):
  3812         if x is None:
  3813             x = 0
  3814         return lhex(self.i2h(pkt, x))
  3815 
  3816 class IEEEFloatField(Field):
  3817     def __init__(self, name, default):
  3818         Field.__init__(self, name, default, "f")
  3819 
  3820 class IEEEDoubleField(Field):
  3821     def __init__(self, name, default):
  3822         Field.__init__(self, name, default, "d")
  3823 
  3824 
  3825 def FIELD_LENGTH_MANAGEMENT_DEPRECATION(x):
  3826     try:
  3827         for tb in traceback.extract_stack()+[("??",-1,None,"")]:
  3828             f,l,_,line = tb
  3829             if line.startswith("fields_desc"):
  3830                 break
  3831     except:
  3832         f,l="??",-1
  3833     log_loading.warning("Deprecated use of %s (%s l. %i). See http://trac.secdev.org/scapy/wiki/LengthFields" % (x,f,l))
  3834 
  3835 class StrField(Field):
  3836     def __init__(self, name, default, fmt="H", remain=0, shift=0):
  3837         Field.__init__(self,name,default,fmt)
  3838         self.remain = remain        
  3839         self.shift = shift
  3840         if shift != 0:
  3841             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  3842     def i2len(self, pkt, i):
  3843         return len(i)+self.shift
  3844     def i2m(self, pkt, x):
  3845         if x is None:
  3846             x = ""
  3847         elif type(x) is not str:
  3848             x=str(x)
  3849         return x
  3850     def addfield(self, pkt, s, val):
  3851         return s+self.i2m(pkt, val)
  3852     def getfield(self, pkt, s):
  3853         if self.remain == 0:
  3854             return "",self.m2i(pkt, s)
  3855         else:
  3856             return s[-self.remain:],self.m2i(pkt, s[:-self.remain])
  3857     def randval(self):
  3858         return RandBin(RandNum(0,1200))
  3859 
  3860 class PacketField(StrField):
  3861     holds_packets=1
  3862     def __init__(self, name, default, cls, remain=0, shift=0):
  3863         StrField.__init__(self, name, default, remain=remain, shift=shift)
  3864         self.cls = cls
  3865     def i2m(self, pkt, i):
  3866         return str(i)
  3867     def m2i(self, pkt, m):
  3868         return self.cls(m)
  3869     def getfield(self, pkt, s):
  3870         i = self.m2i(pkt, s)
  3871         remain = ""
  3872         if i.haslayer(Padding):
  3873             r = i.getlayer(Padding)
  3874             del(r.underlayer.payload)
  3875             remain = r.load
  3876         return remain,i
  3877     
  3878 class PacketLenField(PacketField):
  3879     holds_packets=1
  3880     def __init__(self, name, default, cls, fld=None, length_from=None, shift=0):
  3881         PacketField.__init__(self, name, default, cls, shift=shift)
  3882         self.length_from = length_from
  3883         if fld is not None or shift != 0:
  3884             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  3885             self.count_from = lambda pkt,fld=fld,shift=shift: getattr(pkt,fld)-shift
  3886     def getfield(self, pkt, s):
  3887         l = self.length_from(pkt)
  3888         i = self.m2i(pkt, s[:l])
  3889         return s[l:],i
  3890 
  3891 
  3892 class PacketListField(PacketField):
  3893     islist = 1
  3894     holds_packets=1
  3895     def __init__(self, name, default, cls, fld=None, count_from=None, length_from=None, shift=0):
  3896         if default is None:
  3897             default = []  # Create a new list for each instance
  3898         PacketField.__init__(self, name, default, cls, shift=shift)
  3899         self.count_from = count_from
  3900         self.length_from = length_from
  3901 
  3902         if fld is not None or shift != 0:
  3903             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  3904         if fld is not None:
  3905             self.count_from = lambda pkt,fld=fld,shift=shift: getattr(pkt,fld)-shift
  3906 
  3907     def any2i(self, pkt, x):
  3908         if type(x) is not list:
  3909             return [x]
  3910         else:
  3911             return x
  3912     def i2count(self, pkt, val):
  3913         if type(val) is list:
  3914             return len(val)
  3915         return 1
  3916     def i2len(self, pkt, val):
  3917         return sum( len(p) for p in val )
  3918     def do_copy(self, x):
  3919         return map(lambda p:p.copy(), x)
  3920     def getfield(self, pkt, s):
  3921         c = l = None
  3922         if self.length_from is not None:
  3923             l = self.length_from(pkt)
  3924         elif self.count_from is not None:
  3925             c = self.count_from(pkt)
  3926             
  3927         lst = []
  3928         ret = ""
  3929         remain = s
  3930         if l is not None:
  3931             remain,ret = s[:l],s[l:]
  3932         while remain:
  3933             if c is not None:
  3934                 if c <= 0:
  3935                     break
  3936                 c -= 1
  3937             p = self.m2i(pkt,remain)
  3938             if Padding in p:
  3939                 pad = p[Padding]
  3940                 remain = pad.load
  3941                 del(pad.underlayer.payload)
  3942             else:
  3943                 remain = ""
  3944             lst.append(p)
  3945         return remain+ret,lst
  3946     def addfield(self, pkt, s, val):
  3947         return s+"".join(map(str, val))
  3948 
  3949 
  3950 class StrFixedLenField(StrField):
  3951     def __init__(self, name, default, length=None, length_from=None, shift=0):
  3952         StrField.__init__(self, name, default, shift=shift)
  3953         self.length_from  = length_from
  3954         if length is not None:
  3955             self.length_from = lambda pkt,length=length: length
  3956     def getfield(self, pkt, s):
  3957         l = self.length_from(pkt)
  3958         return s[l:], self.m2i(pkt,s[:l])
  3959     def addfield(self, pkt, s, val):
  3960         l = self.length_from(pkt)
  3961         return s+struct.pack("%is"%l,self.i2m(pkt, val))
  3962     def randval(self):
  3963         try:
  3964             l = self.length_from(None)
  3965         except:
  3966             l = RandNum(0,200)
  3967         return RandBin(l)
  3968 
  3969 class NetBIOSNameField(StrFixedLenField):
  3970     def __init__(self, name, default, length=31, shift=0):
  3971         StrFixedLenField.__init__(self, name, default, length, shift=shift)
  3972     def i2m(self, pkt, x):
  3973         l = self.length_from(pkt)/2
  3974         if x is None:
  3975             x = ""
  3976         x += " "*(l)
  3977         x = x[:l]
  3978         x = "".join(map(lambda x: chr(0x41+(ord(x)>>4))+chr(0x41+(ord(x)&0xf)), x))
  3979         x = " "+x
  3980         return x
  3981     def m2i(self, pkt, x):
  3982         x = x.strip("\x00").strip(" ")
  3983         return "".join(map(lambda x,y: chr((((ord(x)-1)&0xf)<<4)+((ord(y)-1)&0xf)), x[::2],x[1::2]))
  3984 
  3985 class StrLenField(StrField):
  3986     def __init__(self, name, default, fld=None, length_from=None, shift=0):
  3987         StrField.__init__(self, name, default, shift=shift)
  3988         self.length_from = length_from
  3989         if fld is not None or shift != 0:
  3990             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  3991             self.length_from = lambda pkt,fld=fld,shift=shift: getattr(pkt,fld)-shift
  3992     def getfield(self, pkt, s):
  3993         l = self.length_from(pkt)
  3994         return s[l:], self.m2i(pkt,s[:l])
  3995 
  3996 class FieldListField(Field):
  3997     islist=1
  3998     def __init__(self, name, default, field, fld=None, shift=0, length_from=None, count_from=None):
  3999         if default is None:
  4000             default = []  # Create a new list for each instance
  4001         Field.__init__(self, name, default)
  4002         self.count_from = count_from
  4003         self.length_from = length_from
  4004         self.field = field
  4005         if fld is not None or shift != 0:
  4006             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  4007             self.count_from = lambda pkt,fld=fld,shift=shift: getattr(pkt,fld)-shift
  4008             
  4009             
  4010     def i2count(self, pkt, val):
  4011         if type(val) is list:
  4012             return len(val)
  4013         return 1
  4014     def i2len(self, pkt, val):
  4015         return sum( self.field.i2len(pkt,v) for v in val )
  4016     
  4017     def i2m(self, pkt, val):
  4018         if val is None:
  4019             val = []
  4020         return val
  4021     def any2i(self, pkt, x):
  4022         if type(x) is not list:
  4023             return [x]
  4024         else:
  4025             return x
  4026     def addfield(self, pkt, s, val):
  4027         val = self.i2m(pkt, val)
  4028         for v in val:
  4029             s = self.field.addfield(pkt, s, v)
  4030         return s
  4031     def getfield(self, pkt, s):
  4032         c = l = None
  4033         if self.length_from is not None:
  4034             l = self.length_from(pkt)
  4035         elif self.count_from is not None:
  4036             c = self.count_from(pkt)
  4037 
  4038         val = []
  4039         ret=""
  4040         if l is not None:
  4041             s,ret = s[:l],s[l:]
  4042             
  4043         while s:
  4044             if c is not None:
  4045                 if c <= 0:
  4046                     break
  4047                 c -= 1
  4048             s,v = self.field.getfield(pkt, s)
  4049             val.append(v)
  4050         return s+ret, val
  4051 
  4052 class FieldLenField(Field):
  4053     def __init__(self, name, default,  length_of=None, fmt = "H", count_of=None, adjust=lambda pkt,x:x, fld=None):
  4054         Field.__init__(self, name, default, fmt)
  4055         self.length_of=length_of
  4056         self.count_of=count_of
  4057         self.adjust=adjust
  4058         if fld is not None:
  4059             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
  4060             self.length_of = fld
  4061     def i2m(self, pkt, x):
  4062         if x is None:
  4063             if self.length_of is not None:
  4064                 fld,fval = pkt.getfield_and_val(self.length_of)
  4065                 f = fld.i2len(pkt, fval)
  4066             else:
  4067                 fld,fval = pkt.getfield_and_val(self.count_of)
  4068                 f = fld.i2count(pkt, fval)
  4069             x = self.adjust(pkt,f)
  4070         return x
  4071 
  4072 # see http://www.iana.org/assignments/ipsec-registry for details
  4073 ISAKMPAttributeTypes= { "Encryption":    (1, { "DES-CBC"  : 1,
  4074                                                 "IDEA-CBC" : 2,
  4075                                                 "Blowfish-CBC" : 3,
  4076                                                 "RC5-R16-B64-CBC" : 4,
  4077                                                 "3DES-CBC" : 5, 
  4078                                                 "CAST-CBC" : 6, 
  4079                                                 "AES-CBC" : 7, 
  4080                                                 "CAMELLIA-CBC" : 8, }, 0),
  4081                          "Hash":          (2, { "MD5": 1,
  4082                                                 "SHA": 2,
  4083                                                 "Tiger": 3,
  4084                                                 "SHA2-256": 4,
  4085                                                 "SHA2-384": 5,
  4086                                                 "SHA2-512": 6,}, 0),
  4087                          "Authentication":(3, { "PSK": 1, 
  4088                                                 "DSS": 2,
  4089                                                 "RSA Sig": 3,
  4090                                                 "RSA Encryption": 4,
  4091                                                 "RSA Encryption Revised": 5,
  4092                                                 "ElGamal Encryption": 6,
  4093                                                 "ElGamal Encryption Revised": 7,
  4094                                                 "ECDSA Sig": 8,
  4095                                                 "HybridInitRSA": 64221,
  4096                                                 "HybridRespRSA": 64222,
  4097                                                 "HybridInitDSS": 64223,
  4098                                                 "HybridRespDSS": 64224,
  4099                                                 "XAUTHInitPreShared": 65001,
  4100                                                 "XAUTHRespPreShared": 65002,
  4101                                                 "XAUTHInitDSS": 65003,
  4102                                                 "XAUTHRespDSS": 65004,
  4103                                                 "XAUTHInitRSA": 65005,
  4104                                                 "XAUTHRespRSA": 65006,
  4105                                                 "XAUTHInitRSAEncryption": 65007,
  4106                                                 "XAUTHRespRSAEncryption": 65008,
  4107                                                 "XAUTHInitRSARevisedEncryption": 65009,
  4108                                                 "XAUTHRespRSARevisedEncryptio": 65010, }, 0),
  4109                          "GroupDesc":     (4, { "768MODPgr"  : 1,
  4110                                                 "1024MODPgr" : 2, 
  4111                                                 "EC2Ngr155"  : 3,
  4112                                                 "EC2Ngr185"  : 4,
  4113                                                 "1536MODPgr" : 5, 
  4114                                                 "2048MODPgr" : 14, 
  4115                                                 "3072MODPgr" : 15, 
  4116                                                 "4096MODPgr" : 16, 
  4117                                                 "6144MODPgr" : 17, 
  4118                                                 "8192MODPgr" : 18, }, 0),
  4119                          "GroupType":      (5,  {"MODP":       1,
  4120                                                  "ECP":        2,
  4121                                                  "EC2N":       3}, 0),
  4122                          "GroupPrime":     (6,  {}, 1),
  4123                          "GroupGenerator1":(7,  {}, 1),
  4124                          "GroupGenerator2":(8,  {}, 1),
  4125                          "GroupCurveA":    (9,  {}, 1),
  4126                          "GroupCurveB":    (10, {}, 1),
  4127                          "LifeType":       (11, {"Seconds":     1,
  4128                                                  "Kilobytes":   2,  }, 0),
  4129                          "LifeDuration":   (12, {}, 1),
  4130                          "PRF":            (13, {}, 0),
  4131                          "KeyLength":      (14, {}, 0),
  4132                          "FieldSize":      (15, {}, 0),
  4133                          "GroupOrder":     (16, {}, 1),
  4134                          }
  4135 
  4136 # the name 'ISAKMPTransformTypes' is actually a misnomer (since the table 
  4137 # holds info for all ISAKMP Attribute types, not just transforms, but we'll 
  4138 # keep it for backwards compatibility... for now at least
  4139 ISAKMPTransformTypes = ISAKMPAttributeTypes
  4140 
  4141 ISAKMPTransformNum = {}
  4142 for n in ISAKMPTransformTypes:
  4143     val = ISAKMPTransformTypes[n]
  4144     tmp = {}
  4145     for e in val[1]:
  4146         tmp[val[1][e]] = e
  4147     ISAKMPTransformNum[val[0]] = (n,tmp, val[2])
  4148 del(n)
  4149 del(e)
  4150 del(tmp)
  4151 del(val)
  4152 
  4153 
  4154 class ISAKMPTransformSetField(StrLenField):
  4155     islist=1
  4156     def type2num(self, (typ,val)):
  4157         type_val,enc_dict,tlv = ISAKMPTransformTypes.get(typ, (typ,{},0))
  4158         val = enc_dict.get(val, val)
  4159         s = ""
  4160         if (val & ~0xffff):
  4161             if not tlv:
  4162                 warning("%r should not be TLV but is too big => using TLV encoding" % typ)
  4163             n = 0
  4164             while val:
  4165                 s = chr(val&0xff)+s
  4166                 val >>= 8
  4167                 n += 1
  4168             val = n
  4169         else:
  4170             type_val |= 0x8000
  4171         return struct.pack("!HH",type_val, val)+s
  4172     def num2type(self, typ, enc):
  4173         val = ISAKMPTransformNum.get(typ,(typ,{}))
  4174         enc = val[1].get(enc,enc)
  4175         return (val[0],enc)
  4176     def i2m(self, pkt, i):
  4177         if i is None:
  4178             return ""
  4179         i = map(self.type2num, i)
  4180         return "".join(i)
  4181     def m2i(self, pkt, m):
  4182         # I try to ensure that we don't read off the end of our packet based
  4183         # on bad length fields we're provided in the packet. There are still
  4184         # conditions where struct.unpack() may not get enough packet data, but
  4185         # worst case that should result in broken attributes (which would
  4186         # be expected). (wam)
  4187         lst = []
  4188         while len(m) >= 4:
  4189             trans_type, = struct.unpack("!H", m[:2])
  4190             is_tlv = not (trans_type & 0x8000)
  4191             if is_tlv:
  4192                 # We should probably check to make sure the attribute type we
  4193                 # are looking at is allowed to have a TLV format and issue a 
  4194                 # warning if we're given an TLV on a basic attribute.
  4195                 value_len, = struct.unpack("!H", m[2:4])
  4196                 if value_len+4 > len(m):
  4197                     warning("Bad length for ISAKMP tranform type=%#6x" % trans_type)
  4198                 value = m[4:4+value_len]
  4199                 value = reduce(lambda x,y: (x<<8L)|y, struct.unpack("!%s" % ("B"*len(value),), value),0)
  4200             else:
  4201                 trans_type &= 0x7fff
  4202                 value_len=0
  4203                 value, = struct.unpack("!H", m[2:4])
  4204             m=m[4+value_len:]
  4205             lst.append(self.num2type(trans_type, value))
  4206         if len(m) > 0:
  4207             warning("Extra bytes after ISAKMP transform dissection [%r]" % m)
  4208         return lst
  4209 
  4210 class StrNullField(StrField):
  4211     def addfield(self, pkt, s, val):
  4212         return s+self.i2m(pkt, val)+"\x00"
  4213     def getfield(self, pkt, s):
  4214         l = s.find("\x00")
  4215         if l < 0:
  4216             #XXX \x00 not found
  4217             return "",s
  4218         return s[l+1:],self.m2i(pkt, s[:l])
  4219     def randval(self):
  4220         return RandTermString(RandNum(0,1200),"\x00")
  4221 
  4222 class StrStopField(StrField):
  4223     def __init__(self, name, default, stop, additionnal=0):
  4224         Field.__init__(self, name, default)
  4225         self.stop=stop
  4226         self.additionnal=additionnal
  4227     def getfield(self, pkt, s):
  4228         l = s.find(self.stop)
  4229         if l < 0:
  4230             return "",s
  4231 #            raise Scapy_Exception,"StrStopField: stop value [%s] not found" %stop
  4232         l += len(self.stop)+self.additionnal
  4233         return s[l:],s[:l]
  4234     def randval(self):
  4235         return RandTermString(RandNum(0,1200),self.stop)
  4236 
  4237 class LenField(Field):
  4238     def i2m(self, pkt, x):
  4239         if x is None:
  4240             x = len(pkt.payload)
  4241         return x
  4242 
  4243 class BCDFloatField(Field):
  4244     def i2m(self, pkt, x):
  4245         return int(256*x)
  4246     def m2i(self, pkt, x):
  4247         return x/256.0
  4248 
  4249 class BitField(Field):
  4250     def __init__(self, name, default, size):
  4251         Field.__init__(self, name, default)
  4252         self.rev = size < 0 
  4253         self.size = abs(size)
  4254     def reverse(self, val):
  4255         if self.size == 16:
  4256             val = socket.ntohs(val)
  4257         elif self.size == 32:
  4258             val = socket.ntohl(val)
  4259         return val
  4260         
  4261     def addfield(self, pkt, s, val):
  4262         val = self.i2m(pkt, val)
  4263         if type(s) is tuple:
  4264             s,bitsdone,v = s
  4265         else:
  4266             bitsdone = 0
  4267             v = 0
  4268         if self.rev:
  4269             val = self.reverse(val)
  4270         v <<= self.size
  4271         v |= val & ((1L<<self.size) - 1)
  4272         bitsdone += self.size
  4273         while bitsdone >= 8:
  4274             bitsdone -= 8
  4275             s = s+struct.pack("!B", v >> bitsdone)
  4276             v &= (1L<<bitsdone)-1
  4277         if bitsdone:
  4278             return s,bitsdone,v
  4279         else:
  4280             return s
  4281     def getfield(self, pkt, s):
  4282         if type(s) is tuple:
  4283             s,bn = s
  4284         else:
  4285             bn = 0
  4286         # we don't want to process all the string
  4287         nb_bytes = (self.size+bn-1)/8 + 1
  4288         w = s[:nb_bytes]
  4289 
  4290         # split the substring byte by byte
  4291         bytes = struct.unpack('!%dB' % nb_bytes , w)
  4292 
  4293         b = 0L
  4294         for c in range(nb_bytes):
  4295             b |= long(bytes[c]) << (nb_bytes-c-1)*8
  4296 
  4297         # get rid of high order bits
  4298         b &= (1L << (nb_bytes*8-bn)) - 1
  4299 
  4300         # remove low order bits
  4301         b = b >> (nb_bytes*8 - self.size - bn)
  4302 
  4303         if self.rev:
  4304             b = self.reverse(b)
  4305 
  4306         bn += self.size
  4307         s = s[bn/8:]
  4308         bn = bn%8
  4309         b = self.m2i(pkt, b)
  4310         if bn:
  4311             return (s,bn),b
  4312         else:
  4313             return s,b
  4314     def randval(self):
  4315         return RandNum(0,2**self.size-1)
  4316 
  4317 
  4318 class BitFieldLenField(BitField):
  4319     def __init__(self, name, default, size, length_of=None, count_of=None, adjust=lambda pkt,x:x):
  4320         BitField.__init__(self, name, default, size)
  4321         self.length_of=length_of
  4322         self.count_of=count_of
  4323         self.adjust=adjust
  4324     def i2m(self, pkt, x):
  4325         return FieldLenField.i2m.im_func(self, pkt, x)
  4326 
  4327 
  4328 class XBitField(BitField):
  4329     def i2repr(self, pkt, x):
  4330         return lhex(self.i2h(pkt,x))
  4331 
  4332 
  4333 class EnumField(Field):
  4334     def __init__(self, name, default, enum, fmt = "H"):
  4335         i2s = self.i2s = {}
  4336         s2i = self.s2i = {}
  4337         if type(enum) is list:
  4338             keys = xrange(len(enum))
  4339         else:
  4340             keys = enum.keys()
  4341         if filter(lambda x: type(x) is str, keys):
  4342             i2s,s2i = s2i,i2s
  4343         for k in keys:
  4344             i2s[k] = enum[k]
  4345             s2i[enum[k]] = k
  4346         Field.__init__(self, name, default, fmt)
  4347     def any2i_one(self, pkt, x):
  4348         if type(x) is str:
  4349             x = self.s2i[x]
  4350         return x
  4351     def i2repr_one(self, pkt, x):
  4352         if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s:
  4353             return self.i2s[x]
  4354         return repr(x)
  4355     
  4356     def any2i(self, pkt, x):
  4357         if type(x) is list:
  4358             return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x)
  4359         else:
  4360             return self.any2i_one(pkt,x)        
  4361     def i2repr(self, pkt, x):
  4362         if type(x) is list:
  4363             return map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x)
  4364         else:
  4365             return self.i2repr_one(pkt,x)
  4366 
  4367 class CharEnumField(EnumField):
  4368     def __init__(self, name, default, enum, fmt = "1s"):
  4369         EnumField.__init__(self, name, default, enum, fmt)
  4370         k = self.i2s.keys()
  4371         if k and len(k[0]) != 1:
  4372             self.i2s,self.s2i = self.s2i,self.i2s
  4373     def any2i_one(self, pkt, x):
  4374         if len(x) != 1:
  4375             x = self.s2i[x]
  4376         return x
  4377 
  4378 class BitEnumField(BitField,EnumField):
  4379     def __init__(self, name, default, size, enum):
  4380         EnumField.__init__(self, name, default, enum)
  4381         self.rev = size < 0
  4382         self.size = abs(size)
  4383     def any2i(self, pkt, x):
  4384         return EnumField.any2i(self, pkt, x)
  4385     def i2repr(self, pkt, x):
  4386         return EnumField.i2repr(self, pkt, x)
  4387 
  4388 class ShortEnumField(EnumField):
  4389     def __init__(self, name, default, enum):
  4390         EnumField.__init__(self, name, default, enum, "H")
  4391 
  4392 class LEShortEnumField(EnumField):
  4393     def __init__(self, name, default, enum):
  4394         EnumField.__init__(self, name, default, enum, "<H")
  4395 
  4396 class ByteEnumField(EnumField):
  4397     def __init__(self, name, default, enum):
  4398         EnumField.__init__(self, name, default, enum, "B")
  4399 
  4400 class IntEnumField(EnumField):
  4401     def __init__(self, name, default, enum):
  4402         EnumField.__init__(self, name, default, enum, "I")
  4403 
  4404 class SignedIntEnumField(EnumField):
  4405     def __init__(self, name, default, enum):
  4406         EnumField.__init__(self, name, default, enum, "i")
  4407     def randval(self):
  4408         return RandSInt()
  4409 
  4410 class LEIntEnumField(EnumField):
  4411     def __init__(self, name, default, enum):
  4412         EnumField.__init__(self, name, default, enum, "<I")
  4413 
  4414 class XShortEnumField(ShortEnumField):
  4415     def i2repr_one(self, pkt, x):
  4416         if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s:
  4417             return self.i2s[x]
  4418         return lhex(x)
  4419 
  4420 # Little endian long field
  4421 class LELongField(Field):
  4422     def __init__(self, name, default):
  4423         Field.__init__(self, name, default, "<Q")
  4424 
  4425 # Little endian fixed length field
  4426 class LEFieldLenField(FieldLenField):
  4427     def __init__(self, name, default,  length_of=None, fmt = "<H", count_of=None, adjust=lambda pkt,x:x, fld=None):
  4428         FieldLenField.__init__(self, name, default, length_of=length_of, fmt=fmt, fld=fld, adjust=adjust)
  4429 
  4430 
  4431 class FlagsField(BitField):
  4432     def __init__(self, name, default, size, names):
  4433         BitField.__init__(self, name, default, size)
  4434         self.multi = type(names) is list
  4435         if self.multi:
  4436             self.names = map(lambda x:[x], names)
  4437         else:
  4438             self.names = names
  4439     def any2i(self, pkt, x):
  4440         if type(x) is str:
  4441             if self.multi:
  4442                 x = map(lambda y:[y], x.split("+"))
  4443             y = 0
  4444             for i in x:
  4445                 y |= 1 << self.names.index(i)
  4446             x = y
  4447         return x
  4448     def i2repr(self, pkt, x):
  4449         if type(x) is list or type(x) is tuple:
  4450             return repr(x)
  4451         if self.multi:
  4452             r = []
  4453         else:
  4454             r = ""
  4455         i=0
  4456         while x:
  4457             if x & 1:
  4458                 r += self.names[i]
  4459             i += 1
  4460             x >>= 1
  4461         if self.multi:
  4462             r = "+".join(r)
  4463         return r
  4464 
  4465             
  4466 
  4467 
  4468 
  4469 class IPoptionsField(StrField):
  4470     def i2m(self, pkt, x):
  4471         return x+"\x00"*(3-((len(x)+3)%4))
  4472     def getfield(self, pkt, s):
  4473         opsz = (pkt.ihl-5)*4
  4474         if opsz < 0:
  4475             warning("bad ihl (%i). Assuming ihl=5"%pkt.ihl)
  4476             opsz = 0
  4477         return s[opsz:],s[:opsz]
  4478     def randval(self):
  4479         return RandBin(RandNum(0,39))
  4480 
  4481 
  4482 TCPOptions = (
  4483               { 0 : ("EOL",None),
  4484                 1 : ("NOP",None),
  4485                 2 : ("MSS","!H"),
  4486                 3 : ("WScale","!B"),
  4487                 4 : ("SAckOK",None),
  4488                 5 : ("SAck","!"),
  4489                 8 : ("Timestamp","!II"),
  4490                 14 : ("AltChkSum","!BH"),
  4491                 15 : ("AltChkSumOpt",None)
  4492                 },
  4493               { "EOL":0,
  4494                 "NOP":1,
  4495                 "MSS":2,
  4496                 "WScale":3,
  4497                 "SAckOK":4,
  4498                 "SAck":5,
  4499                 "Timestamp":8,
  4500                 "AltChkSum":14,
  4501                 "AltChkSumOpt":15,
  4502                 } )
  4503 
  4504 class TCPOptionsField(StrField):
  4505     islist=1
  4506     def getfield(self, pkt, s):
  4507         opsz = (pkt.dataofs-5)*4
  4508         if opsz < 0:
  4509             warning("bad dataofs (%i). Assuming dataofs=5"%pkt.dataofs)
  4510             opsz = 0
  4511         return s[opsz:],self.m2i(pkt,s[:opsz])
  4512     def m2i(self, pkt, x):
  4513         opt = []
  4514         while x:
  4515             onum = ord(x[0])
  4516             if onum == 0:
  4517                 opt.append(("EOL",None))
  4518                 x=x[1:]
  4519                 break
  4520             if onum == 1:
  4521                 opt.append(("NOP",None))
  4522                 x=x[1:]
  4523                 continue
  4524             olen = ord(x[1])
  4525             if olen < 2:
  4526                 warning("Malformed TCP option (announced length is %i)" % olen)
  4527                 olen = 2
  4528             oval = x[2:olen]
  4529             if TCPOptions[0].has_key(onum):
  4530                 oname, ofmt = TCPOptions[0][onum]
  4531                 if onum == 5: #SAck
  4532                     ofmt += "%iI" % (len(oval)/4)
  4533                 if ofmt and struct.calcsize(ofmt) == len(oval):
  4534                     oval = struct.unpack(ofmt, oval)
  4535                     if len(oval) == 1:
  4536                         oval = oval[0]
  4537                 opt.append((oname, oval))
  4538             else:
  4539                 opt.append((onum, oval))
  4540             x = x[olen:]
  4541         return opt
  4542     
  4543     def i2m(self, pkt, x):
  4544         opt = ""
  4545         for oname,oval in x:
  4546             if type(oname) is str:
  4547                 if oname == "NOP":
  4548                     opt += "\x01"
  4549                     continue
  4550                 elif oname == "EOL":
  4551                     opt += "\x00"
  4552                     continue
  4553                 elif TCPOptions[1].has_key(oname):
  4554                     onum = TCPOptions[1][oname]
  4555                     ofmt = TCPOptions[0][onum][1]
  4556                     if onum == 5: #SAck
  4557                         ofmt += "%iI" % len(oval)
  4558                     if ofmt is not None and (type(oval) is not str or "s" in ofmt):
  4559                         if type(oval) is not tuple:
  4560                             oval = (oval,)
  4561                         oval = struct.pack(ofmt, *oval)
  4562                 else:
  4563                     warning("option [%s] unknown. Skipped."%oname)
  4564                     continue
  4565             else:
  4566                 onum = oname
  4567                 if type(oval) is not str:
  4568                     warning("option [%i] is not string."%onum)
  4569                     continue
  4570             opt += chr(onum)+chr(2+len(oval))+oval
  4571         return opt+"\x00"*(3-((len(opt)+3)%4))
  4572     def randval(self):
  4573         return [] # XXX
  4574     
  4575 
  4576 class DNSStrField(StrField):
  4577     def i2m(self, pkt, x):
  4578         x = [k[:63] for k in x.split(".")] # Truncate chunks that cannont be encoded (more than 63 bytes..)
  4579         x = map(lambda y: chr(len(y))+y, x)
  4580         x = "".join(x)
  4581         if x[-1] != "\x00":
  4582             x += "\x00"
  4583         return x
  4584     def getfield(self, pkt, s):
  4585         n = ""
  4586         while 1:
  4587             l = ord(s[0])
  4588             s = s[1:]
  4589             if not l:
  4590                 break
  4591             if l & 0xc0:
  4592                 raise Scapy_Exception("DNS message can't be compressed at this point!")
  4593             else:
  4594                 n += s[:l]+"."
  4595                 s = s[l:]
  4596         return s, n
  4597 
  4598 
  4599 class DNSRRCountField(ShortField):
  4600     holds_packets=1
  4601     def __init__(self, name, default, rr):
  4602         ShortField.__init__(self, name, default)
  4603         self.rr = rr
  4604     def _countRR(self, pkt):
  4605         x = getattr(pkt,self.rr)
  4606         i = 0
  4607         while isinstance(x, DNSRR) or isinstance(x, DNSQR):
  4608             x = x.payload
  4609             i += 1
  4610         return i
  4611         
  4612     def i2m(self, pkt, x):
  4613         if x is None:
  4614             x = self._countRR(pkt)
  4615         return x
  4616     def i2h(self, pkt, x):
  4617         if x is None:
  4618             x = self._countRR(pkt)
  4619         return x
  4620     
  4621 
  4622 def DNSgetstr(s,p):
  4623     name = ""
  4624     q = 0
  4625     jpath = [p]
  4626     while 1:
  4627         if p >= len(s):
  4628             warning("DNS RR prematured end (ofs=%i, len=%i)"%(p,len(s)))
  4629             break
  4630         l = ord(s[p])
  4631         p += 1
  4632         if l & 0xc0:
  4633             if not q:
  4634                 q = p+1
  4635             if p >= len(s):
  4636                 warning("DNS incomplete jump token at (ofs=%i)" % p)
  4637                 break
  4638             p = ((l & 0x3f) << 8) + ord(s[p]) - 12
  4639             if p in jpath:
  4640                 warning("DNS decompression loop detected")
  4641                 break
  4642             jpath.append(p)
  4643             continue
  4644         elif l > 0:
  4645             name += s[p:p+l]+"."
  4646             p += l
  4647             continue
  4648         break
  4649     if q:
  4650         p = q
  4651     return name,p
  4652         
  4653 
  4654 class DNSRRField(StrField):
  4655     holds_packets=1
  4656     def __init__(self, name, countfld, passon=1):
  4657         StrField.__init__(self, name, None)
  4658         self.countfld = countfld
  4659         self.passon = passon
  4660     def i2m(self, pkt, x):
  4661         if x is None:
  4662             return ""
  4663         return str(x)
  4664     def decodeRR(self, name, s, p):
  4665         ret = s[p:p+10]
  4666         type,cls,ttl,rdlen = struct.unpack("!HHIH", ret)
  4667         p += 10
  4668         rr = DNSRR("\x00"+ret+s[p:p+rdlen])
  4669         if rr.type in [2, 3, 4, 5]:
  4670             rr.rdata = DNSgetstr(s,p)[0]
  4671         del(rr.rdlen)
  4672         
  4673         p += rdlen
  4674         
  4675         rr.rrname = name
  4676         return rr,p
  4677     def getfield(self, pkt, s):
  4678         if type(s) is tuple :
  4679             s,p = s
  4680         else:
  4681             p = 0
  4682         ret = None
  4683         c = getattr(pkt, self.countfld)
  4684         if c > len(s):
  4685             warning("wrong value: DNS.%s=%i" % (self.countfld,c))
  4686             return s,""
  4687         while c:
  4688             c -= 1
  4689             name,p = DNSgetstr(s,p)
  4690             rr,p = self.decodeRR(name, s, p)
  4691             if ret is None:
  4692                 ret = rr
  4693             else:
  4694                 ret.add_payload(rr)
  4695         if self.passon:
  4696             return (s,p),ret
  4697         else:
  4698             return s[p:],ret
  4699             
  4700             
  4701 class DNSQRField(DNSRRField):
  4702     holds_packets=1
  4703     def decodeRR(self, name, s, p):
  4704         ret = s[p:p+4]
  4705         p += 4
  4706         rr = DNSQR("\x00"+ret)
  4707         rr.qname = name
  4708         return rr,p
  4709         
  4710         
  4711 
  4712 class RDataField(StrLenField):
  4713     def m2i(self, pkt, s):
  4714         family = None
  4715         if pkt.type == 1:
  4716             family = socket.AF_INET
  4717         elif pkt.type == 28:
  4718             family = socket.AF_INET6
  4719         elif pkt.type == 12:
  4720             s = DNSgetstr(s, 0)[0]
  4721         if family is not None:    
  4722             s = inet_ntop(family, s)
  4723         return s
  4724     def i2m(self, pkt, s):
  4725         if pkt.type == 1:
  4726             if s:
  4727                 s = inet_aton(s)
  4728         elif pkt.type == 28:
  4729             if s:
  4730                 s = inet_pton(socket.AF_INET6, s)
  4731         elif pkt.type in [2,3,4,5]:
  4732             s = "".join(map(lambda x: chr(len(x))+x, s.split(".")))
  4733             if ord(s[-1]):
  4734                 s += "\x00"
  4735         return s
  4736 
  4737 class RDLenField(Field):
  4738     def __init__(self, name):
  4739         Field.__init__(self, name, None, "H")
  4740     def i2m(self, pkt, x):
  4741         if x is None:
  4742             rdataf = pkt.get_field("rdata")
  4743             x = len(rdataf.i2m(pkt, pkt.rdata))
  4744         return x
  4745     def i2h(self, pkt, x):
  4746         if x is None:
  4747             rdataf = pkt.get_field("rdata")
  4748             x = len(rdataf.i2m(pkt, pkt.rdata))
  4749         return x
  4750     
  4751 # seconds between 01-01-1900 and 01-01-1970
  4752 ntp_basetime = 2208988800
  4753 
  4754 class TimeStampField(BitField):
  4755     def __init__(self, name, default, size):
  4756         BitField.__init__(self, name, default, size)
  4757         self.size  = size
  4758     def getfield(self, pkt, s):
  4759         s,timestamp = BitField.getfield(self, pkt, s)
  4760 
  4761         if timestamp:
  4762             # timestamp is a 64 bits field :
  4763             #  + first 32 bits : number of seconds since 1900
  4764             #  + last 32 bits  : fraction part
  4765             timestamp >>= 32
  4766             timestamp -= ntp_basetime
  4767             
  4768             from time import gmtime, strftime
  4769             b = strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime(timestamp))
  4770         else:
  4771             b = 'None'
  4772         
  4773         return s, b
  4774     def addfield(self, pkt, s, val):
  4775         t = -1
  4776         if type(val) is str:
  4777             from time import strptime, mktime
  4778             t = int(mktime(strptime(val))) + ntp_basetime + 3600
  4779         else:
  4780             if val == -1:
  4781                 from time import time
  4782                 t = int(time()) + ntp_basetime
  4783             else:
  4784                 t = val
  4785         t <<= 32
  4786         return BitField.addfield(self,pkt,s, t)
  4787 
  4788 class ICMPTimeStampField(IntField):
  4789     re_hmsm = re.compile("([0-2]?[0-9])[Hh:](([0-5]?[0-9])([Mm:]([0-5]?[0-9])([sS:.]([0-9]{0,3}))?)?)?$")
  4790     def i2repr(self, pkt, val):
  4791         if val is None:
  4792             return "--"
  4793         else:
  4794             sec, milli = divmod(val, 1000)
  4795             min, sec = divmod(sec, 60)
  4796             hour, min = divmod(min, 60)
  4797             return "%d:%d:%d.%d" %(hour, min, sec, int(milli))
  4798     def any2i(self, pkt, val):
  4799         if type(val) is str:
  4800             hmsms = self.re_hmsm.match(val)
  4801             if hmsms:
  4802                 h,_,m,_,s,_,ms = hmsms = hmsms.groups()
  4803                 ms = int(((ms or "")+"000")[:3])
  4804                 val = ((int(h)*60+int(m or 0))*60+int(s or 0))*1000+ms
  4805             else:
  4806                 val = 0
  4807         elif val is None:
  4808             val = int((time.time()%(24*60*60))*1000)
  4809         return val
  4810 
  4811 class FloatField(BitField):
  4812     def getfield(self, pkt, s):
  4813         s,b = BitField.getfield(self, pkt, s)
  4814         
  4815         # fraction point between bits 15 and 16.
  4816         sec = b >> 16
  4817         frac = b & (1L << (32+1)) - 1
  4818         frac /= 65536.0
  4819         b = sec+frac
  4820         return s,b    
  4821 
  4822 class Dot11SCField(LEShortField):
  4823     def is_applicable(self, pkt):
  4824         return pkt.type != 1 # control frame
  4825     def addfield(self, pkt, s, val):
  4826         if self.is_applicable(pkt):
  4827             return LEShortField.addfield(self, pkt, s, val)
  4828         else:
  4829             return s
  4830     def getfield(self, pkt, s):
  4831         if self.is_applicable(pkt):
  4832             return LEShortField.getfield(self, pkt, s)
  4833         else:
  4834             return s,None
  4835 
  4836 #####################
  4837 #### ASN1 Fields ####
  4838 #####################
  4839 
  4840 class ASN1F_badsequence(Exception):
  4841     pass
  4842 
  4843 class ASN1F_element:
  4844     pass
  4845 
  4846 class ASN1F_optionnal(ASN1F_element):
  4847     def __init__(self, field):
  4848         self._field=field
  4849     def __getattr__(self, attr):
  4850         return getattr(self._field,attr)
  4851     def dissect(self,pkt,s):
  4852         try:
  4853             return self._field.dissect(pkt,s)
  4854         except ASN1F_badsequence:
  4855             self._field.set_val(pkt,None)
  4856             return s
  4857         except BER_Decoding_Error:
  4858             self._field.set_val(pkt,None)
  4859             return s
  4860     def build(self, pkt):
  4861         if self._field.is_empty(pkt):
  4862             return ""
  4863         return self._field.build(pkt)
  4864 
  4865 class ASN1F_field(ASN1F_element):
  4866     holds_packets=0
  4867     islist=0
  4868 
  4869     ASN1_tag = ASN1_Class_UNIVERSAL.ANY
  4870     context=ASN1_Class_UNIVERSAL
  4871     
  4872     def __init__(self, name, default, context=None):
  4873         if context is not None:
  4874             self.context = context
  4875         self.name = name
  4876         self.default = default
  4877 
  4878     def i2repr(self, pkt, x):
  4879         if x is None:
  4880             x = 0
  4881         return repr(x)
  4882     def i2h(self, pkt, x):
  4883         return x
  4884     def any2i(self, pkt, x):
  4885         return x
  4886     def m2i(self, pkt, x):
  4887         return self.ASN1_tag.get_codec(pkt.ASN1_codec).safedec(x, context=self.context)
  4888     def i2m(self, pkt, x):
  4889         if x is None:
  4890             x = 0
  4891         if isinstance(x, ASN1_Object):
  4892             if ( self.ASN1_tag == ASN1_Class_UNIVERSAL.ANY
  4893                  or x.tag == ASN1_Class_UNIVERSAL.RAW
  4894                  or x.tag == ASN1_Class_UNIVERSAL.ERROR
  4895                  or self.ASN1_tag == x.tag ):
  4896                 return x.enc(pkt.ASN1_codec)
  4897             else:
  4898                 raise ASN1_Error("Encoding Error: got %r instead of an %r for field [%s]" % (x, self.ASN1_tag, self.name))
  4899         return self.ASN1_tag.get_codec(pkt.ASN1_codec).enc(x)
  4900 
  4901     def do_copy(self, x):
  4902         if hasattr(x, "copy"):
  4903             return x.copy()
  4904         if type(x) is list:
  4905             x = x[:]
  4906             for i in xrange(len(x)):
  4907                 if isinstance(x[i], Packet):
  4908                     x[i] = x[i].copy()
  4909         return x
  4910 
  4911     def build(self, pkt):
  4912         return self.i2m(pkt, getattr(pkt, self.name))
  4913 
  4914     def set_val(self, pkt, val):
  4915         setattr(pkt, self.name, val)
  4916     def is_empty(self, pkt):
  4917         return getattr(pkt,self.name) is None
  4918     
  4919     def dissect(self, pkt, s):
  4920         v,s = self.m2i(pkt, s)
  4921         self.set_val(pkt, v)
  4922         return s
  4923 
  4924     def get_fields_list(self):
  4925         return [self]
  4926 
  4927     def __hash__(self):
  4928         return hash(self.name)
  4929     def __str__(self):
  4930         return self.name
  4931     def __eq__(self, other):
  4932         return self.name == other
  4933     def __repr__(self):
  4934         return self.name
  4935     def randval(self):
  4936         return RandInt()
  4937 
  4938 
  4939 class ASN1F_INTEGER(ASN1F_field):
  4940     ASN1_tag= ASN1_Class_UNIVERSAL.INTEGER
  4941     def randval(self):
  4942         return RandNum(-2**64, 2**64-1)
  4943 
  4944 class ASN1F_NULL(ASN1F_INTEGER):
  4945     ASN1_tag= ASN1_Class_UNIVERSAL.NULL
  4946 
  4947 class ASN1F_enum_INTEGER(ASN1F_INTEGER):
  4948     def __init__(self, name, default, enum):
  4949         ASN1F_INTEGER.__init__(self, name, default)
  4950         i2s = self.i2s = {}
  4951         s2i = self.s2i = {}
  4952         if type(enum) is list:
  4953             keys = xrange(len(enum))
  4954         else:
  4955             keys = enum.keys()
  4956         if filter(lambda x: type(x) is str, keys):
  4957             i2s,s2i = s2i,i2s
  4958         for k in keys:
  4959             i2s[k] = enum[k]
  4960             s2i[enum[k]] = k
  4961     def any2i_one(self, pkt, x):
  4962         if type(x) is str:
  4963             x = self.s2i[x]
  4964         return x
  4965     def i2repr_one(self, pkt, x):
  4966         return self.i2s.get(x, repr(x))
  4967     
  4968     def any2i(self, pkt, x):
  4969         if type(x) is list:
  4970             return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x)
  4971         else:
  4972             return self.any2i_one(pkt,x)        
  4973     def i2repr(self, pkt, x):
  4974         if type(x) is list:
  4975             return map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x)
  4976         else:
  4977             return self.i2repr_one(pkt,x)
  4978 
  4979 class ASN1F_STRING(ASN1F_field):
  4980     ASN1_tag = ASN1_Class_UNIVERSAL.STRING
  4981     def randval(self):
  4982         return RandString(RandNum(0, 1000))
  4983 
  4984 class ASN1F_PRINTABLE_STRING(ASN1F_STRING):
  4985     ASN1_tag = ASN1_Class_UNIVERSAL.PRINTABLE_STRING
  4986 
  4987 class ASN1F_BIT_STRING(ASN1F_STRING):
  4988     ASN1_tag = ASN1_Class_UNIVERSAL.BIT_STRING
  4989 
  4990 class ASN1F_UTC_TIME(ASN1F_STRING):
  4991     ASN1_tag = ASN1_Class_UNIVERSAL.UTC_TIME
  4992 
  4993 class ASN1F_OID(ASN1F_field):
  4994     ASN1_tag = ASN1_Class_UNIVERSAL.OID
  4995     def randval(self):
  4996         return RandOID()
  4997 
  4998 class ASN1F_SEQUENCE(ASN1F_field):
  4999     ASN1_tag = ASN1_Class_UNIVERSAL.SEQUENCE
  5000     def __init__(self, *seq, **kargs):
  5001         if "ASN1_tag" in kargs:
  5002             self.ASN1_tag = kargs["ASN1_tag"]
  5003         self.seq = seq
  5004     def __repr__(self):
  5005         return "<%s%r>" % (self.__class__.__name__,self.seq,)
  5006     def set_val(self, pkt, val):
  5007         for f in self.seq:
  5008             f.set_val(pkt,val)
  5009     def is_empty(self, pkt):
  5010         for f in self.seq:
  5011             if not f.is_empty(pkt):
  5012                 return False
  5013         return True
  5014     def get_fields_list(self):
  5015         return reduce(lambda x,y: x+y.get_fields_list(), self.seq, [])
  5016     def build(self, pkt):
  5017         s = reduce(lambda x,y: x+y.build(pkt), self.seq, "")
  5018         return self.i2m(pkt, s)
  5019     def dissect(self, pkt, s):
  5020         codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
  5021         try:
  5022             i,s,remain = codec.check_type_check_len(s)
  5023             for obj in self.seq:
  5024                 s = obj.dissect(pkt,s)
  5025             if s:
  5026                 warning("Too many bytes to decode sequence: [%r]" % s) # XXX not reversible!
  5027             return remain
  5028         except ASN1_Error,e:
  5029             raise ASN1F_badsequence(e)
  5030 
  5031 class ASN1F_SET(ASN1F_SEQUENCE):
  5032     ASN1_tag = ASN1_Class_UNIVERSAL.SET
  5033 
  5034 class ASN1F_SEQUENCE_OF(ASN1F_SEQUENCE):
  5035     holds_packets = 1
  5036     islist = 1
  5037     def __init__(self, name, default, asn1pkt, ASN1_tag=0x30):
  5038         self.asn1pkt = asn1pkt
  5039         self.tag = chr(ASN1_tag)
  5040         self.name = name
  5041         self.default = default
  5042     def i2repr(self, pkt, i):
  5043         if i is None:
  5044             return []
  5045         return i
  5046     def get_fields_list(self):
  5047         return [self]
  5048     def set_val(self, pkt, val):
  5049         ASN1F_field.set_val(self, pkt, val)
  5050     def is_empty(self, pkt):
  5051         return ASN1F_field.is_empty(self, pkt)
  5052     def build(self, pkt):
  5053         val = getattr(pkt, self.name)
  5054         if isinstance(val, ASN1_Object) and val.tag == ASN1_Class_UNIVERSAL.RAW:
  5055             s = val
  5056         elif val is None:
  5057             s = ""
  5058         else:
  5059             s = "".join(map(str, val ))
  5060         return self.i2m(pkt, s)
  5061     def set_val(self, pkt, val):
  5062         ASN1F_field.set_val(self, pkt, val)
  5063     def dissect(self, pkt, s):
  5064         codec = self.ASN1_tag.get_codec(pkt.ASN1_codec)
  5065         i,s1,remain = codec.check_type_check_len(s)
  5066         lst = []
  5067         while s1:
  5068             try:
  5069                 p = self.asn1pkt(s1)
  5070             except ASN1F_badsequence,e:
  5071                 lst.append(Raw(s1))
  5072                 break
  5073             lst.append(p)
  5074             if Raw in p:
  5075                 s1 = p[Raw].load
  5076                 del(p[Raw].underlayer.payload)
  5077             else:
  5078                 break
  5079         self.set_val(pkt, lst)
  5080         return remain
  5081     def randval(self):
  5082         return fuzz(self.asn1pkt())
  5083     def __repr__(self):
  5084         return "<%s %s>" % (self.__class__.__name__,self.name)
  5085 
  5086 class ASN1F_PACKET(ASN1F_field):
  5087     holds_packets = 1
  5088     def __init__(self, name, default, cls):
  5089         ASN1_field.__init__(self, name, default)
  5090         self.cls = cls
  5091     def i2m(self, pkt, x):
  5092         if x is None:
  5093             x = ""
  5094         return str(x)
  5095     def extract_packet(self, cls, x):
  5096         try:
  5097             c = cls(x)
  5098         except ASN1F_badsequence:
  5099             c = Raw(x)
  5100         cpad = c[Padding]
  5101         x = ""
  5102         if cpad is not None:
  5103             x = cpad.load
  5104             del(cpad.underlayer.payload)
  5105         return c,x
  5106     def m2i(self, pkt, x):
  5107         return self.extract_packet(self.cls, x)
  5108 
  5109 
  5110 class ASN1F_CHOICE(ASN1F_PACKET):
  5111     ASN1_tag = ASN1_Class_UNIVERSAL.NONE
  5112     def __init__(self, name, default, *args):
  5113         self.name=name
  5114         self.choice = {}
  5115         for p in args:
  5116             self.choice[p.ASN1_root.ASN1_tag] = p
  5117 #        self.context=context
  5118         self.default=default
  5119     def m2i(self, pkt, x):
  5120         if len(x) == 0:
  5121             return Raw(),""
  5122             raise ASN1_Error("ASN1F_CHOICE: got empty string")
  5123         if ord(x[0]) not in self.choice:
  5124             return Raw(x),"" # XXX return RawASN1 packet ? Raise error 
  5125             raise ASN1_Error("Decoding Error: choice [%i] not found in %r" % (ord(x[0]), self.choice.keys()))
  5126 
  5127         z = ASN1F_PACKET.extract_packet(self, self.choice[ord(x[0])], x)
  5128         return z
  5129     def randval(self):
  5130         return RandChoice(*map(lambda x:fuzz(x()), self.choice.values()))
  5131             
  5132     
  5133 
  5134 ###########################
  5135 ## Packet abstract class ##
  5136 ###########################
  5137 
  5138 class Packet_metaclass(type):
  5139     def __new__(cls, name, bases, dct):
  5140         newcls = super(Packet_metaclass, cls).__new__(cls, name, bases, dct)
  5141         for f in newcls.fields_desc:
  5142             f.register_owner(newcls)
  5143         return newcls
  5144     def __getattr__(self, attr):
  5145         for k in self.fields_desc:
  5146             if k.name == attr:
  5147                 return k
  5148         raise AttributeError(attr)
  5149 
  5150 class NewDefaultValues(Packet_metaclass):
  5151     """NewDefaultValues metaclass. Example usage:
  5152     class MyPacket(Packet):
  5153         fields_desc = [ StrField("my_field", "my default value"),  ]
  5154         
  5155     class MyPacket_variant(MyPacket):
  5156         __metaclass__ = NewDefaultValues
  5157         my_field = "my new default value"
  5158     """    
  5159     def __new__(cls, name, bases, dct):
  5160         fields = None
  5161         for b in bases:
  5162             if hasattr(b,"fields_desc"):
  5163                 fields = b.fields_desc
  5164                 break
  5165         if fields is None:
  5166             raise Scapy_Exception("No fields_desc in superclasses")
  5167 
  5168         new_fields = []
  5169         for f in fields:
  5170             if f.name in dct:
  5171                 f = f.copy()
  5172                 f.default = dct[f.name]
  5173                 del(dct[f.name])
  5174             new_fields.append(f)
  5175         dct["fields_desc"] = new_fields
  5176         return super(NewDefaultValues, cls).__new__(cls, name, bases, dct)
  5177 
  5178 class Packet(Gen):
  5179     __metaclass__ = Packet_metaclass
  5180     name=None
  5181 
  5182     fields_desc = []
  5183 
  5184     aliastypes = []
  5185     overload_fields = {}
  5186 
  5187     underlayer = None
  5188 
  5189     payload_guess = []
  5190     initialized = 0
  5191     show_indent=1
  5192     explicit = 0
  5193 
  5194     @classmethod
  5195     def from_hexcap(cls):
  5196         return cls(import_hexcap())
  5197 
  5198     @classmethod
  5199     def upper_bonds(self):
  5200         for fval,upper in self.payload_guess:
  5201             print "%-20s  %s" % (upper.__name__, ", ".join("%-12s" % ("%s=%r"%i) for i in fval.iteritems()))
  5202 
  5203     @classmethod
  5204     def lower_bonds(self):
  5205         for lower,fval in self.overload_fields.iteritems():
  5206             print "%-20s  %s" % (lower.__name__, ", ".join("%-12s" % ("%s=%r"%i) for i in fval.iteritems()))
  5207 
  5208     def __init__(self, _pkt="", post_transform=None, _internal=0, _underlayer=None, **fields):
  5209         self.time  = time.time()
  5210         self.sent_time = 0
  5211         if self.name is None:
  5212             self.name = self.__class__.__name__
  5213         self.aliastypes = [ self.__class__ ] + self.aliastypes
  5214         self.default_fields = {}
  5215         self.overloaded_fields = {}
  5216         self.fields={}
  5217         self.fieldtype={}
  5218         self.packetfields=[]
  5219         self.__dict__["payload"] = NoPayload()
  5220         self.init_fields()
  5221         self.underlayer = _underlayer
  5222         self.initialized = 1
  5223         if _pkt:
  5224             self.dissect(_pkt)
  5225             if not _internal:
  5226                 self.dissection_done(self)
  5227         for f in fields.keys():
  5228             self.fields[f] = self.get_field(f).any2i(self,fields[f])
  5229         if type(post_transform) is list:
  5230             self.post_transforms = post_transform
  5231         elif post_transform is None:
  5232             self.post_transforms = []
  5233         else:
  5234             self.post_transforms = [post_transform]
  5235 
  5236     def init_fields(self):
  5237         self.do_init_fields(self.fields_desc)
  5238 
  5239     def do_init_fields(self, flist):
  5240         for f in flist:
  5241             self.default_fields[f.name] = f.default
  5242             self.fieldtype[f.name] = f
  5243             if f.holds_packets:
  5244                 self.packetfields.append(f)
  5245             
  5246     def dissection_done(self,pkt):
  5247         """DEV: will be called after a dissection is completed"""
  5248         self.post_dissection(pkt)
  5249         self.payload.dissection_done(pkt)
  5250         
  5251     def post_dissection(self, pkt):
  5252         """DEV: is called after the dissection of the whole packet"""
  5253         pass
  5254 
  5255     def get_field(self, fld):
  5256         """DEV: returns the field instance from the name of the field"""
  5257         return self.fieldtype[fld]
  5258         
  5259     def add_payload(self, payload):
  5260         if payload is None:
  5261             return
  5262         elif not isinstance(self.payload, NoPayload):
  5263             self.payload.add_payload(payload)
  5264         else:
  5265             if isinstance(payload, Packet):
  5266                 self.__dict__["payload"] = payload
  5267                 payload.add_underlayer(self)
  5268                 for t in self.aliastypes:
  5269                     if payload.overload_fields.has_key(t):
  5270                         self.overloaded_fields = payload.overload_fields[t]
  5271                         break
  5272             elif type(payload) is str:
  5273                 self.__dict__["payload"] = Raw(load=payload)
  5274             else:
  5275                 raise TypeError("payload must be either 'Packet' or 'str', not [%s]" % repr(payload))
  5276     def remove_payload(self):
  5277         self.payload.remove_underlayer(self)
  5278         self.__dict__["payload"] = NoPayload()
  5279         self.overloaded_fields = {}
  5280     def add_underlayer(self, underlayer):
  5281         self.underlayer = underlayer
  5282     def remove_underlayer(self,other):
  5283         self.underlayer = None
  5284     def copy(self):
  5285         """Returns a deep copy of the instance."""
  5286         clone = self.__class__()
  5287         clone.fields = self.fields.copy()
  5288         for k in clone.fields:
  5289             clone.fields[k]=self.get_field(k).do_copy(clone.fields[k])
  5290         clone.default_fields = self.default_fields.copy()
  5291         clone.overloaded_fields = self.overloaded_fields.copy()
  5292         clone.overload_fields = self.overload_fields.copy()
  5293         clone.underlayer=self.underlayer
  5294         clone.explicit=self.explicit
  5295         clone.post_transforms=self.post_transforms[:]
  5296         clone.__dict__["payload"] = self.payload.copy()
  5297         clone.payload.add_underlayer(clone)
  5298         return clone
  5299 
  5300     def getfieldval(self, attr):
  5301         if attr in self.fields:
  5302             return self.fields[attr]
  5303         if attr in self.overloaded_fields:
  5304             return self.overloaded_fields[attr]
  5305         if attr in self.default_fields:
  5306             return self.default_fields[attr]
  5307         return self.payload.getfieldval(attr)
  5308     
  5309     def getfield_and_val(self, attr):
  5310         if attr in self.fields:
  5311             return self.get_field(attr),self.fields[attr]
  5312         if attr in self.overloaded_fields:
  5313             return self.get_field(attr),self.overloaded_fields[attr]
  5314         if attr in self.default_fields:
  5315             return self.get_field(attr),self.default_fields[attr]
  5316         return self.payload.getfield_and_val(attr)
  5317     
  5318     def __getattr__(self, attr):
  5319         if self.initialized:
  5320             fld,v = self.getfield_and_val(attr)
  5321             if fld is not None:
  5322                 return fld.i2h(self, v)
  5323             return v
  5324         raise AttributeError(attr)
  5325 
  5326     def setfieldval(self, attr, val):
  5327         if self.default_fields.has_key(attr):
  5328             fld = self.get_field(attr)
  5329             if fld is None:
  5330                 any2i = lambda x,y: y
  5331             else:
  5332                 any2i = fld.any2i
  5333             self.fields[attr] = any2i(self, val)
  5334             self.explicit=0
  5335         elif attr == "payload":
  5336             self.remove_payload()
  5337             self.add_payload(val)
  5338         else:
  5339             self.payload.setfieldval(attr,val)
  5340 
  5341     def __setattr__(self, attr, val):
  5342         if self.initialized:
  5343             try:
  5344                 self.setfieldval(attr,val)
  5345             except AttributeError:
  5346                 pass
  5347             else:
  5348                 return
  5349         self.__dict__[attr] = val
  5350 
  5351     def delfieldval(self, attr):
  5352         if self.fields.has_key(attr):
  5353             del(self.fields[attr])
  5354             self.explicit=0 # in case a default value must be explicited
  5355         elif self.default_fields.has_key(attr):
  5356             pass
  5357         elif attr == "payload":
  5358             self.remove_payload()
  5359         else:
  5360             self.payload.delfieldval(attr)
  5361 
  5362     def __delattr__(self, attr):
  5363         if self.initialized:
  5364             try:
  5365                 self.delfieldval(attr)
  5366             except AttributeError:
  5367                 pass
  5368             else:
  5369                 return
  5370         if self.__dict__.has_key(attr):
  5371             del(self.__dict__[attr])
  5372         else:
  5373             raise AttributeError(attr)
  5374             
  5375     def __repr__(self):
  5376         s = ""
  5377         ct = conf.color_theme
  5378         for f in self.fields_desc:
  5379             if isinstance(f, ConditionalField) and not f._evalcond(self):
  5380                 continue
  5381             if f.name in self.fields:
  5382                 val = f.i2repr(self, self.fields[f.name])
  5383             elif f.name in self.overloaded_fields:
  5384                 val =  f.i2repr(self, self.overloaded_fields[f.name])
  5385             else:
  5386                 continue
  5387             if isinstance(f, Emph):
  5388                 ncol = ct.emph_field_name
  5389                 vcol = ct.emph_field_value
  5390             else:
  5391                 ncol = ct.field_name
  5392                 vcol = ct.field_value
  5393 
  5394                 
  5395             s += " %s%s%s" % (ncol(f.name),
  5396                               ct.punct("="),
  5397                               vcol(val))
  5398         return "%s%s %s %s%s%s"% (ct.punct("<"),
  5399                                   ct.layer_name(self.__class__.__name__),
  5400                                   s,
  5401                                   ct.punct("|"),
  5402                                   repr(self.payload),
  5403                                   ct.punct(">"))
  5404     def __str__(self):
  5405         return self.build()
  5406     def __div__(self, other):
  5407         if isinstance(other, Packet):
  5408             cloneA = self.copy()
  5409             cloneB = other.copy()
  5410             cloneA.add_payload(cloneB)
  5411             return cloneA
  5412         elif type(other) is str:
  5413             return self/Raw(load=other)
  5414         else:
  5415             return other.__rdiv__(self)
  5416     def __rdiv__(self, other):
  5417         if type(other) is str:
  5418             return Raw(load=other)/self
  5419         else:
  5420             raise TypeError
  5421     def __mul__(self, other):
  5422         if type(other) is int:
  5423             return  [self]*other
  5424         else:
  5425             raise TypeError
  5426     def __rmul__(self,other):
  5427         return self.__mul__(other)
  5428     
  5429     def __nonzero__(self):
  5430         return True
  5431     def __len__(self):
  5432         return len(self.__str__())
  5433     def do_build(self):
  5434         p=""
  5435         for f in self.fields_desc:
  5436             p = f.addfield(self, p, self.getfieldval(f.name))
  5437         return p
  5438     
  5439     def post_build(self, pkt, pay):
  5440         """DEV: called right after the current layer is build."""
  5441         return pkt+pay
  5442 
  5443     def build_payload(self):
  5444         return self.payload.build(internal=1)
  5445 
  5446     def build(self,internal=0):
  5447         if not self.explicit:
  5448             self = self.__iter__().next()
  5449         pkt = self.do_build()
  5450         for t in self.post_transforms:
  5451             pkt = t(pkt)
  5452         pay = self.build_payload()
  5453         try:
  5454             p = self.post_build(pkt,pay)
  5455         except TypeError:
  5456             log_runtime.error("API changed! post_build() now takes 2 arguments. Compatibility is only assured for a short transition time")
  5457             p = self.post_build(pkt+pay)
  5458         if not internal:
  5459             pad = self.payload.getlayer(Padding) 
  5460             if pad: 
  5461                 p += pad.build()
  5462             p = self.build_done(p)
  5463         return p
  5464 
  5465     def build_done(self, p):
  5466         return self.payload.build_done(p)
  5467 
  5468     def do_build_ps(self):
  5469         p=""
  5470         pl = []
  5471         q=""
  5472         for f in self.fields_desc:
  5473             p = f.addfield(self, p, self.getfieldval(f.name) )
  5474             if type(p) is str:
  5475                 r = p[len(q):]
  5476                 q = p
  5477             else:
  5478                 r = ""
  5479             pl.append( (f, f.i2repr(self,self.getfieldval(f.name)), r) )
  5480             
  5481         pkt,lst = self.payload.build_ps(internal=1)
  5482         p += pkt
  5483         lst.append( (self, pl) )
  5484         
  5485         return p,lst
  5486     
  5487     def build_ps(self,internal=0):
  5488         p,lst = self.do_build_ps()
  5489 #        if not internal:
  5490 #            pkt = self
  5491 #            while pkt.haslayer(Padding):
  5492 #                pkt = pkt.getlayer(Padding)
  5493 #                lst.append( (pkt, [ ("loakjkjd", pkt.load, pkt.load) ] ) )
  5494 #                p += pkt.load
  5495 #                pkt = pkt.payload
  5496         return p,lst
  5497 
  5498 
  5499     def psdump(self, filename=None, **kargs):
  5500         """psdump(filename=None, layer_shift=0, rebuild=1)
  5501 Creates an EPS file describing a packet. If filename is not provided a temporary file is created and gs is called."""
  5502         canvas = self.canvas_dump(**kargs)
  5503         if filename is None:
  5504             fname = "/tmp/scapy.%i"%os.getpid()
  5505             canvas.writeEPSfile(fname)
  5506             os.system("%s '%s.eps' &" % (conf.prog.psreader,fname))
  5507         else:
  5508             canvas.writeEPSfile(filename)
  5509 
  5510     def pdfdump(self, filename=None, **kargs):
  5511         """pdfdump(filename=None, layer_shift=0, rebuild=1)
  5512         Creates a PDF file describing a packet. If filename is not provided a temporary file is created and xpdf is called."""
  5513         canvas = self.canvas_dump(**kargs)
  5514         if filename is None:
  5515             fname = "/tmp/scapy.%i"%os.getpid()
  5516             canvas.writePDFfile(fname)
  5517             os.system("%s '%s.pdf' &" % (conf.prog.pdfreader,fname))
  5518         else:
  5519             canvas.writePDFfile(filename)
  5520 
  5521         
  5522     def canvas_dump(self, layer_shift=0, rebuild=1):
  5523         canvas = pyx.canvas.canvas()
  5524         if rebuild:
  5525             p,t = self.__class__(str(self)).build_ps()
  5526         else:
  5527             p,t = self.build_ps()
  5528         YTXT=len(t)
  5529         for n,l in t:
  5530             YTXT += len(l)
  5531         YTXT = float(YTXT)
  5532         YDUMP=YTXT
  5533 
  5534         XSTART = 1
  5535         XDSTART = 10
  5536         y = 0.0
  5537         yd = 0.0
  5538         xd = 0 
  5539         XMUL= 0.55
  5540         YMUL = 0.4
  5541     
  5542         backcolor=colgen(0.6, 0.8, 1.0, trans=pyx.color.rgb)
  5543         forecolor=colgen(0.2, 0.5, 0.8, trans=pyx.color.rgb)
  5544 #        backcolor=makecol(0.376, 0.729, 0.525, 1.0)
  5545         
  5546         
  5547         def hexstr(x):
  5548             s = []
  5549             for c in x:
  5550                 s.append("%02x" % ord(c))
  5551             return " ".join(s)
  5552 
  5553                 
  5554         def make_dump_txt(x,y,txt):
  5555             return pyx.text.text(XDSTART+x*XMUL, (YDUMP-y)*YMUL, r"\tt{%s}"%hexstr(txt), [pyx.text.size.Large])
  5556 
  5557         def make_box(o):
  5558             return pyx.box.rect(o.left(), o.bottom(), o.width(), o.height(), relcenter=(0.5,0.5))
  5559 
  5560         def make_frame(lst):
  5561             if len(lst) == 1:
  5562                 b = lst[0].bbox()
  5563                 b.enlarge(pyx.unit.u_pt)
  5564                 return b.path()
  5565             else:
  5566                 fb = lst[0].bbox()
  5567                 fb.enlarge(pyx.unit.u_pt)
  5568                 lb = lst[-1].bbox()
  5569                 lb.enlarge(pyx.unit.u_pt)
  5570                 if len(lst) == 2 and fb.left() > lb.right():
  5571                     return pyx.path.path(pyx.path.moveto(fb.right(), fb.top()),
  5572                                          pyx.path.lineto(fb.left(), fb.top()),
  5573                                          pyx.path.lineto(fb.left(), fb.bottom()),
  5574                                          pyx.path.lineto(fb.right(), fb.bottom()),
  5575                                          pyx.path.moveto(lb.left(), lb.top()),
  5576                                          pyx.path.lineto(lb.right(), lb.top()),
  5577                                          pyx.path.lineto(lb.right(), lb.bottom()),
  5578                                          pyx.path.lineto(lb.left(), lb.bottom()))
  5579                 else:
  5580                     # XXX
  5581                     gb = lst[1].bbox()
  5582                     if gb != lb:
  5583                         gb.enlarge(pyx.unit.u_pt)
  5584                     kb = lst[-2].bbox()
  5585                     if kb != gb and kb != lb:
  5586                         kb.enlarge(pyx.unit.u_pt)
  5587                     return pyx.path.path(pyx.path.moveto(fb.left(), fb.top()),
  5588                                          pyx.path.lineto(fb.right(), fb.top()),
  5589                                          pyx.path.lineto(fb.right(), kb.bottom()),
  5590                                          pyx.path.lineto(lb.right(), kb.bottom()),
  5591                                          pyx.path.lineto(lb.right(), lb.bottom()),
  5592                                          pyx.path.lineto(lb.left(), lb.bottom()),
  5593                                          pyx.path.lineto(lb.left(), gb.top()),
  5594                                          pyx.path.lineto(fb.left(), gb.top()),
  5595                                          pyx.path.closepath(),)
  5596                                          
  5597 
  5598         def make_dump(s, shift=0, y=0, col=None, bkcol=None, larg=16):
  5599             c = pyx.canvas.canvas()
  5600             tlist = []
  5601             while s:
  5602                 dmp,s = s[:larg-shift],s[larg-shift:]
  5603                 txt = make_dump_txt(shift, y, dmp)
  5604                 tlist.append(txt)
  5605                 shift += len(dmp)
  5606                 if shift >= 16:
  5607                     shift = 0
  5608                     y += 1
  5609             if col is None:
  5610                 col = pyx.color.rgb.red
  5611             if bkcol is None:
  5612                 col = pyx.color.rgb.white
  5613             c.stroke(make_frame(tlist),[col,pyx.deco.filled([bkcol]),pyx.style.linewidth.Thick])
  5614             for txt in tlist:
  5615                 c.insert(txt)
  5616             return c, tlist[-1].bbox(), shift, y
  5617                             
  5618 
  5619         last_shift,last_y=0,0.0
  5620         while t:
  5621             bkcol = backcolor.next()
  5622             proto,fields = t.pop()
  5623             y += 0.5
  5624             pt = pyx.text.text(XSTART, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % proto.name, [ pyx.text.size.Large])
  5625             y += 1
  5626             ptbb=pt.bbox()
  5627             ptbb.enlarge(pyx.unit.u_pt*2)
  5628             canvas.stroke(ptbb.path(),[pyx.color.rgb.black, pyx.deco.filled([bkcol])])
  5629             canvas.insert(pt)
  5630             for fname, fval, fdump in fields:
  5631                 col = forecolor.next()
  5632                 ft = pyx.text.text(XSTART, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(fname.name))
  5633                 if fval is not None:
  5634                     if len(fval) > 18:
  5635                         fval = fval[:18]+"[...]"
  5636                 else:
  5637                     fval=""
  5638                 vt = pyx.text.text(XSTART+3, (YTXT-y)*YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(fval))
  5639                 y += 1.0
  5640                 if fdump:
  5641                     dt,target,last_shift,last_y = make_dump(fdump, last_shift, last_y, col, bkcol)
  5642 
  5643                     dtb = dt.bbox()
  5644                     dtb=target
  5645                     vtb = vt.bbox()
  5646                     bxvt = make_box(vtb)
  5647                     bxdt = make_box(dtb)
  5648                     dtb.enlarge(pyx.unit.u_pt)
  5649                     try:
  5650                         if yd < 0:
  5651                             cnx = pyx.connector.curve(bxvt,bxdt,absangle1=0, absangle2=-90)
  5652                         else:
  5653                             cnx = pyx.connector.curve(bxvt,bxdt,absangle1=0, absangle2=90)
  5654                     except:
  5655                         pass
  5656                     else:
  5657                         canvas.stroke(cnx,[pyx.style.linewidth.thin,pyx.deco.earrow.small,col])
  5658                         
  5659                     canvas.insert(dt)
  5660                 
  5661                 canvas.insert(ft)
  5662                 canvas.insert(vt)
  5663             last_y += layer_shift
  5664     
  5665         return canvas
  5666 
  5667 
  5668 
  5669     def extract_padding(self, s):
  5670         """DEV: to be overloaded to extract current layer's padding. Return a couple of strings (actual layer, padding)"""
  5671         return s,None
  5672 
  5673     def post_dissect(self, s):
  5674         """DEV: is called right after the current layer has been dissected"""
  5675         return s
  5676 
  5677     def pre_dissect(self, s):
  5678         """DEV: is called right before the current layer is dissected"""
  5679         return s
  5680 
  5681     def do_dissect(self, s):
  5682         flist = self.fields_desc[:]
  5683         flist.reverse()
  5684         while s and flist:
  5685             f = flist.pop()
  5686             s,fval = f.getfield(self, s)
  5687             self.fields[f.name] = fval
  5688             
  5689         return s
  5690 
  5691     def do_dissect_payload(self, s):
  5692         if s:
  5693             cls = self.guess_payload_class(s)
  5694             try:
  5695                 p = cls(s, _internal=1, _underlayer=self)
  5696             except KeyboardInterrupt:
  5697                 raise
  5698             except:
  5699                 if conf.debug_dissector:
  5700                     if isinstance(cls,type) and issubclass(cls,Packet):
  5701                         log_runtime.error("%s dissector failed" % cls.name)
  5702                     else:
  5703                         log_runtime.error("%s.guess_payload_class() returned [%s]" % (self.__class__.__name__,repr(cls)))
  5704                     if cls is not None:
  5705                         raise
  5706                 p = Raw(s, _internal=1, _underlayer=self)
  5707             self.add_payload(p)
  5708 
  5709     def dissect(self, s):
  5710         s = self.pre_dissect(s)
  5711 
  5712         s = self.do_dissect(s)
  5713 
  5714         s = self.post_dissect(s)
  5715             
  5716         payl,pad = self.extract_padding(s)
  5717         self.do_dissect_payload(payl)
  5718         if pad and conf.padding:
  5719             self.add_payload(Padding(pad))
  5720 
  5721 
  5722     def guess_payload_class(self, payload):
  5723         """DEV: Guesses the next payload class from layer bonds. Can be overloaded to use a different mechanism."""
  5724         for t in self.aliastypes:
  5725             for fval, cls in t.payload_guess:
  5726                 ok = 1
  5727                 for k in fval.keys():
  5728                     if not hasattr(self, k) or fval[k] != self.getfieldval(k):
  5729                         ok = 0
  5730                         break
  5731                 if ok:
  5732                     return cls
  5733         return self.default_payload_class(payload)
  5734     
  5735     def default_payload_class(self, payload):
  5736         """DEV: Returns the default payload class if nothing has been found by the guess_payload_class() method."""
  5737         return Raw
  5738 
  5739     def hide_defaults(self):
  5740         """Removes fields' values that are the same as default values."""
  5741         for k in self.fields.keys():
  5742             if self.default_fields.has_key(k):
  5743                 if self.default_fields[k] == self.fields[k]:
  5744                     del(self.fields[k])
  5745         self.payload.hide_defaults()
  5746             
  5747     def clone_with(self, payload=None, **kargs):
  5748         pkt = self.__class__()
  5749         pkt.explicit = 1
  5750         pkt.fields = kargs
  5751         pkt.time = self.time
  5752         pkt.underlayer = self.underlayer
  5753         pkt.overload_fields = self.overload_fields.copy()
  5754         pkt.post_transforms = self.post_transforms
  5755         if payload is not None:
  5756             pkt.add_payload(payload)
  5757         return pkt
  5758         
  5759 
  5760     def __iter__(self):
  5761         def loop(todo, done, self=self):
  5762             if todo:
  5763                 eltname = todo.pop()
  5764                 elt = self.getfieldval(eltname)
  5765                 if not isinstance(elt, Gen):
  5766                     if self.get_field(eltname).islist:
  5767                         elt = SetGen([elt])
  5768                     else:
  5769                         elt = SetGen(elt)
  5770                 for e in elt:
  5771                     done[eltname]=e
  5772                     for x in loop(todo[:], done):
  5773                         yield x
  5774             else:
  5775                 if isinstance(self.payload,NoPayload):
  5776                     payloads = [None]
  5777                 else:
  5778                     payloads = self.payload
  5779                 for payl in payloads:
  5780                     done2=done.copy()
  5781                     for k in done2:
  5782                         if isinstance(done2[k], VolatileValue):
  5783                             done2[k] = done2[k]._fix()
  5784                     pkt = self.clone_with(payload=payl, **done2)
  5785                     yield pkt
  5786 
  5787         if self.explicit:
  5788             todo = []
  5789             done = self.fields
  5790         else:
  5791             todo = [ k for (k,v) in itertools.chain(self.default_fields.iteritems(),
  5792                                                     self.overloaded_fields.iteritems())
  5793                      if isinstance(v, VolatileValue) ] + self.fields.keys()
  5794             done = {}
  5795         return loop(todo, done)
  5796 
  5797     def __gt__(self, other):
  5798         """True if other is an answer from self (self ==> other)."""
  5799         if isinstance(other, Packet):
  5800             return other < self
  5801         elif type(other) is str:
  5802             return 1
  5803         else:
  5804             raise TypeError((self, other))
  5805     def __lt__(self, other):
  5806         """True if self is an answer from other (other ==> self)."""
  5807         if isinstance(other, Packet):
  5808             return self.answers(other)
  5809         elif type(other) is str:
  5810             return 1
  5811         else:
  5812             raise TypeError((self, other))
  5813 
  5814     def __eq__(self, other):
  5815         if not isinstance(other, self.__class__):
  5816             return False
  5817         for f in self.fields_desc:
  5818             if f not in other.fields_desc:
  5819                 return False
  5820             if self.getfieldval(f.name) != other.getfieldval(f.name):
  5821                 return False
  5822         return self.payload == other.payload
  5823 
  5824     def __ne__(self, other):
  5825         return not self.__eq__(other)
  5826 
  5827     def hashret(self):
  5828         """DEV: returns a string that has the same value for a request and its answer."""
  5829         return self.payload.hashret()
  5830     def answers(self, other):
  5831         """DEV: true if self is an answer from other"""
  5832         if other.__class__ == self.__class__:
  5833             return self.payload.answers(other.payload)
  5834         return 0
  5835 
  5836     def haslayer(self, cls):
  5837         """true if self has a layer that is an instance of cls. Superseded by "cls in self" syntax."""
  5838         if self.__class__ == cls or self.__class__.__name__ == cls:
  5839             return 1
  5840         for f in self.packetfields:
  5841             fvalue_gen = self.getfieldval(f.name)
  5842             if fvalue_gen is None:
  5843                 continue
  5844             if not f.islist:
  5845                 fvalue_gen = SetGen(fvalue_gen,_iterpacket=0)
  5846             for fvalue in fvalue_gen:
  5847                 if isinstance(fvalue, Packet):
  5848                     ret = fvalue.haslayer(cls)
  5849                     if ret:
  5850                         return ret
  5851         return self.payload.haslayer(cls)
  5852     def getlayer(self, cls, nb=1, _track=None):
  5853         """Return the nb^th layer that is an instance of cls."""
  5854         if type(cls) is str and "." in cls:
  5855             ccls,fld = cls.split(".",1)
  5856         else:
  5857             ccls,fld = cls,None
  5858         if self.__class__ == cls or self.__class__.name == ccls:
  5859             if nb == 1:
  5860                 if fld is None:
  5861                     return self
  5862                 else:
  5863                     return self.getfieldval(fld)
  5864             else:
  5865                 nb -=1
  5866         for f in self.packetfields:
  5867             fvalue_gen = self.getfieldval(f.name)
  5868             if fvalue_gen is None:
  5869                 continue
  5870             if not f.islist:
  5871                 fvalue_gen = SetGen(fvalue_gen,_iterpacket=0)
  5872             for fvalue in fvalue_gen:
  5873                 if isinstance(fvalue, Packet):
  5874                     track=[]
  5875                     ret = fvalue.getlayer(cls, nb, _track=track)
  5876                     if ret is not None:
  5877                         return ret
  5878                     nb = track[0]
  5879         return self.payload.getlayer(cls,nb,_track=_track)
  5880 
  5881     def __getitem__(self, cls):
  5882         if type(cls) is slice:
  5883             if cls.stop:
  5884                 ret = self.getlayer(cls.start, cls.stop)
  5885             else:
  5886                 ret = self.getlayer(cls.start)
  5887             if ret is None and cls.step is not None:
  5888                 ret = cls.step
  5889             return ret
  5890         else:
  5891             return self.getlayer(cls)
  5892         
  5893     def __contains__(self, cls):
  5894         """"cls in self" returns true if self has a layer which is an instance of cls."""
  5895         return self.haslayer(cls)
  5896         
  5897     
  5898 
  5899     def display(self,*args,**kargs):  # Deprecated. Use show()
  5900         """Deprecated. Use show() method."""
  5901         self.show(*args,**kargs)
  5902     def show(self, indent=3, lvl="", label_lvl=""):
  5903         """Prints a hierarchical view of the packet. "indent" gives the size of indentation for each layer."""
  5904         ct = conf.color_theme
  5905         print "%s%s %s %s" % (label_lvl,
  5906                               ct.punct("###["),
  5907                               ct.layer_name(self.name),
  5908                               ct.punct("]###"))
  5909         for f in self.fields_desc:
  5910             if isinstance(f, ConditionalField) and not f._evalcond(self):
  5911                 continue
  5912             if isinstance(f, Emph):
  5913                 ncol = ct.emph_field_name
  5914                 vcol = ct.emph_field_value
  5915             else:
  5916                 ncol = ct.field_name
  5917                 vcol = ct.field_value
  5918             fvalue = self.getfieldval(f.name)
  5919             if isinstance(fvalue, Packet) or (f.islist and f.holds_packets and type(fvalue) is list):
  5920                 print "%s  \\%-10s\\" % (label_lvl+lvl, ncol(f.name))
  5921                 fvalue_gen = SetGen(fvalue,_iterpacket=0)
  5922                 for fvalue in fvalue_gen:
  5923                     fvalue.show(indent=indent, label_lvl=label_lvl+lvl+"   |")
  5924             else:
  5925                 print "%s  %-10s%s %s" % (label_lvl+lvl,
  5926                                           ncol(f.name),
  5927                                           ct.punct("="),
  5928                                           vcol(f.i2repr(self,fvalue)))
  5929         self.payload.show(indent=indent, lvl=lvl+(" "*indent*self.show_indent), label_lvl=label_lvl)
  5930     def show2(self):
  5931         """Prints a hierarchical view of an assembled version of the packet, so that automatic fields are calculated (checksums, etc.)"""
  5932         self.__class__(str(self)).show()
  5933 
  5934     def sprintf(self, fmt, relax=1):
  5935         """sprintf(format, [relax=1]) -> str
  5936 where format is a string that can include directives. A directive begins and
  5937 ends by % and has the following format %[fmt[r],][cls[:nb].]field%.
  5938 
  5939 fmt is a classic printf directive, "r" can be appended for raw substitution
  5940 (ex: IP.flags=0x18 instead of SA), nb is the number of the layer we want
  5941 (ex: for IP/IP packets, IP:2.src is the src of the upper IP layer).
  5942 Special case : "%.time%" is the creation time.
  5943 Ex : p.sprintf("%.time% %-15s,IP.src% -> %-15s,IP.dst% %IP.chksum% "
  5944                "%03xr,IP.proto% %r,TCP.flags%")
  5945 
  5946 Moreover, the format string can include conditionnal statements. A conditionnal
  5947 statement looks like : {layer:string} where layer is a layer name, and string
  5948 is the string to insert in place of the condition if it is true, i.e. if layer
  5949 is present. If layer is preceded by a "!", the result si inverted. Conditions
  5950 can be imbricated. A valid statement can be :
  5951   p.sprintf("This is a{TCP: TCP}{UDP: UDP}{ICMP:n ICMP} packet")
  5952   p.sprintf("{IP:%IP.dst% {ICMP:%ICMP.type%}{TCP:%TCP.dport%}}")
  5953 
  5954 A side effect is that, to obtain "{" and "}" characters, you must use
  5955 "%(" and "%)".
  5956 """
  5957 
  5958         escape = { "%": "%",
  5959                    "(": "{",
  5960                    ")": "}" }
  5961 
  5962 
  5963         # Evaluate conditions 
  5964         while "{" in fmt:
  5965             i = fmt.rindex("{")
  5966             j = fmt[i+1:].index("}")
  5967             cond = fmt[i+1:i+j+1]
  5968             k = cond.find(":")
  5969             if k < 0:
  5970                 raise Scapy_Exception("Bad condition in format string: [%s] (read sprintf doc!)"%cond)
  5971             cond,format = cond[:k],cond[k+1:]
  5972             res = False
  5973             if cond[0] == "!":
  5974                 res = True
  5975                 cond = cond[1:]
  5976             if self.haslayer(cond):
  5977                 res = not res
  5978             if not res:
  5979                 format = ""
  5980             fmt = fmt[:i]+format+fmt[i+j+2:]
  5981 
  5982         # Evaluate directives
  5983         s = ""
  5984         while "%" in fmt:
  5985             i = fmt.index("%")
  5986             s += fmt[:i]
  5987             fmt = fmt[i+1:]
  5988             if fmt and fmt[0] in escape:
  5989                 s += escape[fmt[0]]
  5990                 fmt = fmt[1:]
  5991                 continue
  5992             try:
  5993                 i = fmt.index("%")
  5994                 sfclsfld = fmt[:i]
  5995                 fclsfld = sfclsfld.split(",")
  5996                 if len(fclsfld) == 1:
  5997                     f = "s"
  5998                     clsfld = fclsfld[0]
  5999                 elif len(fclsfld) == 2:
  6000                     f,clsfld = fclsfld
  6001                 else:
  6002                     raise Scapy_Exception
  6003                 if "." in clsfld:
  6004                     cls,fld = clsfld.split(".")
  6005                 else:
  6006                     cls = self.__class__.__name__
  6007                     fld = clsfld
  6008                 num = 1
  6009                 if ":" in cls:
  6010                     cls,num = cls.split(":")
  6011                     num = int(num)
  6012                 fmt = fmt[i+1:]
  6013             except:
  6014                 raise Scapy_Exception("Bad format string [%%%s%s]" % (fmt[:25], fmt[25:] and "..."))
  6015             else:
  6016                 if fld == "time":
  6017                     val = time.strftime("%H:%M:%S.%%06i", time.localtime(self.time)) % int((self.time-int(self.time))*1000000)
  6018                 elif cls == self.__class__.__name__ and hasattr(self, fld):
  6019                     if num > 1:
  6020                         val = self.payload.sprintf("%%%s,%s:%s.%s%%" % (f,cls,num-1,fld), relax)
  6021                         f = "s"
  6022                     elif f[-1] == "r":  # Raw field value
  6023                         val = getattr(self,fld)
  6024                         f = f[:-1]
  6025                         if not f:
  6026                             f = "s"
  6027                     else:
  6028                         val = getattr(self,fld)
  6029                         if fld in self.fieldtype:
  6030                             val = self.fieldtype[fld].i2repr(self,val)
  6031                 else:
  6032                     val = self.payload.sprintf("%%%s%%" % sfclsfld, relax)
  6033                     f = "s"
  6034                 s += ("%"+f) % val
  6035             
  6036         s += fmt
  6037         return s
  6038 
  6039     def mysummary(self):
  6040         """DEV: can be overloaded to return a string that summarizes the layer.
  6041            Only one mysummary() is used in a whole packet summary: the one of the upper layer,
  6042            except if a mysummary() also returns (as a couple) a list of layers whose
  6043            mysummary() must be called if they are present."""
  6044         return ""
  6045 
  6046     def summary(self, intern=0):
  6047         """Prints a one line summary of a packet."""
  6048         found,s,needed = self.payload.summary(intern=1)
  6049         if s:
  6050             s = " / "+s
  6051         ret = ""
  6052         if not found or self.__class__ in needed:
  6053             ret = self.mysummary()
  6054             if type(ret) is tuple:
  6055                 ret,n = ret
  6056                 needed += n
  6057         if ret or needed:
  6058             found = 1
  6059         if not ret:
  6060             ret = self.__class__.__name__
  6061         ret = "%s%s" % (ret,s)
  6062         if intern:
  6063             return found,ret,needed
  6064         else:
  6065             return ret
  6066     
  6067     def lastlayer(self,layer=None):
  6068         """Returns the uppest layer of the packet"""
  6069         return self.payload.lastlayer(self)
  6070 
  6071     def decode_payload_as(self,cls):
  6072         """Reassembles the payload and decode it using another packet class"""
  6073         s = str(self.payload)
  6074         self.payload = cls(s)
  6075 
  6076     def libnet(self):
  6077         """Not ready yet. Should give the necessary C code that interfaces with libnet to recreate the packet"""
  6078         print "libnet_build_%s(" % self.__class__.name.lower()
  6079         det = self.__class__(str(self))
  6080         for f in self.fields_desc:
  6081             val = det.getfieldval(f.name)
  6082             if val is None:
  6083                 val = 0
  6084             elif type(val) is int:
  6085                 val = str(val)
  6086             else:
  6087                 val = '"%s"' % str(val)
  6088             print "\t%s, \t\t/* %s */" % (val,f.name)
  6089         print ");"
  6090     def command(self):
  6091         """Returns a string representing the command you have to type to obtain the same packet"""
  6092         f = []
  6093         for fn,fv in self.fields.items():
  6094             fld = self.get_field(fn)
  6095             if isinstance(fv, Packet):
  6096                 fv = fv.command()
  6097             elif fld.islist and fld.holds_packets and type(fv) is list:
  6098                 fv = "[%s]" % ",".join( map(Packet.command, fv))
  6099             else:
  6100                 fv = repr(fv)
  6101             f.append("%s=%s" % (fn, fv))
  6102         c = "%s(%s)" % (self.__class__.__name__, ", ".join(f))
  6103         pc = self.payload.command()
  6104         if pc:
  6105             c += "/"+pc
  6106         return c                    
  6107 
  6108 
  6109 class ASN1_Packet(Packet):
  6110     ASN1_root = None
  6111     ASN1_codec = None    
  6112     def init_fields(self):
  6113         flist = self.ASN1_root.get_fields_list()
  6114         self.do_init_fields(flist)
  6115         self.fields_desc = flist    
  6116     def do_build(self):
  6117         return self.ASN1_root.build(self)    
  6118     def do_dissect(self, x):
  6119         return self.ASN1_root.dissect(self, x)
  6120         
  6121 
  6122 class NoPayload(Packet,object):
  6123     def __new__(cls, *args, **kargs):
  6124         singl = cls.__dict__.get("__singl__")
  6125         if singl is None:
  6126             cls.__singl__ = singl = object.__new__(cls)
  6127             Packet.__init__(singl, *args, **kargs)
  6128         return singl
  6129     def __init__(self, *args, **kargs):
  6130         pass
  6131     def dissection_done(self,pkt):
  6132         return
  6133     def add_payload(self, payload):
  6134         raise Scapy_Exception("Can't add payload to NoPayload instance")
  6135     def remove_payload(self):
  6136         pass
  6137     def add_underlayer(self,underlayer):
  6138         pass
  6139     def remove_underlayer(self,other):
  6140         pass
  6141     def copy(self):
  6142         return self
  6143     def __repr__(self):
  6144         return ""
  6145     def __str__(self):
  6146         return ""
  6147     def __nonzero__(self):
  6148         return False
  6149     def build(self, internal=0):
  6150         return ""    
  6151     def build_done(self, p):
  6152         return p
  6153     def build_ps(self, internal=0):
  6154         return "",[]
  6155     def getfieldval(self, attr):
  6156         raise AttributeError(attr)
  6157     def getfield_and_val(self, attr):
  6158         raise AttributeError(attr)
  6159     def setfieldval(self, attr, val):
  6160         raise AttributeError(attr)
  6161     def delfieldval(self, attr):
  6162         raise AttributeError(attr)
  6163     def __getattr__(self, attr):
  6164         if attr in self.__dict__:
  6165             return self.__dict__[attr]
  6166         elif attr in self.__class__.__dict__:
  6167             return self.__class__.__dict__[attr]
  6168         else:
  6169             raise AttributeError, attr
  6170     def hide_defaults(self):
  6171         pass
  6172     def __iter__(self):
  6173         return iter([])
  6174     def __eq__(self, other):
  6175         if isinstance(other, NoPayload):
  6176             return True
  6177         return False
  6178     def hashret(self):
  6179         return ""
  6180     def answers(self, other):
  6181         return isinstance(other, NoPayload) or isinstance(other, Padding)
  6182     def haslayer(self, cls):
  6183         return 0
  6184     def getlayer(self, cls, nb=1, _track=None):
  6185         if _track is not None:
  6186             _track.append(nb)
  6187         return None
  6188     def show(self, indent=3, lvl="", label_lvl=""):
  6189         pass
  6190     def sprintf(self, fmt, relax):
  6191         if relax:
  6192             return "??"
  6193         else:
  6194             raise Scapy_Exception("Format not found [%s]"%fmt)
  6195     def summary(self, intern=0):
  6196         return 0,"",[]
  6197     def lastlayer(self,layer):
  6198         return layer
  6199     def command(self):
  6200         return ""
  6201     
  6202 
  6203 ####################
  6204 ## packet classes ##
  6205 ####################
  6206     
  6207             
  6208 class Raw(Packet):
  6209     name = "Raw"
  6210     fields_desc = [ StrField("load", "") ]
  6211     def answers(self, other):
  6212         return 1
  6213 #        s = str(other)
  6214 #        t = self.load
  6215 #        l = min(len(s), len(t))
  6216 #        return  s[:l] == t[:l]
  6217         
  6218 class Padding(Raw):
  6219     name = "Padding"
  6220     def build(self, internal=0):
  6221         if internal:
  6222             return ""
  6223         else:
  6224             return Raw.build(self)
  6225 
  6226 class Ether(Packet):
  6227     name = "Ethernet"
  6228     fields_desc = [ DestMACField("dst"),
  6229                     SourceMACField("src"),
  6230                     XShortEnumField("type", 0x0000, ETHER_TYPES) ]
  6231     def hashret(self):
  6232         return struct.pack("H",self.type)+self.payload.hashret()
  6233     def answers(self, other):
  6234         if isinstance(other,Ether):
  6235             if self.type == other.type:
  6236                 return self.payload.answers(other.payload)
  6237         return 0
  6238     def mysummary(self):
  6239         return self.sprintf("%src% > %dst% (%type%)")
  6240 
  6241 class PPPoE(Packet):
  6242     name = "PPP over Ethernet"
  6243     fields_desc = [ BitField("version", 1, 4),
  6244                     BitField("type", 1, 4),
  6245                     ByteEnumField("code", 0, {0:"Session"}),
  6246                     XShortField("sessionid", 0x0),
  6247                     ShortField("len", None) ]
  6248 
  6249     def post_build(self, p, pay):
  6250         p += pay
  6251         if self.len is None:
  6252             l = len(p)-6
  6253             p = p[:4]+struct.pack("!H", l)+p[6:]
  6254         return p
  6255 
  6256 class PPPoED(PPPoE):
  6257     name = "PPP over Ethernet Discovery"
  6258     fields_desc = [ BitField("version", 1, 4),
  6259                     BitField("type", 1, 4),
  6260                     ByteEnumField("code", 0x09, {0x09:"PADI",0x07:"PADO",0x19:"PADR",0x65:"PADS",0xa7:"PADT"}),
  6261                     XShortField("sessionid", 0x0),
  6262                     ShortField("len", None) ]
  6263 
  6264 class Dot3(Packet):
  6265     name = "802.3"
  6266     fields_desc = [ MACField("dst", ETHER_BROADCAST),
  6267                     MACField("src", ETHER_ANY),
  6268                     LenField("len", None, "H") ]
  6269     def extract_padding(self,s):
  6270         l = self.len
  6271         return s[:l],s[l:]
  6272     def answers(self, other):
  6273         if isinstance(other,Dot3):
  6274             return self.payload.answers(other.payload)
  6275         return 0
  6276     def mysummary(self):
  6277         return "802.3 %s > %s" % (self.src, self.dst)
  6278 
  6279 
  6280 class LLC(Packet):
  6281     name = "LLC"
  6282     fields_desc = [ XByteField("dsap", 0x00),
  6283                     XByteField("ssap", 0x00),
  6284                     ByteField("ctrl", 0) ]
  6285 
  6286 
  6287 class CookedLinux(Packet):
  6288     name = "cooked linux"
  6289     fields_desc = [ ShortEnumField("pkttype",0, {0: "unicast",
  6290                                                  4:"sent-by-us"}), #XXX incomplete
  6291                     XShortField("lladdrtype",512),
  6292                     ShortField("lladdrlen",0),
  6293                     StrFixedLenField("src","",8),
  6294                     XShortEnumField("proto",0x800,ETHER_TYPES) ]
  6295                     
  6296                                    
  6297 
  6298 class SNAP(Packet):
  6299     name = "SNAP"
  6300     fields_desc = [ X3BytesField("OUI",0x000000),
  6301                     XShortEnumField("code", 0x000, ETHER_TYPES) ]
  6302 
  6303 
  6304 class Dot1Q(Packet):
  6305     name = "802.1Q"
  6306     aliastypes = [ Ether ]
  6307     fields_desc =  [ BitField("prio", 0, 3),
  6308                      BitField("id", 0, 1),
  6309                      BitField("vlan", 1, 12),
  6310                      XShortEnumField("type", 0x0000, ETHER_TYPES) ]
  6311     def answers(self, other):
  6312         if isinstance(other,Dot1Q):
  6313             if ( (self.type == other.type) and
  6314                  (self.vlan == other.vlan) ):
  6315                 return self.payload.answers(other.payload)
  6316         else:
  6317             return self.payload.answers(other)
  6318         return 0
  6319     def default_payload_class(self, pay):
  6320         if self.type <= 1500:
  6321             return LLC
  6322         return Raw
  6323     def extract_padding(self,s):
  6324         if self.type <= 1500:
  6325             return s[:self.type],s[self.type:]
  6326         return s,None
  6327     def mysummary(self):
  6328         if isinstance(self.underlayer, Ether):
  6329             return self.underlayer.sprintf("802.1q %Ether.src% > %Ether.dst% (%Dot1Q.type%) vlan %Dot1Q.vlan%")
  6330         else:
  6331             return self.sprintf("802.1q (%Dot1Q.type%) vlan %Dot1Q.vlan%")
  6332 
  6333             
  6334 
  6335 
  6336 class RadioTap(Packet):
  6337     name = "RadioTap dummy"
  6338     fields_desc = [ ByteField('version', 0),
  6339                     ByteField('pad', 0),
  6340                     FieldLenField('len', None, 'notdecoded', '@H', adjust=lambda pkt,x:x+8),
  6341                     FlagsField('present', None, -32, ['TSFT','Flags','Rate','Channel','FHSS','dBm_AntSignal',
  6342                                                      'dBm_AntNoise','Lock_Quality','TX_Attenuation','dB_TX_Attenuation',
  6343                                                       'dBm_TX_Power', 'Antenna', 'dB_AntSignal', 'dB_AntNoise',
  6344                                                      'b14', 'b15','b16','b17','b18','b19','b20','b21','b22','b23',
  6345                                                      'b24','b25','b26','b27','b28','b29','b30','Ext']),
  6346                     StrLenField('notdecoded', "", length_from= lambda pkt:pkt.len-8) ]
  6347 
  6348 class STP(Packet):
  6349     name = "Spanning Tree Protocol"
  6350     fields_desc = [ ShortField("proto", 0),
  6351                     ByteField("version", 0),
  6352                     ByteField("bpdutype", 0),
  6353                     ByteField("bpduflags", 0),
  6354                     ShortField("rootid", 0),
  6355                     MACField("rootmac", ETHER_ANY),
  6356                     IntField("pathcost", 0),
  6357                     ShortField("bridgeid", 0),
  6358                     MACField("bridgemac", ETHER_ANY),
  6359                     ShortField("portid", 0),
  6360                     BCDFloatField("age", 1),
  6361                     BCDFloatField("maxage", 20),
  6362                     BCDFloatField("hellotime", 2),
  6363                     BCDFloatField("fwddelay", 15) ]
  6364 
  6365 
  6366 class EAPOL(Packet):
  6367     name = "EAPOL"
  6368     fields_desc = [ ByteField("version", 1),
  6369                     ByteEnumField("type", 0, ["EAP_PACKET", "START", "LOGOFF", "KEY", "ASF"]),
  6370                     LenField("len", None, "H") ]
  6371     
  6372     EAP_PACKET= 0
  6373     START = 1
  6374     LOGOFF = 2
  6375     KEY = 3
  6376     ASF = 4
  6377     def extract_padding(self, s):
  6378         l = self.len
  6379         return s[:l],s[l:]
  6380     def hashret(self):
  6381         return chr(self.type)+self.payload.hashret()
  6382     def answers(self, other):
  6383         if isinstance(other,EAPOL):
  6384             if ( (self.type == self.EAP_PACKET) and
  6385                  (other.type == self.EAP_PACKET) ):
  6386                 return self.payload.answers(other.payload)
  6387         return 0
  6388     def mysummary(self):
  6389         return self.sprintf("EAPOL %EAPOL.type%")
  6390              
  6391 
  6392 class EAP(Packet):
  6393     name = "EAP"
  6394     fields_desc = [ ByteEnumField("code", 4, {1:"REQUEST",2:"RESPONSE",3:"SUCCESS",4:"FAILURE"}),
  6395                     ByteField("id", 0),
  6396                     ShortField("len",None),
  6397                     ConditionalField(ByteEnumField("type",0, {1:"ID",4:"MD5"}), lambda pkt:pkt.code not in [EAP.SUCCESS, EAP.FAILURE])
  6398 
  6399                                      ]
  6400     
  6401     REQUEST = 1
  6402     RESPONSE = 2
  6403     SUCCESS = 3
  6404     FAILURE = 4
  6405     TYPE_ID = 1
  6406     TYPE_MD5 = 4
  6407     def answers(self, other):
  6408         if isinstance(other,EAP):
  6409             if self.code == self.REQUEST:
  6410                 return 0
  6411             elif self.code == self.RESPONSE:
  6412                 if ( (other.code == self.REQUEST) and
  6413                      (other.type == self.type) ):
  6414                     return 1
  6415             elif other.code == self.RESPONSE:
  6416                 return 1
  6417         return 0
  6418     
  6419     def post_build(self, p, pay):
  6420         if self.len is None:
  6421             l = len(p)+len(pay)
  6422             p = p[:2]+chr((l>>8)&0xff)+chr(l&0xff)+p[4:]
  6423         return p+pay
  6424              
  6425 
  6426 class ARP(Packet):
  6427     name = "ARP"
  6428     fields_desc = [ XShortField("hwtype", 0x0001),
  6429                     XShortEnumField("ptype",  0x0800, ETHER_TYPES),
  6430                     ByteField("hwlen", 6),
  6431                     ByteField("plen", 4),
  6432                     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}),
  6433                     ARPSourceMACField("hwsrc"),
  6434                     SourceIPField("psrc","pdst"),
  6435                     MACField("hwdst", ETHER_ANY),
  6436                     IPField("pdst", "0.0.0.0") ]
  6437     who_has = 1
  6438     is_at = 2
  6439     def answers(self, other):
  6440         if isinstance(other,ARP):
  6441             if ( (self.op == self.is_at) and
  6442                  (other.op == self.who_has) and
  6443                  (self.psrc == other.pdst) ):
  6444                 return 1
  6445         return 0
  6446     def extract_padding(self, s):
  6447         return "",s
  6448     def mysummary(self):
  6449         if self.op == self.is_at:
  6450             return "ARP is at %s says %s" % (self.hwsrc, self.psrc)
  6451         elif self.op == self.who_has:
  6452             return "ARP who has %s says %s" % (self.pdst, self.psrc)
  6453         else:
  6454             return "ARP %ARP.op% %ARP.psrc% > %ARP.pdst%"
  6455                  
  6456 
  6457 class IP(Packet, IPTools):
  6458     name = "IP"
  6459     fields_desc = [ BitField("version" , 4 , 4),
  6460                     BitField("ihl", None, 4),
  6461                     XByteField("tos", 0),
  6462                     ShortField("len", None),
  6463                     ShortField("id", 1),
  6464                     FlagsField("flags", 0, 3, ["MF","DF","evil"]),
  6465                     BitField("frag", 0, 13),
  6466                     ByteField("ttl", 64),
  6467                     ByteEnumField("proto", 0, IP_PROTOS),
  6468                     XShortField("chksum", None),
  6469                     #IPField("src", "127.0.0.1"),
  6470                     Emph(SourceIPField("src","dst")),
  6471                     Emph(IPField("dst", "127.0.0.1")),
  6472                     IPoptionsField("options", "") ]
  6473     def post_build(self, p, pay):
  6474         ihl = self.ihl
  6475         if ihl is None:
  6476             ihl = len(p)/4
  6477             p = chr(((self.version&0xf)<<4) | ihl&0x0f)+p[1:]
  6478         if self.len is None:
  6479             l = len(p)+len(pay)
  6480             p = p[:2]+struct.pack("!H", l)+p[4:]
  6481         if self.chksum is None:
  6482             ck = checksum(p)
  6483             p = p[:10]+chr(ck>>8)+chr(ck&0xff)+p[12:]
  6484         return p+pay
  6485 
  6486     def extract_padding(self, s):
  6487         l = self.len - (self.ihl << 2)
  6488         return s[:l],s[l:]
  6489 
  6490     def send(self, s, slp=0):
  6491         for p in self:
  6492             try:
  6493                 s.sendto(str(p), (p.dst,0))
  6494             except socket.error, msg:
  6495                 log_runtime.error(msg)
  6496             if slp:
  6497                 time.sleep(slp)
  6498     def hashret(self):
  6499         if ( (self.proto == socket.IPPROTO_ICMP)
  6500              and (isinstance(self.payload, ICMP))
  6501              and (self.payload.type in [3,4,5,11,12]) ):
  6502             return self.payload.payload.hashret()
  6503         else:
  6504             if conf.checkIPsrc and conf.checkIPaddr:
  6505                 return strxor(inet_aton(self.src),inet_aton(self.dst))+struct.pack("B",self.proto)+self.payload.hashret()
  6506             else:
  6507                 return struct.pack("B", self.proto)+self.payload.hashret()
  6508     def answers(self, other):
  6509         if not isinstance(other,IP):
  6510             return 0
  6511         if conf.checkIPaddr and (self.dst != other.src):
  6512             return 0
  6513         if ( (self.proto == socket.IPPROTO_ICMP) and
  6514              (isinstance(self.payload, ICMP)) and
  6515              (self.payload.type in [3,4,5,11,12]) ):
  6516             # ICMP error message
  6517             return self.payload.payload.answers(other)
  6518 
  6519         else:
  6520             if ( (conf.checkIPaddr and (self.src != other.dst)) or
  6521                  (self.proto != other.proto) ):
  6522                 return 0
  6523             return self.payload.answers(other.payload)
  6524     def mysummary(self):
  6525         s = self.sprintf("%IP.src% > %IP.dst% %IP.proto%")
  6526         if self.frag:
  6527             s += " frag:%i" % self.frag
  6528         return s
  6529                  
  6530     
  6531 
  6532 class TCP(Packet):
  6533     name = "TCP"
  6534     fields_desc = [ ShortEnumField("sport", 20, TCP_SERVICES),
  6535                     ShortEnumField("dport", 80, TCP_SERVICES),
  6536                     IntField("seq", 0),
  6537                     IntField("ack", 0),
  6538                     BitField("dataofs", None, 4),
  6539                     BitField("reserved", 0, 4),
  6540                     FlagsField("flags", 0x2, 8, "FSRPAUEC"),
  6541                     ShortField("window", 8192),
  6542                     XShortField("chksum", None),
  6543                     ShortField("urgptr", 0),
  6544                     TCPOptionsField("options", {}) ]
  6545     def post_build(self, p, pay):
  6546         p += pay
  6547         dataofs = self.dataofs
  6548         if dataofs is None:
  6549             dataofs = 5+((len(self.get_field("options").i2m(self,self.options))+3)/4)
  6550             p = p[:12]+chr((dataofs << 4) | ord(p[12])&0x0f)+p[13:]
  6551         if self.chksum is None:
  6552             if isinstance(self.underlayer, IP):
  6553                 if self.underlayer.len is not None:
  6554                     ln = self.underlayer.len-20
  6555                 else:
  6556                     ln = len(p)
  6557                 psdhdr = struct.pack("!4s4sHH",
  6558                                      inet_aton(self.underlayer.src),
  6559                                      inet_aton(self.underlayer.dst),
  6560                                      self.underlayer.proto,
  6561                                      ln)
  6562                 ck=checksum(psdhdr+p)
  6563                 p = p[:16]+struct.pack("!H", ck)+p[18:]
  6564             elif isinstance(self.underlayer, IPv6) or isinstance(self.underlayer, _IPv6OptionHeader):
  6565                 ck = in6_chksum(socket.IPPROTO_TCP, self.underlayer, p)
  6566                 p = p[:16]+struct.pack("!H", ck)+p[18:]
  6567             else:
  6568                 warning("No IP underlayer to compute checksum. Leaving null.")
  6569         return p
  6570     def hashret(self):
  6571         if conf.checkIPsrc:
  6572             return struct.pack("H",self.sport ^ self.dport)+self.payload.hashret()
  6573         else:
  6574             return self.payload.hashret()
  6575     def answers(self, other):
  6576         if not isinstance(other, TCP):
  6577             return 0
  6578         if conf.checkIPsrc:
  6579             if not ((self.sport == other.dport) and
  6580                     (self.dport == other.sport)):
  6581                 return 0
  6582         if (abs(other.seq-self.ack) > 2+len(other.payload)):
  6583             return 0
  6584         return 1
  6585     def mysummary(self):
  6586         if isinstance(self.underlayer, IP):
  6587             return self.underlayer.sprintf("TCP %IP.src%:%TCP.sport% > %IP.dst%:%TCP.dport% %TCP.flags%")
  6588         elif isinstance(self.underlayer, IPv6):
  6589             return self.underlayer.sprintf("TCP %IPv6.src%:%TCP.sport% > %IPv6.dst%:%TCP.dport% %TCP.flags%")
  6590         else:
  6591             return self.sprintf("TCP %TCP.sport% > %TCP.dport% %TCP.flags%")
  6592 
  6593 class UDP(Packet):
  6594     name = "UDP"
  6595     fields_desc = [ ShortEnumField("sport", 53, UDP_SERVICES),
  6596                     ShortEnumField("dport", 53, UDP_SERVICES),
  6597                     ShortField("len", None),
  6598                     XShortField("chksum", None), ]
  6599     def post_build(self, p, pay):
  6600         p += pay
  6601         l = self.len
  6602         if l is None:
  6603             l = len(p)
  6604             p = p[:4]+struct.pack("!H",l)+p[6:]
  6605         if self.chksum is None:
  6606             if isinstance(self.underlayer, IP):
  6607                 if self.underlayer.len is not None:
  6608                     ln = self.underlayer.len-20
  6609                 else:
  6610                     ln = len(p)
  6611                 psdhdr = struct.pack("!4s4sHH",
  6612                                      inet_aton(self.underlayer.src),
  6613                                      inet_aton(self.underlayer.dst),
  6614                                      self.underlayer.proto,
  6615                                      ln)
  6616                 ck=checksum(psdhdr+p)
  6617                 p = p[:6]+struct.pack("!H", ck)+p[8:]
  6618             elif isinstance(self.underlayer, IPv6) or isinstance(self.underlayer, _IPv6OptionHeader):
  6619                 ck = in6_chksum(socket.IPPROTO_UDP, self.underlayer, p)
  6620                 p = p[:6]+struct.pack("!H", ck)+p[8:]
  6621             else:
  6622                 warning("No IP underlayer to compute checksum. Leaving null.")
  6623         return p
  6624     def extract_padding(self, s):
  6625         l = self.len - 8
  6626         return s[:l],s[l:]
  6627     def hashret(self):
  6628         return self.payload.hashret()
  6629     def answers(self, other):
  6630         if not isinstance(other, UDP):
  6631             return 0
  6632         if conf.checkIPsrc:
  6633             if self.dport != other.sport:
  6634                 return 0
  6635         return self.payload.answers(other.payload)
  6636     def mysummary(self):
  6637         if isinstance(self.underlayer, IP):
  6638             return self.underlayer.sprintf("UDP %IP.src%:%UDP.sport% > %IP.dst%:%UDP.dport%")
  6639         elif isinstance(self.underlayer, IPv6):
  6640             return self.underlayer.sprintf("UDP %IPv6.src%:%UDP.sport% > %IPv6.dst%:%UDP.dport%")
  6641         else:
  6642             return self.sprintf("UDP %UDP.sport% > %UDP.dport%")    
  6643 
  6644 icmptypes = { 0 : "echo-reply",
  6645               3 : "dest-unreach",
  6646               4 : "source-quench",
  6647               5 : "redirect",
  6648               8 : "echo-request",
  6649               9 : "router-advertisement",
  6650               10 : "router-solicitation",
  6651               11 : "time-exceeded",
  6652               12 : "parameter-problem",
  6653               13 : "timestamp-request",
  6654               14 : "timestamp-reply",
  6655               15 : "information-request",
  6656               16 : "information-response",
  6657               17 : "address-mask-request",
  6658               18 : "address-mask-reply" }
  6659 
  6660 class ICMP(Packet):
  6661     name = "ICMP"
  6662     fields_desc = [ ByteEnumField("type",8, icmptypes),
  6663                     ByteField("code",0),
  6664                     XShortField("chksum", None),
  6665                     ConditionalField(XShortField("id",0),  lambda pkt:pkt.type in [0,8,13,14,15,16]),
  6666                     ConditionalField(XShortField("seq",0), lambda pkt:pkt.type in [0,8,13,14,15,16]),
  6667                     ConditionalField(ICMPTimeStampField("ts_ori", None), lambda pkt:pkt.type in [13,14]),
  6668                     ConditionalField(ICMPTimeStampField("ts_rx", None), lambda pkt:pkt.type in [13,14]),
  6669                     ConditionalField(ICMPTimeStampField("ts_tx", None), lambda pkt:pkt.type in [13,14]),
  6670                     ConditionalField(IPField("gw","0.0.0.0"),  lambda pkt:pkt.type==5),
  6671                     ConditionalField(ByteField("ptr",0),   lambda pkt:pkt.type==12),
  6672                     ConditionalField(X3BytesField("reserved",0), lambda pkt:pkt.type==12),
  6673                     ConditionalField(IntField("unused",0), lambda pkt:pkt.type not in [0,5,8,12,13,14,15,16]),
  6674                     ]
  6675     def post_build(self, p, pay):
  6676         p += pay
  6677         if self.chksum is None:
  6678             ck = checksum(p)
  6679             p = p[:2]+chr(ck>>8)+chr(ck&0xff)+p[4:]
  6680         return p
  6681     
  6682     def hashret(self):
  6683         return struct.pack("HH",self.id,self.seq)+self.payload.hashret()
  6684     def answers(self, other):
  6685         if not isinstance(other,ICMP):
  6686             return 0
  6687         if ( (other.type,self.type) in [(8,0),(13,14),(15,16),(17,18)] and
  6688              self.id == other.id and
  6689              self.seq == other.seq ):
  6690             return 1
  6691         return 0
  6692 
  6693     def guess_payload_class(self, payload):
  6694         if self.type in [3,4,5,11,12]:
  6695             return IPerror
  6696         else:
  6697             return None
  6698     def mysummary(self):
  6699         if isinstance(self.underlayer, IP):
  6700             return self.underlayer.sprintf("ICMP %IP.src% > %IP.dst% %ICMP.type% %ICMP.code%")
  6701         else:
  6702             return self.sprintf("ICMP %ICMP.type% %ICMP.code%")
  6703     
  6704         
  6705 
  6706 
  6707 
  6708 class IPerror(IP):
  6709     name = "IP in ICMP"
  6710     def answers(self, other):
  6711         if not isinstance(other, IP):
  6712             return 0
  6713         if not ( ((conf.checkIPsrc == 0) or (self.dst == other.dst)) and
  6714                  (self.src == other.src) and
  6715                  ( ((conf.checkIPID == 0)
  6716                     or (self.id == other.id)
  6717                     or (conf.checkIPID == 1 and self.id == socket.htons(other.id)))) and
  6718                  (self.proto == other.proto) ):
  6719             return 0
  6720         return self.payload.answers(other.payload)
  6721     def mysummary(self):
  6722         return Packet.mysummary(self)
  6723 
  6724 
  6725 class TCPerror(TCP):
  6726     name = "TCP in ICMP"
  6727     def answers(self, other):
  6728         if not isinstance(other, TCP):
  6729             return 0
  6730         if conf.checkIPsrc:
  6731             if not ((self.sport == other.sport) and
  6732                     (self.dport == other.dport)):
  6733                 return 0
  6734         if conf.check_TCPerror_seqack:
  6735             if self.seq is not None:
  6736                 if self.seq != other.seq:
  6737                     return 0
  6738             if self.ack is not None:
  6739                 if self.ack != other.ack:
  6740                     return 0
  6741         return 1
  6742     def mysummary(self):
  6743         return Packet.mysummary(self)
  6744 
  6745 
  6746 class UDPerror(UDP):
  6747     name = "UDP in ICMP"
  6748     def answers(self, other):
  6749         if not isinstance(other, UDP):
  6750             return 0
  6751         if conf.checkIPsrc:
  6752             if not ((self.sport == other.sport) and
  6753                     (self.dport == other.dport)):
  6754                 return 0
  6755         return 1
  6756     def mysummary(self):
  6757         return Packet.mysummary(self)
  6758 
  6759                     
  6760 
  6761 class ICMPerror(ICMP):
  6762     name = "ICMP in ICMP"
  6763     def answers(self, other):
  6764         if not isinstance(other,ICMP):
  6765             return 0
  6766         if not ((self.type == other.type) and
  6767                 (self.code == other.code)):
  6768             return 0
  6769         if self.code in [0,8,13,14,17,18]:
  6770             if (self.id == other.id and
  6771                 self.seq == other.seq):
  6772                 return 1
  6773             else:
  6774                 return 0
  6775         else:
  6776             return 1
  6777     def mysummary(self):
  6778         return Packet.mysummary(self)
  6779 
  6780 class IPv6(Packet):
  6781     """See http://namabiiru.hongo.wide.ad.jp/scapy6"""
  6782     name = "IPv6 not implemented here." 
  6783     def __init__(self, *args, **kargs):
  6784         log_interactive.error(self.name)
  6785     def __repr__(self):
  6786         return "<IPv6: ERROR not implemented>"
  6787     
  6788 class _IPv6OptionHeader(Packet):
  6789     """See http://namabiiru.hongo.wide.ad.jp/scapy6"""
  6790     name = "IPv6 not implemented here."
  6791     def __init__(self, *args, **kargs):
  6792         log_interactive.error(self.name)
  6793     def __repr__(self):
  6794         return "<IPv6: ERROR not implemented>"
  6795 
  6796 
  6797 class L2TP(Packet):
  6798     fields_desc = [ ShortEnumField("pkt_type",2,{2:"data"}),
  6799                     ShortField("len", None),
  6800                     ShortField("tunnel_id", 0),
  6801                     ShortField("session_id", 0),
  6802                     ShortField("ns", 0),
  6803                     ShortField("nr", 0),
  6804                     ShortField("offset", 0) ]
  6805 
  6806     def post_build(self, pkt, pay):
  6807         if self.len is None:
  6808             l = len(pkt)+len(pay)
  6809             pkt = pkt[:2]+struct.pack("!H", l)+pkt[4:]
  6810         return pkt+pay
  6811 
  6812 
  6813 _PPP_proto = { 0x0001: "Padding Protocol",
  6814                0x0003: "ROHC small-CID [RFC3095]",
  6815                0x0005: "ROHC large-CID [RFC3095]",
  6816                0x0021: "Internet Protocol version 4",
  6817                0x0023: "OSI Network Layer",
  6818                0x0025: "Xerox NS IDP",
  6819                0x0027: "DECnet Phase IV",
  6820                0x0029: "Appletalk",
  6821                0x002b: "Novell IPX",
  6822                0x002d: "Van Jacobson Compressed TCP/IP",
  6823                0x002f: "Van Jacobson Uncompressed TCP/IP",
  6824                0x0031: "Bridging PDU",
  6825                0x0033: "Stream Protocol (ST-II)",
  6826                0x0035: "Banyan Vines",
  6827                0x0037: "reserved (until 1993) [Typo in RFC1172]",
  6828                0x0039: "AppleTalk EDDP",
  6829                0x003b: "AppleTalk SmartBuffered",
  6830                0x003d: "Multi-Link [RFC1717]",
  6831                0x003f: "NETBIOS Framing",
  6832                0x0041: "Cisco Systems",
  6833                0x0043: "Ascom Timeplex",
  6834                0x0045: "Fujitsu Link Backup and Load Balancing (LBLB)",
  6835                0x0047: "DCA Remote Lan",
  6836                0x0049: "Serial Data Transport Protocol (PPP-SDTP)",
  6837                0x004b: "SNA over 802.2",
  6838                0x004d: "SNA",
  6839                0x004f: "IPv6 Header Compression",
  6840                0x0051: "KNX Bridging Data [ianp]",
  6841                0x0053: "Encryption [Meyer]",
  6842                0x0055: "Individual Link Encryption [Meyer]",
  6843                0x0057: "Internet Protocol version 6 [Hinden]",
  6844                0x0059: "PPP Muxing [RFC3153]",
  6845                0x005b: "Vendor-Specific Network Protocol (VSNP) [RFC3772]",
  6846                0x0061: "RTP IPHC Full Header [RFC3544]",
  6847                0x0063: "RTP IPHC Compressed TCP [RFC3544]",
  6848                0x0065: "RTP IPHC Compressed Non TCP [RFC3544]",
  6849                0x0067: "RTP IPHC Compressed UDP 8 [RFC3544]",
  6850                0x0069: "RTP IPHC Compressed RTP 8 [RFC3544]",
  6851                0x006f: "Stampede Bridging",
  6852                0x0071: "Reserved [Fox]",
  6853                0x0073: "MP+ Protocol [Smith]",
  6854                0x007d: "reserved (Control Escape) [RFC1661]",
  6855                0x007f: "reserved (compression inefficient [RFC1662]",
  6856                0x0081: "Reserved Until 20-Oct-2000 [IANA]",
  6857                0x0083: "Reserved Until 20-Oct-2000 [IANA]",
  6858                0x00c1: "NTCITS IPI [Ungar]",
  6859                0x00cf: "reserved (PPP NLID)",
  6860                0x00fb: "single link compression in multilink [RFC1962]",
  6861                0x00fd: "compressed datagram [RFC1962]",
  6862                0x00ff: "reserved (compression inefficient)",
  6863                0x0201: "802.1d Hello Packets",
  6864                0x0203: "IBM Source Routing BPDU",
  6865                0x0205: "DEC LANBridge100 Spanning Tree",
  6866                0x0207: "Cisco Discovery Protocol [Sastry]",
  6867                0x0209: "Netcs Twin Routing [Korfmacher]",
  6868                0x020b: "STP - Scheduled Transfer Protocol [Segal]",
  6869                0x020d: "EDP - Extreme Discovery Protocol [Grosser]",
  6870                0x0211: "Optical Supervisory Channel Protocol (OSCP)[Prasad]",
  6871                0x0213: "Optical Supervisory Channel Protocol (OSCP)[Prasad]",
  6872                0x0231: "Luxcom",
  6873                0x0233: "Sigma Network Systems",
  6874                0x0235: "Apple Client Server Protocol [Ridenour]",
  6875                0x0281: "MPLS Unicast [RFC3032]  ",
  6876                0x0283: "MPLS Multicast [RFC3032]",
  6877                0x0285: "IEEE p1284.4 standard - data packets [Batchelder]",
  6878                0x0287: "ETSI TETRA Network Protocol Type 1 [Nieminen]",
  6879                0x0289: "Multichannel Flow Treatment Protocol [McCann]",
  6880                0x2063: "RTP IPHC Compressed TCP No Delta [RFC3544]",
  6881                0x2065: "RTP IPHC Context State [RFC3544]",
  6882                0x2067: "RTP IPHC Compressed UDP 16 [RFC3544]",
  6883                0x2069: "RTP IPHC Compressed RTP 16 [RFC3544]",
  6884                0x4001: "Cray Communications Control Protocol [Stage]",
  6885                0x4003: "CDPD Mobile Network Registration Protocol [Quick]",
  6886                0x4005: "Expand accelerator protocol [Rachmani]",
  6887                0x4007: "ODSICP NCP [Arvind]",
  6888                0x4009: "DOCSIS DLL [Gaedtke]",
  6889                0x400B: "Cetacean Network Detection Protocol [Siller]",
  6890                0x4021: "Stacker LZS [Simpson]",
  6891                0x4023: "RefTek Protocol [Banfill]",
  6892                0x4025: "Fibre Channel [Rajagopal]",
  6893                0x4027: "EMIT Protocols [Eastham]",
  6894                0x405b: "Vendor-Specific Protocol (VSP) [RFC3772]",
  6895                0x8021: "Internet Protocol Control Protocol",
  6896                0x8023: "OSI Network Layer Control Protocol",
  6897                0x8025: "Xerox NS IDP Control Protocol",
  6898                0x8027: "DECnet Phase IV Control Protocol",
  6899                0x8029: "Appletalk Control Protocol",
  6900                0x802b: "Novell IPX Control Protocol",
  6901                0x802d: "reserved",
  6902                0x802f: "reserved",
  6903                0x8031: "Bridging NCP",
  6904                0x8033: "Stream Protocol Control Protocol",
  6905                0x8035: "Banyan Vines Control Protocol",
  6906                0x8037: "reserved (until 1993)",
  6907                0x8039: "reserved",
  6908                0x803b: "reserved",
  6909                0x803d: "Multi-Link Control Protocol",
  6910                0x803f: "NETBIOS Framing Control Protocol",
  6911                0x8041: "Cisco Systems Control Protocol",
  6912                0x8043: "Ascom Timeplex",
  6913                0x8045: "Fujitsu LBLB Control Protocol",
  6914                0x8047: "DCA Remote Lan Network Control Protocol (RLNCP)",
  6915                0x8049: "Serial Data Control Protocol (PPP-SDCP)",
  6916                0x804b: "SNA over 802.2 Control Protocol",
  6917                0x804d: "SNA Control Protocol",
  6918                0x804f: "IP6 Header Compression Control Protocol",
  6919                0x8051: "KNX Bridging Control Protocol [ianp]",
  6920                0x8053: "Encryption Control Protocol [Meyer]",
  6921                0x8055: "Individual Link Encryption Control Protocol [Meyer]",
  6922                0x8057: "IPv6 Control Protovol [Hinden]",
  6923                0x8059: "PPP Muxing Control Protocol [RFC3153]",
  6924                0x805b: "Vendor-Specific Network Control Protocol (VSNCP) [RFC3772]",
  6925                0x806f: "Stampede Bridging Control Protocol",
  6926                0x8073: "MP+ Control Protocol [Smith]",
  6927                0x8071: "Reserved [Fox]",
  6928                0x807d: "Not Used - reserved [RFC1661]",
  6929                0x8081: "Reserved Until 20-Oct-2000 [IANA]",
  6930                0x8083: "Reserved Until 20-Oct-2000 [IANA]",
  6931                0x80c1: "NTCITS IPI Control Protocol [Ungar]",
  6932                0x80cf: "Not Used - reserved [RFC1661]",
  6933                0x80fb: "single link compression in multilink control [RFC1962]",
  6934                0x80fd: "Compression Control Protocol [RFC1962]",
  6935                0x80ff: "Not Used - reserved [RFC1661]",
  6936                0x8207: "Cisco Discovery Protocol Control [Sastry]",
  6937                0x8209: "Netcs Twin Routing [Korfmacher]",
  6938                0x820b: "STP - Control Protocol [Segal]",
  6939                0x820d: "EDPCP - Extreme Discovery Protocol Ctrl Prtcl [Grosser]",
  6940                0x8235: "Apple Client Server Protocol Control [Ridenour]",
  6941                0x8281: "MPLSCP [RFC3032]",
  6942                0x8285: "IEEE p1284.4 standard - Protocol Control [Batchelder]",
  6943                0x8287: "ETSI TETRA TNP1 Control Protocol [Nieminen]",
  6944                0x8289: "Multichannel Flow Treatment Protocol [McCann]",
  6945                0xc021: "Link Control Protocol",
  6946                0xc023: "Password Authentication Protocol",
  6947                0xc025: "Link Quality Report",
  6948                0xc027: "Shiva Password Authentication Protocol",
  6949                0xc029: "CallBack Control Protocol (CBCP)",
  6950                0xc02b: "BACP Bandwidth Allocation Control Protocol [RFC2125]",
  6951                0xc02d: "BAP [RFC2125]",
  6952                0xc05b: "Vendor-Specific Authentication Protocol (VSAP) [RFC3772]",
  6953                0xc081: "Container Control Protocol [KEN]",
  6954                0xc223: "Challenge Handshake Authentication Protocol",
  6955                0xc225: "RSA Authentication Protocol [Narayana]",
  6956                0xc227: "Extensible Authentication Protocol [RFC2284]",
  6957                0xc229: "Mitsubishi Security Info Exch Ptcl (SIEP) [Seno]",
  6958                0xc26f: "Stampede Bridging Authorization Protocol",
  6959                0xc281: "Proprietary Authentication Protocol [KEN]",
  6960                0xc283: "Proprietary Authentication Protocol [Tackabury]",
  6961                0xc481: "Proprietary Node ID Authentication Protocol [KEN]"}
  6962 
  6963 
  6964 class HDLC(Packet):
  6965     fields_desc = [ XByteField("address",0xff),
  6966                     XByteField("control",0x03)  ]
  6967 
  6968 class PPP_metaclass(Packet_metaclass):
  6969     def __call__(self, _pkt=None, *args, **kargs):
  6970         cls = self
  6971         if _pkt and _pkt[0] == '\xff':
  6972             cls = HDLC
  6973         i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)
  6974         i.__init__(_pkt=_pkt, *args, **kargs)
  6975         return i
  6976     
  6977 
  6978 class PPP(Packet):
  6979     __metaclass__ = PPP_metaclass
  6980     name = "PPP Link Layer"
  6981     fields_desc = [ ShortEnumField("proto", 0x0021, _PPP_proto) ]
  6982 
  6983 _PPP_conftypes = { 1:"Configure-Request",
  6984                    2:"Configure-Ack",
  6985                    3:"Configure-Nak",
  6986                    4:"Configure-Reject",
  6987                    5:"Terminate-Request",
  6988                    6:"Terminate-Ack",
  6989                    7:"Code-Reject",
  6990                    8:"Protocol-Reject",
  6991                    9:"Echo-Request",
  6992                    10:"Echo-Reply",
  6993                    11:"Discard-Request",
  6994                    14:"Reset-Request",
  6995                    15:"Reset-Ack",
  6996                    }
  6997 
  6998 class PPP_Option_metaclass(Packet_metaclass):
  6999     _known_options={}
  7000     def __call__(self, _pkt=None, *args, **kargs):
  7001         cls = self
  7002         if _pkt:
  7003             t = ord(_pkt[0])
  7004             cls = self._known_options.get(t,self)
  7005         i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)
  7006         i.__init__(_pkt=_pkt, *args, **kargs)
  7007         return i
  7008     def _register(self, cls):
  7009         self._known_options[cls.fields_desc[0].default] = cls
  7010 
  7011 
  7012 ### PPP IPCP stuff (RFC 1332)
  7013 
  7014 # All IPCP options are defined below (names and associated classes) 
  7015 _PPP_ipcpopttypes = {     1:"IP-Addresses (Deprecated)",
  7016                           2:"IP-Compression-Protocol",
  7017                           3:"IP-Address",
  7018                           4:"Mobile-IPv4", # not implemented, present for completeness
  7019                           129:"Primary-DNS-Address",
  7020                           130:"Primary-NBNS-Address",
  7021                           131:"Secondary-DNS-Address",
  7022                           132:"Secondary-NBNS-Address"}
  7023 
  7024 
  7025 
  7026 class PPP_IPCP_Option_metaclass(PPP_Option_metaclass):
  7027     _known_options={}
  7028 
  7029 
  7030 class PPP_IPCP_Option(Packet):
  7031     __metaclass__=PPP_IPCP_Option_metaclass
  7032     name = "PPP IPCP Option"
  7033     fields_desc = [ ByteEnumField("type" , None , _PPP_ipcpopttypes),
  7034                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
  7035                     StrLenField("data", "", length_from=lambda p:max(0,p.len-2)) ]
  7036     def extract_padding(self, pay):
  7037         return "",pay
  7038 
  7039 class PPP_IPCP_Specific_Option_metaclass(PPP_IPCP_Option_metaclass):
  7040     def __new__(cls, name, bases, dct):
  7041         newcls = super(PPP_IPCP_Specific_Option_metaclass, cls).__new__(cls, name, bases, dct)
  7042         PPP_IPCP_Option._register(newcls)
  7043         
  7044 
  7045 class PPP_IPCP_Option_IPAddress(PPP_IPCP_Option):
  7046     __metaclass__=PPP_IPCP_Specific_Option_metaclass
  7047     name = "PPP IPCP Option: IP Address"
  7048     fields_desc = [ ByteEnumField("type" , 3 , _PPP_ipcpopttypes),
  7049                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
  7050                     IPField("data","0.0.0.0"),
  7051                     ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
  7052 
  7053 class PPP_IPCP_Option_DNS1(PPP_IPCP_Option):
  7054     __metaclass__=PPP_IPCP_Specific_Option_metaclass
  7055     name = "PPP IPCP Option: DNS1 Address"
  7056     fields_desc = [ ByteEnumField("type" , 129 , _PPP_ipcpopttypes),
  7057                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
  7058                     IPField("data","0.0.0.0"),
  7059                     ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
  7060 
  7061 class PPP_IPCP_Option_DNS2(PPP_IPCP_Option):
  7062     __metaclass__=PPP_IPCP_Specific_Option_metaclass
  7063     name = "PPP IPCP Option: DNS2 Address"
  7064     fields_desc = [ ByteEnumField("type" , 131 , _PPP_ipcpopttypes),
  7065                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
  7066                     IPField("data","0.0.0.0"),
  7067                     ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
  7068 
  7069 class PPP_IPCP_Option_NBNS1(PPP_IPCP_Option):
  7070     __metaclass__=PPP_IPCP_Specific_Option_metaclass
  7071     name = "PPP IPCP Option: NBNS1 Address"
  7072     fields_desc = [ ByteEnumField("type" , 130 , _PPP_ipcpopttypes),
  7073                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
  7074                     IPField("data","0.0.0.0"),
  7075                     ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
  7076 
  7077 class PPP_IPCP_Option_NBNS2(PPP_IPCP_Option):
  7078     __metaclass__=PPP_IPCP_Specific_Option_metaclass
  7079     name = "PPP IPCP Option: NBNS2 Address"
  7080     fields_desc = [ ByteEnumField("type" , 132 , _PPP_ipcpopttypes),
  7081                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+6),
  7082                     IPField("data","0.0.0.0"),
  7083                     ConditionalField(StrLenField("garbage","", length_from=lambda pkt:pkt.len-6), lambda p:p.len!=6) ]
  7084 
  7085 
  7086 
  7087 
  7088 class PPP_IPCP(Packet):
  7089     fields_desc = [ ByteEnumField("code" , 1, _PPP_conftypes),
  7090 		    XByteField("id", 0 ),
  7091                     FieldLenField("len" , None, fmt="H", length_of="options", adjust=lambda p,x:x+4 ),
  7092                     PacketListField("options", [],  PPP_IPCP_Option, length_from=lambda p:p.len-4,) ]
  7093 
  7094 
  7095 ### ECP
  7096 
  7097 _PPP_ecpopttypes = { 0:"OUI",
  7098                      1:"DESE", }
  7099 
  7100 class PPP_ECP_Option_metaclass(PPP_Option_metaclass):
  7101     _known_options={}
  7102 
  7103 
  7104 
  7105 class PPP_ECP_Option(Packet):
  7106     __metaclass__=PPP_ECP_Option_metaclass
  7107     name = "PPP ECP Option"
  7108     fields_desc = [ ByteEnumField("type" , None , _PPP_ecpopttypes),
  7109                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
  7110                     StrLenField("data", "", length_from=lambda p:max(0,p.len-2)) ]
  7111     def extract_padding(self, pay):
  7112         return "",pay
  7113 
  7114 class PPP_ECP_Specific_Option_metaclass(PPP_ECP_Option_metaclass):
  7115     def __new__(cls, name, bases, dct):
  7116         newcls = super(PPP_ECP_Specific_Option_metaclass, cls).__new__(cls, name, bases, dct)
  7117         PPP_ECP_Option._register(newcls)
  7118         
  7119 
  7120 class PPP_ECP_Option_OUI(PPP_ECP_Option):
  7121     __metaclass__=PPP_ECP_Specific_Option_metaclass
  7122     fields_desc = [ ByteEnumField("type" , 0 , _PPP_ecpopttypes),
  7123                     FieldLenField("len", None, length_of="data", fmt="B", adjust=lambda p,x:x+2),
  7124                     StrFixedLenField("oui","",3),
  7125                     ByteField("subtype",0),
  7126                     StrLenField("data", "", length_from=lambda p:p.len-6) ]
  7127                     
  7128 
  7129 
  7130 class PPP_ECP(Packet):
  7131     fields_desc = [ ByteEnumField("code" , 1, _PPP_conftypes),
  7132 		    XByteField("id", 0 ),
  7133                     FieldLenField("len" , None, fmt="H", length_of="options", adjust=lambda p,x:x+4 ),
  7134                     PacketListField("options", [],  PPP_ECP_Option, length_from=lambda p:p.len-4,) ]
  7135 
  7136 
  7137 
  7138 
  7139 class DNS(Packet):
  7140     name = "DNS"
  7141     fields_desc = [ ShortField("id",0),
  7142                     BitField("qr",0, 1),
  7143                     BitEnumField("opcode", 0, 4, {0:"QUERY",1:"IQUERY",2:"STATUS"}),
  7144                     BitField("aa", 0, 1),
  7145                     BitField("tc", 0, 1),
  7146                     BitField("rd", 0, 1),
  7147                     BitField("ra", 0 ,1),
  7148                     BitField("z", 0, 3),
  7149                     BitEnumField("rcode", 0, 4, {0:"ok", 1:"format-error", 2:"server-failure", 3:"name-error", 4:"not-implemented", 5:"refused"}),
  7150                     DNSRRCountField("qdcount", None, "qd"),
  7151                     DNSRRCountField("ancount", None, "an"),
  7152                     DNSRRCountField("nscount", None, "ns"),
  7153                     DNSRRCountField("arcount", None, "ar"),
  7154                     DNSQRField("qd", "qdcount"),
  7155                     DNSRRField("an", "ancount"),
  7156                     DNSRRField("ns", "nscount"),
  7157                     DNSRRField("ar", "arcount",0) ]
  7158     def answers(self, other):
  7159         return (isinstance(other, DNS)
  7160                 and self.id == other.id
  7161                 and self.qr == 1
  7162                 and other.qr == 0)
  7163         
  7164     def mysummary(self):
  7165         type = ["Qry","Ans"][self.qr]
  7166         name = ""
  7167         if self.qr:
  7168             type = "Ans"
  7169             if self.ancount > 0 and isinstance(self.an, DNSRR):
  7170                 name = ' "%s"' % self.an.rdata
  7171         else:
  7172             type = "Qry"
  7173             if self.qdcount > 0 and isinstance(self.qd, DNSQR):
  7174                 name = ' "%s"' % self.qd.qname
  7175         return 'DNS %s%s ' % (type, name)
  7176 
  7177 dnstypes = { 0:"ANY", 255:"ALL",
  7178              1:"A", 2:"NS", 3:"MD", 4:"MD", 5:"CNAME", 6:"SOA", 7: "MB", 8:"MG",
  7179              9:"MR",10:"NULL",11:"WKS",12:"PTR",13:"HINFO",14:"MINFO",15:"MX",16:"TXT",
  7180              17:"RP",18:"AFSDB",28:"AAAA", 33:"SRV",38:"A6",39:"DNAME"}
  7181 
  7182 dnsqtypes = {251:"IXFR",252:"AXFR",253:"MAILB",254:"MAILA",255:"ALL"}
  7183 dnsqtypes.update(dnstypes)
  7184 dnsclasses =  {1: 'IN',  2: 'CS',  3: 'CH',  4: 'HS',  255: 'ANY'}
  7185 
  7186 
  7187 class DNSQR(Packet):
  7188     name = "DNS Question Record"
  7189     show_indent=0
  7190     fields_desc = [ DNSStrField("qname",""),
  7191                     ShortEnumField("qtype", 1, dnsqtypes),
  7192                     ShortEnumField("qclass", 1, dnsclasses) ]
  7193                     
  7194                     
  7195 
  7196 class DNSRR(Packet):
  7197     name = "DNS Resource Record"
  7198     show_indent=0
  7199     fields_desc = [ DNSStrField("rrname",""),
  7200                     ShortEnumField("type", 1, dnstypes),
  7201                     ShortEnumField("rclass", 1, dnsclasses),
  7202                     IntField("ttl", 0),
  7203                     RDLenField("rdlen"),
  7204                     RDataField("rdata", "", length_from=lambda pkt:pkt.rdlen) ]
  7205 
  7206 dhcpmagic="c\x82Sc"
  7207 
  7208 
  7209 class BOOTP(Packet):
  7210     name = "BOOTP"
  7211     fields_desc = [ ByteEnumField("op",1, {1:"BOOTREQUEST", 2:"BOOTREPLY"}),
  7212                     ByteField("htype",1),
  7213                     ByteField("hlen",6),
  7214                     ByteField("hops",0),
  7215                     IntField("xid",0),
  7216                     ShortField("secs",0),
  7217                     FlagsField("flags", 0, 16, "???????????????B"),
  7218                     IPField("ciaddr","0.0.0.0"),
  7219                     IPField("yiaddr","0.0.0.0"),
  7220                     IPField("siaddr","0.0.0.0"),
  7221                     IPField("giaddr","0.0.0.0"),
  7222                     Field("chaddr","", "16s"),
  7223                     Field("sname","","64s"),
  7224                     Field("file","","128s"),
  7225                     StrField("options","") ]
  7226     def guess_payload_class(self, payload):
  7227         if self.options[:len(dhcpmagic)] == dhcpmagic:
  7228             return DHCP
  7229         else:
  7230             return Packet.guess_payload_class(self, payload)
  7231     def extract_padding(self,s):
  7232         if self.options[:len(dhcpmagic)] == dhcpmagic:
  7233             # set BOOTP options to DHCP magic cookie and make rest a payload of DHCP options
  7234             payload = self.options[len(dhcpmagic):]
  7235             self.options = self.options[:len(dhcpmagic)]
  7236             return payload, None
  7237         else:
  7238             return "", None
  7239     def hashret(self):
  7240         return struct.pack("L", self.xid)
  7241     def answers(self, other):
  7242         if not isinstance(other, BOOTP):
  7243             return 0
  7244         return self.xid == other.xid
  7245 
  7246 
  7247 
  7248 #DHCP_UNKNOWN, DHCP_IP, DHCP_IPLIST, DHCP_TYPE \
  7249 #= range(4)
  7250 #
  7251 
  7252 DHCPTypes = {
  7253                 1: "discover",
  7254                 2: "offer",
  7255                 3: "request",
  7256                 4: "decline",
  7257                 5: "ack",
  7258                 6: "nak",
  7259                 7: "release",
  7260                 8: "inform",
  7261                 9: "force_renew",
  7262                 10:"lease_query",
  7263                 11:"lease_unassigned",
  7264                 12:"lease_unknown",
  7265                 13:"lease_active",
  7266                 }
  7267 
  7268 DHCPOptions = {
  7269     0: "pad",
  7270     1: IPField("subnet_mask", "0.0.0.0"),
  7271     2: "time_zone",
  7272     3: IPField("router","0.0.0.0"),
  7273     4: IPField("time_server","0.0.0.0"),
  7274     5: IPField("IEN_name_server","0.0.0.0"),
  7275     6: IPField("name_server","0.0.0.0"),
  7276     7: IPField("log_server","0.0.0.0"),
  7277     8: IPField("cookie_server","0.0.0.0"),
  7278     9: IPField("lpr_server","0.0.0.0"),
  7279     12: "hostname",
  7280     14: "dump_path",
  7281     15: "domain",
  7282     17: "root_disk_path",
  7283     22: "max_dgram_reass_size",
  7284     23: "default_ttl",
  7285     24: "pmtu_timeout",
  7286     28: IPField("broadcast_address","0.0.0.0"),
  7287     35: "arp_cache_timeout",
  7288     36: "ether_or_dot3",
  7289     37: "tcp_ttl",
  7290     38: "tcp_keepalive_interval",
  7291     39: "tcp_keepalive_garbage",
  7292     40: "NIS_domain",
  7293     41: IPField("NIS_server","0.0.0.0"),
  7294     42: IPField("NTP_server","0.0.0.0"),
  7295     43: "vendor_specific",
  7296     44: IPField("NetBIOS_server","0.0.0.0"),
  7297     45: IPField("NetBIOS_dist_server","0.0.0.0"),
  7298     50: IPField("requested_addr","0.0.0.0"),
  7299     51: IntField("lease_time", 43200),
  7300     54: IPField("server_id","0.0.0.0"),
  7301     55: "param_req_list",
  7302     57: ShortField("max_dhcp_size", 1500),
  7303     58: IntField("renewal_time", 21600),
  7304     59: IntField("rebinding_time", 37800),
  7305     60: "vendor_class_id",
  7306     61: "client_id",
  7307     
  7308     64: "NISplus_domain",
  7309     65: IPField("NISplus_server","0.0.0.0"),
  7310     69: IPField("SMTP_server","0.0.0.0"),
  7311     70: IPField("POP3_server","0.0.0.0"),
  7312     71: IPField("NNTP_server","0.0.0.0"),
  7313     72: IPField("WWW_server","0.0.0.0"),
  7314     73: IPField("Finger_server","0.0.0.0"),
  7315     74: IPField("IRC_server","0.0.0.0"),
  7316     75: IPField("StreetTalk_server","0.0.0.0"),
  7317     76: "StreetTalk_Dir_Assistance",
  7318     82: "relay_agent_Information",
  7319     53: ByteEnumField("message-type", 1, DHCPTypes),
  7320     #             55: DHCPRequestListField("request-list"),
  7321     255: "end"
  7322     }
  7323 
  7324 DHCPRevOptions = {}
  7325 
  7326 for k,v in DHCPOptions.iteritems():
  7327     if type(v) is str:
  7328         n = v
  7329         v = None
  7330     else:
  7331         n = v.name
  7332     DHCPRevOptions[n] = (k,v)
  7333 del(n)
  7334 del(v)
  7335 del(k)
  7336     
  7337     
  7338 
  7339 
  7340 
  7341 class DHCPOptionsField(StrField):
  7342     islist=1
  7343     def i2repr(self,pkt,x):
  7344         s = []
  7345         for v in x:
  7346             if type(v) is tuple and len(v) in [2,3]:
  7347                 if  DHCPRevOptions.has_key(v[0]) and isinstance(DHCPRevOptions[v[0]][1],Field):
  7348                     f = DHCPRevOptions[v[0]][1]
  7349                     vv = f.i2repr(pkt,v[1])
  7350                 else:
  7351                     vv = repr(v[1])
  7352                 r = "%s=%s" % (v[0],vv)
  7353                 if len(v) > 2:
  7354                     r += " (garbage=%r)" % v[2]
  7355                 s.append(r)
  7356             else:
  7357                 s.append(sane(v))
  7358         return "[%s]" % (" ".join(s))
  7359         
  7360     def getfield(self, pkt, s):
  7361         return "", self.m2i(pkt, s)
  7362     def m2i(self, pkt, x):
  7363         opt = []
  7364         while x:
  7365             o = ord(x[0])
  7366             if o == 255:
  7367                 opt.append("end")
  7368                 x = x[1:]
  7369                 continue
  7370             if o == 0:
  7371                 opt.append("pad")
  7372                 x = x[1:]
  7373                 continue
  7374             if len(x) < 2 or len(x) < ord(x[1])+2:
  7375                 opt.append(x)
  7376                 break
  7377             elif DHCPOptions.has_key(o):
  7378                 f = DHCPOptions[o]
  7379 
  7380                 if isinstance(f, str):
  7381                     olen = ord(x[1])
  7382                     opt.append( (f,x[2:olen+2]) )
  7383                     x = x[olen+2:]
  7384                 else:
  7385                     olen = ord(x[1])
  7386                     try:
  7387                         left, val = f.getfield(pkt,x[2:olen+2])
  7388                     except:
  7389                         opt.append(x)
  7390                         break
  7391                     if left:
  7392                         otuple = (f.name, val, left)
  7393                     else:
  7394                         otuple = (f.name, val)
  7395                     opt.append(otuple)
  7396                     x = x[olen+2:]
  7397             else:
  7398                 olen = ord(x[1])
  7399                 opt.append((o, x[2:olen+2]))
  7400                 x = x[olen+2:]
  7401         return opt
  7402     def i2m(self, pkt, x):
  7403         if type(x) is str:
  7404             return x
  7405         s = ""
  7406         for o in x:
  7407             if type(o) is tuple and len(o) in [2,3]:
  7408                 name, val = o[:2]
  7409 
  7410                 if isinstance(name, int):
  7411                     onum, oval = name, val
  7412                 elif DHCPRevOptions.has_key(name):
  7413                     onum, f = DHCPRevOptions[name]
  7414                     if  f is None:
  7415                         oval = val
  7416                     else:
  7417                         oval = f.addfield(pkt,"",f.any2i(pkt,val))
  7418                 else:
  7419                     warning("Unknown field option %s" % name)
  7420                     continue
  7421                 if len(o) > 2:
  7422                     oval += o[2]
  7423 
  7424                 s += chr(onum)
  7425                 s += chr(len(oval))
  7426                 s += oval
  7427 
  7428             elif (type(o) is str and DHCPRevOptions.has_key(o) and 
  7429                   DHCPRevOptions[o][1] == None):
  7430                 s += chr(DHCPRevOptions[o][0])
  7431             elif type(o) is int:
  7432                 s += chr(o)+"\0"
  7433             elif type(o) is str:
  7434                 s += o
  7435             else:
  7436                 warning("Malformed option %s" % o)
  7437         return s
  7438 
  7439 
  7440 class DHCP(Packet):
  7441     name = "DHCP options"
  7442     fields_desc = [ DHCPOptionsField("options","") ]
  7443 
  7444 
  7445 class Dot11(Packet):
  7446     name = "802.11"
  7447     fields_desc = [
  7448                     BitField("subtype", 0, 4),
  7449                     BitEnumField("type", 0, 2, ["Management", "Control", "Data", "Reserved"]),
  7450                     BitField("proto", 0, 2),
  7451                     FlagsField("FCfield", 0, 8, ["to-DS", "from-DS", "MF", "retry", "pw-mgt", "MD", "wep", "order"]),
  7452                     ShortField("ID",0),
  7453                     MACField("addr1", ETHER_ANY),
  7454                     Dot11Addr2MACField("addr2", ETHER_ANY),
  7455                     Dot11Addr3MACField("addr3", ETHER_ANY),
  7456                     Dot11SCField("SC", 0),
  7457                     Dot11Addr4MACField("addr4", ETHER_ANY) 
  7458                     ]
  7459     def mysummary(self):
  7460         return self.sprintf("802.11 %Dot11.type% %Dot11.subtype% %Dot11.addr2% > %Dot11.addr1%")
  7461     def guess_payload_class(self, payload):
  7462         if self.type == 0x02 and (self.subtype >= 0x08 and self.subtype <=0xF and self.subtype != 0xD):
  7463             return Dot11QoS
  7464 	elif self.FCfield & 0x40:
  7465             return Dot11WEP
  7466         else:
  7467             return Packet.guess_payload_class(self, payload)
  7468     def answers(self, other):
  7469         if isinstance(other,Dot11):
  7470             if self.type == 0: # management
  7471                 if self.addr1.lower() != other.addr2.lower(): # check resp DA w/ req SA
  7472                     return 0
  7473                 if (other.subtype,self.subtype) in [(0,1),(2,3),(4,5)]:
  7474                     return 1
  7475                 if self.subtype == other.subtype == 11: # auth
  7476                     return self.payload.answers(other.payload)
  7477             elif self.type == 1: # control
  7478                 return 0
  7479             elif self.type == 2: # data
  7480                 return self.payload.answers(other.payload)
  7481             elif self.type == 3: # reserved
  7482                 return 0
  7483         return 0
  7484     def unwep(self, key=None, warn=1):
  7485         if self.FCfield & 0x40 == 0:
  7486             if warn:
  7487                 warning("No WEP to remove")
  7488             return
  7489         if  isinstance(self.payload.payload, NoPayload):
  7490             if key or conf.wepkey:
  7491                 self.payload.decrypt(key)
  7492             if isinstance(self.payload.payload, NoPayload):
  7493                 if warn:
  7494                     warning("Dot11 can't be decrypted. Check conf.wepkey.")
  7495                 return
  7496         self.FCfield &= ~0x40
  7497         self.payload=self.payload.payload
  7498 
  7499 
  7500 class Dot11QoS(Packet):
  7501     name = "802.11 QoS"
  7502     fields_desc = [ BitField("TID",None,4),
  7503                     BitField("EOSP",None,1),
  7504                     BitField("Ack Policy",None,2),
  7505                     BitField("Reserved",None,1),
  7506                     ByteField("TXOP",None) ]
  7507     def guess_payload_class(self, payload):
  7508         if isinstance(self.underlayer, Dot11):
  7509             if self.underlayer.FCfield & 0x40:
  7510                 return Dot11WEP
  7511         return Packet.guess_payload_class(self, payload)
  7512 
  7513 
  7514 capability_list = [ "res8", "res9", "short-slot", "res11",
  7515                     "res12", "DSSS-OFDM", "res14", "res15",
  7516                    "ESS", "IBSS", "CFP", "CFP-req",
  7517                    "privacy", "short-preamble", "PBCC", "agility"]
  7518 
  7519 reason_code = {0:"reserved",1:"unspec", 2:"auth-expired",
  7520                3:"deauth-ST-leaving",
  7521                4:"inactivity", 5:"AP-full", 6:"class2-from-nonauth",
  7522                7:"class3-from-nonass", 8:"disas-ST-leaving",
  7523                9:"ST-not-auth"}
  7524 
  7525 status_code = {0:"success", 1:"failure", 10:"cannot-support-all-cap",
  7526                11:"inexist-asso", 12:"asso-denied", 13:"algo-unsupported",
  7527                14:"bad-seq-num", 15:"challenge-failure",
  7528                16:"timeout", 17:"AP-full",18:"rate-unsupported" }
  7529 
  7530 class Dot11Beacon(Packet):
  7531     name = "802.11 Beacon"
  7532     fields_desc = [ LELongField("timestamp", 0),
  7533                     LEShortField("beacon_interval", 0x0064),
  7534                     FlagsField("cap", 0, 16, capability_list) ]
  7535     
  7536 
  7537 class Dot11Elt(Packet):
  7538     name = "802.11 Information Element"
  7539     fields_desc = [ ByteEnumField("ID", 0, {0:"SSID", 1:"Rates", 2: "FHset", 3:"DSset", 4:"CFset", 5:"TIM", 6:"IBSSset", 16:"challenge",
  7540                                             42:"ERPinfo", 46:"QoS Capability", 47:"ERPinfo", 48:"RSNinfo", 50:"ESRates",221:"vendor",68:"reserved"}),
  7541                     FieldLenField("len", None, "info", "B"),
  7542                     StrLenField("info", "", length_from=lambda x:x.len) ]
  7543     def mysummary(self):
  7544         if self.ID == 0:
  7545             return "SSID=%s"%repr(self.info),[Dot11]
  7546         else:
  7547             return ""
  7548 
  7549 class Dot11ATIM(Packet):
  7550     name = "802.11 ATIM"
  7551 
  7552 class Dot11Disas(Packet):
  7553     name = "802.11 Disassociation"
  7554     fields_desc = [ LEShortEnumField("reason", 1, reason_code) ]
  7555 
  7556 class Dot11AssoReq(Packet):
  7557     name = "802.11 Association Request"
  7558     fields_desc = [ FlagsField("cap", 0, 16, capability_list),
  7559                     LEShortField("listen_interval", 0x00c8) ]
  7560 
  7561 
  7562 class Dot11AssoResp(Packet):
  7563     name = "802.11 Association Response"
  7564     fields_desc = [ FlagsField("cap", 0, 16, capability_list),
  7565                     LEShortField("status", 0),
  7566                     LEShortField("AID", 0) ]
  7567 
  7568 class Dot11ReassoReq(Packet):
  7569     name = "802.11 Reassociation Request"
  7570     fields_desc = [ FlagsField("cap", 0, 16, capability_list),
  7571                     MACField("current_AP", ETHER_ANY),
  7572                     LEShortField("listen_interval", 0x00c8) ]
  7573 
  7574 
  7575 class Dot11ReassoResp(Dot11AssoResp):
  7576     name = "802.11 Reassociation Response"
  7577 
  7578 class Dot11ProbeReq(Packet):
  7579     name = "802.11 Probe Request"
  7580     
  7581 class Dot11ProbeResp(Packet):
  7582     name = "802.11 Probe Response"
  7583     fields_desc = [ LELongField("timestamp", 0),
  7584                     LEShortField("beacon_interval", 0x0064),
  7585                     FlagsField("cap", 0, 16, capability_list) ]
  7586     
  7587 class Dot11Auth(Packet):
  7588     name = "802.11 Authentication"
  7589     fields_desc = [ LEShortEnumField("algo", 0, ["open", "sharedkey"]),
  7590                     LEShortField("seqnum", 0),
  7591                     LEShortEnumField("status", 0, status_code) ]
  7592     def answers(self, other):
  7593         if self.seqnum == other.seqnum+1:
  7594             return 1
  7595         return 0
  7596 
  7597 class Dot11Deauth(Packet):
  7598     name = "802.11 Deauthentication"
  7599     fields_desc = [ LEShortEnumField("reason", 1, reason_code) ]
  7600 
  7601 
  7602 
  7603 class Dot11WEP(Packet):
  7604     name = "802.11 WEP packet"
  7605     fields_desc = [ StrFixedLenField("iv", "\0\0\0", 3),
  7606                     ByteField("keyid", 0),
  7607                     StrField("wepdata",None,remain=4),
  7608                     IntField("icv",None) ]
  7609 
  7610     def post_dissect(self, s):
  7611 #        self.icv, = struct.unpack("!I",self.wepdata[-4:])
  7612 #        self.wepdata = self.wepdata[:-4]
  7613         self.decrypt()
  7614 
  7615     def build_payload(self):
  7616         if self.wepdata is None:
  7617             return Packet.build_payload(self)
  7618         return ""
  7619 
  7620     def post_build(self, p, pay):
  7621         if self.wepdata is None:
  7622             key = conf.wepkey
  7623             if key:
  7624                 if self.icv is None:
  7625                     pay += struct.pack("<I",crc32(pay))
  7626                     icv = ""
  7627                 else:
  7628                     icv = p[4:8]
  7629                 c = ARC4.new(self.iv+key)
  7630                 p = p[:4]+c.encrypt(pay)+icv
  7631             else:
  7632                 warning("No WEP key set (conf.wepkey).. strange results expected..")
  7633         return p
  7634             
  7635 
  7636     def decrypt(self,key=None):
  7637         if key is None:
  7638             key = conf.wepkey
  7639         if key:
  7640             c = ARC4.new(self.iv+key)
  7641             self.add_payload(LLC(c.decrypt(self.wepdata)))
  7642                     
  7643 
  7644 
  7645 class PrismHeader(Packet):
  7646     """ iwpriv wlan0 monitor 3 """
  7647     name = "Prism header"
  7648     fields_desc = [ LEIntField("msgcode",68),
  7649                     LEIntField("len",144),
  7650                     StrFixedLenField("dev","",16),
  7651                     LEIntField("hosttime_did",0),
  7652                   LEShortField("hosttime_status",0),
  7653                   LEShortField("hosttime_len",0),
  7654                     LEIntField("hosttime",0),
  7655                     LEIntField("mactime_did",0),
  7656                   LEShortField("mactime_status",0),
  7657                   LEShortField("mactime_len",0),
  7658                     LEIntField("mactime",0),
  7659                     LEIntField("channel_did",0),
  7660                   LEShortField("channel_status",0),
  7661                   LEShortField("channel_len",0),
  7662                     LEIntField("channel",0),
  7663                     LEIntField("rssi_did",0),
  7664                   LEShortField("rssi_status",0),
  7665                   LEShortField("rssi_len",0),
  7666                     LEIntField("rssi",0),
  7667                     LEIntField("sq_did",0),
  7668                   LEShortField("sq_status",0),
  7669                   LEShortField("sq_len",0),
  7670                     LEIntField("sq",0),
  7671                     LEIntField("signal_did",0),
  7672                   LEShortField("signal_status",0),
  7673                   LEShortField("signal_len",0),
  7674               LESignedIntField("signal",0),
  7675                     LEIntField("noise_did",0),
  7676                   LEShortField("noise_status",0),
  7677                   LEShortField("noise_len",0),
  7678                     LEIntField("noise",0),
  7679                     LEIntField("rate_did",0),
  7680                   LEShortField("rate_status",0),
  7681                   LEShortField("rate_len",0),
  7682                     LEIntField("rate",0),
  7683                     LEIntField("istx_did",0),
  7684                   LEShortField("istx_status",0),
  7685                   LEShortField("istx_len",0),
  7686                     LEIntField("istx",0),
  7687                     LEIntField("frmlen_did",0),
  7688                   LEShortField("frmlen_status",0),
  7689                   LEShortField("frmlen_len",0),
  7690                     LEIntField("frmlen",0),
  7691                     ]
  7692     def answers(self, other):
  7693         if isinstance(other, PrismHeader):
  7694             return self.payload.answers(other.payload)
  7695         else:
  7696             return self.payload.answers(other)
  7697 
  7698 
  7699 
  7700 class HSRP(Packet):
  7701     name = "HSRP"
  7702     fields_desc = [
  7703         ByteField("version", 0),
  7704         ByteEnumField("opcode", 0, { 0:"Hello"}),
  7705         ByteEnumField("state", 16, { 16:"Active"}),
  7706         ByteField("hellotime", 3),
  7707         ByteField("holdtime", 10),
  7708         ByteField("priority", 120),
  7709         ByteField("group", 1),
  7710         ByteField("reserved", 0),
  7711         StrFixedLenField("auth","cisco",8),
  7712         IPField("virtualIP","192.168.1.1") ]
  7713         
  7714 
  7715 
  7716         
  7717         
  7718 
  7719 
  7720 class NTP(Packet):
  7721     # RFC 1769
  7722     name = "NTP"
  7723     fields_desc = [ 
  7724          BitEnumField('leap', 0, 2,
  7725                       { 0: 'nowarning',
  7726                         1: 'longminute',
  7727                         2: 'shortminute',
  7728                         3: 'notsync'}),
  7729          BitField('version', 3, 3),
  7730          BitEnumField('mode', 3, 3,
  7731                       { 0: 'reserved',
  7732                         1: 'sym_active',
  7733                         2: 'sym_passive',
  7734                         3: 'client',
  7735                         4: 'server',
  7736                         5: 'broadcast',
  7737                         6: 'control',
  7738                         7: 'private'}),
  7739          BitField('stratum', 2, 8),
  7740          BitField('poll', 0xa, 8),          ### XXX : it's a signed int
  7741          BitField('precision', 0, 8),       ### XXX : it's a signed int
  7742          FloatField('delay', 0, 32),
  7743          FloatField('dispersion', 0, 32),
  7744          IPField('id', "127.0.0.1"),
  7745          TimeStampField('ref', 0, 64),
  7746          TimeStampField('orig', -1, 64),  # -1 means current time
  7747          TimeStampField('recv', 0, 64),
  7748          TimeStampField('sent', -1, 64) 
  7749          ]
  7750     def mysummary(self):
  7751         return self.sprintf("NTP v%ir,NTP.version%, %NTP.mode%")
  7752 
  7753 
  7754 class GRE(Packet):
  7755     name = "GRE"
  7756     fields_desc = [ BitField("chksumpresent",0,1),
  7757                     BitField("reserved0",0,12),
  7758                     BitField("version",0,3),
  7759                     XShortEnumField("proto", 0x0000, ETHER_TYPES),
  7760                     ConditionalField(XShortField("chksum",None),lambda pkt:pkt.chksumpresent==1),
  7761                     ConditionalField(XShortField("reserved1",None),lambda pkt:pkt.chksumpresent==1),
  7762                     ]
  7763     def post_build(self, p, pay):
  7764         p += pay
  7765         if self.chksumpresent and self.chksum is None:
  7766             c = checksum(p)
  7767             p = p[:4]+chr((c>>8)&0xff)+chr(c&0xff)+p[6:]
  7768         return p
  7769             
  7770 
  7771 class Radius(Packet):
  7772     name = "Radius"
  7773     fields_desc = [ ByteEnumField("code", 1, {1: "Access-Request",
  7774                                               2: "Access-Accept",
  7775                                               3: "Access-Reject",
  7776                                               4: "Accounting-Request",
  7777                                               5: "Accounting-Accept",
  7778                                               6: "Accounting-Status",
  7779                                               7: "Password-Request",
  7780                                               8: "Password-Ack",
  7781                                               9: "Password-Reject",
  7782                                               10: "Accounting-Message",
  7783                                               11: "Access-Challenge",
  7784                                               12: "Status-Server",
  7785                                               13: "Status-Client",
  7786                                               21: "Resource-Free-Request",
  7787                                               22: "Resource-Free-Response",
  7788                                               23: "Resource-Query-Request",
  7789                                               24: "Resource-Query-Response",
  7790                                               25: "Alternate-Resource-Reclaim-Request",
  7791                                               26: "NAS-Reboot-Request",
  7792                                               27: "NAS-Reboot-Response",
  7793                                               29: "Next-Passcode",
  7794                                               30: "New-Pin",
  7795                                               31: "Terminate-Session",
  7796                                               32: "Password-Expired",
  7797                                               33: "Event-Request",
  7798                                               34: "Event-Response",
  7799                                               40: "Disconnect-Request",
  7800                                               41: "Disconnect-ACK",
  7801                                               42: "Disconnect-NAK",
  7802                                               43: "CoA-Request",
  7803                                               44: "CoA-ACK",
  7804                                               45: "CoA-NAK",
  7805                                               50: "IP-Address-Allocate",
  7806                                               51: "IP-Address-Release",
  7807                                               253: "Experimental-use",
  7808                                               254: "Reserved",
  7809                                               255: "Reserved"} ),
  7810                     ByteField("id", 0),
  7811                     ShortField("len", None),
  7812                     StrFixedLenField("authenticator","",16) ]
  7813     def post_build(self, p, pay):
  7814         p += pay
  7815         l = self.len
  7816         if l is None:
  7817             l = len(p)
  7818             p = p[:2]+struct.pack("!H",l)+p[4:]
  7819         return p
  7820 
  7821 
  7822 
  7823 
  7824 class RIP(Packet):
  7825     name = "RIP header"
  7826     fields_desc = [
  7827         ByteEnumField("command",1,{1:"req",2:"resp",3:"traceOn",4:"traceOff",5:"sun",
  7828                                    6:"trigReq",7:"trigResp",8:"trigAck",9:"updateReq",
  7829                                    10:"updateResp",11:"updateAck"}),
  7830         ByteField("version",1),
  7831         ShortField("null",0),
  7832         ]
  7833 
  7834 class RIPEntry(Packet):
  7835     name = "RIP entry"
  7836     fields_desc = [
  7837         ShortEnumField("AF",2,{2:"IP"}),
  7838         ShortField("RouteTag",0),
  7839         IPField("addr","0.0.0.0"),
  7840         IPField("mask","0.0.0.0"),
  7841         IPField("nextHop","0.0.0.0"),
  7842         IntEnumField("metric",1,{16:"Unreach"}),
  7843         ]
  7844         
  7845 
  7846 
  7847 
  7848 ISAKMP_payload_type = ["None","SA","Proposal","Transform","KE","ID","CERT","CR","Hash",
  7849                        "SIG","Nonce","Notification","Delete","VendorID"]
  7850 
  7851 ISAKMP_exchange_type = ["None","base","identity prot.",
  7852                         "auth only", "aggressive", "info"]
  7853 
  7854 
  7855 class ISAKMP_class(Packet):
  7856     def guess_payload_class(self, payload):
  7857         np = self.next_payload
  7858         if np == 0:
  7859             return Raw
  7860         elif np < len(ISAKMP_payload_type):
  7861             pt = ISAKMP_payload_type[np]
  7862             return globals().get("ISAKMP_payload_%s" % pt, ISAKMP_payload)
  7863         else:
  7864             return ISAKMP_payload
  7865 
  7866 
  7867 class ISAKMP(ISAKMP_class): # rfc2408
  7868     name = "ISAKMP"
  7869     fields_desc = [
  7870         StrFixedLenField("init_cookie","",8),
  7871         StrFixedLenField("resp_cookie","",8),
  7872         ByteEnumField("next_payload",0,ISAKMP_payload_type),
  7873         XByteField("version",0x10),
  7874         ByteEnumField("exch_type",0,ISAKMP_exchange_type),
  7875         FlagsField("flags",0, 8, ["encryption","commit","auth_only","res3","res4","res5","res6","res7"]), # XXX use a Flag field
  7876         IntField("id",0),
  7877         IntField("length",None)
  7878         ]
  7879 
  7880     def guess_payload_class(self, payload):
  7881         if self.flags & 1:
  7882             return Raw
  7883         return ISAKMP_class.guess_payload_class(self, payload)
  7884 
  7885     def answers(self, other):
  7886         if isinstance(other, ISAKMP):
  7887             if other.init_cookie == self.init_cookie:
  7888                 return 1
  7889         return 0
  7890     def post_build(self, p, pay):
  7891         p += pay
  7892         if self.length is None:
  7893             p = p[:24]+struct.pack("!I",len(p))+p[28:]
  7894         return p
  7895        
  7896 
  7897 
  7898 
  7899 class ISAKMP_payload_Transform(ISAKMP_class):
  7900     name = "IKE Transform"
  7901     fields_desc = [
  7902         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7903         ByteField("res",0),
  7904 #        ShortField("len",None),
  7905         ShortField("length",None),
  7906         ByteField("num",None),
  7907         ByteEnumField("id",1,{1:"KEY_IKE"}),
  7908         ShortField("res2",0),
  7909         ISAKMPTransformSetField("transforms",None,length_from=lambda x:x.length-8)
  7910 #        XIntField("enc",0x80010005L),
  7911 #        XIntField("hash",0x80020002L),
  7912 #        XIntField("auth",0x80030001L),
  7913 #        XIntField("group",0x80040002L),
  7914 #        XIntField("life_type",0x800b0001L),
  7915 #        XIntField("durationh",0x000c0004L),
  7916 #        XIntField("durationl",0x00007080L),
  7917         ]
  7918     def post_build(self, p, pay):
  7919         if self.length is None:
  7920             l = len(p)
  7921             p = p[:2]+chr((l>>8)&0xff)+chr(l&0xff)+p[4:]
  7922         p += pay
  7923         return p
  7924             
  7925 
  7926 
  7927         
  7928 class ISAKMP_payload_Proposal(ISAKMP_class):
  7929     name = "IKE proposal"
  7930 #    ISAKMP_payload_type = 0
  7931     fields_desc = [
  7932         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7933         ByteField("res",0),
  7934         FieldLenField("length",None,"trans","H", adjust=lambda pkt,x:x+8),
  7935         ByteField("proposal",1),
  7936         ByteEnumField("proto",1,{1:"ISAKMP"}),
  7937         FieldLenField("SPIsize",None,"SPI","B"),
  7938         ByteField("trans_nb",None),
  7939         StrLenField("SPI","",length_from=lambda x:x.SPIsize),
  7940         PacketLenField("trans",Raw(),ISAKMP_payload_Transform,length_from=lambda x:x.length-8),
  7941         ]
  7942 
  7943 
  7944 class ISAKMP_payload(ISAKMP_class):
  7945     name = "ISAKMP payload"
  7946     fields_desc = [
  7947         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7948         ByteField("res",0),
  7949         FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
  7950         StrLenField("load","",length_from=lambda x:x.length-4),
  7951         ]
  7952 
  7953 
  7954 class ISAKMP_payload_VendorID(ISAKMP_class):
  7955     name = "ISAKMP Vendor ID"
  7956     overload_fields = { ISAKMP: { "next_payload":13 }}
  7957     fields_desc = [
  7958         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7959         ByteField("res",0),
  7960         FieldLenField("length",None,"vendorID","H", adjust=lambda pkt,x:x+4),
  7961         StrLenField("vendorID","",length_from=lambda x:x.length-4),
  7962         ]
  7963 
  7964 class ISAKMP_payload_SA(ISAKMP_class):
  7965     name = "ISAKMP SA"
  7966     overload_fields = { ISAKMP: { "next_payload":1 }}
  7967     fields_desc = [
  7968         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7969         ByteField("res",0),
  7970         FieldLenField("length",None,"prop","H", adjust=lambda pkt,x:x+12),
  7971         IntEnumField("DOI",1,{1:"IPSEC"}),
  7972         IntEnumField("situation",1,{1:"identity"}),
  7973         PacketLenField("prop",Raw(),ISAKMP_payload_Proposal,length_from=lambda x:x.length-12),
  7974         ]
  7975 
  7976 class ISAKMP_payload_Nonce(ISAKMP_class):
  7977     name = "ISAKMP Nonce"
  7978     overload_fields = { ISAKMP: { "next_payload":10 }}
  7979     fields_desc = [
  7980         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7981         ByteField("res",0),
  7982         FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
  7983         StrLenField("load","",length_from=lambda x:x.length-4),
  7984         ]
  7985 
  7986 class ISAKMP_payload_KE(ISAKMP_class):
  7987     name = "ISAKMP Key Exchange"
  7988     overload_fields = { ISAKMP: { "next_payload":4 }}
  7989     fields_desc = [
  7990         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  7991         ByteField("res",0),
  7992         FieldLenField("length",None,"load","H", adjust=lambda pkt,x:x+4),
  7993         StrLenField("load","",length_from=lambda x:x.length-4),
  7994         ]
  7995 
  7996 class ISAKMP_payload_ID(ISAKMP_class):
  7997     name = "ISAKMP Identification"
  7998     overload_fields = { ISAKMP: { "next_payload":5 }}
  7999     fields_desc = [
  8000         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  8001         ByteField("res",0),
  8002         FieldLenField("length",None,"load","H",adjust=lambda pkt,x:x+8),
  8003         ByteEnumField("IDtype",1,{1:"IPv4_addr", 11:"Key"}),
  8004         ByteEnumField("ProtoID",0,{0:"Unused"}),
  8005         ShortEnumField("Port",0,{0:"Unused"}),
  8006 #        IPField("IdentData","127.0.0.1"),
  8007         StrLenField("load","",length_from=lambda x:x.length-8),
  8008         ]
  8009 
  8010 
  8011 
  8012 class ISAKMP_payload_Hash(ISAKMP_class):
  8013     name = "ISAKMP Hash"
  8014     overload_fields = { ISAKMP: { "next_payload":8 }}
  8015     fields_desc = [
  8016         ByteEnumField("next_payload",None,ISAKMP_payload_type),
  8017         ByteField("res",0),
  8018         FieldLenField("length",None,"load","H",adjust=lambda pkt,x:x+4),
  8019         StrLenField("load","",length_from=lambda x:x.length-4),
  8020         ]
  8021 
  8022 
  8023 
  8024 ISAKMP_payload_type_overload = {}
  8025 for i in range(len(ISAKMP_payload_type)):
  8026     name = "ISAKMP_payload_%s" % ISAKMP_payload_type[i]
  8027     if name in globals():
  8028         ISAKMP_payload_type_overload[globals()[name]] = {"next_payload":i}
  8029 
  8030 del(i)
  8031 del(name)
  8032 ISAKMP_class.overload_fields = ISAKMP_payload_type_overload.copy()
  8033 
  8034 
  8035         
  8036 
  8037 # Cisco Skinny protocol
  8038 
  8039 # shamelessly ripped from Ethereal dissector
  8040 skinny_messages = { 
  8041 # Station -> Callmanager
  8042   0x0000: "KeepAliveMessage",
  8043   0x0001: "RegisterMessage",
  8044   0x0002: "IpPortMessage",
  8045   0x0003: "KeypadButtonMessage",
  8046   0x0004: "EnblocCallMessage",
  8047   0x0005: "StimulusMessage",
  8048   0x0006: "OffHookMessage",
  8049   0x0007: "OnHookMessage",
  8050   0x0008: "HookFlashMessage",
  8051   0x0009: "ForwardStatReqMessage",
  8052   0x000A: "SpeedDialStatReqMessage",
  8053   0x000B: "LineStatReqMessage",
  8054   0x000C: "ConfigStatReqMessage",
  8055   0x000D: "TimeDateReqMessage",
  8056   0x000E: "ButtonTemplateReqMessage",
  8057   0x000F: "VersionReqMessage",
  8058   0x0010: "CapabilitiesResMessage",
  8059   0x0011: "MediaPortListMessage",
  8060   0x0012: "ServerReqMessage",
  8061   0x0020: "AlarmMessage",
  8062   0x0021: "MulticastMediaReceptionAck",
  8063   0x0022: "OpenReceiveChannelAck",
  8064   0x0023: "ConnectionStatisticsRes",
  8065   0x0024: "OffHookWithCgpnMessage",
  8066   0x0025: "SoftKeySetReqMessage",
  8067   0x0026: "SoftKeyEventMessage",
  8068   0x0027: "UnregisterMessage",
  8069   0x0028: "SoftKeyTemplateReqMessage",
  8070   0x0029: "RegisterTokenReq",
  8071   0x002A: "MediaTransmissionFailure",
  8072   0x002B: "HeadsetStatusMessage",
  8073   0x002C: "MediaResourceNotification",
  8074   0x002D: "RegisterAvailableLinesMessage",
  8075   0x002E: "DeviceToUserDataMessage",
  8076   0x002F: "DeviceToUserDataResponseMessage",
  8077   0x0030: "UpdateCapabilitiesMessage",
  8078   0x0031: "OpenMultiMediaReceiveChannelAckMessage",
  8079   0x0032: "ClearConferenceMessage",
  8080   0x0033: "ServiceURLStatReqMessage",
  8081   0x0034: "FeatureStatReqMessage",
  8082   0x0035: "CreateConferenceResMessage",
  8083   0x0036: "DeleteConferenceResMessage",
  8084   0x0037: "ModifyConferenceResMessage",
  8085   0x0038: "AddParticipantResMessage",
  8086   0x0039: "AuditConferenceResMessage",
  8087   0x0040: "AuditParticipantResMessage",
  8088   0x0041: "DeviceToUserDataVersion1Message",
  8089 # Callmanager -> Station */
  8090   0x0081: "RegisterAckMessage",
  8091   0x0082: "StartToneMessage",
  8092   0x0083: "StopToneMessage",
  8093   0x0085: "SetRingerMessage",
  8094   0x0086: "SetLampMessage",
  8095   0x0087: "SetHkFDetectMessage",
  8096   0x0088: "SetSpeakerModeMessage",
  8097   0x0089: "SetMicroModeMessage",
  8098   0x008A: "StartMediaTransmission",
  8099   0x008B: "StopMediaTransmission",
  8100   0x008C: "StartMediaReception",
  8101   0x008D: "StopMediaReception",
  8102   0x008F: "CallInfoMessage",
  8103   0x0090: "ForwardStatMessage",
  8104   0x0091: "SpeedDialStatMessage",
  8105   0x0092: "LineStatMessage",
  8106   0x0093: "ConfigStatMessage",
  8107   0x0094: "DefineTimeDate",
  8108   0x0095: "StartSessionTransmission",
  8109   0x0096: "StopSessionTransmission",
  8110   0x0097: "ButtonTemplateMessage",
  8111   0x0098: "VersionMessage",
  8112   0x0099: "DisplayTextMessage",
  8113   0x009A: "ClearDisplay",
  8114   0x009B: "CapabilitiesReqMessage",
  8115   0x009C: "EnunciatorCommandMessage",
  8116   0x009D: "RegisterRejectMessage",
  8117   0x009E: "ServerResMessage",
  8118   0x009F: "Reset",
  8119   0x0100: "KeepAliveAckMessage",
  8120   0x0101: "StartMulticastMediaReception",
  8121   0x0102: "StartMulticastMediaTransmission",
  8122   0x0103: "StopMulticastMediaReception",
  8123   0x0104: "StopMulticastMediaTransmission",
  8124   0x0105: "OpenReceiveChannel",
  8125   0x0106: "CloseReceiveChannel",
  8126   0x0107: "ConnectionStatisticsReq",
  8127   0x0108: "SoftKeyTemplateResMessage",
  8128   0x0109: "SoftKeySetResMessage",
  8129   0x0110: "SelectSoftKeysMessage",
  8130   0x0111: "CallStateMessage",
  8131   0x0112: "DisplayPromptStatusMessage",
  8132   0x0113: "ClearPromptStatusMessage",
  8133   0x0114: "DisplayNotifyMessage",
  8134   0x0115: "ClearNotifyMessage",
  8135   0x0116: "ActivateCallPlaneMessage",
  8136   0x0117: "DeactivateCallPlaneMessage",
  8137   0x0118: "UnregisterAckMessage",
  8138   0x0119: "BackSpaceReqMessage",
  8139   0x011A: "RegisterTokenAck",
  8140   0x011B: "RegisterTokenReject",
  8141   0x0042: "DeviceToUserDataResponseVersion1Message",
  8142   0x011C: "StartMediaFailureDetection",
  8143   0x011D: "DialedNumberMessage",
  8144   0x011E: "UserToDeviceDataMessage",
  8145   0x011F: "FeatureStatMessage",
  8146   0x0120: "DisplayPriNotifyMessage",
  8147   0x0121: "ClearPriNotifyMessage",
  8148   0x0122: "StartAnnouncementMessage",
  8149   0x0123: "StopAnnouncementMessage",
  8150   0x0124: "AnnouncementFinishMessage",
  8151   0x0127: "NotifyDtmfToneMessage",
  8152   0x0128: "SendDtmfToneMessage",
  8153   0x0129: "SubscribeDtmfPayloadReqMessage",
  8154   0x012A: "SubscribeDtmfPayloadResMessage",
  8155   0x012B: "SubscribeDtmfPayloadErrMessage",
  8156   0x012C: "UnSubscribeDtmfPayloadReqMessage",
  8157   0x012D: "UnSubscribeDtmfPayloadResMessage",
  8158   0x012E: "UnSubscribeDtmfPayloadErrMessage",
  8159   0x012F: "ServiceURLStatMessage",
  8160   0x0130: "CallSelectStatMessage",
  8161   0x0131: "OpenMultiMediaChannelMessage",
  8162   0x0132: "StartMultiMediaTransmission",
  8163   0x0133: "StopMultiMediaTransmission",
  8164   0x0134: "MiscellaneousCommandMessage",
  8165   0x0135: "FlowControlCommandMessage",
  8166   0x0136: "CloseMultiMediaReceiveChannel",
  8167   0x0137: "CreateConferenceReqMessage",
  8168   0x0138: "DeleteConferenceReqMessage",
  8169   0x0139: "ModifyConferenceReqMessage",
  8170   0x013A: "AddParticipantReqMessage",
  8171   0x013B: "DropParticipantReqMessage",
  8172   0x013C: "AuditConferenceReqMessage",
  8173   0x013D: "AuditParticipantReqMessage",
  8174   0x013F: "UserToDeviceDataVersion1Message",
  8175   }
  8176 
  8177 
  8178         
  8179 class Skinny(Packet):
  8180     name="Skinny"
  8181     fields_desc = [ LEIntField("len",0),
  8182                     LEIntField("res",0),
  8183                     LEIntEnumField("msg",0,skinny_messages) ]
  8184 
  8185 _rtp_payload_types = {
  8186     # http://www.iana.org/assignments/rtp-parameters
  8187     0:  'G.711 PCMU',    3:  'GSM',
  8188     4:  'G723',    5:  'DVI4',
  8189     6:  'DVI4',    7:  'LPC',
  8190     8:  'PCMA',    9:  'G722',
  8191     10: 'L16',     11: 'L16',
  8192     12: 'QCELP',   13: 'CN',
  8193     14: 'MPA',     15: 'G728',
  8194     16: 'DVI4',    17: 'DVI4',
  8195     18: 'G729',    25: 'CelB',
  8196     26: 'JPEG',    28: 'nv',
  8197     31: 'H261',    32: 'MPV',
  8198     33: 'MP2T',    34: 'H263' }
  8199 
  8200 class RTP(Packet):
  8201     name="RTP"
  8202     fields_desc = [ BitField('version', 2, 2),
  8203                     BitField('padding', 0, 1),
  8204                     BitField('extension', 0, 1),
  8205                     BitFieldLenField('numsync', None, 4, count_of='sync'),
  8206                     BitField('marker', 0, 1),
  8207                     BitEnumField('payload', 0, 7, _rtp_payload_types),
  8208                     ShortField('sequence', 0),
  8209                     IntField('timestamp', 0),
  8210                     IntField('sourcesync', 0),
  8211                     FieldListField('sync', [], IntField("id",0), count_from=lambda pkt:pkt.numsync) ]
  8212     
  8213 ### SEBEK
  8214 
  8215 
  8216 class SebekHead(Packet):
  8217     name = "Sebek header"
  8218     fields_desc = [ XIntField("magic", 0xd0d0d0),
  8219                     ShortField("version", 1),
  8220                     ShortEnumField("type", 0, {"read":0, "write":1,
  8221                                              "socket":2, "open":3}),
  8222                     IntField("counter", 0),
  8223                     IntField("time_sec", 0),
  8224                     IntField("time_usec", 0) ]
  8225     def mysummary(self):
  8226         return self.sprintf("Sebek Header v%SebekHead.version% %SebekHead.type%")
  8227 
  8228 # we need this because Sebek headers differ between v1 and v3, and
  8229 # between v3 type socket and v3 others
  8230 
  8231 class SebekV1(Packet):
  8232     name = "Sebek v1"
  8233     fields_desc = [ IntField("pid", 0),
  8234                     IntField("uid", 0),
  8235                     IntField("fd", 0),
  8236                     StrFixedLenField("command", "", 12),
  8237                     FieldLenField("data_length", None, "data",fmt="I"),
  8238                     StrLenField("data", "", length_from=lambda x:x.data_length) ]
  8239     def mysummary(self):
  8240         if isinstance(self.underlayer, SebekHead):
  8241             return self.underlayer.sprintf("Sebek v1 %SebekHead.type% (%SebekV1.command%)")
  8242         else:
  8243             return self.sprintf("Sebek v1 (%SebekV1.command%)")
  8244 
  8245 class SebekV3(Packet):
  8246     name = "Sebek v3"
  8247     fields_desc = [ IntField("parent_pid", 0),
  8248                     IntField("pid", 0),
  8249                     IntField("uid", 0),
  8250                     IntField("fd", 0),
  8251                     IntField("inode", 0),
  8252                     StrFixedLenField("command", "", 12),
  8253                     FieldLenField("data_length", None, "data",fmt="I"),
  8254                     StrLenField("data", "", length_from=lambda x:x.data_length) ]
  8255     def mysummary(self):
  8256         if isinstance(self.underlayer, SebekHead):
  8257             return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3.command%)")
  8258         else:
  8259             return self.sprintf("Sebek v3 (%SebekV3.command%)")
  8260 
  8261 class SebekV2(SebekV3):
  8262     def mysummary(self):
  8263         if isinstance(self.underlayer, SebekHead):
  8264             return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2.command%)")
  8265         else:
  8266             return self.sprintf("Sebek v2 (%SebekV2.command%)")
  8267 
  8268 class SebekV3Sock(Packet):
  8269     name = "Sebek v2 socket"
  8270     fields_desc = [ IntField("parent_pid", 0),
  8271                     IntField("pid", 0),
  8272                     IntField("uid", 0),
  8273                     IntField("fd", 0),
  8274                     IntField("inode", 0),
  8275                     StrFixedLenField("command", "", 12),
  8276                     IntField("data_length", 15),
  8277                     IPField("dip", "127.0.0.1"),
  8278                     ShortField("dport", 0),
  8279                     IPField("sip", "127.0.0.1"),
  8280                     ShortField("sport", 0),
  8281                     ShortEnumField("call", 0, { "bind":2,
  8282                                                 "connect":3, "listen":4,
  8283                                                "accept":5, "sendmsg":16,
  8284                                                "recvmsg":17, "sendto":11,
  8285                                                "recvfrom":12}),
  8286                     ByteEnumField("proto", 0, IP_PROTOS) ]
  8287     def mysummary(self):
  8288         if isinstance(self.underlayer, SebekHead):
  8289             return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3Sock.command%)")
  8290         else:
  8291             return self.sprintf("Sebek v3 socket (%SebekV3Sock.command%)")
  8292 
  8293 class SebekV2Sock(SebekV3Sock):
  8294     def mysummary(self):
  8295         if isinstance(self.underlayer, SebekHead):
  8296             return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2Sock.command%)")
  8297         else:
  8298             return self.sprintf("Sebek v2 socket (%SebekV2Sock.command%)")
  8299 
  8300 class MGCP(Packet):
  8301     name = "MGCP"
  8302     longname = "Media Gateway Control Protocol"
  8303     fields_desc = [ StrStopField("verb","AUEP"," ", -1),
  8304                     StrFixedLenField("sep1"," ",1),
  8305                     StrStopField("transaction_id","1234567"," ", -1),
  8306                     StrFixedLenField("sep2"," ",1),
  8307                     StrStopField("endpoint","dummy@dummy.net"," ", -1),
  8308                     StrFixedLenField("sep3"," ",1),
  8309                     StrStopField("version","MGCP 1.0 NCS 1.0","\x0a", -1),
  8310                     StrFixedLenField("sep4","\x0a",1),
  8311                     ]
  8312                     
  8313     
  8314 #class MGCP(Packet):
  8315 #    name = "MGCP"
  8316 #    longname = "Media Gateway Control Protocol"
  8317 #    fields_desc = [ ByteEnumField("type",0, ["request","response","others"]),
  8318 #                    ByteField("code0",0),
  8319 #                    ByteField("code1",0),
  8320 #                    ByteField("code2",0),
  8321 #                    ByteField("code3",0),
  8322 #                    ByteField("code4",0),
  8323 #                    IntField("trasid",0),
  8324 #                    IntField("req_time",0),
  8325 #                    ByteField("is_duplicate",0),
  8326 #                    ByteField("req_available",0) ]
  8327 #
  8328 class GPRS(Packet):
  8329     name = "GPRSdummy"
  8330     fields_desc = [
  8331         StrStopField("dummy","","\x65\x00\x00",1)
  8332         ]
  8333 
  8334 
  8335 class HCI_Hdr(Packet):
  8336     name = "HCI header"
  8337     fields_desc = [ ByteEnumField("type",2,{1:"command",2:"ACLdata",3:"SCOdata",4:"event",5:"vendor"}),]
  8338 
  8339     def mysummary(self):
  8340         return self.sprintf("HCI %type%")
  8341 
  8342 class HCI_ACL_Hdr(Packet):
  8343     name = "HCI ACL header"
  8344     fields_desc = [ ByteField("handle",0), # Actually, handle is 12 bits and flags is 4.
  8345                     ByteField("flags",0),  # I wait to write a LEBitField
  8346                     LEShortField("len",None), ]
  8347     def post_build(self, p, pay):
  8348         p += pay
  8349         if self.len is None:
  8350             l = len(p)-4
  8351             p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
  8352         return p
  8353                     
  8354 
  8355 class L2CAP_Hdr(Packet):
  8356     name = "L2CAP header"
  8357     fields_desc = [ LEShortField("len",None),
  8358                     LEShortEnumField("cid",0,{1:"control"}),]
  8359     
  8360     def post_build(self, p, pay):
  8361         p += pay
  8362         if self.len is None:
  8363             l = len(p)-4
  8364             p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
  8365         return p
  8366                     
  8367                 
  8368 
  8369 class L2CAP_CmdHdr(Packet):
  8370     name = "L2CAP command header"
  8371     fields_desc = [
  8372         ByteEnumField("code",8,{1:"rej",2:"conn_req",3:"conn_resp",
  8373                                 4:"conf_req",5:"conf_resp",6:"disconn_req",
  8374                                 7:"disconn_resp",8:"echo_req",9:"echo_resp",
  8375                                 10:"info_req",11:"info_resp"}),
  8376         ByteField("id",0),
  8377         LEShortField("len",None) ]
  8378     def post_build(self, p, pay):
  8379         p += pay
  8380         if self.len is None:
  8381             l = len(p)-4
  8382             p = p[:2]+chr(l&0xff)+chr((l>>8)&0xff)+p[4:]
  8383         return p
  8384     def answers(self, other):
  8385         if other.id == self.id:
  8386             if self.code == 1:
  8387                 return 1
  8388             if other.code in [2,4,6,8,10] and self.code == other.code+1:
  8389                 if other.code == 8:
  8390                     return 1
  8391                 return self.payload.answers(other.payload)
  8392         return 0
  8393 
  8394 class L2CAP_ConnReq(Packet):
  8395     name = "L2CAP Conn Req"
  8396     fields_desc = [ LEShortEnumField("psm",0,{1:"SDP",3:"RFCOMM",5:"telephony control"}),
  8397                     LEShortField("scid",0),
  8398                     ]
  8399 
  8400 class L2CAP_ConnResp(Packet):
  8401     name = "L2CAP Conn Resp"
  8402     fields_desc = [ LEShortField("dcid",0),
  8403                     LEShortField("scid",0),
  8404                     LEShortEnumField("result",0,["no_info","authen_pend","author_pend"]),
  8405                     LEShortEnumField("status",0,["success","pend","bad_psm",
  8406                                                "cr_sec_block","cr_no_mem"]),
  8407                     ]
  8408     def answers(self, other):
  8409         return self.scid == other.scid
  8410 
  8411 class L2CAP_CmdRej(Packet):
  8412     name = "L2CAP Command Rej"
  8413     fields_desc = [ LEShortField("reason",0),
  8414                     ]
  8415     
  8416 
  8417 class L2CAP_ConfReq(Packet):
  8418     name = "L2CAP Conf Req"
  8419     fields_desc = [ LEShortField("dcid",0),
  8420                     LEShortField("flags",0),
  8421                     ]
  8422 
  8423 class L2CAP_ConfResp(Packet):
  8424     name = "L2CAP Conf Resp"
  8425     fields_desc = [ LEShortField("scid",0),
  8426                     LEShortField("flags",0),
  8427                     LEShortEnumField("result",0,["success","unaccept","reject","unknown"]),
  8428                     ]
  8429     def answers(self, other):
  8430         return self.scid == other.scid
  8431 
  8432 
  8433 class L2CAP_DisconnReq(Packet):
  8434     name = "L2CAP Disconn Req"
  8435     fields_desc = [ LEShortField("dcid",0),
  8436                     LEShortField("scid",0), ]
  8437 
  8438 class L2CAP_DisconnResp(Packet):
  8439     name = "L2CAP Disconn Resp"
  8440     fields_desc = [ LEShortField("dcid",0),
  8441                     LEShortField("scid",0), ]
  8442     def answers(self, other):
  8443         return self.scid == other.scid
  8444 
  8445     
  8446 
  8447 class L2CAP_InfoReq(Packet):
  8448     name = "L2CAP Info Req"
  8449     fields_desc = [ LEShortEnumField("type",0,{1:"CL_MTU",2:"FEAT_MASK"}),
  8450                     StrField("data","")
  8451                     ]
  8452 
  8453 
  8454 class L2CAP_InfoResp(Packet):
  8455     name = "L2CAP Info Resp"
  8456     fields_desc = [ LEShortField("type",0),
  8457                     LEShortEnumField("result",0,["success","not_supp"]),
  8458                     StrField("data",""), ]
  8459     def answers(self, other):
  8460         return self.type == other.type
  8461 
  8462 
  8463 
  8464 
  8465 class NetBIOS_DS(Packet):
  8466     name = "NetBIOS datagram service"
  8467     fields_desc = [
  8468         ByteEnumField("type",17, {17:"direct_group"}),
  8469         ByteField("flags",0),
  8470         XShortField("id",0),
  8471         IPField("src","127.0.0.1"),
  8472         ShortField("sport",138),
  8473         ShortField("len",None),
  8474         ShortField("ofs",0),
  8475         NetBIOSNameField("srcname",""),
  8476         NetBIOSNameField("dstname",""),
  8477         ]
  8478     def post_build(self, p, pay):
  8479         p += pay
  8480         if self.len is None:
  8481             l = len(p)-14
  8482             p = p[:10]+struct.pack("!H", l)+p[12:]
  8483         return p
  8484         
  8485 #        ShortField("length",0),
  8486 #        ShortField("Delimitor",0),
  8487 #        ByteField("command",0),
  8488 #        ByteField("data1",0),
  8489 #        ShortField("data2",0),
  8490 #        ShortField("XMIt",0),
  8491 #        ShortField("RSPCor",0),
  8492 #        StrFixedLenField("dest","",16),
  8493 #        StrFixedLenField("source","",16),
  8494 #        
  8495 #        ]
  8496 #
  8497 
  8498 # IR
  8499 
  8500 class IrLAPHead(Packet):
  8501     name = "IrDA Link Access Protocol Header"
  8502     fields_desc = [ XBitField("Address", 0x7f, 7),
  8503                     BitEnumField("Type", 1, 1, {"Response":0,
  8504                                                 "Command":1})]
  8505 
  8506 class IrLAPCommand(Packet):
  8507     name = "IrDA Link Access Protocol Command"
  8508     fields_desc = [ XByteField("Control", 0),
  8509                     XByteField("Format identifier", 0),
  8510                     XIntField("Source address", 0),
  8511                     XIntField("Destination address", 0xffffffffL),
  8512                     XByteField("Discovery flags", 0x1),
  8513                     ByteEnumField("Slot number", 255, {"final":255}),
  8514                     XByteField("Version", 0)]
  8515 
  8516 
  8517 class IrLMP(Packet):
  8518     name = "IrDA Link Management Protocol"
  8519     fields_desc = [ XShortField("Service hints", 0),
  8520                     XByteField("Character set", 0),
  8521                     StrField("Device name", "") ]
  8522 
  8523 
  8524 #NetBIOS
  8525 
  8526 
  8527 # Name Query Request
  8528 # Node Status Request
  8529 class NBNSQueryRequest(Packet):
  8530     name="NBNS query request"
  8531     fields_desc = [ShortField("NAME_TRN_ID",0),
  8532                    ShortField("FLAGS", 0x0110),
  8533                    ShortField("QDCOUNT",1),
  8534                    ShortField("ANCOUNT",0),
  8535                    ShortField("NSCOUNT",0),
  8536                    ShortField("ARCOUNT",0),
  8537                    NetBIOSNameField("QUESTION_NAME","windows"),
  8538                    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"}),
  8539                    ByteField("NULL",0),
  8540                    ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8541                    ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"})]
  8542 
  8543 # Name Registration Request
  8544 # Name Refresh Request
  8545 # Name Release Request or Demand
  8546 class NBNSRequest(Packet):
  8547     name="NBNS request"
  8548     fields_desc = [ShortField("NAME_TRN_ID",0),
  8549                    ShortField("FLAGS", 0x2910),
  8550                    ShortField("QDCOUNT",1),
  8551                    ShortField("ANCOUNT",0),
  8552                    ShortField("NSCOUNT",0),
  8553                    ShortField("ARCOUNT",1),
  8554                    NetBIOSNameField("QUESTION_NAME","windows"),
  8555                    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"}),
  8556                    ByteField("NULL",0),
  8557                    ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8558                    ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"}),
  8559                    ShortEnumField("RR_NAME",0xC00C,{0xC00C:"Label String Pointer to QUESTION_NAME"}),
  8560                    ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8561                    ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  8562                    IntField("TTL", 0),
  8563                    ShortField("RDLENGTH", 6),
  8564                    BitEnumField("G",0,1,{0:"Unique name",1:"Group name"}),
  8565                    BitEnumField("OWNER NODE TYPE",00,2,{00:"B node",01:"P node",02:"M node",03:"H node"}),
  8566                    BitEnumField("UNUSED",0,13,{0:"Unused"}),
  8567                    IPField("NB_ADDRESS", "127.0.0.1")]
  8568 
  8569 # Name Query Response
  8570 # Name Registration Response
  8571 class NBNSQueryResponse(Packet):
  8572     name="NBNS query response"
  8573     fields_desc = [ShortField("NAME_TRN_ID",0),
  8574                    ShortField("FLAGS", 0x8500),
  8575                    ShortField("QDCOUNT",0),
  8576                    ShortField("ANCOUNT",1),
  8577                    ShortField("NSCOUNT",0),
  8578                    ShortField("ARCOUNT",0),
  8579                    NetBIOSNameField("RR_NAME","windows"),
  8580                    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"}),
  8581                    ByteField("NULL",0),
  8582                    ShortEnumField("QUESTION_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8583                    ShortEnumField("QUESTION_CLASS",1,{1:"INTERNET"}),
  8584                    IntField("TTL", 0x493e0),
  8585                    ShortField("RDLENGTH", 6),
  8586                    ShortField("NB_FLAGS", 0),
  8587                    IPField("NB_ADDRESS", "127.0.0.1")]
  8588 
  8589 # Name Query Response (negative)
  8590 # Name Release Response
  8591 class NBNSQueryResponseNegative(Packet):
  8592     name="NBNS query response (negative)"
  8593     fields_desc = [ShortField("NAME_TRN_ID",0), 
  8594                    ShortField("FLAGS", 0x8506),
  8595                    ShortField("QDCOUNT",0),
  8596                    ShortField("ANCOUNT",1),
  8597                    ShortField("NSCOUNT",0),
  8598                    ShortField("ARCOUNT",0),
  8599                    NetBIOSNameField("RR_NAME","windows"),
  8600                    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"}),
  8601                    ByteField("NULL",0),
  8602                    ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8603                    ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  8604                    IntField("TTL",0),
  8605                    ShortField("RDLENGTH",6),
  8606                    BitEnumField("G",0,1,{0:"Unique name",1:"Group name"}),
  8607                    BitEnumField("OWNER NODE TYPE",00,2,{00:"B node",01:"P node",02:"M node",03:"H node"}),
  8608                    BitEnumField("UNUSED",0,13,{0:"Unused"}),
  8609                    IPField("NB_ADDRESS", "127.0.0.1")]
  8610     
  8611 # Node Status Response
  8612 class NBNSNodeStatusResponse(Packet):
  8613     name="NBNS Node Status Response"
  8614     fields_desc = [ShortField("NAME_TRN_ID",0), 
  8615                    ShortField("FLAGS", 0x8500),
  8616                    ShortField("QDCOUNT",0),
  8617                    ShortField("ANCOUNT",1),
  8618                    ShortField("NSCOUNT",0),
  8619                    ShortField("ARCOUNT",0),
  8620                    NetBIOSNameField("RR_NAME","windows"),
  8621                    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"}),
  8622                    ByteField("NULL",0),
  8623                    ShortEnumField("RR_TYPE",0x21, {0x20:"NB",0x21:"NBSTAT"}),
  8624                    ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  8625                    IntField("TTL",0),
  8626                    ShortField("RDLENGTH",83),
  8627                    ByteField("NUM_NAMES",1)]
  8628 
  8629 # Service for Node Status Response
  8630 class NBNSNodeStatusResponseService(Packet):
  8631     name="NBNS Node Status Response Service"
  8632     fields_desc = [StrFixedLenField("NETBIOS_NAME","WINDOWS         ",15),
  8633                    ByteEnumField("SUFFIX",0,{0:"workstation",0x03:"messenger service",0x20:"file server service",0x1b:"domain master browser",0x1c:"domain controller", 0x1e:"browser election service"}),
  8634                    ByteField("NAME_FLAGS",0x4),
  8635                    ByteEnumField("UNUSED",0,{0:"unused"})]
  8636 
  8637 # End of Node Status Response packet
  8638 class NBNSNodeStatusResponseEnd(Packet):
  8639     name="NBNS Node Status Response"
  8640     fields_desc = [SourceMACField("MAC_ADDRESS"),
  8641                    BitField("STATISTICS",0,57*8)]
  8642 
  8643 # Wait for Acknowledgement Response
  8644 class NBNSWackResponse(Packet):
  8645     name="NBNS Wait for Acknowledgement Response"
  8646     fields_desc = [ShortField("NAME_TRN_ID",0),
  8647                    ShortField("FLAGS", 0xBC07),
  8648                    ShortField("QDCOUNT",0),
  8649                    ShortField("ANCOUNT",1),
  8650                    ShortField("NSCOUNT",0),
  8651                    ShortField("ARCOUNT",0),
  8652                    NetBIOSNameField("RR_NAME","windows"),
  8653                    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"}),
  8654                    ByteField("NULL",0),
  8655                    ShortEnumField("RR_TYPE",0x20, {0x20:"NB",0x21:"NBSTAT"}),
  8656                    ShortEnumField("RR_CLASS",1,{1:"INTERNET"}),
  8657                    IntField("TTL", 2),
  8658                    ShortField("RDLENGTH",2),
  8659                    BitField("RDATA",10512,16)] #10512=0010100100010000
  8660 
  8661 class NBTDatagram(Packet):
  8662     name="NBT Datagram Packet"
  8663     fields_desc= [ByteField("Type", 0x10),
  8664                   ByteField("Flags", 0x02),
  8665                   ShortField("ID", 0),
  8666                   IPField("SourceIP", "127.0.0.1"),
  8667                   ShortField("SourcePort", 138),
  8668                   ShortField("Length", 272),
  8669                   ShortField("Offset", 0),
  8670                   NetBIOSNameField("SourceName","windows"),
  8671                   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"}),
  8672                   ByteField("NULL",0),
  8673                   NetBIOSNameField("DestinationName","windows"),
  8674                   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"}),
  8675                   ByteField("NULL",0)]
  8676     
  8677 
  8678 class NBTSession(Packet):
  8679     name="NBT Session Packet"
  8680     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"}),
  8681                   BitField("RESERVED",0x00,7),
  8682                   BitField("LENGTH",0,17)]
  8683 
  8684 
  8685 # SMB NetLogon Response Header
  8686 class SMBNetlogon_Protocol_Response_Header(Packet):
  8687     name="SMBNetlogon Protocol Response Header"
  8688     fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  8689                    ByteEnumField("Command",0x25,{0x25:"Trans"}),
  8690                    ByteField("Error_Class",0x02),
  8691                    ByteField("Reserved",0),
  8692                    LEShortField("Error_code",4),
  8693                    ByteField("Flags",0),
  8694                    LEShortField("Flags2",0x0000),
  8695                    LEShortField("PIDHigh",0x0000),
  8696                    LELongField("Signature",0x0),
  8697                    LEShortField("Unused",0x0),
  8698                    LEShortField("TID",0),
  8699                    LEShortField("PID",0),
  8700                    LEShortField("UID",0),
  8701                    LEShortField("MID",0),
  8702                    ByteField("WordCount",17),
  8703                    LEShortField("TotalParamCount",0),
  8704                    LEShortField("TotalDataCount",112),
  8705                    LEShortField("MaxParamCount",0),
  8706                    LEShortField("MaxDataCount",0),
  8707                    ByteField("MaxSetupCount",0),
  8708                    ByteField("unused2",0),
  8709                    LEShortField("Flags3",0),
  8710                    ByteField("TimeOut1",0xe8),
  8711                    ByteField("TimeOut2",0x03),
  8712                    LEShortField("unused3",0),
  8713                    LEShortField("unused4",0),
  8714                    LEShortField("ParamCount2",0),
  8715                    LEShortField("ParamOffset",0),
  8716                    LEShortField("DataCount",112),
  8717                    LEShortField("DataOffset",92),
  8718                    ByteField("SetupCount", 3),
  8719                    ByteField("unused5", 0)]
  8720 
  8721 # SMB MailSlot Protocol
  8722 class SMBMailSlot(Packet):
  8723     name = "SMB Mail Slot Protocol"
  8724     fields_desc = [LEShortField("opcode", 1),
  8725                    LEShortField("priority", 1),
  8726                    LEShortField("class", 2),
  8727                    LEShortField("size", 135),
  8728                    StrNullField("name","\MAILSLOT\NET\GETDC660")]
  8729 
  8730 # SMB NetLogon Protocol Response Tail SAM
  8731 class SMBNetlogon_Protocol_Response_Tail_SAM(Packet):
  8732     name = "SMB Netlogon Protocol Response Tail SAM"
  8733     fields_desc = [ByteEnumField("Command", 0x17, {0x12:"SAM logon request", 0x17:"SAM Active directory Response"}),
  8734                    ByteField("unused", 0),
  8735                    ShortField("Data1", 0),
  8736                    ShortField("Data2", 0xfd01),
  8737                    ShortField("Data3", 0),
  8738                    ShortField("Data4", 0xacde),
  8739                    ShortField("Data5", 0x0fe5),
  8740                    ShortField("Data6", 0xd10a),
  8741                    ShortField("Data7", 0x374c),
  8742                    ShortField("Data8", 0x83e2),
  8743                    ShortField("Data9", 0x7dd9),
  8744                    ShortField("Data10", 0x3a16),
  8745                    ShortField("Data11", 0x73ff),
  8746                    ByteField("Data12", 0x04),
  8747                    StrFixedLenField("Data13", "rmff", 4),
  8748                    ByteField("Data14", 0x0),
  8749                    ShortField("Data16", 0xc018),
  8750                    ByteField("Data18", 0x0a),
  8751                    StrFixedLenField("Data20", "rmff-win2k", 10),
  8752                    ByteField("Data21", 0xc0),
  8753                    ShortField("Data22", 0x18c0),
  8754                    ShortField("Data23", 0x180a),
  8755                    StrFixedLenField("Data24", "RMFF-WIN2K", 10),
  8756                    ShortField("Data25", 0),
  8757                    ByteField("Data26", 0x17),
  8758                    StrFixedLenField("Data27", "Default-First-Site-Name", 23),
  8759                    ShortField("Data28", 0x00c0),
  8760                    ShortField("Data29", 0x3c10),
  8761                    ShortField("Data30", 0x00c0),
  8762                    ShortField("Data31", 0x0200),
  8763                    ShortField("Data32", 0x0),
  8764                    ShortField("Data33", 0xac14),
  8765                    ShortField("Data34", 0x0064),
  8766                    ShortField("Data35", 0x0),
  8767                    ShortField("Data36", 0x0),
  8768                    ShortField("Data37", 0x0),
  8769                    ShortField("Data38", 0x0),
  8770                    ShortField("Data39", 0x0d00),
  8771                    ShortField("Data40", 0x0),
  8772                    ShortField("Data41", 0xffff)]                   
  8773 
  8774 # SMB NetLogon Protocol Response Tail LM2.0
  8775 class SMBNetlogon_Protocol_Response_Tail_LM20(Packet):
  8776     name = "SMB Netlogon Protocol Response Tail LM20"
  8777     fields_desc = [ByteEnumField("Command",0x06,{0x06:"LM 2.0 Response to logon request"}),
  8778                    ByteField("unused", 0),
  8779                    StrFixedLenField("DblSlash", "\\\\", 2),
  8780                    StrNullField("ServerName","WIN"),
  8781                    LEShortField("LM20Token", 0xffff)]
  8782 
  8783 # SMBNegociate Protocol Request Header
  8784 class SMBNegociate_Protocol_Request_Header(Packet):
  8785     name="SMBNegociate Protocol Request Header"
  8786     fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  8787                    ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  8788                    ByteField("Error_Class",0),
  8789                    ByteField("Reserved",0),
  8790                    LEShortField("Error_code",0),
  8791                    ByteField("Flags",0x18),
  8792                    LEShortField("Flags2",0x0000),
  8793                    LEShortField("PIDHigh",0x0000),
  8794                    LELongField("Signature",0x0),
  8795                    LEShortField("Unused",0x0),
  8796                    LEShortField("TID",0),
  8797                    LEShortField("PID",1),
  8798                    LEShortField("UID",0),
  8799                    LEShortField("MID",2),
  8800                    ByteField("WordCount",0),
  8801                    LEShortField("ByteCount",12)]
  8802 
  8803 # SMB Negociate Protocol Request Tail
  8804 class SMBNegociate_Protocol_Request_Tail(Packet):
  8805     name="SMB Negociate Protocol Request Tail"
  8806     fields_desc=[ByteField("BufferFormat",0x02),
  8807                  StrNullField("BufferData","NT LM 0.12")]
  8808 
  8809 # SMBNegociate Protocol Response Advanced Security
  8810 class SMBNegociate_Protocol_Response_Advanced_Security(Packet):
  8811     name="SMBNegociate Protocol Response Advanced Security"
  8812     fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  8813                    ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  8814                    ByteField("Error_Class",0),
  8815                    ByteField("Reserved",0),
  8816                    LEShortField("Error_Code",0),
  8817                    ByteField("Flags",0x98),
  8818                    LEShortField("Flags2",0x0000),
  8819                    LEShortField("PIDHigh",0x0000),
  8820                    LELongField("Signature",0x0),
  8821                    LEShortField("Unused",0x0),
  8822                    LEShortField("TID",0),
  8823                    LEShortField("PID",1),
  8824                    LEShortField("UID",0),
  8825                    LEShortField("MID",2),
  8826                    ByteField("WordCount",17),
  8827                    LEShortField("DialectIndex",7),
  8828                    ByteField("SecurityMode",0x03),
  8829                    LEShortField("MaxMpxCount",50),
  8830                    LEShortField("MaxNumberVC",1),
  8831                    LEIntField("MaxBufferSize",16144),
  8832                    LEIntField("MaxRawSize",65536),
  8833                    LEIntField("SessionKey",0x0000),
  8834                    LEShortField("ServerCapabilities",0xf3f9),
  8835                    BitField("UnixExtensions",0,1),
  8836                    BitField("Reserved2",0,7),
  8837                    BitField("ExtendedSecurity",1,1),
  8838                    BitField("CompBulk",0,2),
  8839                    BitField("Reserved3",0,5),
  8840 # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
  8841                    LEIntField("ServerTimeHigh",0xD6228000L),
  8842                    LEIntField("ServerTimeLow",0x1C4EF94),
  8843                    LEShortField("ServerTimeZone",0x3c),
  8844                    ByteField("EncryptionKeyLength",0),
  8845                    LEFieldLenField("ByteCount", None, "SecurityBlob", adjust=lambda pkt,x:x-16),
  8846                    BitField("GUID",0,128),
  8847                    StrLenField("SecurityBlob", "", length_from=lambda x:x.ByteCount+16)]
  8848 
  8849 # SMBNegociate Protocol Response No Security
  8850 # When using no security, with EncryptionKeyLength=8, you must have an EncryptionKey before the DomainName
  8851 class SMBNegociate_Protocol_Response_No_Security(Packet):
  8852     name="SMBNegociate Protocol Response No Security"
  8853     fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  8854                    ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  8855                    ByteField("Error_Class",0),
  8856                    ByteField("Reserved",0),
  8857                    LEShortField("Error_Code",0),
  8858                    ByteField("Flags",0x98),
  8859                    LEShortField("Flags2",0x0000),
  8860                    LEShortField("PIDHigh",0x0000),
  8861                    LELongField("Signature",0x0),
  8862                    LEShortField("Unused",0x0),
  8863                    LEShortField("TID",0),
  8864                    LEShortField("PID",1),
  8865                    LEShortField("UID",0),
  8866                    LEShortField("MID",2),
  8867                    ByteField("WordCount",17),
  8868                    LEShortField("DialectIndex",7),
  8869                    ByteField("SecurityMode",0x03),
  8870                    LEShortField("MaxMpxCount",50),
  8871                    LEShortField("MaxNumberVC",1),
  8872                    LEIntField("MaxBufferSize",16144),
  8873                    LEIntField("MaxRawSize",65536),
  8874                    LEIntField("SessionKey",0x0000),
  8875                    LEShortField("ServerCapabilities",0xf3f9),
  8876                    BitField("UnixExtensions",0,1),
  8877                    BitField("Reserved2",0,7),
  8878                    BitField("ExtendedSecurity",0,1),
  8879                    FlagsField("CompBulk",0,2,"CB"),
  8880                    BitField("Reserved3",0,5),
  8881                    # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
  8882                    LEIntField("ServerTimeHigh",0xD6228000L),
  8883                    LEIntField("ServerTimeLow",0x1C4EF94),
  8884                    LEShortField("ServerTimeZone",0x3c),
  8885                    ByteField("EncryptionKeyLength",8),
  8886                    LEShortField("ByteCount",24),
  8887                    BitField("EncryptionKey",0,64),
  8888                    StrNullField("DomainName","WORKGROUP"),
  8889                    StrNullField("ServerName","RMFF1")]
  8890     
  8891 # SMBNegociate Protocol Response No Security No Key
  8892 class SMBNegociate_Protocol_Response_No_Security_No_Key(Packet):
  8893     namez="SMBNegociate Protocol Response No Security No Key"
  8894     fields_desc = [StrFixedLenField("Start","\xffSMB",4),
  8895                    ByteEnumField("Command",0x72,{0x72:"SMB_COM_NEGOTIATE"}),
  8896                    ByteField("Error_Class",0),
  8897                    ByteField("Reserved",0),
  8898                    LEShortField("Error_Code",0),
  8899                    ByteField("Flags",0x98),
  8900                    LEShortField("Flags2",0x0000),
  8901                    LEShortField("PIDHigh",0x0000),
  8902                    LELongField("Signature",0x0),
  8903                    LEShortField("Unused",0x0),
  8904                    LEShortField("TID",0),
  8905                    LEShortField("PID",1),
  8906                    LEShortField("UID",0),
  8907                    LEShortField("MID",2),
  8908                    ByteField("WordCount",17),
  8909                    LEShortField("DialectIndex",7),
  8910                    ByteField("SecurityMode",0x03),
  8911                    LEShortField("MaxMpxCount",50),
  8912                    LEShortField("MaxNumberVC",1),
  8913                    LEIntField("MaxBufferSize",16144),
  8914                    LEIntField("MaxRawSize",65536),
  8915                    LEIntField("SessionKey",0x0000),
  8916                    LEShortField("ServerCapabilities",0xf3f9),
  8917                    BitField("UnixExtensions",0,1),
  8918                    BitField("Reserved2",0,7),
  8919                    BitField("ExtendedSecurity",0,1),
  8920                    FlagsField("CompBulk",0,2,"CB"),
  8921                    BitField("Reserved3",0,5),
  8922                    # There have been 127490112000000000 tenths of micro-seconds between 1st january 1601 and 1st january 2005. 127490112000000000=0x1C4EF94D6228000, so ServerTimeHigh=0xD6228000 and ServerTimeLow=0x1C4EF94.
  8923                    LEIntField("ServerTimeHigh",0xD6228000L),
  8924                    LEIntField("ServerTimeLow",0x1C4EF94),
  8925                    LEShortField("ServerTimeZone",0x3c),
  8926                    ByteField("EncryptionKeyLength",0),
  8927                    LEShortField("ByteCount",16),
  8928                    StrNullField("DomainName","WORKGROUP"),
  8929                    StrNullField("ServerName","RMFF1")]
  8930     
  8931 # Session Setup AndX Request
  8932 class SMBSession_Setup_AndX_Request(Packet):
  8933     name="Session Setup AndX Request"
  8934     fields_desc=[StrFixedLenField("Start","\xffSMB",4),
  8935                 ByteEnumField("Command",0x73,{0x73:"SMB_COM_SESSION_SETUP_ANDX"}),
  8936                  ByteField("Error_Class",0),
  8937                  ByteField("Reserved",0),
  8938                  LEShortField("Error_Code",0),
  8939                  ByteField("Flags",0x18),
  8940                  LEShortField("Flags2",0x0001),
  8941                  LEShortField("PIDHigh",0x0000),
  8942                  LELongField("Signature",0x0),
  8943                  LEShortField("Unused",0x0),
  8944                  LEShortField("TID",0),
  8945                  LEShortField("PID",1),
  8946                  LEShortField("UID",0),
  8947                  LEShortField("MID",2),
  8948                  ByteField("WordCount",13),
  8949                  ByteEnumField("AndXCommand",0x75,{0x75:"SMB_COM_TREE_CONNECT_ANDX"}),
  8950                  ByteField("Reserved2",0),
  8951                  LEShortField("AndXOffset",96),
  8952                  LEShortField("MaxBufferS",2920),
  8953                  LEShortField("MaxMPXCount",50),
  8954                  LEShortField("VCNumber",0),
  8955                  LEIntField("SessionKey",0),
  8956                  LEFieldLenField("ANSIPasswordLength",None,"ANSIPassword"),
  8957                  LEShortField("UnicodePasswordLength",0),
  8958                  LEIntField("Reserved3",0),
  8959                  LEShortField("ServerCapabilities",0x05),
  8960                  BitField("UnixExtensions",0,1),
  8961                  BitField("Reserved4",0,7),
  8962                  BitField("ExtendedSecurity",0,1),
  8963                  BitField("CompBulk",0,2),
  8964                  BitField("Reserved5",0,5),
  8965                  LEShortField("ByteCount",35),
  8966                  StrLenField("ANSIPassword", "Pass",length_from=lambda x:x.ANSIPasswordLength),
  8967                  StrNullField("Account","GUEST"),
  8968                  StrNullField("PrimaryDomain",  ""),
  8969                  StrNullField("NativeOS","Windows 4.0"),
  8970                  StrNullField("NativeLanManager","Windows 4.0"),
  8971                  ByteField("WordCount2",4),
  8972                  ByteEnumField("AndXCommand2",0xFF,{0xFF:"SMB_COM_NONE"}),
  8973                  ByteField("Reserved6",0),
  8974                  LEShortField("AndXOffset2",0),
  8975                  LEShortField("Flags3",0x2),
  8976                  LEShortField("PasswordLength",0x1),
  8977                  LEShortField("ByteCount2",18),
  8978                  ByteField("Password",0),
  8979                  StrNullField("Path","\\\\WIN2K\\IPC$"),
  8980                  StrNullField("Service","IPC")]
  8981 
  8982 # Session Setup AndX Response
  8983 class SMBSession_Setup_AndX_Response(Packet):
  8984     name="Session Setup AndX Response"
  8985     fields_desc=[StrFixedLenField("Start","\xffSMB",4),
  8986                  ByteEnumField("Command",0x73,{0x73:"SMB_COM_SESSION_SETUP_ANDX"}),
  8987                  ByteField("Error_Class",0),
  8988                  ByteField("Reserved",0),
  8989                  LEShortField("Error_Code",0),
  8990                  ByteField("Flags",0x90),
  8991                  LEShortField("Flags2",0x1001),
  8992                  LEShortField("PIDHigh",0x0000),
  8993                  LELongField("Signature",0x0),
  8994                  LEShortField("Unused",0x0),
  8995                  LEShortField("TID",0),
  8996                  LEShortField("PID",1),
  8997                  LEShortField("UID",0),
  8998                  LEShortField("MID",2),
  8999                  ByteField("WordCount",3),
  9000                  ByteEnumField("AndXCommand",0x75,{0x75:"SMB_COM_TREE_CONNECT_ANDX"}),
  9001                  ByteField("Reserved2",0),
  9002                  LEShortField("AndXOffset",66),
  9003                  LEShortField("Action",0),
  9004                  LEShortField("ByteCount",25),
  9005                  StrNullField("NativeOS","Windows 4.0"),
  9006                  StrNullField("NativeLanManager","Windows 4.0"),
  9007                  StrNullField("PrimaryDomain",""),
  9008                  ByteField("WordCount2",3),
  9009                  ByteEnumField("AndXCommand2",0xFF,{0xFF:"SMB_COM_NONE"}),
  9010                  ByteField("Reserved3",0),
  9011                  LEShortField("AndXOffset2",80),
  9012                  LEShortField("OptionalSupport",0x01),
  9013                  LEShortField("ByteCount2",5),
  9014                  StrNullField("Service","IPC"),
  9015                  StrNullField("NativeFileSystem","")]
  9016 
  9017 class MobileIP(Packet):
  9018     name = "Mobile IP (RFC3344)"
  9019     fields_desc = [ ByteEnumField("type", 1, {1:"RRQ", 3:"RRP"}) ]
  9020 
  9021 class MobileIPRRQ(Packet):
  9022     name = "Mobile IP Registration Request (RFC3344)"
  9023     fields_desc = [ XByteField("flags", 0),
  9024                     ShortField("lifetime", 180),
  9025                     IPField("homeaddr", "0.0.0.0"),
  9026                     IPField("haaddr", "0.0.0.0"),
  9027                     IPField("coaddr", "0.0.0.0"),
  9028                     Field("id", "", "64s") ]
  9029 
  9030 class MobileIPRRP(Packet):
  9031     name = "Mobile IP Registration Reply (RFC3344)"
  9032     fields_desc = [ ByteField("code", 0),
  9033                     ShortField("lifetime", 180),
  9034                     IPField("homeaddr", "0.0.0.0"),
  9035                     IPField("haaddr", "0.0.0.0"),
  9036                     Field("id", "", "64s") ]
  9037 
  9038 class MobileIPTunnelData(Packet):
  9039     name = "Mobile IP Tunnel Data Message (RFC3519)"
  9040     fields_desc = [ ByteField("nexthdr", 4),
  9041                     ShortField("res", 0) ]
  9042 
  9043 
  9044 # Cisco Netflow Protocol version 1
  9045 class NetflowHeader(Packet):
  9046     name = "Netflow Header"
  9047     fields_desc = [ ShortField("version", 1) ]
  9048     
  9049 class NetflowHeaderV1(Packet):
  9050     name = "Netflow Header V1"
  9051     fields_desc = [ ShortField("count", 0),
  9052                     IntField("sysUptime", 0),
  9053                     IntField("unixSecs", 0),
  9054                     IntField("unixNanoSeconds", 0) ]
  9055 
  9056 
  9057 class NetflowRecordV1(Packet):
  9058     name = "Netflow Record"
  9059     fields_desc = [ IPField("ipsrc", "0.0.0.0"),
  9060                     IPField("ipdst", "0.0.0.0"),
  9061                     IPField("nexthop", "0.0.0.0"),
  9062                     ShortField("inputIfIndex", 0),
  9063                     ShortField("outpuIfIndex", 0),
  9064                     IntField("dpkts", 0),
  9065                     IntField("dbytes", 0),
  9066                     IntField("starttime", 0),
  9067                     IntField("endtime", 0),
  9068                     ShortField("srcport", 0),
  9069                     ShortField("dstport", 0),
  9070                     ShortField("padding", 0),
  9071                     ByteField("proto", 0),
  9072                     ByteField("tos", 0),
  9073                     IntField("padding1", 0),
  9074                     IntField("padding2", 0) ]
  9075 
  9076 
  9077 TFTP_operations = { 1:"RRQ",2:"WRQ",3:"DATA",4:"ACK",5:"ERROR",6:"OACK" }
  9078 
  9079 
  9080 class TFTP(Packet):
  9081     name = "TFTP opcode"
  9082     fields_desc = [ ShortEnumField("op", 1, TFTP_operations), ]
  9083     
  9084 
  9085 
  9086 class TFTP_RRQ(Packet):
  9087     name = "TFTP Read Request"
  9088     fields_desc = [ StrNullField("filename", ""),
  9089                     StrNullField("mode", "octet") ]
  9090     def answers(self, other):
  9091         return 0
  9092     def mysummary(self):
  9093         return self.sprintf("RRQ %filename%"),[UDP]
  9094         
  9095 
  9096 class TFTP_WRQ(Packet):
  9097     name = "TFTP Write Request"
  9098     fields_desc = [ StrNullField("filename", ""),
  9099                     StrNullField("mode", "octet") ]
  9100     def answers(self, other):
  9101         return 0
  9102     def mysummary(self):
  9103         return self.sprintf("WRQ %filename%"),[UDP]
  9104 
  9105 class TFTP_DATA(Packet):
  9106     name = "TFTP Data"
  9107     fields_desc = [ ShortField("block", 0) ]
  9108     def answers(self, other):
  9109         return  self.block == 1 and isinstance(other, TFTP_RRQ)
  9110     def mysummary(self):
  9111         return self.sprintf("DATA %block%"),[UDP]
  9112 
  9113 class TFTP_Option(Packet):
  9114     fields_desc = [ StrNullField("oname",""),
  9115                     StrNullField("value","") ]
  9116     def extract_padding(self, pkt):
  9117         return "",pkt
  9118 
  9119 class TFTP_Options(Packet):
  9120     fields_desc = [ PacketListField("options", [], TFTP_Option, length_from=lambda x:None) ]
  9121 
  9122     
  9123 class TFTP_ACK(Packet):
  9124     name = "TFTP Ack"
  9125     fields_desc = [ ShortField("block", 0) ]
  9126     def answers(self, other):
  9127         if isinstance(other, TFTP_DATA):
  9128             return self.block == other.block
  9129         elif isinstance(other, TFTP_RRQ) or isinstance(other, TFTP_WRQ) or isinstance(other, TFTP_OACK):
  9130             return self.block == 0
  9131         return 0
  9132     def mysummary(self):
  9133         return self.sprintf("ACK %block%"),[UDP]
  9134 
  9135 TFTP_Error_Codes = {  0: "Not defined",
  9136                       1: "File not found",
  9137                       2: "Access violation",
  9138                       3: "Disk full or allocation exceeded",
  9139                       4: "Illegal TFTP operation",
  9140                       5: "Unknown transfer ID",
  9141                       6: "File already exists",
  9142                       7: "No such user",
  9143                       8: "Terminate transfer due to option negotiation",
  9144                       }
  9145     
  9146 class TFTP_ERROR(Packet):
  9147     name = "TFTP Error"
  9148     fields_desc = [ ShortEnumField("errorcode", 0, TFTP_Error_Codes),
  9149                     StrNullField("errormsg", "")]
  9150     def answers(self, other):
  9151         return (isinstance(other, TFTP_DATA) or
  9152                 isinstance(other, TFTP_RRQ) or
  9153                 isinstance(other, TFTP_WRQ) or 
  9154                 isinstance(other, TFTP_ACK))
  9155     def mysummary(self):
  9156         return self.sprintf("ERROR %errorcode%: %errormsg%"),[UDP]
  9157 
  9158 
  9159 class TFTP_OACK(Packet):
  9160     name = "TFTP Option Ack"
  9161     fields_desc = [  ]
  9162     def answers(self, other):
  9163         return isinstance(other, TFTP_WRQ) or isinstance(other, TFTP_RRQ)
  9164 
  9165 
  9166 ##########
  9167 ## SNMP ##
  9168 ##########
  9169 
  9170 ######[ ASN1 class ]######
  9171 
  9172 class ASN1_Class_SNMP(ASN1_Class_UNIVERSAL):
  9173     name="SNMP"
  9174     PDU_GET = 0xa0
  9175     PDU_NEXT = 0xa1
  9176     PDU_RESPONSE = 0xa2
  9177     PDU_SET = 0xa3
  9178     PDU_TRAPv1 = 0xa4
  9179     PDU_BULK = 0xa5
  9180     PDU_INFORM = 0xa6
  9181     PDU_TRAPv2 = 0xa7
  9182 
  9183 
  9184 class ASN1_SNMP_PDU_GET(ASN1_SEQUENCE):
  9185     tag = ASN1_Class_SNMP.PDU_GET
  9186 
  9187 class ASN1_SNMP_PDU_NEXT(ASN1_SEQUENCE):
  9188     tag = ASN1_Class_SNMP.PDU_NEXT
  9189 
  9190 class ASN1_SNMP_PDU_RESPONSE(ASN1_SEQUENCE):
  9191     tag = ASN1_Class_SNMP.PDU_RESPONSE
  9192 
  9193 class ASN1_SNMP_PDU_SET(ASN1_SEQUENCE):
  9194     tag = ASN1_Class_SNMP.PDU_SET
  9195 
  9196 class ASN1_SNMP_PDU_TRAPv1(ASN1_SEQUENCE):
  9197     tag = ASN1_Class_SNMP.PDU_TRAPv1
  9198 
  9199 class ASN1_SNMP_PDU_BULK(ASN1_SEQUENCE):
  9200     tag = ASN1_Class_SNMP.PDU_BULK
  9201 
  9202 class ASN1_SNMP_PDU_INFORM(ASN1_SEQUENCE):
  9203     tag = ASN1_Class_SNMP.PDU_INFORM
  9204 
  9205 class ASN1_SNMP_PDU_TRAPv2(ASN1_SEQUENCE):
  9206     tag = ASN1_Class_SNMP.PDU_TRAPv2
  9207 
  9208 
  9209 ######[ BER codecs ]#######
  9210 
  9211 class BERcodec_SNMP_PDU_GET(BERcodec_SEQUENCE):
  9212     tag = ASN1_Class_SNMP.PDU_GET
  9213 
  9214 class BERcodec_SNMP_PDU_NEXT(BERcodec_SEQUENCE):
  9215     tag = ASN1_Class_SNMP.PDU_NEXT
  9216 
  9217 class BERcodec_SNMP_PDU_RESPONSE(BERcodec_SEQUENCE):
  9218     tag = ASN1_Class_SNMP.PDU_RESPONSE
  9219 
  9220 class BERcodec_SNMP_PDU_SET(BERcodec_SEQUENCE):
  9221     tag = ASN1_Class_SNMP.PDU_SET
  9222 
  9223 class BERcodec_SNMP_PDU_TRAPv1(BERcodec_SEQUENCE):
  9224     tag = ASN1_Class_SNMP.PDU_TRAPv1
  9225 
  9226 class BERcodec_SNMP_PDU_BULK(BERcodec_SEQUENCE):
  9227     tag = ASN1_Class_SNMP.PDU_BULK
  9228 
  9229 class BERcodec_SNMP_PDU_INFORM(BERcodec_SEQUENCE):
  9230     tag = ASN1_Class_SNMP.PDU_INFORM
  9231 
  9232 class BERcodec_SNMP_PDU_TRAPv2(BERcodec_SEQUENCE):
  9233     tag = ASN1_Class_SNMP.PDU_TRAPv2
  9234 
  9235 
  9236 
  9237 ######[ ASN1 fields ]######
  9238 
  9239 class ASN1F_SNMP_PDU_GET(ASN1F_SEQUENCE):
  9240     ASN1_tag = ASN1_Class_SNMP.PDU_GET
  9241 
  9242 class ASN1F_SNMP_PDU_NEXT(ASN1F_SEQUENCE):
  9243     ASN1_tag = ASN1_Class_SNMP.PDU_NEXT
  9244 
  9245 class ASN1F_SNMP_PDU_RESPONSE(ASN1F_SEQUENCE):
  9246     ASN1_tag = ASN1_Class_SNMP.PDU_RESPONSE
  9247 
  9248 class ASN1F_SNMP_PDU_SET(ASN1F_SEQUENCE):
  9249     ASN1_tag = ASN1_Class_SNMP.PDU_SET
  9250 
  9251 class ASN1F_SNMP_PDU_TRAPv1(ASN1F_SEQUENCE):
  9252     ASN1_tag = ASN1_Class_SNMP.PDU_TRAPv1
  9253 
  9254 class ASN1F_SNMP_PDU_BULK(ASN1F_SEQUENCE):
  9255     ASN1_tag = ASN1_Class_SNMP.PDU_BULK
  9256 
  9257 class ASN1F_SNMP_PDU_INFORM(ASN1F_SEQUENCE):
  9258     ASN1_tag = ASN1_Class_SNMP.PDU_INFORM
  9259 
  9260 class ASN1F_SNMP_PDU_TRAPv2(ASN1F_SEQUENCE):
  9261     ASN1_tag = ASN1_Class_SNMP.PDU_TRAPv2
  9262 
  9263 
  9264 
  9265 ######[ SNMP Packet ]######
  9266 
  9267 SNMP_error = { 0: "no_error",
  9268                1: "too_big",
  9269                2: "no_such_name",
  9270                3: "bad_value",
  9271                4: "read_only",
  9272                5: "generic_error",
  9273                6: "no_access",
  9274                7: "wrong_type",
  9275                8: "wrong_length",
  9276                9: "wrong_encoding",
  9277               10: "wrong_value",
  9278               11: "no_creation",
  9279               12: "inconsistent_value",
  9280               13: "ressource_unavailable",
  9281               14: "commit_failed",
  9282               15: "undo_failed",
  9283               16: "authorization_error",
  9284               17: "not_writable",
  9285               18: "inconsistent_name",
  9286                }
  9287 
  9288 SNMP_trap_types = { 0: "cold_start",
  9289                     1: "warm_start",
  9290                     2: "link_down",
  9291                     3: "link_up",
  9292                     4: "auth_failure",
  9293                     5: "egp_neigh_loss",
  9294                     6: "enterprise_specific",
  9295                     }
  9296 
  9297 class SNMPvarbind(ASN1_Packet):
  9298     ASN1_codec = ASN1_Codecs.BER
  9299     ASN1_root = ASN1F_SEQUENCE( ASN1F_OID("oid","1.3"),
  9300                                 ASN1F_field("value",ASN1_NULL(0))
  9301                                 )
  9302 
  9303 
  9304 class SNMPget(ASN1_Packet):
  9305     ASN1_codec = ASN1_Codecs.BER
  9306     ASN1_root = ASN1F_SNMP_PDU_GET( ASN1F_INTEGER("id",0),
  9307                                     ASN1F_enum_INTEGER("error",0, SNMP_error),
  9308                                     ASN1F_INTEGER("error_index",0),
  9309                                     ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9310                                     )
  9311 
  9312 class SNMPnext(ASN1_Packet):
  9313     ASN1_codec = ASN1_Codecs.BER
  9314     ASN1_root = ASN1F_SNMP_PDU_NEXT( ASN1F_INTEGER("id",0),
  9315                                      ASN1F_enum_INTEGER("error",0, SNMP_error),
  9316                                      ASN1F_INTEGER("error_index",0),
  9317                                      ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9318                                      )
  9319 
  9320 class SNMPresponse(ASN1_Packet):
  9321     ASN1_codec = ASN1_Codecs.BER
  9322     ASN1_root = ASN1F_SNMP_PDU_RESPONSE( ASN1F_INTEGER("id",0),
  9323                                          ASN1F_enum_INTEGER("error",0, SNMP_error),
  9324                                          ASN1F_INTEGER("error_index",0),
  9325                                          ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9326                                          )
  9327 
  9328 class SNMPset(ASN1_Packet):
  9329     ASN1_codec = ASN1_Codecs.BER
  9330     ASN1_root = ASN1F_SNMP_PDU_SET( ASN1F_INTEGER("id",0),
  9331                                     ASN1F_enum_INTEGER("error",0, SNMP_error),
  9332                                     ASN1F_INTEGER("error_index",0),
  9333                                     ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9334                                     )
  9335     
  9336 class SNMPtrapv1(ASN1_Packet):
  9337     ASN1_codec = ASN1_Codecs.BER
  9338     ASN1_root = ASN1F_SNMP_PDU_TRAPv1( ASN1F_INTEGER("id",0),
  9339                                        ASN1F_OID("enterprise", "1.3"),
  9340                                        ASN1F_STRING("agent_addr",""),
  9341                                        ASN1F_enum_INTEGER("generic_trap", 0, SNMP_trap_types),
  9342                                        ASN1F_INTEGER("specific_trap", 0),
  9343                                        ASN1F_INTEGER("time_stamp", IntAutoTime()),
  9344                                        ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9345                                        )
  9346 
  9347 class SNMPbulk(ASN1_Packet):
  9348     ASN1_codec = ASN1_Codecs.BER
  9349     ASN1_root = ASN1F_SNMP_PDU_BULK( ASN1F_INTEGER("id",0),
  9350                                      ASN1F_INTEGER("non_repeaters",0),
  9351                                      ASN1F_INTEGER("max_repetitions",0),
  9352                                      ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9353                                      )
  9354     
  9355 class SNMPinform(ASN1_Packet):
  9356     ASN1_codec = ASN1_Codecs.BER
  9357     ASN1_root = ASN1F_SNMP_PDU_INFORM( ASN1F_INTEGER("id",0),
  9358                                        ASN1F_enum_INTEGER("error",0, SNMP_error),
  9359                                        ASN1F_INTEGER("error_index",0),
  9360                                        ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9361                                        )
  9362     
  9363 class SNMPtrapv2(ASN1_Packet):
  9364     ASN1_codec = ASN1_Codecs.BER
  9365     ASN1_root = ASN1F_SNMP_PDU_TRAPv2( ASN1F_INTEGER("id",0),
  9366                                        ASN1F_enum_INTEGER("error",0, SNMP_error),
  9367                                        ASN1F_INTEGER("error_index",0),
  9368                                        ASN1F_SEQUENCE_OF("varbindlist", [], SNMPvarbind)
  9369                                        )
  9370     
  9371 
  9372 class SNMP(ASN1_Packet):
  9373     ASN1_codec = ASN1_Codecs.BER
  9374     ASN1_root = ASN1F_SEQUENCE(
  9375         ASN1F_enum_INTEGER("version", 1, {0:"v1", 1:"v2c", 2:"v2", 3:"v3"}),
  9376         ASN1F_STRING("community","public"),
  9377         ASN1F_CHOICE("PDU", SNMPget(),
  9378                      SNMPget, SNMPnext, SNMPresponse, SNMPset,
  9379                      SNMPtrapv1, SNMPbulk, SNMPinform, SNMPtrapv2)
  9380         )
  9381     def answers(self, other):
  9382         return ( isinstance(self.PDU, SNMPresponse)    and
  9383                  ( isinstance(other.PDU, SNMPget) or
  9384                    isinstance(other.PDU, SNMPnext) or
  9385                    isinstance(other.PDU, SNMPset)    ) and
  9386                  self.PDU.id == other.PDU.id )
  9387 
  9388 
  9389 ##########
  9390 ## X509 ##
  9391 ##########
  9392 
  9393 ######[ ASN1 class ]######
  9394 
  9395 class ASN1_Class_X509(ASN1_Class_UNIVERSAL):
  9396     name="X509"
  9397     CONT0 = 0xa0
  9398     CONT1 = 0xa1
  9399     CONT2 = 0xa2
  9400     CONT3 = 0xa3
  9401 
  9402 class ASN1_X509_CONT0(ASN1_SEQUENCE):
  9403     tag = ASN1_Class_X509.CONT0
  9404 
  9405 class ASN1_X509_CONT1(ASN1_SEQUENCE):
  9406     tag = ASN1_Class_X509.CONT1
  9407 
  9408 class ASN1_X509_CONT2(ASN1_SEQUENCE):
  9409     tag = ASN1_Class_X509.CONT2
  9410 
  9411 class ASN1_X509_CONT3(ASN1_SEQUENCE):
  9412     tag = ASN1_Class_X509.CONT3
  9413 
  9414 ######[ BER codecs ]#######
  9415 
  9416 class BERcodec_X509_CONT0(BERcodec_SEQUENCE):
  9417     tag = ASN1_Class_X509.CONT0
  9418 
  9419 class BERcodec_X509_CONT1(BERcodec_SEQUENCE):
  9420     tag = ASN1_Class_X509.CONT1
  9421     
  9422 class BERcodec_X509_CONT2(BERcodec_SEQUENCE):
  9423     tag = ASN1_Class_X509.CONT2
  9424     
  9425 class BERcodec_X509_CONT3(BERcodec_SEQUENCE):
  9426     tag = ASN1_Class_X509.CONT3
  9427 
  9428 ######[ ASN1 fields ]######
  9429 
  9430 class ASN1F_X509_CONT0(ASN1F_SEQUENCE):
  9431     ASN1_tag = ASN1_Class_X509.CONT0
  9432     
  9433 class ASN1F_X509_CONT1(ASN1F_SEQUENCE):
  9434     ASN1_tag = ASN1_Class_X509.CONT1
  9435     
  9436 class ASN1F_X509_CONT2(ASN1F_SEQUENCE):
  9437     ASN1_tag = ASN1_Class_X509.CONT2
  9438     
  9439 class ASN1F_X509_CONT3(ASN1F_SEQUENCE):
  9440     ASN1_tag = ASN1_Class_X509.CONT3
  9441 
  9442 ######[ X509 packets ]######
  9443 
  9444 class X509RDN(ASN1_Packet):
  9445     ASN1_codec = ASN1_Codecs.BER
  9446     ASN1_root = ASN1F_SET(
  9447                   ASN1F_SEQUENCE( ASN1F_OID("oid","2.5.4.6"),
  9448                                   ASN1F_PRINTABLE_STRING("value","")
  9449                                   )
  9450                   )
  9451 
  9452 class X509v3Ext(ASN1_Packet):
  9453     ASN1_codec = ASN1_Codecs.BER
  9454     ASN1_root = ASN1F_field("val",ASN1_NULL(0))
  9455     
  9456 
  9457 class X509Cert(ASN1_Packet):
  9458     ASN1_codec = ASN1_Codecs.BER
  9459     ASN1_root = ASN1F_SEQUENCE(
  9460         ASN1F_SEQUENCE(
  9461             ASN1F_optionnal(ASN1F_X509_CONT0(ASN1F_INTEGER("version",3))),
  9462             ASN1F_INTEGER("sn",1),
  9463             ASN1F_SEQUENCE(ASN1F_OID("sign_algo","1.2.840.113549.1.1.5"),
  9464                            ASN1F_field("sa_value",ASN1_NULL(0))),
  9465             ASN1F_SEQUENCE_OF("issuer",[],X509RDN),
  9466             ASN1F_SEQUENCE(ASN1F_UTC_TIME("not_before",ZuluTime(-600)),  # ten minutes ago
  9467                            ASN1F_UTC_TIME("not_after",ZuluTime(+86400))), # for 24h
  9468             ASN1F_SEQUENCE_OF("subject",[],X509RDN),
  9469             ASN1F_SEQUENCE(
  9470                 ASN1F_SEQUENCE(ASN1F_OID("pubkey_algo","1.2.840.113549.1.1.1"),
  9471                                ASN1F_field("pk_value",ASN1_NULL(0))),
  9472                 ASN1F_BIT_STRING("pubkey","")
  9473                 ),
  9474             ASN1F_optionnal(ASN1F_X509_CONT3(ASN1F_SEQUENCE_OF("x509v3ext",[],X509v3Ext))),
  9475             
  9476         ),
  9477         ASN1F_SEQUENCE(ASN1F_OID("sign_algo2","1.2.840.113549.1.1.5"),
  9478                        ASN1F_field("sa2_value",ASN1_NULL(0))),
  9479         ASN1F_BIT_STRING("signature","")
  9480         )
  9481 
  9482 
  9483 
  9484 
  9485 #################
  9486 ## Bind layers ##
  9487 #################
  9488 
  9489 
  9490 def bind_bottom_up(lower, upper, __fval=None, **fval):
  9491     if __fval is not None:
  9492         fval.update(__fval)
  9493     lower.payload_guess = lower.payload_guess[:]
  9494     lower.payload_guess.append((fval, upper))
  9495     
  9496 
  9497 def bind_top_down(lower, upper, __fval=None, **fval):
  9498     if __fval is not None:
  9499         fval.update(__fval)
  9500     upper.overload_fields = upper.overload_fields.copy()
  9501     upper.overload_fields[lower] = fval
  9502     
  9503 def bind_layers(lower, upper, __fval=None, **fval):
  9504     if __fval is not None:
  9505         fval.update(__fval)
  9506     bind_top_down(lower, upper, **fval)
  9507     bind_bottom_up(lower, upper, **fval)
  9508 
  9509 def split_bottom_up(lower, upper, __fval=None, **fval):
  9510     if __fval is not None:
  9511         fval.update(__fval)
  9512     def do_filter((f,u),upper=upper,fval=fval):
  9513         if u != upper:
  9514             return True
  9515         for k in fval:
  9516             if k not in f or f[k] != fval[k]:
  9517                 return True
  9518         return False
  9519     lower.payload_guess = filter(do_filter, lower.payload_guess)
  9520         
  9521 def split_top_down(lower, upper, __fval=None, **fval):
  9522     if __fval is not None:
  9523         fval.update(__fval)
  9524     if lower in upper.overload_fields:
  9525         ofval = upper.overload_fields[lower]
  9526         for k in fval:
  9527             if k not in ofval or ofval[k] != fval[k]:
  9528                 return
  9529         upper.overload_fields = upper.overload_fields.copy()
  9530         del(upper.overload_fields[lower])
  9531 
  9532 def split_layers(lower, upper, __fval=None, **fval):
  9533     if __fval is not None:
  9534         fval.update(__fval)
  9535     split_bottom_up(lower, upper, **fval)
  9536     split_top_down(lower, upper, **fval)
  9537 
  9538 
  9539 bind_layers( Dot3,          LLC,           )
  9540 bind_layers( GPRS,          IP,            )
  9541 bind_layers( PrismHeader,   Dot11,         )
  9542 bind_layers( RadioTap,      Dot11,         )
  9543 bind_layers( Dot11,         LLC,           type=2)
  9544 bind_layers( Dot11QoS,      LLC,           )
  9545 bind_layers( L2TP,          PPP,           )
  9546 bind_layers( HDLC,          PPP,           )
  9547 bind_layers( PPP,           IP,            proto=33)
  9548 bind_layers( PPP,           PPP_IPCP,      proto=0x8021)
  9549 bind_layers( PPP,           PPP_ECP,       proto=0x8053)
  9550 bind_layers( Ether,         LLC,           type=122)
  9551 bind_layers( Ether,         Dot1Q,         type=33024)
  9552 bind_layers( Ether,         Ether,         type=1)
  9553 bind_layers( Ether,         ARP,           type=2054)
  9554 bind_layers( Ether,         IP,            type=2048)
  9555 bind_layers( Ether,         EAPOL,         type=34958)
  9556 bind_layers( Ether,         EAPOL,         dst='01:80:c2:00:00:03', type=34958)
  9557 bind_layers( Ether,         PPPoED,        type=34915)
  9558 bind_layers( Ether,         PPPoE,         type=34916)
  9559 bind_layers( CookedLinux,   LLC,           proto=122)
  9560 bind_layers( CookedLinux,   Dot1Q,         proto=33024)
  9561 bind_layers( CookedLinux,   Ether,         proto=1)
  9562 bind_layers( CookedLinux,   ARP,           proto=2054)
  9563 bind_layers( CookedLinux,   IP,            proto=2048)
  9564 bind_layers( CookedLinux,   EAPOL,         proto=34958)
  9565 bind_layers( CookedLinux,   PPPoED,        proto=34915)
  9566 bind_layers( CookedLinux,   PPPoE,         proto=34916)
  9567 bind_layers( GRE,           LLC,           proto=122)
  9568 bind_layers( GRE,           Dot1Q,         proto=33024)
  9569 bind_layers( GRE,           Ether,         proto=1)
  9570 bind_layers( GRE,           ARP,           proto=2054)
  9571 bind_layers( GRE,           IP,            proto=2048)
  9572 bind_layers( GRE,           EAPOL,         proto=34958)
  9573 bind_layers( PPPoE,         PPP,           code=0)
  9574 bind_layers( EAPOL,         EAP,           type=0)
  9575 bind_layers( LLC,           STP,           dsap=66, ssap=66, ctrl=3)
  9576 bind_layers( LLC,           SNAP,          dsap=170, ssap=170, ctrl=3)
  9577 bind_layers( SNAP,          Dot1Q,         code=33024)
  9578 bind_layers( SNAP,          Ether,         code=1)
  9579 bind_layers( SNAP,          ARP,           code=2054)
  9580 bind_layers( SNAP,          IP,            code=2048)
  9581 bind_layers( SNAP,          EAPOL,         code=34958)
  9582 bind_layers( SNAP,          STP,           code=267)
  9583 bind_layers( IPerror,       IPerror,       frag=0, proto=4)
  9584 bind_layers( IPerror,       ICMPerror,     frag=0, proto=1)
  9585 bind_layers( IPerror,       TCPerror,      frag=0, proto=6)
  9586 bind_layers( IPerror,       UDPerror,      frag=0, proto=17)
  9587 bind_layers( IP,            IP,            frag=0, proto=4)
  9588 bind_layers( IP,            ICMP,          frag=0, proto=1)
  9589 bind_layers( IP,            TCP,           frag=0, proto=6)
  9590 bind_layers( IP,            UDP,           frag=0, proto=17)
  9591 bind_layers( IP,            GRE,           frag=0, proto=47)
  9592 bind_layers( UDP,           L2TP,          sport=1701, dport=1701)
  9593 bind_layers( UDP,           SNMP,          sport=161)
  9594 bind_layers( UDP,           SNMP,          dport=161)
  9595 bind_layers( UDP,           MGCP,          dport=2727)
  9596 bind_layers( UDP,           MGCP,          sport=2727)
  9597 bind_layers( UDP,           DNS,           dport=53)
  9598 bind_layers( UDP,           DNS,           sport=53)
  9599 bind_layers( UDP,           ISAKMP,        dport=500, sport=500)
  9600 bind_layers( UDP,           HSRP,          dport=1985, sport=1985)
  9601 bind_layers( UDP,           NTP,           dport=123, sport=123)
  9602 bind_layers( UDP,           BOOTP,         dport=67, sport=68)
  9603 bind_layers( UDP,           BOOTP,         dport=68, sport=67)
  9604 bind_layers( BOOTP,         DHCP,          options='c\x82Sc')
  9605 bind_layers( UDP,           RIP,           sport=520)
  9606 bind_layers( UDP,           RIP,           dport=520)
  9607 bind_layers( RIP,           RIPEntry,      )
  9608 bind_layers( RIPEntry,      RIPEntry,      )
  9609 bind_layers( Dot11,         Dot11AssoReq,    subtype=0, type=0)
  9610 bind_layers( Dot11,         Dot11AssoResp,   subtype=1, type=0)
  9611 bind_layers( Dot11,         Dot11ReassoReq,  subtype=2, type=0)
  9612 bind_layers( Dot11,         Dot11ReassoResp, subtype=3, type=0)
  9613 bind_layers( Dot11,         Dot11ProbeReq,   subtype=4, type=0)
  9614 bind_layers( Dot11,         Dot11ProbeResp,  subtype=5, type=0)
  9615 bind_layers( Dot11,         Dot11Beacon,     subtype=8, type=0)
  9616 bind_layers( Dot11,         Dot11ATIM,       subtype=9, type=0)
  9617 bind_layers( Dot11,         Dot11Disas,      subtype=10, type=0)
  9618 bind_layers( Dot11,         Dot11Auth,       subtype=11, type=0)
  9619 bind_layers( Dot11,         Dot11Deauth,     subtype=12, type=0)
  9620 bind_layers( Dot11Beacon,     Dot11Elt,    )
  9621 bind_layers( Dot11AssoReq,    Dot11Elt,    )
  9622 bind_layers( Dot11AssoResp,   Dot11Elt,    )
  9623 bind_layers( Dot11ReassoReq,  Dot11Elt,    )
  9624 bind_layers( Dot11ReassoResp, Dot11Elt,    )
  9625 bind_layers( Dot11ProbeReq,   Dot11Elt,    )
  9626 bind_layers( Dot11ProbeResp,  Dot11Elt,    )
  9627 bind_layers( Dot11Auth,       Dot11Elt,    )
  9628 bind_layers( Dot11Elt,        Dot11Elt,    )
  9629 bind_layers( TCP,           Skinny,        dport=2000)
  9630 bind_layers( TCP,           Skinny,        sport=2000)
  9631 bind_layers( UDP,           SebekHead,     sport=1101)
  9632 bind_layers( UDP,           SebekHead,     dport=1101)
  9633 bind_layers( UDP,           SebekHead,     dport=1101, sport=1101)
  9634 bind_layers( SebekHead,     SebekV1,       version=1)
  9635 bind_layers( SebekHead,     SebekV2Sock,   version=2, type=2)
  9636 bind_layers( SebekHead,     SebekV2,       version=2)
  9637 bind_layers( SebekHead,     SebekV3Sock,   version=3, type=2)
  9638 bind_layers( SebekHead,     SebekV3,       version=3)
  9639 bind_layers( CookedLinux,   IrLAPHead,     proto=23)
  9640 bind_layers( IrLAPHead,     IrLAPCommand,  Type=1)
  9641 bind_layers( IrLAPCommand,  IrLMP,         )
  9642 bind_layers( UDP,           NBNSQueryRequest,  dport=137)
  9643 bind_layers( UDP,           NBNSRequest,       dport=137)
  9644 bind_layers( UDP,           NBNSQueryResponse, sport=137)
  9645 bind_layers( UDP,           NBNSQueryResponseNegative, sport=137)
  9646 bind_layers( UDP,           NBNSNodeStatusResponse,    sport=137)
  9647 bind_layers( NBNSNodeStatusResponse,        NBNSNodeStatusResponseService, )
  9648 bind_layers( NBNSNodeStatusResponse,        NBNSNodeStatusResponseService, )
  9649 bind_layers( NBNSNodeStatusResponseService, NBNSNodeStatusResponseService, )
  9650 bind_layers( NBNSNodeStatusResponseService, NBNSNodeStatusResponseEnd, )
  9651 bind_layers( UDP,           NBNSWackResponse, sport=137)
  9652 bind_layers( UDP,           NBTDatagram,      dport=138)
  9653 bind_layers( TCP,           NBTSession,       dport=139)
  9654 bind_layers( NBTSession,                           SMBNegociate_Protocol_Request_Header, )
  9655 bind_layers( SMBNegociate_Protocol_Request_Header, SMBNegociate_Protocol_Request_Tail, )
  9656 bind_layers( SMBNegociate_Protocol_Request_Tail,   SMBNegociate_Protocol_Request_Tail, )
  9657 bind_layers( NBTSession,    SMBNegociate_Protocol_Response_Advanced_Security,  ExtendedSecurity=1)
  9658 bind_layers( NBTSession,    SMBNegociate_Protocol_Response_No_Security,        ExtendedSecurity=0, EncryptionKeyLength=8)
  9659 bind_layers( NBTSession,    SMBNegociate_Protocol_Response_No_Security_No_Key, ExtendedSecurity=0, EncryptionKeyLength=0)
  9660 bind_layers( NBTSession,    SMBSession_Setup_AndX_Request, )
  9661 bind_layers( NBTSession,    SMBSession_Setup_AndX_Response, )
  9662 bind_layers( HCI_Hdr,       HCI_ACL_Hdr,   type=2)
  9663 bind_layers( HCI_Hdr,       Raw,           )
  9664 bind_layers( HCI_ACL_Hdr,   L2CAP_Hdr,     )
  9665 bind_layers( L2CAP_Hdr,     L2CAP_CmdHdr,      cid=1)
  9666 bind_layers( L2CAP_CmdHdr,  L2CAP_CmdRej,      code=1)
  9667 bind_layers( L2CAP_CmdHdr,  L2CAP_ConnReq,     code=2)
  9668 bind_layers( L2CAP_CmdHdr,  L2CAP_ConnResp,    code=3)
  9669 bind_layers( L2CAP_CmdHdr,  L2CAP_ConfReq,     code=4)
  9670 bind_layers( L2CAP_CmdHdr,  L2CAP_ConfResp,    code=5)
  9671 bind_layers( L2CAP_CmdHdr,  L2CAP_DisconnReq,  code=6)
  9672 bind_layers( L2CAP_CmdHdr,  L2CAP_DisconnResp, code=7)
  9673 bind_layers( L2CAP_CmdHdr,  L2CAP_InfoReq,     code=10)
  9674 bind_layers( L2CAP_CmdHdr,  L2CAP_InfoResp,    code=11)
  9675 bind_layers( UDP,           MobileIP,           sport=434)
  9676 bind_layers( UDP,           MobileIP,           dport=434)
  9677 bind_layers( MobileIP,      MobileIPRRQ,        type=1)
  9678 bind_layers( MobileIP,      MobileIPRRP,        type=3)
  9679 bind_layers( MobileIP,      MobileIPTunnelData, type=4)
  9680 bind_layers( MobileIPTunnelData, IP,           nexthdr=4)
  9681 bind_layers( NetflowHeader,   NetflowHeaderV1, version=1)
  9682 bind_layers( NetflowHeaderV1, NetflowRecordV1, )
  9683 
  9684 bind_layers(UDP, TFTP, dport=69)
  9685 bind_layers(TFTP, TFTP_RRQ, op=1)
  9686 bind_layers(TFTP, TFTP_WRQ, op=2)
  9687 bind_layers(TFTP, TFTP_DATA, op=3)
  9688 bind_layers(TFTP, TFTP_ACK, op=4)
  9689 bind_layers(TFTP, TFTP_ERROR, op=5)
  9690 bind_layers(TFTP, TFTP_OACK, op=6)
  9691 bind_layers(TFTP_RRQ, TFTP_Options)
  9692 bind_layers(TFTP_WRQ, TFTP_Options)
  9693 bind_layers(TFTP_OACK, TFTP_Options)
  9694 
  9695 
  9696 ###################
  9697 ## Fragmentation ##
  9698 ###################
  9699 
  9700 def fragment(pkt, fragsize=1480):
  9701     fragsize = (fragsize+7)/8*8
  9702     lst = []
  9703     for p in pkt:
  9704         s = str(p[IP].payload)
  9705         nb = (len(s)+fragsize-1)/fragsize
  9706         for i in range(nb):            
  9707             q = p.copy()
  9708             del(q[IP].payload)
  9709             del(q[IP].chksum)
  9710             del(q[IP].len)
  9711             if i == nb-1:
  9712                 q[IP].flags &= ~1
  9713             else:
  9714                 q[IP].flags |= 1 
  9715             q[IP].frag = i*fragsize/8
  9716             r = Raw(load=s[i*fragsize:(i+1)*fragsize])
  9717             r.overload_fields = p[IP].payload.overload_fields.copy()
  9718             q.add_payload(r)
  9719             lst.append(q)
  9720     return lst
  9721 
  9722 def overlap_frag(p, overlap, fragsize=8, overlap_fragsize=None):
  9723     if overlap_fragsize is None:
  9724         overlap_fragsize = fragsize
  9725     q = p.copy()
  9726     del(q[IP].payload)
  9727     q[IP].add_payload(overlap)
  9728 
  9729     qfrag = fragment(q, overlap_fragsize)
  9730     qfrag[-1][IP].flags |= 1
  9731     return qfrag+fragment(p, fragsize)
  9732 
  9733 def defrag(plist):
  9734     """defrag(plist) -> ([not fragmented], [defragmented],
  9735                   [ [bad fragments], [bad fragments], ... ])"""
  9736     frags = {}
  9737     nofrag = PacketList()
  9738     for p in plist:
  9739         ip = p[IP]
  9740         if IP not in p:
  9741             nofrag.append(p)
  9742             continue
  9743         if ip.frag == 0 and ip.flags & 1 == 0:
  9744             nofrag.append(p)
  9745             continue
  9746         uniq = (ip.id,ip.src,ip.dst,ip.proto)
  9747         if uniq in frags:
  9748             frags[uniq].append(p)
  9749         else:
  9750             frags[uniq] = PacketList([p])
  9751     defrag = []
  9752     missfrag = []
  9753     for lst in frags.itervalues():
  9754         lst.sort(lambda x,y:cmp(x.frag, y.frag))
  9755         p = lst[0]
  9756         if p.frag > 0:
  9757             missfrag.append(lst)
  9758             continue
  9759         p = p.copy()
  9760         if Padding in p:
  9761             del(p[Padding].underlayer.payload)
  9762         ip = p[IP]
  9763         if ip.len is None or ip.ihl is None:
  9764             clen = len(ip.payload)
  9765         else:
  9766             clen = ip.len - (ip.ihl<<2)
  9767         txt = Raw()
  9768         for q in lst[1:]:
  9769             if clen != q.frag<<3:
  9770                 if clen > q.frag<<3:
  9771                     warning("Fragment overlap (%i > %i) %r || %r ||  %r" % (clen, q.frag<<3, p,txt,q))
  9772                 missfrag.append(lst)
  9773                 txt = None
  9774                 break
  9775             if q[IP].len is None or q[IP].ihl is None:
  9776                 clen += len(q[IP].payload)
  9777             else:
  9778                 clen += q[IP].len - (q[IP].ihl<<2)
  9779             if Padding in q:
  9780                 del(q[Padding].underlayer.payload)
  9781             txt.add_payload(q[IP].payload.copy())
  9782             
  9783         if txt is None:
  9784             continue
  9785 
  9786         ip.flags &= ~1 # !MF
  9787         del(ip.chksum)
  9788         del(ip.len)
  9789         p = p/txt
  9790         defrag.append(p)
  9791     defrag2=PacketList()
  9792     for p in defrag:
  9793         defrag2.append(p.__class__(str(p)))
  9794     return nofrag,defrag2,missfrag
  9795             
  9796 def defragment(plist):
  9797     """defrag(plist) -> plist defragmented as much as possible """
  9798     frags = {}
  9799     final = []
  9800 
  9801     pos = 0
  9802     for p in plist:
  9803         p._defrag_pos = pos
  9804         pos += 1
  9805         if IP in p:
  9806             ip = p[IP]
  9807             if ip.frag != 0 or ip.flags & 1:
  9808                 ip = p[IP]
  9809                 uniq = (ip.id,ip.src,ip.dst,ip.proto)
  9810                 if uniq in frags:
  9811                     frags[uniq].append(p)
  9812                 else:
  9813                     frags[uniq] = [p]
  9814                 continue
  9815         final.append(p)
  9816 
  9817     defrag = []
  9818     missfrag = []
  9819     for lst in frags.itervalues():
  9820         lst.sort(lambda x,y:cmp(x.frag, y.frag))
  9821         p = lst[0]
  9822         if p.frag > 0:
  9823             missfrag += lst
  9824             continue
  9825         p = p.copy()
  9826         if Padding in p:
  9827             del(p[Padding].underlayer.payload)
  9828         ip = p[IP]
  9829         if ip.len is None or ip.ihl is None:
  9830             clen = len(ip.payload)
  9831         else:
  9832             clen = ip.len - (ip.ihl<<2)
  9833         txt = Raw()
  9834         for q in lst[1:]:
  9835             if clen != q.frag<<3:
  9836                 if clen > q.frag<<3:
  9837                     warning("Fragment overlap (%i > %i) %r || %r ||  %r" % (clen, q.frag<<3, p,txt,q))
  9838                 missfrag += lst
  9839                 txt = None
  9840                 break
  9841             if q[IP].len is None or q[IP].ihl is None:
  9842                 clen += len(q[IP].payload)
  9843             else:
  9844                 clen += q[IP].len - (q[IP].ihl<<2)
  9845             if Padding in q:
  9846                 del(q[Padding].underlayer.payload)
  9847             txt.add_payload(q[IP].payload.copy())
  9848             
  9849         if txt is None:
  9850             continue
  9851 
  9852         ip.flags &= ~1 # !MF
  9853         del(ip.chksum)
  9854         del(ip.len)
  9855         p = p/txt
  9856         p._defrag_pos = lst[-1]._defrag_pos
  9857         defrag.append(p)
  9858     defrag2=[]
  9859     for p in defrag:
  9860         q = p.__class__(str(p))
  9861         q._defrag_pos = p._defrag_pos
  9862         defrag2.append(q)
  9863     final += defrag2
  9864     final += missfrag
  9865     final.sort(lambda x,y: cmp(x._defrag_pos, y._defrag_pos))
  9866     for p in final:
  9867         del(p._defrag_pos)
  9868 
  9869     if hasattr(plist, "listname"):
  9870         name = "Defragmented %s" % plist.listname
  9871     else:
  9872         name = "Defragmented"
  9873         
  9874     
  9875     return PacketList(final, name=name)
  9876             
  9877             
  9878         
  9879     
  9880 
  9881 
  9882 ###################
  9883 ## Super sockets ##
  9884 ###################
  9885 
  9886 def Ether_Dot3_Dispatcher(pkt=None, **kargs):
  9887     if type(pkt) is str and len(pkt) >= 14 and struct.unpack("!H", pkt[12:14])[0] <= 1500:
  9888         return Dot3(pkt, **kargs)
  9889     return Ether(pkt, **kargs)
  9890 
  9891 # According to libdnet
  9892 LLTypes = { ARPHDR_ETHER : Ether_Dot3_Dispatcher,
  9893             ARPHDR_METRICOM : Ether_Dot3_Dispatcher,
  9894             ARPHDR_LOOPBACK : Ether_Dot3_Dispatcher,
  9895             9: PPP,
  9896             12 : IP,
  9897             101 : IP,
  9898             801 : Dot11,
  9899             802 : PrismHeader,
  9900             803 : RadioTap,
  9901             105 : Dot11,
  9902             113 : CookedLinux,
  9903             119 : PrismHeader, # for atheros
  9904             127 : RadioTap,
  9905             144 : CookedLinux, # called LINUX_IRDA, similar to CookedLinux
  9906             783 : IrLAPHead,
  9907             0xB1E70073L : HCI_Hdr, # I invented this one
  9908             }
  9909 
  9910 LLNumTypes = { Ether : ARPHDR_ETHER,
  9911                PPP: 9,
  9912                IP  : 12,
  9913                IP  : 101,
  9914                Dot11  : 801,
  9915                PrismHeader : 802,
  9916                RadioTap    : 803,
  9917                RadioTap    : 127,
  9918                Dot11 : 105,
  9919                CookedLinux : 113,
  9920                CookedLinux : 144,
  9921                IrLAPHead : 783
  9922             }
  9923 
  9924 L3Types = { ETH_P_IP : IP,
  9925             ETH_P_ARP : ARP,
  9926             ETH_P_ALL : IP
  9927             }
  9928 
  9929 
  9930 def flush_fd(fd):
  9931     if type(fd) is not int:
  9932         fd = fd.fileno()
  9933     while 1:
  9934         r,w,e = select([fd],[],[],0)
  9935         if r:
  9936             os.read(fd,MTU)
  9937         else:
  9938             break
  9939 
  9940 class SuperSocket:
  9941     closed=0
  9942     def __init__(self, family=socket.AF_INET,type=socket.SOCK_STREAM, proto=0):
  9943         self.ins = socket.socket(family, type, proto)
  9944         self.outs = self.ins
  9945         self.promisc=None
  9946     def send(self, x):
  9947         sx = str(x)
  9948         x.sent_time = time.time()
  9949         return self.outs.send(sx)
  9950     def recv(self, x):
  9951         return Raw(self.ins.recv(x))
  9952     def fileno(self):
  9953         return self.ins.fileno()
  9954     def close(self):
  9955         if self.closed:
  9956             return
  9957         self.closed=1
  9958         if self.ins != self.outs:
  9959             if self.outs and self.outs.fileno() != -1:
  9960                 self.outs.close()
  9961         if self.ins and self.ins.fileno() != -1:
  9962             self.ins.close()
  9963     def bind_in(self, addr):
  9964         self.ins.bind(addr)
  9965     def bind_out(self, addr):
  9966         self.outs.bind(addr)
  9967 
  9968 
  9969 class L3RawSocket(SuperSocket):
  9970     def __init__(self, type = ETH_P_IP, filter=None, iface=None, promisc=None, nofilter=0):
  9971         self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
  9972         self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
  9973         self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
  9974     def recv(self, x):
  9975         return Ether(self.ins.recv(x)).payload
  9976     def send(self, x):
  9977         try:
  9978             sx = str(x)
  9979             x.sent_time = time.time()
  9980             self.outs.sendto(sx,(x.dst,0))
  9981         except socket.error,msg:
  9982             log_runtime.error(msg)
  9983         
  9984 
  9985 
  9986 class L3PacketSocket(SuperSocket):
  9987     def __init__(self, type = ETH_P_ALL, filter=None, promisc=None, iface=None, nofilter=0):
  9988         self.type = type
  9989         self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
  9990         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
  9991         flush_fd(self.ins)
  9992         if iface:
  9993             self.ins.bind((iface, type))
  9994         if not nofilter:
  9995             if conf.except_filter:
  9996                 if filter:
  9997                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
  9998                 else:
  9999                     filter = "not (%s)" % conf.except_filter
 10000             if filter is not None:
 10001                 attach_filter(self.ins, filter)
 10002         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
 10003         self.outs = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
 10004         self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30)
 10005         if promisc is None:
 10006             promisc = conf.promisc
 10007         self.promisc = promisc
 10008         if self.promisc:
 10009             if iface is None:
 10010                 self.iff = get_if_list()
 10011             else:
 10012                 if iface.__class__ is list:
 10013                     self.iff = iface
 10014                 else:
 10015                     self.iff = [iface]
 10016             for i in self.iff:
 10017                 set_promisc(self.ins, i)
 10018     def close(self):
 10019         if self.closed:
 10020             return
 10021         self.closed=1
 10022         if self.promisc:
 10023             for i in self.iff:
 10024                 set_promisc(self.ins, i, 0)
 10025         SuperSocket.close(self)
 10026     def recv(self, x):
 10027         pkt, sa_ll = self.ins.recvfrom(x)
 10028         if sa_ll[2] == socket.PACKET_OUTGOING:
 10029             return None
 10030         if LLTypes.has_key(sa_ll[3]):
 10031             cls = LLTypes[sa_ll[3]]
 10032             lvl = 2
 10033         elif L3Types.has_key(sa_ll[1]):
 10034             cls = L3Types[sa_ll[1]]
 10035             lvl = 3
 10036         else:
 10037             warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using Ethernet" % (sa_ll[0],sa_ll[1],sa_ll[3]))
 10038             cls = Ether
 10039             lvl = 2
 10040 
 10041         try:
 10042             pkt = cls(pkt)
 10043         except KeyboardInterrupt:
 10044             raise
 10045         except:
 10046             if conf.debug_dissector:
 10047                 raise
 10048             pkt = Raw(pkt)
 10049         if lvl == 2:
 10050             pkt = pkt.payload
 10051             
 10052         if pkt is not None:
 10053             pkt.time = get_last_packet_timestamp(self.ins)
 10054         return pkt
 10055     
 10056     def send(self, x):
 10057         if isinstance(x, IPv6):
 10058             iff,a,gw = conf.route6.route(x.dst)
 10059         elif hasattr(x,"dst"):
 10060             iff,a,gw = conf.route.route(x.dst)
 10061         else:
 10062             iff = conf.iface
 10063         sdto = (iff, self.type)
 10064         self.outs.bind(sdto)
 10065         sn = self.outs.getsockname()
 10066         ll = lambda x:x
 10067         if sn[3] in (ARPHDR_PPP,ARPHDR_TUN):
 10068             sdto = (iff, ETH_P_IP)
 10069         if LLTypes.has_key(sn[3]):
 10070             ll = lambda x:LLTypes[sn[3]]()/x
 10071         try:
 10072             sx = str(ll(x))
 10073             x.sent_time = time.time()
 10074             self.outs.sendto(sx, sdto)
 10075         except socket.error,msg:
 10076             x.sent_time = time.time()  # bad approximation
 10077             if conf.auto_fragment and msg[0] == 90:
 10078                 for p in fragment(x):
 10079                     self.outs.sendto(str(ll(p)), sdto)
 10080             else:
 10081                 raise
 10082                     
 10083 
 10084 
 10085 
 10086 class L2Socket(SuperSocket):
 10087     def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
 10088         if iface is None:
 10089             iface = conf.iface
 10090         self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
 10091         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
 10092         flush_fd(self.ins)
 10093         if not nofilter: 
 10094             if conf.except_filter:
 10095                 if filter:
 10096                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
 10097                 else:
 10098                     filter = "not (%s)" % conf.except_filter
 10099             if filter is not None:
 10100                 attach_filter(self.ins, filter)
 10101         self.ins.bind((iface, type))
 10102         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
 10103         self.outs = self.ins
 10104         self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 2**30)
 10105         sa_ll = self.outs.getsockname()
 10106         if LLTypes.has_key(sa_ll[3]):
 10107             self.LL = LLTypes[sa_ll[3]]
 10108         elif L3Types.has_key(sa_ll[1]):
 10109             self.LL = L3Types[sa_ll[1]]
 10110         else:
 10111             warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using Ethernet" % (sa_ll[0],sa_ll[1],sa_ll[3]))
 10112             self.LL = Ether
 10113             
 10114     def recv(self, x):
 10115         pkt, sa_ll = self.ins.recvfrom(x)
 10116         if sa_ll[2] == socket.PACKET_OUTGOING:
 10117             return None
 10118         try:
 10119             q = self.LL(pkt)
 10120         except KeyboardInterrupt:
 10121             raise
 10122         except:
 10123             if conf.debug_dissector:
 10124                 raise
 10125             q = Raw(pkt)
 10126         q.time = get_last_packet_timestamp(self.ins)
 10127         return q
 10128 
 10129 
 10130 class L2ListenSocket(SuperSocket):
 10131     def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None, nofilter=0):
 10132         self.type = type
 10133         self.outs = None
 10134         self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
 10135         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0)
 10136         flush_fd(self.ins)
 10137         if iface is not None:
 10138             self.ins.bind((iface, type))
 10139         if not nofilter:
 10140             if conf.except_filter:
 10141                 if filter:
 10142                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
 10143                 else:
 10144                     filter = "not (%s)" % conf.except_filter
 10145             if filter is not None:
 10146                 attach_filter(self.ins, filter)
 10147         if promisc is None:
 10148             promisc = conf.sniff_promisc
 10149         self.promisc = promisc
 10150         if iface is None:
 10151             self.iff = get_if_list()
 10152         else:
 10153             if iface.__class__ is list:
 10154                 self.iff = iface
 10155             else:
 10156                 self.iff = [iface]
 10157         if self.promisc:
 10158             for i in self.iff:
 10159                 set_promisc(self.ins, i)
 10160         self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 2**30)
 10161     def close(self):
 10162         if self.promisc:
 10163             for i in self.iff:
 10164                 set_promisc(self.ins, i, 0)
 10165         SuperSocket.close(self)
 10166 
 10167     def recv(self, x):
 10168         pkt, sa_ll = self.ins.recvfrom(x)
 10169         if LLTypes.has_key(sa_ll[3]):
 10170             cls = LLTypes[sa_ll[3]]
 10171         elif L3Types.has_key(sa_ll[1]):
 10172             cls = L3Types[sa_ll[1]]
 10173         else:
 10174             warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using Ethernet" % (sa_ll[0],sa_ll[1],sa_ll[3]))
 10175             cls = Ether
 10176 
 10177         try:
 10178             pkt = cls(pkt)
 10179         except KeyboardInterrupt:
 10180             raise
 10181         except:
 10182             if conf.debug_dissector:
 10183                 raise
 10184             pkt = Raw(pkt)
 10185         pkt.time = get_last_packet_timestamp(self.ins)
 10186         return pkt
 10187     
 10188     def send(self, x):
 10189         raise Scapy_Exception("Can't send anything with L2ListenSocket")
 10190 
 10191 
 10192 
 10193 class L3dnetSocket(SuperSocket):
 10194     def __init__(self, type = ETH_P_ALL, filter=None, promisc=None, iface=None, nofilter=0):
 10195         self.iflist = {}
 10196         self.ins = pcap.pcapObject()
 10197         if iface is None:
 10198             iface = conf.iface
 10199         self.iface = iface
 10200         self.ins.open_live(iface, 1600, 0, 100)
 10201         try:
 10202             ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
 10203         except:
 10204             pass
 10205         if nofilter:
 10206             if type != ETH_P_ALL:  # PF_PACKET stuff. Need to emulate this for pcap
 10207                 filter = "ether proto %i" % type
 10208             else:
 10209                 filter = None
 10210         else:
 10211             if conf.except_filter:
 10212                 if filter:
 10213                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
 10214                 else:
 10215                     filter = "not (%s)" % conf.except_filter
 10216             if type != ETH_P_ALL:  # PF_PACKET stuff. Need to emulate this for pcap
 10217                 if filter:
 10218                     filter = "(ether proto %i) and (%s)" % (type,filter)
 10219                 else:
 10220                     filter = "ether proto %i" % type
 10221         if filter:
 10222             self.ins.setfilter(filter, 0, 0)
 10223     def send(self, x):
 10224         if isinstance(x, IPv6):
 10225             iff,a,gw = conf.route6.route(x.dst)
 10226         elif hasattr(x,"dst"):
 10227             iff,a,gw = conf.route.route(x.dst)
 10228         else:
 10229             iff = conf.iface
 10230         ifs = self.iflist.get(iff)
 10231         if ifs is None:
 10232             self.iflist[iff] = ifs = dnet.eth(iff)
 10233         sx = str(Ether()/x)
 10234         x.sent_time = time.time()
 10235         ifs.send(sx)
 10236     def recv(self,x=MTU):
 10237         ll = self.ins.datalink()
 10238         if LLTypes.has_key(ll):
 10239             cls = LLTypes[ll]
 10240         else:
 10241             warning("Unable to guess datalink type (interface=%s linktype=%i). Using Ethernet" % (self.iface, ll))
 10242             cls = Ether
 10243 
 10244         pkt = self.ins.next()
 10245         if pkt is not None:
 10246             l,pkt,ts = pkt
 10247         if pkt is None:
 10248             return
 10249 
 10250         try:
 10251             pkt = cls(pkt)
 10252         except KeyboardInterrupt:
 10253             raise
 10254         except:
 10255             if conf.debug_dissector:
 10256                 raise
 10257             pkt = Raw(pkt)
 10258         pkt.time = ts
 10259         return pkt.payload
 10260 
 10261     def nonblock_recv(self):
 10262         self.ins.setnonblock(1)
 10263         p = self.recv()
 10264         self.ins.setnonblock(0)
 10265         return p
 10266 
 10267     def close(self):
 10268         if hasattr(self, "ins"):
 10269             del(self.ins)
 10270         if hasattr(self, "outs"):
 10271             del(self.outs)
 10272 
 10273 class L2dnetSocket(SuperSocket):
 10274     def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
 10275         if iface is None:
 10276             iface = conf.iface
 10277         self.iface = iface
 10278         self.ins = pcap.pcapObject()
 10279         self.ins.open_live(iface, 1600, 0, 100)
 10280         try:
 10281             ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
 10282         except:
 10283             pass
 10284         if nofilter:
 10285             if type != ETH_P_ALL:  # PF_PACKET stuff. Need to emulate this for pcap
 10286                 filter = "ether proto %i" % type
 10287             else:
 10288                 filter = None
 10289         else:
 10290             if conf.except_filter:
 10291                 if filter:
 10292                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
 10293                 else:
 10294                     filter = "not (%s)" % conf.except_filter
 10295             if type != ETH_P_ALL:  # PF_PACKET stuff. Need to emulate this for pcap
 10296                 if filter:
 10297                     filter = "(ether proto %i) and (%s)" % (type,filter)
 10298                 else:
 10299                     filter = "ether proto %i" % type
 10300         if filter:
 10301             self.ins.setfilter(filter, 0, 0)
 10302         self.outs = dnet.eth(iface)
 10303     def recv(self,x):
 10304         ll = self.ins.datalink()
 10305         if LLTypes.has_key(ll):
 10306             cls = LLTypes[ll]
 10307         else:
 10308             warning("Unable to guess datalink type (interface=%s linktype=%i). Using Ethernet" % (self.iface, ll))
 10309             cls = Ether
 10310 
 10311         pkt = self.ins.next()
 10312         if pkt is not None:
 10313             l,pkt,ts = pkt
 10314         if pkt is None:
 10315             return
 10316         
 10317         try:
 10318             pkt = cls(pkt)
 10319         except KeyboardInterrupt:
 10320             raise
 10321         except:
 10322             if conf.debug_dissector:
 10323                 raise
 10324             pkt = Raw(pkt)
 10325         pkt.time = ts
 10326         return pkt
 10327 
 10328     def nonblock_recv(self):
 10329         self.ins.setnonblock(1)
 10330         p = self.recv(MTU)
 10331         self.ins.setnonblock(0)
 10332         return p
 10333 
 10334     def close(self):
 10335         if hasattr(self, "ins"):
 10336             del(self.ins)
 10337         if hasattr(self, "outs"):
 10338             del(self.outs)
 10339     
 10340     
 10341     
 10342 
 10343 
 10344 class L2pcapListenSocket(SuperSocket):
 10345     def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None):
 10346         self.type = type
 10347         self.outs = None
 10348         self.ins = pcap.pcapObject()
 10349         self.iface = iface
 10350         if iface is None:
 10351             iface = conf.iface
 10352         if promisc is None:
 10353             promisc = conf.sniff_promisc
 10354         self.promisc = promisc
 10355         self.ins.open_live(iface, 1600, self.promisc, 100)
 10356         try:
 10357             ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
 10358         except:
 10359             pass
 10360         if type == ETH_P_ALL: # Do not apply any filter if Ethernet type is given
 10361             if conf.except_filter:
 10362                 if filter:
 10363                     filter = "(%s) and not (%s)" % (filter, conf.except_filter)
 10364                 else:
 10365                     filter = "not (%s)" % conf.except_filter
 10366             if filter:
 10367                 self.ins.setfilter(filter, 0, 0)
 10368 
 10369     def close(self):
 10370         del(self.ins)
 10371         
 10372     def recv(self, x):
 10373         ll = self.ins.datalink()
 10374         if LLTypes.has_key(ll):
 10375             cls = LLTypes[ll]
 10376         else:
 10377             warning("Unable to guess datalink type (interface=%s linktype=%i). Using Ethernet" % (self.iface, ll))
 10378             cls = Ether
 10379 
 10380         pkt = None
 10381         while pkt is None:
 10382             pkt = self.ins.next()
 10383             if pkt is not None:
 10384                 l,pkt,ts = pkt
 10385         
 10386         try:
 10387             pkt = cls(pkt)
 10388         except KeyboardInterrupt:
 10389             raise
 10390         except:
 10391             if conf.debug_dissector:
 10392                 raise
 10393             pkt = Raw(pkt)
 10394         pkt.time = ts
 10395         return pkt
 10396 
 10397     def send(self, x):
 10398         raise Scapy_Exception("Can't send anything with L2pcapListenSocket")
 10399 
 10400 
 10401 class SimpleSocket(SuperSocket):
 10402     def __init__(self, sock):
 10403         self.ins = sock
 10404         self.outs = sock
 10405 
 10406 
 10407 class StreamSocket(SimpleSocket):
 10408     def __init__(self, sock, basecls=Raw):
 10409         SimpleSocket.__init__(self, sock)
 10410         self.basecls = basecls
 10411         
 10412     def recv(self, x=MTU):
 10413         pkt = self.ins.recv(x, socket.MSG_PEEK)
 10414         x = len(pkt)
 10415         pkt = self.basecls(pkt)
 10416         pad = pkt[Padding]
 10417         if pad is not None and pad.underlayer is not None:
 10418             del(pad.underlayer.payload)
 10419         while pad is not None and not isinstance(pad, NoPayload):
 10420             x -= len(pad.load)
 10421             pad = pad.payload
 10422         self.ins.recv(x)
 10423         return pkt
 10424         
 10425         
 10426 class BluetoothL2CAPSocket(SuperSocket):
 10427     def __init__(self, peer):
 10428         s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW,
 10429                           socket.BTPROTO_L2CAP)
 10430         s.connect((peer,0))
 10431         
 10432         self.ins = self.outs = s
 10433 
 10434     def recv(self, x):
 10435         return L2CAP_CmdHdr(self.ins.recv(x))
 10436     
 10437 
 10438 class BluetoothHCISocket(SuperSocket):
 10439     def __init__(self, iface=0x10000, type=None):
 10440         s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_RAW, socket.BTPROTO_HCI)
 10441         s.setsockopt(socket.SOL_HCI, socket.HCI_DATA_DIR,1)
 10442         s.setsockopt(socket.SOL_HCI, socket.HCI_TIME_STAMP,1)
 10443         s.setsockopt(socket.SOL_HCI, socket.HCI_FILTER, struct.pack("IIIh2x", 0xffffffffL,0xffffffffL,0xffffffffL,0)) #type mask, event mask, event mask, opcode
 10444         s.bind((iface,))
 10445         self.ins = self.outs = s
 10446 #        s.connect((peer,0))
 10447         
 10448 
 10449     def recv(self, x):
 10450         return HCI_Hdr(self.ins.recv(x))
 10451     
 10452 
 10453 
 10454 ####################
 10455 ## Send / Receive ##
 10456 ####################
 10457 
 10458 
 10459 
 10460 
 10461 def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, multi=0):
 10462     if not isinstance(pkt, Gen):
 10463         pkt = SetGen(pkt)
 10464         
 10465     if verbose is None:
 10466         verbose = conf.verb
 10467     debug.recv = PacketList([],"Unanswered")
 10468     debug.sent = PacketList([],"Sent")
 10469     debug.match = SndRcvList([])
 10470     nbrecv=0
 10471     ans = []
 10472     # do it here to fix random fields, so that parent and child have the same
 10473     all_stimuli = tobesent = [p for p in pkt]
 10474     notans = len(tobesent)
 10475 
 10476     hsent={}
 10477     for i in tobesent:
 10478         h = i.hashret()
 10479         if h in hsent:
 10480             hsent[h].append(i)
 10481         else:
 10482             hsent[h] = [i]
 10483     if retry < 0:
 10484         retry = -retry
 10485         autostop=retry
 10486     else:
 10487         autostop=0
 10488 
 10489 
 10490     while retry >= 0:
 10491         found=0
 10492     
 10493         if timeout < 0:
 10494             timeout = None
 10495             
 10496         rdpipe,wrpipe = os.pipe()
 10497         rdpipe=os.fdopen(rdpipe)
 10498         wrpipe=os.fdopen(wrpipe,"w")
 10499 
 10500         pid=1
 10501         try:
 10502             pid = os.fork()
 10503             if pid == 0:
 10504                 try:
 10505                     sys.stdin.close()
 10506                     rdpipe.close()
 10507                     try:
 10508                         i = 0
 10509                         if verbose:
 10510                             print "Begin emission:"
 10511                         for p in tobesent:
 10512                             pks.send(p)
 10513                             i += 1
 10514                             time.sleep(inter)
 10515                         if verbose:
 10516                             print "Finished to send %i packets." % i
 10517                     except SystemExit:
 10518                         pass
 10519                     except KeyboardInterrupt:
 10520                         pass
 10521                     except:
 10522                         log_runtime.exception("--- Error in child %i" % os.getpid())
 10523                         log_runtime.info("--- Error in child %i" % os.getpid())
 10524                 finally:
 10525                     try:
 10526                         os.setpgrp() # Chance process group to avoid ctrl-C
 10527                         sent_times = [p.sent_time for p in all_stimuli if p.sent_time]
 10528                         cPickle.dump( (arp_cache,sent_times), wrpipe )
 10529                         wrpipe.close()
 10530                     except:
 10531                         pass
 10532             elif pid < 0:
 10533                 log_runtime.error("fork error")
 10534             else:
 10535                 wrpipe.close()
 10536                 stoptime = 0
 10537                 remaintime = None
 10538                 inmask = [rdpipe,pks]
 10539                 try:
 10540                     try:
 10541                         while 1:
 10542                             if stoptime:
 10543                                 remaintime = stoptime-time.time()
 10544                                 if remaintime <= 0:
 10545                                     break
 10546                             r = None
 10547                             if FREEBSD or DARWIN:
 10548                                 inp, out, err = select(inmask,[],[], 0.05)
 10549                                 if len(inp) == 0 or pks in inp:
 10550                                     r = pks.nonblock_recv()
 10551                             else:
 10552                                 inp, out, err = select(inmask,[],[], remaintime)
 10553                                 if len(inp) == 0:
 10554                                     break
 10555                                 if pks in inp:
 10556                                     r = pks.recv(MTU)
 10557                             if rdpipe in inp:
 10558                                 if timeout:
 10559                                     stoptime = time.time()+timeout
 10560                                 del(inmask[inmask.index(rdpipe)])
 10561                             if r is None:
 10562                                 continue
 10563                             ok = 0
 10564                             h = r.hashret()
 10565                             if h in hsent:
 10566                                 hlst = hsent[h]
 10567                                 for i in range(len(hlst)):
 10568                                     if r.answers(hlst[i]):
 10569                                         ans.append((hlst[i],r))
 10570                                         if verbose > 1:
 10571                                             os.write(1, "*")
 10572                                         ok = 1                                
 10573                                         if not multi:
 10574                                             del(hlst[i])
 10575                                             notans -= 1;
 10576                                         else:
 10577                                             if not hasattr(hlst[i], '_answered'):
 10578                                                 notans -= 1;
 10579                                             hlst[i]._answered = 1;
 10580                                         break
 10581                             if notans == 0 and not multi:
 10582                                 break
 10583                             if not ok:
 10584                                 if verbose > 1:
 10585                                     os.write(1, ".")
 10586                                 nbrecv += 1
 10587                                 if conf.debug_match:
 10588                                     debug.recv.append(r)
 10589                     except KeyboardInterrupt:
 10590                         if chainCC:
 10591                             raise
 10592                 finally:
 10593                     try:
 10594                         ac,sent_times = cPickle.load(rdpipe)
 10595                     except EOFError:
 10596                         warning("Child died unexpectedly. Packets may have not been sent %i"%os.getpid())
 10597                     else:
 10598                         arp_cache.update(ac)
 10599                         for p,t in zip(all_stimuli, sent_times):
 10600                             p.sent_time = t
 10601                     os.waitpid(pid,0)
 10602         finally:
 10603             if pid == 0:
 10604                 os._exit(0)
 10605 
 10606         remain = reduce(list.__add__, hsent.values(), [])
 10607         if multi:
 10608             remain = filter(lambda p: not hasattr(p, '_answered'), remain);
 10609             
 10610         if autostop and len(remain) > 0 and len(remain) != len(tobesent):
 10611             retry = autostop
 10612             
 10613         tobesent = remain
 10614         if len(tobesent) == 0:
 10615             break
 10616         retry -= 1
 10617         
 10618     if conf.debug_match:
 10619         debug.sent=PacketList(remain[:],"Sent")
 10620         debug.match=SndRcvList(ans[:])
 10621 
 10622     #clean the ans list to delete the field _answered
 10623     if (multi):
 10624         for s,r in ans:
 10625             if hasattr(s, '_answered'):
 10626                 del(s._answered)
 10627     
 10628     if verbose:
 10629         print "\nReceived %i packets, got %i answers, remaining %i packets" % (nbrecv+len(ans), len(ans), notans)
 10630     return SndRcvList(ans),PacketList(remain,"Unanswered"),debug.recv
 10631 
 10632 
 10633 def __gen_send(s, x, inter=0, loop=0, count=None, verbose=None, *args, **kargs):
 10634     if not isinstance(x, Gen):
 10635         x = SetGen(x)
 10636     if verbose is None:
 10637         verbose = conf.verb
 10638     n = 0
 10639     if count is not None:
 10640         loop = -count
 10641     elif not loop:
 10642         loop=-1
 10643     try:
 10644         while loop:
 10645             for p in x:
 10646                 s.send(p)
 10647                 n += 1
 10648                 if verbose:
 10649                     os.write(1,".")
 10650                 time.sleep(inter)
 10651             if loop < 0:
 10652                 loop += 1
 10653     except KeyboardInterrupt:
 10654         pass
 10655     s.close()
 10656     if verbose:
 10657         print "\nSent %i packets." % n
 10658 
 10659 def send(x, inter=0, loop=0, count=None, verbose=None, *args, **kargs):
 10660     """Send packets at layer 3
 10661 send(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
 10662     __gen_send(conf.L3socket(*args, **kargs), x, inter=inter, loop=loop, count=count,verbose=verbose)
 10663 
 10664 def sendp(x, inter=0, loop=0, iface=None, iface_hint=None, count=None, verbose=None, *args, **kargs):
 10665     """Send packets at layer 2
 10666 sendp(packets, [inter=0], [loop=0], [verbose=conf.verb]) -> None"""
 10667     if iface is None and iface_hint is not None:
 10668         iface = conf.route.route(iface_hint)[0]
 10669     __gen_send(conf.L2socket(iface=iface, *args, **kargs), x, inter=inter, loop=loop, count=count, verbose=verbose)
 10670 
 10671 def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, iface=None):
 10672     """Send packets at layer 2 using tcpreplay for performance
 10673     pps:  packets per second
 10674     mpbs: MBits per second
 10675     realtime: use packet's timestamp, bending time with realtime value
 10676     loop: number of times to process the packet list
 10677     iface: output interface """
 10678     if iface is None:
 10679         iface = conf.iface
 10680     options = ["--intf1=%s" % iface ]
 10681     if pps is not None:
 10682         options.append("--pps=%i" % pps)
 10683     elif mbps is not None:
 10684         options.append("--mbps=%i" % mbps)
 10685     elif realtime is not None:
 10686         options.append("--multiplier=%i" % realtime)
 10687     else:
 10688         options.append("--topspeed")
 10689 
 10690     if loop:
 10691         options.append("--loop=%i" % loop)
 10692 
 10693     f = os.tempnam("scapy")
 10694     options.append(f)
 10695     wrpcap(f, x)
 10696     try:
 10697         try:
 10698             os.spawnlp(os.P_WAIT, conf.prog.tcpreplay, conf.prog.tcpreplay, *options)
 10699         except KeyboardInterrupt:
 10700             log_interactive.info("Interrupted by user")
 10701     finally:
 10702         os.unlink(f)
 10703 
 10704         
 10705 
 10706         
 10707     
 10708 def sr(x,filter=None, iface=None, nofilter=0, *args,**kargs):
 10709     """Send and receive packets at layer 3
 10710 nofilter: put 1 to avoid use of bpf filters
 10711 retry:    if positive, how many times to resend unanswered packets
 10712           if negative, how many times to retry when no more packets are answered
 10713 timeout:  how much time to wait after the last packet has been sent
 10714 verbose:  set verbosity level
 10715 multi:    whether to accept multiple answers for the same stimulus
 10716 filter:   provide a BPF filter
 10717 iface:    listen answers only on the given interface"""
 10718     if not kargs.has_key("timeout"):
 10719         kargs["timeout"] = -1
 10720     s = conf.L3socket(filter=filter, iface=iface, nofilter=nofilter)
 10721     a,b,c=sndrcv(s,x,*args,**kargs)
 10722     s.close()
 10723     return a,b
 10724 
 10725 def sr1(x,filter=None,iface=None, nofilter=0, *args,**kargs):
 10726     """Send packets at layer 3 and return only the first answer
 10727 nofilter: put 1 to avoid use of bpf filters
 10728 retry:    if positive, how many times to resend unanswered packets
 10729           if negative, how many times to retry when no more packets are answered
 10730 timeout:  how much time to wait after the last packet has been sent
 10731 verbose:  set verbosity level
 10732 multi:    whether to accept multiple answers for the same stimulus
 10733 filter:   provide a BPF filter
 10734 iface:    listen answers only on the given interface"""
 10735     if not kargs.has_key("timeout"):
 10736         kargs["timeout"] = -1
 10737     s=conf.L3socket(filter=filter, nofilter=nofilter, iface=iface)
 10738     a,b,c=sndrcv(s,x,*args,**kargs)
 10739     s.close()
 10740     if len(a) > 0:
 10741         return a[0][1]
 10742     else:
 10743         return None
 10744 
 10745 def srp(x,iface=None, iface_hint=None, filter=None, nofilter=0, type=ETH_P_ALL, *args,**kargs):
 10746     """Send and receive packets at layer 2
 10747 nofilter: put 1 to avoid use of bpf filters
 10748 retry:    if positive, how many times to resend unanswered packets
 10749           if negative, how many times to retry when no more packets are answered
 10750 timeout:  how much time to wait after the last packet has been sent
 10751 verbose:  set verbosity level
 10752 multi:    whether to accept multiple answers for the same stimulus
 10753 filter:   provide a BPF filter
 10754 iface:    work only on the given interface"""
 10755     if not kargs.has_key("timeout"):
 10756         kargs["timeout"] = -1
 10757     if iface is None and iface_hint is not None:
 10758         iface = conf.route.route(iface_hint)[0]
 10759     s = conf.L2socket(iface=iface, filter=filter, nofilter=nofilter, type=type)
 10760     a,b,c=sndrcv(s ,x,*args,**kargs)
 10761     s.close()
 10762     return a,b
 10763 
 10764 def srp1(*args,**kargs):
 10765     """Send and receive packets at layer 2 and return only the first answer
 10766 nofilter: put 1 to avoid use of bpf filters
 10767 retry:    if positive, how many times to resend unanswered packets
 10768           if negative, how many times to retry when no more packets are answered
 10769 timeout:  how much time to wait after the last packet has been sent
 10770 verbose:  set verbosity level
 10771 multi:    whether to accept multiple answers for the same stimulus
 10772 filter:   provide a BPF filter
 10773 iface:    work only on the given interface"""
 10774     if not kargs.has_key("timeout"):
 10775         kargs["timeout"] = -1
 10776     a,b=srp(*args,**kargs)
 10777     if len(a) > 0:
 10778         return a[0][1]
 10779     else:
 10780         return None
 10781 
 10782 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):
 10783     n = 0
 10784     r = 0
 10785     ct = conf.color_theme
 10786     if verbose is None:
 10787         verbose = conf.verb
 10788     parity = 0
 10789     ans=[]
 10790     unans=[]
 10791     if timeout is None:
 10792         timeout = min(2*inter, 5)
 10793     try:
 10794         while 1:
 10795             parity ^= 1
 10796             col = [ct.even,ct.odd][parity]
 10797             if count is not None:
 10798                 if count == 0:
 10799                     break
 10800                 count -= 1
 10801             start = time.time()
 10802             print "\rsend...\r",
 10803             res = srfunc(pkts, timeout=timeout, verbose=0, chainCC=1, *args, **kargs)
 10804             n += len(res[0])+len(res[1])
 10805             r += len(res[0])
 10806             if verbose > 1 and prn and len(res[0]) > 0:
 10807                 msg = "RECV %i:" % len(res[0])
 10808                 print  "\r"+ct.success(msg),
 10809                 for p in res[0]:
 10810                     print col(prn(p))
 10811                     print " "*len(msg),
 10812             if verbose > 1 and prnfail and len(res[1]) > 0:
 10813                 msg = "fail %i:" % len(res[1])
 10814                 print "\r"+ct.fail(msg),
 10815                 for p in res[1]:
 10816                     print col(prnfail(p))
 10817                     print " "*len(msg),
 10818             if verbose > 1 and not (prn or prnfail):
 10819                 print "recv:%i  fail:%i" % tuple(map(len, res[:2]))
 10820             if store:
 10821                 ans += res[0]
 10822                 unans += res[1]
 10823             end=time.time()
 10824             if end-start < inter:
 10825                 time.sleep(inter+start-end)
 10826     except KeyboardInterrupt:
 10827         pass
 10828  
 10829     if verbose and n>0:
 10830         print ct.normal("\nSent %i packets, received %i packets. %3.1f%% hits." % (n,r,100.0*r/n))
 10831     return SndRcvList(ans),PacketList(unans)
 10832 
 10833 def srloop(pkts, *args, **kargs):
 10834     """Send a packet at layer 3 in loop and print the answer each time
 10835 srloop(pkts, [prn], [inter], [count], ...) --> None"""
 10836     return __sr_loop(sr, pkts, *args, **kargs)
 10837 
 10838 def srploop(pkts, *args, **kargs):
 10839     """Send a packet at layer 2 in loop and print the answer each time
 10840 srloop(pkts, [prn], [inter], [count], ...) --> None"""
 10841     return __sr_loop(srp, pkts, *args, **kargs)
 10842 
 10843 
 10844 def sndrcvflood(pks, pkt, prn=lambda (s,r):r.summary(), chainCC=0, store=1, unique=0):
 10845     if not isinstance(pkt, Gen):
 10846         pkt = SetGen(pkt)
 10847     tobesent = [p for p in pkt]
 10848     received = SndRcvList()
 10849     seen = {}
 10850 
 10851     hsent={}
 10852     for i in tobesent:
 10853         h = i.hashret()
 10854         if h in hsent:
 10855             hsent[h].append(i)
 10856         else:
 10857             hsent[h] = [i]
 10858 
 10859     def send_in_loop(tobesent):
 10860         while 1:
 10861             for p in tobesent:
 10862                 yield p
 10863 
 10864     packets_to_send = send_in_loop(tobesent)
 10865 
 10866     ssock = rsock = pks.fileno()
 10867 
 10868     try:
 10869         while 1:
 10870             readyr,readys,_ = select([rsock],[ssock],[])
 10871             if ssock in readys:
 10872                 pks.send(packets_to_send.next())
 10873                 
 10874             if rsock in readyr:
 10875                 p = pks.recv(MTU)
 10876                 if p is None:
 10877                     continue
 10878                 h = p.hashret()
 10879                 if h in hsent:
 10880                     hlst = hsent[h]
 10881                     for i in hlst:
 10882                         if p.answers(i):
 10883                             res = prn((i,p))
 10884                             if unique:
 10885                                 if res in seen:
 10886                                     continue
 10887                                 seen[res] = None
 10888                             if res is not None:
 10889                                 print res
 10890                             if store:
 10891                                 received.append((i,p))
 10892     except KeyboardInterrupt:
 10893         if chainCC:
 10894             raise
 10895     return received
 10896 
 10897 def srflood(x,filter=None, iface=None, nofilter=None, *args,**kargs):
 10898     """Flood and receive packets at layer 3
 10899 prn:      function applied to packets received. Ret val is printed if not None
 10900 store:    if 1 (default), store answers and return them
 10901 unique:   only consider packets whose print 
 10902 nofilter: put 1 to avoid use of bpf filters
 10903 filter:   provide a BPF filter
 10904 iface:    listen answers only on the given interface"""
 10905     s = conf.L3socket(filter=filter, iface=iface, nofilter=nofilter)
 10906     r=sndrcvflood(s,x,*args,**kargs)
 10907     s.close()
 10908     return r
 10909 
 10910 def srpflood(x,filter=None, iface=None, iface_hint=None, nofilter=None, *args,**kargs):
 10911     """Flood and receive packets at layer 2
 10912 prn:      function applied to packets received. Ret val is printed if not None
 10913 store:    if 1 (default), store answers and return them
 10914 unique:   only consider packets whose print 
 10915 nofilter: put 1 to avoid use of bpf filters
 10916 filter:   provide a BPF filter
 10917 iface:    listen answers only on the given interface"""
 10918     if iface is None and iface_hint is not None:
 10919         iface = conf.route.route(iface_hint)[0]    
 10920     s = conf.L2socket(filter=filter, iface=iface, nofilter=nofilter)
 10921     r=sndrcvflood(s,x,*args,**kargs)
 10922     s.close()
 10923     return r
 10924 
 10925            
 10926 ## Bluetooth
 10927 
 10928 
 10929 def srbt(peer, pkts, inter=0.1, *args, **kargs):
 10930     s = conf.BTsocket(peer=peer)
 10931     a,b,c=sndrcv(s,pkts,inter=inter,*args,**kargs)
 10932     s.close()
 10933     return a,b
 10934 
 10935 def srbt1(peer, pkts, *args, **kargs):
 10936     a,b = srbt(peer, pkts, *args, **kargs)
 10937     if len(a) > 0:
 10938         return a[0][1]
 10939         
 10940     
 10941 
 10942 
 10943 
 10944 #############################
 10945 ## pcap capture file stuff ##
 10946 #############################
 10947 
 10948 def wrpcap(filename, pkt, *args, **kargs):
 10949     """Write a list of packets to a pcap file
 10950 gz: set to 1 to save a gzipped capture
 10951 linktype: force linktype value
 10952 endianness: "<" or ">", force endianness"""
 10953     PcapWriter(filename, *args, **kargs).write(pkt)
 10954 
 10955 def rdpcap(filename, count=-1):
 10956     """Read a pcap file and return a packet list
 10957 count: read only <count> packets"""
 10958     return PcapReader(filename).read_all(count=count)
 10959 
 10960 class PcapReader:
 10961     """A stateful pcap reader
 10962     
 10963     Based entirely on scapy.rdpcap(), this class allows for packets
 10964     to be dispatched without having to be loaded into memory all at
 10965     once
 10966     """
 10967 
 10968     def __init__(self, filename):
 10969         self.filename = filename
 10970         try:
 10971             self.f = gzip.open(filename,"rb")
 10972             magic = self.f.read(4)
 10973         except IOError:
 10974             self.f = open(filename,"rb")
 10975             magic = self.f.read(4)
 10976         if magic == "\xa1\xb2\xc3\xd4": #big endian
 10977             self.endian = ">"
 10978         elif  magic == "\xd4\xc3\xb2\xa1": #little endian
 10979             self.endian = "<"
 10980         else:
 10981             raise RuntimeWarning, "Not a pcap capture file (bad magic)"
 10982         hdr = self.f.read(20)
 10983         if len(hdr)<20:
 10984             raise RuntimeWarning, "Invalid pcap file (too short)"
 10985         vermaj,vermin,tz,sig,snaplen,linktype = struct.unpack(self.endian+"HHIIII",hdr)
 10986         self.LLcls = LLTypes.get(linktype, Raw)
 10987         if self.LLcls == Raw:
 10988             warning("PcapReader: unkonwon LL type [%i]/[%#x]. Using Raw packets" % (linktype,linktype))
 10989 
 10990     def __iter__(self):
 10991         return self
 10992 
 10993     def next(self):
 10994         """impliment the iterator protocol on a set of packets in a
 10995         pcap file
 10996         """
 10997         pkt = self.read_packet()
 10998         if pkt == None:
 10999             raise StopIteration
 11000         return pkt
 11001 
 11002 
 11003     def read_packet(self):
 11004         """return a single packet read from the file
 11005         
 11006         returns None when no more packets are available
 11007         """
 11008         hdr = self.f.read(16)
 11009         if len(hdr) < 16:
 11010             return None
 11011         sec,usec,caplen,olen = struct.unpack(self.endian+"IIII", hdr)
 11012         s = self.f.read(caplen)
 11013         try:
 11014             p = self.LLcls(s)
 11015         except KeyboardInterrupt:
 11016             raise
 11017         except:
 11018             if conf.debug_dissector:
 11019                 raise
 11020             p = Raw(s)
 11021         p.time = sec+0.000001*usec
 11022         return p
 11023 
 11024     def dispatch(self, callback):
 11025         """call the specified callback routine for each packet read
 11026         
 11027         This is just a convienience function for the main loop
 11028         that allows for easy launching of packet processing in a 
 11029         thread.
 11030         """
 11031         p = self.read_packet()
 11032         while p != None:
 11033             callback(p)
 11034             p = self.read_packet()
 11035 
 11036     def read_all(self,count=-1):
 11037         """return a list of all packets in the pcap file
 11038         """
 11039         res=[]
 11040         while count != 0:
 11041             count -= 1
 11042             p = self.read_packet()
 11043             if p is None:
 11044                 break
 11045             res.append(p)
 11046         return PacketList(res,name = os.path.basename(self.filename))
 11047 
 11048     def recv(self, size):
 11049         """ Emulate a socket
 11050         """
 11051         return self.read_packet()
 11052 
 11053     def fileno(self):
 11054         return self.f.fileno()
 11055         
 11056 
 11057 
 11058 class PcapWriter:
 11059     """A stream PCAP writer with more control than wrpcap()"""
 11060     def __init__(self, filename, linktype=None, gz=False, endianness="", append=False, sync=False):
 11061         """
 11062         linktype: force linktype to a given value. If None, linktype is taken
 11063                   from the first writter packet
 11064         gz: compress the capture on the fly
 11065         endianness: force an endianness (little:"<", big:">"). Default is native
 11066         append: append packets to the capture file instead of truncating it
 11067         sync: do not bufferize writes to the capture file
 11068         """
 11069         
 11070         self.linktype = linktype
 11071         self.header_present = 0
 11072         self.append=append
 11073         self.gz = gz
 11074         self.endian = endianness
 11075         self.filename=filename
 11076         self.sync=sync
 11077         bufsz=4096
 11078         if sync:
 11079             bufsz=0
 11080 
 11081         self.f = [open,gzip.open][gz](filename,append and "ab" or "wb", gz and 9 or bufsz)
 11082         
 11083             
 11084 
 11085     def fileno(self):
 11086         return self.f.fileno()
 11087 
 11088     def _write_header(self, pkt):
 11089         self.header_present=1
 11090 
 11091         if self.linktype == None:
 11092             if type(pkt) is list or type(pkt) is tuple:
 11093                 pkt = pkt[0]
 11094             self.linktype = LLNumTypes.get(pkt.__class__,1)
 11095 
 11096         if self.append:
 11097             # Even if prone to race conditions, this seems to be
 11098             # safest way to tell whether the header is already present
 11099             # because we have to handle compressed streams that
 11100             # are not as flexible as basic files
 11101             g = [open,gzip.open][self.gz](self.filename,"rb")
 11102             if g.read(16):
 11103                 return
 11104             
 11105         self.f.write(struct.pack(self.endian+"IHHIIII", 0xa1b2c3d4L,
 11106                                  2, 4, 0, 0, MTU, self.linktype))
 11107         self.f.flush()
 11108     
 11109 
 11110     def write(self, pkt):
 11111         """accepts a either a single packet or a list of packets
 11112         to be written to the dumpfile
 11113         """
 11114         if not self.header_present:
 11115             self._write_header(pkt)
 11116         for p in pkt:
 11117             self._write_packet(p)
 11118 
 11119     def _write_packet(self, packet):
 11120         """writes a single packet to the pcap file
 11121         """
 11122         s = str(packet)
 11123         l = len(s)
 11124         sec = int(packet.time)
 11125         usec = int((packet.time-sec)*1000000)
 11126         self.f.write(struct.pack(self.endian+"IIII", sec, usec, l, l))
 11127         self.f.write(s)
 11128         if self.gz and self.sync:
 11129             self.f.flush()
 11130 
 11131     def flush(self):
 11132         return self.f.flush()
 11133     def close(self):
 11134         return self.f.close()
 11135                 
 11136 
 11137 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})")
 11138 
 11139 def import_hexcap():
 11140     p = ""
 11141     try:
 11142         while 1:
 11143             l = raw_input().strip()
 11144             try:
 11145                 p += re_extract_hexcap.match(l).groups()[3]
 11146             except:
 11147                 warning("Parsing error during hexcap")
 11148                 continue
 11149     except EOFError:
 11150         pass
 11151     
 11152     p = p.replace(" ","")
 11153     p2=""
 11154     for i in range(len(p)/2):
 11155         p2 += chr(int(p[2*i:2*i+2],16))
 11156     return p2
 11157         
 11158 
 11159 
 11160 def wireshark(pktlist):
 11161     f = os.tempnam("scapy")
 11162     wrpcap(f, pktlist)
 11163     os.spawnlp(os.P_NOWAIT, conf.prog.wireshark, conf.prog.wireshark, "-r", f)
 11164 
 11165 def hexedit(x):
 11166     x = str(x)
 11167     f = os.tempnam("scapy")
 11168     open(f,"w").write(x)
 11169     os.spawnlp(os.P_WAIT, conf.prog.hexedit, conf.prog.hexedit, f)
 11170     x = open(f).read()
 11171     os.unlink(f)
 11172     return x
 11173 
 11174 
 11175 #####################
 11176 ## knowledge bases ##
 11177 #####################
 11178 
 11179 class KnowledgeBase:
 11180     def __init__(self, filename):
 11181         self.filename = filename
 11182         self.base = None
 11183 
 11184     def lazy_init(self):
 11185         self.base = ""
 11186 
 11187     def reload(self, filename = None):
 11188         if filename is not None:
 11189             self.filename = filename
 11190         oldbase = self.base
 11191         self.base = None
 11192         self.lazy_init()
 11193         if self.base is None:
 11194             self.base = oldbase
 11195 
 11196     def get_base(self):
 11197         if self.base is None:
 11198             self.lazy_init()
 11199         return self.base
 11200     
 11201 
 11202 
 11203 ##########################
 11204 ## IP location database ##
 11205 ##########################
 11206 
 11207 class IPCountryKnowledgeBase(KnowledgeBase):
 11208     """
 11209 How to generate the base :
 11210 db = []
 11211 for l in open("GeoIPCountryWhois.csv").readlines():
 11212     s,e,c = l.split(",")[2:5]
 11213     db.append((int(s[1:-1]),int(e[1:-1]),c[1:-1]))
 11214 cPickle.dump(gzip.open("xxx","w"),db)
 11215 """
 11216     def lazy_init(self):
 11217         self.base = load_object(self.filename)
 11218 
 11219 
 11220 class CountryLocKnowledgeBase(KnowledgeBase):
 11221     def lazy_init(self):
 11222         f=open(self.filename)
 11223         self.base = {}
 11224         while 1:
 11225             l = f.readline()
 11226             if not l:
 11227                 break
 11228             l = l.strip().split(",")
 11229             if len(l) != 3:
 11230                 continue
 11231             c,lat,long = l
 11232             
 11233             self.base[c] = (float(long),float(lat))
 11234         f.close()
 11235             
 11236         
 11237 
 11238 
 11239 def locate_ip(ip):
 11240     ip=map(int,ip.split("."))
 11241     ip = ip[3]+(ip[2]<<8L)+(ip[1]<<16L)+(ip[0]<<24L)
 11242 
 11243     cloc = country_loc_kdb.get_base()
 11244     db = IP_country_kdb.get_base()
 11245 
 11246     d=0
 11247     f=len(db)-1
 11248     while (f-d) > 1:
 11249         guess = (d+f)/2
 11250         if ip > db[guess][0]:
 11251             d = guess
 11252         else:
 11253             f = guess
 11254     s,e,c = db[guess]
 11255     if  s <= ip and ip <= e:
 11256         return cloc.get(c,None)
 11257 
 11258 
 11259     
 11260 
 11261 ###############
 11262 ## p0f stuff ##
 11263 ###############
 11264 
 11265 # File format (according to p0f.fp) :
 11266 #
 11267 # wwww:ttt:D:ss:OOO...:QQ:OS:Details
 11268 #
 11269 # wwww    - window size
 11270 # ttt     - initial TTL
 11271 # D       - don't fragment bit  (0=unset, 1=set) 
 11272 # ss      - overall SYN packet size
 11273 # OOO     - option value and order specification
 11274 # QQ      - quirks list
 11275 # OS      - OS genre
 11276 # details - OS description
 11277 
 11278 
 11279 
 11280 class p0fKnowledgeBase(KnowledgeBase):
 11281     def __init__(self, filename):
 11282         KnowledgeBase.__init__(self, filename)
 11283         #self.ttl_range=[255]
 11284     def lazy_init(self):
 11285         try:
 11286             f=open(self.filename)
 11287         except IOError:
 11288             warning("Can't open base %s" % self.filename)
 11289             return
 11290         try:
 11291             self.base = []
 11292             for l in f:
 11293                 if l[0] in ["#","\n"]:
 11294                     continue
 11295                 l = tuple(l.split(":"))
 11296                 if len(l) < 8:
 11297                     continue
 11298                 li = map(int,l[1:4])
 11299                 #if li[0] not in self.ttl_range:
 11300                 #    self.ttl_range.append(li[0])
 11301                 #    self.ttl_range.sort()
 11302                 self.base.append((l[0], li[0], li[1], li[2], l[4], l[5], l[6], l[7][:-1]))
 11303         except:
 11304             warning("Can't parse p0f database (new p0f version ?)")
 11305             self.base = None
 11306         f.close()
 11307 
 11308 
 11309 def packet2p0f(pkt):
 11310     while pkt.haslayer(IP) and pkt.haslayer(TCP):
 11311         pkt = pkt.getlayer(IP)
 11312         if isinstance(pkt.payload, TCP):
 11313             break
 11314         pkt = pkt.payload
 11315 
 11316     if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
 11317         raise TypeError("Not a TCP/IP packet")
 11318     if pkt.payload.flags & 0x13 != 0x02: #S,!A,!F
 11319         raise TypeError("Not a syn packet")
 11320     
 11321     #t = p0f_kdb.ttl_range[:]
 11322     #t += [pkt.ttl]
 11323     #t.sort()
 11324     #ttl=t[t.index(pkt.ttl)+1]
 11325     ttl = pkt.ttl
 11326 
 11327     df = (pkt.flags & 2) / 2
 11328     ss = len(pkt)
 11329     # from p0f/config.h : PACKET_BIG = 100
 11330     if ss > 100:
 11331         ss = 0
 11332 
 11333     ooo = ""
 11334     mss = -1
 11335     qqT = False
 11336     qqP = False
 11337     #qqBroken = False
 11338     ilen = (pkt[TCP].dataofs << 2) - 20 # from p0f.c
 11339     for option in pkt.payload.options:
 11340         ilen -= 1
 11341         if option[0] == "MSS":
 11342             ooo += "M" + str(option[1]) + ","
 11343             mss = option[1]
 11344             # FIXME: qqBroken
 11345             ilen -= 3
 11346         elif option[0] == "WScale":
 11347             ooo += "W" + str(option[1]) + ","
 11348             # FIXME: qqBroken
 11349             ilen -= 2
 11350         elif option[0] == "Timestamp":
 11351             if option[1][0] == 0:
 11352                 ooo += "T0,"
 11353             else:
 11354                 ooo += "T,"
 11355             if option[1][1] != 0:
 11356                 qqT = True
 11357             ilen -= 9
 11358         elif option[0] == "SAckOK":
 11359             ooo += "S,"
 11360             ilen -= 1
 11361         elif option[0] == "NOP":
 11362             ooo += "N,"
 11363         elif option[0] == "EOL":
 11364             ooo += "E,"
 11365             if ilen > 0:
 11366                 qqP = True
 11367         else:
 11368             ooo += "?,"
 11369             # FIXME: ilen
 11370     ooo = ooo[:-1]
 11371     if ooo == "": ooo = "."
 11372 
 11373     win = pkt.payload.window
 11374     if mss != -1:
 11375         if win % mss == 0:
 11376             win = "S" + str(win/mss)
 11377         elif win % (mss + 40) == 0:
 11378             win = "T" + str(win/(mss+40))
 11379         win = str(win)
 11380 
 11381     qq = ""
 11382 
 11383     if qqP:
 11384         qq += "P"
 11385     if pkt[IP].id == 0:
 11386         qq += "Z"
 11387     if pkt[IP].options != '':
 11388         qq += "I"
 11389     if pkt[TCP].urgptr != 0:
 11390         qq += "U"
 11391     if pkt[TCP].reserved != 0:
 11392         qq += "X"
 11393     if pkt[TCP].ack != 0:
 11394         qq += "A"
 11395     if qqT:
 11396         qq += "T"
 11397     if pkt[TCP].flags & 40 != 0:
 11398         # U or P
 11399         qq += "F"
 11400     if not isinstance(pkt[TCP].payload, NoPayload):
 11401         qq += "D"
 11402     # FIXME : "!" - broken options segment
 11403 
 11404     if qq == "":
 11405         qq = "."
 11406 
 11407     return (win,
 11408             ttl,
 11409             df,
 11410             ss,
 11411             ooo,
 11412             qq)
 11413 
 11414 def p0f_correl(x,y):
 11415     d = 0
 11416     # wwww can be "*" or "%nn"
 11417     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))
 11418     # ttl
 11419     d += (y[1] >= x[1] and y[1] - x[1] < 32)
 11420     for i in [2, 3, 5]:
 11421         d += (x[i] == y[i])
 11422     xopt = x[4].split(",")
 11423     yopt = y[4].split(",")
 11424     if len(xopt) == len(yopt):
 11425         same = True
 11426         for i in range(len(xopt)):
 11427             if not (xopt[i] == yopt[i] or
 11428                     (len(yopt[i]) == 2 and len(xopt[i]) > 1 and
 11429                      yopt[i][1] == "*" and xopt[i][0] == yopt[i][0]) or
 11430                     (len(yopt[i]) > 2 and len(xopt[i]) > 1 and
 11431                      yopt[i][1] == "%" and xopt[i][0] == yopt[i][0] and
 11432                      int(xopt[i][1:]) % int(yopt[i][2:]) == 0)):
 11433                 same = False
 11434                 break
 11435         if same:
 11436             d += len(xopt)
 11437     return d
 11438 
 11439 
 11440 def p0f(pkt):
 11441     """Passive OS fingerprinting: which OS emitted this TCP SYN ?
 11442 p0f(packet) -> accuracy, [list of guesses]
 11443 """
 11444     pb = p0f_kdb.get_base()
 11445     if not pb:
 11446         warning("p0f base empty.")
 11447         return []
 11448     s = len(pb[0][0])
 11449     r = []
 11450     sig = packet2p0f(pkt)
 11451     max = len(sig[4].split(",")) + 5
 11452     for b in pb:
 11453         d = p0f_correl(sig,b)
 11454         if d == max:
 11455             r.append((b[6], b[7], b[1] - pkt[IP].ttl))
 11456     return r
 11457             
 11458 
 11459 def prnp0f(pkt):
 11460     try:
 11461         r = p0f(pkt)
 11462     except:
 11463         return
 11464     if r == []:
 11465         r = ("UNKNOWN", "[" + ":".join(map(str, packet2p0f(pkt))) + ":?:?]", None)
 11466     else:
 11467         r = r[0]
 11468     uptime = None
 11469     try:
 11470         uptime = pkt2uptime(pkt)
 11471     except:
 11472         pass
 11473     if uptime == 0:
 11474         uptime = None
 11475     res = pkt.sprintf("%IP.src%:%TCP.sport% - " + r[0] + " " + r[1])
 11476     if uptime is not None:
 11477         res += pkt.sprintf(" (up: " + str(uptime/3600) + " hrs)\n  -> %IP.dst%:%TCP.dport%")
 11478     else:
 11479         res += pkt.sprintf("\n  -> %IP.dst%:%TCP.dport%")
 11480     if r[2] is not None:
 11481         res += " (distance " + str(r[2]) + ")"
 11482     print res
 11483 
 11484 
 11485 def pkt2uptime(pkt, HZ=100):
 11486     """Calculate the date the machine which emitted the packet booted using TCP timestamp
 11487 pkt2uptime(pkt, [HZ=100])"""
 11488     if not isinstance(pkt, Packet):
 11489         raise TypeError("Not a TCP packet")
 11490     if isinstance(pkt,NoPayload):
 11491         raise TypeError("Not a TCP packet")
 11492     if not isinstance(pkt, TCP):
 11493         return pkt2uptime(pkt.payload)
 11494     for opt in pkt.options:
 11495         if opt[0] == "Timestamp":
 11496             #t = pkt.time - opt[1][0] * 1.0/HZ
 11497             #return time.ctime(t)
 11498             t = opt[1][0] / HZ
 11499             return t
 11500     raise TypeError("No timestamp option")
 11501 
 11502 
 11503 
 11504 #################
 11505 ## Queso stuff ##
 11506 #################
 11507 
 11508 
 11509 def quesoTCPflags(flags):
 11510     if flags == "-":
 11511         return "-"
 11512     flv = "FSRPAUXY"
 11513     v = 0
 11514     for i in flags:
 11515         v |= 2**flv.index(i)
 11516     return "%x" % v
 11517 
 11518 class QuesoKnowledgeBase(KnowledgeBase):
 11519     def lazy_init(self):
 11520         try:
 11521             f = open(self.filename)
 11522         except IOError:
 11523             return
 11524         self.base = {}
 11525         p = None
 11526         try:
 11527             for l in f:
 11528                 l = l.strip()
 11529                 if not l or l[0] == ';':
 11530                     continue
 11531                 if l[0] == '*':
 11532                     if p is not None:
 11533                         p[""] = name
 11534                     name = l[1:].strip()
 11535                     p = self.base
 11536                     continue
 11537                 if l[0] not in list("0123456"):
 11538                     continue
 11539                 res = l[2:].split()
 11540                 res[-1] = quesoTCPflags(res[-1])
 11541                 res = " ".join(res)
 11542                 if not p.has_key(res):
 11543                     p[res] = {}
 11544                 p = p[res]
 11545             if p is not None:
 11546                 p[""] = name
 11547         except:
 11548             self.base = None
 11549             warning("Can't load queso base [%s]", self.filename)
 11550         f.close()
 11551             
 11552         
 11553 
 11554     
 11555 def queso_sig(target, dport=80, timeout=3):
 11556     p = queso_kdb.get_base()
 11557     ret = []
 11558     for flags in ["S", "SA", "F", "FA", "SF", "P", "SEC"]:
 11559         ans, unans = sr(IP(dst=target)/TCP(dport=dport,flags=flags,seq=RandInt()),
 11560                         timeout=timeout, verbose=0)
 11561         if len(ans) == 0:
 11562             rs = "- - - -"
 11563         else:
 11564             s,r = ans[0]
 11565             rs = "%i" % (r.seq != 0)
 11566             if not r.ack:
 11567                 r += " 0"
 11568             elif r.ack-s.seq > 666:
 11569                 rs += " R" % 0
 11570             else:
 11571                 rs += " +%i" % (r.ack-s.seq)
 11572             rs += " %X" % r.window
 11573             rs += " %x" % r.payload.flags
 11574         ret.append(rs)
 11575     return ret
 11576             
 11577 def queso_search(sig):
 11578     p = queso_kdb.get_base()
 11579     sig.reverse()
 11580     ret = []
 11581     try:
 11582         while sig:
 11583             s = sig.pop()
 11584             p = p[s]
 11585             if p.has_key(""):
 11586                 ret.append(p[""])
 11587     except KeyError:
 11588         pass
 11589     return ret
 11590         
 11591 
 11592 def queso(*args,**kargs):
 11593     """Queso OS fingerprinting
 11594 queso(target, dport=80, timeout=3)"""
 11595     return queso_search(queso_sig(*args, **kargs))
 11596 
 11597 
 11598 
 11599 ######################
 11600 ## nmap OS fp stuff ##
 11601 ######################
 11602 
 11603 
 11604 class NmapKnowledgeBase(KnowledgeBase):
 11605     def lazy_init(self):
 11606         try:
 11607             f=open(self.filename)
 11608         except IOError:
 11609             return
 11610 
 11611         self.base = []
 11612         name = None
 11613         try:
 11614             for l in f:
 11615                 l = l.strip()
 11616                 if not l or l[0] == "#":
 11617                     continue
 11618                 if l[:12] == "Fingerprint ":
 11619                     if name is not None:
 11620                         self.base.append((name,sig))
 11621                     name = l[12:].strip()
 11622                     sig={}
 11623                     p = self.base
 11624                     continue
 11625                 elif l[:6] == "Class ":
 11626                     continue
 11627                 op = l.find("(")
 11628                 cl = l.find(")")
 11629                 if op < 0 or cl < 0:
 11630                     warning("error reading nmap os fp base file")
 11631                     continue
 11632                 test = l[:op]
 11633                 s = map(lambda x: x.split("="), l[op+1:cl].split("%"))
 11634                 si = {}
 11635                 for n,v in s:
 11636                     si[n] = v
 11637                 sig[test]=si
 11638             if name is not None:
 11639                 self.base.append((name,sig))
 11640         except:
 11641             self.base = None
 11642             warning("Can't read nmap database [%s](new nmap version ?)" % self.filename)
 11643         f.close()
 11644         
 11645 def TCPflags2str(f):
 11646     fl="FSRPAUEC"
 11647     s=""
 11648     for i in range(len(fl)):
 11649         if f & 1:
 11650             s = fl[i]+s
 11651         f >>= 1
 11652     return s
 11653 
 11654 def nmap_tcppacket_sig(pkt):
 11655     r = {}
 11656     if pkt is not None:
 11657 #        r["Resp"] = "Y"
 11658         r["DF"] = (pkt.flags & 2) and "Y" or "N"
 11659         r["W"] = "%X" % pkt.window
 11660         r["ACK"] = pkt.ack==2 and "S++" or pkt.ack==1 and "S" or "O"
 11661         r["Flags"] = TCPflags2str(pkt.payload.flags)
 11662         r["Ops"] = "".join(map(lambda x: x[0][0],pkt.payload.options))
 11663     else:
 11664         r["Resp"] = "N"
 11665     return r
 11666 
 11667 
 11668 def nmap_udppacket_sig(S,T):
 11669     r={}
 11670     if T is None:
 11671         r["Resp"] = "N"
 11672     else:
 11673         r["DF"] = (T.flags & 2) and "Y" or "N"
 11674         r["TOS"] = "%X" % T.tos
 11675         r["IPLEN"] = "%X" % T.len
 11676         r["RIPTL"] = "%X" % T.payload.payload.len
 11677         r["RID"] = S.id == T.payload.payload.id and "E" or "F"
 11678         r["RIPCK"] = S.chksum == T.getlayer(IPerror).chksum and "E" or T.getlayer(IPerror).chksum == 0 and "0" or "F"
 11679         r["UCK"] = S.payload.chksum == T.getlayer(UDPerror).chksum and "E" or T.getlayer(UDPerror).chksum ==0 and "0" or "F"
 11680         r["ULEN"] = "%X" % T.getlayer(UDPerror).len
 11681         r["DAT"] = T.getlayer(Raw) is None and "E" or S.getlayer(Raw).load == T.getlayer(Raw).load and "E" or "F"
 11682     return r
 11683     
 11684 
 11685 
 11686 def nmap_match_one_sig(seen, ref):
 11687     c = 0
 11688     for k in seen.keys():
 11689         if ref.has_key(k):
 11690             if seen[k] in ref[k].split("|"):
 11691                 c += 1
 11692     if c == 0 and seen.get("Resp") == "N":
 11693         return 0.7
 11694     else:
 11695         return 1.0*c/len(seen.keys())
 11696         
 11697         
 11698 
 11699 def nmap_sig(target, oport=80, cport=81, ucport=1):
 11700     res = {}
 11701 
 11702     tcpopt = [ ("WScale", 10),
 11703                ("NOP",None),
 11704                ("MSS", 256),
 11705                ("Timestamp",(123,0)) ]
 11706     tests = [ IP(dst=target, id=1)/TCP(seq=1, sport=5001, dport=oport, options=tcpopt, flags="CS"),
 11707               IP(dst=target, id=1)/TCP(seq=1, sport=5002, dport=oport, options=tcpopt, flags=0),
 11708               IP(dst=target, id=1)/TCP(seq=1, sport=5003, dport=oport, options=tcpopt, flags="SFUP"),
 11709               IP(dst=target, id=1)/TCP(seq=1, sport=5004, dport=oport, options=tcpopt, flags="A"),
 11710               IP(dst=target, id=1)/TCP(seq=1, sport=5005, dport=cport, options=tcpopt, flags="S"),
 11711               IP(dst=target, id=1)/TCP(seq=1, sport=5006, dport=cport, options=tcpopt, flags="A"),
 11712               IP(dst=target, id=1)/TCP(seq=1, sport=5007, dport=cport, options=tcpopt, flags="FPU"),
 11713               IP(str(IP(dst=target)/UDP(sport=5008,dport=ucport)/(300*"i"))) ]
 11714 
 11715     ans, unans = sr(tests, timeout=2)
 11716     ans += map(lambda x: (x,None), unans)
 11717 
 11718     for S,T in ans:
 11719         if S.sport == 5008:
 11720             res["PU"] = nmap_udppacket_sig(S,T)
 11721         else:
 11722             t = "T%i" % (S.sport-5000)
 11723             if T is not None and T.haslayer(ICMP):
 11724                 warning("Test %s answered by an ICMP" % t)
 11725                 T=None
 11726             res[t] = nmap_tcppacket_sig(T)
 11727 
 11728     return res
 11729 
 11730 def nmap_probes2sig(tests):
 11731     tests=tests.copy()
 11732     res = {}
 11733     if "PU" in tests:
 11734         res["PU"] = nmap_udppacket_sig(*tests["PU"])
 11735         del(tests["PU"])
 11736     for k in tests:
 11737         res[k] = nmap_tcppacket_sig(tests[k])
 11738     return res
 11739         
 11740 
 11741 def nmap_search(sigs):
 11742     guess = 0,[]
 11743     for os,fp in nmap_kdb.get_base():
 11744         c = 0.0
 11745         for t in sigs.keys():
 11746             if t in fp:
 11747                 c += nmap_match_one_sig(sigs[t], fp[t])
 11748         c /= len(sigs.keys())
 11749         if c > guess[0]:
 11750             guess = c,[ os ]
 11751         elif c == guess[0]:
 11752             guess[1].append(os)
 11753     return guess
 11754     
 11755     
 11756 def nmap_fp(target, oport=80, cport=81):
 11757     """nmap fingerprinting
 11758 nmap_fp(target, [oport=80,] [cport=81,]) -> list of best guesses with accuracy
 11759 """
 11760     sigs = nmap_sig(target, oport, cport)
 11761     return nmap_search(sigs)
 11762         
 11763 
 11764 def nmap_sig2txt(sig):
 11765     torder = ["TSeq","T1","T2","T3","T4","T5","T6","T7","PU"]
 11766     korder = ["Class", "gcd", "SI", "IPID", "TS",
 11767               "Resp", "DF", "W", "ACK", "Flags", "Ops",
 11768               "TOS", "IPLEN", "RIPTL", "RID", "RIPCK", "UCK", "ULEN", "DAT" ]
 11769     txt=[]
 11770     for i in sig.keys():
 11771         if i not in torder:
 11772             torder.append(i)
 11773     for t in torder:
 11774         sl = sig.get(t)
 11775         if sl is None:
 11776             continue
 11777         s = []
 11778         for k in korder:
 11779             v = sl.get(k)
 11780             if v is None:
 11781                 continue
 11782             s.append("%s=%s"%(k,v))
 11783         txt.append("%s(%s)" % (t, "%".join(s)))
 11784     return "\n".join(txt)
 11785             
 11786         
 11787 
 11788 
 11789 
 11790 ###################
 11791 ## User commands ##
 11792 ###################
 11793 
 11794 
 11795 def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None, *arg, **karg):
 11796     """Sniff packets
 11797 sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets
 11798 
 11799   count: number of packets to capture. 0 means infinity
 11800   store: wether to store sniffed packets or discard them
 11801     prn: function to apply to each packet. If something is returned,
 11802          it is displayed. Ex:
 11803          ex: prn = lambda x: x.summary()
 11804 lfilter: python function applied to each packet to determine
 11805          if further action may be done
 11806          ex: lfilter = lambda x: x.haslayer(Padding)
 11807 offline: pcap file to read packets from, instead of sniffing them
 11808 timeout: stop sniffing after a given time (default: None)
 11809 L2socket: use the provided L2socket
 11810     """
 11811     c = 0
 11812 
 11813     if offline is None:
 11814         if L2socket is None:
 11815             L2socket = conf.L2listen
 11816         s = L2socket(type=ETH_P_ALL, *arg, **karg)
 11817     else:
 11818         s = PcapReader(offline)
 11819 
 11820     lst = []
 11821     if timeout is not None:
 11822         stoptime = time.time()+timeout
 11823     remain = None
 11824     while 1:
 11825         try:
 11826             if timeout is not None:
 11827                 remain = stoptime-time.time()
 11828                 if remain <= 0:
 11829                     break
 11830             sel = select([s],[],[],remain)
 11831             if s in sel[0]:
 11832                 p = s.recv(MTU)
 11833                 if p is None:
 11834                     break
 11835                 if lfilter and not lfilter(p):
 11836                     continue
 11837                 if store:
 11838                     lst.append(p)
 11839                 c += 1
 11840                 if prn:
 11841                     r = prn(p)
 11842                     if r is not None:
 11843                         print r
 11844                 if count > 0 and c >= count:
 11845                     break
 11846         except KeyboardInterrupt:
 11847             break
 11848     s.close()
 11849     return PacketList(lst,"Sniffed")
 11850 
 11851 
 11852 
 11853 def arpcachepoison(target, victim, interval=60):
 11854     """Poison target's cache with (your MAC,victim's IP) couple
 11855 arpcachepoison(target, victim, [interval=60]) -> None
 11856 """
 11857     tmac = getmacbyip(target)
 11858     p = Ether(dst=tmac)/ARP(op="who-has", psrc=victim, pdst=target)
 11859     try:
 11860         while 1:
 11861             sendp(p, iface_hint=target)
 11862             if conf.verb > 1:
 11863                 os.write(1,".")
 11864             time.sleep(interval)
 11865     except KeyboardInterrupt:
 11866         pass
 11867 
 11868 def traceroute(target, dport=80, minttl=1, maxttl=30, sport=RandShort(), l4 = None, filter=None, timeout=2, verbose=None, **kargs):
 11869     """Instant TCP traceroute
 11870 traceroute(target, [maxttl=30,] [dport=80,] [sport=80,] [verbose=conf.verb]) -> None
 11871 """
 11872     if verbose is None:
 11873         verbose = conf.verb
 11874     if filter is None:
 11875         # we only consider ICMP error packets and TCP packets with at
 11876         # least the ACK flag set *and* either the SYN or the RST flag
 11877         # set
 11878         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))"
 11879     if l4 is None:
 11880         a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport),
 11881                  timeout=timeout, filter=filter, verbose=verbose, **kargs)
 11882     else:
 11883         # this should always work
 11884         filter="ip"
 11885         a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/l4,
 11886                  timeout=timeout, filter=filter, verbose=verbose, **kargs)
 11887 
 11888     a = TracerouteResult(a.res)
 11889     if verbose:
 11890         a.show()
 11891     return a,b
 11892 
 11893 
 11894 
 11895 
 11896 def arping(net, timeout=2, cache=0, verbose=None, **kargs):
 11897     """Send ARP who-has requests to determine which hosts are up
 11898 arping(net, [cache=0,] [iface=conf.iface,] [verbose=conf.verb]) -> None
 11899 Set cache=True if you want arping to modify internal ARP-Cache"""
 11900     if verbose is None:
 11901         verbose = conf.verb
 11902     ans,unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=net), verbose=verbose,
 11903                     filter="arp and arp[7] = 2", timeout=timeout, iface_hint=net, **kargs)
 11904     ans = ARPingResult(ans.res)
 11905 
 11906     if cache and ans is not None:
 11907         for pair in ans:
 11908             arp_cache[pair[1].psrc] = (pair[1].hwsrc, time.time())
 11909     if verbose:
 11910         ans.show()
 11911     return ans,unans
 11912 
 11913 def dyndns_add(nameserver, name, rdata, type="A", ttl=10):
 11914     """Send a DNS add message to a nameserver for "name" to have a new "rdata"
 11915 dyndns_add(nameserver, name, rdata, type="A", ttl=10) -> result code (0=ok)
 11916 
 11917 example: dyndns_add("ns1.toto.com", "dyn.toto.com", "127.0.0.1")
 11918 RFC2136
 11919 """
 11920     zone = name[name.find(".")+1:]
 11921     r=sr1(IP(dst=nameserver)/UDP()/DNS(opcode=5,
 11922                                        qd=[DNSQR(qname=zone, qtype="SOA")],
 11923                                        ns=[DNSRR(rrname=name, type="A",
 11924                                                  ttl=ttl, rdata=rdata)]),
 11925           verbose=0, timeout=5)
 11926     if r and r.haslayer(DNS):
 11927         return r.getlayer(DNS).rcode
 11928     else:
 11929         return -1
 11930     
 11931     
 11932     
 11933 
 11934 def dyndns_del(nameserver, name, type="ALL", ttl=10):
 11935     """Send a DNS delete message to a nameserver for "name"
 11936 dyndns_del(nameserver, name, type="ANY", ttl=10) -> result code (0=ok)
 11937 
 11938 example: dyndns_del("ns1.toto.com", "dyn.toto.com")
 11939 RFC2136
 11940 """
 11941     zone = name[name.find(".")+1:]
 11942     r=sr1(IP(dst=nameserver)/UDP()/DNS(opcode=5,
 11943                                        qd=[DNSQR(qname=zone, qtype="SOA")],
 11944                                        ns=[DNSRR(rrname=name, type=type,
 11945                                                  rclass="ANY", ttl=0, rdata="")]),
 11946           verbose=0, timeout=5)
 11947     if r and r.haslayer(DNS):
 11948         return r.getlayer(DNS).rcode
 11949     else:
 11950         return -1
 11951     
 11952 
 11953 def is_promisc(ip, fake_bcast="ff:ff:00:00:00:00",**kargs):
 11954     """Try to guess if target is in Promisc mode. The target is provided by its ip."""
 11955 
 11956     responses = srp1(Ether(dst=fake_bcast) / ARP(op="who-has", pdst=ip),type=ETH_P_ARP, iface_hint=ip, timeout=1, verbose=0,**kargs)
 11957 
 11958     return responses is not None
 11959 
 11960 def promiscping(net, timeout=2, fake_bcast="ff:ff:ff:ff:ff:fe", **kargs):
 11961     """Send ARP who-has requests to determine which hosts are in promiscuous mode
 11962     promiscping(net, iface=conf.iface)"""
 11963     ans,unans = srp(Ether(dst=fake_bcast)/ARP(pdst=net),
 11964                     filter="arp and arp[7] = 2", timeout=timeout, iface_hint=net, **kargs)
 11965     ans = ARPingResult(ans.res, name="PROMISCPing")
 11966 
 11967     ans.display()
 11968     return ans,unans
 11969 
 11970 def ikescan(ip):
 11971     return sr(IP(dst=ip)/UDP()/ISAKMP(init_cookie=RandString(8),
 11972                                       exch_type=2)/ISAKMP_payload_SA(prop=ISAKMP_payload_Proposal()))
 11973 
 11974 
 11975 def dhcp_request(iface=None,**kargs):
 11976     if conf.checkIPaddr != 0:
 11977         warning("conf.checkIPaddr is not 0, I may not be able to match the answer")
 11978     if iface is None:
 11979         iface = conf.iface
 11980     fam,hw = get_if_raw_hwaddr(iface)
 11981     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)
 11982                  /BOOTP(chaddr=hw)/DHCP(options=[("message-type","discover"),"end"]),iface=iface,**kargs)
 11983 
 11984 def snmpwalk(dst, oid="1", community="public"):
 11985     try:
 11986         while 1:
 11987             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)
 11988             if ICMP in r:
 11989                 print repr(r)
 11990                 break
 11991             if r is None:
 11992                 print "No answers"
 11993                 break
 11994             print "%-40s: %r" % (r[SNMPvarbind].oid.val,r[SNMPvarbind].value)
 11995             oid = r[SNMPvarbind].oid
 11996             
 11997     except KeyboardInterrupt:
 11998         pass
 11999 
 12000 
 12001 #####################
 12002 ## Reporting stuff ##
 12003 #####################
 12004 
 12005 def report_ports(target, ports):
 12006     """portscan a target and output a LaTeX table
 12007 report_ports(target, ports) -> string"""
 12008     ans,unans = sr(IP(dst=target)/TCP(dport=ports),timeout=5)
 12009     rep = "\\begin{tabular}{|r|l|l|}\n\\hline\n"
 12010     for s,r in ans:
 12011         if not r.haslayer(ICMP):
 12012             if r.payload.flags == 0x12:
 12013                 rep += r.sprintf("%TCP.sport% & open & SA \\\\\n")
 12014     rep += "\\hline\n"
 12015     for s,r in ans:
 12016         if r.haslayer(ICMP):
 12017             rep += r.sprintf("%TCPerror.dport% & closed & ICMP type %ICMP.type%/%ICMP.code% from %IP.src% \\\\\n")
 12018         elif r.payload.flags != 0x12:
 12019             rep += r.sprintf("%TCP.sport% & closed & TCP %TCP.flags% \\\\\n")
 12020     rep += "\\hline\n"
 12021     for i in unans:
 12022         rep += i.sprintf("%TCP.dport% & ? & unanswered \\\\\n")
 12023     rep += "\\hline\n\\end{tabular}\n"
 12024     return rep
 12025 
 12026 
 12027 def __make_table(yfmtfunc, fmtfunc, endline, list, fxyz, sortx=None, sorty=None, seplinefunc=None):
 12028     vx = {} 
 12029     vy = {} 
 12030     vz = {}
 12031     vxf = {}
 12032     vyf = {}
 12033     l = 0
 12034     for e in list:
 12035         xx,yy,zz = map(str, fxyz(e))
 12036         l = max(len(yy),l)
 12037         vx[xx] = max(vx.get(xx,0), len(xx), len(zz))
 12038         vy[yy] = None
 12039         vz[(xx,yy)] = zz
 12040 
 12041     vxk = vx.keys()
 12042     vyk = vy.keys()
 12043     if sortx:
 12044         vxk.sort(sortx)
 12045     else:
 12046         try:
 12047             vxk.sort(lambda x,y:int(x)-int(y))
 12048         except:
 12049             try:
 12050                 vxk.sort(lambda x,y: cmp(atol(x),atol(y)))
 12051             except:
 12052                 vxk.sort()
 12053     if sorty:
 12054         vyk.sort(sorty)
 12055     else:
 12056         try:
 12057             vyk.sort(lambda x,y:int(x)-int(y))
 12058         except:
 12059             try:
 12060                 vyk.sort(lambda x,y: cmp(atol(x),atol(y)))
 12061             except:
 12062                 vyk.sort()
 12063 
 12064 
 12065     if seplinefunc:
 12066         sepline = seplinefunc(l, map(lambda x:vx[x],vxk))
 12067         print sepline
 12068 
 12069     fmt = yfmtfunc(l)
 12070     print fmt % "",
 12071     for x in vxk:
 12072         vxf[x] = fmtfunc(vx[x])
 12073         print vxf[x] % x,
 12074     print endline
 12075     if seplinefunc:
 12076         print sepline
 12077     for y in vyk:
 12078         print fmt % y,
 12079         for x in vxk:
 12080             print vxf[x] % vz.get((x,y), "-"),
 12081         print endline
 12082     if seplinefunc:
 12083         print sepline
 12084 
 12085 def make_table(*args, **kargs):
 12086     __make_table(lambda l:"%%-%is" % l, lambda l:"%%-%is" % l, "", *args, **kargs)
 12087     
 12088 def make_lined_table(*args, **kargs):
 12089     __make_table(lambda l:"%%-%is |" % l, lambda l:"%%-%is |" % l, "",
 12090                  seplinefunc=lambda a,x:"+".join(map(lambda y:"-"*(y+2), [a-1]+x+[-2])),
 12091                  *args, **kargs)
 12092 
 12093 def make_tex_table(*args, **kargs):
 12094     __make_table(lambda l: "%s", lambda l: "& %s", "\\\\", seplinefunc=lambda a,x:"\\hline", *args, **kargs)
 12095     
 12096 
 12097 ######################
 12098 ## Online doc stuff ##
 12099 ######################
 12100 
 12101 
 12102 def lsc(cmd=None):
 12103     """List user commands"""
 12104     if cmd is None:
 12105         for c in user_commands:
 12106             doc = "No doc. available"
 12107             if c.__doc__:
 12108                 doc = c.__doc__.split("\n")[0]
 12109             
 12110             print "%-16s : %s" % (c.__name__, doc)
 12111     else:
 12112         print cmd.__doc__
 12113 
 12114 def ls(obj=None):
 12115     """List  available layers, or infos on a given layer"""
 12116     if obj is None:
 12117         import __builtin__
 12118         all = __builtin__.__dict__.copy()
 12119         all.update(globals())
 12120         objlst = filter(lambda (n,o): isinstance(o,type) and issubclass(o,Packet), all.items())
 12121         objlst.sort(lambda x,y:cmp(x[0],y[0]))
 12122         for n,o in objlst:
 12123             print "%-10s : %s" %(n,o.name)
 12124     else:
 12125         if isinstance(obj, type) and issubclass(obj, Packet):
 12126             for f in obj.fields_desc:
 12127                 print "%-10s : %-20s = (%s)" % (f.name, f.__class__.__name__,  repr(f.default))
 12128         elif isinstance(obj, Packet):
 12129             for f in obj.fields_desc:
 12130                 print "%-10s : %-20s = %-15s (%s)" % (f.name, f.__class__.__name__, repr(getattr(obj,f.name)), repr(f.default))
 12131             if not isinstance(obj.payload, NoPayload):
 12132                 print "--"
 12133                 ls(obj.payload)
 12134                 
 12135 
 12136         else:
 12137             print "Not a packet class. Type 'ls()' to list packet classes."
 12138 
 12139 
 12140     
 12141 
 12142 
 12143 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 ]
 12144 
 12145 
 12146 ##############
 12147 ## Automata ##
 12148 ##############
 12149 
 12150 class ATMT:
 12151     STATE = "State"
 12152     ACTION = "Action"
 12153     CONDITION = "Condition"
 12154     RECV = "Receive condition"
 12155     TIMEOUT = "Timeout condition"
 12156 
 12157     class NewStateRequested(Exception):
 12158         def __init__(self, state_func, automaton, *args, **kargs):
 12159             self.func = state_func
 12160             self.state = state_func.atmt_state
 12161             self.initial = state_func.atmt_initial
 12162             self.error = state_func.atmt_error
 12163             self.final = state_func.atmt_final
 12164             Exception.__init__(self, "Request state [%s]" % self.state)
 12165             self.automaton = automaton
 12166             self.args = args
 12167             self.kargs = kargs
 12168             self.action_parameters() # init action parameters
 12169         def action_parameters(self, *args, **kargs):
 12170             self.action_args = args
 12171             self.action_kargs = kargs
 12172             return self
 12173         def run(self):
 12174             return self.func(self.automaton, *self.args, **self.kargs)
 12175 
 12176     @staticmethod
 12177     def state(initial=0,final=0,error=0):
 12178         def deco(f,initial=initial, final=final):
 12179             f.atmt_type = ATMT.STATE
 12180             f.atmt_state = f.func_name
 12181             f.atmt_initial = initial
 12182             f.atmt_final = final
 12183             f.atmt_error = error
 12184             def state_wrapper(self, *args, **kargs):
 12185                 return ATMT.NewStateRequested(f, self, *args, **kargs)
 12186 
 12187             state_wrapper.func_name = "%s_wrapper" % f.func_name
 12188             state_wrapper.atmt_type = ATMT.STATE
 12189             state_wrapper.atmt_state = f.func_name
 12190             state_wrapper.atmt_initial = initial
 12191             state_wrapper.atmt_final = final
 12192             state_wrapper.atmt_error = error
 12193             state_wrapper.atmt_origfunc = f
 12194             return state_wrapper
 12195         return deco
 12196     @staticmethod
 12197     def action(cond, prio=0):
 12198         def deco(f,cond=cond):
 12199             if not hasattr(f,"atmt_type"):
 12200                 f.atmt_cond = {}
 12201             f.atmt_type = ATMT.ACTION
 12202             f.atmt_cond[cond.atmt_condname] = prio
 12203             return f
 12204         return deco
 12205     @staticmethod
 12206     def condition(state, prio=0):
 12207         def deco(f, state=state):
 12208             f.atmt_type = ATMT.CONDITION
 12209             f.atmt_state = state.atmt_state
 12210             f.atmt_condname = f.func_name
 12211             f.atmt_prio = prio
 12212             return f
 12213         return deco
 12214     @staticmethod
 12215     def receive_condition(state, prio=0):
 12216         def deco(f, state=state):
 12217             f.atmt_type = ATMT.RECV
 12218             f.atmt_state = state.atmt_state
 12219             f.atmt_condname = f.func_name
 12220             f.atmt_prio = prio
 12221             return f
 12222         return deco
 12223     @staticmethod
 12224     def timeout(state, timeout):
 12225         def deco(f, state=state, timeout=timeout):
 12226             f.atmt_type = ATMT.TIMEOUT
 12227             f.atmt_state = state.atmt_state
 12228             f.atmt_timeout = timeout
 12229             f.atmt_condname = f.func_name
 12230             return f
 12231         return deco
 12232 
 12233 
 12234 class Automaton_metaclass(type):
 12235     def __new__(cls, name, bases, dct):
 12236         cls = super(Automaton_metaclass, cls).__new__(cls, name, bases, dct)
 12237         cls.states={}
 12238         cls.state = None
 12239         cls.recv_conditions={}
 12240         cls.conditions={}
 12241         cls.timeout={}
 12242         cls.actions={}
 12243         cls.initial_states=[]
 12244 
 12245         members = {}
 12246         classes = [cls]
 12247         while classes:
 12248             c = classes.pop(0) # order is important to avoid breaking method overloading
 12249             classes += list(c.__bases__)
 12250             for k,v in c.__dict__.iteritems():
 12251                 if k not in members:
 12252                     members[k] = v
 12253 
 12254         decorated = [v for v in members.itervalues()
 12255                      if type(v) is types.FunctionType and hasattr(v, "atmt_type")]
 12256         
 12257         for m in decorated:
 12258             if m.atmt_type == ATMT.STATE:
 12259                 s = m.atmt_state
 12260                 cls.states[s] = m
 12261                 cls.recv_conditions[s]=[]
 12262                 cls.conditions[s]=[]
 12263                 cls.timeout[s]=[]
 12264                 if m.atmt_initial:
 12265                     cls.initial_states.append(m)
 12266             elif m.atmt_type in [ATMT.CONDITION, ATMT.RECV, ATMT.TIMEOUT]:
 12267                 cls.actions[m.atmt_condname] = []
 12268     
 12269         for m in decorated:
 12270             if m.atmt_type == ATMT.CONDITION:
 12271                 cls.conditions[m.atmt_state].append(m)
 12272             elif m.atmt_type == ATMT.RECV:
 12273                 cls.recv_conditions[m.atmt_state].append(m)
 12274             elif m.atmt_type == ATMT.TIMEOUT:
 12275                 cls.timeout[m.atmt_state].append((m.atmt_timeout, m))
 12276             elif m.atmt_type == ATMT.ACTION:
 12277                 for c in m.atmt_cond:
 12278                     cls.actions[c].append(m)
 12279             
 12280 
 12281         for v in cls.timeout.itervalues():
 12282             v.sort(lambda (t1,f1),(t2,f2): cmp(t1,t2))
 12283             v.append((None, None))
 12284         for v in itertools.chain(cls.conditions.itervalues(),
 12285                                  cls.recv_conditions.itervalues()):
 12286             v.sort(lambda c1,c2: cmp(c1.atmt_prio,c2.atmt_prio))
 12287         for condname,actlst in cls.actions.iteritems():
 12288             actlst.sort(lambda c1,c2: cmp(c1.atmt_cond[condname], c2.atmt_cond[condname]))
 12289 
 12290         return cls
 12291 
 12292         
 12293     def graph(self, **kargs):
 12294         s = 'digraph "%s" {\n'  % self.__class__.__name__
 12295         
 12296         se = "" # Keep initial nodes at the begining for better rendering
 12297         for st in self.states.itervalues():
 12298             if st.atmt_initial:
 12299                 se = ('\t"%s" [ style=filled, fillcolor=blue, shape=box, root=true];\n' % st.atmt_state)+se
 12300             elif st.atmt_final:
 12301                 se += '\t"%s" [ style=filled, fillcolor=green, shape=octagon ];\n' % st.atmt_state
 12302             elif st.atmt_error:
 12303                 se += '\t"%s" [ style=filled, fillcolor=red, shape=octagon ];\n' % st.atmt_state
 12304         s += se
 12305 
 12306         for st in self.states.values():
 12307             for n in st.atmt_origfunc.func_code.co_names+st.atmt_origfunc.func_code.co_consts:
 12308                 if n in self.states:
 12309                     s += '\t"%s" -> "%s" [ color=green ];\n' % (st.atmt_state,n)
 12310             
 12311 
 12312         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()]:
 12313             for f in v:
 12314                 for n in f.func_code.co_names+f.func_code.co_consts:
 12315                     if n in self.states:
 12316                         l = f.atmt_condname
 12317                         for x in self.actions[f.atmt_condname]:
 12318                             l += "\\l>[%s]" % x.func_name
 12319                         s += '\t"%s" -> "%s" [label="%s", color=%s];\n' % (k,n,l,c)
 12320         for k,v in self.timeout.iteritems():
 12321             for t,f in v:
 12322                 if f is None:
 12323                     continue
 12324                 for n in f.func_code.co_names+f.func_code.co_consts:
 12325                     if n in self.states:
 12326                         l = "%s/%.1fs" % (f.atmt_condname,t)                        
 12327                         for x in self.actions[f.atmt_condname]:
 12328                             l += "\\l>[%s]" % x.func_name
 12329                         s += '\t"%s" -> "%s" [label="%s",color=blue];\n' % (k,n,l)
 12330         s += "}\n"
 12331         return do_graph(s, **kargs)
 12332         
 12333 
 12334 
 12335 class Automaton:
 12336     __metaclass__ = Automaton_metaclass
 12337 
 12338     def __init__(self, *args, **kargs):
 12339         self.debug_level=0
 12340         self.init_args=args
 12341         self.init_kargs=kargs
 12342         self.parse_args(*args, **kargs)
 12343 
 12344     def debug(self, lvl, msg):
 12345         if self.debug_level >= lvl:
 12346             log_interactive.debug(msg)
 12347             
 12348 
 12349 
 12350 
 12351     class ErrorState(Exception):
 12352         def __init__(self, msg, result=None):
 12353             Exception.__init__(self, msg)
 12354             self.result = result
 12355     class Stuck(ErrorState):
 12356         pass
 12357 
 12358     def parse_args(self, debug=0, store=1, **kargs):
 12359         self.debug_level=debug
 12360         self.socket_kargs = kargs
 12361         self.store_packets = store
 12362         
 12363 
 12364     def master_filter(self, pkt):
 12365         return True
 12366 
 12367     def run_condition(self, cond, *args, **kargs):
 12368         try:
 12369             cond(self,*args, **kargs)
 12370         except ATMT.NewStateRequested, state_req:
 12371             self.debug(2, "%s [%s] taken to state [%s]" % (cond.atmt_type, cond.atmt_condname, state_req.state))
 12372             if cond.atmt_type == ATMT.RECV:
 12373                 self.packets.append(args[0])
 12374             for action in self.actions[cond.atmt_condname]:
 12375                 self.debug(2, "   + Running action [%s]" % action.func_name)
 12376                 action(self, *state_req.action_args, **state_req.action_kargs)
 12377             raise
 12378         else:
 12379             self.debug(2, "%s [%s] not taken" % (cond.atmt_type, cond.atmt_condname))
 12380             
 12381 
 12382     def run(self, *args, **kargs):
 12383         # Update default parameters
 12384         a = args+self.init_args[len(args):]
 12385         k = self.init_kargs
 12386         k.update(kargs)
 12387         self.parse_args(*a,**k)
 12388 
 12389         # Start the automaton
 12390         self.state=self.initial_states[0](self)
 12391         self.send_sock = conf.L3socket()
 12392         l = conf.L2listen(**self.socket_kargs)
 12393         self.packets = PacketList(name="session[%s]"%self.__class__.__name__)
 12394         while 1:
 12395             try:
 12396                 self.debug(1, "## state=[%s]" % self.state.state)
 12397 
 12398                 # Entering a new state. First, call new state function
 12399                 state_output = self.state.run()
 12400                 if self.state.error:
 12401                     raise self.ErrorState("Reached %s: [%r]" % (self.state.state, state_output), result=state_output)
 12402                 if self.state.final:
 12403                     return state_output
 12404 
 12405                 if state_output is None:
 12406                     state_output = ()
 12407                 elif type(state_output) is not list:
 12408                     state_output = state_output,
 12409                 
 12410                 # Then check immediate conditions
 12411                 for cond in self.conditions[self.state.state]:
 12412                     self.run_condition(cond, *state_output)
 12413 
 12414                 # If still there and no conditions left, we are stuck!
 12415                 if ( len(self.recv_conditions[self.state.state]) == 0
 12416                      and len(self.timeout[self.state.state]) == 1 ):
 12417                     raise self.Stuck("stuck in [%s]" % self.state.state,result=state_output)
 12418 
 12419                 # Finally listen and pay attention to timeouts
 12420                 expirations = iter(self.timeout[self.state.state])
 12421                 next_timeout,timeout_func = expirations.next()
 12422                 t0 = time.time()
 12423                 
 12424                 while 1:
 12425                     t = time.time()-t0
 12426                     if next_timeout is not None:
 12427                         if next_timeout <= t:
 12428                             self.run_condition(timeout_func, *state_output)
 12429                             next_timeout,timeout_func = expirations.next()
 12430                     if next_timeout is None:
 12431                         remain = None
 12432                     else:
 12433                         remain = next_timeout-t
 12434     
 12435                     r,_,_ = select([l],[],[],remain)
 12436                     if l in r:
 12437                         pkt = l.recv(MTU)
 12438                         if pkt is not None:
 12439                             if self.master_filter(pkt):
 12440                                 self.debug(3, "RECVD: %s" % pkt.summary())
 12441                                 for rcvcond in self.recv_conditions[self.state.state]:
 12442                                     self.run_condition(rcvcond, pkt, *state_output)
 12443                             else:
 12444                                 self.debug(4, "FILTR: %s" % pkt.summary())
 12445 
 12446             except ATMT.NewStateRequested,state_req:
 12447                 self.debug(2, "switching from [%s] to [%s]" % (self.state.state,state_req.state))
 12448                 self.state = state_req
 12449             except KeyboardInterrupt:
 12450                 self.debug(1,"Interrupted by user")
 12451                 break
 12452 
 12453     def my_send(self, pkt):
 12454         self.send_sock.send(pkt)
 12455 
 12456     def send(self, pkt):
 12457         self.my_send(pkt)
 12458         self.debug(3,"SENT : %s" % pkt.summary())
 12459         self.packets.append(pkt.copy())
 12460 
 12461 
 12462         
 12463 
 12464     
 12465 
 12466 class TFTP_read(Automaton):
 12467     def parse_args(self, filename, server, sport = None, port=69, **kargs):
 12468         Automaton.parse_args(self, **kargs)
 12469         self.filename = filename
 12470         self.server = server
 12471         self.port = port
 12472         self.sport = sport
 12473 
 12474 
 12475     def master_filter(self, pkt):
 12476         return ( IP in pkt and pkt[IP].src == self.server and UDP in pkt
 12477                  and pkt[UDP].dport == self.my_tid
 12478                  and (self.server_tid is None or pkt[UDP].sport == self.server_tid) )
 12479         
 12480     # BEGIN
 12481     @ATMT.state(initial=1)
 12482     def BEGIN(self):
 12483         self.blocksize=512
 12484         self.my_tid = self.sport or RandShort()._fix()
 12485         bind_bottom_up(UDP, TFTP, dport=self.my_tid)
 12486         self.server_tid = None
 12487         self.res = ""
 12488 
 12489         self.l3 = IP(dst=self.server)/UDP(sport=self.my_tid, dport=self.port)/TFTP()
 12490         self.last_packet = self.l3/TFTP_RRQ(filename=self.filename, mode="octet")
 12491         self.send(self.last_packet)
 12492         self.awaiting=1
 12493         
 12494         raise self.WAITING()
 12495         
 12496     # WAITING
 12497     @ATMT.state()
 12498     def WAITING(self):
 12499         pass
 12500 
 12501 
 12502     @ATMT.receive_condition(WAITING)
 12503     def receive_data(self, pkt):
 12504         if TFTP_DATA in pkt and pkt[TFTP_DATA].block == self.awaiting:
 12505             if self.server_tid is None:
 12506                 self.server_tid = pkt[UDP].sport
 12507                 self.l3[UDP].dport = self.server_tid
 12508             raise self.RECEIVING(pkt)
 12509 
 12510     @ATMT.receive_condition(WAITING, prio=1)
 12511     def receive_error(self, pkt):
 12512         if TFTP_ERROR in pkt:
 12513             raise self.ERROR(pkt)
 12514     
 12515         
 12516     @ATMT.timeout(WAITING, 3)
 12517     def timeout_waiting(self):
 12518         raise self.WAITING()
 12519     @ATMT.action(timeout_waiting)
 12520     def retransmit_last_packet(self):
 12521         self.send(self.last_packet)
 12522 
 12523     @ATMT.action(receive_data)
 12524 #    @ATMT.action(receive_error)
 12525     def send_ack(self):
 12526         self.last_packet = self.l3 / TFTP_ACK(block = self.awaiting)
 12527         self.send(self.last_packet)
 12528     
 12529 
 12530     # RECEIVED
 12531     @ATMT.state()
 12532     def RECEIVING(self, pkt):
 12533         if Raw in pkt:
 12534             recvd = pkt[Raw].load
 12535         else:
 12536             recvd = ""
 12537         self.res += recvd
 12538         self.awaiting += 1
 12539         if len(recvd) == self.blocksize:
 12540             raise self.WAITING()
 12541         raise self.END()
 12542 
 12543     # ERROR
 12544     @ATMT.state(error=1)
 12545     def ERROR(self,pkt):
 12546         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12547         return pkt[TFTP_ERROR].summary()
 12548     
 12549     #END
 12550     @ATMT.state(final=1)
 12551     def END(self):
 12552         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12553         return self.res
 12554 
 12555 
 12556 
 12557 
 12558 class TFTP_write(Automaton):
 12559     def parse_args(self, filename, data, server, sport=None, port=69,**kargs):
 12560         Automaton.parse_args(self, **kargs)
 12561         self.filename = filename
 12562         self.server = server
 12563         self.port = port
 12564         self.sport = sport
 12565         self.blocksize = 512
 12566         self.origdata = data
 12567 
 12568     def master_filter(self, pkt):
 12569         return ( IP in pkt and pkt[IP].src == self.server and UDP in pkt
 12570                  and pkt[UDP].dport == self.my_tid
 12571                  and (self.server_tid is None or pkt[UDP].sport == self.server_tid) )
 12572         
 12573 
 12574     # BEGIN
 12575     @ATMT.state(initial=1)
 12576     def BEGIN(self):
 12577         self.data = [ self.origdata[i*self.blocksize:(i+1)*self.blocksize]
 12578                       for i in range( len(self.origdata)/self.blocksize+1) ] 
 12579         self.my_tid = self.sport or RandShort()._fix()
 12580         bind_bottom_up(UDP, TFTP, dport=self.my_tid)
 12581         self.server_tid = None
 12582         
 12583         self.l3 = IP(dst=self.server)/UDP(sport=self.my_tid, dport=self.port)/TFTP()
 12584         self.last_packet = self.l3/TFTP_WRQ(filename=self.filename, mode="octet")
 12585         self.send(self.last_packet)
 12586         self.res = ""
 12587         self.awaiting=0
 12588 
 12589         raise self.WAITING_ACK()
 12590         
 12591     # WAITING_ACK
 12592     @ATMT.state()
 12593     def WAITING_ACK(self):
 12594         pass
 12595 
 12596     @ATMT.receive_condition(WAITING_ACK)    
 12597     def received_ack(self,pkt):
 12598         if TFTP_ACK in pkt and pkt[TFTP_ACK].block == self.awaiting:
 12599             if self.server_tid is None:
 12600                 self.server_tid = pkt[UDP].sport
 12601                 self.l3[UDP].dport = self.server_tid
 12602             raise self.SEND_DATA()
 12603 
 12604     @ATMT.receive_condition(WAITING_ACK)
 12605     def received_error(self, pkt):
 12606         if TFTP_ERROR in pkt:
 12607             raise self.ERROR(pkt)
 12608 
 12609     @ATMT.timeout(WAITING_ACK, 3)
 12610     def timeout_waiting(self):
 12611         raise self.WAITING_ACK()
 12612     @ATMT.action(timeout_waiting)
 12613     def retransmit_last_packet(self):
 12614         self.send(self.last_packet)
 12615     
 12616     # SEND_DATA
 12617     @ATMT.state()
 12618     def SEND_DATA(self):
 12619         self.awaiting += 1
 12620         self.last_packet = self.l3/TFTP_DATA(block=self.awaiting)/self.data.pop(0)
 12621         self.send(self.last_packet)
 12622         if self.data:
 12623             raise self.WAITING_ACK()
 12624         raise self.END()
 12625     
 12626 
 12627     # ERROR
 12628     @ATMT.state(error=1)
 12629     def ERROR(self,pkt):
 12630         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12631         return pkt[TFTP_ERROR].summary()
 12632 
 12633     # END
 12634     @ATMT.state(final=1)
 12635     def END(self):
 12636         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12637 
 12638 
 12639 class TFTP_WRQ_server(Automaton):
 12640 
 12641     def parse_args(self, ip=None, sport=None, *args, **kargs):
 12642         Automaton.parse_args(self, *args, **kargs)
 12643         self.ip = ip
 12644         self.sport = sport
 12645 
 12646     def master_filter(self, pkt):
 12647         return TFTP in pkt and (not self.ip or pkt[IP].dst == self.ip)
 12648 
 12649     @ATMT.state(initial=1)
 12650     def BEGIN(self):
 12651         self.blksize=512
 12652         self.blk=1
 12653         self.filedata=""
 12654         self.my_tid = self.sport or random.randint(10000,65500)
 12655         bind_bottom_up(UDP, TFTP, dport=self.my_tid)
 12656 
 12657     @ATMT.receive_condition(BEGIN)
 12658     def receive_WRQ(self,pkt):
 12659         if TFTP_WRQ in pkt:
 12660             raise self.WAIT_DATA().action_parameters(pkt)
 12661         
 12662     @ATMT.action(receive_WRQ)
 12663     def ack_WRQ(self, pkt):
 12664         ip = pkt[IP]
 12665         self.ip = ip.dst
 12666         self.dst = ip.src
 12667         self.filename = pkt[TFTP_WRQ].filename
 12668         options = pkt[TFTP_Options]
 12669         self.l3 = IP(src=ip.dst, dst=ip.src)/UDP(sport=self.my_tid, dport=pkt.sport)/TFTP()
 12670         if options is None:
 12671             self.last_packet = self.l3/TFTP_ACK(block=0)
 12672             self.send(self.last_packet)
 12673         else:
 12674             opt = [x for x in options.options if x.oname.upper() == "BLKSIZE"]
 12675             if opt:
 12676                 self.blksize = int(opt[0].value)
 12677                 self.debug(2,"Negotiated new blksize at %i" % self.blksize)
 12678             self.last_packet = self.l3/TFTP_OACK()/TFTP_Options(options=opt)
 12679             self.send(self.last_packet)
 12680 
 12681     @ATMT.state()
 12682     def WAIT_DATA(self):
 12683         pass
 12684 
 12685     @ATMT.timeout(WAIT_DATA, 1)
 12686     def resend_ack(self):
 12687         self.send(self.last_packet)
 12688         raise self.WAIT_DATA()
 12689         
 12690     @ATMT.receive_condition(WAIT_DATA)
 12691     def receive_data(self, pkt):
 12692         if TFTP_DATA in pkt:
 12693             data = pkt[TFTP_DATA]
 12694             if data.block == self.blk:
 12695                 raise self.DATA(data)
 12696 
 12697     @ATMT.action(receive_data)
 12698     def ack_data(self):
 12699         self.last_packet = self.l3/TFTP_ACK(block = self.blk)
 12700         self.send(self.last_packet)
 12701 
 12702     @ATMT.state()
 12703     def DATA(self, data):
 12704         self.filedata += data.load
 12705         if len(data.load) < self.blksize:
 12706             raise self.END()
 12707         self.blk += 1
 12708         raise self.WAIT_DATA()
 12709 
 12710     @ATMT.state(final=1)
 12711     def END(self):
 12712         return self.filename,self.filedata
 12713         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12714         
 12715 
 12716 class TFTP_RRQ_server(Automaton):
 12717     def parse_args(self, store=None, joker=None, dir=None, ip=None, sport=None, serve_one=False, **kargs):
 12718         Automaton.parse_args(self,**kargs)
 12719         if store is None:
 12720             store = {}
 12721         if dir is not None:
 12722             self.dir = os.path.join(os.path.abspath(dir),"")
 12723         else:
 12724             self.dir = None
 12725         self.store = store
 12726         self.joker = joker
 12727         self.ip = ip
 12728         self.sport = sport
 12729         self.serve_one = serve_one
 12730         self.my_tid = self.sport or random.randint(10000,65500)
 12731         bind_bottom_up(UDP, TFTP, dport=self.my_tid)
 12732         
 12733     def master_filter(self, pkt):
 12734         return TFTP in pkt and (not self.ip or pkt[IP].dst == self.ip)
 12735 
 12736     @ATMT.state(initial=1)
 12737     def WAIT_RRQ(self):
 12738         self.blksize=512
 12739         self.blk=0
 12740 
 12741     @ATMT.receive_condition(WAIT_RRQ)
 12742     def receive_rrq(self, pkt):
 12743         if TFTP_RRQ in pkt:
 12744             raise self.RECEIVED_RRQ(pkt)
 12745 
 12746 
 12747     @ATMT.state()
 12748     def RECEIVED_RRQ(self, pkt):
 12749         ip = pkt[IP]
 12750         options = pkt[TFTP_Options]
 12751         self.l3 = IP(src=ip.dst, dst=ip.src)/UDP(sport=self.my_tid, dport=ip.sport)/TFTP()
 12752         self.filename = pkt[TFTP_RRQ].filename
 12753         self.blk=1
 12754         self.data = None
 12755         if self.filename in self.store:
 12756             self.data = self.store[self.filename]
 12757         elif self.dir is not None:
 12758             fn = os.path.abspath(os.path.join(self.dir, self.filename))
 12759             if fn.startswith(self.dir): # Check we're still in the server's directory
 12760                 try:
 12761                     self.data=open(fn).read()
 12762                 except IOError:
 12763                     pass
 12764         if self.data is None:
 12765             self.data = self.joker
 12766 
 12767         if options:
 12768             opt = [x for x in options.options if x.oname.upper() == "BLKSIZE"]
 12769             if opt:
 12770                 self.blksize = int(opt[0].value)
 12771                 self.debug(2,"Negotiated new blksize at %i" % self.blksize)
 12772             self.last_packet = self.l3/TFTP_OACK()/TFTP_Options(options=opt)
 12773             self.send(self.last_packet)
 12774                 
 12775 
 12776             
 12777 
 12778     @ATMT.condition(RECEIVED_RRQ)
 12779     def file_in_store(self):
 12780         if self.data is not None:
 12781             self.blknb = len(self.data)/self.blksize+1
 12782             raise self.SEND_FILE()
 12783 
 12784     @ATMT.condition(RECEIVED_RRQ)
 12785     def file_not_found(self):
 12786         if self.data is None:
 12787             raise self.WAIT_RRQ()
 12788     @ATMT.action(file_not_found)
 12789     def send_error(self):
 12790         self.send(self.l3/TFTP_ERROR(errorcode=1, errormsg=TFTP_Error_Codes[1]))
 12791 
 12792     @ATMT.state()
 12793     def SEND_FILE(self):
 12794         self.send(self.l3/TFTP_DATA(block=self.blk)/self.data[(self.blk-1)*self.blksize:self.blk*self.blksize])
 12795         
 12796     @ATMT.timeout(SEND_FILE, 3)
 12797     def timeout_waiting_ack(self):
 12798         raise self.SEND_FILE()
 12799             
 12800     @ATMT.receive_condition(SEND_FILE)
 12801     def received_ack(self, pkt):
 12802         if TFTP_ACK in pkt and pkt[TFTP_ACK].block == self.blk:
 12803             raise self.RECEIVED_ACK()
 12804     @ATMT.state()
 12805     def RECEIVED_ACK(self):
 12806         self.blk += 1
 12807 
 12808     @ATMT.condition(RECEIVED_ACK)
 12809     def no_more_data(self):
 12810         if self.blk > self.blknb:
 12811             if self.serve_one:
 12812                 raise self.END()
 12813             raise self.WAIT_RRQ()
 12814     @ATMT.condition(RECEIVED_ACK, prio=2)
 12815     def data_remaining(self):
 12816         raise self.SEND_FILE()
 12817 
 12818     @ATMT.state(final=1)
 12819     def END(self):
 12820         split_bottom_up(UDP, TFTP, dport=self.my_tid)
 12821     
 12822 
 12823         
 12824 
 12825 ########################
 12826 ## Answering machines ##
 12827 ########################
 12828 
 12829 class ReferenceAM(type):
 12830     def __new__(cls, name, bases, dct):
 12831         o = super(ReferenceAM, cls).__new__(cls, name, bases, dct)
 12832         if o.function_name:
 12833             globals()[o.function_name] = lambda o=o,*args,**kargs: o(*args,**kargs)()
 12834         return o
 12835 
 12836 
 12837 class AnsweringMachine(object):
 12838     __metaclass__ = ReferenceAM
 12839     function_name = ""
 12840     filter = None
 12841     sniff_options = { "store":0 }
 12842     sniff_options_list =