Home | History | Annotate | Download | only in scapy
      1 ## This file is part of Scapy
      2 ## See http://www.secdev.org/projects/scapy for more informations
      3 ## Copyright (C) Philippe Biondi <phil (at] secdev.org>
      4 ## This program is published under a GPLv2 license
      5 
      6 """
      7 Fields: basic data structures that make up parts of packets.
      8 """
      9 
     10 from __future__ import absolute_import
     11 import struct,copy,socket,collections
     12 from scapy.config import conf
     13 from scapy.dadict import DADict
     14 from scapy.volatile import *
     15 from scapy.data import *
     16 from scapy.compat import *
     17 from scapy.utils import *
     18 from scapy.base_classes import BasePacket, Gen, Net, Field_metaclass
     19 from scapy.error import warning
     20 import scapy.modules.six as six
     21 from scapy.modules.six.moves import range
     22 
     23 
     24 ############
     25 ## Fields ##
     26 ############
     27 
     28 class Field(six.with_metaclass(Field_metaclass, object)):
     29     """For more informations on how this work, please refer to
     30        http://www.secdev.org/projects/scapy/files/scapydoc.pdf
     31        chapter ``Adding a New Field''"""
     32     __slots__ = ["name", "fmt", "default", "sz", "owners"]
     33     islist = 0
     34     ismutable = False
     35     holds_packets = 0
     36     def __init__(self, name, default, fmt="H"):
     37         self.name = name
     38         if fmt[0] in "@=<>!":
     39             self.fmt = fmt
     40         else:
     41             self.fmt = "!"+fmt
     42         self.default = self.any2i(None,default)
     43         self.sz = struct.calcsize(self.fmt)
     44         self.owners = []
     45 
     46     def register_owner(self, cls):
     47         self.owners.append(cls)
     48 
     49     def i2len(self, pkt, x):
     50         """Convert internal value to a length usable by a FieldLenField"""
     51         return self.sz
     52     def i2count(self, pkt, x):
     53         """Convert internal value to a number of elements usable by a FieldLenField.
     54         Always 1 except for list fields"""
     55         return 1
     56     def h2i(self, pkt, x):
     57         """Convert human value to internal value"""
     58         return x
     59     def i2h(self, pkt, x):
     60         """Convert internal value to human value"""
     61         return x
     62     def m2i(self, pkt, x):
     63         """Convert machine value to internal value"""
     64         return x
     65     def i2m(self, pkt, x):
     66         """Convert internal value to machine value"""
     67         if x is None:
     68             x = 0
     69         elif isinstance(x, str):
     70             return raw(x)
     71         return x
     72     def any2i(self, pkt, x):
     73         """Try to understand the most input values possible and make an internal value from them"""
     74         return self.h2i(pkt, x)
     75     def i2repr(self, pkt, x):
     76         """Convert internal value to a nice representation"""
     77         return repr(self.i2h(pkt,x))
     78     def addfield(self, pkt, s, val):
     79         """Add an internal value  to a string"""
     80         return s+struct.pack(self.fmt, self.i2m(pkt,val))
     81     def getfield(self, pkt, s):
     82         """Extract an internal value from a string"""
     83         return  s[self.sz:], self.m2i(pkt, struct.unpack(self.fmt, s[:self.sz])[0])
     84     def do_copy(self, x):
     85         if hasattr(x, "copy"):
     86             return x.copy()
     87         if isinstance(x, list):
     88             x = x[:]
     89             for i in range(len(x)):
     90                 if isinstance(x[i], BasePacket):
     91                     x[i] = x[i].copy()
     92         return x
     93     def __repr__(self):
     94         return "<Field (%s).%s>" % (",".join(x.__name__ for x in self.owners),self.name)
     95     def copy(self):
     96         return copy.deepcopy(self)
     97     def randval(self):
     98         """Return a volatile object whose value is both random and suitable for this field"""
     99         fmtt = self.fmt[-1]
    100         if fmtt in "BHIQ":
    101             return {"B":RandByte,"H":RandShort,"I":RandInt, "Q":RandLong}[fmtt]()
    102         elif fmtt == "s":
    103             if self.fmt[0] in "0123456789":
    104                 l = int(self.fmt[:-1])
    105             else:
    106                 l = int(self.fmt[1:-1])
    107             return RandBin(l)
    108         else:
    109             warning("no random class for [%s] (fmt=%s).", self.name, self.fmt)
    110 
    111 
    112 
    113 
    114 class Emph(object):
    115     __slots__ = ["fld"]
    116     def __init__(self, fld):
    117         self.fld = fld
    118     def __getattr__(self, attr):
    119         return getattr(self.fld,attr)
    120     def __hash__(self):
    121         return hash(self.fld)
    122     def __eq__(self, other):
    123         return self.fld == other
    124 
    125 
    126 class ActionField(object):
    127     __slots__ = ["_fld", "_action_method", "_privdata"]
    128     def __init__(self, fld, action_method, **kargs):
    129         self._fld = fld
    130         self._action_method = action_method
    131         self._privdata = kargs
    132     def any2i(self, pkt, val):
    133         getattr(pkt, self._action_method)(val, self._fld, **self._privdata)
    134         return getattr(self._fld, "any2i")(pkt, val)
    135     def __getattr__(self, attr):
    136         return getattr(self._fld,attr)
    137 
    138 
    139 class ConditionalField(object):
    140     __slots__ = ["fld", "cond"]
    141     def __init__(self, fld, cond):
    142         self.fld = fld
    143         self.cond = cond
    144     def _evalcond(self,pkt):
    145         return self.cond(pkt)
    146 
    147     def getfield(self, pkt, s):
    148         if self._evalcond(pkt):
    149             return self.fld.getfield(pkt,s)
    150         else:
    151             return s,None
    152 
    153     def addfield(self, pkt, s, val):
    154         if self._evalcond(pkt):
    155             return self.fld.addfield(pkt,s,val)
    156         else:
    157             return s
    158     def __getattr__(self, attr):
    159         return getattr(self.fld,attr)
    160 
    161 
    162 class PadField(object):
    163     """Add bytes after the proxified field so that it ends at the specified
    164        alignment from its beginning"""
    165     __slots__ = ["_fld", "_align", "_padwith"]
    166     def __init__(self, fld, align, padwith=None):
    167         self._fld = fld
    168         self._align = align
    169         self._padwith = padwith or b""
    170 
    171     def padlen(self, flen):
    172         return -flen%self._align
    173 
    174     def getfield(self, pkt, s):
    175         remain,val = self._fld.getfield(pkt,s)
    176         padlen = self.padlen(len(s)-len(remain))
    177         return remain[padlen:], val
    178 
    179     def addfield(self, pkt, s, val):
    180         sval = self._fld.addfield(pkt, b"", val)
    181         return s+sval+struct.pack("%is" % (self.padlen(len(sval))), self._padwith)
    182 
    183     def __getattr__(self, attr):
    184         return getattr(self._fld,attr)
    185 
    186 
    187 class DestField(Field):
    188     __slots__ = ["defaultdst"]
    189     # Each subclass must have its own bindings attribute
    190     # bindings = {}
    191     def __init__(self, name, default):
    192         self.defaultdst = default
    193     def dst_from_pkt(self, pkt):
    194         for addr, condition in self.bindings.get(pkt.payload.__class__, []):
    195             try:
    196                 if all(pkt.payload.getfieldval(field) == value
    197                        for field, value in six.iteritems(condition)):
    198                     return addr
    199             except AttributeError:
    200                 pass
    201         return self.defaultdst
    202     @classmethod
    203     def bind_addr(cls, layer, addr, **condition):
    204         cls.bindings.setdefault(layer, []).append((addr, condition))
    205 
    206 
    207 class MACField(Field):
    208     def __init__(self, name, default):
    209         Field.__init__(self, name, default, "6s")
    210     def i2m(self, pkt, x):
    211         if x is None:
    212             return b"\0\0\0\0\0\0"
    213         return mac2str(x)
    214     def m2i(self, pkt, x):
    215         return str2mac(x)
    216     def any2i(self, pkt, x):
    217         if isinstance(x, bytes) and len(x) == 6:
    218             x = self.m2i(pkt, x)
    219         return x
    220     def i2repr(self, pkt, x):
    221         x = self.i2h(pkt, x)
    222         if self in conf.resolve:
    223             x = conf.manufdb._resolve_MAC(x)
    224         return x
    225     def randval(self):
    226         return RandMAC()
    227 
    228 
    229 class IPField(Field):
    230     slots = []
    231     def __init__(self, name, default):
    232         Field.__init__(self, name, default, "4s")
    233     def h2i(self, pkt, x):
    234         if isinstance(x, bytes):
    235             x = plain_str(x)
    236         if isinstance(x, str):
    237             try:
    238                 inet_aton(x)
    239             except socket.error:
    240                 x = Net(x)
    241         elif isinstance(x, list):
    242             x = [self.h2i(pkt, n) for n in x]
    243         return x
    244     def resolve(self, x):
    245         if self in conf.resolve:
    246             try:
    247                 ret = socket.gethostbyaddr(x)[0]
    248             except:
    249                 pass
    250             else:
    251                 if ret:
    252                     return ret
    253         return x
    254     def i2m(self, pkt, x):
    255         return inet_aton(x)
    256     def m2i(self, pkt, x):
    257         return inet_ntoa(x)
    258     def any2i(self, pkt, x):
    259         return self.h2i(pkt,x)
    260     def i2repr(self, pkt, x):
    261         return self.resolve(self.i2h(pkt, x))
    262     def randval(self):
    263         return RandIP()
    264 
    265 class SourceIPField(IPField):
    266     __slots__ = ["dstname"]
    267     def __init__(self, name, dstname):
    268         IPField.__init__(self, name, None)
    269         self.dstname = dstname
    270     def __findaddr(self, pkt):
    271         if conf.route is None:
    272             # unused import, only to initialize conf.route
    273             import scapy.route
    274         dst = ("0.0.0.0" if self.dstname is None
    275                else getattr(pkt, self.dstname))
    276         if isinstance(dst, (Gen, list)):
    277             r = {conf.route.route(daddr) for daddr in dst}
    278             if len(r) > 1:
    279                 warning("More than one possible route for %r" % (dst,))
    280             return min(r)[1]
    281         return conf.route.route(dst)[1]
    282     def i2m(self, pkt, x):
    283         if x is None:
    284             x = self.__findaddr(pkt)
    285         return IPField.i2m(self, pkt, x)
    286     def i2h(self, pkt, x):
    287         if x is None:
    288             x = self.__findaddr(pkt)
    289         return IPField.i2h(self, pkt, x)
    290 
    291 
    292 
    293 
    294 class ByteField(Field):
    295     def __init__(self, name, default):
    296         Field.__init__(self, name, default, "B")
    297 
    298 class XByteField(ByteField):
    299     def i2repr(self, pkt, x):
    300         return lhex(self.i2h(pkt, x))
    301 
    302 class OByteField(ByteField):
    303     def i2repr(self, pkt, x):
    304         return "%03o"%self.i2h(pkt, x)
    305 
    306 class X3BytesField(XByteField):
    307     def __init__(self, name, default):
    308         Field.__init__(self, name, default, "!I")
    309     def addfield(self, pkt, s, val):
    310         return s+struct.pack(self.fmt, self.i2m(pkt,val))[1:4]
    311     def getfield(self, pkt, s):
    312         return  s[3:], self.m2i(pkt, struct.unpack(self.fmt, b"\x00"+s[:3])[0])
    313 
    314 class ThreeBytesField(X3BytesField, ByteField):
    315     def i2repr(self, pkt, x):
    316         return ByteField.i2repr(self, pkt, x)
    317 
    318 class SignedByteField(Field):
    319     def __init__(self, name, default):
    320         Field.__init__(self, name, default, "b")
    321 
    322 class ShortField(Field):
    323     def __init__(self, name, default):
    324         Field.__init__(self, name, default, "H")
    325 
    326 class SignedShortField(Field):
    327     def __init__(self, name, default):
    328         Field.__init__(self, name, default, "h")
    329 
    330 class LEShortField(Field):
    331     def __init__(self, name, default):
    332         Field.__init__(self, name, default, "<H")
    333 
    334 class XShortField(ShortField):
    335     def i2repr(self, pkt, x):
    336         return lhex(self.i2h(pkt, x))
    337 
    338 
    339 class IntField(Field):
    340     def __init__(self, name, default):
    341         Field.__init__(self, name, default, "I")
    342 
    343 class SignedIntField(Field):
    344     def __init__(self, name, default):
    345         Field.__init__(self, name, default, "i")
    346     def randval(self):
    347         return RandSInt()
    348 
    349 class LEIntField(Field):
    350     def __init__(self, name, default):
    351         Field.__init__(self, name, default, "<I")
    352 
    353 class LESignedIntField(Field):
    354     def __init__(self, name, default):
    355         Field.__init__(self, name, default, "<i")
    356     def randval(self):
    357         return RandSInt()
    358 
    359 class XIntField(IntField):
    360     def i2repr(self, pkt, x):
    361         return lhex(self.i2h(pkt, x))
    362 
    363 
    364 class LongField(Field):
    365     def __init__(self, name, default):
    366         Field.__init__(self, name, default, "Q")
    367 
    368 class LELongField(LongField):
    369     def __init__(self, name, default):
    370         Field.__init__(self, name, default, "<Q")
    371 
    372 class XLongField(LongField):
    373     def i2repr(self, pkt, x):
    374         return lhex(self.i2h(pkt, x))
    375 
    376 class IEEEFloatField(Field):
    377     def __init__(self, name, default):
    378         Field.__init__(self, name, default, "f")
    379 
    380 class IEEEDoubleField(Field):
    381     def __init__(self, name, default):
    382         Field.__init__(self, name, default, "d")
    383 
    384 
    385 class StrField(Field):
    386     __slots__ = ["remain"]
    387     def __init__(self, name, default, fmt="H", remain=0):
    388         Field.__init__(self,name,default,fmt)
    389         self.remain = remain
    390     def i2len(self, pkt, i):
    391         return len(i)
    392     def any2i(self, pkt, x):
    393         if isinstance(x, str if six.PY3 else unicode):
    394             x = raw(x)
    395         return super(StrField, self).any2i(pkt, x)
    396     def i2repr(self, pkt, x):
    397         val = super(StrField, self).i2repr(pkt, x)
    398         if val[:2] in ['b"', "b'"]:
    399             return val[1:]
    400         return val
    401     def i2m(self, pkt, x):
    402         if x is None:
    403             return b""
    404         if not isinstance(x, bytes):
    405             return raw(x)
    406         return x
    407     def addfield(self, pkt, s, val):
    408         return s + self.i2m(pkt, val)
    409     def getfield(self, pkt, s):
    410         if self.remain == 0:
    411             return b"", self.m2i(pkt, s)
    412         else:
    413             return s[-self.remain:],self.m2i(pkt, s[:-self.remain])
    414     def randval(self):
    415         return RandBin(RandNum(0,1200))
    416 
    417 class PacketField(StrField):
    418     __slots__ = ["cls"]
    419     holds_packets = 1
    420     def __init__(self, name, default, cls, remain=0):
    421         StrField.__init__(self, name, default, remain=remain)
    422         self.cls = cls
    423     def i2m(self, pkt, i):
    424         if i is None:
    425             return b""
    426         return raw(i)
    427     def m2i(self, pkt, m):
    428         return self.cls(m)
    429     def getfield(self, pkt, s):
    430         i = self.m2i(pkt, s)
    431         remain = b""
    432         if conf.padding_layer in i:
    433             r = i[conf.padding_layer]
    434             del(r.underlayer.payload)
    435             remain = r.load
    436         return remain,i
    437 
    438 class PacketLenField(PacketField):
    439     __slots__ = ["length_from"]
    440     def __init__(self, name, default, cls, length_from=None):
    441         PacketField.__init__(self, name, default, cls)
    442         self.length_from = length_from
    443     def getfield(self, pkt, s):
    444         l = self.length_from(pkt)
    445         try:
    446             i = self.m2i(pkt, s[:l])
    447         except Exception:
    448             if conf.debug_dissector:
    449                 raise
    450             i = conf.raw_layer(load=s[:l])
    451         return s[l:],i
    452 
    453 
    454 class PacketListField(PacketField):
    455     """ PacketListField represents a series of Packet instances that might occur right in the middle of another Packet
    456     field list.
    457     This field type may also be used to indicate that a series of Packet instances have a sibling semantic instead of
    458     a parent/child relationship (i.e. a stack of layers).
    459     """
    460     __slots__ = ["count_from", "length_from", "next_cls_cb"]
    461     islist = 1
    462     def __init__(self, name, default, cls=None, count_from=None, length_from=None, next_cls_cb=None):
    463         """ The number of Packet instances that are dissected by this field can be parametrized using one of three
    464         different mechanisms/parameters:
    465             * count_from: a callback that returns the number of Packet instances to dissect. The callback prototype is:
    466             count_from(pkt:Packet) -> int
    467             * length_from: a callback that returns the number of bytes that must be dissected by this field. The
    468             callback prototype is:
    469             length_from(pkt:Packet) -> int
    470             * next_cls_cb: a callback that enables a Scapy developer to dynamically discover if another Packet instance
    471             should be dissected or not. See below for this callback prototype.
    472 
    473         The bytes that are not consumed during the dissection of this field are passed to the next field of the current
    474         packet.
    475 
    476         For the serialization of such a field, the list of Packets that are contained in a PacketListField can be
    477         heterogeneous and is unrestricted.
    478 
    479         The type of the Packet instances that are dissected with this field is specified or discovered using one of the
    480         following mechanism:
    481             * the cls parameter may contain a callable that returns an instance of the dissected Packet. This
    482                 may either be a reference of a Packet subclass (e.g. DNSRROPT in layers/dns.py) to generate an
    483                 homogeneous PacketListField or a function deciding the type of the Packet instance
    484                 (e.g. _CDPGuessAddrRecord in contrib/cdp.py)
    485             * the cls parameter may contain a class object with a defined "dispatch_hook" classmethod. That
    486                 method must return a Packet instance. The dispatch_hook callmethod must implement the following prototype:
    487                 dispatch_hook(cls, _pkt:Optional[Packet], *args, **kargs) -> Packet_metaclass
    488                 The _pkt parameter may contain a reference to the packet instance containing the PacketListField that is
    489                 being dissected.
    490             * the next_cls_cb parameter may contain a callable whose prototype is:
    491                 cbk(pkt:Packet, lst:List[Packet], cur:Optional[Packet], remain:str) -> Optional[Packet_metaclass]
    492                 The pkt argument contains a reference to the Packet instance containing the PacketListField that is
    493                 being dissected. The lst argument is the list of all Packet instances that were previously parsed during
    494                 the current PacketListField dissection, save for the very last Packet instance. The cur argument
    495                 contains a reference to that very last parsed Packet instance. The remain argument contains the bytes
    496                 that may still be consumed by the current PacketListField dissection operation. This callback returns
    497                 either the type of the next Packet to dissect or None to indicate that no more Packet are to be
    498                 dissected.
    499                 These four arguments allows a variety of dynamic discovery of the number of Packet to dissect and of the
    500                 type of each one of these Packets, including: type determination based on current Packet instances or
    501                 its underlayers, continuation based on the previously parsed Packet instances within that
    502                 PacketListField, continuation based on a look-ahead on the bytes to be dissected...
    503 
    504         The cls and next_cls_cb parameters are semantically exclusive, although one could specify both. If both are
    505         specified, cls is silently ignored. The same is true for count_from and next_cls_cb.
    506         length_from and next_cls_cb are compatible and the dissection will end, whichever of the two stop conditions
    507         comes first.
    508 
    509         @param name: the name of the field
    510         @param default: the default value of this field; generally an empty Python list
    511         @param cls: either a callable returning a Packet instance or a class object defining a dispatch_hook class
    512             method
    513         @param count_from: a callback returning the number of Packet instances to dissect
    514         @param length_from: a callback returning the number of bytes to dissect
    515         @param next_cls_cb: a callback returning either None or the type of the next Packet to dissect.
    516         """
    517         if default is None:
    518             default = []  # Create a new list for each instance
    519         PacketField.__init__(self, name, default, cls)
    520         self.count_from = count_from
    521         self.length_from = length_from
    522         self.next_cls_cb = next_cls_cb
    523 
    524     def any2i(self, pkt, x):
    525         if not isinstance(x, list):
    526             return [x]
    527         else:
    528             return x
    529     def i2count(self, pkt, val):
    530         if isinstance(val, list):
    531             return len(val)
    532         return 1
    533     def i2len(self, pkt, val):
    534         return sum( len(p) for p in val )
    535     def do_copy(self, x):
    536         if x is None:
    537             return None
    538         else:
    539             return [p if isinstance(p, six.string_types) else p.copy() for p in x]
    540     def getfield(self, pkt, s):
    541         c = l = cls = None
    542         if self.length_from is not None:
    543             l = self.length_from(pkt)
    544         elif self.count_from is not None:
    545             c = self.count_from(pkt)
    546         if self.next_cls_cb is not None:
    547             cls = self.next_cls_cb(pkt, [], None, s)
    548             c = 1
    549 
    550         lst = []
    551         ret = b""
    552         remain = s
    553         if l is not None:
    554             remain,ret = s[:l],s[l:]
    555         while remain:
    556             if c is not None:
    557                 if c <= 0:
    558                     break
    559                 c -= 1
    560             try:
    561                 if cls is not None:
    562                     p = cls(remain)
    563                 else:
    564                     p = self.m2i(pkt, remain)
    565             except Exception:
    566                 if conf.debug_dissector:
    567                     raise
    568                 p = conf.raw_layer(load=remain)
    569                 remain = b""
    570             else:
    571                 if conf.padding_layer in p:
    572                     pad = p[conf.padding_layer]
    573                     remain = pad.load
    574                     del(pad.underlayer.payload)
    575                     if self.next_cls_cb is not None:
    576                         cls = self.next_cls_cb(pkt, lst, p, remain)
    577                         if cls is not None:
    578                             c += 1
    579                 else:
    580                     remain = b""
    581             lst.append(p)
    582         return remain+ret,lst
    583     def addfield(self, pkt, s, val):
    584         return s + b"".join(raw(v) for v in val)
    585 
    586 
    587 class StrFixedLenField(StrField):
    588     __slots__ = ["length_from"]
    589     def __init__(self, name, default, length=None, length_from=None):
    590         StrField.__init__(self, name, default)
    591         self.length_from  = length_from
    592         if length is not None:
    593             self.length_from = lambda pkt,length=length: length
    594     def i2repr(self, pkt, v):
    595         if isinstance(v, bytes):
    596             v = v.rstrip(b"\0")
    597         return super(StrFixedLenField, self).i2repr(pkt, v)
    598     def getfield(self, pkt, s):
    599         l = self.length_from(pkt)
    600         return s[l:], self.m2i(pkt,s[:l])
    601     def addfield(self, pkt, s, val):
    602         l = self.length_from(pkt)
    603         return s+struct.pack("%is"%l,self.i2m(pkt, val))
    604     def randval(self):
    605         try:
    606             l = self.length_from(None)
    607         except:
    608             l = RandNum(0,200)
    609         return RandBin(l)
    610 
    611 class StrFixedLenEnumField(StrFixedLenField):
    612     __slots__ = ["enum"]
    613     def __init__(self, name, default, length=None, enum=None, length_from=None):
    614         StrFixedLenField.__init__(self, name, default, length=length, length_from=length_from)
    615         self.enum = enum
    616     def i2repr(self, pkt, v):
    617         r = v.rstrip("\0")
    618         rr = repr(r)
    619         if v in self.enum:
    620             rr = "%s (%s)" % (rr, self.enum[v])
    621         elif r in self.enum:
    622             rr = "%s (%s)" % (rr, self.enum[r])
    623         return rr
    624 
    625 class NetBIOSNameField(StrFixedLenField):
    626     def __init__(self, name, default, length=31):
    627         StrFixedLenField.__init__(self, name, default, length)
    628     def i2m(self, pkt, x):
    629         l = self.length_from(pkt)//2
    630         if x is None:
    631             x = b""
    632         x += b" "*(l)
    633         x = x[:l]
    634         x = b"".join(chb(0x41 + orb(b)>>4) + chb(0x41 + orb(b)&0xf) for b in x)
    635         x = b" "+x
    636         return x
    637     def m2i(self, pkt, x):
    638         x = x.strip(b"\x00").strip(b" ")
    639         return b"".join(map(lambda x,y: chb((((orb(x)-1)&0xf)<<4)+((orb(y)-1)&0xf)), x[::2],x[1::2]))
    640 
    641 class StrLenField(StrField):
    642     __slots__ = ["length_from"]
    643     def __init__(self, name, default, fld=None, length_from=None):
    644         StrField.__init__(self, name, default)
    645         self.length_from = length_from
    646     def getfield(self, pkt, s):
    647         l = self.length_from(pkt)
    648         return s[l:], self.m2i(pkt,s[:l])
    649 
    650 class XStrField(StrField):
    651     """
    652     StrField which value is printed as hexadecimal.
    653     """
    654 
    655     def i2repr(self, pkt, x):
    656         if x is None:
    657             return repr(x)
    658         return bytes_hex(x).decode()
    659 
    660 class XStrLenField(StrLenField):
    661     """
    662     StrLenField which value is printed as hexadecimal.
    663     """
    664 
    665     def i2repr(self, pkt, x):
    666         if not x:
    667             return repr(x)
    668         return bytes_hex(x[:self.length_from(pkt)]).decode()
    669 
    670 class XStrFixedLenField(StrFixedLenField):
    671     """
    672     StrFixedLenField which value is printed as hexadecimal.
    673     """
    674 
    675     def i2repr(self, pkt, x):
    676         if not x:
    677             return repr(x)
    678         return bytes_hex(x[:self.length_from(pkt)]).decode()
    679 
    680 class StrLenFieldUtf16(StrLenField):
    681     def h2i(self, pkt, x):
    682         return plain_str(x).encode('utf-16')[2:]
    683     def i2h(self, pkt, x):
    684         return x.decode('utf-16')
    685 
    686 class BoundStrLenField(StrLenField):
    687     __slots__ = ["minlen", "maxlen"]
    688     def __init__(self,name, default, minlen= 0, maxlen= 255, fld=None, length_from=None):
    689         StrLenField.__init__(self, name, default, fld, length_from)
    690         self.minlen = minlen
    691         self.maxlen = maxlen
    692 
    693     def randval(self):
    694         return RandBin(RandNum(self.minlen, self.maxlen))
    695 
    696 class FieldListField(Field):
    697     __slots__ = ["field", "count_from", "length_from"]
    698     islist = 1
    699     def __init__(self, name, default, field, length_from=None, count_from=None):
    700         if default is None:
    701             default = []  # Create a new list for each instance
    702         self.field = field
    703         Field.__init__(self, name, default)
    704         self.count_from = count_from
    705         self.length_from = length_from
    706 
    707     def i2count(self, pkt, val):
    708         if isinstance(val, list):
    709             return len(val)
    710         return 1
    711     def i2len(self, pkt, val):
    712         return int(sum(self.field.i2len(pkt,v) for v in val))
    713 
    714     def i2m(self, pkt, val):
    715         if val is None:
    716             val = []
    717         return val
    718     def any2i(self, pkt, x):
    719         if not isinstance(x, list):
    720             return [self.field.any2i(pkt, x)]
    721         else:
    722             return [self.field.any2i(pkt, e) for e in x]
    723     def i2repr(self, pkt, x):
    724         res = []
    725         for v in x:
    726             r = self.field.i2repr(pkt, v)
    727             res.append(r)
    728         return "[%s]" % ", ".join(res)
    729     def addfield(self, pkt, s, val):
    730         val = self.i2m(pkt, val)
    731         for v in val:
    732             s = self.field.addfield(pkt, s, v)
    733         return s
    734     def getfield(self, pkt, s):
    735         c = l = None
    736         if self.length_from is not None:
    737             l = self.length_from(pkt)
    738         elif self.count_from is not None:
    739             c = self.count_from(pkt)
    740 
    741         val = []
    742         ret = b""
    743         if l is not None:
    744             s,ret = s[:l],s[l:]
    745 
    746         while s:
    747             if c is not None:
    748                 if c <= 0:
    749                     break
    750                 c -= 1
    751             s,v = self.field.getfield(pkt, s)
    752             val.append(v)
    753         return s+ret, val
    754 
    755 class FieldLenField(Field):
    756     __slots__ = ["length_of", "count_of", "adjust"]
    757     def __init__(self, name, default,  length_of=None, fmt = "H", count_of=None, adjust=lambda pkt,x:x, fld=None):
    758         Field.__init__(self, name, default, fmt)
    759         self.length_of = length_of
    760         self.count_of = count_of
    761         self.adjust = adjust
    762         if fld is not None:
    763             #FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
    764             self.length_of = fld
    765     def i2m(self, pkt, x):
    766         if x is None:
    767             if self.length_of is not None:
    768                 fld,fval = pkt.getfield_and_val(self.length_of)
    769                 f = fld.i2len(pkt, fval)
    770             else:
    771                 fld,fval = pkt.getfield_and_val(self.count_of)
    772                 f = fld.i2count(pkt, fval)
    773             x = self.adjust(pkt,f)
    774         return x
    775 
    776 class StrNullField(StrField):
    777     def addfield(self, pkt, s, val):
    778         return s+self.i2m(pkt, val)+b"\x00"
    779     def getfield(self, pkt, s):
    780         l = s.find(b"\x00")
    781         if l < 0:
    782             #XXX \x00 not found
    783             return b"",s
    784         return s[l+1:],self.m2i(pkt, s[:l])
    785     def randval(self):
    786         return RandTermString(RandNum(0,1200),b"\x00")
    787 
    788 class StrStopField(StrField):
    789     __slots__ = ["stop", "additionnal"]
    790     def __init__(self, name, default, stop, additionnal=0):
    791         Field.__init__(self, name, default)
    792         self.stop = stop
    793         self.additionnal = additionnal
    794     def getfield(self, pkt, s):
    795         l = s.find(self.stop)
    796         if l < 0:
    797             return b"",s
    798 #            raise Scapy_Exception,"StrStopField: stop value [%s] not found" %stop
    799         l += len(self.stop)+self.additionnal
    800         return s[l:],s[:l]
    801     def randval(self):
    802         return RandTermString(RandNum(0,1200),self.stop)
    803 
    804 class LenField(Field):
    805     __slots__ = ["adjust"]
    806     def __init__(self, name, default, fmt="H", adjust=lambda x: x):
    807         Field.__init__(self, name, default, fmt)
    808         self.adjust = adjust
    809     def i2m(self, pkt, x):
    810         if x is None:
    811             x = self.adjust(len(pkt.payload))
    812         return x
    813 
    814 class BCDFloatField(Field):
    815     def i2m(self, pkt, x):
    816         return int(256*x)
    817     def m2i(self, pkt, x):
    818         return x/256.0
    819 
    820 class BitField(Field):
    821     __slots__ = ["rev", "size"]
    822     def __init__(self, name, default, size):
    823         Field.__init__(self, name, default)
    824         self.rev = size < 0
    825         self.size = abs(size)
    826     def reverse(self, val):
    827         if self.size == 16:
    828             # Replaces socket.ntohs (but work on both little/big endian)
    829             val = struct.unpack('>H',struct.pack('<H', int(val)))[0]
    830         elif self.size == 32:
    831             # Same here but for socket.ntohl
    832             val = struct.unpack('>I',struct.pack('<I', int(val)))[0]
    833         return val
    834 
    835     def addfield(self, pkt, s, val):
    836         val = self.i2m(pkt, val)
    837         if isinstance(s, tuple):
    838             s,bitsdone,v = s
    839         else:
    840             bitsdone = 0
    841             v = 0
    842         if self.rev:
    843             val = self.reverse(val)
    844         v <<= self.size
    845         v |= val & ((1<<self.size) - 1)
    846         bitsdone += self.size
    847         while bitsdone >= 8:
    848             bitsdone -= 8
    849             s = s+struct.pack("!B", v >> bitsdone)
    850             v &= (1<<bitsdone)-1
    851         if bitsdone:
    852             return s,bitsdone,v
    853         else:
    854             return s
    855     def getfield(self, pkt, s):
    856         if isinstance(s, tuple):
    857             s,bn = s
    858         else:
    859             bn = 0
    860         # we don't want to process all the string
    861         nb_bytes = (self.size+bn-1)//8 + 1
    862         w = s[:nb_bytes]
    863 
    864         # split the substring byte by byte
    865         _bytes = struct.unpack('!%dB' % nb_bytes , w)
    866 
    867         b = 0
    868         for c in range(nb_bytes):
    869             b |= int(_bytes[c]) << (nb_bytes-c-1)*8
    870 
    871         # get rid of high order bits
    872         b &= (1 << (nb_bytes*8-bn)) - 1
    873 
    874         # remove low order bits
    875         b = b >> (nb_bytes*8 - self.size - bn)
    876 
    877         if self.rev:
    878             b = self.reverse(b)
    879 
    880         bn += self.size
    881         s = s[bn//8:]
    882         bn = bn%8
    883         b = self.m2i(pkt, b)
    884         if bn:
    885             return (s,bn),b
    886         else:
    887             return s,b
    888     def randval(self):
    889         return RandNum(0,2**self.size-1)
    890     def i2len(self, pkt, x):
    891         return float(self.size)/8
    892 
    893 
    894 class BitFieldLenField(BitField):
    895     __slots__ = ["length_of", "count_of", "adjust"]
    896     def __init__(self, name, default, size, length_of=None, count_of=None, adjust=lambda pkt,x:x):
    897         BitField.__init__(self, name, default, size)
    898         self.length_of = length_of
    899         self.count_of = count_of
    900         self.adjust = adjust
    901     def i2m(self, pkt, x):
    902         return (FieldLenField.i2m.__func__ if six.PY2 else FieldLenField.i2m)(self, pkt, x)
    903 
    904 
    905 class XBitField(BitField):
    906     def i2repr(self, pkt, x):
    907         return lhex(self.i2h(pkt,x))
    908 
    909 
    910 class _EnumField(Field):
    911     def __init__(self, name, default, enum, fmt = "H"):
    912         """ Initializes enum fields.
    913 
    914         @param name:    name of this field
    915         @param default: default value of this field
    916         @param enum:    either a dict or a tuple of two callables. Dict keys are
    917                         the internal values, while the dict values are the
    918                         user-friendly representations. If the tuple is provided,
    919                         the first callable receives the internal value as
    920                         parameter and returns the user-friendly representation
    921                         and the second callable does the converse. The first
    922                         callable may return None to default to a literal string
    923                         (repr()) representation.
    924         @param fmt:     struct.pack format used to parse and serialize the
    925                         internal value from and to machine representation.
    926         """
    927         if isinstance(enum, tuple):
    928             self.i2s_cb = enum[0]
    929             self.s2i_cb = enum[1]
    930             self.i2s = None
    931             self.s2i = None
    932         else:
    933             i2s = self.i2s = {}
    934             s2i = self.s2i = {}
    935             self.i2s_cb = None
    936             self.s2i_cb = None
    937             if isinstance(enum, list):
    938                 keys = range(len(enum))
    939             elif isinstance(enum, DADict):
    940                 keys = enum.iterkeys()
    941             else:
    942                 keys = list(enum)
    943             if any(isinstance(x, str) for x in keys):
    944                 i2s, s2i = s2i, i2s
    945             for k in keys:
    946                 i2s[k] = enum[k]
    947                 s2i[enum[k]] = k
    948         Field.__init__(self, name, default, fmt)
    949 
    950     def any2i_one(self, pkt, x):
    951         if isinstance(x, str):
    952             try:
    953                 x = self.s2i[x]
    954             except TypeError:
    955                 x = self.s2i_cb(x)
    956         return x
    957 
    958     def i2repr_one(self, pkt, x):
    959         if self not in conf.noenum and not isinstance(x,VolatileValue):
    960             try:
    961                 return self.i2s[x]
    962             except KeyError:
    963                 pass
    964             except TypeError:
    965                 ret = self.i2s_cb(x)
    966                 if ret is not None:
    967                     return ret
    968         return repr(x)
    969 
    970     def any2i(self, pkt, x):
    971         if isinstance(x, list):
    972             return [self.any2i_one(pkt, z) for z in x]
    973         else:
    974             return self.any2i_one(pkt,x)
    975 
    976     def i2repr(self, pkt, x):
    977         if isinstance(x, list):
    978             return [self.i2repr_one(pkt, z) for z in x]
    979         else:
    980             return self.i2repr_one(pkt,x)
    981 
    982 class EnumField(_EnumField):
    983     __slots__ = ["i2s", "s2i", "s2i_cb", "i2s_cb"]
    984 
    985 class CharEnumField(EnumField):
    986     def __init__(self, name, default, enum, fmt = "1s"):
    987         EnumField.__init__(self, name, default, enum, fmt)
    988         if self.i2s is not None:
    989             k = list(self.i2s)
    990             if k and len(k[0]) != 1:
    991                 self.i2s,self.s2i = self.s2i,self.i2s
    992     def any2i_one(self, pkt, x):
    993         if len(x) != 1:
    994             if self.s2i is None:
    995                 x = self.s2i_cb(x)
    996             else:
    997                 x = self.s2i[x]
    998         return x
    999 
   1000 class BitEnumField(BitField, _EnumField):
   1001     __slots__ = EnumField.__slots__
   1002     def __init__(self, name, default, size, enum):
   1003         _EnumField.__init__(self, name, default, enum)
   1004         self.rev = size < 0
   1005         self.size = abs(size)
   1006     def any2i(self, pkt, x):
   1007         return _EnumField.any2i(self, pkt, x)
   1008     def i2repr(self, pkt, x):
   1009         return _EnumField.i2repr(self, pkt, x)
   1010 
   1011 class ShortEnumField(EnumField):
   1012     __slots__ = EnumField.__slots__
   1013     def __init__(self, name, default, enum):
   1014         EnumField.__init__(self, name, default, enum, "H")
   1015 
   1016 class LEShortEnumField(EnumField):
   1017     def __init__(self, name, default, enum):
   1018         EnumField.__init__(self, name, default, enum, "<H")
   1019 
   1020 class ByteEnumField(EnumField):
   1021     def __init__(self, name, default, enum):
   1022         EnumField.__init__(self, name, default, enum, "B")
   1023 
   1024 class IntEnumField(EnumField):
   1025     def __init__(self, name, default, enum):
   1026         EnumField.__init__(self, name, default, enum, "I")
   1027 
   1028 class SignedIntEnumField(EnumField):
   1029     def __init__(self, name, default, enum):
   1030         EnumField.__init__(self, name, default, enum, "i")
   1031     def randval(self):
   1032         return RandSInt()
   1033 
   1034 class LEIntEnumField(EnumField):
   1035     def __init__(self, name, default, enum):
   1036         EnumField.__init__(self, name, default, enum, "<I")
   1037 
   1038 class XShortEnumField(ShortEnumField):
   1039     def i2repr_one(self, pkt, x):
   1040         if self not in conf.noenum and not isinstance(x,VolatileValue):
   1041             try:
   1042                 return self.i2s[x]
   1043             except KeyError:
   1044                 pass
   1045             except TypeError:
   1046                 ret = self.i2s_cb(x)
   1047                 if ret is not None:
   1048                     return ret
   1049         return lhex(x)
   1050 
   1051 
   1052 class _MultiEnumField(_EnumField):
   1053     def __init__(self, name, default, enum, depends_on, fmt = "H"):
   1054 
   1055         self.depends_on = depends_on
   1056         self.i2s_multi = enum
   1057         self.s2i_multi = {}
   1058         self.s2i_all = {}
   1059         for m in enum:
   1060             self.s2i_multi[m] = s2i = {}
   1061             for k,v in six.iteritems(enum[m]):
   1062                 s2i[v] = k
   1063                 self.s2i_all[v] = k
   1064         Field.__init__(self, name, default, fmt)
   1065     def any2i_one(self, pkt, x):
   1066         if isinstance(x, str):
   1067             v = self.depends_on(pkt)
   1068             if v in self.s2i_multi:
   1069                 s2i = self.s2i_multi[v]
   1070                 if x in s2i:
   1071                     return s2i[x]
   1072             return self.s2i_all[x]
   1073         return x
   1074     def i2repr_one(self, pkt, x):
   1075         v = self.depends_on(pkt)
   1076         if v in self.i2s_multi:
   1077             return self.i2s_multi[v].get(x,x)
   1078         return x
   1079 
   1080 class MultiEnumField(_MultiEnumField, EnumField):
   1081     __slots__ = ["depends_on", "i2s_multi", "s2i_multi", "s2i_all"]
   1082 
   1083 class BitMultiEnumField(BitField, _MultiEnumField):
   1084     __slots__ = EnumField.__slots__ + MultiEnumField.__slots__
   1085     def __init__(self, name, default, size, enum, depends_on):
   1086         _MultiEnumField.__init__(self, name, default, enum, depends_on)
   1087         self.rev = size < 0
   1088         self.size = abs(size)
   1089     def any2i(self, pkt, x):
   1090         return _MultiEnumField.any2i(self, pkt, x)
   1091     def i2repr(self, pkt, x):
   1092         return _MultiEnumField.i2repr(self, pkt, x)
   1093 
   1094 
   1095 class ByteEnumKeysField(ByteEnumField):
   1096     """ByteEnumField that picks valid values when fuzzed. """
   1097     def randval(self):
   1098         return RandEnumKeys(self.i2s)
   1099 
   1100 
   1101 class ShortEnumKeysField(ShortEnumField):
   1102     """ShortEnumField that picks valid values when fuzzed. """
   1103     def randval(self):
   1104         return RandEnumKeys(self.i2s)
   1105 
   1106 
   1107 class IntEnumKeysField(IntEnumField):
   1108     """IntEnumField that picks valid values when fuzzed. """
   1109     def randval(self):
   1110         return RandEnumKeys(self.i2s)
   1111 
   1112 
   1113 # Little endian long field
   1114 class LELongField(Field):
   1115     def __init__(self, name, default):
   1116         Field.__init__(self, name, default, "<Q")
   1117 
   1118 # Little endian fixed length field
   1119 class LEFieldLenField(FieldLenField):
   1120     def __init__(self, name, default,  length_of=None, fmt = "<H", count_of=None, adjust=lambda pkt,x:x, fld=None):
   1121         FieldLenField.__init__(self, name, default, length_of=length_of, fmt=fmt, count_of=count_of, fld=fld, adjust=adjust)
   1122 
   1123 
   1124 class FlagValue(object):
   1125     __slots__ = ["value", "names", "multi"]
   1126     def _fixvalue(self, value):
   1127         if isinstance(value, six.string_types):
   1128             value = value.split('+') if self.multi else list(value)
   1129         if isinstance(value, list):
   1130             y = 0
   1131             for i in value:
   1132                 y |= 1 << self.names.index(i)
   1133             value = y
   1134         return None if value is None else int(value)
   1135     def __init__(self, value, names):
   1136         self.multi = isinstance(names, list)
   1137         self.names = names
   1138         self.value = self._fixvalue(value)
   1139     def __hash__(self):
   1140         return hash(self.value)
   1141     def __int__(self):
   1142         return self.value
   1143     def __eq__(self, other):
   1144         return self.value == self._fixvalue(other)
   1145     def __lt__(self, other):
   1146         return self.value < self._fixvalue(other)
   1147     def __le__(self, other):
   1148         return self.value <= self._fixvalue(other)
   1149     def __gt__(self, other):
   1150         return self.value > self._fixvalue(other)
   1151     def __ge__(self, other):
   1152         return self.value >= self._fixvalue(other)
   1153     def __ne__(self, other):
   1154         return self.value != self._fixvalue(other)
   1155     def __and__(self, other):
   1156         return self.__class__(self.value & self._fixvalue(other), self.names)
   1157     __rand__ = __and__
   1158     def __or__(self, other):
   1159         return self.__class__(self.value | self._fixvalue(other), self.names)
   1160     __ror__ = __or__
   1161     def __lshift__(self, other):
   1162         return self.value << self._fixvalue(other)
   1163     def __rshift__(self, other):
   1164         return self.value >> self._fixvalue(other)
   1165     def __nonzero__(self):
   1166         return bool(self.value)
   1167     __bool__ = __nonzero__
   1168     def flagrepr(self):
   1169         warning("obj.flagrepr() is obsolete. Use str(obj) instead.")
   1170         return str(self)
   1171     def __str__(self):
   1172         i = 0
   1173         r = []
   1174         x = int(self)
   1175         while x:
   1176             if x & 1:
   1177                 r.append(self.names[i])
   1178             i += 1
   1179             x >>= 1
   1180         return ("+" if self.multi else "").join(r)
   1181     def __repr__(self):
   1182         return "<Flag %d (%s)>" % (self, self)
   1183     def __deepcopy__(self, memo):
   1184         return self.__class__(int(self), self.names)
   1185     def __getattr__(self, attr):
   1186         if attr in self.__slots__:
   1187             return super(FlagValue, self).__getattr__(attr)
   1188         try:
   1189             if self.multi:
   1190                 return bool((2 ** self.names.index(attr)) & int(self))
   1191             return all(bool((2 ** self.names.index(flag)) & int(self))
   1192                        for flag in attr)
   1193         except ValueError:
   1194             return super(FlagValue, self).__getattr__(attr)
   1195     def __setattr__(self, attr, value):
   1196         if attr == "value" and not isinstance(value, six.integer_types):
   1197             raise ValueError(value)
   1198         if attr in self.__slots__:
   1199             return super(FlagValue, self).__setattr__(attr, value)
   1200         if attr in self.names:
   1201             if value:
   1202                 self.value |= (2 ** self.names.index(attr))
   1203             else:
   1204                 self.value &= ~(2 ** self.names.index(attr))
   1205         else:
   1206             return super(FlagValue, self).__setattr__(attr, value)
   1207     def copy(self):
   1208         return self.__class__(self.value, self.names)
   1209 
   1210 
   1211 class FlagsField(BitField):
   1212     """ Handle Flag type field
   1213 
   1214    Make sure all your flags have a label
   1215 
   1216    Example:
   1217        >>> from scapy.packet import Packet
   1218        >>> class FlagsTest(Packet):
   1219                fields_desc = [FlagsField("flags", 0, 8, ["f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7"])]
   1220        >>> FlagsTest(flags=9).show2()
   1221        ###[ FlagsTest ]###
   1222          flags     = f0+f3
   1223        >>> FlagsTest(flags=0).show2().strip()
   1224        ###[ FlagsTest ]###
   1225          flags     =
   1226 
   1227    :param name: field's name
   1228    :param default: default value for the field
   1229    :param size: number of bits in the field
   1230    :param names: (list or dict) label for each flag, Least Significant Bit tag's name is written first
   1231    """
   1232     ismutable = True
   1233     __slots__ = ["multi", "names"]
   1234 
   1235     def __init__(self, name, default, size, names):
   1236         self.multi = isinstance(names, list)
   1237         self.names = names
   1238         BitField.__init__(self, name, default, size)
   1239 
   1240     def _fixup_val(self, x):
   1241         """Returns a FlagValue instance when needed. Internal method, to be
   1242 used in *2i() and i2*() methods.
   1243 
   1244         """
   1245         if isinstance(x, (list, tuple)):
   1246             return type(x)(
   1247                 v if v is None or isinstance(v, FlagValue)
   1248                 else FlagValue(v, self.names)
   1249                 for v in x
   1250             )
   1251         return x if x is None or isinstance(x, FlagValue) else FlagValue(x, self.names)
   1252 
   1253     def any2i(self, pkt, x):
   1254         return self._fixup_val(super(FlagsField, self).any2i(pkt, x))
   1255 
   1256     def m2i(self, pkt, x):
   1257         return self._fixup_val(super(FlagsField, self).m2i(pkt, x))
   1258 
   1259     def i2h(self, pkt, x):
   1260         return self._fixup_val(super(FlagsField, self).i2h(pkt, x))
   1261 
   1262     def i2repr(self, pkt, x):
   1263         if isinstance(x, (list, tuple)):
   1264             return repr(type(x)(
   1265                 None if v is None else str(self._fixup_val(v)) for v in x
   1266             ))
   1267         return None if x is None else str(self._fixup_val(x))
   1268 
   1269 
   1270 MultiFlagsEntry = collections.namedtuple('MultiFlagEntry', ['short', 'long'])
   1271 
   1272 
   1273 class MultiFlagsField(BitField):
   1274     __slots__ = FlagsField.__slots__ + ["depends_on"]
   1275 
   1276     def __init__(self, name, default, size, names, depends_on):
   1277         self.names = names
   1278         self.depends_on = depends_on
   1279         super(MultiFlagsField, self).__init__(name, default, size)
   1280 
   1281     def any2i(self, pkt, x):
   1282         assert isinstance(x, six.integer_types + (set,)), 'set expected'
   1283 
   1284         if pkt is not None:
   1285             if isinstance(x, six.integer_types):
   1286                 x = self.m2i(pkt, x)
   1287             else:
   1288                 v = self.depends_on(pkt)
   1289                 if v is not None:
   1290                     assert v in self.names, 'invalid dependency'
   1291                     these_names = self.names[v]
   1292                     s = set()
   1293                     for i in x:
   1294                         for val in six.itervalues(these_names):
   1295                             if val.short == i:
   1296                                 s.add(i)
   1297                                 break
   1298                         else:
   1299                             assert False, 'Unknown flag "{}" with this dependency'.format(i)
   1300                             continue
   1301                     x = s
   1302         return x
   1303 
   1304     def i2m(self, pkt, x):
   1305         v = self.depends_on(pkt)
   1306         if v in self.names:
   1307             these_names = self.names[v]
   1308         else:
   1309             these_names = {}
   1310 
   1311         r = 0
   1312         for flag_set in x:
   1313             for i, val in six.iteritems(these_names):
   1314                 if val.short == flag_set:
   1315                     r |= 1 << i
   1316                     break
   1317             else:
   1318                 r |= 1 << int(flag_set[len('bit '):])
   1319         return r
   1320 
   1321     def m2i(self, pkt, x):
   1322         v = self.depends_on(pkt)
   1323         if v in self.names:
   1324             these_names = self.names[v]
   1325         else:
   1326             these_names = {}
   1327 
   1328         r = set()
   1329         i = 0
   1330 
   1331         while x:
   1332             if x & 1:
   1333                 if i in these_names:
   1334                     r.add(these_names[i].short)
   1335                 else:
   1336                     r.add('bit {}'.format(i))
   1337             x >>= 1
   1338             i += 1
   1339         return r
   1340 
   1341     def i2repr(self, pkt, x):
   1342         v = self.depends_on(pkt)
   1343         if v in self.names:
   1344             these_names = self.names[v]
   1345         else:
   1346             these_names = {}
   1347 
   1348         r = set()
   1349         for flag_set in x:
   1350             for i in six.itervalues(these_names):
   1351                 if i.short == flag_set:
   1352                     r.add("{} ({})".format(i.long, i.short))
   1353                     break
   1354             else:
   1355                 r.add(flag_set)
   1356         return repr(r)
   1357 
   1358 
   1359 class FixedPointField(BitField):
   1360     __slots__ = ['frac_bits']
   1361     def __init__(self, name, default, size, frac_bits=16):
   1362         self.frac_bits = frac_bits
   1363         BitField.__init__(self, name, default, size)
   1364 
   1365     def any2i(self, pkt, val):
   1366         if val is None:
   1367             return val
   1368         ival = int(val)
   1369         fract = int( (val-ival) * 2**self.frac_bits )
   1370         return (ival << self.frac_bits) | fract
   1371 
   1372     def i2h(self, pkt, val):
   1373         int_part = val >> self.frac_bits
   1374         frac_part = val & (1 << self.frac_bits) - 1
   1375         frac_part /= 2.0**self.frac_bits
   1376         return int_part+frac_part
   1377     def i2repr(self, pkt, val):
   1378         return self.i2h(pkt, val)
   1379 
   1380 
   1381 # Base class for IPv4 and IPv6 Prefixes inspired by IPField and IP6Field.
   1382 # Machine values are encoded in a multiple of wordbytes bytes.
   1383 class _IPPrefixFieldBase(Field):
   1384     __slots__ = ["wordbytes", "maxbytes", "aton", "ntoa", "length_from"]
   1385     def __init__(self, name, default, wordbytes, maxbytes, aton, ntoa, length_from):
   1386         self.wordbytes = wordbytes
   1387         self.maxbytes = maxbytes
   1388         self.aton = aton
   1389         self.ntoa = ntoa
   1390         Field.__init__(self, name, default, "%is" % self.maxbytes)
   1391         self.length_from = length_from
   1392 
   1393     def _numbytes(self, pfxlen):
   1394         wbits= self.wordbytes * 8
   1395         return ((pfxlen + (wbits - 1)) // wbits) * self.wordbytes
   1396 
   1397     def h2i(self, pkt, x):
   1398         # "fc00:1::1/64" -> ("fc00:1::1", 64)
   1399         [pfx,pfxlen]= x.split('/')
   1400         self.aton(pfx) # check for validity
   1401         return (pfx, int(pfxlen))
   1402 
   1403 
   1404     def i2h(self, pkt, x):
   1405         # ("fc00:1::1", 64) -> "fc00:1::1/64"
   1406         (pfx,pfxlen)= x
   1407         return "%s/%i" % (pfx,pfxlen)
   1408 
   1409     def i2m(self, pkt, x):
   1410         # ("fc00:1::1", 64) -> (b"\xfc\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 64)
   1411         (pfx,pfxlen)= x
   1412         s= self.aton(pfx);
   1413         return (s[:self._numbytes(pfxlen)], pfxlen)
   1414 
   1415     def m2i(self, pkt, x):
   1416         # (b"\xfc\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 64) -> ("fc00:1::1", 64)
   1417         (s,pfxlen)= x
   1418 
   1419         if len(s) < self.maxbytes:
   1420             s= s + (b"\0" * (self.maxbytes - len(s)))
   1421         return (self.ntoa(s), pfxlen)
   1422 
   1423     def any2i(self, pkt, x):
   1424         if x is None:
   1425             return (self.ntoa(b"\0"*self.maxbytes), 1)
   1426 
   1427         return self.h2i(pkt,x)
   1428 
   1429     def i2len(self, pkt, x):
   1430         (_,pfxlen)= x
   1431         return pfxlen
   1432 
   1433     def addfield(self, pkt, s, val):
   1434         (rawpfx,pfxlen)= self.i2m(pkt,val)
   1435         fmt= "!%is" % self._numbytes(pfxlen)
   1436         return s+struct.pack(fmt, rawpfx)
   1437 
   1438     def getfield(self, pkt, s):
   1439         pfxlen= self.length_from(pkt)
   1440         numbytes= self._numbytes(pfxlen)
   1441         fmt= "!%is" % numbytes
   1442         return s[numbytes:], self.m2i(pkt, (struct.unpack(fmt, s[:numbytes])[0], pfxlen))
   1443 
   1444 
   1445 class IPPrefixField(_IPPrefixFieldBase):
   1446     def __init__(self, name, default, wordbytes=1, length_from= None):
   1447         _IPPrefixFieldBase.__init__(self, name, default, wordbytes, 4, inet_aton, inet_ntoa, length_from)
   1448 
   1449 
   1450 class IP6PrefixField(_IPPrefixFieldBase):
   1451     def __init__(self, name, default, wordbytes= 1, length_from= None):
   1452         _IPPrefixFieldBase.__init__(self, name, default, wordbytes, 16, lambda a: inet_pton(socket.AF_INET6, a), lambda n: inet_ntop(socket.AF_INET6, n), length_from)
   1453 
   1454 class UTCTimeField(IntField):
   1455     __slots__ = ["epoch", "delta", "strf", "use_nano"]
   1456     def __init__(self, name, default, epoch=None, use_nano=False, strf="%a, %d %b %Y %H:%M:%S +0000"):
   1457         IntField.__init__(self, name, default)
   1458         if epoch is None:
   1459             mk_epoch = EPOCH
   1460         else:
   1461             mk_epoch = time.mktime(epoch)
   1462         self.epoch = mk_epoch
   1463         self.delta = mk_epoch - EPOCH
   1464         self.strf = strf
   1465         self.use_nano = use_nano
   1466     def i2repr(self, pkt, x):
   1467         if x is None:
   1468             x = 0
   1469         elif self.use_nano:
   1470             x = x/1e9
   1471         x = int(x) + self.delta
   1472         t = time.strftime(self.strf, time.gmtime(x))
   1473         return "%s (%d)" % (t, x)
   1474     def i2m(self, pkt, x):
   1475         return int(x) if x != None else 0
   1476