BIND 10 trac3203, updated. c5e286f1fdaef8bde35951ca0b2a8947654c9095 [3203] Client classification added in DHCPv4.
BIND 10 source code commits
bind10-changes at lists.isc.org
Fri Oct 18 09:11:12 UTC 2013
The branch, trac3203 has been updated
via c5e286f1fdaef8bde35951ca0b2a8947654c9095 (commit)
via edc603c54d0da5cdff12a67d9b2f993d5705570f (commit)
from bdc703178e699d643504b21c6a754345e821b8ed (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit c5e286f1fdaef8bde35951ca0b2a8947654c9095
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Fri Oct 18 11:10:54 2013 +0200
[3203] Client classification added in DHCPv4.
commit edc603c54d0da5cdff12a67d9b2f993d5705570f
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Fri Oct 18 10:46:52 2013 +0200
[3203] DHCPv4 Vendor-class option is now a string.
-----------------------------------------------------------------------
Summary of changes:
src/bin/dhcp4/dhcp4_messages.mes | 8 +++
src/bin/dhcp4/dhcp4_srv.cc | 77 ++++++++++++++++++++++++++++-
src/bin/dhcp4/dhcp4_srv.h | 13 +++++
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc | 29 +++++++++++
src/bin/dhcp4/tests/dhcp4_test_utils.h | 12 ++++-
src/bin/dhcp4/tests/wireshark.cc | 60 +++++++++++++++++++++-
src/lib/dhcp/dhcp4.h | 1 +
src/lib/dhcp/std_option_defs.h | 2 +-
src/lib/dhcp/tests/libdhcp++_unittest.cc | 2 +-
9 files changed, 198 insertions(+), 6 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/dhcp4/dhcp4_messages.mes b/src/bin/dhcp4/dhcp4_messages.mes
index fca75bf..2e7b9b7 100644
--- a/src/bin/dhcp4/dhcp4_messages.mes
+++ b/src/bin/dhcp4/dhcp4_messages.mes
@@ -27,6 +27,14 @@ successfully established a session with the BIND 10 control channel.
This debug message is issued just before the IPv4 DHCP server attempts
to establish a session with the BIND 10 control channel.
+% DHCP4_CLASS_PROCESSING_FAILED client class specific processing failed
+This debug message means that the server processing that is unique for each
+client class has reported a failure. The response packet will not be sent.
+
+% DHCP4_CLASS_ASSIGNED client packet has been assigned to the following class(es): %1
+This debug message informs that incoming packet has been assigned to specified
+class or classes. This is a norma
+
% DHCP4_COMMAND_RECEIVED received command %1, arguments: %2
A debug message listing the command (and possible arguments) received
from the BIND 10 control system by the IPv4 DHCP server.
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index f2903ba..87cf238 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -20,6 +20,7 @@
#include <dhcp/option4_addrlst.h>
#include <dhcp/option_int.h>
#include <dhcp/option_int_array.h>
+#include <dhcp/option_string.h>
#include <dhcp/pkt4.h>
#include <dhcp4/dhcp4_log.h>
#include <dhcp4/dhcp4_srv.h>
@@ -293,6 +294,9 @@ Dhcpv4Srv::run() {
callout_handle->getArgument("query4", query);
}
+ // Assign this packet to one or more classes if needed
+ classifyPacket(query);
+
try {
switch (query->getType()) {
case DHCPDISCOVER:
@@ -351,7 +355,14 @@ Dhcpv4Srv::run() {
adjustRemoteAddr(query, rsp);
- if (!rsp->getHops()) {
+ if (!classSpecificProcessing(query, rsp)) {
+ /// @todo add more verbosity here
+ LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_PROCESSING_FAILED);
+
+ continue;
+ }
+
+ if (query->getRemotePort() == DHCP4_CLIENT_PORT) {
rsp->setRemotePort(DHCP4_CLIENT_PORT);
} else {
rsp->setRemotePort(DHCP4_SERVER_PORT);
@@ -1266,6 +1277,70 @@ Dhcpv4Srv::unpackOptions(const OptionBuffer& buf,
return (offset);
}
+void Dhcpv4Srv::classifyPacket(const Pkt4Ptr& pkt) {
+ boost::shared_ptr<OptionString> vendor_class =
+ boost::dynamic_pointer_cast<OptionString>(pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER));
+
+ string classes = "";
+
+ if (!vendor_class) {
+ return;
+ }
+
+ // DOCSIS specific section
+ if (vendor_class->getValue().find("docsis3.0") != std::string::npos) {
+ pkt->addClass("docsis3.0");
+ classes += "docsis3.0 ";
+ }
+
+ if (vendor_class->getValue().find("eRouter1.0") != std::string::npos) {
+ pkt->addClass("eRouter1.0");
+ classes += "eRouter1.0 ";
+ }
+
+ classes += vendor_class->getValue();
+ pkt->addClass(vendor_class->getValue());
+
+ if (!classes.empty()) {
+ LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_ASSIGNED)
+ .arg(classes);
+ }
+}
+
+bool Dhcpv4Srv::classSpecificProcessing(const Pkt4Ptr& query, const Pkt4Ptr& rsp) {
+
+ Subnet4Ptr subnet = selectSubnet(query);
+ if (!subnet) {
+ return (true);
+ }
+
+ if (query->inClass("docsis3.0")) {
+
+ // set next-server
+ // @todo uncomment this once 3191 is merged
+ // rsp->setSiaddr(subnet->getSiaddr());
+
+ Subnet::OptionDescriptor desc =
+ subnet->getOptionDescriptor("dhcp4", DHO_BOOT_FILE_NAME);
+
+ if (desc.option) {
+ boost::shared_ptr<OptionString> boot =
+ boost::dynamic_pointer_cast<OptionString>(desc.option);
+ if (boot) {
+ std::string filename = boot->getValue();
+ rsp->setFile((const uint8_t*)filename.c_str(), filename.size());
+ }
+ }
+ }
+
+ if (query->inClass("eRouter1.0")) {
+
+
+ }
+
+ return (true);
+}
+
} // namespace dhcp
} // namespace isc
diff --git a/src/bin/dhcp4/dhcp4_srv.h b/src/bin/dhcp4/dhcp4_srv.h
index 5c89c85..aedfa71 100644
--- a/src/bin/dhcp4/dhcp4_srv.h
+++ b/src/bin/dhcp4/dhcp4_srv.h
@@ -361,6 +361,19 @@ protected:
const std::string& option_space,
isc::dhcp::OptionCollection& options);
+ /// @brief Assigns incoming packet to a given class
+ /// @param pkt packet to be classified
+ void classifyPacket(const Pkt4Ptr& pkt);
+
+ /// @brief Performs packet processing specific to a class
+ ///
+ /// This processing is a likely candidate to be pushed into hooks.
+ ///
+ /// @param query incoming client's packet
+ /// @param rsp server's response
+ /// @return true if successful, false otherwise (will prevent sending response)
+ bool classSpecificProcessing(const Pkt4Ptr& query, const Pkt4Ptr& rsp);
+
private:
/// @brief Constructs netmask option based on subnet4
diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
index 3f2da84..313c5ff 100644
--- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
+++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
@@ -151,6 +151,7 @@ public:
using Dhcpv4Srv::sanityCheck;
using Dhcpv4Srv::srvidToString;
using Dhcpv4Srv::unpackOptions;
+ using Dhcpv4Srv::classifyPacket;
};
#endif
@@ -2633,6 +2634,34 @@ TEST_F(HooksDhcpv4SrvTest, lease4ReleaseSkip) {
//EXPECT_EQ(leases.size(), 1);
}
+// Checks if client packets are classified properly
+TEST_F(Dhcpv4SrvTest, clientClassification) {
+
+ NakedDhcpv4Srv srv(0);
+
+ // Let's create a relayed DISCOVER. This particular relayed DISCOVER has
+ // vendor-class set to docsis3.0
+ Pkt4Ptr dis1;
+ ASSERT_NO_THROW(dis1 = captureRelayedDiscover());
+ ASSERT_NO_THROW(dis1->unpack());
+
+ srv.classifyPacket(dis1);
+
+ EXPECT_TRUE(dis1->inClass("docsis3.0"));
+ EXPECT_FALSE(dis1->inClass("eRouter1.0"));
+
+ // Let's create a relayed DISCOVER. This particular relayed DISCOVER has
+ // vendor-class set to eRouter1.0
+ Pkt4Ptr dis2;
+ ASSERT_NO_THROW(dis2 = captureRelayedDiscover2());
+ ASSERT_NO_THROW(dis2->unpack());
+
+ srv.classifyPacket(dis2);
+
+ EXPECT_TRUE(dis2->inClass("eRouter1.0"));
+ EXPECT_FALSE(dis2->inClass("docsis3.0"));
+}
+
}; // end of isc::dhcp::test namespace
}; // end of isc::dhcp namespace
}; // end of isc namespace
diff --git a/src/bin/dhcp4/tests/dhcp4_test_utils.h b/src/bin/dhcp4/tests/dhcp4_test_utils.h
index 2e39a8b..90abda1 100644
--- a/src/bin/dhcp4/tests/dhcp4_test_utils.h
+++ b/src/bin/dhcp4/tests/dhcp4_test_utils.h
@@ -178,11 +178,20 @@ public:
/// @brief returns captured DISCOVER that went through a relay
///
- /// See method code for a detailed explanation.
+ /// See method code for a detailed explanation. This is a discover from
+ /// docsis3.0 device (Cable Modem)
///
/// @return relayed DISCOVER
Pkt4Ptr captureRelayedDiscover();
+ /// @brief returns captured DISCOVER that went through a relay
+ ///
+ /// See method code for a detailed explanation. This is a discover from
+ /// eRouter1.0 device (CPE device integrated with cable modem)
+ ///
+ /// @return relayed DISCOVER
+ Pkt4Ptr captureRelayedDiscover2();
+
/// @brief generates a DHCPv4 packet based on provided hex string
///
/// @return created packet
@@ -308,6 +317,7 @@ public:
using Dhcpv4Srv::sanityCheck;
using Dhcpv4Srv::srvidToString;
using Dhcpv4Srv::unpackOptions;
+ using Dhcpv4Srv::classifyPacket;
};
}; // end of isc::dhcp::test namespace
diff --git a/src/bin/dhcp4/tests/wireshark.cc b/src/bin/dhcp4/tests/wireshark.cc
index b563354..f6bb4b2 100644
--- a/src/bin/dhcp4/tests/wireshark.cc
+++ b/src/bin/dhcp4/tests/wireshark.cc
@@ -71,7 +71,10 @@ void Dhcpv4SrvTest::captureSetDefaultFields(const Pkt4Ptr& pkt) {
Pkt4Ptr Dhcpv4SrvTest::captureRelayedDiscover() {
-/* string exported from Wireshark:
+/* This is packet 1 from capture
+ dhcp-val/pcap/docsis-*-CG3000DCR-Registration-Filtered.cap
+
+string exported from Wireshark:
User Datagram Protocol, Src Port: bootps (67), Dst Port: bootps (67)
Source port: bootps (67)
@@ -98,7 +101,7 @@ Bootstrap Protocol
Magic cookie: DHCP
Option: (53) DHCP Message Type
Option: (55) Parameter Request List
- Option: (60) Vendor class identifier
+ Option: (60) Vendor class identifier (docsis3.0)
Option: (125) V-I Vendor-specific Information
Option: (43) Vendor-Specific Information (CableLabs)
Option: (61) Client identifier
@@ -127,6 +130,59 @@ Bootstrap Protocol
return (packetFromCapture(hex_string));
}
+Pkt4Ptr Dhcpv4SrvTest::captureRelayedDiscover2() {
+
+/* This is packet 5 from capture
+ dhcp-val/pcap/docsis-*-CG3000DCR-Registration-Filtered.cap
+
+string exported from Wireshark:
+
+User Datagram Protocol, Src Port: bootps (67), Dst Port: bootps (67)
+Bootstrap Protocol
+ Message type: Boot Request (1)
+ Hardware type: Ethernet (0x01)
+ Hardware address length: 6
+ Hops: 1
+ Transaction ID: 0x5d05478f
+ Seconds elapsed: 5
+ Bootp flags: 0x0000 (Unicast)
+ Client IP address: 0.0.0.0 (0.0.0.0)
+ Your (client) IP address: 0.0.0.0 (0.0.0.0)
+ Next server IP address: 0.0.0.0 (0.0.0.0)
+ Relay agent IP address: 10.254.226.1 (10.254.226.1)
+ Client MAC address: Netgear_b8:15:15 (20:e5:2a:b8:15:15)
+ Client hardware address padding: 00000000000000000000
+ Server host name not given
+ Boot file name not given
+ Magic cookie: DHCP
+ Option: (53) DHCP Message Type
+ Option: (55) Parameter Request List
+ Option: (43) Vendor-Specific Information
+ Option: (60) Vendor class identifier (eRouter1.0)
+ Option: (15) Domain Name
+ Option: (61) Client identifier
+ Option: (57) Maximum DHCP Message Size
+ Option: (82) Agent Information Option
+ Option: (255) End */
+
+ string hex_string =
+ "010106015d05478f000500000000000000000000000000000afee20120e52ab8151500"
+ "0000000000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000000063825363350101370e"
+ "480102030406070c0f171a36337a2b63020745524f55544552030b45434d3a45524f55"
+ "544552040d324252323239553430303434430504312e3034060856312e33332e303307"
+ "07322e332e305232080630303039354209094347333030304443520a074e6574676561"
+ "720f0745524f555445523c0a65526f75746572312e300f14687364312e70612e636f6d"
+ "636173742e6e65742e3d0fff2ab815150003000120e52ab81515390205dc5219010420"
+ "000002020620e52ab8151409090000118b0401020300ff";
+
+ return (packetFromCapture(hex_string));
+}
+
}; // end of isc::dhcp::test namespace
}; // end of isc::dhcp namespace
}; // end of isc namespace
diff --git a/src/lib/dhcp/dhcp4.h b/src/lib/dhcp/dhcp4.h
index 002e74f..12e08e4 100644
--- a/src/lib/dhcp/dhcp4.h
+++ b/src/lib/dhcp/dhcp4.h
@@ -125,6 +125,7 @@ enum DHCPOptionType {
DHO_DHCP_CLIENT_IDENTIFIER = 61,
DHO_NWIP_DOMAIN_NAME = 62,
DHO_NWIP_SUBOPTIONS = 63,
+ DHO_BOOT_FILE_NAME = 67,
DHO_USER_CLASS = 77,
DHO_FQDN = 81,
DHO_DHCP_AGENT_OPTIONS = 82,
diff --git a/src/lib/dhcp/std_option_defs.h b/src/lib/dhcp/std_option_defs.h
index 8ef33d0..856711f 100644
--- a/src/lib/dhcp/std_option_defs.h
+++ b/src/lib/dhcp/std_option_defs.h
@@ -158,7 +158,7 @@ const OptionDefParams OPTION_DEF_PARAMS4[] = {
{ "dhcp-rebinding-time", DHO_DHCP_REBINDING_TIME,
OPT_UINT32_TYPE, false, NO_RECORD_DEF, "" },
{ "vendor-class-identifier", DHO_VENDOR_CLASS_IDENTIFIER,
- OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
+ OPT_STRING_TYPE, false, NO_RECORD_DEF, "" },
{ "dhcp-client-identifier", DHO_DHCP_CLIENT_IDENTIFIER,
OPT_BINARY_TYPE, false, NO_RECORD_DEF, "" },
{ "nwip-domain-name", DHO_NWIP_DOMAIN_NAME, OPT_STRING_TYPE, false, NO_RECORD_DEF, "" },
diff --git a/src/lib/dhcp/tests/libdhcp++_unittest.cc b/src/lib/dhcp/tests/libdhcp++_unittest.cc
index fa863a4..b274de8 100644
--- a/src/lib/dhcp/tests/libdhcp++_unittest.cc
+++ b/src/lib/dhcp/tests/libdhcp++_unittest.cc
@@ -721,7 +721,7 @@ TEST_F(LibDhcpTest, stdOptionDefs4) {
typeid(OptionInt<uint32_t>));
LibDhcpTest::testStdOptionDefs4(DHO_VENDOR_CLASS_IDENTIFIER, begin, end,
- typeid(Option));
+ typeid(OptionString));
LibDhcpTest::testStdOptionDefs4(DHO_DHCP_CLIENT_IDENTIFIER, begin, end,
typeid(Option));
More information about the bind10-changes
mailing list