Browse Source

[2892] Merge branch 'trac2892'

Wlodek Wencel 11 years ago
parent
commit
3bd69e9b4a

+ 5 - 1
src/bin/dhcp6/dhcp6_messages.mes

@@ -1,4 +1,4 @@
-# Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2012-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
@@ -272,6 +272,10 @@ of packet.  Note that a packet marked as UNKNOWN may well be a valid
 DHCP packet, just a type not expected by the server (e.g. it will report
 DHCP packet, just a type not expected by the server (e.g. it will report
 a received OFFER packet as UNKNOWN).
 a received OFFER packet as UNKNOWN).
 
 
+% DHCP6_PACKET_MISMATCH_SERVERID_DROP dropping packet %1 (transid=%2, interface=%3) having mismatched server identifier
+A debug message noting that server has received message with server identifier
+option that not matching server identifier that server is using.
+
 % DHCP6_PACKET_RECEIVE_FAIL error on attempt to receive packet: %1
 % DHCP6_PACKET_RECEIVE_FAIL error on attempt to receive packet: %1
 The IPv6 DHCP server tried to receive a packet but an error
 The IPv6 DHCP server tried to receive a packet but an error
 occurred during this attempt. The reason for the error is included in
 occurred during this attempt. The reason for the error is included in

+ 33 - 0
src/bin/dhcp6/dhcp6_srv.cc

@@ -211,6 +211,33 @@ void Dhcpv6Srv::sendPacket(const Pkt6Ptr& packet) {
     IfaceMgr::instance().send(packet);
     IfaceMgr::instance().send(packet);
 }
 }
 
 
+bool
+Dhcpv6Srv::testServerID(const Pkt6Ptr& pkt){
+	/// @todo Currently we always check server identifier regardless if
+	/// it is allowed in the received message or not (per RFC3315).
+	/// If the server identifier is not allowed in the message, the
+	/// sanityCheck function should deal with it. We may rethink this
+	/// design if we decide that it is appropriate to check at this stage
+	/// of message processing that the server identifier must or must not
+	/// be present. In such case however, the logic checking server id
+	/// will have to be removed from sanityCheck and placed here instead,
+	/// to avoid duplicate checks.
+	OptionPtr server_id = pkt->getOption(D6O_SERVERID);
+	if (server_id){
+		// Let us test received ServerID if it is same as ServerID
+		// which is beeing used by server
+		if (getServerID()->getData() != server_id->getData()){
+			LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_PACKET_MISMATCH_SERVERID_DROP)
+				.arg(pkt->getName())
+				.arg(pkt->getTransid())
+				.arg(pkt->getIface());
+			return (false);
+		}
+	}
+	// retun True if: no serverid received or ServerIDs matching
+	return (true);
+}
+
 bool Dhcpv6Srv::run() {
 bool Dhcpv6Srv::run() {
     while (!shutdown_) {
     while (!shutdown_) {
         /// @todo Calculate actual timeout to the next event (e.g. lease
         /// @todo Calculate actual timeout to the next event (e.g. lease
@@ -283,6 +310,12 @@ bool Dhcpv6Srv::run() {
                 continue;
                 continue;
             }
             }
         }
         }
+        // Check if received query carries server identifier matching
+        // server identifier being used by the server.
+        if (!testServerID(query)){
+        	continue;
+        }
+
         LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PACKET_RECEIVED)
         LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL, DHCP6_PACKET_RECEIVED)
             .arg(query->getName());
             .arg(query->getName());
         LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_QUERY_DATA)
         LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL_DATA, DHCP6_QUERY_DATA)

+ 10 - 0
src/bin/dhcp6/dhcp6_srv.h

@@ -119,6 +119,16 @@ public:
 
 
 protected:
 protected:
 
 
+    /// @brief Compare received server id with our server id
+    ///
+    /// Checks if the server id carried in a query from a client matches
+    /// server identifier being used by the server.
+    ///
+    /// @param pkt DHCPv6 packet carrying server identifier to be checked.
+    /// @return true if server id carried in the query matches server id
+    /// used by the server; false otherwise.
+    bool testServerID(const Pkt6Ptr& pkt);
+
     /// @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

+ 37 - 1
src/bin/dhcp6/tests/dhcp6_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
@@ -1073,6 +1073,42 @@ TEST_F(Dhcpv6SrvTest, sanityCheck) {
     EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY),
     EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY),
                  RFCViolation);
                  RFCViolation);
 }
 }
+// Check that the server is testing if server identifier received in the
+// query, matches server identifier used by the server.
+TEST_F(Dhcpv6SrvTest, testServerID) {
+	NakedDhcpv6Srv srv(0);
+
+	Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
+    std::vector<uint8_t> bin;
+
+    // diud_llt constructed with: time = 0, macaddress = 00:00:00:00:00:00
+    // it's necessary to generate server identifier option
+    isc::util::encode::decodeHex("0001000100000000000000000000", bin);
+    // Now create server identifier option
+    OptionPtr serverid = OptionPtr(new Option(Option::V6, D6O_SERVERID, bin));
+
+    // Server identifier option is MANDATORY in Request message.
+    // Add server identifier option with different value from one that
+    // server is using.
+    req->addOption(serverid);
+
+    // Message shoud be dropped
+    EXPECT_FALSE(srv.testServerID(req));
+
+    // Delete server identifier option and add new one, with same value as
+    // server's server identifier.
+    req->delOption(D6O_SERVERID);
+    req->addOption(srv.getServerID());
+
+    // With proper server identifier we expect true
+    EXPECT_TRUE(srv.testServerID(req));
+
+    // server-id MUST NOT appear in Solicit, so check if server is
+    // not dropping a message without server id.
+    Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
+
+    EXPECT_TRUE(srv.testServerID(req));
+}
 
 
 // This test verifies if selectSubnet() selects proper subnet for a given
 // This test verifies if selectSubnet() selects proper subnet for a given
 // source address.
 // source address.

+ 2 - 1
src/bin/dhcp6/tests/dhcp6_test_utils.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2013  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-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
@@ -111,6 +111,7 @@ public:
     using Dhcpv6Srv::createRemovalNameChangeRequest;
     using Dhcpv6Srv::createRemovalNameChangeRequest;
     using Dhcpv6Srv::createStatusCode;
     using Dhcpv6Srv::createStatusCode;
     using Dhcpv6Srv::selectSubnet;
     using Dhcpv6Srv::selectSubnet;
+    using Dhcpv6Srv::testServerID;
     using Dhcpv6Srv::sanityCheck;
     using Dhcpv6Srv::sanityCheck;
     using Dhcpv6Srv::classifyPacket;
     using Dhcpv6Srv::classifyPacket;
     using Dhcpv6Srv::loadServerID;
     using Dhcpv6Srv::loadServerID;