class AS_resolver_riswhois(AS_resolver):
    server = "riswhois.ripe.net"
    options = "-k -M -1" class Gen(Generic[_T]):
    __slots__ = []  # type: List[str]

    def __iter__(self):
        # type: () -> Iterator[_T]
        return iter([])

    def __iterlen__(self):
        # type: () -> int
        return sum(1 for _ in iter(self)) def chb(x):
    # type: (int) -> bytes
    if isinstance(x, str):
        return x
    return chr(x) def orb(x):
    # type: (Union[int, str, bytes]) -> int
    """Return ord(x) when not already an int."""
    if isinstance(x, int):
        return x
    return ord(x) def raw(x):
    # type: (Union[Packet]) -> bytes
    """
    Builds a packet and returns its bytes representation.
    This function is and will always be cross-version compatible
    """
    if hasattr(x, "__bytes__"):
        return x.__bytes__()
    return bytes(x) def plain_str(x):
    # type: (AnyStr) -> str
    """Convert basic byte objects to str"""
    if isinstance(x, bytes):
        return x.decode(errors="ignore")
    return str(x) def bytes_encode(x):
    # type: (Any) -> bytes
    """Ensure that the given object is bytes.
    If the parameter is a packet, raw() should be preferred.
    """
    if isinstance(x, str):
        return x.encode()
    return bytes(x) class ConfClass(object):
class Interceptor(object):
class ProgPath(ConfClass):
class ConfigFieldList:
class Emphasize(ConfigFieldList):
class Resolve(ConfigFieldList):
class Num2Layer:
class LayersList(List[Type['scapy.packet.Packet']]):
class CommandsList(List[Callable[..., Any]]):
class CacheInstance(Dict[str, Any], object):
class NetCache:
class Conf(ConfClass):
    def configure(self, cnf):
    def __repr__(self):
    def __str__(self):
    def __init__(self,
                 name,  # type: str
                 default,  # type: Any
                 hook,  # type: Callable[..., Any]
                 args=None,  # type: Optional[List[Any]]
                 kargs=None  # type: Optional[Dict[str, Any]]
                 ):
    def __get__(self, obj, typ=None):
    def set_from_hook(obj, name, val):
    def __set__(self, obj, val):
def _readonly(name):
    def __init__(self):
    def _is_field(f):
    def _recalc_layer_list(self):
    def add(self, *flds):
    def remove(self, *flds):
    def __contains__(self, elt):
    def __repr__(self):
    def __init__(self):
    def register(self, num, layer):
    def register_num2layer(self, num, layer):
    def register_layer2num(self, num, layer):
    def __getitem__(self, item):
    def __contains__(self, item):
    def get(self,
            item,  # type: Union[int, Type[Packet]]
            default=None,  # type: Optional[Type[Packet]]
            ):
    def __repr__(self):
    def __init__(self):
    def __repr__(self):
    def register(self, layer):
    def layers(self):
    def filter(self, items):
    def unfilter(self):
    def __repr__(self):
    def register(self, cmd):
def lsc():
    def __init__(self, name="noname", timeout=None):
    def flush(self):
    def __getitem__(self, item):
    def get(self, item, default=None):
    def __setitem__(self, item, v):
    def update(self,  # type: ignore
               other,  # type: Any
               **kwargs  # type: Any
               ):
    def iteritems(self):
    def iterkeys(self):
    def __iter__(self):
    def itervalues(self):
    def items(self):
    def keys(self):
    def values(self):
    def __len__(self):
    def summary(self):
    def __repr__(self):
    def copy(self):
    def __init__(self):
    def add_cache(self, cache):
    def new_cache(self, name, timeout=None):
    def __delattr__(self, attr):
    def update(self, other):
    def flush(self):
    def __repr__(self):
def _version_checker(module, minver):
def isCryptographyValid():
def isCryptographyAdvanced():
def isPyPy():
def _prompt_changer(attr, val, old):
def _set_conf_sockets():
def _socket_changer(attr, val, old):
def _loglevel_changer(attr, val, old):
def _iface_changer(attr, val, old):
    def __getattribute__(self, attr):
def crypto_validator(func):
    def func_in(*args, **kwargs):
def scapy_delete_temp_files(): class BitEnumField(_BitField[Union[List[int], int]], _EnumField[int]):
    __slots__ = EnumField.__slots__

    def __init__(self, name, default, size, enum, **kwargs):
        # type: (str, Optional[int], int, Dict[int, str], **Any) -> None
        _EnumField.__init__(self, name, default, enum)
        _BitField.__init__(self, name, default, size, **kwargs)

    def any2i(self, pkt, x):
        # type: (Optional[Packet], Any) -> Union[List[int], int]
        return _EnumField.any2i(self, pkt, x)

    def i2repr(self,
               pkt,  # type: Optional[Packet]
               x,  # type: Union[List[int], int]
               ):
        # type: (...) -> Any
        return _EnumField.i2repr(self, pkt, x) class BitField(_BitField[int]):
    __doc__ = _BitField.__doc__ class ByteEnumField(EnumField[int]):
    def __init__(self, name, default, enum):
        # type: (str, Optional[int], Dict[int, str]) -> None
        EnumField.__init__(self, name, default, enum, "B") class ByteField(Field[int, int]):
    def __init__(self, name, default):
        # type: (str, Optional[int]) -> None
        Field.__init__(self, name, default, "B") class DestIP6Field(IP6Field, DestField):
    bindings = {}  # type: Dict[Type[Packet], Tuple[str, Any]]

    def __init__(self, name, default):
        # type: (str, str) -> None
        IP6Field.__init__(self, name, None)
        DestField.__init__(self, name, default)

    def i2m(self, pkt, x):
        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> bytes
        if x is None and pkt is not None:
            x = self.dst_from_pkt(pkt)
        return IP6Field.i2m(self, pkt, x)

    def i2h(self, pkt, x):
        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str
        if x is None and pkt is not None:
            x = self.dst_from_pkt(pkt)
        return super(DestIP6Field, self).i2h(pkt, x) class FieldLenField(Field[int, int]):
    __slots__ = ["length_of", "count_of", "adjust"]

    def __init__(
            self,
            name,  # type: str
            default,  # type: Optional[Any]
            length_of=None,  # type: Optional[str]
            fmt="H",  # type: str
            count_of=None,  # type: Optional[str]
            adjust=lambda pkt, x: x,  # type: Callable[[Packet, int], int]
    ):
        # type: (...) -> None
        Field.__init__(self, name, default, fmt)
        self.length_of = length_of
        self.count_of = count_of
        self.adjust = adjust

    def i2m(self, pkt, x):
        # type: (Optional[Packet], Optional[int]) -> int
        if x is None and pkt is not None:
            if self.length_of is not None:
                fld, fval = pkt.getfield_and_val(self.length_of)
                f = fld.i2len(pkt, fval)
            elif self.count_of is not None:
                fld, fval = pkt.getfield_and_val(self.count_of)
                f = fld.i2count(pkt, fval)
            else:
                raise ValueError(
                    "Field should have either length_of or count_of"
                )
            x = self.adjust(pkt, f)
        elif x is None:
            x = 0
        return x class FlagsField(_BitField[Optional[Union[int, FlagValue]]]):
    """ Handle Flag type field

   Make sure all your flags have a label

   Example (list):
       >>> from scapy.packet import Packet
       >>> class FlagsTest(Packet):
               fields_desc = [FlagsField("flags", 0, 8, ["f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7"])]  # noqa: E501
       >>> FlagsTest(flags=9).show2()
       ###[ FlagsTest ]###
         flags     = f0+f3

    Example (str):
       >>> from scapy.packet import Packet
       >>> class TCPTest(Packet):
               fields_desc = [
                   BitField("reserved", 0, 7),
                   FlagsField("flags", 0x2, 9, "FSRPAUECN")
               ]
       >>> TCPTest(flags=3).show2()
       ###[ FlagsTest ]###
         reserved  = 0
         flags     = FS

    Example (dict):
       >>> from scapy.packet import Packet
       >>> class FlagsTest2(Packet):
               fields_desc = [
                   FlagsField("flags", 0x2, 16, {
                       0x0001: "A",
                       0x0008: "B",
                   })
               ]

   :param name: field's name
   :param default: default value for the field
   :param size: number of bits in the field (in bits). if negative, LE
   :param names: (list or str or dict) label for each flag
       If it's a str or a list, the least Significant Bit tag's name
       is written first.
   """
    ismutable = True
    __slots__ = ["names"]

    def __init__(self,
                 name,  # type: str
                 default,  # type: Optional[Union[int, FlagValue]]
                 size,  # type: int
                 names  # type: Union[List[str], str, Dict[int, str]]
                 ):
        # type: (...) -> None
        # Convert the dict to a list
        if isinstance(names, dict):
            tmp = ["bit_%d" % i for i in range(abs(size))]
            for i, v in six.viewitems(names):
                tmp[int(math.floor(math.log(i, 2)))] = v
            names = tmp
        # Store the names as str or list
        self.names = names
        super(FlagsField, self).__init__(name, default, size)

    def _fixup_val(self, x):
        # type: (Any) -> Optional[FlagValue]
        """Returns a FlagValue instance when needed. Internal method, to be
used in *2i() and i2*() methods.

        """
        if isinstance(x, (FlagValue, VolatileValue)):
            return x  # type: ignore
        if x is None:
            return None
        return FlagValue(x, self.names)

    def any2i(self, pkt, x):
        # type: (Optional[Packet], Any) -> Optional[FlagValue]
        return self._fixup_val(super(FlagsField, self).any2i(pkt, x))

    def m2i(self, pkt, x):
        # type: (Optional[Packet], int) -> Optional[FlagValue]
        return self._fixup_val(super(FlagsField, self).m2i(pkt, x))

    def i2h(self, pkt, x):
        # type: (Optional[Packet], Any) -> Optional[FlagValue]
        return self._fixup_val(super(FlagsField, self).i2h(pkt, x))

    def i2repr(self,
               pkt,  # type: Optional[Packet]
               x,  # type: Any
               ):
        # type: (...) -> str
        if isinstance(x, (list, tuple)):
            return repr(type(x)(
                "None" if v is None else str(self._fixup_val(v)) for v in x
            ))
        return "None" if x is None else str(self._fixup_val(x)) class IntField(Field[int, int]):
    def __init__(self, name, default):
        # type: (str, Optional[int]) -> None
        Field.__init__(self, name, default, "I") class IP6Field(Field[Optional[Union[str, Net6]], bytes]):
    def __init__(self, name, default):
        # type: (str, Optional[str]) -> None
        Field.__init__(self, name, default, "16s")

    def h2i(self, pkt, x):
        # type: (Optional[Packet], Optional[str]) -> str
        if isinstance(x, bytes):
            x = plain_str(x)
        if isinstance(x, str):
            try:
                x = in6_ptop(x)
            except socket.error:
                return Net6(x)  # type: ignore
        elif isinstance(x, list):
            x = [self.h2i(pkt, n) for n in x]
        return x  # type: ignore

    def i2h(self, pkt, x):
        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str
        return cast(str, x)

    def i2m(self, pkt, x):
        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> bytes
        if x is None:
            x = "::"
        return inet_pton(socket.AF_INET6, plain_str(x))

    def m2i(self, pkt, x):
        # type: (Optional[Packet], bytes) -> str
        return inet_ntop(socket.AF_INET6, x)

    def any2i(self, pkt, x):
        # type: (Optional[Packet], Optional[str]) -> str
        return self.h2i(pkt, x)

    def i2repr(self, pkt, x):
        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str
        if x is None:
            return self.i2h(pkt, x)
        elif not isinstance(x, Net6) and not isinstance(x, list):
            if in6_isaddrTeredo(x):   # print Teredo info
                server, _, maddr, mport = teredoAddrExtractInfo(x)
                return "%s [Teredo srv: %s cli: %s:%s]" % (self.i2h(pkt, x), server, maddr, mport)  # noqa: E501
            elif in6_isaddr6to4(x):   # print encapsulated address
                vaddr = in6_6to4ExtractAddr(x)
                return "%s [6to4 GW: %s]" % (self.i2h(pkt, x), vaddr)
        r = self.i2h(pkt, x)          # No specific information to return
        return r if isinstance(r, str) else repr(r)

    def randval(self):
        # type: () -> RandIP6
        return RandIP6() class LongField(Field[int, int]):
    def __init__(self, name, default):
        # type: (str, int) -> None
        Field.__init__(self, name, default, "Q") class MACField(Field[Optional[str], bytes]):
    def __init__(self, name, default):
        # type: (str, Optional[Any]) -> None
        Field.__init__(self, name, default, "6s")

    def i2m(self, pkt, x):
        # type: (Optional[Packet], Optional[str]) -> bytes
        if x is None:
            return b"\0\0\0\0\0\0"
        try:
            y = mac2str(x)
        except (struct.error, OverflowError):
            y = bytes_encode(x)
        return y

    def m2i(self, pkt, x):
        # type: (Optional[Packet], bytes) -> str
        return str2mac(x)

    def any2i(self, pkt, x):
        # type: (Optional[Packet], Any) -> str
        if isinstance(x, bytes) and len(x) == 6:
            return self.m2i(pkt, x)
        return cast(str, x)

    def i2repr(self, pkt, x):
        # type: (Optional[Packet], Optional[str]) -> str
        x = self.i2h(pkt, x)
        if x is None:
            return repr(x)
        if self in conf.resolve:
            x = conf.manufdb._resolve_MAC(x)
        return x

    def randval(self):
        # type: () -> RandMAC
        return RandMAC() class PacketLenField(_PacketField[Optional[BasePacket]]):
    __slots__ = ["length_from"]

    def __init__(self,
                 name,  # type: str
                 default,  # type: Packet
                 cls,  # type: Union[Callable[[bytes], Packet], Type[Packet]]  # noqa: E501
                 length_from=None  # type: Optional[Callable[[Packet], int]]  # noqa: E501
                 ):
        # type: (...) -> None
        super(PacketLenField, self).__init__(name, default, cls)
        self.length_from = length_from or (lambda x: 0)

    def getfield(self,
                 pkt,  # type: Packet
                 s,  # type: bytes
                 ):
        # type: (...) -> Tuple[bytes, Optional[Packet]]
        len_pkt = self.length_from(pkt)
        i = None
        if len_pkt:
            try:
                i = self.m2i(pkt, s[:len_pkt])
            except Exception:
                if conf.debug_dissector:
                    raise
                i = conf.raw_layer(load=s[:len_pkt])
        return s[len_pkt:], i class PacketListField(_PacketField[List[BasePacket]]):
    """PacketListField represents a list containing a series of Packet instances
    that might occur right in the middle of another Packet field.
    This field type may also be used to indicate that a series of Packet
    instances have a sibling semantic instead of a parent/child relationship
    (i.e. a stack of layers).
    """
    __slots__ = ["count_from", "length_from", "next_cls_cb"]
    islist = 1

    def __init__(
            self,
            name,  # type: str
            default,  # type: Optional[List[BasePacket]]
            pkt_cls=None,  # type: Optional[Union[Callable[[bytes], Packet], Type[Packet]]]  # noqa: E501
            count_from=None,  # type: Optional[Callable[[Packet], int]]
            length_from=None,  # type: Optional[Callable[[Packet], int]]
            next_cls_cb=None,  # type: Optional[Callable[[Packet, List[BasePacket], Optional[Packet], bytes], Type[Packet]]]  # noqa: E501
    ):
        # type: (...) -> None
        """
        The number of Packet instances that are dissected by this field can
        be parametrized using one of three different mechanisms/parameters:

            * count_from: a callback that returns the number of Packet
              instances to dissect. The callback prototype is::

                count_from(pkt:Packet) -> int

            * length_from: a callback that returns the number of bytes that
              must be dissected by this field. The callback prototype is::

                length_from(pkt:Packet) -> int

            * next_cls_cb: a callback that enables a Scapy developer to
              dynamically discover if another Packet instance should be
              dissected or not. See below for this callback prototype.

        The bytes that are not consumed during the dissection of this field
        are passed to the next field of the current packet.

        For the serialization of such a field, the list of Packets that are
        contained in a PacketListField can be heterogeneous and is
        unrestricted.

        The type of the Packet instances that are dissected with this field is
        specified or discovered using one of the following mechanism:

            * the pkt_cls parameter may contain a callable that returns an
              instance of the dissected Packet. This may either be a
              reference of a Packet subclass (e.g. DNSRROPT in layers/dns.py)
              to generate an homogeneous PacketListField or a function
              deciding the type of the Packet instance
              (e.g. _CDPGuessAddrRecord in contrib/cdp.py)

            * the pkt_cls parameter may contain a class object with a defined
              ``dispatch_hook`` classmethod. That method must return a Packet
              instance. The ``dispatch_hook`` callmethod must implement the
                following prototype::

                dispatch_hook(cls,
                              _pkt:Optional[Packet],
                              *args, **kargs
                ) -> Type[Packet]

                The _pkt parameter may contain a reference to the packet
                instance containing the PacketListField that is being
                dissected.

            * the ``next_cls_cb`` parameter may contain a callable whose
              prototype is::

                cbk(pkt:Packet,
                    lst:List[Packet],
                    cur:Optional[Packet],
                    remain:str
                ) -> Optional[Type[Packet]]

              The pkt argument contains a reference to the Packet instance
              containing the PacketListField that is being dissected.
              The lst argument is the list of all Packet instances that were
              previously parsed during the current ``PacketListField``
              dissection, saved for the very last Packet instance.
              The cur argument contains a reference to that very last parsed
              ``Packet`` instance. The remain argument contains the bytes
              that may still be consumed by the current PacketListField
              dissection operation.

              This callback returns either the type of the next Packet to
              dissect or None to indicate that no more Packet are to be
              dissected.

              These four arguments allows a variety of dynamic discovery of
              the number of Packet to dissect and of the type of each one of
              these Packets, including: type determination based on current
              Packet instances or its underlayers, continuation based on the
              previously parsed Packet instances within that PacketListField,
              continuation based on a look-ahead on the bytes to be
              dissected...

        The pkt_cls and next_cls_cb parameters are semantically exclusive,
        although one could specify both. If both are specified, pkt_cls is
        silently ignored. The same is true for count_from and next_cls_cb.

        length_from and next_cls_cb are compatible and the dissection will
        end, whichever of the two stop conditions comes first.

        :param name: the name of the field
        :param default: the default value of this field; generally an empty
            Python list
        :param pkt_cls: either a callable returning a Packet instance or a
            class object defining a ``dispatch_hook`` class method
        :param count_from: a callback returning the number of Packet
            instances to dissect.
        :param length_from: a callback returning the number of bytes to dissect
        :param next_cls_cb: a callback returning either None or the type of
            the next Packet to dissect.
        """
        if default is None:
            default = []  # Create a new list for each instance
        super(PacketListField, self).__init__(
            name,
            default,
            pkt_cls  # type: ignore
        )
        self.count_from = count_from
        self.length_from = length_from
        self.next_cls_cb = next_cls_cb

    def any2i(self, pkt, x):
        # type: (Optional[Packet], Any) -> List[BasePacket]
        if not isinstance(x, list):
            return [x]
        else:
            return x

    def i2count(self,
                pkt,  # type: Optional[Packet]
                val,  # type: List[BasePacket]
                ):
        # type: (...) -> int
        if isinstance(val, list):
            return len(val)
        return 1

    def i2len(self,
              pkt,  # type: Optional[Packet]
              val,  # type: List[Packet]
              ):
        # type: (...) -> int
        return sum(len(p) for p in val)

    def getfield(self, pkt, s):
        # type: (Packet, bytes) -> Tuple[bytes, List[BasePacket]]
        c = len_pkt = cls = None
        if self.length_from is not None:
            len_pkt = self.length_from(pkt)
        elif self.count_from is not None:
            c = self.count_from(pkt)
        if self.next_cls_cb is not None:
            cls = self.next_cls_cb(pkt, [], None, s)
            c = 1
            if cls is None:
                c = 0

        lst = []  # type: List[BasePacket]
        ret = b""
        remain = s
        if len_pkt is not None:
            remain, ret = s[:len_pkt], s[len_pkt:]
        while remain:
            if c is not None:
                if c <= 0:
                    break
                c -= 1
            try:
                if cls is not None:
                    p = cls(remain)
                else:
                    p = self.m2i(pkt, remain)
            except Exception:
                if conf.debug_dissector:
                    raise
                p = conf.raw_layer(load=remain)
                remain = b""
            else:
                if conf.padding_layer in p:
                    pad = p[conf.padding_layer]
                    remain = pad.load
                    del(pad.underlayer.payload)
                    if self.next_cls_cb is not None:
                        cls = self.next_cls_cb(pkt, lst, p, remain)
                        if cls is not None:
                            c = 0 if c is None else c
                            c += 1
                else:
                    remain = b""
            lst.append(p)
        return remain + ret, lst

    def addfield(self, pkt, s, val):
        # type: (Packet, bytes, Any) -> bytes
        return s + b"".join(bytes_encode(v) for v in val) class ShortEnumField(EnumField[int]):
    __slots__ = EnumField.__slots__

    def __init__(self,
                 name,  # type: str
                 default,  # type: int
                 enum,  # type: Union[Dict[int, str], Dict[str, int], Tuple[Callable[[int], str], Callable[[str], int]], DADict[int, str]]  # noqa: E501
                 ):
        # type: (...) -> None
        EnumField.__init__(self, name, default, enum, "H") class ShortField(Field[int, int]):
    def __init__(self, name, default):
        # type: (str, Optional[int]) -> None
        Field.__init__(self, name, default, "H") class SourceIP6Field(IP6Field):
    __slots__ = ["dstname"]

    def __init__(self, name, dstname):
        # type: (str, str) -> None
        IP6Field.__init__(self, name, None)
        self.dstname = dstname

    def i2m(self, pkt, x):
        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> bytes
        if x is None:
            dst = ("::" if self.dstname is None else
                   getattr(pkt, self.dstname) or "::")
            iff, x, nh = conf.route6.route(dst)
        return super(SourceIP6Field, self).i2m(pkt, x)

    def i2h(self, pkt, x):
        # type: (Optional[Packet], Optional[Union[str, Net6]]) -> str
        if x is None:
            if conf.route6 is None:
                # unused import, only to initialize conf.route6
                import scapy.route6  # noqa: F401
            dst = ("::" if self.dstname is None else getattr(pkt, self.dstname))  # noqa: E501
            if isinstance(dst, (Gen, list)):
                r = {conf.route6.route(str(daddr))
                     for daddr in dst}
                if len(r) > 1:
                    warning("More than one possible route for %r" % (dst,))
                x = min(r)[1]
            else:
                x = conf.route6.route(dst)[1]
        return super(SourceIP6Field, self).i2h(pkt, x) class StrField(_StrField[bytes]):
    pass class StrFixedLenField(StrField):
    __slots__ = ["length_from"]

    def __init__(
            self,
            name,  # type: str
            default,  # type: Optional[bytes]
            length=None,  # type: Optional[int]
            length_from=None,  # type: Optional[Callable[[Packet], int]]  # noqa: E501
    ):
        # type: (...) -> None
        super(StrFixedLenField, self).__init__(name, default)
        self.length_from = length_from or (lambda x: 0)
        if length is not None:
            self.length_from = lambda x, length=length: length  # type: ignore

    def i2repr(self,
               pkt,  # type: Optional[Packet]
               v,  # type: bytes
               ):
        # type: (...) -> str
        if isinstance(v, bytes):
            v = v.rstrip(b"\0")
        return super(StrFixedLenField, self).i2repr(pkt, v)

    def getfield(self, pkt, s):
        # type: (Packet, bytes) -> Tuple[bytes, bytes]
        len_pkt = self.length_from(pkt)
        return s[len_pkt:], self.m2i(pkt, s[:len_pkt])

    def addfield(self, pkt, s, val):
        # type: (Packet, bytes, Optional[bytes]) -> bytes
        len_pkt = self.length_from(pkt)
        if len_pkt is None:
            return s + self.i2m(pkt, val)
        return s + struct.pack("%is" % len_pkt, self.i2m(pkt, val))

    def randval(self):
        # type: () -> RandBin
        try:
            return RandBin(self.length_from(None))  # type: ignore
        except Exception:
            return RandBin(RandNum(0, 200)) class StrLenField(StrField):
    __slots__ = ["length_from", "max_length"]

    def __init__(
            self,
            name,  # type: str
            default,  # type: bytes
            length_from=None,  # type: Optional[Callable[[Packet], int]]
            max_length=None,  # type: Optional[Any]
    ):
        # type: (...) -> None
        super(StrLenField, self).__init__(name, default)
        self.length_from = length_from
        self.max_length = max_length

    def getfield(self, pkt, s):
        # type: (Any, bytes) -> Tuple[bytes, bytes]
        len_pkt = (self.length_from or (lambda x: 0))(pkt)
        return s[len_pkt:], self.m2i(pkt, s[:len_pkt])

    def randval(self):
        # type: () -> RandBin
        return RandBin(RandNum(0, self.max_length or 1200)) class X3BytesField(ThreeBytesField, XByteField):
    def i2repr(self, pkt, x):
        # type: (Optional[Packet], int) -> str
        return XByteField.i2repr(self, pkt, x) class XBitField(BitField):
    def i2repr(self, pkt, x):
        # type: (Optional[Packet], int) -> str
        return lhex(self.i2h(pkt, x)) class XIntField(IntField):
    def i2repr(self, pkt, x):
        # type: (Optional[Packet], int) -> str
        return lhex(self.i2h(pkt, x)) class XShortField(ShortField):
    def i2repr(self, pkt, x):
        # type: (Optional[Packet], int) -> str
        return lhex(self.i2h(pkt, x)) class IP(Packet, IPTools):
    __slots__ = ["_defrag_pos"]
    name = "IP"
    fields_desc = [BitField("version", 4, 4),
                   BitField("ihl", None, 4),
                   XByteField("tos", 0),
                   ShortField("len", None),
                   ShortField("id", 1),
                   FlagsField("flags", 0, 3, ["MF", "DF", "evil"]),
                   BitField("frag", 0, 13),
                   ByteField("ttl", 64),
                   ByteEnumField("proto", 0, IP_PROTOS),
                   XShortField("chksum", None),
                   # IPField("src", "127.0.0.1"),
                   Emph(SourceIPField("src", "dst")),
                   Emph(DestIPField("dst", "127.0.0.1")),
                   PacketListField("options", [], IPOption, length_from=lambda p:p.ihl * 4 - 20)]  # noqa: E501

    def post_build(self, p, pay):
        ihl = self.ihl
        p += b"\0" * ((-len(p)) % 4)  # pad IP options if needed
        if ihl is None:
            ihl = len(p) // 4
            p = chb(((self.version & 0xf) << 4) | ihl & 0x0f) + p[1:]
        if self.len is None:
            tmp_len = len(p) + len(pay)
            p = p[:2] + struct.pack("!H", tmp_len) + p[4:]
        if self.chksum is None:
            ck = checksum(p)
            p = p[:10] + chb(ck >> 8) + chb(ck & 0xff) + p[12:]
        return p + pay

    def extract_padding(self, s):
        tmp_len = self.len - (self.ihl << 2)
        if tmp_len < 0:
            return s, b""
        return s[:tmp_len], s[tmp_len:]

    def route(self):
        dst = self.dst
        if isinstance(dst, Gen):
            dst = next(iter(dst))
        if conf.route is None:
            # unused import, only to initialize conf.route
            import scapy.route  # noqa: F401
        return conf.route.route(dst)

    def hashret(self):
        if ((self.proto == socket.IPPROTO_ICMP) and
            (isinstance(self.payload, ICMP)) and
                (self.payload.type in [3, 4, 5, 11, 12])):
            return self.payload.payload.hashret()
        if not conf.checkIPinIP and self.proto in [4, 41]:  # IP, IPv6
            return self.payload.hashret()
        if self.dst == "224.0.0.251":  # mDNS
            return struct.pack("B", self.proto) + self.payload.hashret()
        if conf.checkIPsrc and conf.checkIPaddr:
            return (strxor(inet_pton(socket.AF_INET, self.src),
                           inet_pton(socket.AF_INET, self.dst)) +
                    struct.pack("B", self.proto) + self.payload.hashret())
        return struct.pack("B", self.proto) + self.payload.hashret()

    def answers(self, other):
        if not conf.checkIPinIP:  # skip IP in IP and IPv6 in IP
            if self.proto in [4, 41]:
                return self.payload.answers(other)
            if isinstance(other, IP) and other.proto in [4, 41]:
                return self.answers(other.payload)
            if conf.ipv6_enabled \
               and isinstance(other, scapy.layers.inet6.IPv6) \
               and other.nh in [4, 41]:
                return self.answers(other.payload)
        if not isinstance(other, IP):
            return 0
        if conf.checkIPaddr:
            if other.dst == "224.0.0.251" and self.dst == "224.0.0.251":  # mDNS  # noqa: E501
                return self.payload.answers(other.payload)
            elif (self.dst != other.src):
                return 0
        if ((self.proto == socket.IPPROTO_ICMP) and
            (isinstance(self.payload, ICMP)) and
                (self.payload.type in [3, 4, 5, 11, 12])):
            # ICMP error message
            return self.payload.payload.answers(other)

        else:
            if ((conf.checkIPaddr and (self.src != other.dst)) or
                    (self.proto != other.proto)):
                return 0
            return self.payload.answers(other.payload)

    def mysummary(self):
        s = self.sprintf("%IP.src% > %IP.dst% %IP.proto%")
        if self.frag:
            s += " frag:%i" % self.frag
        return s

    def fragment(self, fragsize=1480):
        """Fragment IP datagrams"""
        lastfragsz = fragsize
        fragsize -= fragsize % 8
        lst = []
        fnb = 0
        fl = self
        while fl.underlayer is not None:
            fnb += 1
            fl = fl.underlayer

        for p in fl:
            s = raw(p[fnb].payload)
            if len(s) <= lastfragsz:
                lst.append(p)
                continue

            nb = (len(s) - lastfragsz + fragsize - 1) // fragsize + 1
            for i in range(nb):
                q = p.copy()
                del(q[fnb].payload)
                del(q[fnb].chksum)
                del(q[fnb].len)
                if i != nb - 1:
                    q[fnb].flags |= 1
                    fragend = (i + 1) * fragsize
                else:
                    fragend = i * fragsize + lastfragsz
                q[fnb].frag += i * fragsize // 8
                r = conf.raw_layer(load=s[i * fragsize:fragend])
                r.overload_fields = p[fnb].payload.overload_fields.copy()
                q.add_payload(r)
                lst.append(q)
        return lst class IPTools(object):
    """Add more powers to a class with an "src" attribute."""
    __slots__ = []

    def whois(self):
        """whois the source and print the output"""
        print(whois(self.src).decode("utf8", "ignore"))

    def _ttl(self):
        """Returns ttl or hlim, depending on the IP version"""
        return self.hlim if isinstance(self, scapy.layers.inet6.IPv6) else self.ttl  # noqa: E501

    def ottl(self):
        t = sorted([32, 64, 128, 255] + [self._ttl()])
        return t[t.index(self._ttl()) + 1]

    def hops(self):
        return self.ottl() - self._ttl() class TCP(Packet):
    name = "TCP"
    fields_desc = [ShortEnumField("sport", 20, TCP_SERVICES),
                   ShortEnumField("dport", 80, TCP_SERVICES),
                   IntField("seq", 0),
                   IntField("ack", 0),
                   BitField("dataofs", None, 4),
                   BitField("reserved", 0, 3),
                   FlagsField("flags", 0x2, 9, "FSRPAUECN"),
                   ShortField("window", 8192),
                   XShortField("chksum", None),
                   ShortField("urgptr", 0),
                   TCPOptionsField("options", "")]

    def post_build(self, p, pay):
        p += pay
        dataofs = self.dataofs
        if dataofs is None:
            opt_len = len(self.get_field("options").i2m(self, self.options))
            dataofs = 5 + ((opt_len + 3) // 4)
            dataofs = (dataofs << 4) | orb(p[12]) & 0x0f
            p = p[:12] + chb(dataofs & 0xff) + p[13:]
        if self.chksum is None:
            if isinstance(self.underlayer, IP):
                ck = in4_chksum(socket.IPPROTO_TCP, self.underlayer, p)
                p = p[:16] + struct.pack("!H", ck) + p[18:]
            elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr):  # noqa: E501
                ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer, p)  # noqa: E501
                p = p[:16] + struct.pack("!H", ck) + p[18:]
            else:
                log_runtime.info(
                    "No IP underlayer to compute checksum. Leaving null."
                )
        return p

    def hashret(self):
        if conf.checkIPsrc:
            return struct.pack("H", self.sport ^ self.dport) + self.payload.hashret()  # noqa: E501
        else:
            return self.payload.hashret()

    def answers(self, other):
        if not isinstance(other, TCP):
            return 0
        # RST packets don't get answers
        if other.flags.R:
            return 0
        # We do not support the four-way handshakes with the SYN+ACK
        # answer split in two packets (one ACK and one SYN): in that
        # case the ACK will be seen as an answer, but not the SYN.
        if self.flags.S:
            # SYN packets without ACK are not answers
            if not self.flags.A:
                return 0
            # SYN+ACK packets answer SYN packets
            if not other.flags.S:
                return 0
        if conf.checkIPsrc:
            if not ((self.sport == other.dport) and
                    (self.dport == other.sport)):
                return 0
        # Do not check ack value for SYN packets without ACK
        if not (other.flags.S and not other.flags.A) \
           and abs(other.ack - self.seq) > 2:
            return 0
        # Do not check ack value for RST packets without ACK
        if self.flags.R and not self.flags.A:
            return 1
        if abs(other.seq - self.ack) > 2 + len(other.payload):
            return 0
        return 1

    def mysummary(self):
        if isinstance(self.underlayer, IP):
            return self.underlayer.sprintf("TCP %IP.src%:%TCP.sport% > %IP.dst%:%TCP.dport% %TCP.flags%")  # noqa: E501
        elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6):  # noqa: E501
            return self.underlayer.sprintf("TCP %IPv6.src%:%TCP.sport% > %IPv6.dst%:%TCP.dport% %TCP.flags%")  # noqa: E501
        else:
            return self.sprintf("TCP %TCP.sport% > %TCP.dport% %TCP.flags%") class TCPerror(TCP):
    name = "TCP in ICMP"

    def answers(self, other):
        if not isinstance(other, TCP):
            return 0
        if conf.checkIPsrc:
            if not ((self.sport == other.sport) and
                    (self.dport == other.dport)):
                return 0
        if conf.check_TCPerror_seqack:
            if self.seq is not None:
                if self.seq != other.seq:
                    return 0
            if self.ack is not None:
                if self.ack != other.ack:
                    return 0
        return 1

    def mysummary(self):
        return Packet.mysummary(self) class TracerouteResult(SndRcvList):
    __slots__ = ["graphdef", "graphpadding", "graphASres", "padding", "hloc",
                 "nloc"]

    def __init__(self, res=None, name="Traceroute", stats=None):
        SndRcvList.__init__(self, res, name, stats)
        self.graphdef = None
        self.graphASres = None
        self.padding = 0
        self.hloc = None
        self.nloc = None

    def show(self):
        return self.make_table(lambda s, r: (s.sprintf("%IP.dst%:{TCP:tcp%ir,TCP.dport%}{UDP:udp%ir,UDP.dport%}{ICMP:ICMP}"),  # noqa: E501
                                             s.ttl,
                                             r.sprintf("%-15s,IP.src% {TCP:%TCP.flags%}{ICMP:%ir,ICMP.type%}")))  # noqa: E501

    def get_trace(self):
        trace = {}
        for s, r in self.res:
            if IP not in s:
                continue
            d = s[IP].dst
            if d not in trace:
                trace[d] = {}
            trace[d][s[IP].ttl] = r[IP].src, ICMP not in r
        for k in six.itervalues(trace):
            try:
                m = min(x for x, y in six.iteritems(k) if y[1])
            except ValueError:
                continue
            for li in list(k):  # use list(): k is modified in the loop
                if li > m:
                    del k[li]
        return trace

    def trace3D(self, join=True):
        """Give a 3D representation of the traceroute.
        right button: rotate the scene
        middle button: zoom
        shift-left button: move the scene
        left button on a ball: toggle IP displaying
        double-click button on a ball: scan ports 21,22,23,25,80 and 443 and display the result"""  # noqa: E501
        # When not ran from a notebook, vpython pooly closes itself
        # using os._exit once finished. We pack it into a Process
        import multiprocessing
        p = multiprocessing.Process(target=self.trace3D_notebook)
        p.start()
        if join:
            p.join()

    def trace3D_notebook(self):
        """Same than trace3D, used when ran from Jupyter notebooks"""
        trace = self.get_trace()
        import vpython

        class IPsphere(vpython.sphere):
            def __init__(self, ip, **kargs):
                vpython.sphere.__init__(self, **kargs)
                self.ip = ip
                self.label = None
                self.setlabel(self.ip)
                self.last_clicked = None
                self.full = False
                self.savcolor = vpython.vec(*self.color.value)

            def fullinfos(self):
                self.full = True
                self.color = vpython.vec(1, 0, 0)
                a, b = sr(IP(dst=self.ip) / TCP(dport=[21, 22, 23, 25, 80, 443], flags="S"), timeout=2, verbose=0)  # noqa: E501
                if len(a) == 0:
                    txt = "%s:\nno results" % self.ip
                else:
                    txt = "%s:\n" % self.ip
                    for s, r in a:
                        txt += r.sprintf("{TCP:%IP.src%:%TCP.sport% %TCP.flags%}{TCPerror:%IPerror.dst%:%TCPerror.dport% %IP.src% %ir,ICMP.type%}\n")  # noqa: E501
                self.setlabel(txt, visible=1)

            def unfull(self):
                self.color = self.savcolor
                self.full = False
                self.setlabel(self.ip)

            def setlabel(self, txt, visible=None):
                if self.label is not None:
                    if visible is None:
                        visible = self.label.visible
                    self.label.visible = 0
                elif visible is None:
                    visible = 0
                self.label = vpython.label(text=txt, pos=self.pos, space=self.radius, xoffset=10, yoffset=20, visible=visible)  # noqa: E501

            def check_double_click(self):
                try:
                    if self.full or not self.label.visible:
                        return False
                    if self.last_clicked is not None:
                        return (time.time() - self.last_clicked) < 0.5
                    return False
                finally:
                    self.last_clicked = time.time()

            def action(self):
                self.label.visible ^= 1
                if self.full:
                    self.unfull()

        vpython.scene = vpython.canvas()
        vpython.scene.title = "<center><u><b>%s</b></u></center>" % self.listname  # noqa: E501
        vpython.scene.append_to_caption(
            re.sub(
                r'\%(.*)\%',
                r'<span style="color: red">\1</span>',
                re.sub(
                    r'\`(.*)\`',
                    r'<span style="color: #3399ff">\1</span>',
                    """<u><b>Commands:</b></u>
%Click% to toggle information about a node.
%Double click% to perform a quick web scan on this node.
<u><b>Camera usage:</b></u>
`Right button drag or Ctrl-drag` to rotate "camera" to view scene.
`Shift-drag` to move the object around.
`Middle button or Alt-drag` to drag up or down to zoom in or out.
  On a two-button mouse, `middle is wheel or left + right`.
Touch screen: pinch/extend to zoom, swipe or two-finger rotate."""
                )
            )
        )
        vpython.scene.exit = True
        rings = {}
        tr3d = {}
        for i in trace:
            tr = trace[i]
            tr3d[i] = []
            for t in range(1, max(tr) + 1):
                if t not in rings:
                    rings[t] = []
                if t in tr:
                    if tr[t] not in rings[t]:
                        rings[t].append(tr[t])
                    tr3d[i].append(rings[t].index(tr[t]))
                else:
                    rings[t].append(("unk", -1))
                    tr3d[i].append(len(rings[t]) - 1)

        for t in rings:
            r = rings[t]
            tmp_len = len(r)
            for i in range(tmp_len):
                if r[i][1] == -1:
                    col = vpython.vec(0.75, 0.75, 0.75)
                elif r[i][1]:
                    col = vpython.color.green
                else:
                    col = vpython.color.blue

                s = IPsphere(pos=vpython.vec((tmp_len - 1) * vpython.cos(2 * i * vpython.pi / tmp_len), (tmp_len - 1) * vpython.sin(2 * i * vpython.pi / tmp_len), 2 * t),  # noqa: E501
                             ip=r[i][0],
                             color=col)
                for trlst in six.itervalues(tr3d):
                    if t <= len(trlst):
                        if trlst[t - 1] == i:
                            trlst[t - 1] = s
        forecol = colgen(0.625, 0.4375, 0.25, 0.125)
        for trlst in six.itervalues(tr3d):
            col = vpython.vec(*next(forecol))
            start = vpython.vec(0, 0, 0)
            for ip in trlst:
                vpython.cylinder(pos=start, axis=ip.pos - start, color=col, radius=0.2)  # noqa: E501
                start = ip.pos

        vpython.rate(50)

        # Keys handling
        # TODO: there is currently no way of closing vpython correctly
        # https://github.com/BruceSherwood/vpython-jupyter/issues/36
        # def keyboard_press(ev):
        #     k = ev.key
        #     if k == "esc" or k == "q":
        #         pass  # TODO: close
        #
        # vpython.scene.bind('keydown', keyboard_press)

        # Mouse handling
        def mouse_click(ev):
            if ev.press == "left":
                o = vpython.scene.mouse.pick
                if o and isinstance(o, IPsphere):
                    if o.check_double_click():
                        if o.ip == "unk":
                            return
                        o.fullinfos()
                    else:
                        o.action()

        vpython.scene.bind('mousedown', mouse_click)

    def world_trace(self):
        """Display traceroute results on a world map."""

        # Check that the geoip2 module can be imported
        # Doc: http://geoip2.readthedocs.io/en/latest/
        try:
            # GeoIP2 modules need to be imported as below
            import geoip2.database
            import geoip2.errors
        except ImportError:
            log_runtime.error(
                "Cannot import geoip2. Won't be able to plot the world."
            )
            return []
        # Check availability of database
        if not conf.geoip_city:
            log_runtime.error(
                "Cannot import the geolite2 CITY database.\n"
                "Download it from http://dev.maxmind.com/geoip/geoip2/geolite2/"  # noqa: E501
                " then set its path to conf.geoip_city"
            )
            return []
        # Check availability of plotting devices
        try:
            import cartopy.crs as ccrs
        except ImportError:
            log_runtime.error(
                "Cannot import cartopy.\n"
                "More infos on http://scitools.org.uk/cartopy/docs/latest/installing.html"  # noqa: E501
            )
            return []
        if not MATPLOTLIB:
            log_runtime.error(
                "Matplotlib is not installed. Won't be able to plot the world."
            )
            return []

        # Open & read the GeoListIP2 database
        try:
            db = geoip2.database.Reader(conf.geoip_city)
        except Exception:
            log_runtime.error(
                "Cannot open geoip2 database at %s",
                conf.geoip_city
            )
            return []

        # Regroup results per trace
        ips = {}
        rt = {}
        ports_done = {}
        for s, r in self.res:
            ips[r.src] = None
            if s.haslayer(TCP) or s.haslayer(UDP):
                trace_id = (s.src, s.dst, s.proto, s.dport)
            elif s.haslayer(ICMP):
                trace_id = (s.src, s.dst, s.proto, s.type)
            else:
                trace_id = (s.src, s.dst, s.proto, 0)
            trace = rt.get(trace_id, {})
            if not r.haslayer(ICMP) or r.type != 11:
                if trace_id in ports_done:
                    continue
                ports_done[trace_id] = None
            trace[s.ttl] = r.src
            rt[trace_id] = trace

        # Get the addresses locations
        trt = {}
        for trace_id in rt:
            trace = rt[trace_id]
            loctrace = []
            for i in range(max(trace)):
                ip = trace.get(i, None)
                if ip is None:
                    continue
                # Fetch database
                try:
                    sresult = db.city(ip)
                except geoip2.errors.AddressNotFoundError:
                    continue
                loctrace.append((sresult.location.longitude, sresult.location.latitude))  # noqa: E501
            if loctrace:
                trt[trace_id] = loctrace

        # Load the map renderer
        plt.figure(num='Scapy')
        ax = plt.axes(projection=ccrs.PlateCarree())
        # Draw countries
        ax.coastlines()
        ax.stock_img()
        # Set normal size
        ax.set_global()
        # Add title
        plt.title("Scapy traceroute results")

        from matplotlib.collections import LineCollection
        from matplotlib import colors as mcolors
        colors_cycle = iter(mcolors.BASE_COLORS)
        lines = []

        # Split traceroute measurement
        for key, trc in six.iteritems(trt):
            # Get next color
            color = next(colors_cycle)
            # Gather mesurments data
            data_lines = [(trc[i], trc[i + 1]) for i in range(len(trc) - 1)]
            # Create line collection
            line_col = LineCollection(data_lines, linewidths=2,
                                      label=key[1],
                                      color=color)
            lines.append(line_col)
            ax.add_collection(line_col)
            # Create map points
            lines.extend([ax.plot(*x, marker='.', color=color) for x in trc])

        # Generate legend
        ax.legend()

        # Call show() if matplotlib is not inlined
        if not MATPLOTLIB_INLINED:
            plt.show()

        # Clean
        ax.remove()

        # Return the drawn lines
        return lines

    def make_graph(self, ASres=None, padding=0):
        self.graphASres = ASres
        self.graphpadding = padding
        ips = {}
        rt = {}
        ports = {}
        ports_done = {}
        for s, r in self.res:
            r = r.getlayer(IP) or (conf.ipv6_enabled and r[scapy.layers.inet6.IPv6]) or r  # noqa: E501
            s = s.getlayer(IP) or (conf.ipv6_enabled and s[scapy.layers.inet6.IPv6]) or s  # noqa: E501
            ips[r.src] = None
            if TCP in s:
                trace_id = (s.src, s.dst, 6, s.dport)
            elif UDP in s:
                trace_id = (s.src, s.dst, 17, s.dport)
            elif ICMP in s:
                trace_id = (s.src, s.dst, 1, s.type)
            else:
                trace_id = (s.src, s.dst, s.proto, 0)
            trace = rt.get(trace_id, {})
            ttl = conf.ipv6_enabled and scapy.layers.inet6.IPv6 in s and s.hlim or s.ttl  # noqa: E501
            if not (ICMP in r and r[ICMP].type == 11) and not (conf.ipv6_enabled and scapy.layers.inet6.IPv6 in r and scapy.layers.inet6.ICMPv6TimeExceeded in r):  # noqa: E501
                if trace_id in ports_done:
                    continue
                ports_done[trace_id] = None
                p = ports.get(r.src, [])
                if TCP in r:
                    p.append(r.sprintf("<T%ir,TCP.sport%> %TCP.sport% %TCP.flags%"))  # noqa: E501
                    trace[ttl] = r.sprintf('"%r,src%":T%ir,TCP.sport%')
                elif UDP in r:
                    p.append(r.sprintf("<U%ir,UDP.sport%> %UDP.sport%"))
                    trace[ttl] = r.sprintf('"%r,src%":U%ir,UDP.sport%')
                elif ICMP in r:
                    p.append(r.sprintf("<I%ir,ICMP.type%> ICMP %ICMP.type%"))
                    trace[ttl] = r.sprintf('"%r,src%":I%ir,ICMP.type%')
                else:
                    p.append(r.sprintf("{IP:<P%ir,proto%> IP %proto%}{IPv6:<P%ir,nh%> IPv6 %nh%}"))  # noqa: E501
                    trace[ttl] = r.sprintf('"%r,src%":{IP:P%ir,proto%}{IPv6:P%ir,nh%}')  # noqa: E501
                ports[r.src] = p
            else:
                trace[ttl] = r.sprintf('"%r,src%"')
            rt[trace_id] = trace

        # Fill holes with unk%i nodes
        unknown_label = incremental_label("unk%i")
        blackholes = []
        bhip = {}
        for rtk in rt:
            trace = rt[rtk]
            max_trace = max(trace)
            for n in range(min(trace), max_trace):
                if n not in trace:
                    trace[n] = next(unknown_label)
            if rtk not in ports_done:
                if rtk[2] == 1:  # ICMP
                    bh = "%s %i/icmp" % (rtk[1], rtk[3])
                elif rtk[2] == 6:  # TCP
                    bh = "%s %i/tcp" % (rtk[1], rtk[3])
                elif rtk[2] == 17:  # UDP
                    bh = '%s %i/udp' % (rtk[1], rtk[3])
                else:
                    bh = '%s %i/proto' % (rtk[1], rtk[2])
                ips[bh] = None
                bhip[rtk[1]] = bh
                bh = '"%s"' % bh
                trace[max_trace + 1] = bh
                blackholes.append(bh)

        # Find AS numbers
        ASN_query_list = set(x.rsplit(" ", 1)[0] for x in ips)
        if ASres is None:
            ASNlist = []
        else:
            ASNlist = ASres.resolve(*ASN_query_list)

        ASNs = {}
        ASDs = {}
        for ip, asn, desc, in ASNlist:
            if asn is None:
                continue
            iplist = ASNs.get(asn, [])
            if ip in bhip:
                if ip in ports:
                    iplist.append(ip)
                iplist.append(bhip[ip])
            else:
                iplist.append(ip)
            ASNs[asn] = iplist
            ASDs[asn] = desc

        backcolorlist = colgen("60", "86", "ba", "ff")
        forecolorlist = colgen("a0", "70", "40", "20")

        s = "digraph trace {\n"

        s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n"

        s += "\n#ASN clustering\n"
        for asn in ASNs:
            s += '\tsubgraph cluster_%s {\n' % asn
            col = next(backcolorlist)
            s += '\t\tcolor="#%s%s%s";' % col
            s += '\t\tnode [fillcolor="#%s%s%s",style=filled];' % col
            s += '\t\tfontsize = 10;'
            s += '\t\tlabel = "%s\\n[%s]"\n' % (asn, ASDs[asn])
            for ip in ASNs[asn]:

                s += '\t\t"%s";\n' % ip
            s += "\t}\n"

        s += "#endpoints\n"
        for p in ports:
            s += '\t"%s" [shape=record,color=black,fillcolor=green,style=filled,label="%s|%s"];\n' % (p, p, "|".join(ports[p]))  # noqa: E501

        s += "\n#Blackholes\n"
        for bh in blackholes:
            s += '\t%s [shape=octagon,color=black,fillcolor=red,style=filled];\n' % bh  # noqa: E501

        if padding:
            s += "\n#Padding\n"
            pad = {}
            for snd, rcv in self.res:
                if rcv.src not in ports and rcv.haslayer(conf.padding_layer):
                    p = rcv.getlayer(conf.padding_layer).load
                    if p != b"\x00" * len(p):
                        pad[rcv.src] = None
            for rcv in pad:
                s += '\t"%s" [shape=triangle,color=black,fillcolor=red,style=filled];\n' % rcv  # noqa: E501

        s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n"

        for rtk in rt:
            s += "#---[%s\n" % repr(rtk)
            s += '\t\tedge [color="#%s%s%s"];\n' % next(forecolorlist)
            trace = rt[rtk]
            maxtrace = max(trace)
            for n in range(min(trace), maxtrace):
                s += '\t%s ->\n' % trace[n]
            s += '\t%s;\n' % trace[maxtrace]

        s += "}\n"
        self.graphdef = s

    def graph(self, ASres=conf.AS_resolver, padding=0, **kargs):
        """x.graph(ASres=conf.AS_resolver, other args):
        ASres=None          : no AS resolver => no clustering
        ASres=AS_resolver() : default whois AS resolver (riswhois.ripe.net)
        ASres=AS_resolver_cymru(): use whois.cymru.com whois database
        ASres=AS_resolver(server="whois.ra.net")
        type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option  # noqa: E501
        target: filename or redirect. Defaults pipe to Imagemagick's display program  # noqa: E501
        prog: which graphviz program to use"""
        if (self.graphdef is None or
            self.graphASres != ASres or
                self.graphpadding != padding):
            self.make_graph(ASres, padding)

        return do_graph(self.graphdef, **kargs) class UDP(Packet):
    name = "UDP"
    fields_desc = [ShortEnumField("sport", 53, UDP_SERVICES),
                   ShortEnumField("dport", 53, UDP_SERVICES),
                   ShortField("len", None),
                   XShortField("chksum", None), ]

    def post_build(self, p, pay):
        p += pay
        tmp_len = self.len
        if tmp_len is None:
            tmp_len = len(p)
            p = p[:4] + struct.pack("!H", tmp_len) + p[6:]
        if self.chksum is None:
            if isinstance(self.underlayer, IP):
                ck = in4_chksum(socket.IPPROTO_UDP, self.underlayer, p)
                # According to RFC768 if the result checksum is 0, it should be set to 0xFFFF  # noqa: E501
                if ck == 0:
                    ck = 0xFFFF
                p = p[:6] + struct.pack("!H", ck) + p[8:]
            elif isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr):  # noqa: E501
                ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_UDP, self.underlayer, p)  # noqa: E501
                # According to RFC2460 if the result checksum is 0, it should be set to 0xFFFF  # noqa: E501
                if ck == 0:
                    ck = 0xFFFF
                p = p[:6] + struct.pack("!H", ck) + p[8:]
            else:
                log_runtime.info(
                    "No IP underlayer to compute checksum. Leaving null."
                )
        return p

    def extract_padding(self, s):
        tmp_len = self.len - 8
        return s[:tmp_len], s[tmp_len:]

    def hashret(self):
        return self.payload.hashret()

    def answers(self, other):
        if not isinstance(other, UDP):
            return 0
        if conf.checkIPsrc:
            if self.dport != other.sport:
                return 0
        return self.payload.answers(other.payload)

    def mysummary(self):
        if isinstance(self.underlayer, IP):
            return self.underlayer.sprintf("UDP %IP.src%:%UDP.sport% > %IP.dst%:%UDP.dport%")  # noqa: E501
        elif isinstance(self.underlayer, scapy.layers.inet6.IPv6):
            return self.underlayer.sprintf("UDP %IPv6.src%:%UDP.sport% > %IPv6.dst%:%UDP.dport%")  # noqa: E501
        else:
            return self.sprintf("UDP %UDP.sport% > %UDP.dport%") class UDPerror(UDP):
    name = "UDP in ICMP"

    def answers(self, other):
        if not isinstance(other, UDP):
            return 0
        if conf.checkIPsrc:
            if not ((self.sport == other.sport) and
                    (self.dport == other.dport)):
                return 0
        return 1

    def mysummary(self):
        return Packet.mysummary(self) class CookedLinux(Packet):
    # Documentation: http://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL.html
    name = "cooked linux"
    # from wireshark's database
    fields_desc = [ShortEnumField("pkttype", 0, {0: "unicast",
                                                 1: "broadcast",
                                                 2: "multicast",
                                                 3: "unicast-to-another-host",
                                                 4: "sent-by-us"}),
                   XShortField("lladdrtype", 512),
                   ShortField("lladdrlen", 0),
                   StrFixedLenField("src", b"", 8),
                   XShortEnumField("proto", 0x800, ETHER_TYPES)] class Ether(Packet):
    name = "Ethernet"
    fields_desc = [DestMACField("dst"),
                   SourceMACField("src"),
                   XShortEnumField("type", 0x9000, ETHER_TYPES)]
    __slots__ = ["_defrag_pos"]

    def hashret(self):
        # type: () -> bytes
        return struct.pack("H", self.type) + self.payload.hashret()

    def answers(self, other):
        # type: (Packet) -> int
        if isinstance(other, Ether):
            if self.type == other.type:
                return self.payload.answers(other.payload)
        return 0

    def mysummary(self):
        # type: () -> str
        return self.sprintf("%src% > %dst% (%type%)")

    @classmethod
    def dispatch_hook(cls, _pkt=None, *args, **kargs):
        # type: (Optional[bytes], *Any, **Any) -> Type[Packet]
        if _pkt and len(_pkt) >= 14:
            if struct.unpack("!H", _pkt[12:14])[0] <= 1500:
                return Dot3
        return cls class GRE(Packet):
    name = "GRE"
    deprecated_fields = {
        "seqence_number": ("sequence_number", "2.4.4"),
    }
    fields_desc = [BitField("chksum_present", 0, 1),
                   BitField("routing_present", 0, 1),
                   BitField("key_present", 0, 1),
                   BitField("seqnum_present", 0, 1),
                   BitField("strict_route_source", 0, 1),
                   BitField("recursion_control", 0, 3),
                   BitField("flags", 0, 5),
                   BitField("version", 0, 3),
                   XShortEnumField("proto", 0x0000, ETHER_TYPES),
                   ConditionalField(XShortField("chksum", None), lambda pkt:pkt.chksum_present == 1 or pkt.routing_present == 1),  # noqa: E501
                   ConditionalField(XShortField("offset", None), lambda pkt:pkt.chksum_present == 1 or pkt.routing_present == 1),  # noqa: E501
                   ConditionalField(XIntField("key", None), lambda pkt:pkt.key_present == 1),  # noqa: E501
                   ConditionalField(XIntField("sequence_number", None), lambda pkt:pkt.seqnum_present == 1),  # noqa: E501
                   ]

    @classmethod
    def dispatch_hook(cls, _pkt=None, *args, **kargs):
        # type: (Optional[Any], *Any, **Any) -> Type[Packet]
        if _pkt and struct.unpack("!H", _pkt[2:4])[0] == 0x880b:
            return GRE_PPTP
        return cls

    def post_build(self, p, pay):
        # type: (bytes, bytes) -> bytes
        p += pay
        if self.chksum_present and self.chksum is None:
            c = checksum(p)
            p = p[:4] + chb((c >> 8) & 0xff) + chb(c & 0xff) + p[6:]
        return p class Loopback(Packet):
    r"""\*BSD loopback layer"""

    name = "Loopback"
    if consts.OPENBSD:
        fields_desc = [IntEnumField("type", 0x2, LOOPBACK_TYPES)]
    else:
        fields_desc = [LoIntEnumField("type", 0x2, LOOPBACK_TYPES)]
    __slots__ = ["_defrag_pos"] class SNAP(Packet):
    name = "SNAP"
    fields_desc = [OUIField("OUI", 0x000000),
                   XShortEnumField("code", 0x000, ETHER_TYPES)] @conf.commands.register
def bind_layers(lower,  # type: Type[Packet]
                upper,  # type: Type[Packet]
                __fval=None,  # type: Optional[Dict[str, int]]
                **fval  # type: Any
                ):
    # type: (...) -> None
    """Bind 2 layers on some specific fields' values.

    It makes the packet being built and dissected when the arguments
    are present.

    This function calls both bind_bottom_up and bind_top_down, with
    all passed arguments.

    Please have a look at their docs:
     - help(bind_bottom_up)
     - help(bind_top_down)
     """
    if __fval is not None:
        fval.update(__fval)
    bind_top_down(lower, upper, **fval)
    bind_bottom_up(lower, upper, **fval) class Packet(six.with_metaclass(Packet_metaclass,  # type: ignore
             BasePacket, _CanvasDumpExtended)):
    __slots__ = [
        "time", "sent_time", "name",
        "default_fields", "fields", "fieldtype",
        "overload_fields", "overloaded_fields",
        "packetfields",
        "original", "explicit", "raw_packet_cache",
        "raw_packet_cache_fields", "_pkt", "post_transforms",
        # then payload and underlayer
        "payload", "underlayer",
        "name",
        # used for sr()
        "_answered",
        # used when sniffing
        "direction", "sniffed_on",
        # handle snaplen Vs real length
        "wirelen",
    ]
    name = None
    fields_desc = []  # type: Sequence[AnyField]
    deprecated_fields = {}  # type: Dict[str, Tuple[str, str]]
    overload_fields = {}  # type: Dict[Type[Packet], Dict[str, Any]]
    payload_guess = []  # type: List[Tuple[Dict[str, Any], Type[Packet]]]
    show_indent = 1
    show_summary = True
    match_subclass = False
    class_dont_cache = {}  # type: Dict[Type[Packet], bool]
    class_packetfields = {}  # type: Dict[Type[Packet], Any]
    class_default_fields = {}  # type: Dict[Type[Packet], Dict[str, Any]]
    class_default_fields_ref = {}  # type: Dict[Type[Packet], List[str]]
    class_fieldtype = {}  # type: Dict[Type[Packet], Dict[str, AnyField]]  # noqa: E501

    @classmethod
    def from_hexcap(cls):
        # type: (Type[Packet]) -> Packet
        return cls(import_hexcap())

    @classmethod
    def upper_bonds(self):
        # type: () -> None
        for fval, upper in self.payload_guess:
            print("%-20s  %s" % (upper.__name__, ", ".join("%-12s" % ("%s=%r" % i) for i in six.iteritems(fval))))  # noqa: E501

    @classmethod
    def lower_bonds(self):
        # type: () -> None
        for lower, fval in six.iteritems(self._overload_fields):
            print("%-20s  %s" % (lower.__name__, ", ".join("%-12s" % ("%s=%r" % i) for i in six.iteritems(fval))))  # noqa: E501

    def __init__(self,
                 _pkt=b"",  # type: bytes
                 post_transform=None,  # type: Any
                 _internal=0,  # type: int
                 _underlayer=None,  # type: Optional[Packet]
                 **fields  # type: Any
                 ):
        # type: (...) -> None
        self.time = time.time()  # type: Union[EDecimal, float]
        self.sent_time = None  # type: Union[EDecimal, float, None]
        self.name = (self.__class__.__name__
                     if self._name is None else
                     self._name)
        self.default_fields = {}  # type: Dict[str, Any]
        self.overload_fields = self._overload_fields
        self.overloaded_fields = {}  # type: Dict[str, Any]
        self.fields = {}  # type: Dict[str, Any]
        self.fieldtype = {}  # type: Dict[str, AnyField]
        self.packetfields = []  # type: List[AnyField]
        self.payload = NoPayload()
        self.init_fields()
        self.underlayer = _underlayer
        self.original = _pkt
        self.explicit = 0
        self.raw_packet_cache = None  # type: Optional[bytes]
        self.raw_packet_cache_fields = None  # type: Optional[Dict[str, Any]]  # noqa: E501
        self.wirelen = None  # type: Optional[int]
        self.direction = None  # type: Optional[int]
        self.sniffed_on = None  # type: Optional[_GlobInterfaceType]
        if _pkt:
            self.dissect(_pkt)
            if not _internal:
                self.dissection_done(self)
        # We use this strange initialization so that the fields
        # are initialized in their declaration order.
        # It is required to always support MultipleTypeField
        for field in self.fields_desc:
            fname = field.name
            try:
                value = fields.pop(fname)
            except KeyError:
                continue
            self.fields[fname] = self.get_field(fname).any2i(self, value)
        # The remaining fields are unknown
        for fname in fields:
            if fname in self.deprecated_fields:
                # Resolve deprecated fields
                value = fields[fname]
                fname = self._resolve_alias(fname)
                self.fields[fname] = self.get_field(fname).any2i(self, value)
                continue
            raise AttributeError(fname)
        if isinstance(post_transform, list):
            self.post_transforms = post_transform
        elif post_transform is None:
            self.post_transforms = []
        else:
            self.post_transforms = [post_transform]

    _PickleType = Tuple[
        Union[EDecimal, float],
        Optional[Union[EDecimal, float, None]],
        Optional[int],
        Optional[_GlobInterfaceType],
        Optional[int]
    ]

    def __reduce__(self):
        # type: () -> Tuple[Type[Packet], Tuple[bytes], Packet._PickleType]
        """Used by pickling methods"""
        return (self.__class__, (self.build(),), (
            self.time,
            self.sent_time,
            self.direction,
            self.sniffed_on,
            self.wirelen,
        ))

    def __setstate__(self, state):
        # type: (Packet._PickleType) -> Packet
        """Rebuild state using pickable methods"""
        self.time = state[0]
        self.sent_time = state[1]
        self.direction = state[2]
        self.sniffed_on = state[3]
        self.wirelen = state[4]
        return self

    def __deepcopy__(self,
                     memo,  # type: Any
                     ):
        # type: (...) -> Packet
        """Used by copy.deepcopy"""
        return self.copy()

    def init_fields(self):
        # type: () -> None
        """
        Initialize each fields of the fields_desc dict
        """

        if self.class_dont_cache.get(self.__class__, False):
            self.do_init_fields(self.fields_desc)
        else:
            self.do_init_cached_fields()

    def do_init_fields(self,
                       flist,  # type: Sequence[AnyField]
                       ):
        # type: (...) -> None
        """
        Initialize each fields of the fields_desc dict
        """
        default_fields = {}
        for f in flist:
            default_fields[f.name] = copy.deepcopy(f.default)
            self.fieldtype[f.name] = f
            if f.holds_packets:
                self.packetfields.append(f)
        # We set default_fields last to avoid race issues
        self.default_fields = default_fields

    def do_init_cached_fields(self):
        # type: () -> None
        """
        Initialize each fields of the fields_desc dict, or use the cached
        fields information
        """

        cls_name = self.__class__

        # Build the fields information
        if Packet.class_default_fields.get(cls_name, None) is None:
            self.prepare_cached_fields(self.fields_desc)

        # Use fields information from cache
        default_fields = Packet.class_default_fields.get(cls_name, None)
        if default_fields:
            self.default_fields = default_fields
            self.fieldtype = Packet.class_fieldtype[cls_name]
            self.packetfields = Packet.class_packetfields[cls_name]

            # Deepcopy default references
            for fname in Packet.class_default_fields_ref[cls_name]:
                value = self.default_fields[fname]
                try:
                    self.fields[fname] = value.copy()
                except AttributeError:
                    # Python 2.7 - list only
                    self.fields[fname] = value[:]

    def prepare_cached_fields(self, flist):
        # type: (Sequence[AnyField]) -> None
        """
        Prepare the cached fields of the fields_desc dict
        """

        cls_name = self.__class__

        # Fields cache initialization
        if not flist:
            return

        class_default_fields = dict()
        class_default_fields_ref = list()
        class_fieldtype = dict()
        class_packetfields = list()

        # Fields initialization
        for f in flist:
            if isinstance(f, MultipleTypeField):
                # Abort
                self.class_dont_cache[cls_name] = True
                self.do_init_fields(self.fields_desc)
                return

            tmp_copy = copy.deepcopy(f.default)
            class_default_fields[f.name] = tmp_copy
            class_fieldtype[f.name] = f
            if f.holds_packets:
                class_packetfields.append(f)

            # Remember references
            if isinstance(f.default, (list, dict, set, RandField, Packet)):
                class_default_fields_ref.append(f.name)

        # Apply
        Packet.class_default_fields_ref[cls_name] = class_default_fields_ref
        Packet.class_fieldtype[cls_name] = class_fieldtype
        Packet.class_packetfields[cls_name] = class_packetfields
        # Last to avoid racing issues
        Packet.class_default_fields[cls_name] = class_default_fields

    def dissection_done(self, pkt):
        # type: (Packet) -> None
        """DEV: will be called after a dissection is completed"""
        self.post_dissection(pkt)
        self.payload.dissection_done(pkt)

    def post_dissection(self, pkt):
        # type: (Packet) -> None
        """DEV: is called after the dissection of the whole packet"""
        pass

    def get_field(self, fld):
        # type: (str) -> AnyField
        """DEV: returns the field instance from the name of the field"""
        return self.fieldtype[fld]

    def add_payload(self, payload):
        # type: (Union[Packet, bytes]) -> None
        if payload is None:
            return
        elif not isinstance(self.payload, NoPayload):
            self.payload.add_payload(payload)
        else:
            if isinstance(payload, Packet):
                self.payload = payload
                payload.add_underlayer(self)
                for t in self.aliastypes:
                    if t in payload.overload_fields:
                        self.overloaded_fields = payload.overload_fields[t]
                        break
            elif isinstance(payload, (bytes, str, bytearray, memoryview)):
                self.payload = conf.raw_layer(load=bytes_encode(payload))
            else:
                raise TypeError("payload must be 'Packet', 'bytes', 'str', 'bytearray', or 'memoryview', not [%s]" % repr(payload))  # noqa: E501

    def remove_payload(self):
        # type: () -> None
        self.payload.remove_underlayer(self)
        self.payload = NoPayload()
        self.overloaded_fields = {}

    def add_underlayer(self, underlayer):
        # type: (Packet) -> None
        self.underlayer = underlayer

    def remove_underlayer(self, other):
        # type: (Packet) -> None
        self.underlayer = None

    def copy(self):
        # type: () -> Packet
        """Returns a deep copy of the instance."""
        clone = self.__class__()
        clone.fields = self.copy_fields_dict(self.fields)
        clone.default_fields = self.copy_fields_dict(self.default_fields)
        clone.overloaded_fields = self.overloaded_fields.copy()
        clone.underlayer = self.underlayer
        clone.explicit = self.explicit
        clone.raw_packet_cache = self.raw_packet_cache
        clone.raw_packet_cache_fields = self.copy_fields_dict(
            self.raw_packet_cache_fields
        )
        clone.wirelen = self.wirelen
        clone.post_transforms = self.post_transforms[:]
        clone.payload = self.payload.copy()
        clone.payload.add_underlayer(clone)
        clone.time = self.time
        return clone

    def _resolve_alias(self, attr):
        # type: (str) -> str
        new_attr, version = self.deprecated_fields[attr]
        warnings.warn(
            "%s has been deprecated in favor of %s since %s !" % (
                attr, new_attr, version
            ), DeprecationWarning
        )
        return new_attr

    def getfieldval(self, attr):
        # type: (str) -> Any
        if self.deprecated_fields and attr in self.deprecated_fields:
            attr = self._resolve_alias(attr)
        if attr in self.fields:
            return self.fields[attr]
        if attr in self.overloaded_fields:
            return self.overloaded_fields[attr]
        if attr in self.default_fields:
            return self.default_fields[attr]
        return self.payload.getfieldval(attr)

    def getfield_and_val(self, attr):
        # type: (str) -> Tuple[AnyField, Any]
        if self.deprecated_fields and attr in self.deprecated_fields:
            attr = self._resolve_alias(attr)
        if attr in self.fields:
            return self.get_field(attr), self.fields[attr]
        if attr in self.overloaded_fields:
            return self.get_field(attr), self.overloaded_fields[attr]
        if attr in self.default_fields:
            return self.get_field(attr), self.default_fields[attr]
        raise ValueError

    def __getattr__(self, attr):
        # type: (str) -> Any
        try:
            fld, v = self.getfield_and_val(attr)
        except ValueError:
            return self.payload.__getattr__(attr)
        if fld is not None:
            return fld.i2h(self, v)
        return v

    def setfieldval(self, attr, val):
        # type: (str, Any) -> None
        if self.deprecated_fields and attr in self.deprecated_fields:
            attr = self._resolve_alias(attr)
        if attr in self.default_fields:
            fld = self.get_field(attr)
            if fld is None:
                any2i = lambda x, y: y  # type: Callable[..., Any]
            else:
                any2i = fld.any2i
            self.fields[attr] = any2i(self, val)
            self.explicit = 0
            self.raw_packet_cache = None
            self.raw_packet_cache_fields = None
            self.wirelen = None
        elif attr == "payload":
            self.remove_payload()
            self.add_payload(val)
        else:
            self.payload.setfieldval(attr, val)

    def __setattr__(self, attr, val):
        # type: (str, Any) -> None
        if attr in self.__all_slots__:
            return object.__setattr__(self, attr, val)
        try:
            return self.setfieldval(attr, val)
        except AttributeError:
            pass
        return object.__setattr__(self, attr, val)

    def delfieldval(self, attr):
        # type: (str) -> None
        if attr in self.fields:
            del(self.fields[attr])
            self.explicit = 0  # in case a default value must be explicit
            self.raw_packet_cache = None
            self.raw_packet_cache_fields = None
            self.wirelen = None
        elif attr in self.default_fields:
            pass
        elif attr == "payload":
            self.remove_payload()
        else:
            self.payload.delfieldval(attr)

    def __delattr__(self, attr):
        # type: (str) -> None
        if attr == "payload":
            return self.remove_payload()
        if attr in self.__all_slots__:
            return object.__delattr__(self, attr)
        try:
            return self.delfieldval(attr)
        except AttributeError:
            pass
        return object.__delattr__(self, attr)

    def _superdir(self):
        # type: () -> Set[str]
        """
        Return a list of slots and methods, including those from subclasses.
        """
        attrs = set()
        cls = self.__class__
        if hasattr(cls, '__all_slots__'):
            attrs.update(cls.__all_slots__)
        for bcls in cls.__mro__:
            if hasattr(bcls, '__dict__'):
                attrs.update(bcls.__dict__)
        return attrs

    def __dir__(self):
        # type: () -> List[str]
        """
        Add fields to tab completion list.
        """
        return sorted(itertools.chain(self._superdir(), self.default_fields))

    def __repr__(self):
        # type: () -> str
        s = ""
        ct = conf.color_theme
        for f in self.fields_desc:
            if isinstance(f, ConditionalField) and not f._evalcond(self):
                continue
            if f.name in self.fields:
                fval = self.fields[f.name]
                if isinstance(fval, (list, dict, set)) and len(fval) == 0:
                    continue
                val = f.i2repr(self, fval)
            elif f.name in self.overloaded_fields:
                fover = self.overloaded_fields[f.name]
                if isinstance(fover, (list, dict, set)) and len(fover) == 0:
                    continue
                val = f.i2repr(self, fover)
            else:
                continue
            if isinstance(f, Emph) or f in conf.emph:
                ncol = ct.emph_field_name
                vcol = ct.emph_field_value
            else:
                ncol = ct.field_name
                vcol = ct.field_value

            s += " %s%s%s" % (ncol(f.name),
                              ct.punct("="),
                              vcol(val))
        return "%s%s %s %s%s%s" % (ct.punct("<"),
                                   ct.layer_name(self.__class__.__name__),
                                   s,
                                   ct.punct("|"),
                                   repr(self.payload),
                                   ct.punct(">"))

    if six.PY2:
        def __str__(self):
            # type: () -> str
            return self.build()
    else:
        def __str__(self):
            # type: () -> str
            warning("Calling str(pkt) on Python 3 makes no sense!")
            return str(self.build())

    def __bytes__(self):
        # type: () -> bytes
        return self.build()

    def __div__(self, other):
        # type: (Any) -> Packet
        if isinstance(other, Packet):
            cloneA = self.copy()
            cloneB = other.copy()
            cloneA.add_payload(cloneB)
            return cloneA
        elif isinstance(other, (bytes, str, bytearray, memoryview)):
            return self / conf.raw_layer(load=bytes_encode(other))
        else:
            return other.__rdiv__(self)  # type: ignore
    __truediv__ = __div__

    def __rdiv__(self, other):
        # type: (Any) -> Packet
        if isinstance(other, (bytes, str, bytearray, memoryview)):
            return conf.raw_layer(load=bytes_encode(other)) / self
        else:
            raise TypeError
    __rtruediv__ = __rdiv__

    def __mul__(self, other):
        # type: (Any) -> List[Packet]
        if isinstance(other, int):
            return [self] * other
        else:
            raise TypeError

    def __rmul__(self, other):
        # type: (Any) -> List[Packet]
        return self.__mul__(other)

    def __nonzero__(self):
        # type: () -> bool
        return True
    __bool__ = __nonzero__

    def __len__(self):
        # type: () -> int
        return len(self.__bytes__())

    def copy_field_value(self, fieldname, value):
        # type: (str, Any) -> Any
        return self.get_field(fieldname).do_copy(value)

    def copy_fields_dict(self, fields):
        # type: (_T) -> _T
        if fields is None:
            return None
        return {fname: self.copy_field_value(fname, fval)
                for fname, fval in six.iteritems(fields)}

    def clear_cache(self):
        # type: () -> None
        """Clear the raw packet cache for the field and all its subfields"""
        self.raw_packet_cache = None
        for fld, fval in six.iteritems(self.fields):
            fld = self.get_field(fld)
            if fld.holds_packets:
                if isinstance(fval, Packet):
                    fval.clear_cache()
                elif isinstance(fval, list):
                    for fsubval in fval:
                        fsubval.clear_cache()
        self.payload.clear_cache()

    def self_build(self):
        # type: () -> bytes
        """
        Create the default layer regarding fields_desc dict

        :param field_pos_list:
        """
        if self.raw_packet_cache is not None:
            for fname, fval in six.iteritems(self.raw_packet_cache_fields):
                if self.getfieldval(fname) != fval:
                    self.raw_packet_cache = None
                    self.raw_packet_cache_fields = None
                    self.wirelen = None
                    break
            if self.raw_packet_cache is not None:
                return self.raw_packet_cache
        p = b""
        for f in self.fields_desc:
            val = self.getfieldval(f.name)
            if isinstance(val, RawVal):
                p += bytes(val)
            else:
                try:
                    p = f.addfield(self, p, val)
                except Exception as ex:
                    try:
                        ex.args = (
                            "While disescting field '%s': " % f.name +
                            ex.args[0],
                        ) + ex.args[1:]
                    except (AttributeError, IndexError):
                        pass
                    raise ex
        return p

    def do_build_payload(self):
        # type: () -> bytes
        """
        Create the default version of the payload layer

        :return: a string of payload layer
        """
        return self.payload.do_build()

    def do_build(self):
        # type: () -> bytes
        """
        Create the default version of the layer

        :return: a string of the packet with the payload
        """
        if not self.explicit:
            self = next(iter(self))
        pkt = self.self_build()
        for t in self.post_transforms:
            pkt = t(pkt)
        pay = self.do_build_payload()
        if self.raw_packet_cache is None:
            return self.post_build(pkt, pay)
        else:
            return pkt + pay

    def build_padding(self):
        # type: () -> bytes
        return self.payload.build_padding()

    def build(self):
        # type: () -> bytes
        """
        Create the current layer

        :return: string of the packet with the payload
        """
        p = self.do_build()
        p += self.build_padding()
        p = self.build_done(p)
        return p

    def post_build(self, pkt, pay):
        # type: (bytes, bytes) -> bytes
        """
        DEV: called right after the current layer is build.

        :param str pkt: the current packet (build by self_build function)
        :param str pay: the packet payload (build by do_build_payload function)
        :return: a string of the packet with the payload
        """
        return pkt + pay

    def build_done(self, p):
        # type: (bytes) -> bytes
        return self.payload.build_done(p)

    def do_build_ps(self):
        # type: () -> Tuple[bytes, List[Tuple[Packet, List[Tuple[Field[Any, Any], str, bytes]]]]]  # noqa: E501
        p = b""
        pl = []
        q = b""
        for f in self.fields_desc:
            if isinstance(f, ConditionalField) and not f._evalcond(self):
                continue
            p = f.addfield(self, p, self.getfieldval(f.name))
            if isinstance(p, bytes):
                r = p[len(q):]
                q = p
            else:
                r = b""
            pl.append((f, f.i2repr(self, self.getfieldval(f.name)), r))

        pkt, lst = self.payload.build_ps(internal=1)
        p += pkt
        lst.append((self, pl))

        return p, lst

    def build_ps(self, internal=0):
        # type: (int) -> Tuple[bytes, List[Tuple[Packet, List[Tuple[Any, Any, bytes]]]]]  # noqa: E501
        p, lst = self.do_build_ps()
#        if not internal:
#            pkt = self
#            while pkt.haslayer(conf.padding_layer):
#                pkt = pkt.getlayer(conf.padding_layer)
#                lst.append( (pkt, [ ("loakjkjd", pkt.load, pkt.load) ] ) )
#                p += pkt.load
#                pkt = pkt.payload
        return p, lst

    def canvas_dump(self, layer_shift=0, rebuild=1):
        # type: (int, int) -> pyx.canvas.canvas
        if PYX == 0:
            raise ImportError("PyX and its dependencies must be installed")
        canvas = pyx.canvas.canvas()
        if rebuild:
            _, t = self.__class__(raw(self)).build_ps()
        else:
            _, t = self.build_ps()
        YTXTI = len(t)
        for _, l in t:
            YTXTI += len(l)
        YTXT = float(YTXTI)
        YDUMP = YTXT

        XSTART = 1
        XDSTART = 10
        y = 0.0
        yd = 0.0
        XMUL = 0.55
        YMUL = 0.4

        backcolor = colgen(0.6, 0.8, 1.0, trans=pyx.color.rgb)
        forecolor = colgen(0.2, 0.5, 0.8, trans=pyx.color.rgb)
#        backcolor=makecol(0.376, 0.729, 0.525, 1.0)

        def hexstr(x):
            # type: (bytes) -> str
            return " ".join("%02x" % orb(c) for c in x)

        def make_dump_txt(x, y, txt):
            # type: (int, float, bytes) -> pyx.text.text
            return pyx.text.text(
                XDSTART + x * XMUL,
                (YDUMP - y) * YMUL,
                r"\tt{%s}" % hexstr(txt),
                [pyx.text.size.Large]
            )

        def make_box(o):
            # type: (pyx.bbox.bbox) -> pyx.bbox.bbox
            return pyx.box.rect(
                o.left(), o.bottom(), o.width(), o.height(),
                relcenter=(0.5, 0.5)
            )

        def make_frame(lst):
            # type: (List[Any]) -> pyx.path.path
            if len(lst) == 1:
                b = lst[0].bbox()
                b.enlarge(pyx.unit.u_pt)
                return b.path()
            else:
                fb = lst[0].bbox()
                fb.enlarge(pyx.unit.u_pt)
                lb = lst[-1].bbox()
                lb.enlarge(pyx.unit.u_pt)
                if len(lst) == 2 and fb.left() > lb.right():
                    return pyx.path.path(pyx.path.moveto(fb.right(), fb.top()),
                                         pyx.path.lineto(fb.left(), fb.top()),
                                         pyx.path.lineto(fb.left(), fb.bottom()),  # noqa: E501
                                         pyx.path.lineto(fb.right(), fb.bottom()),  # noqa: E501
                                         pyx.path.moveto(lb.left(), lb.top()),
                                         pyx.path.lineto(lb.right(), lb.top()),
                                         pyx.path.lineto(lb.right(), lb.bottom()),  # noqa: E501
                                         pyx.path.lineto(lb.left(), lb.bottom()))  # noqa: E501
                else:
                    # XXX
                    gb = lst[1].bbox()
                    if gb != lb:
                        gb.enlarge(pyx.unit.u_pt)
                    kb = lst[-2].bbox()
                    if kb != gb and kb != lb:
                        kb.enlarge(pyx.unit.u_pt)
                    return pyx.path.path(pyx.path.moveto(fb.left(), fb.top()),
                                         pyx.path.lineto(fb.right(), fb.top()),
                                         pyx.path.lineto(fb.right(), kb.bottom()),  # noqa: E501
                                         pyx.path.lineto(lb.right(), kb.bottom()),  # noqa: E501
                                         pyx.path.lineto(lb.right(), lb.bottom()),  # noqa: E501
                                         pyx.path.lineto(lb.left(), lb.bottom()),  # noqa: E501
                                         pyx.path.lineto(lb.left(), gb.top()),
                                         pyx.path.lineto(fb.left(), gb.top()),
                                         pyx.path.closepath(),)

        def make_dump(s,   # type: bytes
                      shift=0,  # type: int
                      y=0.,  # type: float
                      col=None,  # type: pyx.color.color
                      bkcol=None,  # type: pyx.color.color
                      large=16  # type: int
                      ):
            # type: (...) -> Tuple[pyx.canvas.canvas, pyx.bbox.bbox, int, float]  # noqa: E501
            c = pyx.canvas.canvas()
            tlist = []
            while s:
                dmp, s = s[:large - shift], s[large - shift:]
                txt = make_dump_txt(shift, y, dmp)
                tlist.append(txt)
                shift += len(dmp)
                if shift >= 16:
                    shift = 0
                    y += 1
            if col is None:
                col = pyx.color.rgb.red
            if bkcol is None:
                bkcol = pyx.color.rgb.white
            c.stroke(make_frame(tlist), [col, pyx.deco.filled([bkcol]), pyx.style.linewidth.Thick])  # noqa: E501
            for txt in tlist:
                c.insert(txt)
            return c, tlist[-1].bbox(), shift, y

        last_shift, last_y = 0, 0.0
        while t:
            bkcol = next(backcolor)
            proto, fields = t.pop()
            y += 0.5
            pt = pyx.text.text(
                XSTART,
                (YTXT - y) * YMUL,
                r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(
                    str(proto.name)
                ),
                [pyx.text.size.Large]
            )
            y += 1
            ptbb = pt.bbox()
            ptbb.enlarge(pyx.unit.u_pt * 2)
            canvas.stroke(ptbb.path(), [pyx.color.rgb.black, pyx.deco.filled([bkcol])])  # noqa: E501
            canvas.insert(pt)
            for field, fval, fdump in fields:
                col = next(forecolor)
                ft = pyx.text.text(XSTART, (YTXT - y) * YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(field.name))  # noqa: E501
                if isinstance(field, BitField):
                    fsize = '%sb' % field.size
                else:
                    fsize = '%sB' % len(fdump)
                if (hasattr(field, 'field') and
                        'LE' in field.field.__class__.__name__[:3] or
                        'LE' in field.__class__.__name__[:3]):
                    fsize = r'$\scriptstyle\langle$' + fsize
                st = pyx.text.text(XSTART + 3.4, (YTXT - y) * YMUL, r"\font\cmbxfont=cmssbx10 scaled 600\cmbxfont{%s}" % fsize, [pyx.text.halign.boxright])  # noqa: E501
                if isinstance(fval, str):
                    if len(fval) > 18:
                        fval = fval[:18] + "[...]"
                else:
                    fval = ""
                vt = pyx.text.text(XSTART + 3.5, (YTXT - y) * YMUL, r"\font\cmssfont=cmss10\cmssfont{%s}" % tex_escape(fval))  # noqa: E501
                y += 1.0
                if fdump:
                    dt, target, last_shift, last_y = make_dump(fdump, last_shift, last_y, col, bkcol)  # noqa: E501

                    dtb = target
                    vtb = vt.bbox()
                    bxvt = make_box(vtb)
                    bxdt = make_box(dtb)
                    dtb.enlarge(pyx.unit.u_pt)
                    try:
                        if yd < 0:
                            cnx = pyx.connector.curve(bxvt, bxdt, absangle1=0, absangle2=-90)  # noqa: E501
                        else:
                            cnx = pyx.connector.curve(bxvt, bxdt, absangle1=0, absangle2=90)  # noqa: E501
                    except Exception:
                        pass
                    else:
                        canvas.stroke(cnx, [pyx.style.linewidth.thin, pyx.deco.earrow.small, col])  # noqa: E501

                    canvas.insert(dt)

                canvas.insert(ft)
                canvas.insert(st)
                canvas.insert(vt)
            last_y += layer_shift

        return canvas

    def extract_padding(self, s):
        # type: (bytes) -> Tuple[bytes, Optional[bytes]]
        """
        DEV: to be overloaded to extract current layer's padding.

        :param str s: the current layer
        :return: a couple of strings (actual layer, padding)
        """
        return s, None

    def post_dissect(self, s):
        # type: (bytes) -> bytes
        """DEV: is called right after the current layer has been dissected"""
        return s

    def pre_dissect(self, s):
        # type: (bytes) -> bytes
        """DEV: is called right before the current layer is dissected"""
        return s

    def do_dissect(self, s):
        # type: (bytes) -> bytes
        _raw = s
        self.raw_packet_cache_fields = {}
        for f in self.fields_desc:
            if not s:
                break
            s, fval = f.getfield(self, s)
            # Skip unused ConditionalField
            if isinstance(f, ConditionalField) and fval is None:
                continue
            # We need to track fields with mutable values to discard
            # .raw_packet_cache when needed.
            if f.islist or f.holds_packets or f.ismutable:
                self.raw_packet_cache_fields[f.name] = f.do_copy(fval)
            self.fields[f.name] = fval
        self.raw_packet_cache = _raw[:-len(s)] if s else _raw
        self.explicit = 1
        return s

    def do_dissect_payload(self, s):
        # type: (bytes) -> None
        """
        Perform the dissection of the layer's payload

        :param str s: the raw layer
        """
        if s:
            cls = self.guess_payload_class(s)
            try:
                p = cls(s, _internal=1, _underlayer=self)
            except KeyboardInterrupt:
                raise
            except Exception:
                if conf.debug_dissector:
                    if issubtype(cls, Packet):
                        log_runtime.error("%s dissector failed", cls.__name__)
                    else:
                        log_runtime.error("%s.guess_payload_class() returned "
                                          "[%s]",
                                          self.__class__.__name__, repr(cls))
                    if cls is not None:
                        raise
                p = conf.raw_layer(s, _internal=1, _underlayer=self)
            self.add_payload(p)

    def dissect(self, s):
        # type: (bytes) -> None
        s = self.pre_dissect(s)

        s = self.do_dissect(s)

        s = self.post_dissect(s)

        payl, pad = self.extract_padding(s)
        self.do_dissect_payload(payl)
        if pad and conf.padding:
            self.add_payload(conf.padding_layer(pad))

    def guess_payload_class(self, payload):
        # type: (bytes) -> Type[Packet]
        """
        DEV: Guesses the next payload class from layer bonds.
        Can be overloaded to use a different mechanism.

        :param str payload: the layer's payload
        :return: the payload class
        """
        for t in self.aliastypes:
            for fval, cls in t.payload_guess:
                try:
                    if all(v == self.getfieldval(k)
                           for k, v in six.iteritems(fval)):
                        return cls  # type: ignore
                except AttributeError:
                    pass
        return self.default_payload_class(payload)

    def default_payload_class(self, payload):
        # type: (bytes) -> Type[Packet]
        """
        DEV: Returns the default payload class if nothing has been found by the
        guess_payload_class() method.

        :param str payload: the layer's payload
        :return: the default payload class define inside the configuration file
        """
        return conf.raw_layer

    def hide_defaults(self):
        # type: () -> None
        """Removes fields' values that are the same as default values."""
        # use list(): self.fields is modified in the loop
        for k, v in list(six.iteritems(self.fields)):
            v = self.fields[k]
            if k in self.default_fields:
                if self.default_fields[k] == v:
                    del self.fields[k]
        self.payload.hide_defaults()

    def clone_with(self, payload=None, **kargs):
        # type: (Optional[Any], **Any) -> Any
        pkt = self.__class__()
        pkt.explicit = 1
        pkt.fields = kargs
        pkt.default_fields = self.copy_fields_dict(self.default_fields)
        pkt.overloaded_fields = self.overloaded_fields.copy()
        pkt.time = self.time
        pkt.underlayer = self.underlayer
        pkt.post_transforms = self.post_transforms
        pkt.raw_packet_cache = self.raw_packet_cache
        pkt.raw_packet_cache_fields = self.copy_fields_dict(
            self.raw_packet_cache_fields
        )
        pkt.wirelen = self.wirelen
        if payload is not None:
            pkt.add_payload(payload)
        return pkt

    def __iter__(self):
        # type: () -> Iterator[Packet]
        """Iterates through all sub-packets generated by this Packet."""
        def loop(todo, done, self=self):
            # type: (List[str], Dict[str, Any], Any) -> Iterator[Packet]
            if todo:
                eltname = todo.pop()
                elt = self.getfieldval(eltname)
                if not isinstance(elt, Gen):
                    if self.get_field(eltname).islist:
                        elt = SetGen([elt])
                    else:
                        elt = SetGen(elt)
                for e in elt:
                    done[eltname] = e
                    for x in loop(todo[:], done):
                        yield x
            else:
                if isinstance(self.payload, NoPayload):
                    payloads = SetGen([None])  # type: SetGen[Packet]
                else:
                    payloads = self.payload
                for payl in payloads:
                    # Let's make sure subpackets are consistent
                    done2 = done.copy()
                    for k in done2:
                        if isinstance(done2[k], VolatileValue):
                            done2[k] = done2[k]._fix()
                    pkt = self.clone_with(payload=payl, **done2)
                    yield pkt

        if self.explicit or self.raw_packet_cache is not None:
            todo = []
            done = self.fields
        else:
            todo = [k for (k, v) in itertools.chain(six.iteritems(self.default_fields),  # noqa: E501
                                                    six.iteritems(self.overloaded_fields))  # noqa: E501
                    if isinstance(v, VolatileValue)] + list(self.fields)
            done = {}
        return loop(todo, done)

    def iterpayloads(self):
        # type: () -> Iterator[Packet]
        """Used to iter through the payloads of a Packet.
        Useful for DNS or 802.11 for instance.
        """
        yield self
        current = self
        while current.payload:
            current = current.payload
            yield current

    def __gt__(self, other):
        # type: (Packet) -> int
        """True if other is an answer from self (self ==> other)."""
        if isinstance(other, Packet):
            return other < self
        elif isinstance(other, bytes):
            return 1
        else:
            raise TypeError((self, other))

    def __lt__(self, other):
        # type: (Packet) -> int
        """True if self is an answer from other (other ==> self)."""
        if isinstance(other, Packet):
            return self.answers(other)
        elif isinstance(other, bytes):
            return 1
        else:
            raise TypeError((self, other))

    def __eq__(self, other):
        # type: (Any) -> bool
        if not isinstance(other, self.__class__):
            return False
        for f in self.fields_desc:
            if f not in other.fields_desc:
                return False
            if self.getfieldval(f.name) != other.getfieldval(f.name):
                return False
        return self.payload == other.payload

    def __ne__(self, other):
        # type: (Any) -> bool
        return not self.__eq__(other)

    # Note: setting __hash__ to None is the standard way
    # of making an object un-hashable. mypy doesn't know that
    __hash__ = None  # type: ignore

    def hashret(self):
        # type: () -> bytes
        """DEV: returns a string that has the same value for a request
        and its answer."""
        return self.payload.hashret()

    def answers(self, other):
        # type: (Packet) -> int
        """DEV: true if self is an answer from other"""
        if other.__class__ == self.__class__:
            return self.payload.answers(other.payload)
        return 0

    def layers(self):
        # type: () -> List[Type[Packet]]
        """returns a list of layer classes (including subclasses) in this packet"""  # noqa: E501
        layers = []
        lyr = self  # type: Optional[Packet]
        while lyr:
            layers.append(lyr.__class__)
            lyr = lyr.payload.getlayer(0, _subclass=True)
        return layers

    def haslayer(self, cls, _subclass=None):
        # type: (Union[Type[Packet], str], Optional[bool]) -> int
        """
        true if self has a layer that is an instance of cls.
        Superseded by "cls in self" syntax.
        """
        if _subclass is None:
            _subclass = self.match_subclass or None
        if _subclass:
            match = issubtype
        else:
            match = lambda cls1, cls2: bool(cls1 == cls2)
        if cls is None or match(self.__class__, cls) \
           or cls in [self.__class__.__name__, self._name]:
            return True
        for f in self.packetfields:
            fvalue_gen = self.getfieldval(f.name)
            if fvalue_gen is None:
                continue
            if not f.islist:
                fvalue_gen = SetGen(fvalue_gen, _iterpacket=0)
            for fvalue in fvalue_gen:
                if isinstance(fvalue, Packet):
                    ret = fvalue.haslayer(cls, _subclass=_subclass)
                    if ret:
                        return ret
        return self.payload.haslayer(cls, _subclass=_subclass)

    def getlayer(self,
                 cls,  # type: Union[int, Type[Packet], str]
                 nb=1,  # type: int
                 _track=None,  # type: Optional[List[int]]
                 _subclass=None,  # type: Optional[bool]
                 **flt  # type: Any
                 ):
        # type: (...) -> Optional[Packet]
        """Return the nb^th layer that is an instance of cls, matching flt
values.
        """
        if _subclass is None:
            _subclass = self.match_subclass or None
        if _subclass:
            match = issubtype
        else:
            match = lambda cls1, cls2: bool(cls1 == cls2)
        # Note:
        # cls can be int, packet, str
        # string_class_name can be packet, str (packet or packet+field)
        # class_name can be packet, str (packet only)
        if isinstance(cls, int):
            nb = cls + 1
            string_class_name = ""  # type: Union[Type[Packet], str]
        else:
            string_class_name = cls
        class_name = ""  # type: Union[Type[Packet], str]
        fld = None  # type: Optional[str]
        if isinstance(string_class_name, str) and "." in string_class_name:
            class_name, fld = string_class_name.split(".", 1)
        else:
            class_name, fld = string_class_name, None
        if not class_name or match(self.__class__, class_name) \
           or class_name in [self.__class__.__name__, self._name]:
            if all(self.getfieldval(fldname) == fldvalue
                   for fldname, fldvalue in six.iteritems(flt)):
                if nb == 1:
                    if fld is None:
                        return self
                    else:
                        return self.getfieldval(fld)  # type: ignore
                else:
                    nb -= 1
        for f in self.packetfields:
            fvalue_gen = self.getfieldval(f.name)
            if fvalue_gen is None:
                continue
            if not f.islist:
                fvalue_gen = SetGen(fvalue_gen, _iterpacket=0)
            for fvalue in fvalue_gen:
                if isinstance(fvalue, Packet):
                    track = []  # type: List[int]
                    ret = fvalue.getlayer(class_name, nb=nb, _track=track,
                                          _subclass=_subclass, **flt)
                    if ret is not None:
                        return ret
                    nb = track[0]
        return self.payload.getlayer(class_name, nb=nb, _track=_track,
                                     _subclass=_subclass, **flt)

    def firstlayer(self):
        # type: () -> Packet
        q = self
        while q.underlayer is not None:
            q = q.underlayer
        return q

    def __getitem__(self, cls):
        # type: (Union[Type[Packet], str]) -> Any
        if isinstance(cls, slice):
            lname = cls.start
            if cls.stop:
                ret = self.getlayer(cls.start, nb=cls.stop, **(cls.step or {}))
            else:
                ret = self.getlayer(cls.start, **(cls.step or {}))
        else:
            lname = cls
            ret = self.getlayer(cls)
        if ret is None:
            if isinstance(lname, type):
                name = lname.__name__
            elif not isinstance(lname, bytes):
                name = repr(lname)
            else:
                name = cast(str, lname)
            raise IndexError("Layer [%s] not found" % name)
        return ret

    def __delitem__(self, cls):
        # type: (Type[Packet]) -> None
        del(self[cls].underlayer.payload)

    def __setitem__(self, cls, val):
        # type: (Type[Packet], Packet) -> None
        self[cls].underlayer.payload = val

    def __contains__(self, cls):
        # type: (Union[Type[Packet], str]) -> int
        """
        "cls in self" returns true if self has a layer which is an
        instance of cls.
        """
        return self.haslayer(cls)

    def route(self):
        # type: () -> Tuple[Optional[str], Optional[str], Optional[str]]
        return self.payload.route()

    def fragment(self, *args, **kargs):
        # type: (*Any, **Any) -> List[Packet]
        return self.payload.fragment(*args, **kargs)

    def display(self, *args, **kargs):  # Deprecated. Use show()
        # type: (*Any, **Any) -> None
        """Deprecated. Use show() method."""
        self.show(*args, **kargs)

    def _show_or_dump(self,
                      dump=False,  # type: bool
                      indent=3,  # type: int
                      lvl="",  # type: str
                      label_lvl="",  # type: str
                      first_call=True  # type: bool
                      ):
        # type: (...) -> Optional[str]
        """
        Internal method that shows or dumps a hierarchical view of a packet.
        Called by show.

        :param dump: determine if it prints or returns the string value
        :param int indent: the size of indentation for each layer
        :param str lvl: additional information about the layer lvl
        :param str label_lvl: additional information about the layer fields
        :param first_call: determine if the current function is the first
        :return: return a hierarchical view if dump, else print it
        """

        if dump:
            from scapy.themes import AnsiColorTheme
            ct = AnsiColorTheme()  # No color for dump output
        else:
            ct = conf.color_theme
        s = "%s%s %s %s \n" % (label_lvl,
                               ct.punct("###["),
                               ct.layer_name(self.name),
                               ct.punct("]###"))
        for f in self.fields_desc:
            if isinstance(f, ConditionalField) and not f._evalcond(self):
                continue
            if isinstance(f, Emph) or f in conf.emph:
                ncol = ct.emph_field_name
                vcol = ct.emph_field_value
            else:
                ncol = ct.field_name
                vcol = ct.field_value
            fvalue = self.getfieldval(f.name)
            if isinstance(fvalue, Packet) or (f.islist and f.holds_packets and isinstance(fvalue, list)):  # noqa: E501
                pad = max(0, 10 - len(f.name)) * " "
                s += "%s  \\%s%s\\\n" % (label_lvl + lvl, ncol(f.name), pad)
                fvalue_gen = SetGen(
                    fvalue,
                    _iterpacket=0
                )  # type: SetGen[Packet]
                for fvalue in fvalue_gen:
                    s += fvalue._show_or_dump(dump=dump, indent=indent, label_lvl=label_lvl + lvl + "   |", first_call=False)  # noqa: E501
            else:
                pad = max(0, 10 - len(f.name)) * " "
                begn = "%s  %s%s%s " % (label_lvl + lvl,
                                        ncol(f.name),
                                        pad,
                                        ct.punct("="),)
                reprval = f.i2repr(self, fvalue)
                if isinstance(reprval, str):
                    reprval = reprval.replace("\n", "\n" + " " * (len(label_lvl) +  # noqa: E501
                                                                  len(lvl) +
                                                                  len(f.name) +
                                                                  4))
                s += "%s%s\n" % (begn, vcol(reprval))
        if self.payload:
            s += self.payload._show_or_dump(  # type: ignore
                dump=dump,
                indent=indent,
                lvl=lvl + (" " * indent * self.show_indent),
                label_lvl=label_lvl,
                first_call=False
            )

        if first_call and not dump:
            print(s)
            return None
        else:
            return s

    def show(self, dump=False, indent=3, lvl="", label_lvl=""):
        # type: (bool, int, str, str) -> Optional[Any]
        """
        Prints or returns (when "dump" is true) a hierarchical view of the
        packet.

        :param dump: determine if it prints or returns the string value
        :param int indent: the size of indentation for each layer
        :param str lvl: additional information about the layer lvl
        :param str label_lvl: additional information about the layer fields
        :return: return a hierarchical view if dump, else print it
        """
        return self._show_or_dump(dump, indent, lvl, label_lvl)

    def show2(self, dump=False, indent=3, lvl="", label_lvl=""):
        # type: (bool, int, str, str) -> Optional[Any]
        """
        Prints or returns (when "dump" is true) a hierarchical view of an
        assembled version of the packet, so that automatic fields are
        calculated (checksums, etc.)

        :param dump: determine if it prints or returns the string value
        :param int indent: the size of indentation for each layer
        :param str lvl: additional information about the layer lvl
        :param str label_lvl: additional information about the layer fields
        :return: return a hierarchical view if dump, else print it
        """
        return self.__class__(raw(self)).show(dump, indent, lvl, label_lvl)

    def sprintf(self, fmt, relax=1):
        # type: (str, int) -> str
        """
        sprintf(format, [relax=1]) -> str

        Where format is a string that can include directives. A directive
        begins and ends by % and has the following format:
        ``%[fmt[r],][cls[:nb].]field%``

        :param fmt: is a classic printf directive, "r" can be appended for raw
          substitution:
          (ex: IP.flags=0x18 instead of SA), nb is the number of the layer
          (ex: for IP/IP packets, IP:2.src is the src of the upper IP layer).
          Special case : "%.time%" is the creation time.
          Ex::

            p.sprintf(
              "%.time% %-15s,IP.src% -> %-15s,IP.dst% %IP.chksum% "
              "%03xr,IP.proto% %r,TCP.flags%"
            )

          Moreover, the format string can include conditional statements. A
          conditional statement looks like : {layer:string} where layer is a
          layer name, and string is the string to insert in place of the
          condition if it is true, i.e. if layer is present. If layer is
          preceded by a "!", the result is inverted. Conditions can be
          imbricated. A valid statement can be::

            p.sprintf("This is a{TCP: TCP}{UDP: UDP}{ICMP:n ICMP} packet")
            p.sprintf("{IP:%IP.dst% {ICMP:%ICMP.type%}{TCP:%TCP.dport%}}")

          A side effect is that, to obtain "{" and "}" characters, you must use
          "%(" and "%)".
        """

        escape = {"%": "%",
                  "(": "{",
                  ")": "}"}

        # Evaluate conditions
        while "{" in fmt:
            i = fmt.rindex("{")
            j = fmt[i + 1:].index("}")
            cond = fmt[i + 1:i + j + 1]
            k = cond.find(":")
            if k < 0:
                raise Scapy_Exception("Bad condition in format string: [%s] (read sprintf doc!)" % cond)  # noqa: E501
            cond, format_ = cond[:k], cond[k + 1:]
            res = False
            if cond[0] == "!":
                res = True
                cond = cond[1:]
            if self.haslayer(cond):
                res = not res
            if not res:
                format_ = ""
            fmt = fmt[:i] + format_ + fmt[i + j + 2:]

        # Evaluate directives
        s = ""
        while "%" in fmt:
            i = fmt.index("%")
            s += fmt[:i]
            fmt = fmt[i + 1:]
            if fmt and fmt[0] in escape:
                s += escape[fmt[0]]
                fmt = fmt[1:]
                continue
            try:
                i = fmt.index("%")
                sfclsfld = fmt[:i]
                fclsfld = sfclsfld.split(",")
                if len(fclsfld) == 1:
                    f = "s"
                    clsfld = fclsfld[0]
                elif len(fclsfld) == 2:
                    f, clsfld = fclsfld
                else:
                    raise Scapy_Exception
                if "." in clsfld:
                    cls, fld = clsfld.split(".")
                else:
                    cls = self.__class__.__name__
                    fld = clsfld
                num = 1
                if ":" in cls:
                    cls, snum = cls.split(":")
                    num = int(snum)
                fmt = fmt[i + 1:]
            except Exception:
                raise Scapy_Exception("Bad format string [%%%s%s]" % (fmt[:25], fmt[25:] and "..."))  # noqa: E501
            else:
                if fld == "time":
                    val = time.strftime(
                        "%H:%M:%S.%%06i",
                        time.localtime(float(self.time))
                    ) % int((self.time - int(self.time)) * 1000000)
                elif cls == self.__class__.__name__ and hasattr(self, fld):
                    if num > 1:
                        val = self.payload.sprintf("%%%s,%s:%s.%s%%" % (f, cls, num - 1, fld), relax)  # noqa: E501
                        f = "s"
                    else:
                        try:
                            val = self.getfieldval(fld)
                        except AttributeError:
                            val = getattr(self, fld)
                        if f[-1] == "r":  # Raw field value
                            f = f[:-1]
                            if not f:
                                f = "s"
                        else:
                            if fld in self.fieldtype:
                                val = self.fieldtype[fld].i2repr(self, val)
                else:
                    val = self.payload.sprintf("%%%s%%" % sfclsfld, relax)
                    f = "s"
                s += ("%" + f) % val

        s += fmt
        return s

    def mysummary(self):
        # type: () -> str
        """DEV: can be overloaded to return a string that summarizes the layer.
           Only one mysummary() is used in a whole packet summary: the one of the upper layer,  # noqa: E501
           except if a mysummary() also returns (as a couple) a list of layers whose  # noqa: E501
           mysummary() must be called if they are present."""
        return ""

    def _do_summary(self):
        # type: () -> Tuple[int, str, List[Any]]
        found, s, needed = self.payload._do_summary()
        ret = ""
        if not found or self.__class__ in needed:
            ret = self.mysummary()
            if isinstance(ret, tuple):
                ret, n = ret
                needed += n
        if ret or needed:
            found = 1
        if not ret:
            ret = self.__class__.__name__ if self.show_summary else ""
        if self.__class__ in conf.emph:
            impf = []
            for f in self.fields_desc:
                if f in conf.emph:
                    impf.append("%s=%s" % (f.name, f.i2repr(self, self.getfieldval(f.name))))  # noqa: E501
            ret = "%s [%s]" % (ret, " ".join(impf))
        if ret and s:
            ret = "%s / %s" % (ret, s)
        else:
            ret = "%s%s" % (ret, s)
        return found, ret, needed

    def summary(self, intern=0):
        # type: (int) -> str
        """Prints a one line summary of a packet."""
        return self._do_summary()[1]

    def lastlayer(self, layer=None):
        # type: (Optional[Packet]) -> Packet
        """Returns the uppest layer of the packet"""
        return self.payload.lastlayer(self)

    def decode_payload_as(self, cls):
        # type: (Type[Packet]) -> None
        """Reassembles the payload and decode it using another packet class"""
        s = raw(self.payload)
        self.payload = cls(s, _internal=1, _underlayer=self)
        pp = self
        while pp.underlayer is not None:
            pp = pp.underlayer
        self.payload.dissection_done(pp)

    def command(self):
        # type: () -> str
        """
        Returns a string representing the command you have to type to
        obtain the same packet
        """
        f = []
        for fn, fv in six.iteritems(self.fields):
            fld = self.get_field(fn)
            if isinstance(fv, (list, dict, set)) and len(fv) == 0:
                continue
            if isinstance(fv, Packet):
                fv = fv.command()
            elif fld.islist and fld.holds_packets and isinstance(fv, list):
                fv = "[%s]" % ",".join(map(Packet.command, fv))
            elif isinstance(fld, FlagsField):
                fv = int(fv)
            elif callable(getattr(fv, 'command', None)):
                fv = fv.command()
            else:
                fv = repr(fv)
            f.append("%s=%s" % (fn, fv))
        c = "%s(%s)" % (self.__class__.__name__, ", ".join(f))
        pc = self.payload.command()
        if pc:
            c += "/" + pc
        return c class Raw(Packet):
    name = "Raw"
    fields_desc = [StrField("load", b"")]

    def __init__(self, _pkt=b"", *args, **kwargs):
        # type: (bytes, *Any, **Any) -> None
        if _pkt and not isinstance(_pkt, bytes):
            _pkt = bytes_encode(_pkt)
        super(Raw, self).__init__(_pkt, *args, **kwargs)

    def answers(self, other):
        # type: (Packet) -> int
        return 1

    def mysummary(self):
        # type: () -> str
        cs = conf.raw_summary
        if cs:
            if callable(cs):
                return "Raw %s" % cs(self.load)
            else:
                return "Raw %r" % self.load
        return Packet.mysummary(self) @conf.commands.register
def sendp(x,  # type: _PacketIterable
          iface=None,  # type: Optional[_GlobInterfaceType]
          iface_hint=None,  # type: Optional[str]
          socket=None,  # type: Optional[SuperSocket]
          **kargs  # type: Any
          ):
    # type: (...) -> Optional[PacketList]
    """
    Send packets at layer 2

    :param x: the packets
    :param inter: time (in s) between two packets (default 0)
    :param loop: send packet indefinitely (default 0)
    :param count: number of packets to send (default None=1)
    :param verbose: verbose mode (default None=conf.verbose)
    :param realtime: check that a packet was sent before sending the next one
    :param return_packets: return the sent packets
    :param socket: the socket to use (default is conf.L3socket(kargs))
    :param iface: the interface to send the packets on
    :param monitor: (not on linux) send in monitor mode
    :returns: None
    """
    if iface is None and iface_hint is not None and socket is None:
        iface = conf.route.route(iface_hint)[0]
    return _send(
        x,
        lambda iface: iface.l2socket(),
        iface=iface,
        socket=socket,
        **kargs
    ) @conf.commands.register
def sniff(*args, **kwargs):
    # type: (*Any, **Any) -> PacketList
    sniffer = AsyncSniffer()
    sniffer._run(*args, **kwargs)
    return cast(PacketList, sniffer.results) @conf.commands.register
def sr(x,  # type: _PacketIterable
       promisc=None,  # type: Optional[bool]
       filter=None,  # type: Optional[str]
       iface=None,  # type: Optional[_GlobInterfaceType]
       nofilter=0,  # type: int
       *args,  # type: Any
       **kargs  # type: Any
       ):
    # type: (...) -> Tuple[SndRcvList, PacketList]
    """
    Send and receive packets at layer 3
    """
    s = conf.L3socket(promisc=promisc, filter=filter,
                      iface=iface, nofilter=nofilter)
    result = sndrcv(s, x, *args, **kargs)
    s.close()
    return result @conf.commands.register
def srp1(*args, **kargs):
    # type: (*Packet, **Any) -> Optional[Packet]
    """
    Send and receive packets at layer 2 and return only the first answer
    """
    ans, _ = srp(*args, **kargs)
    if len(ans) > 0:
        return cast(Packet, ans[0][1])
    return None class SuperSocket:
    closed = 0    # type: int
    nonblocking_socket = False  # type: bool
    auxdata_available = False   # type: bool

    def __init__(self,
                 family=socket.AF_INET,  # type: int
                 type=socket.SOCK_STREAM,  # type: int
                 proto=0,  # type: int
                 iface=None,  # type: Optional[_GlobInterfaceType]
                 **kwargs  # type: Any
                 ):
        # type: (...) -> None
        self.ins = socket.socket(family, type, proto)  # type: socket.socket
        self.outs = self.ins  # type: Optional[socket.socket]
        self.promisc = None
        self.iface = iface

    def send(self, x):
        # type: (Packet) -> int
        sx = raw(x)
        try:
            x.sent_time = time.time()
        except AttributeError:
            pass

        if self.outs:
            return self.outs.send(sx)
        else:
            return 0

    if six.PY2:
        def _recv_raw(self, sock, x):
            # type: (socket.socket, int) -> Tuple[bytes, Any, Optional[float]]
            """Internal function to receive a Packet"""
            pkt, sa_ll = sock.recvfrom(x)
            return pkt, sa_ll, None
    else:
        def _recv_raw(self, sock, x):
            # type: (socket.socket, int) -> Tuple[bytes, Any, Optional[float]]
            """Internal function to receive a Packet,
            and process ancillary data.
            """
            timestamp = None
            if not self.auxdata_available:
                pkt, _, _, sa_ll = sock.recvmsg(x)
                return pkt, sa_ll, timestamp
            flags_len = socket.CMSG_LEN(4096)
            pkt, ancdata, flags, sa_ll = sock.recvmsg(x, flags_len)
            if not pkt:
                return pkt, sa_ll, timestamp
            for cmsg_lvl, cmsg_type, cmsg_data in ancdata:
                # Check available ancillary data
                if (cmsg_lvl == SOL_PACKET and cmsg_type == PACKET_AUXDATA):
                    # Parse AUXDATA
                    try:
                        auxdata = tpacket_auxdata.from_buffer_copy(cmsg_data)
                    except ValueError:
                        # Note: according to Python documentation, recvmsg()
                        #       can return a truncated message. A ValueError
                        #       exception likely indicates that Auxiliary
                        #       Data is not supported by the Linux kernel.
                        return pkt, sa_ll, timestamp
                    if auxdata.tp_vlan_tci != 0 or \
                            auxdata.tp_status & TP_STATUS_VLAN_VALID:
                        # Insert VLAN tag
                        tpid = ETH_P_8021Q
                        if auxdata.tp_status & TP_STATUS_VLAN_TPID_VALID:
                            tpid = auxdata.tp_vlan_tpid
                        tag = struct.pack(
                            "!HH",
                            tpid,
                            auxdata.tp_vlan_tci
                        )
                        pkt = pkt[:12] + tag + pkt[12:]
                elif cmsg_lvl == socket.SOL_SOCKET and \
                        cmsg_type == SO_TIMESTAMPNS:
                    length = len(cmsg_data)
                    if length == 16:  # __kernel_timespec
                        tmp = struct.unpack("ll", cmsg_data)
                    elif length == 8:  # timespec
                        tmp = struct.unpack("ii", cmsg_data)
                    else:
                        log_runtime.warning("Unknown timespec format.. ?!")
                        continue
                    timestamp = tmp[0] + tmp[1] * 1e-9
            return pkt, sa_ll, timestamp

    def recv_raw(self, x=MTU):
        # type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]]  # noqa: E501
        """Returns a tuple containing (cls, pkt_data, time)"""
        return conf.raw_layer, self.ins.recv(x), None

    def recv(self, x=MTU):
        # type: (int) -> Optional[Packet]
        cls, val, ts = self.recv_raw(x)
        if not val or not cls:
            return None
        try:
            pkt = cls(val)  # type: Packet
        except KeyboardInterrupt:
            raise
        except Exception:
            if conf.debug_dissector:
                from scapy.sendrecv import debug
                debug.crashed_on = (cls, val)
                raise
            pkt = conf.raw_layer(val)
        if ts:
            pkt.time = ts
        return pkt

    def fileno(self):
        # type: () -> int
        return self.ins.fileno()

    def close(self):
        # type: () -> None
        if self.closed:
            return
        self.closed = True
        if getattr(self, "outs", None):
            if getattr(self, "ins", None) != self.outs:
                if self.outs and (WINDOWS or self.outs.fileno() != -1):
                    self.outs.close()
        if getattr(self, "ins", None):
            if WINDOWS or self.ins.fileno() != -1:
                self.ins.close()

    def sr(self, *args, **kargs):
        # type: (Any, Any) -> Tuple[SndRcvList, PacketList]
        from scapy import sendrecv
        ans, unans = sendrecv.sndrcv(self, *args, **kargs)  # type: SndRcvList, PacketList  # noqa: E501
        return ans, unans

    def sr1(self, *args, **kargs):
        # type: (Any, Any) -> Optional[Packet]
        from scapy import sendrecv
        ans = sendrecv.sndrcv(self, *args, **kargs)[0]  # type: SndRcvList
        if len(ans) > 0:
            pkt = ans[0][1]  # type: Packet
            return pkt
        else:
            return None

    def sniff(self, *args, **kargs):
        # type: (Any, Any) -> PacketList
        from scapy import sendrecv
        pkts = sendrecv.sniff(opened_socket=self, *args, **kargs)  # type: PacketList  # noqa: E501
        return pkts

    def tshark(self, *args, **kargs):
        # type: (Any, Any) -> None
        from scapy import sendrecv
        sendrecv.tshark(opened_socket=self, *args, **kargs)

    # TODO: use 'scapy.ansmachine.AnsweringMachine' when typed
    def am(self,
           cls,  # type: Type[Any]
           *args,  # type: Any
           **kwargs  # type: Any
           ):
        # type: (...) -> Any
        """
        Creates an AnsweringMachine associated with this socket.

        :param cls: A subclass of AnsweringMachine to instantiate
        """
        return cls(*args, opened_socket=self, socket=self, **kwargs)

    @staticmethod
    def select(sockets, remain=conf.recv_poll_rate):
        # type: (List[SuperSocket], Optional[float]) -> List[SuperSocket]
        """This function is called during sendrecv() routine to select
        the available sockets.

        :param sockets: an array of sockets that need to be selected
        :returns: an array of sockets that were selected and
            the function to be called next to get the packets (i.g. recv)
        """
        try:
            inp, _, _ = select(sockets, [], [], remain)
        except (IOError, select_error) as exc:
            # select.error has no .errno attribute
            if not exc.args or exc.args[0] != errno.EINTR:
                raise
        return inp

    def __del__(self):
        # type: () -> None
        """Close the socket"""
        self.close()

    def __enter__(self):
        # type: () -> SuperSocket
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        # type: (Optional[Type[BaseException]], Optional[BaseException], Optional[Any]) -> None  # noqa: E501
        """Close the socket"""
        self.close() class L3RawSocket(SuperSocket):
    desc = "Layer 3 using Raw sockets (PF_INET/SOCK_RAW)"

    def __init__(self,
                 type=ETH_P_IP,  # type: int
                 filter=None,  # type: Optional[str]
                 iface=None,  # type: Optional[_GlobInterfaceType]
                 promisc=None,  # type: Optional[bool]
                 nofilter=0  # type: int
                 ):
        # type: (...) -> None
        self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)  # noqa: E501
        self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
        self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))  # noqa: E501
        self.iface = iface
        if iface is not None:
            iface = network_name(iface)
            self.ins.bind((iface, type))
        if not six.PY2:
            try:
                # Receive Auxiliary Data (VLAN tags)
                self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)
                self.ins.setsockopt(
                    socket.SOL_SOCKET,
                    SO_TIMESTAMPNS,
                    1
                )
                self.auxdata_available = True
            except OSError:
                # Note: Auxiliary Data is only supported since
                #       Linux 2.6.21
                msg = "Your Linux Kernel does not support Auxiliary Data!"
                log_runtime.info(msg)

    def recv(self, x=MTU):
        # type: (int) -> Optional[Packet]
        data, sa_ll, ts = self._recv_raw(self.ins, x)
        if sa_ll[2] == socket.PACKET_OUTGOING:
            return None
        if sa_ll[3] in conf.l2types:
            cls = conf.l2types.num2layer[sa_ll[3]]  # type: Type[Packet]
            lvl = 2
        elif sa_ll[1] in conf.l3types:
            cls = conf.l3types.num2layer[sa_ll[1]]
            lvl = 3
        else:
            cls = conf.default_l2
            warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s", sa_ll[0], sa_ll[1], sa_ll[3], cls.name)  # noqa: E501
            lvl = 3

        try:
            pkt = cls(data)
        except KeyboardInterrupt:
            raise
        except Exception:
            if conf.debug_dissector:
                raise
            pkt = conf.raw_layer(data)

        if lvl == 2:
            pkt = pkt.payload

        if pkt is not None:
            if ts is None:
                from scapy.arch.linux import get_last_packet_timestamp
                ts = get_last_packet_timestamp(self.ins)
            pkt.time = ts
        return pkt

    def send(self, x):
        # type: (Packet) -> int
        try:
            sx = raw(x)
            if self.outs:
                x.sent_time = time.time()
                return self.outs.sendto(
                    sx,
                    (x.dst, 0)
                )
        except AttributeError:
            raise ValueError(
                "Missing 'dst' attribute in the first layer to be "
                "sent using a native L3 socket ! (make sure you passed the "
                "IP layer)"
            )
        except socket.error as msg:
            log_runtime.error(msg)
        return 0 def checksum(pkt):
    # type: (bytes) -> int
    if len(pkt) % 2 == 1:
        pkt += b"\0"
    s = sum(array.array("H", pkt))
    s = (s >> 16) + (s & 0xffff)
    s += s >> 16
    s = ~s
    return checksum_endian_transform(s) & 0xffff def strxor(s1, s2):
    # type: (bytes, bytes) -> bytes
    """
    Returns the binary XOR of the 2 provided strings s1 and s2. s1 and s2
    must be of same length.
    """
    return b"".join(map(lambda x, y: chb(orb(x) ^ orb(y)), s1, s2)) def in6_getnsma(a):
    # type: (bytes) -> bytes
    """
    Return link-local solicited-node multicast address for given
    address. Passed address must be provided in network format.
    Returned value is also in network format.
    """

    r = in6_and(a, inet_pton(socket.AF_INET6, '::ff:ffff'))
    r = in6_or(inet_pton(socket.AF_INET6, 'ff02::1:ff00:0'), r)
    return r def in6_getnsmac(a):
    # type: (bytes) -> str
    """
    Return the multicast mac address associated with provided
    IPv6 address. Passed address must be in network format.
    """

    ba = struct.unpack('16B', a)[-4:]
    mac = '33:33:'
    mac += ':'.join("%.2x" % x for x in ba)
    return mac def in6_isaddr6to4(x):
    # type: (str) -> bool
    """
    Return True if provided address (in printable format) is a 6to4
    address (being in 2002::/16).
    """
    bx = inet_pton(socket.AF_INET6, x)
    return bx[:2] == b' \x02' def in6_isaddrllallnodes(str):
    # type: (str) -> bool
    """
    Returns True if address is the link-local all-nodes multicast
    address (ff02::1).
    """
    return (inet_pton(socket.AF_INET6, "ff02::1") ==
            inet_pton(socket.AF_INET6, str)) def in6_isaddrllallservers(str):
    # type: (str) -> bool
    """
    Returns True if address is the link-local all-servers multicast
    address (ff02::2).
    """
    return (inet_pton(socket.AF_INET6, "ff02::2") ==
            inet_pton(socket.AF_INET6, str)) def in6_isaddrTeredo(x):
    # type: (str) -> bool
    """
    Return True if provided address is a Teredo, meaning it is under
    the /32 conf.teredoPrefix prefix value (by default, 2001::).
    Otherwise, False is returned. Address must be passed in printable
    format.
    """
    our = inet_pton(socket.AF_INET6, x)[0:4]
    teredoPrefix = inet_pton(socket.AF_INET6, conf.teredoPrefix)[0:4]
    return teredoPrefix == our def in6_isllsnmaddr(str):
    # type: (str) -> bool
    """
    Return True if provided address is a link-local solicited node
    multicast address, i.e. belongs to ff02::1:ff00:0/104. False is
    returned otherwise.
    """
    temp = in6_and(b"\xff" * 13 + b"\x00" * 3, inet_pton(socket.AF_INET6, str))
    temp2 = b'\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\x00\x00\x00'
    return temp == temp2 def in6_ismaddr(str):
    # type: (str) -> bool
    """
    Returns True if provided address in printable format belongs to
    allocated Multicast address space (ff00::/8).
    """
    return in6_isincluded(str, 'ff00::', 8) class Net6(Net):  # syntax ex. 2011:db8::/126
    """Network object from an IP address or hostname and mask"""
    name = "Net6"  # type: str
    family = socket.AF_INET6  # type: int
    max_mask = 128  # type: int

    @classmethod
    def ip2int(cls, addr):
        # type: (str) -> int
        val1, val2 = struct.unpack(
            '!QQ', inet_pton(socket.AF_INET6, cls.name2addr(addr))
        )
        return cast(int, (val1 << 64) + val2)

    @staticmethod
    def int2ip(val):
        # type: (int) -> str
        return inet_ntop(
            socket.AF_INET6,
            struct.pack('!QQ', val >> 64, val & 0xffffffffffffffff),
        ) def teredoAddrExtractInfo(x):
    # type: (str) -> Tuple[str, int, str, int]
    """
    Extract information from a Teredo address. Return value is
    a 4-tuple made of IPv4 address of Teredo server, flag value (int),
    mapped address (non obfuscated) and mapped port (non obfuscated).
    No specific checks are performed on passed address.
    """
    addr = inet_pton(socket.AF_INET6, x)
    server = inet_ntop(socket.AF_INET, addr[4:8])
    flag = struct.unpack("!H", addr[8:10])[0]  # type: int
    mappedport = struct.unpack("!H", strxor(addr[10:12], b'\xff' * 2))[0]
    mappedaddr = inet_ntop(socket.AF_INET, strxor(addr[12:16], b'\xff' * 4))
    return server, flag, mappedaddr, mappedport class RandInt(RandNum):
    def __init__(self):
        # type: () -> None
        RandNum.__init__(self, 0, 2**32 - 1) class RandShort(RandNum):
    def __init__(self):
        # type: () -> None
        RandNum.__init__(self, 0, 2**16 - 1)
from hashlib import md5
from time import gmtime, strftime
from scapy.arch import get_if_hwaddr
from scapy.as_resolvers import AS_resolver_riswhois
from scapy.base_classes import Gen
from scapy.compat import chb, orb, raw, plain_str, bytes_encode
from scapy.consts import WINDOWS
from scapy.config import conf
from scapy.data import DLT_IPV6, DLT_RAW, DLT_RAW_ALT, ETHER_ANY, ETH_P_IPV6, \
    MTU
from scapy.error import log_runtime, warning
from scapy.fields import BitEnumField, BitField, ByteEnumField, ByteField, \
    DestIP6Field, FieldLenField, FlagsField, IntField, IP6Field, \
    LongField, MACField, PacketLenField, PacketListField, ShortEnumField, \
    ShortField, SourceIP6Field, StrField, StrFixedLenField, StrLenField, \
    X3BytesField, XBitField, XIntField, XShortField
from scapy.layers.inet import IP, IPTools, TCP, TCPerror, TracerouteResult, \
    UDP, UDPerror
from scapy.layers.l2 import CookedLinux, Ether, GRE, Loopback, SNAP
from scapy.packet import bind_layers, Packet, Raw
from scapy.sendrecv import sendp, sniff, sr, srp1
from scapy.supersocket import SuperSocket, L3RawSocket
from scapy.utils import checksum, strxor
from scapy.pton_ntop import inet_pton, inet_ntop
from scapy.utils6 import in6_getnsma, in6_getnsmac, in6_isaddr6to4, \
    in6_isaddrllallnodes, in6_isaddrllallservers, in6_isaddrTeredo, \
    in6_isllsnmaddr, in6_ismaddr, Net6, teredoAddrExtractInfo
from scapy.volatile import RandInt, RandShort
import random
import socket
import struct
import scapy.modules.six as six
    import scapy.route6  # noqa: F401
            # ss = inet_pton(socket.AF_INET6, self.src)
            sd = inet_pton(socket.AF_INET6, self.dst)
            os = inet_pton(socket.AF_INET6, other.src)
            od = inet_pton(socket.AF_INET6, other.dst)
            # request was sent to a multicast address (other.dst)
            # Check reply destination addr matches request source addr (i.e
            # sd == os) except when reply is multicasted too
            # XXX test mcast scope matching ?
            if in6_ismaddr(other.dst):
                if in6_ismaddr(self.dst):
                    if ((od == sd) or
                            (in6_isaddrllallnodes(self.dst) and in6_isaddrllallservers(other.dst))):  # noqa: E501
                        return self.payload.answers(other.payload)
                    return False
                if (os == sd):
                    return self.payload.answers(other.payload)
                return False
            elif (sd != os):  # or ss != od): <- removed for ICMP errors
                return False
        if self.nh == 58 and isinstance(self.payload, _ICMPv6) and self.payload.type < 128:  # noqa: E501
            # ICMPv6 Error message -> generated by IPv6 packet
            # Note : at the moment, we jump the ICMPv6 specific class
            # to call answers() method of erroneous packet (over
            # initial packet). There can be cases where an ICMPv6 error
            # class could implement a specific answers method that perform
            # a specific task. Currently, don't see any use ...
            return self.payload.payload.answers(other)
        elif other.nh == 0 and isinstance(other.payload, IPv6ExtHdrHopByHop):
            return self.payload.answers(other.payload)
        elif other.nh == 44 and isinstance(other.payload, IPv6ExtHdrFragment):
            return self.payload.answers(other.payload.payload)
        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrRouting):
            return self.payload.answers(other.payload.payload)  # Buggy if self.payload is a IPv6ExtHdrRouting  # noqa: E501
        elif other.nh == 43 and isinstance(other.payload, IPv6ExtHdrSegmentRouting):  # noqa: E501
            return self.payload.answers(other.payload.payload)  # Buggy if self.payload is a IPv6ExtHdrRouting  # noqa: E501
        elif other.nh == 60 and isinstance(other.payload, IPv6ExtHdrDestOpt):
            return self.payload.payload.answers(other.payload.payload)
        elif self.nh == 60 and isinstance(self.payload, IPv6ExtHdrDestOpt):  # BU in reply to BRR, for instance  # noqa: E501
            return self.payload.payload.answers(other.payload)
        else:
            if (self.nh != other.nh):
                return False
            return self.payload.answers(other.payload)


class IPv46(IP):
    """
    This class implements a dispatcher that is used to detect the IP version
    while parsing Raw IP pcap files.
    """
    @classmethod
    def dispatch_hook(cls, _pkt=None, *_, **kargs):
        if _pkt:
            if orb(_pkt[0]) >> 4 == 6:
                return IPv6
        elif kargs.get("version") == 6:
            return IPv6
        return IP


def inet6_register_l3(l2, l3):
    return getmacbyip6(l3.dst)


conf.neighbor.register_l3(Ether, IPv6, inet6_register_l3)


class IPerror6(IPv6):
    name = "IPv6 in ICMPv6"

    def answers(self, other):
        if not isinstance(other, IPv6):
            return False
        sd = inet_pton(socket.AF_INET6, self.dst)
        ss = inet_pton(socket.AF_INET6, self.src)
        od = inet_pton(socket.AF_INET6, other.dst)
        os = inet_pton(socket.AF_INET6, other.src)

        # Make sure that the ICMPv6 error is related to the packet scapy sent
        if isinstance(self.underlayer, _ICMPv6) and self.underlayer.type < 128:

            # find upper layer for self (possible citation)
            selfup = self.payload
            while selfup is not None and isinstance(selfup, _IPv6ExtHdr):
                selfup = selfup.payload

            # find upper layer for other (initial packet). Also look for RH
            otherup = other.payload
            request_has_rh = False
            while otherup is not None and isinstance(otherup, _IPv6ExtHdr):
                if isinstance(otherup, IPv6ExtHdrRouting):
                    request_has_rh = True
                otherup = otherup.payload

            if ((ss == os and sd == od) or  # < Basic case
                    (ss == os and request_has_rh)):
                # ^ Request has a RH : don't check dst address

                # Let's deal with possible MSS Clamping
                if (isinstance(selfup, TCP) and
                    isinstance(otherup, TCP) and
                        selfup.options != otherup.options):  # seems clamped

                    # Save fields modified by MSS clamping
                    old_otherup_opts = otherup.options
                    old_otherup_cksum = otherup.chksum
                    old_otherup_dataofs = otherup.dataofs
                    old_selfup_opts = selfup.options
                    old_selfup_cksum = selfup.chksum
                    old_selfup_dataofs = selfup.dataofs

                    # Nullify them
                    otherup.options = []
                    otherup.chksum = 0
                    otherup.dataofs = 0
                    selfup.options = []
                    selfup.chksum = 0
                    selfup.dataofs = 0

                    # Test it and save result

                    s1 = raw(selfup)