]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[677-kea4-not-honouring-the-p-switch] Improved -p support
authorFrancis Dupont <fdupont@isc.org>
Fri, 11 Oct 2019 12:46:00 +0000 (14:46 +0200)
committerTomek Mrugalski <tomasz@isc.org>
Thu, 24 Oct 2019 19:40:08 +0000 (21:40 +0200)
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/dhcp4_srv.h
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dhcp4_test_utils.h
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/dhcp6_srv.h
src/bin/dhcp6/kea-dhcp6.rst
src/bin/dhcp6/kea-dhcp6.xml
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
src/bin/dhcp6/tests/dhcp6_test_utils.h

index 456c6d9d896dcd75aab209a4d52092b2d3ca4c5d..1b4b155561d14d32cae10713275cc01dd46a37db 100644 (file)
@@ -466,7 +466,7 @@ const std::string Dhcpv4Srv::VENDOR_CLASS_PREFIX("VENDOR_CLASS_");
 Dhcpv4Srv::Dhcpv4Srv(uint16_t server_port, uint16_t client_port,
                      const bool use_bcast, const bool direct_response_desired)
     : io_service_(new IOService()), shutdown_(true), alloc_engine_(),
-      server_port_(server_port), use_bcast_(use_bcast),
+      use_bcast_(use_bcast), server_port_(server_port),
       client_port_(client_port),
       network_state_(new NetworkState(NetworkState::DHCPv4)),
       cb_control_(new CBControlDHCPv4()) {
@@ -2461,7 +2461,11 @@ Dhcpv4Srv::adjustIfaceData(Dhcpv4Exchange& ex) {
         response->setIface(query->getIface());
     }
 
-    response->setLocalPort(DHCP4_SERVER_PORT);
+    if (server_port_) {
+        response->setLocalPort(server_port_);
+    } else {
+        response->setLocalPort(DHCP4_SERVER_PORT);
+    }
 }
 
 void
index 490387a9249ae99c7fa23d9d9f450b7147bc19dd..13265a5e29521b73610193a9d603a62f05094d7d 100644 (file)
@@ -984,14 +984,14 @@ private:
     /// @return Option that contains netmask information
     static OptionPtr getNetmaskOption(const Subnet4Ptr& subnet);
 
-    /// UDP port number on which server listens.
-    uint16_t server_port_;
-
     /// Should broadcast be enabled on sockets (if true).
     bool use_bcast_;
 
 protected:
 
+    /// UDP port number on which server listens.
+    uint16_t server_port_;
+
     /// UDP port number to which server sends responses.
     uint16_t client_port_;
 
index 07e6fe6d9d85dac7286e7784547f92cbe7c90e53..da1621bae3e1c6e017b0b3b154ef45ddf869c76d 100644 (file)
@@ -200,8 +200,9 @@ TEST_F(Dhcpv4SrvTest, adjustIfaceDataRelay) {
     // Clear remote address.
     resp->setRemoteAddr(IOAddress("0.0.0.0"));
 
-    // Set the client port.
+    // Set the client and server ports.
     srv_.client_port_ = 1234;
+    srv_.server_port_ = 2345;
 
     ASSERT_NO_THROW(srv_.adjustIfaceData(ex));
 
@@ -210,6 +211,9 @@ TEST_F(Dhcpv4SrvTest, adjustIfaceDataRelay) {
 
     // Remote port was enforced to the client port.
     EXPECT_EQ(srv_.client_port_, resp->getRemotePort());
+
+    // Local port was enforced to the server port.
+    EXPECT_EQ(srv_.server_port_, resp->getLocalPort());
 }
 
 // This test verifies that the remote port is adjusted when
@@ -2125,6 +2129,48 @@ TEST_F(Dhcpv4SrvTest, portsClientPort) {
     EXPECT_EQ(srv.client_port_, offer->getRemotePort());
 }
 
+// Checks if server port can be overridden in packets being sent.
+TEST_F(Dhcpv4SrvTest, portsServerPort) {
+    IfaceMgrTestConfig test_config(true);
+    IfaceMgr::instance().openSockets4();
+
+    // Do not use DHCP4_SERVER_PORT here as 0 means don't open sockets.
+    NakedDhcpv4Srv srv(0);
+    EXPECT_EQ(0, srv.server_port_);
+
+    // Use of the captured DHCPDISCOVER packet requires that
+    // subnet 10.254.226.0/24 is in use, because this packet
+    // contains the giaddr which belongs to this subnet and
+    // this giaddr is used to select the subnet
+    configure(CONFIGS[0]);
+    srv.server_port_ = 1234;
+
+    // Let's create a relayed DISCOVER. This particular relayed DISCOVER has
+    // added option 82 (relay agent info) with 3 suboptions. The server
+    // is supposed to echo it back in its response.
+    Pkt4Ptr dis;
+    ASSERT_NO_THROW(dis = PktCaptures::captureRelayedDiscover());
+
+    // Simulate that we have received that traffic
+    srv.fakeReceive(dis);
+
+    // Server will now process to run its normal loop, but instead of calling
+    // IfaceMgr::receive4(), it will read all packets from the list set by
+    // fakeReceive()
+    // In particular, it should call registered buffer4_receive callback.
+    srv.run();
+
+    // Check that the server did send a response
+    ASSERT_EQ(1, srv.fake_sent_.size());
+
+    // Make sure that we received a response
+    Pkt4Ptr offer = srv.fake_sent_.front();
+    ASSERT_TRUE(offer);
+
+    // Get Relay Agent Info from query...
+    EXPECT_EQ(srv.server_port_, offer->getLocalPort());
+}
+
 /// @todo Implement tests for subnetSelect See tests in dhcp6_srv_unittest.cc:
 /// selectSubnetAddr, selectSubnetIface, selectSubnetRelayLinkaddr,
 /// selectSubnetRelayInterfaceId. Note that the concept of interface-id is not
index 433db9f7b920b9eabf4f3ddd9dc9de780f7d2772..231655b42bc299ec0cfa53c3eb0e1b0e56bf22bc 100644 (file)
@@ -229,6 +229,7 @@ public:
     using Dhcpv4Srv::VENDOR_CLASS_PREFIX;
     using Dhcpv4Srv::shutdown_;
     using Dhcpv4Srv::alloc_engine_;
+    using Dhcpv4Srv::server_port_;
     using Dhcpv4Srv::client_port_;
 };
 
index 6f9236ac64c852b45e0782c44a0390544ba49205..d1e02821ae738324a58f9d574acafac0b0405d89 100644 (file)
@@ -835,7 +835,11 @@ Dhcpv6Srv::processPacket(Pkt6Ptr& query, Pkt6Ptr& rsp) {
         rsp->setRemotePort(relay_port ? relay_port : DHCP6_SERVER_PORT);
     }
 
-    rsp->setLocalPort(DHCP6_SERVER_PORT);
+    if (server_port_) {
+        rsp->setLocalPort(server_port_);
+    } else {
+        rsp->setLocalPort(DHCP6_SERVER_PORT);
+    }
     rsp->setIndex(query->getIndex());
     rsp->setIface(query->getIface());
 
index 248e4c3eb8790cd3ac75978967f27bdbaa33baaa..80e42a47b11173eb41342934372ad3d789879baa 100644 (file)
@@ -999,10 +999,10 @@ private:
     /// @return true if option has been requested in the ORO.
     bool requestedInORO(const Pkt6Ptr& query, const uint16_t code) const;
 
+protected:
     /// UDP port number on which server listens.
     uint16_t server_port_;
 
-protected:
     /// UDP port number to which server sends all responses.
     uint16_t client_port_;
 
index f8d1430b18df25383bdda084459e586854f81150..5086315f8ca25f0791148f75c1c6d76629cb7819 100644 (file)
@@ -3,7 +3,7 @@ kea-dhcp6
 Kea
 kea-dhcp6
 DHCPv6 server in Kea
-2011-2018
+2011-2019
 Internet Systems Consortium, Inc. ("ISC")
 kea-dhcp6
 -v
@@ -16,6 +16,8 @@ config-file
 config-file
 -p
 server-port-number
+-P
+client-port-number
 DESCRIPTION
 ===========
 
@@ -52,6 +54,10 @@ The arguments are as follows:
    Server port number (1-65535) on which the server listens. This is
    useful for testing purposes only.
 
+``-P``
+   Client port number (1-65535) to which the server responds. This is
+   useful for testing purposes only.
+
 DOCUMENTATION
 =============
 
index da10304760c8e88b38bee294515a24942b60287f..eae41f2745beaac242b0860591f8c759c986ce53 100644 (file)
@@ -9,8 +9,8 @@
 
   <info>
     <productname>ISC Kea</productname>
-    <date>Aug 28, 2019</date>
-    <edition>1.6.0</edition>
+    <date>Oct 11, 2019</date>
+    <edition>1.7.1</edition>
     <author>
       <contrib>The Kea software has been written by a number of
         engineers working for ISC: Tomek Mrugalski, Stephen Morris, Marcin
@@ -49,6 +49,7 @@
       <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
       <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">config-file</replaceable></option></arg>
       <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">server-port-number</replaceable></option></arg>
+      <arg choice="opt" rep="norepeat"><option>-P <replaceable class="parameter">client-port-number</replaceable></option></arg>
     </cmdsynopsis>
   </refsynopsisdiv>
 
         </para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>-P</option></term>
+        <listitem><para>
+          Client port number (1-65535) to which the server responds.
+          This is useful for testing purposes only.
+        </para></listitem>
+      </varlistentry>
+
     </variablelist>
   </refsect1>
 
index e8062b43ac269f65fa487cb1208243a25ba6563b..4e6cbb1fec44d8664994e940e65515d68dd1b0f9 100644 (file)
@@ -1967,6 +1967,36 @@ TEST_F(Dhcpv6SrvTest, portsClientPort) {
     EXPECT_EQ(srv.client_port_, adv->getRemotePort());
 }
 
+// Checks if server responses are sent to the proper port.
+TEST_F(Dhcpv6SrvTest, portsServerPort) {
+
+    // Create the test server in test mode.
+    NakedDhcpv6Srv srv(0);
+
+    // Enforce a specific server port value.
+    EXPECT_EQ(0, srv.server_port_);
+    srv.server_port_ = 1234;
+
+    // Let's create a simple SOLICIT
+    Pkt6Ptr sol = PktCaptures::captureSimpleSolicit();
+
+    // Simulate that we have received that traffic
+    srv.fakeReceive(sol);
+
+    // 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();
+
+    // Get Advertise...
+    ASSERT_FALSE(srv.fake_sent_.empty());
+    Pkt6Ptr adv = srv.fake_sent_.front();
+    ASSERT_TRUE(adv);
+
+    // Verify the local port: it must be the server port.
+    EXPECT_EQ(srv.server_port_, adv->getLocalPort());
+}
+
 // Checks if server responses are sent to the proper port.
 TEST_F(Dhcpv6SrvTest, portsDirectTraffic) {
 
index 8ae6b80029a40775092f8792d5e88662801e8fca..d295bb72342862981547963614bcb597ed40cf93 100644 (file)
@@ -272,6 +272,7 @@ public:
     using Dhcpv6Srv::name_change_reqs_;
     using Dhcpv6Srv::VENDOR_CLASS_PREFIX;
     using Dhcpv6Srv::initContext;
+    using Dhcpv6Srv::server_port_;
     using Dhcpv6Srv::client_port_;
 
     /// @brief packets we pretend to receive