123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254 |
- // Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #include <config.h>
- #include <dhcp/dhcp4.h>
- #include <dhcp/dhcp6.h>
- #include <dhcp/docsis3_option_defs.h>
- #include <dhcp/libdhcp++.h>
- #include <dhcp/option4_addrlst.h>
- #include <dhcp/option4_client_fqdn.h>
- #include <dhcp/option6_addrlst.h>
- #include <dhcp/option6_client_fqdn.h>
- #include <dhcp/option6_ia.h>
- #include <dhcp/option6_iaaddr.h>
- #include <dhcp/option6_iaprefix.h>
- #include <dhcp/option6_status_code.h>
- #include <dhcp/option_custom.h>
- #include <dhcp/option_int.h>
- #include <dhcp/option_int_array.h>
- #include <dhcp/option_string.h>
- #include <dhcp/option_vendor.h>
- #include <dhcp/option_vendor_class.h>
- #include <util/buffer.h>
- #include <util/encode/hex.h>
- #include <boost/pointer_cast.hpp>
- #include <gtest/gtest.h>
- #include <iostream>
- #include <sstream>
- #include <arpa/inet.h>
- using namespace std;
- using namespace isc;
- using namespace isc::dhcp;
- using namespace isc::util;
- namespace {
- // DHCPv6 suboptions of Vendor Options Option.
- /// @todo move to src/lib/dhcp/docsis3_option_defs.h once #3194 is merged.
- const uint16_t OPTION_CMTS_CAPS = 1025;
- const uint16_t OPTION_CM_MAC = 1026;
- class LibDhcpTest : public ::testing::Test {
- public:
- LibDhcpTest() { }
- /// @brief Generic factory function to create any option.
- ///
- /// Generic factory function to create any option.
- ///
- /// @param u universe (V4 or V6)
- /// @param type option-type
- /// @param buf option-buffer
- static OptionPtr genericOptionFactory(Option::Universe u, uint16_t type,
- const OptionBuffer& buf) {
- return (OptionPtr(new Option(u, type, buf)));
- }
- /// @brief Test DHCPv4 option definition.
- ///
- /// This function tests if option definition for standard
- /// option has been initialized correctly.
- ///
- /// @param code option code.
- /// @param begin iterator pointing at beginning of a buffer to
- /// be used to create option instance.
- /// @param end iterator pointing at end of a buffer to be
- /// used to create option instance.
- /// @param expected_type type of the option created by the
- /// factory function returned by the option definition.
- /// @param encapsulates name of the option space being encapsulated
- /// by the option.
- static void testStdOptionDefs4(const uint16_t code,
- const OptionBufferConstIter begin,
- const OptionBufferConstIter end,
- const std::type_info& expected_type,
- const std::string& encapsulates = "") {
- // Use V4 universe.
- testStdOptionDefs(Option::V4, code, begin, end, expected_type,
- encapsulates);
- }
- /// @brief Test DHCPv6 option definition.
- ///
- /// This function tests if option definition for standard
- /// option has been initialized correctly.
- ///
- /// @param code option code.
- /// @param begin iterator pointing at beginning of a buffer to
- /// be used to create option instance.
- /// @param end iterator pointing at end of a buffer to be
- /// used to create option instance.
- /// @param expected_type type of the option created by the
- /// factory function returned by the option definition.
- /// @param encapsulates name of the option space being encapsulated
- /// by the option.
- static void testStdOptionDefs6(const uint16_t code,
- const OptionBufferConstIter begin,
- const OptionBufferConstIter end,
- const std::type_info& expected_type,
- const std::string& encapsulates = "") {
- // Use V6 universe.
- testStdOptionDefs(Option::V6, code, begin, end, expected_type,
- encapsulates);
- }
- /// @brief Create a sample DHCPv4 option 43 with suboptions.
- static OptionBuffer createVendorOption() {
- const uint8_t opt_data[] = {
- 0x2B, 0x0D, // Vendor-Specific Information (CableLabs)
- // Suboptions start here...
- 0x02, 0x05, // Device Type Option (length = 5)
- 'D', 'u', 'm', 'm', 'y',
- 0x04, 0x04, // Serial Number Option (length = 4)
- 0x42, 0x52, 0x32, 0x32 // Serial number
- };
- return (OptionBuffer(opt_data, opt_data + sizeof(opt_data)));
- }
- /// @brief Create a sample DHCPv4 option 82 with suboptions.
- static OptionBuffer createAgentInformationOption() {
- const uint8_t opt_data[] = {
- 0x52, 0x0E, // Agent Information Option (length = 14)
- // Suboptions start here...
- 0x01, 0x04, // Agent Circuit ID (length = 4)
- 0x20, 0x00, 0x00, 0x02, // ID
- 0x02, 0x06, // Agent Remote ID
- 0x20, 0xE5, 0x2A, 0xB8, 0x15, 0x14 // ID
- };
- return (OptionBuffer(opt_data, opt_data + sizeof(opt_data)));
- }
- private:
- /// @brief Test DHCPv4 or DHCPv6 option definition.
- ///
- /// This function tests if option definition for standard
- /// option has been initialized correctly.
- ///
- /// @param code option code.
- /// @param begin iterator pointing at beginning of a buffer to
- /// be used to create option instance.
- /// @param end iterator pointing at end of a buffer to be
- /// used to create option instance.
- /// @param expected_type type of the option created by the
- /// factory function returned by the option definition.
- /// @param encapsulates name of the option space being encapsulated
- /// by the option.
- static void testStdOptionDefs(const Option::Universe u,
- const uint16_t code,
- const OptionBufferConstIter begin,
- const OptionBufferConstIter end,
- const std::type_info& expected_type,
- const std::string& encapsulates) {
- // Get all option definitions, we will use them to extract
- // the definition for a particular option code.
- // We don't have to initialize option definitions here because they
- // are initialized in the class's constructor.
- OptionDefContainer options = LibDHCP::getOptionDefs(u);
- // Get the container index #1. This one allows for searching
- // option definitions using option code.
- const OptionDefContainerTypeIndex& idx = options.get<1>();
- // Get 'all' option definitions for a particular option code.
- // For standard options we expect that the range returned
- // will contain single option as their codes are unique.
- OptionDefContainerTypeRange range = idx.equal_range(code);
- ASSERT_EQ(1, std::distance(range.first, range.second))
- << "Standard option definition for the code " << code
- << " has not been found.";
- // If we have single option definition returned, the
- // first iterator holds it.
- OptionDefinitionPtr def = *(range.first);
- // It should not happen that option definition is NULL but
- // let's make sure (test should take things like that into
- // account).
- ASSERT_TRUE(def) << "Option definition for the code "
- << code << " is NULL.";
- // Check that option definition is valid.
- ASSERT_NO_THROW(def->validate())
- << "Option definition for the option code " << code
- << " is invalid";
- // Check that the valid encapsulated option space name
- // has been specified.
- EXPECT_EQ(encapsulates, def->getEncapsulatedSpace());
- OptionPtr option;
- // Create the option.
- ASSERT_NO_THROW(option = def->optionFactory(u, code, begin, end))
- << "Option creation failed for option code " << code;
- // Make sure it is not NULL.
- ASSERT_TRUE(option);
- // And the actual object type is the one that we expect.
- // Note that for many options there are dedicated classes
- // derived from Option class to represent them.
- EXPECT_TRUE(typeid(*option) == expected_type)
- << "Invalid class returned for option code " << code;
- }
- };
- // The DHCPv6 options in the wire format, used by multiple tests.
- const uint8_t v6packed[] = {
- 0, 1, 0, 5, 100, 101, 102, 103, 104, // CLIENT_ID (9 bytes)
- 0, 2, 0, 3, 105, 106, 107, // SERVER_ID (7 bytes)
- 0, 14, 0, 0, // RAPID_COMMIT (0 bytes)
- 0, 6, 0, 4, 108, 109, 110, 111, // ORO (8 bytes)
- 0, 8, 0, 2, 112, 113, // ELAPSED_TIME (6 bytes)
- // Vendor Specific Information Option starts here
- 0x00, 0x11, // VSI Option Code
- 0x00, 0x16, // VSI Option Length
- 0x00, 0x00, 0x11, 0x8B, // Enterprise ID
- 0x04, 0x01, // CMTS Capabilities Option
- 0x00, 0x04, // Length
- 0x01, 0x02,
- 0x03, 0x00, // DOCSIS Version Number
- 0x04, 0x02, // CM MAC Address Suboption
- 0x00, 0x06, // Length
- 0x74, 0x56, 0x12, 0x29, 0x97, 0xD0, // Actual MAC Address
- };
- TEST_F(LibDhcpTest, optionFactory) {
- OptionBuffer buf;
- // Factory functions for specific options must be registered before
- // they can be used to create options instances. Otherwise exception
- // is rised.
- EXPECT_THROW(LibDHCP::optionFactory(Option::V4, DHO_SUBNET_MASK, buf),
- isc::BadValue);
- // Let's register some factory functions (two v4 and one v6 function).
- // Registration may trigger exception if function for the specified
- // option has been registered already.
- ASSERT_NO_THROW(
- LibDHCP::OptionFactoryRegister(Option::V4, DHO_SUBNET_MASK,
- &LibDhcpTest::genericOptionFactory);
- );
- ASSERT_NO_THROW(
- LibDHCP::OptionFactoryRegister(Option::V4, DHO_TIME_OFFSET,
- &LibDhcpTest::genericOptionFactory);
- );
- ASSERT_NO_THROW(
- LibDHCP::OptionFactoryRegister(Option::V6, D6O_CLIENTID,
- &LibDhcpTest::genericOptionFactory);
- );
- // Invoke factory functions for all options (check if registration
- // was successful).
- OptionPtr opt_subnet_mask;
- opt_subnet_mask = LibDHCP::optionFactory(Option::V4,
- DHO_SUBNET_MASK,
- buf);
- // Check if non-NULL DHO_SUBNET_MASK option pointer has been returned.
- ASSERT_TRUE(opt_subnet_mask);
- // Validate if type and universe is correct.
- EXPECT_EQ(Option::V4, opt_subnet_mask->getUniverse());
- EXPECT_EQ(DHO_SUBNET_MASK, opt_subnet_mask->getType());
- // Expect that option does not have content..
- EXPECT_EQ(0, opt_subnet_mask->len() - opt_subnet_mask->getHeaderLen());
- // Fill the time offset buffer with 4 bytes of data. Each byte set to 1.
- OptionBuffer time_offset_buf(4, 1);
- OptionPtr opt_time_offset;
- opt_time_offset = LibDHCP::optionFactory(Option::V4,
- DHO_TIME_OFFSET,
- time_offset_buf);
- // Check if non-NULL DHO_TIME_OFFSET option pointer has been returned.
- ASSERT_TRUE(opt_time_offset);
- // Validate if option length, type and universe is correct.
- EXPECT_EQ(Option::V4, opt_time_offset->getUniverse());
- EXPECT_EQ(DHO_TIME_OFFSET, opt_time_offset->getType());
- EXPECT_EQ(time_offset_buf.size(),
- opt_time_offset->len() - opt_time_offset->getHeaderLen());
- // Validate data in the option.
- EXPECT_TRUE(std::equal(time_offset_buf.begin(), time_offset_buf.end(),
- opt_time_offset->getData().begin()));
- // Fill the client id buffer with 20 bytes of data. Each byte set to 2.
- OptionBuffer clientid_buf(20, 2);
- OptionPtr opt_clientid;
- opt_clientid = LibDHCP::optionFactory(Option::V6,
- D6O_CLIENTID,
- clientid_buf);
- // Check if non-NULL D6O_CLIENTID option pointer has been returned.
- ASSERT_TRUE(opt_clientid);
- // Validate if option length, type and universe is correct.
- EXPECT_EQ(Option::V6, opt_clientid->getUniverse());
- EXPECT_EQ(D6O_CLIENTID, opt_clientid->getType());
- EXPECT_EQ(clientid_buf.size(), opt_clientid->len() - opt_clientid->getHeaderLen());
- // Validate data in the option.
- EXPECT_TRUE(std::equal(clientid_buf.begin(), clientid_buf.end(),
- opt_clientid->getData().begin()));
- }
- TEST_F(LibDhcpTest, packOptions6) {
- OptionBuffer buf(512);
- isc::dhcp::OptionCollection opts; // list of options
- // generate content for options
- for (int i = 0; i < 64; i++) {
- buf[i]=i+100;
- }
- OptionPtr opt1(new Option(Option::V6, 1, buf.begin() + 0, buf.begin() + 5));
- OptionPtr opt2(new Option(Option::V6, 2, buf.begin() + 5, buf.begin() + 8));
- OptionPtr opt3(new Option(Option::V6, 14, buf.begin() + 8, buf.begin() + 8));
- OptionPtr opt4(new Option(Option::V6, 6, buf.begin() + 8, buf.begin() + 12));
- OptionPtr opt5(new Option(Option::V6, 8, buf.begin() + 12, buf.begin() + 14));
- OptionPtr cm_mac(new Option(Option::V6, OPTION_CM_MAC,
- OptionBuffer(v6packed + 54, v6packed + 60)));
- OptionPtr cmts_caps(new Option(Option::V6, OPTION_CMTS_CAPS,
- OptionBuffer(v6packed + 46, v6packed + 50)));
- boost::shared_ptr<OptionInt<uint32_t> >
- vsi(new OptionInt<uint32_t>(Option::V6, D6O_VENDOR_OPTS, 4491));
- vsi->addOption(cm_mac);
- vsi->addOption(cmts_caps);
- opts.insert(make_pair(opt1->getType(), opt1));
- opts.insert(make_pair(opt1->getType(), opt2));
- opts.insert(make_pair(opt1->getType(), opt3));
- opts.insert(make_pair(opt1->getType(), opt4));
- opts.insert(make_pair(opt1->getType(), opt5));
- opts.insert(make_pair(opt1->getType(), vsi));
- OutputBuffer assembled(512);
- EXPECT_NO_THROW(LibDHCP::packOptions(assembled, opts));
- EXPECT_EQ(sizeof(v6packed), assembled.getLength());
- EXPECT_EQ(0, memcmp(assembled.getData(), v6packed, sizeof(v6packed)));
- }
- TEST_F(LibDhcpTest, unpackOptions6) {
- // just couple of random options
- // Option is used as a simple option implementation
- // More advanced uses are validated in tests dedicated for
- // specific derived classes.
- isc::dhcp::OptionCollection options; // list of options
- OptionBuffer buf(512);
- memcpy(&buf[0], v6packed, sizeof(v6packed));
- EXPECT_NO_THROW ({
- LibDHCP::unpackOptions6(OptionBuffer(buf.begin(), buf.begin() + sizeof(v6packed)),
- "dhcp6", options);
- });
- EXPECT_EQ(options.size(), 6); // there should be 5 options
- isc::dhcp::OptionCollection::const_iterator x = options.find(1);
- ASSERT_FALSE(x == options.end()); // option 1 should exist
- EXPECT_EQ(1, x->second->getType()); // this should be option 1
- ASSERT_EQ(9, x->second->len()); // it should be of length 9
- ASSERT_EQ(5, x->second->getData().size());
- EXPECT_EQ(0, memcmp(&x->second->getData()[0], v6packed + 4, 5)); // data len=5
- x = options.find(2);
- ASSERT_FALSE(x == options.end()); // option 2 should exist
- EXPECT_EQ(2, x->second->getType()); // this should be option 2
- ASSERT_EQ(7, x->second->len()); // it should be of length 7
- ASSERT_EQ(3, x->second->getData().size());
- EXPECT_EQ(0, memcmp(&x->second->getData()[0], v6packed + 13, 3)); // data len=3
- x = options.find(14);
- ASSERT_FALSE(x == options.end()); // option 14 should exist
- EXPECT_EQ(14, x->second->getType()); // this should be option 14
- ASSERT_EQ(4, x->second->len()); // it should be of length 4
- EXPECT_EQ(0, x->second->getData().size()); // data len = 0
- x = options.find(6);
- ASSERT_FALSE(x == options.end()); // option 6 should exist
- EXPECT_EQ(6, x->second->getType()); // this should be option 6
- ASSERT_EQ(8, x->second->len()); // it should be of length 8
- // Option with code 6 is the OPTION_ORO. This option is
- // represented by the OptionIntArray<uint16_t> class which
- // comprises the set of uint16_t values. We need to cast the
- // returned pointer to this type to get values stored in it.
- boost::shared_ptr<OptionIntArray<uint16_t> > opt_oro =
- boost::dynamic_pointer_cast<OptionIntArray<uint16_t> >(x->second);
- // This value will be NULL if cast was unsuccessful. This is the case
- // when returned option has different type than expected.
- ASSERT_TRUE(opt_oro);
- // Get set of uint16_t values.
- std::vector<uint16_t> opts = opt_oro->getValues();
- // Prepare the refrence data.
- std::vector<uint16_t> expected_opts;
- expected_opts.push_back(0x6C6D); // equivalent to: 108, 109
- expected_opts.push_back(0x6E6F); // equivalent to 110, 111
- ASSERT_EQ(expected_opts.size(), opts.size());
- // Validated if option has been unpacked correctly.
- EXPECT_TRUE(std::equal(expected_opts.begin(), expected_opts.end(),
- opts.begin()));
- x = options.find(8);
- ASSERT_FALSE(x == options.end()); // option 8 should exist
- EXPECT_EQ(8, x->second->getType()); // this should be option 8
- ASSERT_EQ(6, x->second->len()); // it should be of length 9
- // Option with code 8 is OPTION_ELAPSED_TIME. This option is
- // represented by Option6Int<uint16_t> value that holds single
- // uint16_t value.
- boost::shared_ptr<OptionInt<uint16_t> > opt_elapsed_time =
- boost::dynamic_pointer_cast<OptionInt<uint16_t> >(x->second);
- // This value will be NULL if cast was unsuccessful. This is the case
- // when returned option has different type than expected.
- ASSERT_TRUE(opt_elapsed_time);
- // Returned value should be equivalent to two byte values: 112, 113
- EXPECT_EQ(0x7071, opt_elapsed_time->getValue());
- // Check if Vendor Specific Information Option along with suboptions
- // have been parsed correctly.
- x = options.find(D6O_VENDOR_OPTS);
- EXPECT_FALSE(x == options.end());
- EXPECT_EQ(D6O_VENDOR_OPTS, x->second->getType());
- EXPECT_EQ(26, x->second->len());
- // CM MAC Address Option
- OptionPtr cm_mac = x->second->getOption(OPTION_CM_MAC);
- ASSERT_TRUE(cm_mac);
- EXPECT_EQ(OPTION_CM_MAC, cm_mac->getType());
- ASSERT_EQ(10, cm_mac->len());
- EXPECT_EQ(0, memcmp(&cm_mac->getData()[0], v6packed + 54, 6));
- // CMTS Capabilities
- OptionPtr cmts_caps = x->second->getOption(OPTION_CMTS_CAPS);
- ASSERT_TRUE(cmts_caps);
- EXPECT_EQ(OPTION_CMTS_CAPS, cmts_caps->getType());
- ASSERT_EQ(8, cmts_caps->len());
- EXPECT_EQ(0, memcmp(&cmts_caps->getData()[0], v6packed + 46, 4));
- x = options.find(0);
- EXPECT_TRUE(x == options.end()); // option 0 not found
- x = options.find(256); // 256 is htons(1) on little endians. Worth checking
- EXPECT_TRUE(x == options.end()); // option 1 not found
- x = options.find(7);
- EXPECT_TRUE(x == options.end()); // option 2 not found
- x = options.find(32000);
- EXPECT_TRUE(x == options.end()); // option 32000 not found */
- }
- /// V4 Options being used to test pack/unpack operations.
- /// These are variable length options only so as there
- /// is no restriction on the data length being carried by them.
- /// For simplicity, we assign data of the length 3 for each
- /// of them.
- static uint8_t v4_opts[] = {
- 12, 3, 0, 1, 2, // Hostname
- 60, 3, 10, 11, 12, // Class Id
- 14, 3, 20, 21, 22, // Merit Dump File
- 254, 3, 30, 31, 32, // Reserved
- 128, 3, 40, 41, 42, // Vendor specific
- 0x52, 0x19, // RAI
- 0x01, 0x04, 0x20, 0x00, 0x00, 0x02, // Agent Circuit ID
- 0x02, 0x06, 0x20, 0xE5, 0x2A, 0xB8, 0x15, 0x14, // Agent Remote ID
- 0x09, 0x09, 0x00, 0x00, 0x11, 0x8B, 0x04, // Vendor Specific Information
- 0x01, 0x02, 0x03, 0x00 // Vendor Specific Information continued
- };
- TEST_F(LibDhcpTest, packOptions4) {
- vector<uint8_t> payload[5];
- for (int i = 0; i < 5; i++) {
- payload[i].resize(3);
- payload[i][0] = i*10;
- payload[i][1] = i*10+1;
- payload[i][2] = i*10+2;
- }
- OptionPtr opt1(new Option(Option::V4, 12, payload[0]));
- OptionPtr opt2(new Option(Option::V4, 60, payload[1]));
- OptionPtr opt3(new Option(Option::V4, 14, payload[2]));
- OptionPtr opt4(new Option(Option::V4,254, payload[3]));
- OptionPtr opt5(new Option(Option::V4,128, payload[4]));
- // Add RAI option, which comprises 3 sub-options.
- // Get the option definition for RAI option. This option is represented
- // by OptionCustom which requires a definition to be passed to
- // the constructor.
- OptionDefinitionPtr rai_def = LibDHCP::getOptionDef(Option::V4,
- DHO_DHCP_AGENT_OPTIONS);
- ASSERT_TRUE(rai_def);
- // Create RAI option.
- OptionCustomPtr rai(new OptionCustom(*rai_def, Option::V4));
- // The sub-options are created using the bits of v4_opts buffer because
- // we want to use this buffer as a reference to verify that produced
- // option in on-wire format is correct.
- // Create Ciruit ID sub-option and add to RAI.
- OptionPtr circuit_id(new Option(Option::V4, RAI_OPTION_AGENT_CIRCUIT_ID,
- OptionBuffer(v4_opts + 29,
- v4_opts + 33)));
- rai->addOption(circuit_id);
- // Create Remote ID option and add to RAI.
- OptionPtr remote_id(new Option(Option::V4, RAI_OPTION_REMOTE_ID,
- OptionBuffer(v4_opts + 35, v4_opts + 41)));
- rai->addOption(remote_id);
- // Create Vendor Specific Information and add to RAI.
- OptionPtr vsi(new Option(Option::V4, RAI_OPTION_VSI,
- OptionBuffer(v4_opts + 43, v4_opts + 52)));
- rai->addOption(vsi);
- isc::dhcp::OptionCollection opts; // list of options
- // Note that we insert each option under the same option code into
- // the map. This gurantees that options are packed in the same order
- // they were added. Otherwise, options would get sorted by code and
- // the resulting buffer wouldn't match with the reference buffer.
- opts.insert(make_pair(opt1->getType(), opt1));
- opts.insert(make_pair(opt1->getType(), opt2));
- opts.insert(make_pair(opt1->getType(), opt3));
- opts.insert(make_pair(opt1->getType(), opt4));
- opts.insert(make_pair(opt1->getType(), opt5));
- opts.insert(make_pair(opt1->getType(), rai));
- OutputBuffer buf(100);
- EXPECT_NO_THROW(LibDHCP::packOptions(buf, opts));
- ASSERT_EQ(buf.getLength(), sizeof(v4_opts));
- EXPECT_EQ(0, memcmp(v4_opts, buf.getData(), sizeof(v4_opts)));
- }
- TEST_F(LibDhcpTest, unpackOptions4) {
- vector<uint8_t> v4packed(v4_opts, v4_opts + sizeof(v4_opts));
- isc::dhcp::OptionCollection options; // list of options
- ASSERT_NO_THROW(
- LibDHCP::unpackOptions4(v4packed, "dhcp4", options);
- );
- isc::dhcp::OptionCollection::const_iterator x = options.find(12);
- ASSERT_FALSE(x == options.end()); // option 1 should exist
- // Option 12 holds a string so let's cast it to an appropriate type.
- OptionStringPtr option12 = boost::static_pointer_cast<OptionString>(x->second);
- ASSERT_TRUE(option12);
- EXPECT_EQ(12, option12->getType()); // this should be option 12
- ASSERT_EQ(3, option12->getValue().length()); // it should be of length 3
- EXPECT_EQ(5, option12->len()); // total option length 5
- EXPECT_EQ(0, memcmp(&option12->getValue()[0], v4_opts + 2, 3)); // data len=3
- x = options.find(60);
- ASSERT_FALSE(x == options.end()); // option 2 should exist
- EXPECT_EQ(60, x->second->getType()); // this should be option 60
- ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
- EXPECT_EQ(5, x->second->len()); // total option length 5
- EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4_opts + 7, 3)); // data len=3
- x = options.find(14);
- ASSERT_FALSE(x == options.end()); // option 3 should exist
- OptionStringPtr option14 = boost::static_pointer_cast<OptionString>(x->second);
- ASSERT_TRUE(option14);
- EXPECT_EQ(14, option14->getType()); // this should be option 14
- ASSERT_EQ(3, option14->getValue().length()); // it should be of length 3
- EXPECT_EQ(5, option14->len()); // total option length 5
- EXPECT_EQ(0, memcmp(&option14->getValue()[0], v4_opts + 12, 3)); // data len=3
- x = options.find(254);
- ASSERT_FALSE(x == options.end()); // option 3 should exist
- EXPECT_EQ(254, x->second->getType()); // this should be option 254
- ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
- EXPECT_EQ(5, x->second->len()); // total option length 5
- EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4_opts + 17, 3)); // data len=3
- x = options.find(128);
- ASSERT_FALSE(x == options.end()); // option 3 should exist
- EXPECT_EQ(128, x->second->getType()); // this should be option 254
- ASSERT_EQ(3, x->second->getData().size()); // it should be of length 3
- EXPECT_EQ(5, x->second->len()); // total option length 5
- EXPECT_EQ(0, memcmp(&x->second->getData()[0], v4_opts + 22, 3)); // data len=3
- // Checking DHCP Relay Agent Information Option.
- x = options.find(DHO_DHCP_AGENT_OPTIONS);
- ASSERT_FALSE(x == options.end());
- EXPECT_EQ(DHO_DHCP_AGENT_OPTIONS, x->second->getType());
- // RAI is represented by OptionCustom.
- OptionCustomPtr rai = boost::dynamic_pointer_cast<OptionCustom>(x->second);
- ASSERT_TRUE(rai);
- // RAI should have 3 sub-options: Circuit ID, Agent Remote ID, Vendor
- // Specific Information option. Note that by parsing these suboptions we
- // are checking that unpackOptions4 differentiates between standard option
- // space called "dhcp4" and other option spaces. These sub-options do not
- // belong to standard option space and should be parsed using different
- // option definitions.
- // @todo Currently, definitions for option space "dhcp-agent-options-space"
- // are not defined. Therefore all suboptions will be represented here by
- // the generic Option class.
- // Check that Circuit ID option is among parsed options.
- OptionPtr rai_option = rai->getOption(RAI_OPTION_AGENT_CIRCUIT_ID);
- ASSERT_TRUE(rai_option);
- EXPECT_EQ(RAI_OPTION_AGENT_CIRCUIT_ID, rai_option->getType());
- ASSERT_EQ(6, rai_option->len());
- EXPECT_EQ(0, memcmp(&rai_option->getData()[0], v4_opts + 29, 4));
- // Check that Remote ID option is among parsed options.
- rai_option = rai->getOption(RAI_OPTION_REMOTE_ID);
- ASSERT_TRUE(rai_option);
- EXPECT_EQ(RAI_OPTION_REMOTE_ID, rai_option->getType());
- ASSERT_EQ(8, rai_option->len());
- EXPECT_EQ(0, memcmp(&rai_option->getData()[0], v4_opts + 35, 6));
- // Check that Vendor Specific Information option is among parsed options.
- rai_option = rai->getOption(RAI_OPTION_VSI);
- ASSERT_TRUE(rai_option);
- EXPECT_EQ(RAI_OPTION_VSI, rai_option->getType());
- ASSERT_EQ(11, rai_option->len());
- EXPECT_EQ(0, memcmp(&rai_option->getData()[0], v4_opts + 43, 9));
- // Make sure, that option other than those above is not present.
- EXPECT_FALSE(rai->getOption(10));
- // Check the same for the global option space.
- x = options.find(0);
- EXPECT_TRUE(x == options.end()); // option 0 not found
- x = options.find(1);
- EXPECT_TRUE(x == options.end()); // option 1 not found
- x = options.find(2);
- EXPECT_TRUE(x == options.end()); // option 2 not found
- }
- TEST_F(LibDhcpTest, isStandardOption4) {
- // Get all option codes that are not occupied by standard options.
- const uint16_t unassigned_codes[] = { 84, 96, 102, 103, 104, 105, 106, 107, 108,
- 109, 110, 111, 115, 126, 127, 147, 148, 149,
- 178, 179, 180, 181, 182, 183, 184, 185, 186,
- 187, 188, 189, 190, 191, 192, 193, 194, 195,
- 196, 197, 198, 199, 200, 201, 202, 203, 204,
- 205, 206, 207, 214, 215, 216, 217, 218, 219,
- 222, 223, 224, 225, 226, 227, 228, 229, 230,
- 231, 232, 233, 234, 235, 236, 237, 238, 239,
- 240, 241, 242, 243, 244, 245, 246, 247, 248,
- 249, 250, 251, 252, 253, 254 };
- const size_t unassigned_num = sizeof(unassigned_codes) / sizeof(unassigned_codes[0]);
- // Try all possible option codes.
- for (size_t i = 0; i < 256; ++i) {
- // Some ranges of option codes are unassigned and thus the isStandardOption
- // should return false for them.
- bool check_unassigned = false;
- // Check the array of unassigned options to find out whether option code
- // is assigned to standard option or unassigned.
- for (size_t j = 0; j < unassigned_num; ++j) {
- // If option code is found within the array of unassigned options
- // we the isStandardOption function should return false.
- if (unassigned_codes[j] == i) {
- check_unassigned = true;
- EXPECT_FALSE(LibDHCP::isStandardOption(Option::V4,
- unassigned_codes[j]))
- << "Test failed for option code " << unassigned_codes[j];
- break;
- }
- }
- // If the option code belongs to the standard option then the
- // isStandardOption should return true.
- if (!check_unassigned) {
- EXPECT_TRUE(LibDHCP::isStandardOption(Option::V4, i))
- << "Test failed for the option code " << i;
- }
- }
- }
- TEST_F(LibDhcpTest, isStandardOption6) {
- // All option codes in the range from 0 to 78 (except 10 and 35)
- // identify the standard options.
- for (uint16_t code = 0; code < 79; ++code) {
- if (code != 10 && code != 35) {
- EXPECT_TRUE(LibDHCP::isStandardOption(Option::V6, code))
- << "Test failed for option code " << code;
- }
- }
- // Check the option codes 10 and 35. They are unassigned.
- EXPECT_FALSE(LibDHCP::isStandardOption(Option::V6, 10));
- EXPECT_FALSE(LibDHCP::isStandardOption(Option::V6, 35));
- // Check a range of option codes above 78. Those are option codes
- // identifying non-standard options.
- for (uint16_t code = 79; code < 512; ++code) {
- EXPECT_FALSE(LibDHCP::isStandardOption(Option::V6, code))
- << "Test failed for option code " << code;
- }
- }
- TEST_F(LibDhcpTest, stdOptionDefs4) {
- // Create a buffer that holds dummy option data.
- // It will be used to create most of the options.
- std::vector<uint8_t> buf(48, 1);
- OptionBufferConstIter begin = buf.begin();
- OptionBufferConstIter end = buf.end();
- LibDhcpTest::testStdOptionDefs4(DHO_SUBNET_MASK, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_TIME_OFFSET, begin, begin + 4,
- typeid(OptionInt<int32_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_ROUTERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_TIME_SERVERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_NAME_SERVERS, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_DOMAIN_NAME_SERVERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_LOG_SERVERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_COOKIE_SERVERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_LPR_SERVERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_IMPRESS_SERVERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_RESOURCE_LOCATION_SERVERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_HOST_NAME, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_BOOT_SIZE, begin, begin + 2,
- typeid(OptionInt<uint16_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_MERIT_DUMP, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_DOMAIN_NAME, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_SWAP_SERVER, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_ROOT_PATH, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_EXTENSIONS_PATH, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_IP_FORWARDING, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_NON_LOCAL_SOURCE_ROUTING, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_POLICY_FILTER, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_MAX_DGRAM_REASSEMBLY, begin, begin + 2,
- typeid(OptionInt<uint16_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_DEFAULT_IP_TTL, begin, begin + 1,
- typeid(OptionInt<uint8_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_PATH_MTU_AGING_TIMEOUT, begin, begin + 4,
- typeid(OptionInt<uint32_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_PATH_MTU_PLATEAU_TABLE, begin, begin + 10,
- typeid(OptionIntArray<uint16_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_INTERFACE_MTU, begin, begin + 2,
- typeid(OptionInt<uint16_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_ALL_SUBNETS_LOCAL, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_BROADCAST_ADDRESS, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_PERFORM_MASK_DISCOVERY, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_MASK_SUPPLIER, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_ROUTER_DISCOVERY, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_ROUTER_SOLICITATION_ADDRESS, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_STATIC_ROUTES, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_TRAILER_ENCAPSULATION, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_ARP_CACHE_TIMEOUT, begin, begin + 4,
- typeid(OptionInt<uint32_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_IEEE802_3_ENCAPSULATION, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_DEFAULT_TCP_TTL, begin, begin + 1,
- typeid(OptionInt<uint8_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_TCP_KEEPALIVE_INTERVAL, begin,
- begin + 4, typeid(OptionInt<uint32_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_TCP_KEEPALIVE_GARBAGE, begin, begin + 1,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_NIS_DOMAIN, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_NIS_SERVERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_NTP_SERVERS, begin, end,
- typeid(Option4AddrLst));
- // The following option requires well formed buffer to be created from.
- // Not just a dummy one. This buffer includes some suboptions.
- OptionBuffer vendor_opts_buf = createVendorOption();
- LibDhcpTest::testStdOptionDefs4(DHO_VENDOR_ENCAPSULATED_OPTIONS,
- vendor_opts_buf.begin(),
- vendor_opts_buf.end(),
- typeid(OptionCustom),
- "vendor-encapsulated-options-space");
- LibDhcpTest::testStdOptionDefs4(DHO_NETBIOS_NAME_SERVERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_NETBIOS_DD_SERVER, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_NETBIOS_NODE_TYPE, begin, begin + 1,
- typeid(OptionInt<uint8_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_NETBIOS_SCOPE, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_FONT_SERVERS, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_X_DISPLAY_MANAGER, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_REQUESTED_ADDRESS, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_LEASE_TIME, begin, begin + 4,
- typeid(OptionInt<uint32_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_OPTION_OVERLOAD, begin, begin + 1,
- typeid(OptionInt<uint8_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_MESSAGE_TYPE, begin, begin + 1,
- typeid(OptionInt<uint8_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_SERVER_IDENTIFIER, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_PARAMETER_REQUEST_LIST, begin, end,
- typeid(OptionUint8Array));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_MESSAGE, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_MAX_MESSAGE_SIZE, begin, begin + 2,
- typeid(OptionInt<uint16_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_RENEWAL_TIME, begin, begin + 4,
- typeid(OptionInt<uint32_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_REBINDING_TIME, begin, begin + 4,
- typeid(OptionInt<uint32_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_VENDOR_CLASS_IDENTIFIER, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_CLIENT_IDENTIFIER, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs4(DHO_NWIP_DOMAIN_NAME, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_NWIP_SUBOPTIONS, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs4(DHO_TFTP_SERVER_NAME, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_BOOT_FILE_NAME, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs4(DHO_USER_CLASS, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs4(DHO_FQDN, begin, begin + 3,
- typeid(Option4ClientFqdn));
- // The following option requires well formed buffer to be created from.
- // Not just a dummy one. This buffer includes some suboptions.
- OptionBuffer agent_info_buf = createAgentInformationOption();
- LibDhcpTest::testStdOptionDefs4(DHO_DHCP_AGENT_OPTIONS,
- agent_info_buf.begin(),
- agent_info_buf.end(),
- typeid(OptionCustom),
- "dhcp-agent-options-space");
- LibDhcpTest::testStdOptionDefs4(DHO_AUTHENTICATE, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs4(DHO_CLIENT_LAST_TRANSACTION_TIME,
- begin, begin + 4,
- typeid(OptionInt<uint32_t>));
- LibDhcpTest::testStdOptionDefs4(DHO_ASSOCIATED_IP, begin, end,
- typeid(Option4AddrLst));
- LibDhcpTest::testStdOptionDefs4(DHO_SUBNET_SELECTION, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs4(DHO_DOMAIN_SEARCH, begin, end,
- typeid(Option));
- // V-I Vendor option requires specially crafted data.
- const char vivco_data[] = {
- 1, 2, 3, 4, // enterprise id
- 3, 1, 2, 3 // first byte is opaque data length, the rest is opaque data
- };
- std::vector<uint8_t> vivco_buf(vivco_data, vivco_data + sizeof(vivco_data));
- LibDhcpTest::testStdOptionDefs4(DHO_VIVCO_SUBOPTIONS, vivco_buf.begin(),
- vivco_buf.end(), typeid(OptionVendorClass));
- LibDhcpTest::testStdOptionDefs4(DHO_VIVSO_SUBOPTIONS, begin, end,
- typeid(OptionVendor));
- }
- // Test that definitions of standard options have been initialized
- // correctly.
- // @todo Only limited number of option definitions are now created
- // This test have to be extended once all option definitions are
- // created.
- TEST_F(LibDhcpTest, stdOptionDefs6) {
- // Create a buffer that holds dummy option data.
- // It will be used to create most of the options.
- std::vector<uint8_t> buf(48, 1);
- OptionBufferConstIter begin = buf.begin();
- OptionBufferConstIter end = buf.end();
- // Prepare buffer holding an array of FQDNs.
- const char data[] = {
- 8, 109, 121, 100, 111, 109, 97, 105, 110, // "mydomain"
- 7, 101, 120, 97, 109, 112, 108, 101, // "example"
- 3, 99, 111, 109, // "com"
- 0,
- 7, 101, 120, 97, 109, 112, 108, 101, // "example"
- 3, 99, 111, 109, // "com"
- 0
- };
- // Initialize a vector with the FQDN data.
- std::vector<uint8_t> fqdn_buf(data, data + sizeof(data));
- // The CLIENT_FQDN holds a uint8_t value and FQDN. We have
- // to add the uint8_t value to it and then append the buffer
- // holding some valid FQDN.
- std::vector<uint8_t> client_fqdn_buf(1);
- client_fqdn_buf.insert(client_fqdn_buf.end(), fqdn_buf.begin(),
- fqdn_buf.end());
- // Initialize test buffer for Vendor Class option.
- const char vclass_data[] = {
- 0x00, 0x01, 0x02, 0x03,
- 0x00, 0x01, 0x02
- };
- std::vector<uint8_t> vclass_buf(vclass_data,
- vclass_data + sizeof(vclass_data));;
- // The actual test starts here for all supported option codes.
- LibDhcpTest::testStdOptionDefs6(D6O_CLIENTID, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs6(D6O_SERVERID, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs6(D6O_IA_NA, begin, end,
- typeid(Option6IA));
- LibDhcpTest::testStdOptionDefs6(D6O_IA_TA, begin, begin + 4,
- typeid(OptionInt<uint32_t>));
- LibDhcpTest::testStdOptionDefs6(D6O_IAADDR, begin, end,
- typeid(Option6IAAddr));
- LibDhcpTest::testStdOptionDefs6(D6O_ORO, begin, end,
- typeid(OptionIntArray<uint16_t>));
- LibDhcpTest::testStdOptionDefs6(D6O_PREFERENCE, begin, begin + 1,
- typeid(OptionInt<uint8_t>));
- LibDhcpTest::testStdOptionDefs6(D6O_ELAPSED_TIME, begin, begin + 2,
- typeid(OptionInt<uint16_t>));
- LibDhcpTest::testStdOptionDefs6(D6O_RELAY_MSG, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs6(D6O_STATUS_CODE, begin, end,
- typeid(Option6StatusCode));
- LibDhcpTest::testStdOptionDefs6(D6O_RAPID_COMMIT, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs6(D6O_USER_CLASS, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs6(D6O_VENDOR_CLASS, vclass_buf.begin(),
- vclass_buf.end(),
- typeid(OptionVendorClass));
- LibDhcpTest::testStdOptionDefs6(D6O_VENDOR_OPTS, begin, end,
- typeid(OptionVendor),
- "vendor-opts-space");
- LibDhcpTest::testStdOptionDefs6(D6O_INTERFACE_ID, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs6(D6O_RECONF_MSG, begin, begin + 1,
- typeid(OptionInt<uint8_t>));
- LibDhcpTest::testStdOptionDefs6(D6O_RECONF_ACCEPT, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs6(D6O_SIP_SERVERS_DNS, fqdn_buf.begin(),
- fqdn_buf.end(),
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs6(D6O_SIP_SERVERS_ADDR, begin, end,
- typeid(Option6AddrLst));
- LibDhcpTest::testStdOptionDefs6(D6O_NAME_SERVERS, begin, end,
- typeid(Option6AddrLst));
- LibDhcpTest::testStdOptionDefs6(D6O_DOMAIN_SEARCH, fqdn_buf.begin(),
- fqdn_buf.end(), typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs6(D6O_IA_PD, begin, end,
- typeid(Option6IA));
- LibDhcpTest::testStdOptionDefs6(D6O_IAPREFIX, begin, begin + 25,
- typeid(Option6IAPrefix));
- LibDhcpTest::testStdOptionDefs6(D6O_NIS_SERVERS, begin, end,
- typeid(Option6AddrLst));
- LibDhcpTest::testStdOptionDefs6(D6O_NISP_SERVERS, begin, end,
- typeid(Option6AddrLst));
- LibDhcpTest::testStdOptionDefs6(D6O_NIS_DOMAIN_NAME, fqdn_buf.begin(),
- fqdn_buf.end(),
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs6(D6O_NISP_DOMAIN_NAME, fqdn_buf.begin(),
- fqdn_buf.end(),
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs6(D6O_SNTP_SERVERS, begin, end,
- typeid(Option6AddrLst));
- LibDhcpTest::testStdOptionDefs6(D6O_INFORMATION_REFRESH_TIME,
- begin, begin + 4,
- typeid(OptionInt<uint32_t>));
- LibDhcpTest::testStdOptionDefs6(D6O_BCMCS_SERVER_D, fqdn_buf.begin(),
- fqdn_buf.end(),
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs6(D6O_BCMCS_SERVER_A, begin, end,
- typeid(Option6AddrLst));
- LibDhcpTest::testStdOptionDefs6(D6O_GEOCONF_CIVIC, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs6(D6O_REMOTE_ID, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs6(D6O_SUBSCRIBER_ID, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs6(D6O_CLIENT_FQDN, client_fqdn_buf.begin(),
- client_fqdn_buf.end(),
- typeid(Option6ClientFqdn));
- LibDhcpTest::testStdOptionDefs6(D6O_PANA_AGENT, begin, end,
- typeid(Option6AddrLst));
- LibDhcpTest::testStdOptionDefs6(D6O_PANA_AGENT, begin, end,
- typeid(Option6AddrLst));
- LibDhcpTest::testStdOptionDefs6(D6O_NEW_POSIX_TIMEZONE, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs6(D6O_NEW_TZDB_TIMEZONE, begin, end,
- typeid(OptionString));
- LibDhcpTest::testStdOptionDefs6(D6O_ERO, begin, end,
- typeid(OptionIntArray<uint16_t>));
- LibDhcpTest::testStdOptionDefs6(D6O_LQ_QUERY, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs6(D6O_CLIENT_DATA, begin, end,
- typeid(Option));
- LibDhcpTest::testStdOptionDefs6(D6O_CLT_TIME, begin, begin + 4,
- typeid(OptionInt<uint32_t>));
- LibDhcpTest::testStdOptionDefs6(D6O_LQ_RELAY_DATA, begin, end,
- typeid(OptionCustom));
- LibDhcpTest::testStdOptionDefs6(D6O_LQ_CLIENT_LINK, begin, end,
- typeid(Option6AddrLst));
- LibDhcpTest::testStdOptionDefs6(D6O_RSOO, begin, end,
- typeid(OptionCustom),
- "rsoo-opts");
- LibDhcpTest::testStdOptionDefs6(D6O_ERP_LOCAL_DOMAIN_NAME,
- fqdn_buf.begin(), fqdn_buf.end(),
- typeid(OptionCustom));
- }
- // This test checks if the DHCPv6 option definition can be searched by
- // an option name.
- TEST_F(LibDhcpTest, getOptionDefByName6) {
- // Get all definitions.
- const OptionDefContainer& defs = LibDHCP::getOptionDefs(Option::V6);
- // For each definition try to find it using option name.
- for (OptionDefContainer::const_iterator def = defs.begin();
- def != defs.end(); ++def) {
- OptionDefinitionPtr def_by_name =
- LibDHCP::getOptionDef(Option::V6, (*def)->getName());
- ASSERT_TRUE(def_by_name);
- ASSERT_TRUE(**def == *def_by_name);
- }
- }
- // This test checks if the DHCPv4 option definition can be searched by
- // an option name.
- TEST_F(LibDhcpTest, getOptionDefByName4) {
- // Get all definitions.
- const OptionDefContainer& defs = LibDHCP::getOptionDefs(Option::V4);
- // For each definition try to find it using option name.
- for (OptionDefContainer::const_iterator def = defs.begin();
- def != defs.end(); ++def) {
- OptionDefinitionPtr def_by_name =
- LibDHCP::getOptionDef(Option::V4, (*def)->getName());
- ASSERT_TRUE(def_by_name);
- ASSERT_TRUE(**def == *def_by_name);
- }
- }
- // This test checks if the definition of the DHCPv6 vendor option can
- // be searched by option name.
- TEST_F(LibDhcpTest, getVendorOptionDefByName6) {
- const OptionDefContainer* defs =
- LibDHCP::getVendorOption6Defs(VENDOR_ID_CABLE_LABS);
- ASSERT_TRUE(defs != NULL);
- for (OptionDefContainer::const_iterator def = defs->begin();
- def != defs->end(); ++def) {
- OptionDefinitionPtr def_by_name =
- LibDHCP::getVendorOptionDef(Option::V6, VENDOR_ID_CABLE_LABS,
- (*def)->getName());
- ASSERT_TRUE(def_by_name);
- ASSERT_TRUE(**def == *def_by_name);
- }
- }
- // This test checks if the definition of the DHCPv4 vendor option can
- // be searched by option name.
- TEST_F(LibDhcpTest, getVendorOptionDefByName4) {
- const OptionDefContainer* defs =
- LibDHCP::getVendorOption4Defs(VENDOR_ID_CABLE_LABS);
- ASSERT_TRUE(defs != NULL);
- for (OptionDefContainer::const_iterator def = defs->begin();
- def != defs->end(); ++def) {
- OptionDefinitionPtr def_by_name =
- LibDHCP::getVendorOptionDef(Option::V4, VENDOR_ID_CABLE_LABS,
- (*def)->getName());
- ASSERT_TRUE(def_by_name);
- ASSERT_TRUE(**def == *def_by_name);
- }
- }
- // tests whether v6 vendor-class option can be parsed properly.
- TEST_F(LibDhcpTest, vendorClass6) {
- isc::dhcp::OptionCollection options; // Will store parsed option here
- // Exported from wireshark: vendor-class option with enterprise-id = 4491
- // and a single data entry containing "eRouter1.0"
- string vendor_class_hex = "001000100000118b000a65526f75746572312e30";
- OptionBuffer bin;
- // Decode the hex string and store it in bin (which happens
- // to be OptionBuffer format)
- isc::util::encode::decodeHex(vendor_class_hex, bin);
- ASSERT_NO_THROW ({
- LibDHCP::unpackOptions6(bin, "dhcp6", options);
- });
- EXPECT_EQ(options.size(), 1); // There should be 1 option.
- // Option vendor-class should be there
- ASSERT_FALSE(options.find(D6O_VENDOR_CLASS) == options.end());
- // It should be of type OptionVendorClass
- boost::shared_ptr<OptionVendorClass> vclass =
- boost::dynamic_pointer_cast<OptionVendorClass>(options.begin()->second);
- ASSERT_TRUE(vclass);
- // Let's investigate if the option content is correct
- // 3 fields expected: vendor-id, data-len and data
- EXPECT_EQ(4491, vclass->getVendorId());
- EXPECT_EQ(20, vclass->len());
- ASSERT_EQ(1, vclass->getTuplesNum());
- EXPECT_EQ("eRouter1.0", vclass->getTuple(0).getText());
- }
- } // end of anonymous space
|