From f80901e0759c948fb194783182261834bf64c359 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Tue, 19 Dec 2017 23:29:58 +0100 Subject: [PATCH 1/5] [5404] Implemented DHCPv4 port relay --- src/bin/dhcp4/dhcp4_srv.cc | 17 +++++- src/bin/dhcp4/dhcp4_srv.h | 6 ++ src/bin/dhcp4/tests/dhcp4_srv_unittest.cc | 68 +++++++++++++++++++++++ src/lib/dhcp/dhcp4.h | 1 + 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 97ecfa5cf3..a834e30987 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -2035,6 +2035,19 @@ Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) { } } +uint16_t +Dhcpv4Srv::checkRelayPort(const Dhcpv4Exchange& ex) { + + // Look for a relay-port RAI sub-option in the query. + const Pkt4Ptr& query = ex.getQuery(); + const OptionPtr& rai = query->getOption(DHO_DHCP_AGENT_OPTIONS); + if (rai && rai->getOption(RAI_OPTION_RELAY_PORT)) { + // Got the sub-option so use the remote port set by the relay. + return (query->getRemotePort()); + } + return (0); +} + void Dhcpv4Srv::adjustIfaceData(Dhcpv4Exchange& ex) { adjustRemoteAddr(ex); @@ -2061,7 +2074,9 @@ Dhcpv4Srv::adjustIfaceData(Dhcpv4Exchange& ex) { response->setRemotePort(DHCP4_CLIENT_PORT); } else { - response->setRemotePort(DHCP4_SERVER_PORT); + // draft-ietf-dhc-relay-port-10.txt section 5.1 + uint16_t relay_port = checkRelayPort(ex); + response->setRemotePort(relay_port ? relay_port : DHCP4_SERVER_PORT); } CfgIfacePtr cfg_iface = CfgMgr::instance().getCurrentCfg()->getCfgIface(); diff --git a/src/bin/dhcp4/dhcp4_srv.h b/src/bin/dhcp4/dhcp4_srv.h index e72af87c84..765944531c 100644 --- a/src/bin/dhcp4/dhcp4_srv.h +++ b/src/bin/dhcp4/dhcp4_srv.h @@ -701,6 +701,12 @@ protected: /// server's response. static void appendServerID(Dhcpv4Exchange& ex); + /// @brief Check if the relay port RAI sub-option was set in the query. + /// + /// @param ex The exchange holding the client's message + /// @return the port to use to join the relay or 0 for the default + static uint16_t checkRelayPort(const Dhcpv4Exchange& ex); + /// @brief Set IP/UDP and interface parameters for the DHCPv4 response. /// /// This method sets the following parameters for the DHCPv4 message being diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index df1ae36fb9..2b3e25abc9 100644 --- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc @@ -161,6 +161,9 @@ TEST_F(Dhcpv4SrvTest, adjustIfaceDataRelay) { req->setIface("eth1"); req->setIndex(1); + // Set remote port (it will be used in the next test). + req->setRemotePort(1234); + // Create the exchange using the req. Dhcpv4Exchange ex = createExchange(req); @@ -204,6 +207,71 @@ TEST_F(Dhcpv4SrvTest, adjustIfaceDataRelay) { EXPECT_EQ("192.0.1.50", resp->getRemoteAddr().toText()); } +// This test verifies that the remote port is adjusted when +// the query carries a relay port RAI sub-option. +TEST_F(Dhcpv4SrvTest, adjustIfaceDataRelayPort) { + IfaceMgrTestConfig test_config(true); + IfaceMgr::instance().openSockets4(); + + // Create the instance of the incoming packet. + boost::shared_ptr req(new Pkt4(DHCPDISCOVER, 1234)); + // Set the giaddr to non-zero address and hops to non-zero value + // as if it was relayed. + req->setGiaddr(IOAddress("192.0.1.1")); + req->setHops(2); + // Set ciaddr to zero. This simulates the client which applies + // for the new lease. + req->setCiaddr(IOAddress("0.0.0.0")); + // Clear broadcast flag. + req->setFlags(0x0000); + + // Set local address, port and interface. + req->setLocalAddr(IOAddress("192.0.2.5")); + req->setLocalPort(1001); + req->setIface("eth1"); + req->setIndex(1); + + // Set remote port. + req->setRemotePort(1234); + + // Add a RAI relay-port sub-option (the only difference with the previous test). + OptionDefinitionPtr rai_def = + LibDHCP::getOptionDef(DHCP4_OPTION_SPACE, DHO_DHCP_AGENT_OPTIONS); + ASSERT_TRUE(rai_def); + OptionCustomPtr rai(new OptionCustom(*rai_def, Option::V4)); + ASSERT_TRUE(rai); + req->addOption(rai); + OptionPtr relay_port(new Option(Option::V4, RAI_OPTION_RELAY_PORT)); + ASSERT_TRUE(relay_port); + rai->addOption(relay_port); + + // Create the exchange using the req. + Dhcpv4Exchange ex = createExchange(req); + + Pkt4Ptr resp = ex.getResponse(); + resp->setYiaddr(IOAddress("192.0.1.100")); + // Clear the remote address. + resp->setRemoteAddr(IOAddress("0.0.0.0")); + // Set hops value for the response. + resp->setHops(req->getHops()); + + // This function never throws. + ASSERT_NO_THROW(NakedDhcpv4Srv::adjustIfaceData(ex)); + + // Now the destination address should be relay's address. + EXPECT_EQ("192.0.1.1", resp->getRemoteAddr().toText()); + // The query has been relayed, so the response must be sent to the port 67. + EXPECT_EQ(1234, resp->getRemotePort()); + // Local address should be the address assigned to interface eth1. + EXPECT_EQ("192.0.2.5", resp->getLocalAddr().toText()); + // The local port is always DHCPv4 server port 67. + EXPECT_EQ(DHCP4_SERVER_PORT, resp->getLocalPort()); + // We will send response over the same interface which was used to receive + // query. + EXPECT_EQ("eth1", resp->getIface()); + EXPECT_EQ(1, resp->getIndex()); +} + // This test verifies that it is possible to configure the server to use // routing information to determine the right outbound interface to sent // responses to a relayed client. diff --git a/src/lib/dhcp/dhcp4.h b/src/lib/dhcp/dhcp4.h index 8fd8297ea9..9b8af7dece 100644 --- a/src/lib/dhcp/dhcp4.h +++ b/src/lib/dhcp/dhcp4.h @@ -272,6 +272,7 @@ static const uint16_t RAI_OPTION_ACCESS_POINT_NAME = 15; // RFC7839 static const uint16_t RAI_OPTION_ACCESS_POINT_BSSID = 16; // RFC7839 static const uint16_t RAI_OPTION_OPERATOR_ID = 17; // RFC7839 static const uint16_t RAI_OPTION_OPERATOR_REALM = 18; // RFC7839 +static const uint16_t RAI_OPTION_RELAY_PORT = 19; // I-D, to be assigned static const uint16_t RAI_OPTION_VIRTUAL_SUBNET_SELECT = 151; //RFC6607 static const uint16_t RAI_OPTION_VIRTUAL_SUBNET_SELECT_CTRL = 152; //RFC6607 From 7d520c058883425d0d66ffdd06e1bfca684d7be8 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Wed, 20 Dec 2017 02:42:11 +0100 Subject: [PATCH 2/5] [5404] Implemented DHCPv6 port relay --- src/bin/dhcp6/dhcp6_srv.cc | 19 ++++- src/bin/dhcp6/dhcp6_srv.h | 6 ++ src/bin/dhcp6/tests/dhcp6_srv_unittest.cc | 91 +++++++++++++++++++++++ src/lib/dhcp/dhcp6.h | 2 + src/lib/dhcp/pkt6.cc | 6 ++ src/lib/dhcp/std_option_defs.h | 1 + src/lib/dhcp/tests/libdhcp++_unittest.cc | 3 + 7 files changed, 127 insertions(+), 1 deletion(-) diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 94fd68d137..cbba992675 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -764,7 +764,8 @@ Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp) { rsp->setRemotePort(DHCP6_CLIENT_PORT); } else { // Relayed traffic, send back to the relay agent - rsp->setRemotePort(DHCP6_SERVER_PORT); + uint16_t relay_port = testRelaySourcePort(query); + rsp->setRemotePort(relay_port ? relay_port : DHCP6_SERVER_PORT); } rsp->setLocalPort(DHCP6_SERVER_PORT); @@ -3373,6 +3374,22 @@ void Dhcpv6Srv::processRSOO(const Pkt6Ptr& query, const Pkt6Ptr& rsp) { } } +uint16_t Dhcpv6Srv::testRelaySourcePort(const Pkt6Ptr& query) { + + if (query->relay_info_.empty()) { + // No relay agent + return (0); + } + + // Did the last relay agent add a relay-source-port? + if (query->getRelayOption(D6O_RELAY_SOURCE_PORT, 0)) { + // draft-ietf-dhc-relay-port-10.txt section 5.2 + return (query->getRemotePort()); + } + + return (0); +} + void Dhcpv6Srv::processStatsReceived(const Pkt6Ptr& query) { // Note that we're not bumping pkt6-received statistic as it was // increased early in the packet reception code. diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h index 53d0d25a3c..6b6b3bde18 100644 --- a/src/bin/dhcp6/dhcp6_srv.h +++ b/src/bin/dhcp6/dhcp6_srv.h @@ -754,6 +754,12 @@ protected: void setStatusCode(boost::shared_ptr& container, const OptionPtr& status); + /// @brief Check if the last relay added a relay-source-port option. + /// + /// @param query DHCPv6 message to be checked. + /// @return the port to use to join the relay or 0 for the default. + static uint16_t testRelaySourcePort(const Pkt6Ptr& query); + private: /// @public diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc index cb408c4b34..534b7b2371 100644 --- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc +++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc @@ -1548,6 +1548,97 @@ TEST_F(Dhcpv6SrvTest, portsRelayedTraffic) { EXPECT_EQ(DHCP6_SERVER_PORT, adv->getRemotePort()); } +// Test that the server processes relay-source-port option correctly. +TEST_F(Dhcpv6SrvTest, relaySourcePort) { + + NakedDhcpv6Srv srv(0); + + string config = + "{" + " \"preferred-lifetime\": 3000," + " \"rebind-timer\": 2000, " + " \"renew-timer\": 1000, " + " \"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8::/64\" } ]," + " \"subnet\": \"2001:db8::/48\" " + " } ]," + " \"valid-lifetime\": 4000" + "}"; + + EXPECT_NO_THROW(configure(config, srv)); + + // Create a solicit + Pkt6Ptr sol(new Pkt6(DHCPV6_SOLICIT, 1234)); + sol->setRemoteAddr(IOAddress("fe80::abcd")); + sol->setIface("eth0"); + sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000)); + OptionPtr clientid = generateClientId(); + sol->addOption(clientid); + + // Pretend the packet came via one relay. + Pkt6::RelayInfo relay; + relay.msg_type_ = DHCPV6_RELAY_FORW; + relay.hop_count_ = 1; + relay.linkaddr_ = IOAddress("2001:db8::1"); + relay.peeraddr_ = IOAddress("fe80::1"); + + // Set the source port + sol->setRemotePort(1234); + + // Simulate that we have received that traffic + sol->pack(); + + // Add a relay-source-port option + OptionBuffer zero(2, 0); + OptionPtr opt(new Option(Option::V6, D6O_RELAY_SOURCE_PORT, zero)); + relay.options_.insert(make_pair(opt->getType(), opt)); + sol->relay_info_.push_back(relay); + + // Simulate that we have received that traffic + sol->pack(); + EXPECT_EQ(DHCPV6_RELAY_FORW, sol->getBuffer()[0]); + Pkt6Ptr query(new Pkt6(static_cast + (sol->getBuffer().getData()), + sol->getBuffer().getLength())); + query->setRemoteAddr(sol->getRemoteAddr()); + query->setRemotePort(sol->getRemotePort()); + query->setLocalAddr(sol->getLocalAddr()); + query->setLocalPort(sol->getLocalPort()); + query->setIface(sol->getIface()); + + srv.fakeReceive(query); + + // Server will now process to run its normal loop, but instead of calling + // IfaceMgr::receive6(), it will read all packets from the list set by + // fakeReceive() + srv.run(); + + // Check trace of processing + EXPECT_EQ(1234, query->getRemotePort()); + ASSERT_EQ(1, query->relay_info_.size()); + EXPECT_TRUE(query->getRelayOption(D6O_RELAY_SOURCE_PORT, 0)); + + // Get Response... + ASSERT_FALSE(srv.fake_sent_.empty()); + Pkt6Ptr rsp = srv.fake_sent_.front(); + ASSERT_TRUE(rsp); + + // Check it + EXPECT_EQ(1234, rsp->getRemotePort()); + EXPECT_EQ(DHCPV6_RELAY_REPL, rsp->getBuffer()[0]); + + // Get Advertise + Pkt6Ptr adv(new Pkt6(static_cast + (rsp->getBuffer().getData()), + rsp->getBuffer().getLength())); + adv->unpack(); + + // Check it + EXPECT_EQ(DHCPV6_ADVERTISE, adv->getType()); + ASSERT_EQ(1, adv->relay_info_.size()); + EXPECT_TRUE(adv->getRelayOption(D6O_RELAY_SOURCE_PORT, 0)); +} + // Checks effect of persistency (aka always-true) flag on the ORO TEST_F(Dhcpv6SrvTest, prlPersistency) { IfaceMgrTestConfig test_config(true); diff --git a/src/lib/dhcp/dhcp6.h b/src/lib/dhcp/dhcp6.h index 5783b15e1d..78c8c07380 100644 --- a/src/lib/dhcp/dhcp6.h +++ b/src/lib/dhcp/dhcp6.h @@ -152,6 +152,8 @@ enum DHCPv6OptionType { // D6O_F_SERVER_STATE = 132, /* RFC8156 */ // D6O_F_START_TIME_OF_STATE = 133, /* RFC8156 */ // D6O_F_STATE_EXPIRATION_TIME = 134, /* RFC8156 */ +// not yet assigned but next free value + D6O_RELAY_SOURCE_PORT = 135, /* draft-ietf-dhc-relay-port-10.txt */ // 135-142 unassigned D6O_IPV6_ADDRESS_ANDSF = 143, /* RFC6153 */ diff --git a/src/lib/dhcp/pkt6.cc b/src/lib/dhcp/pkt6.cc index 19de2f7a76..f30e908831 100644 --- a/src/lib/dhcp/pkt6.cc +++ b/src/lib/dhcp/pkt6.cc @@ -794,6 +794,12 @@ void Pkt6::copyRelayInfo(const Pkt6Ptr& question) { info.options_.insert(make_pair(opt->getType(), opt)); } + // Same for relay-source-port option + opt = question->getNonCopiedRelayOption(D6O_RELAY_SOURCE_PORT, i); + if (opt) { + info.options_.insert(make_pair(opt->getType(), opt)); + } + /// @todo: Implement support for ERO (Echo Request Option, RFC4994) // Add this relay-forw info (client's message) to our relay-repl diff --git a/src/lib/dhcp/std_option_defs.h b/src/lib/dhcp/std_option_defs.h index 69cd4cc8b7..47d9c2256a 100644 --- a/src/lib/dhcp/std_option_defs.h +++ b/src/lib/dhcp/std_option_defs.h @@ -444,6 +444,7 @@ const OptionDefParams STANDARD_V6_OPTION_DEFINITIONS[] = { NO_RECORD_DEF, "" }, { "v6-captive-portal", D6O_V6_CAPTIVE_PORTAL, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" }, + { "relay-source-port", D6O_RELAY_SOURCE_PORT, OPT_UINT16_TYPE, false, NO_RECORD_DEF, "" }, { "ipv6-address-andsf", D6O_IPV6_ADDRESS_ANDSF, OPT_IPV6_ADDRESS_TYPE, true, NO_RECORD_DEF, "" }, { "public-key", D6O_PUBLIC_KEY, OPT_BINARY_TYPE, false, diff --git a/src/lib/dhcp/tests/libdhcp++_unittest.cc b/src/lib/dhcp/tests/libdhcp++_unittest.cc index fc0f383786..3503a4e8a6 100644 --- a/src/lib/dhcp/tests/libdhcp++_unittest.cc +++ b/src/lib/dhcp/tests/libdhcp++_unittest.cc @@ -1736,6 +1736,9 @@ TEST_F(LibDhcpTest, stdOptionDefs6) { LibDhcpTest::testStdOptionDefs6(D6O_V6_CAPTIVE_PORTAL, begin, end, typeid(OptionString)); + LibDhcpTest::testStdOptionDefs6(D6O_RELAY_SOURCE_PORT, begin, begin + 2, + typeid(OptionInt)); + LibDhcpTest::testStdOptionDefs6(D6O_IPV6_ADDRESS_ANDSF, begin, end, typeid(Option6AddrLst)); From 4fb30e285512a6b64571bebb14ed16e9b9b81cb1 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 23 Dec 2017 20:31:48 +0100 Subject: [PATCH 3/5] [5404] checkpoint: adding 4o6 support --- src/bin/dhcp6/dhcp6_srv.h | 4 ++ src/bin/dhcp6/dhcp6to4_ipc.cc | 3 +- src/lib/dhcp/dhcp6.h | 1 + src/lib/dhcp/std_option_defs.h | 4 +- src/lib/dhcpsrv/dhcp4o6_ipc.cc | 21 +++++++++- src/lib/dhcpsrv/dhcp4o6_ipc.h | 20 +++++----- src/lib/dhcpsrv/tests/dhcp4o6_ipc_unittest.cc | 39 +++++++++++++++++++ 7 files changed, 79 insertions(+), 13 deletions(-) diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h index 6b6b3bde18..390ae19d4d 100644 --- a/src/bin/dhcp6/dhcp6_srv.h +++ b/src/bin/dhcp6/dhcp6_srv.h @@ -754,6 +754,10 @@ protected: void setStatusCode(boost::shared_ptr& container, const OptionPtr& status); +public: + + /// Used for DHCPv4-over-DHCPv6 too. + /// @brief Check if the last relay added a relay-source-port option. /// /// @param query DHCPv6 message to be checked. diff --git a/src/bin/dhcp6/dhcp6to4_ipc.cc b/src/bin/dhcp6/dhcp6to4_ipc.cc index 7ec9397973..71759732f3 100644 --- a/src/bin/dhcp6/dhcp6to4_ipc.cc +++ b/src/bin/dhcp6/dhcp6to4_ipc.cc @@ -89,7 +89,8 @@ void Dhcp6to4Ipc::handler() { // getType() always returns the type of internal message. uint8_t msg_type = buf[0]; if ((msg_type == DHCPV6_RELAY_FORW) || (msg_type == DHCPV6_RELAY_REPL)) { - pkt->setRemotePort(DHCP6_SERVER_PORT); + uint16_t relay_port = Dhcpv6Srv::testRelaySourcePort(pkt); + pkt->setRemotePort(relay_port ? relay_port : DHCP6_SERVER_PORT); } else { pkt->setRemotePort(DHCP6_CLIENT_PORT); } diff --git a/src/lib/dhcp/dhcp6.h b/src/lib/dhcp/dhcp6.h index 78c8c07380..7b67badbb6 100644 --- a/src/lib/dhcp/dhcp6.h +++ b/src/lib/dhcp/dhcp6.h @@ -280,6 +280,7 @@ static const uint32_t ENTERPRISE_ID_ISC = 2495; codes for the ISC vendor specific options used in 4o6 */ static const uint16_t ISC_V6_4O6_INTERFACE = 60000; static const uint16_t ISC_V6_4O6_SRC_ADDRESS = 60001; +static const uint16_t ISC_V6_4O6_SRC_PORT = 60002; /* Offsets into IA_*'s where Option spaces commence. */ static const uint16_t IA_NA_OFFSET = 12; /* IAID, T1, T2, all 4 octets each */ diff --git a/src/lib/dhcp/std_option_defs.h b/src/lib/dhcp/std_option_defs.h index 47d9c2256a..e3db039e58 100644 --- a/src/lib/dhcp/std_option_defs.h +++ b/src/lib/dhcp/std_option_defs.h @@ -476,7 +476,9 @@ const OptionDefParams ISC_V6_OPTION_DEFINITIONS[] = { { "4o6-interface", ISC_V6_4O6_INTERFACE, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" }, { "4o6-source-address", ISC_V6_4O6_SRC_ADDRESS, OPT_IPV6_ADDRESS_TYPE, - false, NO_RECORD_DEF, "" } + false, NO_RECORD_DEF, "" }, + { "4o6-source-port", ISC_V6_4O6_SRC_PORT, OPT_UINT16_TYPE, false, + NO_RECORD_DEF, "" } }; const int ISC_V6_OPTION_DEFINITIONS_SIZE = diff --git a/src/lib/dhcpsrv/dhcp4o6_ipc.cc b/src/lib/dhcpsrv/dhcp4o6_ipc.cc index 86dfafc378..031c805956 100644 --- a/src/lib/dhcpsrv/dhcp4o6_ipc.cc +++ b/src/lib/dhcpsrv/dhcp4o6_ipc.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -191,14 +192,29 @@ Pkt6Ptr Dhcp4o6IpcBase::receive() { "or has incorrect type)"); } + // Get the option holding source port. + OptionPtr sport = option_vendor->getOption(ISC_V6_4O6_SRC_PORT); + if (!sport || (sport->len() - sport->getHeaderLen() != 2)) { + LOG_WARN(dhcpsrv_logger, DHCPSRV_DHCP4O6_RECEIVED_BAD_PACKET) + .arg("no source port suboption"); + isc_throw(Dhcp4o6IpcError, + "malformed packet (source port suboption missing " + "or has incorrect length)"); + } + const OptionBuffer& sport_buf = sport->getData(); + uint16_t sport_value = static_cast(sport_buf[0]) << 8; + sport_value |= static_cast(sport_buf[1]); + // Update the packet. pkt->setRemoteAddr(srcs->readAddress()); + pkt->setRemotePort(sport_value); pkt->setIface(iface->getName()); pkt->setIndex(iface->getIndex()); // Remove options that have been added by the IPC sender. static_cast(option_vendor->delOption(ISC_V6_4O6_INTERFACE)); static_cast(option_vendor->delOption(ISC_V6_4O6_SRC_ADDRESS)); + static_cast(option_vendor->delOption(ISC_V6_4O6_SRC_PORT)); // If there are no more options, the IPC sender has probably created the // vendor option, in which case we should remove it here. @@ -243,6 +259,9 @@ void Dhcp4o6IpcBase::send(const Pkt6Ptr& pkt) { option_vendor->addOption(Option6AddrLstPtr(new Option6AddrLst( ISC_V6_4O6_SRC_ADDRESS, pkt->getRemoteAddr()))); + option_vendor->addOption(OptionUint16Ptr(new OptionUint16(Option::V6, + ISC_V6_4O6_SRC_PORT, + pkt->getRemotePort()))); // Get packet content OutputBuffer& buf = pkt->getBuffer(); buf.clear(); diff --git a/src/lib/dhcpsrv/dhcp4o6_ipc.h b/src/lib/dhcpsrv/dhcp4o6_ipc.h index fd7c4d8c16..d67f2d2176 100644 --- a/src/lib/dhcpsrv/dhcp4o6_ipc.h +++ b/src/lib/dhcpsrv/dhcp4o6_ipc.h @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -54,10 +54,10 @@ public: /// the original DHCPv4 query message sent by the client. This /// information is known by the DHCPv6 server and needs to be conveyed /// to the DHCPv4 server. The IPC conveys it in the -/// @c ISC_V6_4O6_INTERFACE and @c ISC_V6_4O6_SRC_ADDRESS options -/// within the Vendor Specific Information option, with ISC -/// enterprise id. These options are added by the IPC sender and removed -/// by the IPC receiver. +/// @c ISC_V6_4O6_INTERFACE, @c ISC_V6_4O6_SRC_ADDRESS and @c +/// ISC_V6_4O6_SRC_PORT options within the Vendor Specific Information +/// option, with ISC enterprise id. These options are added by the IPC +/// sender and removed by the IPC receiver. class Dhcp4o6IpcBase : public boost::noncopyable { public: @@ -105,11 +105,11 @@ public: /// @brief Send message over IPC. /// - /// The IPC uses @c ISC_V6_4O6_INTERFACE and @c ISC_V6_4O6_SRC_ADDRESS - /// options conveyed within the Vendor Specific Information option, with - /// ISC enterprise id, to communicate the client remote address and the - /// interface on which the DHCPv4 query was received. These options will - /// be removed by the receiver. + /// The IPC uses @c ISC_V6_4O6_INTERFACE, @c ISC_V6_4O6_SRC_ADDRESS + /// and @c ISC_V6_4O6_SRC_PORT options conveyed within the Vendor + /// Specific Information option, with ISC enterprise id, to communicate + /// the client remote address and the interface on which the DHCPv4 query + /// was received. These options will be removed by the receiver. /// /// @param pkt Pointer to a DHCPv6 message with interface and remote /// address. diff --git a/src/lib/dhcpsrv/tests/dhcp4o6_ipc_unittest.cc b/src/lib/dhcpsrv/tests/dhcp4o6_ipc_unittest.cc index 07ac8bd326..84b6d10ae2 100644 --- a/src/lib/dhcpsrv/tests/dhcp4o6_ipc_unittest.cc +++ b/src/lib/dhcpsrv/tests/dhcp4o6_ipc_unittest.cc @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -173,6 +174,10 @@ Dhcp4o6IpcBaseTest::createDHCPv4o6Message(uint16_t msg_type, // right address. pkt->setRemoteAddr(IOAddress(concatenate("2001:db8:1::", postfix))); + // The remote port of the sender of the DHCPv6 packet is carried + // between the servers in the dedicated option. + pkt->setRemotePort(10000 + (postfix % 1000)); + // Determine the endpoint type using the message type. TestIpc::EndpointType src = (msg_type == DHCPV6_DHCPV4_QUERY) ? TestIpc::ENDPOINT_TYPE_V6 : TestIpc::ENDPOINT_TYPE_V4; @@ -286,6 +291,9 @@ Dhcp4o6IpcBaseTest::testSendReceive(uint16_t iterations_num, EXPECT_EQ(concatenate("2001:db8:1::", i), pkt_received->getRemoteAddr().toText()); + // Check that the port conveyed is correct. + EXPECT_EQ(10000 + (i % 1000), pkt_received->getRemotePort()); + // Check that encapsulated DHCPv4 message has been received. EXPECT_TRUE(pkt_received->getOption(D6O_DHCPV4_MSG)); @@ -320,6 +328,7 @@ Dhcp4o6IpcBaseTest::testReceiveError(const Pkt6Ptr& pkt) { pkt->setIface("eth0"); pkt->setRemoteAddr(IOAddress("2001:db8:1::1")); + pkt->setRemotePort(TEST_PORT); pkt->addOption(createDHCPv4MsgOption(TestIpc::ENDPOINT_TYPE_V6)); OutputBuffer& buf = pkt->getBuffer(); @@ -476,6 +485,10 @@ TEST_F(Dhcp4o6IpcBaseTest, receiveWithoutInterfaceOption) { Option6AddrLstPtr(new Option6AddrLst(ISC_V6_4O6_SRC_ADDRESS, IOAddress("2001:db8:1::1"))) ); + option_vendor->addOption( + OptionUint16Ptr(new OptionUint16(Option::V6, + ISC_V6_4O6_SRC_PORT, + TEST_PORT))); pkt->addOption(option_vendor); testReceiveError(pkt); @@ -495,6 +508,10 @@ TEST_F(Dhcp4o6IpcBaseTest, receiveWithInvalidInterface) { Option6AddrLstPtr(new Option6AddrLst(ISC_V6_4O6_SRC_ADDRESS, IOAddress("2001:db8:1::1"))) ); + option_vendor->addOption( + OptionUint16Ptr(new OptionUint16(Option::V6, + ISC_V6_4O6_SRC_PORT, + TEST_PORT))); pkt->addOption(option_vendor); testReceiveError(pkt); @@ -510,6 +527,28 @@ TEST_F(Dhcp4o6IpcBaseTest, receiveWithoutSourceAddressOption) { option_vendor->addOption( OptionStringPtr(new OptionString(Option::V6, ISC_V6_4O6_INTERFACE, "eth0"))); + option_vendor->addOption( + OptionUint16Ptr(new OptionUint16(Option::V6, + ISC_V6_4O6_SRC_PORT, + TEST_PORT))); + + pkt->addOption(option_vendor); + testReceiveError(pkt); +} + +// This test verifies that receiving packet over the IPC fails when the +// source port option is not present. +TEST_F(Dhcp4o6IpcBaseTest, receiveWithoutSourcePortOption) { + Pkt6Ptr pkt(new Pkt6(DHCPV6_DHCPV4_QUERY, 0)); + OptionVendorPtr option_vendor(new OptionVendor(Option::V6, + ENTERPRISE_ID_ISC)); + option_vendor->addOption( + OptionStringPtr(new OptionString(Option::V6, ISC_V6_4O6_INTERFACE, + "eth0"))); + option_vendor->addOption( + Option6AddrLstPtr(new Option6AddrLst(ISC_V6_4O6_SRC_ADDRESS, + IOAddress("2001:db8:1::1"))) + ); pkt->addOption(option_vendor); testReceiveError(pkt); From 7e4953a9c96db09fe5205c3d66eb4941ff046b92 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 23 Dec 2017 22:59:15 +0100 Subject: [PATCH 4/5] [5404] Finished 4o6 code --- src/bin/dhcp4/dhcp4_messages.mes | 8 ++++---- src/bin/dhcp4/dhcp4_srv.cc | 3 ++- src/bin/dhcp4/dhcp4to6_ipc.cc | 2 ++ src/bin/dhcp6/dhcp6_messages.mes | 2 +- src/bin/dhcp6/dhcp6to4_ipc.cc | 5 ++++- src/lib/dhcpsrv/dhcp4o6_ipc.cc | 12 +++++------- 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/bin/dhcp4/dhcp4_messages.mes b/src/bin/dhcp4/dhcp4_messages.mes index 05426d29e7..ddcb93bb13 100644 --- a/src/bin/dhcp4/dhcp4_messages.mes +++ b/src/bin/dhcp4/dhcp4_messages.mes @@ -176,11 +176,11 @@ a client's error or a server's purged database. % DHCP4_DHCP4O6_BAD_PACKET received malformed DHCPv4o6 packet: %1 A malformed DHCPv4o6 packet was received. -% DHCP4_DHCP4O6_PACKET_SEND %1: trying to send packet %2 (type %3) to %4 on interface %5 encapsulating %6: %7 (type %8) +% DHCP4_DHCP4O6_PACKET_SEND %1: trying to send packet %2 (type %3) to %4 port %5 on interface %6 encapsulating %7: %8 (type %9) The arguments specify the client identification information (HW address and client identifier), DHCPv6 message name and type, source IPv6 -address and interface name, DHCPv4 client identification, message -name and type. +address and port, and interface name, DHCPv4 client identification, +message name and type. % DHCP4_DHCP4O6_PACKET_SEND_FAIL %1: failed to send DHCPv4o6 packet: %2 This error is output if the IPv4 DHCP server fails to send an @@ -693,6 +693,6 @@ and will send DHCPNAK if the received message was DHCPREQUEST. The argument includes the client and the transaction identification information. -% DHCP6_DHCP4O6_PACKET_RECEIVED received DHCPv4o6 packet from DHCPv6 server (type %1) for %2 on interface %3 +% DHCP6_DHCP4O6_PACKET_RECEIVED received DHCPv4o6 packet from DHCPv6 server (type %1) for %2 port %3 on interface %4 This debug message is printed when the server is receiving a DHCPv4o6 from the DHCPv6 server over inter-process communication. diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index a834e30987..7bfcb39d17 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -205,10 +205,11 @@ Dhcpv4Exchange::initResponse4o6() { if (!query6->relay_info_.empty()) { resp6->copyRelayInfo(query6); } - // Copy interface and remote address + // Copy interface, and remote address and port resp6->setIface(query6->getIface()); resp6->setIndex(query6->getIndex()); resp6->setRemoteAddr(query6->getRemoteAddr()); + resp6->setRemotePort(query6->getRemotePort()); resp_.reset(new Pkt4o6(resp_, resp6)); } diff --git a/src/bin/dhcp4/dhcp4to6_ipc.cc b/src/bin/dhcp4/dhcp4to6_ipc.cc index b219207265..f3cfb2bdf1 100644 --- a/src/bin/dhcp4/dhcp4to6_ipc.cc +++ b/src/bin/dhcp4/dhcp4to6_ipc.cc @@ -66,6 +66,7 @@ void Dhcp4to6Ipc::handler() { LOG_DEBUG(packet4_logger, DBG_DHCP4_BASIC, DHCP6_DHCP4O6_PACKET_RECEIVED) .arg(static_cast(pkt->getType())) .arg(pkt->getRemoteAddr().toText()) + .arg(pkt->getRemotePort()) .arg(pkt->getIface()); } } catch (const std::exception& e) { @@ -156,6 +157,7 @@ void Dhcp4to6Ipc::handler() { .arg(rsp6->getName()) .arg(static_cast(rsp6->getType())) .arg(rsp6->getRemoteAddr()) + .arg(rsp6->getRemotePort()) .arg(rsp6->getIface()) .arg(rsp->getLabel()) .arg(rsp->getName()) diff --git a/src/bin/dhcp6/dhcp6_messages.mes b/src/bin/dhcp6/dhcp6_messages.mes index 0d6c9caebe..8a8173c504 100644 --- a/src/bin/dhcp6/dhcp6_messages.mes +++ b/src/bin/dhcp6/dhcp6_messages.mes @@ -205,7 +205,7 @@ received in Decline message. It's expected that the option will contain an address that is being declined. Specific information will be printed in a separate message. -% DHCP6_DHCP4O6_PACKET_RECEIVED received DHCPv4o6 packet from DHCPv4 server (type %1) for %2 on interface %3 +% DHCP6_DHCP4O6_PACKET_RECEIVED received DHCPv4o6 packet from DHCPv4 server (type %1) for %2 port %3 on interface %4 This debug message is printed when the server is receiving a DHCPv4o6 from the DHCPv4 server over inter-process communication. diff --git a/src/bin/dhcp6/dhcp6to4_ipc.cc b/src/bin/dhcp6/dhcp6to4_ipc.cc index 71759732f3..a3fa09120e 100644 --- a/src/bin/dhcp6/dhcp6to4_ipc.cc +++ b/src/bin/dhcp6/dhcp6to4_ipc.cc @@ -64,6 +64,7 @@ void Dhcp6to4Ipc::handler() { LOG_DEBUG(packet6_logger, DBG_DHCP6_BASIC, DHCP6_DHCP4O6_PACKET_RECEIVED) .arg(static_cast(pkt->getType())) .arg(pkt->getRemoteAddr().toText()) + .arg(pkt->getRemotePort()) .arg(pkt->getIface()); } } catch (const std::exception& e) { @@ -77,6 +78,9 @@ void Dhcp6to4Ipc::handler() { // Should we check it is a DHCPV6_DHCPV4_RESPONSE? + // Handle relay port + uint16_t relay_port = Dhcpv6Srv::testRelaySourcePort(pkt); + // The received message has been unpacked by the receive() function. This // method could have modified the message so it's better to pack() it // again because we'll be forwarding it to a client. @@ -89,7 +93,6 @@ void Dhcp6to4Ipc::handler() { // getType() always returns the type of internal message. uint8_t msg_type = buf[0]; if ((msg_type == DHCPV6_RELAY_FORW) || (msg_type == DHCPV6_RELAY_REPL)) { - uint16_t relay_port = Dhcpv6Srv::testRelaySourcePort(pkt); pkt->setRemotePort(relay_port ? relay_port : DHCP6_SERVER_PORT); } else { pkt->setRemotePort(DHCP6_CLIENT_PORT); diff --git a/src/lib/dhcpsrv/dhcp4o6_ipc.cc b/src/lib/dhcpsrv/dhcp4o6_ipc.cc index 031c805956..e3f23fc1f1 100644 --- a/src/lib/dhcpsrv/dhcp4o6_ipc.cc +++ b/src/lib/dhcpsrv/dhcp4o6_ipc.cc @@ -193,21 +193,19 @@ Pkt6Ptr Dhcp4o6IpcBase::receive() { } // Get the option holding source port. - OptionPtr sport = option_vendor->getOption(ISC_V6_4O6_SRC_PORT); - if (!sport || (sport->len() - sport->getHeaderLen() != 2)) { + OptionUint16Ptr sport = boost::dynamic_pointer_cast< + OptionUint16>(option_vendor->getOption(ISC_V6_4O6_SRC_PORT)); + if (!sport) { LOG_WARN(dhcpsrv_logger, DHCPSRV_DHCP4O6_RECEIVED_BAD_PACKET) .arg("no source port suboption"); isc_throw(Dhcp4o6IpcError, "malformed packet (source port suboption missing " - "or has incorrect length)"); + "or has incorrect type)"); } - const OptionBuffer& sport_buf = sport->getData(); - uint16_t sport_value = static_cast(sport_buf[0]) << 8; - sport_value |= static_cast(sport_buf[1]); // Update the packet. pkt->setRemoteAddr(srcs->readAddress()); - pkt->setRemotePort(sport_value); + pkt->setRemotePort(sport->getValue()); pkt->setIface(iface->getName()); pkt->setIndex(iface->getIndex()); From 955441318a10d0455d67514529bec5e25cd4255b Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Wed, 4 Apr 2018 16:44:56 +0200 Subject: [PATCH 5/5] [5404] Addressed comments and updated I-D references --- src/bin/dhcp4/dhcp4_srv.cc | 4 ++-- src/bin/dhcp4/tests/dhcp4_srv_unittest.cc | 8 ++++++-- src/bin/dhcp6/dhcp6_srv.cc | 8 ++++---- src/bin/dhcp6/dhcp6_srv.h | 4 ++-- src/bin/dhcp6/dhcp6to4_ipc.cc | 4 ++-- src/bin/dhcp6/tests/dhcp6_srv_unittest.cc | 2 +- src/lib/dhcp/dhcp4.h | 4 ++-- src/lib/dhcp/dhcp6.h | 5 ++--- 8 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 7bfcb39d17..aa29e665a1 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -2075,7 +2075,7 @@ Dhcpv4Srv::adjustIfaceData(Dhcpv4Exchange& ex) { response->setRemotePort(DHCP4_CLIENT_PORT); } else { - // draft-ietf-dhc-relay-port-10.txt section 5.1 + // RFC 8357 section 5.1 uint16_t relay_port = checkRelayPort(ex); response->setRemotePort(relay_port ? relay_port : DHCP4_SERVER_PORT); } diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index 2b3e25abc9..a1e75bff61 100644 --- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -255,12 +255,16 @@ TEST_F(Dhcpv4SrvTest, adjustIfaceDataRelayPort) { // Set hops value for the response. resp->setHops(req->getHops()); + // Set the remote port to 67 as we know it will be updated. + resp->setRemotePort(67); + // This function never throws. ASSERT_NO_THROW(NakedDhcpv4Srv::adjustIfaceData(ex)); // Now the destination address should be relay's address. EXPECT_EQ("192.0.1.1", resp->getRemoteAddr().toText()); - // The query has been relayed, so the response must be sent to the port 67. + // The query has been relayed, so the response should be sent to the + // port 67, but here there is a relay port RAI so another value is used. EXPECT_EQ(1234, resp->getRemotePort()); // Local address should be the address assigned to interface eth1. EXPECT_EQ("192.0.2.5", resp->getLocalAddr().toText()); diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index cbba992675..64ea2821e3 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -764,7 +764,7 @@ Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp) { rsp->setRemotePort(DHCP6_CLIENT_PORT); } else { // Relayed traffic, send back to the relay agent - uint16_t relay_port = testRelaySourcePort(query); + uint16_t relay_port = checkRelaySourcePort(query); rsp->setRemotePort(relay_port ? relay_port : DHCP6_SERVER_PORT); } @@ -3374,7 +3374,7 @@ void Dhcpv6Srv::processRSOO(const Pkt6Ptr& query, const Pkt6Ptr& rsp) { } } -uint16_t Dhcpv6Srv::testRelaySourcePort(const Pkt6Ptr& query) { +uint16_t Dhcpv6Srv::checkRelaySourcePort(const Pkt6Ptr& query) { if (query->relay_info_.empty()) { // No relay agent @@ -3383,7 +3383,7 @@ uint16_t Dhcpv6Srv::testRelaySourcePort(const Pkt6Ptr& query) { // Did the last relay agent add a relay-source-port? if (query->getRelayOption(D6O_RELAY_SOURCE_PORT, 0)) { - // draft-ietf-dhc-relay-port-10.txt section 5.2 + // RFC 8357 section 5.2 return (query->getRemotePort()); } diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h index 390ae19d4d..3f4e6afe96 100644 --- a/src/bin/dhcp6/dhcp6_srv.h +++ b/src/bin/dhcp6/dhcp6_srv.h @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -762,7 +762,7 @@ public: /// /// @param query DHCPv6 message to be checked. /// @return the port to use to join the relay or 0 for the default. - static uint16_t testRelaySourcePort(const Pkt6Ptr& query); + static uint16_t checkRelaySourcePort(const Pkt6Ptr& query); private: diff --git a/src/bin/dhcp6/dhcp6to4_ipc.cc b/src/bin/dhcp6/dhcp6to4_ipc.cc index a3fa09120e..e236dfcd3a 100644 --- a/src/bin/dhcp6/dhcp6to4_ipc.cc +++ b/src/bin/dhcp6/dhcp6to4_ipc.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -79,7 +79,7 @@ void Dhcp6to4Ipc::handler() { // Should we check it is a DHCPV6_DHCPV4_RESPONSE? // Handle relay port - uint16_t relay_port = Dhcpv6Srv::testRelaySourcePort(pkt); + uint16_t relay_port = Dhcpv6Srv::checkRelaySourcePort(pkt); // The received message has been unpacked by the receive() function. This // method could have modified the message so it's better to pack() it diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc index 534b7b2371..e5c5b50fd8 100644 --- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc +++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/src/lib/dhcp/dhcp4.h b/src/lib/dhcp/dhcp4.h index 9b8af7dece..3a7081c9a5 100644 --- a/src/lib/dhcp/dhcp4.h +++ b/src/lib/dhcp/dhcp4.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2017 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2018 Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1995-2003 by Internet Software Consortium * * This Source Code Form is subject to the terms of the Mozilla Public @@ -272,7 +272,7 @@ static const uint16_t RAI_OPTION_ACCESS_POINT_NAME = 15; // RFC7839 static const uint16_t RAI_OPTION_ACCESS_POINT_BSSID = 16; // RFC7839 static const uint16_t RAI_OPTION_OPERATOR_ID = 17; // RFC7839 static const uint16_t RAI_OPTION_OPERATOR_REALM = 18; // RFC7839 -static const uint16_t RAI_OPTION_RELAY_PORT = 19; // I-D, to be assigned +static const uint16_t RAI_OPTION_RELAY_PORT = 19; // RFC8357 static const uint16_t RAI_OPTION_VIRTUAL_SUBNET_SELECT = 151; //RFC6607 static const uint16_t RAI_OPTION_VIRTUAL_SUBNET_SELECT_CTRL = 152; //RFC6607 diff --git a/src/lib/dhcp/dhcp6.h b/src/lib/dhcp/dhcp6.h index 7b67badbb6..7b96f11824 100644 --- a/src/lib/dhcp/dhcp6.h +++ b/src/lib/dhcp/dhcp6.h @@ -152,9 +152,8 @@ enum DHCPv6OptionType { // D6O_F_SERVER_STATE = 132, /* RFC8156 */ // D6O_F_START_TIME_OF_STATE = 133, /* RFC8156 */ // D6O_F_STATE_EXPIRATION_TIME = 134, /* RFC8156 */ -// not yet assigned but next free value - D6O_RELAY_SOURCE_PORT = 135, /* draft-ietf-dhc-relay-port-10.txt */ - // 135-142 unassigned + D6O_RELAY_SOURCE_PORT = 135, /* RFC8357 */ + // 136-142 unassigned D6O_IPV6_ADDRESS_ANDSF = 143, /* RFC6153 */ // The following are EXPERIMENTAL and may change when IANA assigns official