def send_DHCPv6_Reply(self, pkt): """ Sends out the DHCPv6 Reply message. """ header = self.build_reply_headers(pkt) trid = pkt[DHCP6_InfoRequest].trid srv_duid = header[Ether].src cli_id = DHCP6OptClientId(duid=pkt[DHCP6OptClientId].duid) srv_id = DHCP6OptServerId(duid=DUID_LL(lladdr=srv_duid)) sendp( header / DHCP6_Reply(trid=trid) / cli_id / srv_id, iface=self.iface, verbose=False, )
def craft_dhcp_request(self, hw=None): """Generates a DHCPv6 Request packet Args: hw (str|bytes, optional): Defaults to MAC of Scapy's `conf.iface`. Client MAC address to use for DUID LL. Returns: scapy.layers.inet.IPv6: DHCPv6 Request packet """ if not hw: _, hw = get_if_raw_hwaddr(conf.iface) else: hw = mac_str_to_bytes(hw) # TODO # Request Message # - sent by clients # - includes a server identifier option # - the content of Server Identifier option must match server's DUID # - includes a client identifier option # - must include an ORO Option (even with hints) p40 # - can includes a reconfigure Accept option indicating whether or # not the client is willing to accept Reconfigure messages from # the server (p40) # - When the server receives a Request message via unicast from a # client to which the server has not sent a unicast option, the server # discards the Request message and responds with a Reply message # containing Status Code option with the value UseMulticast, a Server # Identifier Option containing the server's DUID, the client # Identifier option from the client message and no other option. dhcp_request = (IPv6(dst="ff02::1:2") / UDP(sport=546, dport=547) / DHCP6_Request(trid=self.xid) / DHCP6OptServerId(duid=self.server_id) / DHCP6OptElapsedTime() / DHCP6OptClientId(duid=DUID_LL(lladdr=hw)) / DHCP6OptIA_NA(iaid=0)) if settings.DEBUG: print(dhcp_request.show()) return dhcp_request
def craft_discover(self, hw=None): """Generates a DHCPv6 Solicit packet Args: hw (str|bytes, optional): Defaults to MAC of Scapy's `conf.iface`. Client MAC address to use for DUID LL. Returns: scapy.layers.inet.IPv6: DHCPv6 Solicit packet """ if not hw: _, hw = get_if_raw_hwaddr(conf.iface) else: hw = mac_str_to_bytes(hw) dhcp_solicit = (IPv6(dst="ff02::1:2") / UDP(sport=546, dport=547) / DHCP6_Solicit(trid=self.xid) / DHCP6OptElapsedTime() / DHCP6OptClientId(duid=DUID_LL(lladdr=hw)) / DHCP6OptIA_NA(iaid=0)) if settings.DEBUG: print(dhcp_solicit.show()) return dhcp_solicit
def testfunc(child): iface = os.environ["TAP"] pkt = wait_for_dhcpv6_pkt(iface) # the packet was a solicit assert DHCP6_Solicit in pkt # check if the sender is the upstream interface of the node upstream_netif = get_upstream_netif(child) print(upstream_netif) upstream_hwaddrs = get_hwaddrs(child, upstream_netif) assert DHCP6OptClientId in pkt and DUID_LL in pkt[DHCP6OptClientId].duid assert pkt[DHCP6OptClientId].duid[DUID_LL].lladdr in upstream_hwaddrs # and it is asking for a prefix delegation assert DHCP6OptIA_PD in pkt # reply to solicit with advertise and a prefix provided trid = pkt[DHCP6_Solicit].trid srv_duid = "aa:bb:cc:dd:ee:ff" cli_id = DHCP6OptClientId(duid=pkt[DHCP6OptClientId].duid) srv_id = DHCP6OptServerId(duid=DUID_LL(lladdr=srv_duid)) prefix = "2001:db8:{:x}:{:x}::".format(random.randint(0, 0xffff), random.randint(0, 0xffff)) ia_pd = DHCP6OptIA_PD(T1=12000, T2=13000, iaid=pkt[DHCP6OptIA_PD].iaid, iapdopt=[ DHCP6OptIAPrefix(preflft=14000, validlft=15000, prefix=prefix, plen=64) ]) # start sniffer to catch incoming request sniffer = start_sniffer(iface, stop_filter=lambda pkt: DHCP6_Request in pkt) sendp(build_reply_headers(pkt) / DHCP6_Advertise(trid=trid) / cli_id / srv_id / ia_pd, iface=iface, verbose=False) # wait for request pkt = wait_for_dhcpv6_pkt(iface, sniffer) # the packet was indeed a request assert DHCP6_Request in pkt # and from the client assert DHCP6OptClientId in pkt and DUID_LL in pkt[DHCP6OptClientId].duid assert pkt[DHCP6OptClientId].duid[DUID_LL].lladdr in upstream_hwaddrs # and it is trying to talk to this server assert DHCP6OptServerId in pkt and DUID_LL in pkt[DHCP6OptServerId].duid assert pkt[DHCP6OptServerId].duid[DUID_LL].lladdr == srv_duid # and is still asking for a prefix delegation assert DHCP6OptIA_PD in pkt # reply to request with reply and a prefix provided trid = pkt[DHCP6_Request].trid sendp(build_reply_headers(pkt) / DHCP6_Reply(trid=trid) / cli_id / srv_id / ia_pd, iface=iface, verbose=False) time.sleep(1) # check if global address was configured child.sendline("ifconfig {}".format(get_downstream_netif(child))) # remove one trailing ':' from prefix just to be safe ;-) child.expect(r"inet6 addr:\s+{}[0-9a-fA-F:]+\s".format(prefix[:-1])) print("SUCCESS")