From: Thomas Markwalder Date: Tue, 27 Feb 2018 19:46:40 +0000 (-0500) Subject: [5551] kea-dhcp4 now attempts to process packets with truncated VIVSO X-Git-Tag: trac5530a_base~3^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f202ec600b358897bda88f9f9c119b98c7b19a8e;p=thirdparty%2Fkea.git [5551] kea-dhcp4 now attempts to process packets with truncated VIVSO src/lib/dhcp/option.h SkipRemainingOptionsError - new error to signal that unpacking skipped options src/lib/dhcp/option_vendor.cc OptionVendor::unpack() - modified to throw SkipRemainingOptions on truncated length src/lib/dhcp/option_definition.cc OptionDefinition::optionFactory() Added catch-rethrow of SkipRemainginOptionsError src/bin/dhcp4/dhcp4_messages.mes Added DHCP4_PACKET_OPTIONS_SKIPPED log message src/bin/dhcp4/dhcp4_srv.cc Dhcpv4Srv::processPacket() - added explicit catch of SkipRemainingOptionsError which logs the error but allows the processing to continue. src/bin/dhcp4/tests/dhcp4_srv_unittest.cc TEST_F(Dhcpv4SrvTest, truncatedVIVSOOption) - new test to verify skip-options logic for truncated vendor option src/lib/dhcp/tests/pkt4_unittest.cc TEST_F(Pkt4Test, truncatedVendorLength) - new test that verifies Pkt4 unpacking of truncated VIVSO src/lib/dhcp/tests/pkt_captures4.cc Pkt4Ptr PktCaptures::discoverWithValidVIVSO() Pkt4Ptr PktCaptures::discoverWithTruncatedVIVSO() - new captured discovers --- diff --git a/src/bin/dhcp4/dhcp4_messages.mes b/src/bin/dhcp4/dhcp4_messages.mes index fef6ef62dc..c7ff62fe03 100644 --- a/src/bin/dhcp4/dhcp4_messages.mes +++ b/src/bin/dhcp4/dhcp4_messages.mes @@ -376,6 +376,11 @@ server is about to open sockets on the specified port. A warning message issued when IfaceMgr fails to open and bind a socket. The reason for the failure is appended as an argument of the log message. +% DHCP4_PACKET_OPTIONS_SKIPPED An error upacking an option, caused subsequent options to be skipped: %1 +A debug message issued when an option failed to unpack correctly, making it +impossible to unpack the remaining options in the packet. The server will +server will still attempt to service the packet + % DHCP4_PACKET_DROP_0001 failed to parse packet from %1 to %2, received over interface %3, reason: %4 The DHCPv4 server has received a packet that it is unable to interpret. The reason why the packet is invalid is included in the message. diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 03b3873d73..20b9b480f0 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 @@ -964,6 +964,12 @@ Dhcpv4Srv::processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp) { .arg(query->getLocalAddr().toText()) .arg(query->getIface()); query->unpack(); + } catch (const SkipRemainingOptionsError& e) { + // An option failed to unpack but we are to attempt to process it + // anyway. Log it and let's hope for the best. + LOG_DEBUG(options4_logger, DBG_DHCP4_DETAIL, + DHCP4_PACKET_OPTIONS_SKIPPED) + .arg(e.what()); } catch (const std::exception& e) { // Failed to parse the packet. LOG_DEBUG(bad_packet4_logger, DBG_DHCP4_DETAIL, @@ -3107,7 +3113,7 @@ Dhcpv4Srv::deferredUnpack(Pkt4Ptr& query) opt = def->optionFactory(Option::V4, code, buf.cbegin(), buf.cend()); query->addOption(opt); } -} +} void Dhcpv4Srv::startD2() { diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index 25b540c1ff..d7158c0148 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 @@ -2458,7 +2458,7 @@ TEST_F(Dhcpv4SrvTest, option43LastResort) { // Check if we get response at all checkResponse(offer, DHCPOFFER, 1234); - + // Processing should add a vendor-class-identifier (code 60) OptionPtr opt = offer->getOption(DHO_VENDOR_CLASS_IDENTIFIER); EXPECT_TRUE(opt); @@ -2549,7 +2549,7 @@ TEST_F(Dhcpv4SrvTest, option43BadRaw) { // Check if we get response at all checkResponse(offer, DHCPOFFER, 1234); - + // Processing should add a vendor-class-identifier (code 60) OptionPtr opt = offer->getOption(DHO_VENDOR_CLASS_IDENTIFIER); EXPECT_TRUE(opt); @@ -2713,7 +2713,7 @@ TEST_F(Dhcpv4SrvTest, option43RawGlobal) { // Check if we get response at all checkResponse(offer, DHCPOFFER, 1234); - + // Processing should add a vendor-class-identifier (code 60) OptionPtr opt = offer->getOption(DHO_VENDOR_CLASS_IDENTIFIER); EXPECT_TRUE(opt); @@ -2808,7 +2808,7 @@ TEST_F(Dhcpv4SrvTest, option43RawClass) { // Check if we get response at all checkResponse(offer, DHCPOFFER, 1234); - + // Processing should add a vendor-class-identifier (code 60) OptionPtr opt = offer->getOption(DHO_VENDOR_CLASS_IDENTIFIER); EXPECT_TRUE(opt); @@ -2920,7 +2920,7 @@ TEST_F(Dhcpv4SrvTest, option43Class) { // Check if we get response at all checkResponse(offer, DHCPOFFER, 1234); - + // Processing should add a vendor-class-identifier (code 60) OptionPtr opt = offer->getOption(DHO_VENDOR_CLASS_IDENTIFIER); EXPECT_TRUE(opt); @@ -3054,7 +3054,7 @@ TEST_F(Dhcpv4SrvTest, option43ClassPriority) { // Check if we get response at all checkResponse(offer, DHCPOFFER, 1234); - + // Processing should add a vendor-class-identifier (code 60) OptionPtr opt = offer->getOption(DHO_VENDOR_CLASS_IDENTIFIER); EXPECT_TRUE(opt); @@ -3194,7 +3194,7 @@ TEST_F(Dhcpv4SrvTest, option43Classes) { // Check if we get response at all checkResponse(offer, DHCPOFFER, 1234); - + // Processing should add a vendor-class-identifier (code 60) OptionPtr opt = offer->getOption(DHO_VENDOR_CLASS_IDENTIFIER); EXPECT_TRUE(opt); @@ -3305,7 +3305,7 @@ TEST_F(Dhcpv4SrvTest, privateOption) { // Check if we get response at all checkResponse(offer, DHCPOFFER, 1234); - + // Processing should add an option with code 234 OptionPtr opt = offer->getOption(234); EXPECT_TRUE(opt); @@ -4118,6 +4118,64 @@ TEST_F(Dhcpv4SrvTest, userContext) { EXPECT_EQ("{ \"value\": 42 }", pools[0]->getContext()->str()); } +// Verifies that an a client query with a truncated length in +// vendor option (125) will still be processed by the server. +TEST_F(Dhcpv4SrvTest, truncatedVIVSOOption) { + IfaceMgrTestConfig test_config(true); + IfaceMgr::instance().openSockets4(); + + NakedDhcpv4Srv srv(0); + + string config = "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet4\": [ { " + " \"pools\": [ { \"pool\": \"10.206.80.0/25\" } ]," + " \"subnet\": \"10.206.80.0/24\", " + " \"rebind-timer\": 2000, " + " \"renew-timer\": 1000, " + " \"valid-lifetime\": 4000," + " \"interface\": \"eth0\" " + " } ]," + "\"valid-lifetime\": 4000 }"; + + ConstElementPtr json; + ASSERT_NO_THROW(json = parseDHCP4(config)); + ConstElementPtr status; + + // Configure the server and make sure the config is accepted + EXPECT_NO_THROW(status = configureDhcp4Server(srv, json)); + ASSERT_TRUE(status); + comment_ = config::parseAnswer(rcode_, status); + ASSERT_EQ(0, rcode_); + + CfgMgr::instance().commit(); + + // Create a DISCOVER with a VIVSO option whose length is + // too short. + Pkt4Ptr dis; + ASSERT_NO_THROW(dis = PktCaptures::discoverWithTruncatedVIVSO()); + + // 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 an response and it was an offer + Pkt4Ptr offer = srv.fake_sent_.front(); + ASSERT_TRUE(offer); +} + + /// @todo: Implement proper tests for MySQL lease/host database, /// see ticket #4214. diff --git a/src/lib/dhcp/option.h b/src/lib/dhcp/option.h index 3d0868c808..6afe4205bd 100644 --- a/src/lib/dhcp/option.h +++ b/src/lib/dhcp/option.h @@ -1,4 +1,4 @@ -// Copyright (C) 2011-2016 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 @@ -42,6 +42,13 @@ typedef std::multimap OptionCollection; /// A pointer to an OptionCollection typedef boost::shared_ptr OptionCollectionPtr; +/// @brief Exception thrown during option unpacking +class SkipRemainingOptionsError : public Exception { +public: + SkipRemainingOptionsError (const char* file, size_t line, const char* what) : + isc::Exception(file, line, what) { }; +}; + class Option { public: /// length of the usual DHCPv4 option header (there are exceptions) diff --git a/src/lib/dhcp/option_definition.cc b/src/lib/dhcp/option_definition.cc index 8f07b97119..4f77621a33 100644 --- a/src/lib/dhcp/option_definition.cc +++ b/src/lib/dhcp/option_definition.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-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 @@ -221,6 +221,9 @@ OptionDefinition::optionFactory(Option::Universe u, uint16_t type, ; } return (OptionPtr(new OptionCustom(*this, u, begin, end))); + } catch (const SkipRemainingOptionsError& ex) { + // We need to throw this one as is. + throw ex; } catch (const Exception& ex) { isc_throw(InvalidOptionValue, ex.what()); } @@ -813,7 +816,7 @@ OptionPtr OptionDefinition::factoryFqdnList(Option::Universe u, OptionBufferConstIter begin, OptionBufferConstIter end) const { - + const std::vector data(begin, end); if (data.empty()) { isc_throw(InvalidOptionValue, "FQDN list option has invalid length of 0"); diff --git a/src/lib/dhcp/option_vendor.cc b/src/lib/dhcp/option_vendor.cc index aa137f7b4c..ff22379602 100644 --- a/src/lib/dhcp/option_vendor.cc +++ b/src/lib/dhcp/option_vendor.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2013-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 @@ -53,8 +53,12 @@ void OptionVendor::pack(isc::util::OutputBuffer& buf) const { void OptionVendor::unpack(OptionBufferConstIter begin, OptionBufferConstIter end) { + + // We throw SkipRemainingOptionsError so callers can + // abandon further unpacking, if desired. if (distance(begin, end) < sizeof(uint32_t)) { - isc_throw(OutOfRange, "Truncated vendor-specific information option" + isc_throw(SkipRemainingOptionsError, + "Truncated vendor-specific information option" << ", length=" << distance(begin, end)); } diff --git a/src/lib/dhcp/option_vendor.h b/src/lib/dhcp/option_vendor.h index f8a55a54a7..c566eae218 100644 --- a/src/lib/dhcp/option_vendor.h +++ b/src/lib/dhcp/option_vendor.h @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2013-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 @@ -67,7 +67,8 @@ public: /// @param begin iterator to first byte of option data /// @param end iterator to end of option data (first byte after option end) /// - /// @throw isc::OutOfRange if provided buffer is shorter than data size. + /// @throw isc::SkipRemainingOptionsBuffer if provided buffer is + /// shorter than data size. virtual void unpack(OptionBufferConstIter begin, OptionBufferConstIter end); /// @brief Sets enterprise identifier diff --git a/src/lib/dhcp/tests/pkt4_unittest.cc b/src/lib/dhcp/tests/pkt4_unittest.cc index d02c2cb28e..a20c8aa939 100644 --- a/src/lib/dhcp/tests/pkt4_unittest.cc +++ b/src/lib/dhcp/tests/pkt4_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 @@ -13,9 +13,12 @@ #include #include #include +#include #include #include #include +#include +#include #include #include @@ -1131,4 +1134,76 @@ TEST_F(Pkt4Test, getType) { EXPECT_TRUE(pkt.getName()); } +// Verifies that when the VIVSO option 125 has length that is too +// short (i.e. less than sizeof(uint8_t), unpack throws a +// SkipRemainingOptionsError exception +TEST_F(Pkt4Test, truncatedVendorLength) { + // Raw data for a valid DISCOVER packet. Its option 125 has a valid length + // of 133 (x85). Look for 303a7d: next two digits = 85 + const char* good_discover = + "010106012d5d43cb000080000000000000000000000000000ace50017896845ef7af0" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000063825363350" + "10137070102030407067d3c0a646f63736973332e303a7d850000118b80010102057b" + "01010102010303010104010105010106010107010f0801100901030a01010b01180c0" + "1010d0201000e0201000f010110040000000211010113010114010015013f16010117" + "01011801041901041a01041b01201c01021d01081e01201f011020011021010222010" + "1230100240100250101260200ff2701012801d82b7c020345434d030b45434d3a4552" + "4f5554455208030020400418333936373739343234343335353037373031303134303" + "035050131061e534247365838322d382e362e302e302d47412d30312d3937312d4e4f" + "5348070432343030090a534247363738322d41430a144d6f746f726f6c6120436f727" + "06f726174696f6e3d0fff845ef7af000300017896845ef7af390205dc521b01048005" + "03f802067896845ef7af090b0000118b06010401020300ff"; + + // Same DISCOVER as above but with the option 125 length changed to 01. + const char* bad_discover = + "010106012d5d43cb000080000000000000000000000000000ace50017896845ef7af0" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000063825363350" + "10137070102030407067d3c0a646f63736973332e303a7d010000118b80010102057b" + "01010102010303010104010105010106010107010f0801100901030a01010b01180c0" + "1010d0201000e0201000f010110040000000211010113010114010015013f16010117" + "01011801041901041a01041b01201c01021d01081e01201f011020011021010222010" + "1230100240100250101260200ff2701012801d82b7c020345434d030b45434d3a4552" + "4f5554455208030020400418333936373739343234343335353037373031303134303" + "035050131061e534247365838322d382e362e302e302d47412d30312d3937312d4e4f" + "5348070432343030090a534247363738322d41430a144d6f746f726f6c6120436f727" + "06f726174696f6e3d0fff845ef7af000300017896845ef7af390205dc521b01048005" + "03f802067896845ef7af090b0000118b06010401020300ff"; + + // Build a good discover packet + Pkt4Ptr pkt = test::PktCaptures::discoverWithValidVIVSO(); + + // Unpacking should not throw + ASSERT_NO_THROW(pkt->unpack()); + ASSERT_EQ(DHCPDISCOVER, pkt->getType()); + + // VIVSO option should be there + OptionPtr x = pkt->getOption(DHO_VIVSO_SUBOPTIONS); + ASSERT_TRUE(x); + ASSERT_EQ(DHO_VIVSO_SUBOPTIONS, x->getType()); + OptionVendorPtr vivso = boost::dynamic_pointer_cast(x); + ASSERT_TRUE(vivso); + EXPECT_EQ(133+2, vivso->len()); // data + opt code + len + + // Build a bad discover packet + pkt = test::PktCaptures::discoverWithTruncatedVIVSO(); + + // Unpack should throw Skip exception + ASSERT_THROW(pkt->unpack(), SkipRemainingOptionsError); + ASSERT_EQ(DHCPDISCOVER, pkt->getType()); + + // VIVSO option should not be there + x = pkt->getOption(DHO_VIVSO_SUBOPTIONS); + ASSERT_FALSE(x); +} + } // end of anonymous namespace diff --git a/src/lib/dhcp/tests/pkt_captures.h b/src/lib/dhcp/tests/pkt_captures.h index 5b499a2c6d..9b280cd383 100644 --- a/src/lib/dhcp/tests/pkt_captures.h +++ b/src/lib/dhcp/tests/pkt_captures.h @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-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 @@ -33,6 +33,20 @@ public: /// @return relayed DISCOVER static isc::dhcp::Pkt4Ptr captureRelayedDiscover2(); + /// @brief returns captured DISCOVER that contains a valid VIVSO option + /// + /// See method code for a detailed explanation. + /// + /// @return relayed DISCOVER + static isc::dhcp::Pkt4Ptr discoverWithValidVIVSO(); + + /// @brief returns captured DISCOVER that contains a truncated VIVSO option + /// + /// See method code for a detailed explanation. + /// + /// @return relayed DISCOVER + static isc::dhcp::Pkt4Ptr discoverWithTruncatedVIVSO(); + // see pkt_captures6.cc for descriptions // The descriptions are too large and too closely related to the // code, so it is kept in .cc rather than traditionally in .h diff --git a/src/lib/dhcp/tests/pkt_captures4.cc b/src/lib/dhcp/tests/pkt_captures4.cc index a7eaa13b3a..75596384b7 100644 --- a/src/lib/dhcp/tests/pkt_captures4.cc +++ b/src/lib/dhcp/tests/pkt_captures4.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2013-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 @@ -178,6 +178,110 @@ Bootstrap Protocol return (packetFromCapture(hex_string)); } +Pkt4Ptr PktCaptures::discoverWithValidVIVSO() { +/* DISCOVER that contains a valid VIVSO option 125 +User Datagram Protocol, Src Port: 67, Dst Port: 67 +Bootstrap Protocol (Discover) + Message type: Boot Request (1) + Hardware type: Ethernet (0x01) + Hardware address length: 6 + Hops: 1 + Transaction ID: 0x2d5d43cb + Seconds elapsed: 0 + Bootp flags: 0x8000, Broadcast flag (Broadcast) + Client IP address: 0.0.0.0 + Your (client) IP address: 0.0.0.0 + Next server IP address: 0.0.0.0 + Relay agent IP address: 10.206.80.1 + Client MAC address: ArrisGro_5e:f7:af (78:96:84:5e:f7:af) + Client hardware address padding: 00000000000000000000 + Server host name not given + Boot file name not given + Magic cookie: DHCP + Option: (53) DHCP Message Type (Discover) + Option: (55) Parameter Request List + Option: (60) Vendor class identifier + Option: (125) V-I Vendor-specific Information + Option: (43) Vendor-Specific Information (CableLabs) + Option: (61) Client identifier + Option: (57) Maximum DHCP Message Size + Option: (82) Agent Information Option + Option: (255) End +*/ + string hex_string = + "010106012d5d43cb000080000000000000000000000000000ace50017896845ef7af0" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000063825363350" + "10137070102030407067d3c0a646f63736973332e303a7d850000118b80010102057b" + "01010102010303010104010105010106010107010f0801100901030a01010b01180c0" + "1010d0201000e0201000f010110040000000211010113010114010015013f16010117" + "01011801041901041a01041b01201c01021d01081e01201f011020011021010222010" + "1230100240100250101260200ff2701012801d82b7c020345434d030b45434d3a4552" + "4f5554455208030020400418333936373739343234343335353037373031303134303" + "035050131061e534247365838322d382e362e302e302d47412d30312d3937312d4e4f" + "5348070432343030090a534247363738322d41430a144d6f746f726f6c6120436f727" + "06f726174696f6e3d0fff845ef7af000300017896845ef7af390205dc521b01048005" + "03f802067896845ef7af090b0000118b06010401020300ff"; + + return (packetFromCapture(hex_string)); +} + +Pkt4Ptr PktCaptures::discoverWithTruncatedVIVSO() { +/* DISCOVER that contains VIVSO option 125 with an INVALID length of 01 +User Datagram Protocol, Src Port: 67, Dst Port: 67 +Bootstrap Protocol (Discover) + Message type: Boot Request (1) + Hardware type: Ethernet (0x01) + Hardware address length: 6 + Hops: 1 + Transaction ID: 0x2d5d43cb + Seconds elapsed: 0 + Bootp flags: 0x8000, Broadcast flag (Broadcast) + Client IP address: 0.0.0.0 + Your (client) IP address: 0.0.0.0 + Next server IP address: 0.0.0.0 + Relay agent IP address: 10.206.80.1 + Client MAC address: ArrisGro_5e:f7:af (78:96:84:5e:f7:af) + Client hardware address padding: 00000000000000000000 + Server host name not given + Boot file name not given + Magic cookie: DHCP + Option: (53) DHCP Message Type (Discover) + Option: (55) Parameter Request List + Option: (60) Vendor class identifier + Option: (125) V-I Vendor-specific Information + Option: (43) Vendor-Specific Information (CableLabs) + Option: (61) Client identifier + Option: (57) Maximum DHCP Message Size + Option: (82) Agent Information Option + Option: (255) End +*/ + string hex_string = + "010106012d5d43cb000080000000000000000000000000000ace50017896845ef7af0" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000063825363350" + "10137070102030407067d3c0a646f63736973332e303a7d010000118b80010102057b" + "01010102010303010104010105010106010107010f0801100901030a01010b01180c0" + "1010d0201000e0201000f010110040000000211010113010114010015013f16010117" + "01011801041901041a01041b01201c01021d01081e01201f011020011021010222010" + "1230100240100250101260200ff2701012801d82b7c020345434d030b45434d3a4552" + "4f5554455208030020400418333936373739343234343335353037373031303134303" + "035050131061e534247365838322d382e362e302e302d47412d30312d3937312d4e4f" + "5348070432343030090a534247363738322d41430a144d6f746f726f6c6120436f727" + "06f726174696f6e3d0fff845ef7af000300017896845ef7af390205dc521b01048005" + "03f802067896845ef7af090b0000118b06010401020300ff"; + + return (packetFromCapture(hex_string)); +} + }; // end of isc::dhcp::test namespace }; // end of isc::dhcp namespace }; // end of isc namespace