示例#1
0
    def test_no_prefix_available_in_advertise(self):
        """Advertise message contains NoPrefixAvail status code"""

        self.wait_for_solicit()
        noavail = DHCP6OptStatusCode(statuscode=6)  # NoPrefixAvail
        self.send_advertise(iapdopt=noavail)
        self.wait_for_solicit(is_resend=True)
示例#2
0
    def test_no_address_available_in_advertise(self):
        """Advertise message contains NoAddrsAvail status code"""

        self.wait_for_solicit()
        noavail = DHCP6OptStatusCode(statuscode=2)  # NoAddrsAvail
        self.send_advertise(ianaopts=noavail)
        self.wait_for_solicit(is_resend=True)
示例#3
0
    def test_dhcp_ia_na_send_solicit_receive_advertise(self):
        """Verify DHCPv6 IA NA Solicit packet and Advertise event"""

        self.vapi.dhcp6_clients_enable_disable(enable=1)

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        address = {"address": "1:2:3::5", "preferred_time": 60, "valid_time": 120}
        self.vapi.dhcp6_send_client_message(
            server_index=0xFFFFFFFF,
            mrc=1,
            msg_type=VppEnum.vl_api_dhcpv6_msg_type_t.DHCPV6_MSG_API_SOLICIT,
            sw_if_index=self.pg0.sw_if_index,
            T1=20,
            T2=40,
            addresses=[address],
            n_addresses=len([address]),
        )
        rx_list = self.pg0.get_capture(1)
        self.assertEqual(len(rx_list), 1)
        packet = rx_list[0]

        self.assertEqual(packet.haslayer(IPv6), 1)
        self.assertEqual(packet[IPv6].haslayer(DHCP6_Solicit), 1)

        client_duid = packet[DHCP6OptClientId].duid
        trid = packet[DHCP6_Solicit].trid

        dst = ip6_normalize(packet[IPv6].dst)
        dst2 = ip6_normalize("ff02::1:2")
        self.assert_equal(dst, dst2)
        src = ip6_normalize(packet[IPv6].src)
        src2 = ip6_normalize(self.pg0.local_ip6_ll)
        self.assert_equal(src, src2)
        ia_na = packet[DHCP6OptIA_NA]
        self.assert_equal(ia_na.T1, 20)
        self.assert_equal(ia_na.T2, 40)
        self.assert_equal(len(ia_na.ianaopts), 1)
        address = ia_na.ianaopts[0]
        self.assert_equal(address.addr, "1:2:3::5")
        self.assert_equal(address.preflft, 60)
        self.assert_equal(address.validlft, 120)

        self.vapi.want_dhcp6_reply_events(enable_disable=1, pid=os.getpid())

        try:
            ia_na_opts = DHCP6OptIAAddress(addr="7:8::2", preflft=60, validlft=120)
            p = (
                Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
                / IPv6(
                    src=util.mk_ll_addr(self.pg0.remote_mac), dst=self.pg0.local_ip6_ll
                )
                / UDP(sport=547, dport=546)
                / DHCP6_Advertise(trid=trid)
                / DHCP6OptServerId(duid=self.server_duid)
                / DHCP6OptClientId(duid=client_duid)
                / DHCP6OptPref(prefval=7)
                / DHCP6OptStatusCode(statuscode=1)
                / DHCP6OptIA_NA(iaid=1, T1=20, T2=40, ianaopts=ia_na_opts)
            )
            self.pg0.add_stream([p])
            self.pg_start()

            ev = self.vapi.wait_for_event(1, "dhcp6_reply_event")

            self.assert_equal(ev.preference, 7)
            self.assert_equal(ev.status_code, 1)
            self.assert_equal(ev.T1, 20)
            self.assert_equal(ev.T2, 40)

            reported_address = ev.addresses[0]
            address = ia_na_opts.getfieldval("addr")
            self.assert_equal(str(reported_address.address), address)
            self.assert_equal(
                reported_address.preferred_time, ia_na_opts.getfieldval("preflft")
            )
            self.assert_equal(
                reported_address.valid_time, ia_na_opts.getfieldval("validlft")
            )

        finally:
            self.vapi.want_dhcp6_reply_events(enable_disable=0)
        self.vapi.dhcp6_clients_enable_disable(enable=0)
示例#4
0
    def test_dhcp_pd_send_solicit_receive_advertise(self):
        """Verify DHCPv6 PD Solicit packet and Advertise event"""

        self.vapi.dhcp6_clients_enable_disable(enable=1)

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        prefix = {
            "prefix": {"address": "1:2:3::", "len": 50},
            "preferred_time": 60,
            "valid_time": 120,
        }
        prefixes = [prefix]
        self.vapi.dhcp6_pd_send_client_message(
            server_index=0xFFFFFFFF,
            mrc=1,
            msg_type=VppEnum.vl_api_dhcpv6_msg_type_t.DHCPV6_MSG_API_SOLICIT,
            sw_if_index=self.pg0.sw_if_index,
            T1=20,
            T2=40,
            prefixes=prefixes,
            n_prefixes=len(prefixes),
        )
        rx_list = self.pg0.get_capture(1)
        self.assertEqual(len(rx_list), 1)
        packet = rx_list[0]

        self.assertEqual(packet.haslayer(IPv6), 1)
        self.assertEqual(packet[IPv6].haslayer(DHCP6_Solicit), 1)

        client_duid = packet[DHCP6OptClientId].duid
        trid = packet[DHCP6_Solicit].trid

        dst = ip6_normalize(packet[IPv6].dst)
        dst2 = ip6_normalize("ff02::1:2")
        self.assert_equal(dst, dst2)
        src = ip6_normalize(packet[IPv6].src)
        src2 = ip6_normalize(self.pg0.local_ip6_ll)
        self.assert_equal(src, src2)
        ia_pd = packet[DHCP6OptIA_PD]
        self.assert_equal(ia_pd.T1, 20)
        self.assert_equal(ia_pd.T2, 40)
        self.assert_equal(len(ia_pd.iapdopt), 1)
        prefix = ia_pd.iapdopt[0]
        self.assert_equal(prefix.prefix, "1:2:3::")
        self.assert_equal(prefix.plen, 50)
        self.assert_equal(prefix.preflft, 60)
        self.assert_equal(prefix.validlft, 120)

        self.vapi.want_dhcp6_pd_reply_events(enable_disable=1, pid=os.getpid())

        try:
            ia_pd_opts = DHCP6OptIAPrefix(
                prefix="7:8::", plen=56, preflft=60, validlft=120
            )
            p = (
                Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
                / IPv6(
                    src=util.mk_ll_addr(self.pg0.remote_mac), dst=self.pg0.local_ip6_ll
                )
                / UDP(sport=547, dport=546)
                / DHCP6_Advertise(trid=trid)
                / DHCP6OptServerId(duid=self.server_duid)
                / DHCP6OptClientId(duid=client_duid)
                / DHCP6OptPref(prefval=7)
                / DHCP6OptStatusCode(statuscode=1)
                / DHCP6OptIA_PD(iaid=1, T1=20, T2=40, iapdopt=ia_pd_opts)
            )
            self.pg0.add_stream([p])
            self.pg_start()

            ev = self.vapi.wait_for_event(1, "dhcp6_pd_reply_event")

            self.assert_equal(ev.preference, 7)
            self.assert_equal(ev.status_code, 1)
            self.assert_equal(ev.T1, 20)
            self.assert_equal(ev.T2, 40)

            reported_prefix = ev.prefixes[0]
            prefix = ia_pd_opts.getfieldval("prefix")
            self.assert_equal(str(reported_prefix.prefix).split("/")[0], prefix)
            self.assert_equal(
                int(str(reported_prefix.prefix).split("/")[1]),
                ia_pd_opts.getfieldval("plen"),
            )
            self.assert_equal(
                reported_prefix.preferred_time, ia_pd_opts.getfieldval("preflft")
            )
            self.assert_equal(
                reported_prefix.valid_time, ia_pd_opts.getfieldval("validlft")
            )

        finally:
            self.vapi.want_dhcp6_pd_reply_events(enable_disable=0)
        self.vapi.dhcp6_clients_enable_disable(enable=0)
    def test_dhcp6_proxy(self):
        """ DHCPv6 Proxy"""
        #
        # Verify no response to DHCP request without DHCP config
        #
        dhcp_solicit_dst = "ff02::1:2"
        dhcp_solicit_src_vrf0 = mk_ll_addr(self.pg2.remote_mac)
        dhcp_solicit_src_vrf1 = mk_ll_addr(self.pg3.remote_mac)
        server_addr_vrf0 = self.pg0.remote_ip6n
        src_addr_vrf0 = self.pg0.local_ip6n
        server_addr_vrf1 = self.pg1.remote_ip6n
        src_addr_vrf1 = self.pg1.local_ip6n

        dmac = in6_getnsmac(inet_pton(socket.AF_INET6, dhcp_solicit_dst))
        p_solicit_vrf0 = (
            Ether(dst=dmac, src=self.pg2.remote_mac) /
            IPv6(src=dhcp_solicit_src_vrf0, dst=dhcp_solicit_dst) /
            UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) /
            DHCP6_Solicit())
        p_solicit_vrf1 = (
            Ether(dst=dmac, src=self.pg3.remote_mac) /
            IPv6(src=dhcp_solicit_src_vrf1, dst=dhcp_solicit_dst) /
            UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) /
            DHCP6_Solicit())

        self.send_and_assert_no_replies(self.pg2, p_solicit_vrf0,
                                        "DHCP with no configuration")
        self.send_and_assert_no_replies(self.pg3, p_solicit_vrf1,
                                        "DHCP with no configuration")

        #
        # DHCPv6 config in VRF 0.
        # Packets still dropped because the client facing interface has no
        # IPv6 config
        #
        self.vapi.dhcp_proxy_config(server_addr_vrf0,
                                    src_addr_vrf0,
                                    rx_table_id=0,
                                    server_table_id=0,
                                    is_ipv6=1)

        self.send_and_assert_no_replies(self.pg2, p_solicit_vrf0,
                                        "DHCP with no configuration")
        self.send_and_assert_no_replies(self.pg3, p_solicit_vrf1,
                                        "DHCP with no configuration")

        #
        # configure an IP address on the client facing interface
        #
        self.pg2.config_ip6()

        #
        # Now the DHCP requests are relayed to the server
        #
        self.pg2.add_stream(p_solicit_vrf0)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg0.get_capture(1)

        self.verify_dhcp6_solicit(rx[0], self.pg0, dhcp_solicit_src_vrf0,
                                  self.pg2.remote_mac)

        #
        # Exception cases for rejected relay responses
        #

        # 1 - not a relay reply
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_Advertise())
        self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
                                        "DHCP6 not a relay reply")

        # 2 - no relay message option
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() / DHCP6_Advertise())
        self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
                                        "DHCP not a relay message")

        # 3 - no circuit ID
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() / DHCP6OptRelayMsg(optlen=0) /
                      DHCP6_Advertise())
        self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
                                        "DHCP6 no circuit ID")
        # 4 - wrong circuit ID
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise())
        self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
                                        "DHCP6 wrong circuit ID")

        #
        # Send the relay response (the advertisement)
        #   - no peer address
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x03') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
                      DHCP6OptStatusCode(statuscode=0))
        pkts_adv_vrf0 = [p_adv_vrf0]

        self.pg0.add_stream(pkts_adv_vrf0)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg2.get_capture(1)

        self.verify_dhcp6_advert(rx[0], self.pg2, "::")

        #
        # Send the relay response (the advertisement)
        #   - with peer address
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf0) /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x03') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
                      DHCP6OptStatusCode(statuscode=0))
        pkts_adv_vrf0 = [p_adv_vrf0]

        self.pg0.add_stream(pkts_adv_vrf0)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg2.get_capture(1)

        self.verify_dhcp6_advert(rx[0], self.pg2, dhcp_solicit_src_vrf0)

        #
        # Add all the config for VRF 1
        #
        self.vapi.dhcp_proxy_config(server_addr_vrf1,
                                    src_addr_vrf1,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_ipv6=1)
        self.pg3.config_ip6()

        #
        # VRF 1 solicit
        #
        self.pg3.add_stream(p_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac)

        #
        # VRF 1 Advert
        #
        p_adv_vrf1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
                      IPv6(dst=self.pg1.local_ip6, src=self.pg1.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
                      DHCP6OptStatusCode(statuscode=0))
        pkts_adv_vrf1 = [p_adv_vrf1]

        self.pg1.add_stream(pkts_adv_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg3.get_capture(1)

        self.verify_dhcp6_advert(rx[0], self.pg3, dhcp_solicit_src_vrf1)

        #
        # Add VSS config
        #  table=1, fib=id=1, oui=4
        self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_ip6=1)

        self.pg3.add_stream(p_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        self.verify_dhcp6_solicit(rx[0],
                                  self.pg1,
                                  dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac,
                                  fib_id=1,
                                  oui=4)

        #
        # Remove the VSS config
        #  relayed DHCP has default vlaues in the option.
        #
        self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_ip6=1, is_add=0)

        self.pg3.add_stream(p_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac)

        #
        # Add a second DHCP server in VRF 1
        #  expect clients messages to be relay to both configured servers
        #
        self.pg1.generate_remote_hosts(2)
        server_addr2 = socket.inet_pton(AF_INET6, self.pg1.remote_hosts[1].ip6)

        self.vapi.dhcp_proxy_config(server_addr2,
                                    src_addr_vrf1,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_ipv6=1)

        #
        # We'll need an ND entry for the server to send it packets
        #
        nd_entry = VppNeighbor(self,
                               self.pg1.sw_if_index,
                               self.pg1.remote_hosts[1].mac,
                               self.pg1.remote_hosts[1].ip6,
                               af=AF_INET6)
        nd_entry.add_vpp_config()

        #
        # Send a discover from the client. expect two relayed messages
        # The frist packet is sent to the second server
        # We're not enforcing that here, it's just the way it is.
        #
        self.pg3.add_stream(p_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(2)

        self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac)
        self.verify_dhcp6_solicit(rx[1],
                                  self.pg1,
                                  dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac,
                                  dst_mac=self.pg1.remote_hosts[1].mac,
                                  dst_ip=self.pg1.remote_hosts[1].ip6)

        #
        # Send both packets back. Client gets both.
        #
        p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
              IPv6(dst=self.pg1.local_ip6, src=self.pg1.remote_ip6) /
              UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
              DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
              DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
              DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
              DHCP6OptStatusCode(statuscode=0))
        p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_hosts[1].mac) /
              IPv6(dst=self.pg1.local_ip6, src=self.pg1._remote_hosts[1].ip6) /
              UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
              DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
              DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
              DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
              DHCP6OptStatusCode(statuscode=0))

        pkts = [p1, p2]

        self.pg1.add_stream(pkts)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg3.get_capture(2)

        self.verify_dhcp6_advert(rx[0], self.pg3, dhcp_solicit_src_vrf1)
        self.verify_dhcp6_advert(rx[1], self.pg3, dhcp_solicit_src_vrf1)

        #
        # Ensure only solicit messages are duplicated
        #
        p_request_vrf1 = (
            Ether(dst=dmac, src=self.pg3.remote_mac) /
            IPv6(src=dhcp_solicit_src_vrf1, dst=dhcp_solicit_dst) /
            UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) /
            DHCP6_Request())

        self.pg3.add_stream(p_request_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        #
        # Test we drop DHCP packets from addresses that are not configured as
        # DHCP servers
        #
        p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_hosts[1].mac) /
              IPv6(dst=self.pg1.local_ip6, src="3001::1") /
              UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
              DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
              DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
              DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
              DHCP6OptStatusCode(statuscode=0))
        self.send_and_assert_no_replies(self.pg1, p2, "DHCP6 not from server")

        #
        # Remove the second DHCP server
        #
        self.vapi.dhcp_proxy_config(server_addr2,
                                    src_addr_vrf1,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_ipv6=1,
                                    is_add=0)

        #
        # Test we can still relay with the first
        #
        self.pg3.add_stream(p_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)

        self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac)

        #
        # Cleanup
        #
        self.vapi.dhcp_proxy_config(server_addr_vrf1,
                                    src_addr_vrf1,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_ipv6=1,
                                    is_add=0)
        self.vapi.dhcp_proxy_config(server_addr_vrf0,
                                    src_addr_vrf0,
                                    rx_table_id=0,
                                    server_table_id=0,
                                    is_ipv6=1,
                                    is_add=0)

        # duplicate delete
        self.vapi.dhcp_proxy_config(server_addr_vrf0,
                                    src_addr_vrf0,
                                    rx_table_id=0,
                                    server_table_id=0,
                                    is_ipv6=1,
                                    is_add=0)
        self.pg2.unconfig_ip6()
        self.pg3.unconfig_ip6()
示例#6
0
    def test_dhcp_ia_na_send_solicit_receive_advertise(self):
        """ Verify DHCPv6 IA NA Solicit packet and Advertise envent """

        self.vapi.dhcp6_clients_enable_disable()

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        address_bin = '\00\01\00\02\00\03' + '\00' * 8 + '\00\05'
        address = {'address': address_bin,
                   'preferred_time': 60,
                   'valid_time': 120}
        self.vapi.dhcp6_send_client_message(1, self.pg0.sw_if_index,
                                            T1=20, T2=40, addresses=[address])
        rx_list = self.pg0.get_capture(1)
        self.assertEqual(len(rx_list), 1)
        packet = rx_list[0]

        self.assertTrue(packet.haslayer(IPv6))
        self.assertTrue(packet[IPv6].haslayer(DHCP6_Solicit))

        client_duid = packet[DHCP6OptClientId].duid
        trid = packet[DHCP6_Solicit].trid

        dst = ip6_normalize(packet[IPv6].dst)
        dst2 = ip6_normalize("ff02::1:2")
        self.assert_equal(dst, dst2)
        src = ip6_normalize(packet[IPv6].src)
        src2 = ip6_normalize(self.pg0.local_ip6_ll)
        self.assert_equal(src, src2)
        ia_na = packet[DHCP6OptIA_NA]
        self.assert_equal(ia_na.T1, 20)
        self.assert_equal(ia_na.T2, 40)
        self.assert_equal(len(ia_na.ianaopts), 1)
        address = ia_na.ianaopts[0]
        self.assert_equal(address.addr, '1:2:3::5')
        self.assert_equal(address.preflft, 60)
        self.assert_equal(address.validlft, 120)

        self.vapi.want_dhcp6_reply_events()

        try:
            ia_na_opts = DHCP6OptIAAddress(addr='7:8::2', preflft=60,
                                           validlft=120)
            p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src=mk_ll_addr(self.pg0.remote_mac),
                      dst=self.pg0.local_ip6_ll) /
                 UDP(sport=547, dport=546) /
                 DHCP6_Advertise(trid=trid) /
                 DHCP6OptServerId(duid=self.server_duid) /
                 DHCP6OptClientId(duid=client_duid) /
                 DHCP6OptPref(prefval=7) /
                 DHCP6OptStatusCode(statuscode=1) /
                 DHCP6OptIA_NA(iaid=1, T1=20, T2=40, ianaopts=ia_na_opts)
                 )
            self.pg0.add_stream([p])
            self.pg_start()

            ev = self.vapi.wait_for_event(1, "dhcp6_reply_event")

            self.assert_equal(ev.preference, 7)
            self.assert_equal(ev.status_code, 1)
            self.assert_equal(ev.T1, 20)
            self.assert_equal(ev.T2, 40)

            reported_address = ev.addresses[0]
            address = inet_pton(AF_INET6, ia_na_opts.getfieldval("addr"))
            self.assert_equal(reported_address.address, address)
            self.assert_equal(reported_address.preferred_time,
                              ia_na_opts.getfieldval("preflft"))
            self.assert_equal(reported_address.valid_time,
                              ia_na_opts.getfieldval("validlft"))

        finally:
            self.vapi.want_dhcp6_reply_events(enable_disable=0)
示例#7
0
    def test_dhcp_pd_send_solicit_receive_advertise(self):
        """ Verify DHCPv6 PD Solicit packet and Advertise envent """

        self.vapi.dhcp6_clients_enable_disable()

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        prefix_bin = '\00\01\00\02\00\03' + '\00' * 10
        prefix = {'prefix': prefix_bin,
                  'prefix_length': 50,
                  'preferred_time': 60,
                  'valid_time': 120}
        self.vapi.dhcp6_pd_send_client_message(1, self.pg0.sw_if_index,
                                               T1=20, T2=40, prefixes=[prefix])
        rx_list = self.pg0.get_capture(1)
        self.assertEqual(len(rx_list), 1)
        packet = rx_list[0]

        self.assertTrue(packet.haslayer(IPv6))
        self.assertTrue(packet[IPv6].haslayer(DHCP6_Solicit))

        client_duid = packet[DHCP6OptClientId].duid
        trid = packet[DHCP6_Solicit].trid

        dst = ip6_normalize(packet[IPv6].dst)
        dst2 = ip6_normalize("ff02::1:2")
        self.assert_equal(dst, dst2)
        src = ip6_normalize(packet[IPv6].src)
        src2 = ip6_normalize(self.pg0.local_ip6_ll)
        self.assert_equal(src, src2)
        ia_pd = packet[DHCP6OptIA_PD]
        self.assert_equal(ia_pd.T1, 20)
        self.assert_equal(ia_pd.T2, 40)
        self.assert_equal(len(ia_pd.iapdopt), 1)
        prefix = ia_pd.iapdopt[0]
        self.assert_equal(prefix.prefix, '1:2:3::')
        self.assert_equal(prefix.plen, 50)
        self.assert_equal(prefix.preflft, 60)
        self.assert_equal(prefix.validlft, 120)

        self.vapi.want_dhcp6_pd_reply_events()

        try:
            ia_pd_opts = DHCP6OptIAPrefix(prefix='7:8::', plen=56, preflft=60,
                                          validlft=120)
            p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src=mk_ll_addr(self.pg0.remote_mac),
                      dst=self.pg0.local_ip6_ll) /
                 UDP(sport=547, dport=546) /
                 DHCP6_Advertise(trid=trid) /
                 DHCP6OptServerId(duid=self.server_duid) /
                 DHCP6OptClientId(duid=client_duid) /
                 DHCP6OptPref(prefval=7) /
                 DHCP6OptStatusCode(statuscode=1) /
                 DHCP6OptIA_PD(iaid=1, T1=20, T2=40, iapdopt=ia_pd_opts)
                 )
            self.pg0.add_stream([p])
            self.pg_start()

            ev = self.vapi.wait_for_event(1, "dhcp6_pd_reply_event")

            self.assert_equal(ev.preference, 7)
            self.assert_equal(ev.status_code, 1)
            self.assert_equal(ev.T1, 20)
            self.assert_equal(ev.T2, 40)

            reported_prefix = ev.prefixes[0]
            prefix = inet_pton(AF_INET6, ia_pd_opts.getfieldval("prefix"))
            self.assert_equal(reported_prefix.prefix, prefix)
            self.assert_equal(reported_prefix.prefix_length,
                              ia_pd_opts.getfieldval("plen"))
            self.assert_equal(reported_prefix.preferred_time,
                              ia_pd_opts.getfieldval("preflft"))
            self.assert_equal(reported_prefix.valid_time,
                              ia_pd_opts.getfieldval("validlft"))

        finally:
            self.vapi.want_dhcp6_pd_reply_events(enable_disable=0)
示例#8
0
    def test_dhcp6_proxy(self):
        """ DHCPv6 Proxy"""
        #
        # Verify no response to DHCP request without DHCP config
        #
        dhcp_solicit_dst = "ff02::1:2"
        dhcp_solicit_src_vrf0 = mk_ll_addr(self.pg2.remote_mac)
        dhcp_solicit_src_vrf1 = mk_ll_addr(self.pg3.remote_mac)
        server_addr_vrf0 = self.pg0.remote_ip6n
        src_addr_vrf0 = self.pg0.local_ip6n
        server_addr_vrf1 = self.pg1.remote_ip6n
        src_addr_vrf1 = self.pg1.local_ip6n

        dmac = in6_getnsmac(inet_pton(socket.AF_INET6, dhcp_solicit_dst))
        p_solicit_vrf0 = (
            Ether(dst=dmac, src=self.pg2.remote_mac) /
            IPv6(src=dhcp_solicit_src_vrf0, dst=dhcp_solicit_dst) /
            UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) /
            DHCP6_Solicit())
        pkts_solicit_vrf0 = [p_solicit_vrf0]
        p_solicit_vrf1 = (
            Ether(dst=dmac, src=self.pg3.remote_mac) /
            IPv6(src=dhcp_solicit_src_vrf1, dst=dhcp_solicit_dst) /
            UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) /
            DHCP6_Solicit())
        pkts_solicit_vrf1 = [p_solicit_vrf1]

        self.send_and_assert_no_replies(self.pg2, pkts_solicit_vrf0,
                                        "DHCP with no configuration")
        self.send_and_assert_no_replies(self.pg3, pkts_solicit_vrf1,
                                        "DHCP with no configuration")

        #
        # DHCPv6 config in VRF 0.
        # Packets still dropped because the client facing interface has no
        # IPv6 config
        #
        self.vapi.dhcp_proxy_config(server_addr_vrf0,
                                    src_addr_vrf0,
                                    rx_table_id=0,
                                    server_table_id=0,
                                    is_ipv6=1)

        self.send_and_assert_no_replies(self.pg2, pkts_solicit_vrf0,
                                        "DHCP with no configuration")
        self.send_and_assert_no_replies(self.pg3, pkts_solicit_vrf1,
                                        "DHCP with no configuration")

        #
        # configure an IP address on the client facing interface
        #
        self.pg2.config_ip6()

        #
        # Now the DHCP requests are relayed to the server
        #
        self.pg2.add_stream(pkts_solicit_vrf0)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg0.get_capture(1)
        rx = rx[0]
        self.verify_dhcp6_solicit(rx, self.pg0, dhcp_solicit_src_vrf0,
                                  self.pg2.remote_mac)

        #
        # Exception cases for rejected relay responses
        #

        # 1 - not a relay reply
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_Advertise())
        pkts_adv_vrf0 = [p_adv_vrf0]
        self.send_and_assert_no_replies(self.pg2, pkts_adv_vrf0,
                                        "DHCP6 not a relay reply")

        # 2 - no relay message option
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() / DHCP6_Advertise())
        pkts_adv_vrf0 = [p_adv_vrf0]
        self.send_and_assert_no_replies(self.pg2, pkts_adv_vrf0,
                                        "DHCP not a relay message")

        # 3 - no circuit ID
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() / DHCP6OptRelayMsg(optlen=0) /
                      DHCP6_Advertise())
        pkts_adv_vrf0 = [p_adv_vrf0]
        self.send_and_assert_no_replies(self.pg2, pkts_adv_vrf0,
                                        "DHCP6 no circuit ID")
        # 4 - wrong circuit ID
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise())
        pkts_adv_vrf0 = [p_adv_vrf0]
        self.send_and_assert_no_replies(self.pg2, pkts_adv_vrf0,
                                        "DHCP6 wrong circuit ID")

        #
        # Send the relay response (the advertisement)
        #   - no peer address
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply() /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x03') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
                      DHCP6OptStatusCode(statuscode=0))
        pkts_adv_vrf0 = [p_adv_vrf0]

        self.pg0.add_stream(pkts_adv_vrf0)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg2.get_capture(1)
        rx = rx[0]
        self.verify_dhcp6_advert(rx, self.pg2, "::")

        #
        # Send the relay response (the advertisement)
        #   - with peer address
        p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                      IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf0) /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x03') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
                      DHCP6OptStatusCode(statuscode=0))
        pkts_adv_vrf0 = [p_adv_vrf0]

        self.pg0.add_stream(pkts_adv_vrf0)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg2.get_capture(1)
        rx = rx[0]
        self.verify_dhcp6_advert(rx, self.pg2, dhcp_solicit_src_vrf0)

        #
        # Add all the config for VRF 1
        #
        self.vapi.dhcp_proxy_config(server_addr_vrf1,
                                    src_addr_vrf1,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_ipv6=1)
        self.pg3.config_ip6()

        #
        # VRF 1 solicit
        #
        self.pg3.add_stream(pkts_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)
        rx = rx[0]
        self.verify_dhcp6_solicit(rx, self.pg1, dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac)

        #
        # VRF 1 Advert
        #
        p_adv_vrf1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
                      IPv6(dst=self.pg1.local_ip6, src=self.pg1.remote_ip6) /
                      UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
                      DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
                      DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
                      DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) /
                      DHCP6OptStatusCode(statuscode=0))
        pkts_adv_vrf1 = [p_adv_vrf1]

        self.pg1.add_stream(pkts_adv_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg3.get_capture(1)
        rx = rx[0]
        self.verify_dhcp6_advert(rx, self.pg3, dhcp_solicit_src_vrf1)

        #
        # Add VSS config
        #  table=1, fib=id=1, oui=4
        self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_ip6=1)

        self.pg3.add_stream(pkts_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)
        rx = rx[0]
        self.verify_dhcp6_solicit(rx,
                                  self.pg1,
                                  dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac,
                                  fib_id=1,
                                  oui=4)

        #
        # Remove the VSS config
        #  relayed DHCP has default vlaues in the option.
        #
        self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_ip6=1, is_add=0)

        self.pg3.add_stream(pkts_solicit_vrf1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg1.get_capture(1)
        rx = rx[0]
        self.verify_dhcp6_solicit(rx, self.pg1, dhcp_solicit_src_vrf1,
                                  self.pg3.remote_mac)

        #
        # Cleanup
        #
        self.vapi.dhcp_proxy_config(server_addr_vrf1,
                                    src_addr_vrf1,
                                    rx_table_id=1,
                                    server_table_id=1,
                                    is_ipv6=1,
                                    is_add=0)
        self.vapi.dhcp_proxy_config(server_addr_vrf1,
                                    src_addr_vrf1,
                                    rx_table_id=0,
                                    server_table_id=0,
                                    is_ipv6=1,
                                    is_add=0)