Browse Source

[3279] Implemented a Dhcpv4Srv function which checks server identifier.

Marcin Siodelski 11 years ago
parent
commit
eb73d9223b

+ 29 - 1
src/bin/dhcp4/dhcp4_srv.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -1525,6 +1525,34 @@ Dhcpv4Srv::selectSubnet(const Pkt4Ptr& question) {
     return (subnet);
     return (subnet);
 }
 }
 
 
+bool
+Dhcpv4Srv::acceptServerId(const Pkt4Ptr& pkt) const {
+    // This function is meant to be called internally by the server class, so
+    // we rely on the caller to sanity check the pointer and we don't check
+    // it here.
+
+    // Check if server identifier option is present. If it is not present
+    // we accept the message because it is targetted to all servers.
+    // Note that we don't check cases that server identifier is mandatory
+    // but not present. This is meant to be sanity checked in other
+    // functions.
+    OptionPtr option = pkt->getOption(DHO_DHCP_SERVER_IDENTIFIER);
+    if (!option) {
+        return (true);
+    }
+    // Server identifier is present. Let's convert it to 4-byte address
+    // and try to match with server identifiers used by the server.
+    Option4AddrLstPtr option_addrs =
+        boost::dynamic_pointer_cast<Option4AddrLst>(option);
+    Option4AddrLst::AddressContainer addrs = option_addrs->getAddresses();
+
+    if (addrs.size() != 1) {
+        return (false);
+    }
+
+    return (IfaceMgr::instance().hasOpenSocket(addrs[0]));
+}
+
 void
 void
 Dhcpv4Srv::sanityCheck(const Pkt4Ptr& pkt, RequirementLevel serverid) {
 Dhcpv4Srv::sanityCheck(const Pkt4Ptr& pkt, RequirementLevel serverid) {
     OptionPtr server_id = pkt->getOption(DHO_DHCP_SERVER_IDENTIFIER);
     OptionPtr server_id = pkt->getOption(DHO_DHCP_SERVER_IDENTIFIER);

+ 15 - 0
src/bin/dhcp4/dhcp4_srv.h

@@ -167,6 +167,21 @@ public:
 
 
 protected:
 protected:
 
 
+    /// @brief Verifies if the server id belongs to our server.
+    ///
+    /// This function checks if the server identifier carried in the specified
+    /// DHCPv4 message belongs to this server. If the server identifier option
+    /// is absent or the value carried by this option is equal to one of the
+    /// server identifiers used by the server, the true is returned. If the
+    /// server identifier option is present, but it doesn't match any server
+    /// identifier used by this server, the false value is returned.
+    ///
+    /// @param pkt DHCPv4 message which server identifier is to be checked.
+    ///
+    /// @return true, if the server identifier is absent or matches one of the
+    /// server identifiers that the server is using; false otherwise.
+    bool acceptServerId(const Pkt4Ptr& pkt) const;
+
     /// @brief verifies if specified packet meets RFC requirements
     /// @brief verifies if specified packet meets RFC requirements
     ///
     ///
     /// Checks if mandatory option is really there, that forbidden option
     /// Checks if mandatory option is really there, that forbidden option

+ 47 - 1
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2011-2013  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -1031,6 +1031,52 @@ TEST_F(Dhcpv4SrvFakeIfaceTest, RenewBasic) {
     EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
     EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
 }
 }
 
 
+// This test verifies that the logic which matches server identifier in the
+// received message with server identifiers used by a server works correctly:
+// - a message with no server identifier is accepted,
+// - a message with a server identifier which matches one of the server
+// identifiers used by a server is accepted,
+// - a message with a server identifier which doesn't match any server
+// identifier used by a server, is not accepted.
+TEST_F(Dhcpv4SrvFakeIfaceTest, acceptServerId) {
+    NakedDhcpv4Srv srv(0);
+
+    Pkt4Ptr pkt(new Pkt4(DHCPREQUEST, 1234));
+    // If no server identifier option is present, the message is always
+    // accepted.
+    EXPECT_TRUE(srv.acceptServerId(pkt));
+
+    // Add a server identifier option which doesn't match server ids being
+    // 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 interface.
+    OptionPtr other_serverid(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER,
+                                                IOAddress("10.1.2.3")));
+    pkt->addOption(other_serverid);
+    EXPECT_FALSE(srv.acceptServerId(pkt));
+
+    // Remove the server identifier.
+    ASSERT_NO_THROW(pkt->delOption(DHO_DHCP_SERVER_IDENTIFIER));
+
+    // Add a server id being an IPv4 address configured on eth0 interface.
+    // A DHCPv4 message holding this server identifier should be accepted.
+    OptionPtr eth0_serverid(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER,
+                                               IOAddress("192.0.3.1")));
+    ASSERT_NO_THROW(pkt->addOption(eth0_serverid));
+    EXPECT_TRUE(srv.acceptServerId(pkt));
+
+    // Remove the server identifier.
+    ASSERT_NO_THROW(pkt->delOption(DHO_DHCP_SERVER_IDENTIFIER));
+
+    // Add a server id being an IPv4 address configured on eth1 interface.
+    // A DHCPv4 message holding this server identifier should be accepted.
+    OptionPtr eth1_serverid(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER,
+                                               IOAddress("10.0.0.1")));
+    ASSERT_NO_THROW(pkt->addOption(eth1_serverid));
+    EXPECT_TRUE(srv.acceptServerId(pkt));
+
+}
+
 // @todo: Implement tests for rejecting renewals
 // @todo: Implement tests for rejecting renewals
 
 
 // This test verifies if the sanityCheck() really checks options presence.
 // This test verifies if the sanityCheck() really checks options presence.

+ 1 - 0
src/bin/dhcp4/tests/dhcp4_test_utils.h

@@ -438,6 +438,7 @@ public:
     using Dhcpv4Srv::processClientName;
     using Dhcpv4Srv::processClientName;
     using Dhcpv4Srv::computeDhcid;
     using Dhcpv4Srv::computeDhcid;
     using Dhcpv4Srv::createNameChangeRequests;
     using Dhcpv4Srv::createNameChangeRequests;
+    using Dhcpv4Srv::acceptServerId;
     using Dhcpv4Srv::sanityCheck;
     using Dhcpv4Srv::sanityCheck;
     using Dhcpv4Srv::srvidToString;
     using Dhcpv4Srv::srvidToString;
     using Dhcpv4Srv::unpackOptions;
     using Dhcpv4Srv::unpackOptions;