Instruction:
Make a summary of the following Python 3 code
def NDP_Attack_Fake_Router(ra, iface=None, mac_src_filter=None,
                           ip_src_filter=None):
    """
    The purpose of this function is to send provided RA message at layer 2
    (i.e. providing a packet starting with IPv6 will not work) in response
    to received RS messages. In the end, the function is a simple wrapper
    around sendp() that monitor the link for RS messages.

    It is probably better explained with an example:

      >>> ra  = Ether()/IPv6()/ICMPv6ND_RA()
      >>> ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:1::", prefixlen=64)
      >>> ra /= ICMPv6NDOptPrefixInfo(prefix="2001:db8:2::", prefixlen=64)
      >>> ra /= ICMPv6NDOptSrcLLAddr(lladdr="00:11:22:33:44:55")
      >>> NDP_Attack_Fake_Router(ra, iface="eth0")
      Fake RA sent in response to RS from fe80::213:58ff:fe8c:b573
      Fake RA sent in response to RS from fe80::213:72ff:fe8c:b9ae
      ...

    Following arguments can be used to change the behavior:

      ra: the RA message to send in response to received RS message.

      iface: a specific interface (e.g. "eth0") of the system on which the
             DoS should be launched. If none is provided, conf.iface is
             used.

      mac_src_filter: a mac address (e.g "00:13:72:8c:b5:69") to filter on.
         Only RS messages received from this source will trigger a reply.
         Note that no changes to provided RA is done which imply that if
         you intend to target only the source of the RS using this option,
         you will have to set the Ethernet destination address to the same
         value in your RA.
         The default value for this parameter is None: no filtering on the
         source of RS is done.

    ip_src_filter: an IPv6 address (e.g. fe80::21e:bff:fe4e:3b2) to filter
         on. Only RS messages received from this source address will trigger
         replies. Same comment as for previous argument apply: if you use
         the option, you will probably want to set a specific Ethernet
         destination address in the RA.
    """

    def is_request(req, mac_src_filter, ip_src_filter):
        """
        Check if packet req is a request
        """

        if not (Ether in req and IPv6 in req and ICMPv6ND_RS in req):
            return 0

        mac_src = req[Ether].src
        if mac_src_filter and mac_src != mac_src_filter:
            return 0

        ip_src = req[IPv6].src
        if ip_src_filter and ip_src != ip_src_filter:
            return 0

        return 1

    def ra_reply_callback(req, iface):
        """
        Callback that sends an RA in reply to an RS
        """

        src = req[IPv6].src
        sendp(ra, iface=iface, verbose=0)
        print("Fake RA sent in response to RS from %s" % src)

    if not iface:
        iface = conf.iface
    sniff_filter = "icmp6"

    sniff(store=0,
          filter=sniff_filter,
          lfilter=lambda x: is_request(x, mac_src_filter, ip_src_filter),
          prn=lambda x: ra_reply_callback(x, iface),
          iface=iface)

Response: This function is used to send a fake router to the network.


Instruction:
Can you create a Python 3 function that
uses to select the L2 address

Response:
def route(self):
        """Used to select the L2 address"""
        dst = self.dst
        if isinstance(dst, Gen):
            dst = next(iter(dst))
        return conf.route6.route(dst)


Instruction:
Can you generate the documentation for the following Python 3 function
def extract_padding(self, data):

        if self.plen == 0 and self.nh == 0 and len(data) >= 8:
            # Extract Hop-by-Hop extension length
            hbh_len = orb(data[1])
            hbh_len = 8 + hbh_len * 8

            # Extract length from the Jumbogram option
            # Note: the following algorithm take advantage of the Jumbo option
            #        mandatory alignment (4n + 2, RFC2675 Section 2)
            jumbo_len = None
            idx = 0
            offset = 4 * idx + 2
            while offset <= len(data):
                opt_type = orb(data[offset])
                if opt_type == 0xc2:  # Jumbo option
                    jumbo_len = struct.unpack("I", data[offset + 2:offset + 2 + 4])[0]  # noqa: E501
                    break
                offset = 4 * idx + 2
                idx += 1

            if jumbo_len is None:
                warning("Scapy did not find a Jumbo option")
                jumbo_len = 0

            tmp_len = hbh_len + jumbo_len
        else:
            tmp_len = self.plen

        return data[:tmp_len], data[tmp_len:]

Response: Extract the padding from the IPv6 payload.


Instruction:
Implement a Python 3 function for
computing the sources_number field when needed

Response:
def post_build(self, packet, payload):
        """Compute the 'sources_number' field when needed"""
        if self.sources_number is None:
            srcnum = struct.pack("!H", len(self.sources))
            packet = packet[:26] + srcnum + packet[28:]
        return _ICMPv6.post_build(self, packet, payload)


Instruction:
Can you tell what is the following Python 3 function doing
def post_build(self, packet, payload):
        if self.records_number is None:
            recnum = struct.pack("!H", len(self.records))
            packet = packet[:6] + recnum + packet[8:]
        return _ICMPv6.post_build(self, packet, payload)

Response: Compute the records_number field when needed


Instruction:
How would you code a function in Python 3 to
parse a json file to get a configuration

Response:
def parse_config_file(config_path, verb=3):
    """Parse provided json to get configuration
    Empty default json:
    {
      "testfiles": [],
      "breakfailed": true,
      "onlyfailed": false,
      "verb": 3,
      "dump": 0,
      "crc": true,
      "scapy": "scapy",
      "preexec": {},
      "global_preexec": "",
      "outputfile": null,
      "local": true,
      "format": "ansi",
      "num": null,
      "modules": [],
      "kw_ok": [],
      "kw_ko": []
    }

    """
    import json
    import unicodedata
    with open(config_path) as config_file:
        data = json.load(config_file, encoding="utf8")
        if verb > 2:
            print("### Loaded config file", config_path, file=sys.stderr)

    def get_if_exist(key, default):
        return data[key] if key in data else default
    return Bunch(testfiles=get_if_exist("testfiles", []),
                 breakfailed=get_if_exist("breakfailed", True),
                 remove_testfiles=get_if_exist("remove_testfiles", []),
                 onlyfailed=get_if_exist("onlyfailed", False),
                 verb=get_if_exist("verb", 3),
                 dump=get_if_exist("dump", 0), crc=get_if_exist("crc", 1),
                 scapy=get_if_exist("scapy", "scapy"),
                 preexec=get_if_exist("preexec", {}),
                 global_preexec=get_if_exist("global_preexec", ""),
                 outfile=get_if_exist("outputfile", sys.stdout),
                 local=get_if_exist("local", False),
                 num=get_if_exist("num", None),
                 modules=get_if_exist("modules", []),
                 kw_ok=get_if_exist("kw_ok", []),
                 kw_ko=get_if_exist("kw_ko", []),
                 format=get_if_exist("format", "ansi"))


Instruction:
Write a Python 3 function for
adding the endianness to the format

Response:
def set_endianess(self, pkt):
        """Add the endianness to the format"""
        end = self.endianess_from(pkt)
        if isinstance(end, str) and end:
            if isinstance(self.fld, UUIDField):
                self.fld.uuid_fmt = (UUIDField.FORMAT_LE if end == '<'
                                     else UUIDField.FORMAT_BE)
            else:
                # fld.fmt should always start with a order specifier, cf field
                # init
                self.fld.fmt = end[0] + self.fld.fmt[1:]


Instruction:
Can you implement a function in Python 3 that
retrieves the field with endianness

Response:
def getfield(self, pkt, buf):
        """retrieve the field with endianness"""
        self.set_endianess(pkt)
        return self.fld.getfield(pkt, buf)


Instruction:
Write a Python 3 script for
adding the field with endianness to the buffer

Response:
def addfield(self, pkt, buf, val):
        """add the field with endianness to the buffer"""
        self.set_endianess(pkt)
        return self.fld.addfield(pkt, buf, val)


Instruction:
How would you implement a function in Python 3 that
returns whether the AbstractUVarIntField is represented on multiple bytes or not.

Response:
def _detect_multi_byte(self, fb):
        # type: (str) -> bool
        """ _detect_multi_byte returns whether the AbstractUVarIntField is represented on  # noqa: E501
          multiple bytes or not.

          A multibyte representation is indicated by all of the first size bits being set  # noqa: E501

        @param str fb: first byte, as a character.
        @return bool: True if multibyte repr detected, else False.
        @raise AssertionError
        """
        assert(isinstance(fb, int) or len(fb) == 1)
        return (orb(fb) & self._max_value) == self._max_value


Instruction:
Can you tell what is the following Python 3 function doing
def m2i(self, pkt, x):
        # type: (Optional[packet.Packet], Union[str, Tuple[str, int]]) -> int
        """
          A tuple is expected for the "x" param only if "size" is different than 8. If a tuple is received, some bits  # noqa: E501
          were consumed by another field. This field consumes the remaining bits, therefore the int of the tuple must  # noqa: E501
          equal "size".

        @param packet.Packet|None pkt: unused.
        @param str|(str, int) x: the string to convert. If bits were consumed by a previous bitfield-compatible field.  # noqa: E501
        @raise AssertionError
        """
        assert(isinstance(x, bytes) or (isinstance(x, tuple) and x[1] >= 0))

        if isinstance(x, tuple):
            assert (8 - x[1]) == self.size, 'EINVAL: x: not enough bits remaining in current byte to read the prefix'  # noqa: E501
            val = x[0]
        else:
            assert isinstance(x, bytes) and self.size == 8, 'EINVAL: x: tuple expected when prefix_len is not a full byte'  # noqa: E501
            val = x

        if self._detect_multi_byte(val[0]):
            ret = self._parse_multi_byte(val)
        else:
            ret = orb(val[0]) & self._max_value

        assert(ret >= 0)
        return ret

Response: Convert a string to an integer.


Instruction:
Can you create a Python 3 function that
converts an any value to an internal value.

Response:
def any2i(self, pkt, x):
        # type: (Optional[packet.Packet], Union[None, str, int]) -> Optional[int]  # noqa: E501
        """
          A "x" value as a string is parsed as a binary encoding of a UVarInt. An int is considered an internal value.  # noqa: E501
          None is returned as is.

        @param packet.Packet|None pkt: the packet containing this field; probably unused.  # noqa: E501
        @param str|int|None x: the value to convert.
        @return int|None: the converted value.
        @raise AssertionError
        """
        if isinstance(x, type(None)):
            return x
        if isinstance(x, six.integer_types):
            assert(x >= 0)
            ret = self.h2i(pkt, x)
            assert(isinstance(ret, six.integer_types) and ret >= 0)
            return ret
        elif isinstance(x, bytes):
            ret = self.m2i(pkt, x)
            assert (isinstance(ret, six.integer_types) and ret >= 0)
            return ret
        assert False, 'EINVAL: x: No idea what the parameter format is'


Instruction:
Given the following Python 3 function, write the documentation
def addfield(self, pkt, s, val):
        # type: (Optional[packet.Packet], Union[str, Tuple[str, int, int]], int) -> str  # noqa: E501
        """ An AbstractUVarIntField prefix always consumes the remaining bits
          of a BitField;if no current BitField is in use (no tuple in
          entry) then the prefix length is 8 bits and the whole byte is to
          be consumed
        @param packet.Packet|None pkt: the packet containing this field. Probably unused.  # noqa: E501
        @param str|(str, int, long) s: the string to append this field to. A tuple indicates that some bits were already  # noqa: E501
          generated by another bitfield-compatible field. This MUST be the case if "size" is not 8. The int is the  # noqa: E501
          number of bits already generated in the first byte of the str. The long is the value that was generated by the  # noqa: E501
          previous bitfield-compatible fields.
        @param int val: the positive or null value to be added.
        @return str: s concatenated with the machine representation of this field.  # noqa: E501
        @raise AssertionError
        """
        assert(val >= 0)
        if isinstance(s, bytes):
            assert self.size == 8, 'EINVAL: s: tuple expected when prefix_len is not a full byte'  # noqa: E501
            return s + self.i2m(pkt, val)

        # s is a tuple
        # assert(s[1] >= 0)
        # assert(s[2] >= 0)
        # assert (8 - s[1]) == self.size, 'EINVAL: s: not enough bits remaining in current byte to read the prefix'  # noqa: E501

        if val >= self._max_value:
            return s[0] + chb((s[2] << self.size) + self._max_value) + self.i2m(pkt, val)[1:]  # noqa: E501
        # This AbstractUVarIntField is only one byte long; setting the prefix value  # noqa: E501
        # and appending the resulting byte to the string
        return s[0] + chb((s[2] << self.size) + orb(self.i2m(pkt, val)))

Response: Add a field to the current bitfield.