def add_relay(self, p, srv_ip, relay_ip=None): """Modify passed DHCP client packet as if a DHCP relay would Encapsulate DHCPv6 request message into DHCPv6 RelayForward, update UDP src port and set IP dest address. Args: p (scapy.packet.Packet): DHCP client packet srv_ip (str): IPv6 address of server to relay to relay_ip (str, optional): Defaults to dhcpdoctor's IPv6. IPv6 address of relay. """ if not relay_ip: relay_ip = get_if_addr6(conf.iface) # get payload of UDP to get whatever type of DHCPv6 request it is and # replace it with our relay data dhcp_request = p[UDP].payload assert isinstance(dhcp_request, DHCP6) p[UDP].remove_payload() p[UDP].add_payload( DHCP6_RelayForward(linkaddr=relay_ip, peeraddr=p[IPv6].src) / DHCP6OptRelayMsg(message=dhcp_request)) p[UDP].sport = 547 p[IPv6].src = relay_ip p[IPv6].dst = srv_ip if settings.DEBUG: print(p.show())
def test_dhcpv6_relay_forward_hop_limit_exceeded(self): test_trid = 0xc0ffee hoplimit = self.CONFIG_DHCPV6_RELAY_HOP_LIMIT pkt = DHCP6_RelayForward(hopcount=hoplimit + 1, peeraddr="fe80::f00:1337") / \ DHCP6OptIfaceId(ifaceid=b"ab") / \ DHCP6OptRelayMsg(message=DHCP6_Rebind(trid=test_trid)) self.assert_pkt_ignored(pkt, client_pkt=False)
def test_dhcpv6_relay_forward_from_unspec(self): hopcount = self.CONFIG_DHCPV6_RELAY_HOP_LIMIT - 1 peeraddr = "fe80::f00:1337" ifaceid = b"ab" self.assertGreater(hopcount, 0) pkt = DHCP6_RelayForward(peeraddr=peeraddr, hopcount=hopcount) / \ DHCP6OptIfaceId(ifaceid=ifaceid) / \ DHCP6OptRelayMsg(message=DHCP6_Rebind(trid=self.test_trid)) self.assert_pkt_ignored(pkt, ipv6_src="::")
def test_dhcpv6_simple_relay_reply_foreign_option(self): pkt = DHCP6_RelayReply(peeraddr=self.tap_lladdr) / \ DHCP6OptIfaceId(ifaceid=self.node_ifaceid) / \ DHCP6OptClientId() / \ DHCP6OptRelayMsg(message=DHCP6_Reply(trid=self.test_trid)) result = self.send_and_exp_pkts(pkt, DHCP6_Reply, client=False) self.assert_len(result, 1) pkt = result[0] self.assert_relayed_reply_pkt_w_trid(pkt, DHCP6_Reply) self.assert_node_responsive()
def test_dhcpv6_relay_forward_options_reversed(self): hopcount = self.CONFIG_DHCPV6_RELAY_HOP_LIMIT - 1 peeraddr = "fe80::f00:1337" ifaceid = b"ab" self.assertGreater(hopcount, 0) pkt = DHCP6_RelayForward(peeraddr=peeraddr, hopcount=hopcount) / \ DHCP6OptRelayMsg(message=DHCP6_Rebind(trid=self.test_trid)) / \ DHCP6OptIfaceId(ifaceid=ifaceid) rpkt = self._test_dhcpv6_relay_forward(pkt, hopcount, peeraddr, ifaceid) self.assertIn(DHCP6_Rebind, rpkt[DHCP6OptRelayMsg].message) self.assertEqual(rpkt[DHCP6OptRelayMsg].message[DHCP6_Rebind].trid, self.test_trid)
def test_dhcpv6_nested_relay_reply(self): peeraddr = "fe80::f00:affe" ifaceid = b"abcd" pkt = DHCP6_RelayReply(peeraddr=self.tap_lladdr) / \ DHCP6OptIfaceId(ifaceid=self.node_ifaceid) / \ DHCP6OptRelayMsg( message=DHCP6_RelayReply(peeraddr=peeraddr) / # noqa: E131 (easier to read with this indentation) DHCP6OptIfaceId(ifaceid=ifaceid) / DHCP6OptRelayMsg( message=DHCP6_Reconf(trid=self.test_trid) ) ) result = self.send_and_exp_pkts(pkt, DHCP6_Reconf, client=False) self.assert_len(result, 1) pkt = result[0] self.assertIn(DHCP6_RelayReply, pkt) self.assertNotIn(DHCP6_RelayReply, pkt[DHCP6_RelayReply].message) self.assertEqual(pkt[DHCP6_RelayReply].peeraddr, peeraddr) self.assertIn(DHCP6OptIfaceId, pkt) self.assertEqual(pkt[DHCP6OptIfaceId].ifaceid, ifaceid) self.assertIn(DHCP6_Reconf, pkt[DHCP6_RelayReply].message) self.assertEqual(pkt[DHCP6_Reconf].trid, self.test_trid) self.assert_node_responsive()
def test_dhcpv6_relay_reply_empty(self): pkt = DHCP6_RelayReply(peeraddr=self.tap_lladdr) / \ DHCP6OptIfaceId(ifaceid=self.node_ifaceid) / \ DHCP6OptRelayMsg() self.assert_pkt_ignored(pkt, client_pkt=False)
def test_dhcpv6_relay_reply_no_ifaceid_no_linkaddr(self): pkt = DHCP6_RelayReply(peeraddr=self.tap_lladdr) / \ DHCP6OptRelayMsg(message=DHCP6_Reply(trid=self.test_trid)) self.assert_pkt_ignored(pkt, client_pkt=False)
def test_dhcpv6_relay_reply_invalid_optlen(self): pkt = DHCP6_RelayReply(peeraddr=self.tap_lladdr) / \ DHCP6OptIfaceId(ifaceid=self.node_ifaceid) / \ DHCP6OptRelayMsg(optlen=32, message=DHCP6_Reply(trid=self.test_trid)) self.assert_pkt_ignored(pkt, client_pkt=False)
def test_dhcpv6_relay_reply_unexpected_peeraddr(self): pkt = DHCP6_RelayReply(peeraddr="fe80::abcd:f00:1337") / \ DHCP6OptIfaceId(ifaceid=self.node_ifaceid) / \ DHCP6OptRelayMsg(message=DHCP6_Reply(trid=self.test_trid)) self.assert_pkt_ignored(pkt, client_pkt=False)
def test_dhcpv6_relay_reply_unexpected_ifaceid(self): pkt = DHCP6_RelayReply(peeraddr=self.tap_lladdr) / \ DHCP6OptIfaceId(ifaceid=b"ab") / \ DHCP6OptRelayMsg(message=DHCP6_Reply(trid=self.test_trid)) self.assert_pkt_ignored(pkt, client_pkt=False)
def test_dhcpv6_simple_relay_reply_foreign_option_w_bogus_optlen(self): pkt = DHCP6_RelayReply(peeraddr=self.tap_lladdr) / \ DHCP6OptIfaceId(ifaceid=self.node_ifaceid) / \ DHCP6OptRelayMsg(message=DHCP6_Reply(trid=self.test_trid)) / \ DHCP6OptClientId(optlen=32) self.assert_pkt_ignored(pkt, client_pkt=False)
def test_dhcpv6_simple_relay_reply_options_reversed(self): pkt = DHCP6_RelayReply(peeraddr=self.tap_lladdr) / \ DHCP6OptRelayMsg(message=DHCP6_Reply(trid=self.test_trid)) / \ DHCP6OptIfaceId(ifaceid=self.node_ifaceid) self._test_dhcpv6_simple_relay_reply(pkt, DHCP6_Reply)
def test_dhcpv6_simple_relay_reply(self): pkt = DHCP6_RelayReply(peeraddr=self.tap_lladdr) / \ DHCP6OptIfaceId(ifaceid=self.node_ifaceid) / \ DHCP6OptRelayMsg(message=DHCP6_Advertise(trid=self.test_trid)) self._test_dhcpv6_simple_relay_reply(pkt, DHCP6_Advertise)