From a6d13a60fff36a47b1aaf370c482d0cf24c61139 Mon Sep 17 00:00:00 2001 From: Razvan Becheriu Date: Mon, 14 Feb 2022 15:45:29 +0200 Subject: [PATCH] [#1695] added support for RAI relay suboption 11 (RAI_OPTION_SERVER_ID_OVERRIDE) --- doc/sphinx/arm/dhcp4-srv.rst | 87 ++++++++++++----------- src/bin/dhcp4/dhcp4_srv.cc | 8 +++ src/bin/dhcp4/tests/dhcp4_srv_unittest.cc | 40 +++++++++-- 3 files changed, 86 insertions(+), 49 deletions(-) diff --git a/doc/sphinx/arm/dhcp4-srv.rst b/doc/sphinx/arm/dhcp4-srv.rst index 67ac2677b8..d90ea25083 100644 --- a/doc/sphinx/arm/dhcp4-srv.rst +++ b/doc/sphinx/arm/dhcp4-srv.rst @@ -2035,6 +2035,8 @@ to be configured with those options. +--------------------+------+----------------------------------------------------------------------+ | subscriber-id | 6 | Can be used with flex-id to identify hosts. | +--------------------+------+----------------------------------------------------------------------+ + | server-id-override | 11 | If sent by the relay, Kea accepts it as the `server-id`. | + +--------------------+------+----------------------------------------------------------------------+ | relay-source-port | 19 | If sent by the relay, Kea sends back its responses to this port. | +--------------------+------+----------------------------------------------------------------------+ @@ -6699,28 +6701,27 @@ Supported DHCP Standards The following standards are currently supported in Kea: -- *BOOTP Vendor Information Extensions*, `RFC - 1497 `__: This requires the open - source BOOTP hook to be loaded. See :ref:`hooks-bootp` for details. +- *BOOTP Vendor Information Extensions*, `RFC 1497 + `__: This requires the open source + BOOTP hook to be loaded. See :ref:`hooks-bootp` for details. -- *Dynamic Host Configuration Protocol*, `RFC - 2131 `__: Supported messages are +- *Dynamic Host Configuration Protocol*, `RFC 2131 + `__: Supported messages are DHCPDISCOVER (1), DHCPOFFER (2), DHCPREQUEST (3), DHCPRELEASE (7), DHCPINFORM (8), DHCPACK (5), and DHCPNAK(6). -- *DHCP Options and BOOTP Vendor Extensions*, `RFC - 2132 `__: Supported options are - PAD (0), END(255), Message Type(53), DHCP Server Identifier (54), - Domain Name (15), DNS Servers (6), IP Address Lease Time (51), Subnet - Mask (1), and Routers (3). +- *DHCP Options and BOOTP Vendor Extensions*, `RFC 2132 + `__: Supported options are PAD (0), + END(255), Message Type(53), DHCP Server Identifier (54), Domain Name (15), + DNS Servers (6), IP Address Lease Time (51), Subnet Mask (1), and Routers (3). -- *The IPv4 Subnet Selection Option for DHCP*, `RFC - 3011 `__: The subnet-selection option - is supported; if received in a packet, it is used in the subnet-selection +- *The IPv4 Subnet Selection Option for DHCP*, `RFC 3011 + `__: The subnet-selection option is + supported; if received in a packet, it is used in the subnet-selection process. -- *DHCP Relay Agent Information Option*, `RFC - 3046 `__: Relay Agent Information, +- *DHCP Relay Agent Information Option*, `RFC 3046 + `__: Relay Agent Information, Circuit ID, and Remote ID options are supported. - *Link Selection sub-option for the Relay Agent Option*, `RFC 3527 @@ -6728,45 +6729,47 @@ The following standards are currently supported in Kea: is supported. - *Vendor-Identifying Vendor Options for Dynamic Host Configuration - Protocol version 4*, `RFC - 3925 `__: The Vendor-Identifying - Vendor Class and Vendor-Identifying Vendor-Specific Information - options are supported. + Protocol version 4*, `RFC 3925 + `__: The Vendor-Identifying Vendor Class + and Vendor-Identifying Vendor-Specific Information options are supported. -- *Subscriber-ID Suboption for the DHCP Relay Agent Option*, `RFC - 3993 `__: The Subscriber-ID - option is supported. +- *Subscriber-ID Suboption for the DHCP Relay Agent Option*, `RFC 3993 + `__: The Subscriber-ID option is + supported. - *The Dynamic Host Configuration Protocol (DHCP) Client Fully Qualified Domain Name (FQDN) Option*, `RFC 4702 - `__: The Kea server is able to - handle the Client FQDN option. Also, it is able to use the - ``kea-dhcp-ddns`` component to initiate appropriate DNS Update - operations. + `__: The Kea server is able to handle + the Client FQDN option. Also, it is able to use the ``kea-dhcp-ddns`` + component to initiate appropriate DNS Update operations. -- *Resolution of Fully Qualified Domain Name (FQDN) Conflicts among Dynamic Host - Configuration Protocol (DHCP) Clients*, `RFC 4703 +- *Resolution of Fully Qualified Domain Name (FQDN) Conflicts among Dynamic + Host Configuration Protocol (DHCP) Clients*, `RFC 4703 `__: The DHCPv6 server uses a DHCP-DDNS server to resolve conflicts. -- *Client Identifier Option in DHCP Server Replies*, `RFC - 6842 `__: The server by default sends - back the ``client-id`` option. That capability can be disabled. See :ref:`dhcp4-echo-client-id` for details. +- *Client Identifier Option in DHCP Server Replies*, `RFC 6842 + `__: The server by default sends back + the ``client-id`` option. That capability can be disabled. See + :ref:`dhcp4-echo-client-id` for details. -- *Generalized UDP Source Port for DHCP Relay*, `RFC 8357 - `__: The Kea server - handles the Relay Agent Information Source Port sub-option in a received - message, remembers the UDP port, and sends back a reply to the same relay - agent using this UDP port. +- *Generalized UDP Source Port for the DHCP Relay Agent Option*, `RFC 8357 + `__: The Kea server handles the Relay + Agent Information Source Port sub-option in a received message, remembers the + UDP port, and sends back a reply to the same relay agent using this UDP port. -- *Captive-Portal Identification in DHCP and Router Advertisements (RAs)*, `RFC 8910 - `__: The Kea server can configure both v4 - and v6 versions of the captive portal options. +- *Captive-Portal Identification in DHCP and Router Advertisements (RAs)*, `RFC + 8910 `__: The Kea server can configure + both v4 and v6 versions of the captive portal options. - *IPv6-Only Preferred Option for DHCPv4*, `RFC 8925 - `__: The Kea - server is able to designate its pools and subnets as IPv6-Only Preferred and send - back the ``v6-only-preferred`` option to clients that requested it. + `__: The Kea server is able to designate + its pools and subnets as IPv6-Only Preferred and send back the + ``v6-only-preferred`` option to clients that requested it. + +- *Server Identifier Override sub-option for the Relay Agent Option*, `RFC 5107 + `__: The server identifier override + sub-option is supported. Known RFC Violations -------------------- diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index e8b6697981..9c291639c0 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -3695,6 +3695,14 @@ Dhcpv4Srv::acceptServerId(const Pkt4Ptr& query) const { return (false); } + OptionPtr rai_option = query->getOption(DHO_DHCP_AGENT_OPTIONS); + if (rai_option) { + OptionPtr rai_suboption = rai_option->getOption(RAI_OPTION_SERVER_ID_OVERRIDE); + if (rai_suboption && (server_id.toBytes() == rai_suboption->toBinary())) { + return (true); + } + } + // This function iterates over all interfaces on which the // server is listening to find the one which has a socket bound // to the address carried in the server identifier option. diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index 69f638339a..56ccc1caa5 100644 --- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc @@ -2448,7 +2448,7 @@ TEST_F(Dhcpv4SrvTest, acceptServerId) { // used by the server. The accepted server ids are the IPv4 addresses // configured on the interfaces. The 10.1.2.3 is not configured on // any interfaces. - OptionCustomPtr other_serverid(new OptionCustom(def, Option::V6)); + OptionCustomPtr other_serverid(new OptionCustom(def, Option::V4)); other_serverid->writeAddress(IOAddress("10.1.2.3")); pkt->addOption(other_serverid); EXPECT_FALSE(srv.acceptServerId(pkt)); @@ -2458,7 +2458,7 @@ TEST_F(Dhcpv4SrvTest, acceptServerId) { // Add a server id being an IPv4 address configured on eth1 interface. // A DHCPv4 message holding this server identifier should be accepted. - OptionCustomPtr eth1_serverid(new OptionCustom(def, Option::V6)); + OptionCustomPtr eth1_serverid(new OptionCustom(def, Option::V4)); eth1_serverid->writeAddress(IOAddress("192.0.2.3")); ASSERT_NO_THROW(pkt->addOption(eth1_serverid)); EXPECT_TRUE(srv.acceptServerId(pkt)); @@ -2468,7 +2468,7 @@ TEST_F(Dhcpv4SrvTest, acceptServerId) { // Add a server id being an IPv4 address configured on eth0 interface. // A DHCPv4 message holding this server identifier should be accepted. - OptionCustomPtr eth0_serverid(new OptionCustom(def, Option::V6)); + OptionCustomPtr eth0_serverid(new OptionCustom(def, Option::V4)); eth0_serverid->writeAddress(IOAddress("10.0.0.1")); ASSERT_NO_THROW(pkt->addOption(eth0_serverid)); EXPECT_TRUE(srv.acceptServerId(pkt)); @@ -2478,7 +2478,7 @@ TEST_F(Dhcpv4SrvTest, acceptServerId) { // Add a server id being an IPv4 address configured on subnet3. // A DHCPv4 message holding this server identifier should be accepted. - OptionCustomPtr subnet_serverid(new OptionCustom(def, Option::V6)); + OptionCustomPtr subnet_serverid(new OptionCustom(def, Option::V4)); subnet_serverid->writeAddress(IOAddress("192.0.3.254")); ASSERT_NO_THROW(pkt->addOption(subnet_serverid)); EXPECT_TRUE(srv.acceptServerId(pkt)); @@ -2488,7 +2488,7 @@ TEST_F(Dhcpv4SrvTest, acceptServerId) { // Add a server id being an IPv4 address configured on shared network1. // A DHCPv4 message holding this server identifier should be accepted. - OptionCustomPtr network_serverid(new OptionCustom(def, Option::V6)); + OptionCustomPtr network_serverid(new OptionCustom(def, Option::V4)); network_serverid->writeAddress(IOAddress("192.0.4.254")); ASSERT_NO_THROW(pkt->addOption(network_serverid)); EXPECT_TRUE(srv.acceptServerId(pkt)); @@ -2499,7 +2499,7 @@ TEST_F(Dhcpv4SrvTest, acceptServerId) { // Add a server id being an IPv4 address configured on client class. // A DHCPv4 message holding this server identifier should be accepted. Pkt4Ptr pkt_with_classes(new Pkt4(DHCPREQUEST, 1234)); - OptionCustomPtr class_serverid(new OptionCustom(def, Option::V6)); + OptionCustomPtr class_serverid(new OptionCustom(def, Option::V4)); class_serverid->writeAddress(IOAddress("192.0.5.254")); ASSERT_NO_THROW(pkt_with_classes->addOption(class_serverid)); pkt_with_classes->addClass("foo"); @@ -2512,7 +2512,7 @@ TEST_F(Dhcpv4SrvTest, acceptServerId) { // The configured class does not define the server id option. // A DHCPv4 message holding this server identifier should be accepted. Pkt4Ptr pkt_with_classes_option_not_defined(new Pkt4(DHCPREQUEST, 1234)); - OptionCustomPtr global_serverid(new OptionCustom(def, Option::V6)); + OptionCustomPtr global_serverid(new OptionCustom(def, Option::V4)); global_serverid->writeAddress(IOAddress("10.0.0.254")); ASSERT_NO_THROW(pkt_with_classes_option_not_defined->addOption(global_serverid)); pkt_with_classes_option_not_defined->addClass("bar"); @@ -2539,6 +2539,32 @@ TEST_F(Dhcpv4SrvTest, acceptServerId) { // Remove the server identifier. ASSERT_NO_THROW(pkt->delOption(DHO_DHCP_SERVER_IDENTIFIER)); + + OptionDefinitionPtr rai_def = LibDHCP::getOptionDef(DHCP4_OPTION_SPACE, + DHO_DHCP_AGENT_OPTIONS); + + OptionBuffer override_server_id_buf(IOAddress("10.0.0.128").toBytes()); + + // Create RAI option. + OptionCustomPtr rai(new OptionCustom(*rai_def, Option::V4)); + OptionPtr rai_override_server_id(new Option(Option::V4, + RAI_OPTION_SERVER_ID_OVERRIDE, + override_server_id_buf)); + rai->addOption(rai_override_server_id); + + // Add a server id being an IPv4 address matching RAI sub-option 11 + // (RAI_OPTION_SERVER_ID_OVERRIDE). + // A DHCPv4 message holding this server identifier should be accepted. + Pkt4Ptr pkt_with_override_server_id(new Pkt4(DHCPREQUEST, 1234)); + OptionCustomPtr override_serverid(new OptionCustom(def, Option::V4)); + override_serverid->writeAddress(IOAddress("10.0.0.128")); + + ASSERT_NO_THROW(pkt_with_override_server_id->addOption(override_serverid)); + ASSERT_NO_THROW(pkt_with_override_server_id->addOption(rai)); + EXPECT_TRUE(srv.acceptServerId(pkt_with_override_server_id)); + + // Remove the server identifier. + ASSERT_NO_THROW(pkt_with_override_server_id->delOption(DHO_DHCP_SERVER_IDENTIFIER)); } // @todo: Implement tests for rejecting renewals