The main purpose of this function is to send fake Neighbor Solicitations
    messages to a victim, in order to either create a new entry in its neighbor
    cache or update an existing one. In section 7.2.3 of RFC 4861, it is stated
    that a node SHOULD create the entry or update an existing one (if it is not
    currently performing DAD for the target of the NS). The entry's reachability  # noqa: E501
    state is set to STALE.

    The two main parameters of the function are the source link-layer address
    (carried by the Source Link-Layer Address option in the NS) and the
    source address of the packet.

    Unlike some other NDP_Attack_* function, this one is not based on a
    stimulus/response model. When called, it sends the same NS packet in loop
    every second (the default)

    Following arguments can be used to change the format of the packets:

    src_lladdr: the MAC address used in the Source Link-Layer Address option
         included in the NS packet. This is the address that the peer should
         associate in its neighbor cache with the IPv6 source address of the
         packet. If None is provided, the mac address of the interface is
         used.

    src: the IPv6 address used as source of the packet. If None is provided,
         an address associated with the emitting interface will be used
         (based on the destination address of the packet).

    target: the target address of the NS packet. If no value is provided,
         a dummy address (2001:db8::1) is used. The value of the target
         has a direct impact on the destination address of the packet if it
         is not overridden. By default, the solicited-node multicast address
         associated with the target is used as destination address of the
         packet. Consider specifying a specific destination address if you
         intend to use a target address different than the one of the victim.

    dst: The destination address of the NS. By default, the solicited node
         multicast address associated with the target address (see previous
         parameter) is used if no specific value is provided. The victim
         is not expected to check the destination address of the packet,
         so using a multicast address like ff02::1 should work if you want
         the attack to target all hosts on the link. On the contrary, if
         you want to be more stealth, you should provide the target address
         for this parameter in order for the packet to be sent only to the
         victim.

    src_mac: the MAC address used as source of the packet. By default, this
         is the address of the interface. If you want to be more stealth,
         feel free to use something else. Note that this address is not the
         that the victim will use to populate its neighbor cache.

    dst_mac: The MAC address used as destination address of the packet. If
         the IPv6 destination address is multicast (all-nodes, solicited
         node, ...), it will be computed. If the destination address is
         unicast, a neighbor solicitation will be performed to get the
         associated address. If you want the attack to be stealth, you
         can provide the MAC address using this parameter.

    loop: By default, this parameter is True, indicating that NS packets
         will be sent in loop, separated by 'inter' seconds (see below).
         When set to False, a single packet is sent.

    inter: When loop parameter is True (the default), this parameter provides
         the interval in seconds used for sending NS packets.

    iface: to force the sending interface.

def NDP_Attack_NS_Spoofing(src_lladdr=None, src=None, target="2001:db8::1",
                           dst=None, src_mac=None, dst_mac=None, loop=True,
                           inter=1, iface=None):
    """
    The main purpose of this function is to send fake Neighbor Solicitations
    messages to a victim, in order to either create a new entry in its neighbor
    cache or update an existing one. In section 7.2.3 of RFC 4861, it is stated
    that a node SHOULD create the entry or update an existing one (if it is not
    currently performing DAD for the target of the NS). The entry's reachability  # noqa: E501
    state is set to STALE.

    The two main parameters of the function are the source link-layer address
    (carried by the Source Link-Layer Address option in the NS) and the
    source address of the packet.

    Unlike some other NDP_Attack_* function, this one is not based on a
    stimulus/response model. When called, it sends the same NS packet in loop
    every second (the default)

    Following arguments can be used to change the format of the packets:

    src_lladdr: the MAC address used in the Source Link-Layer Address option
         included in the NS packet. This is the address that the peer should
         associate in its neighbor cache with the IPv6 source address of the
         packet. If None is provided, the mac address of the interface is
         used.

    src: the IPv6 address used as source of the packet. If None is provided,
         an address associated with the emitting interface will be used
         (based on the destination address of the packet).

    target: the target address of the NS packet. If no value is provided,
         a dummy address (2001:db8::1) is used. The value of the target
         has a direct impact on the destination address of the packet if it
         is not overridden. By default, the solicited-node multicast address
         associated with the target is used as destination address of the
         packet. Consider specifying a specific destination address if you
         intend to use a target address different than the one of the victim.

    dst: The destination address of the NS. By default, the solicited node
         multicast address associated with the target address (see previous
         parameter) is used if no specific value is provided. The victim
         is not expected to check the destination address of the packet,
         so using a multicast address like ff02::1 should work if you want
         the attack to target all hosts on the link. On the contrary, if
         you want to be more stealth, you should provide the target address
         for this parameter in order for the packet to be sent only to the
         victim.

    src_mac: the MAC address used as source of the packet. By default, this
         is the address of the interface. If you want to be more stealth,
         feel free to use something else. Note that this address is not the
         that the victim will use to populate its neighbor cache.

    dst_mac: The MAC address used as destination address of the packet. If
         the IPv6 destination address is multicast (all-nodes, solicited
         node, ...), it will be computed. If the destination address is
         unicast, a neighbor solicitation will be performed to get the
         associated address. If you want the attack to be stealth, you
         can provide the MAC address using this parameter.

    loop: By default, this parameter is True, indicating that NS packets
         will be sent in loop, separated by 'inter' seconds (see below).
         When set to False, a single packet is sent.

    inter: When loop parameter is True (the default), this parameter provides
         the interval in seconds used for sending NS packets.

    iface: to force the sending interface.
    """

    if not iface:
        iface = conf.iface

    # Use provided MAC address as source link-layer address option
    # or the MAC address of the interface if none is provided.
    if not src_lladdr:
        src_lladdr = get_if_hwaddr(iface)

    # Prepare packets parameters
    ether_params = {}
    if src_mac:
        ether_params["src"] = src_mac

    if dst_mac:
        ether_params["dst"] = dst_mac

    ipv6_params = {}
    if src:
        ipv6_params["src"] = src
    if dst:
        ipv6_params["dst"] = dst
    else:
        # Compute the solicited-node multicast address
        # associated with the target address.
        tmp = inet_ntop(socket.AF_INET6,
                        in6_getnsma(inet_pton(socket.AF_INET6, target)))
        ipv6_params["dst"] = tmp

    pkt = Ether(**ether_params)
    pkt /= IPv6(**ipv6_params)
    pkt /= ICMPv6ND_NS(tgt=target)
    pkt /= ICMPv6NDOptSrcLLAddr(lladdr=src_lladdr)

    sendp(pkt, inter=inter, loop=loop, iface=iface, verbose=0)