12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160 |
- // Copyright (C) 2015-2016 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
- // file, You can obtain one at http://mozilla.org/MPL/2.0/.
- #include <dhcp/dhcp6.h>
- #include <dhcp/libdhcp++.h>
- #include <dhcp/option4_addrlst.h>
- #include <dhcp/option6_addrlst.h>
- #include <dhcp/option_space.h>
- #include <dhcp/option_string.h>
- #include <dhcp/option_int.h>
- #include <dhcp/option_vendor.h>
- #include <dhcpsrv/tests/generic_host_data_source_unittest.h>
- #include <dhcpsrv/tests/test_utils.h>
- #include <dhcpsrv/database_connection.h>
- #include <asiolink/io_address.h>
- #include <util/buffer.h>
- #include <boost/foreach.hpp>
- #include <gtest/gtest.h>
- #include <cstring>
- #include <list>
- #include <string>
- #include <sstream>
- #include <typeinfo>
- using namespace std;
- using namespace isc::asiolink;
- using namespace isc::util;
- namespace isc {
- namespace dhcp {
- namespace test {
- GenericHostDataSourceTest::GenericHostDataSourceTest()
- :hdsptr_() {
- LibDHCP::clearRuntimeOptionDefs();
- }
- GenericHostDataSourceTest::~GenericHostDataSourceTest() {
- LibDHCP::clearRuntimeOptionDefs();
- }
- std::vector<uint8_t>
- GenericHostDataSourceTest::generateHWAddr(const bool new_identifier) {
- /// @todo: Consider moving this somewhere to lib/testutils.
- // Let's use something that is easily printable. That's convenient
- // if you need to enter MySQL queries by hand.
- static uint8_t hwaddr[] = {65, 66, 67, 68, 69, 70};
- if (new_identifier) {
- // Increase the address for the next time we use it.
- // This is primitive, but will work for 65k unique
- // addresses.
- hwaddr[sizeof(hwaddr) - 1]++;
- if (hwaddr[sizeof(hwaddr) - 1] == 0) {
- hwaddr[sizeof(hwaddr) - 2]++;
- }
- }
- return (std::vector<uint8_t>(hwaddr, hwaddr + sizeof(hwaddr)));
- }
- std::vector<uint8_t>
- GenericHostDataSourceTest::generateIdentifier(const bool new_identifier) {
- /// @todo: Consider moving this somewhere to lib/testutils.
- // Let's use something that is easily printable. That's convenient
- // if you need to enter MySQL queries by hand.
- static uint8_t ident[] = { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74 };
- // Increase the identifier for the next time we use it.
- // This is primitive, but will work for 65k unique
- // identifiers.
- if (new_identifier) {
- ident[sizeof(ident) - 1]++;
- if (ident[sizeof(ident) - 1] == 0) {
- ident[sizeof(ident) - 2]++;
- }
- }
- return (std::vector<uint8_t>(ident, ident + sizeof(ident)));
- }
- HostPtr
- GenericHostDataSourceTest::initializeHost4(const std::string& address,
- const Host::IdentifierType& id) {
- std::vector<uint8_t> ident;
- if (id == Host::IDENT_HWADDR) {
- ident = generateHWAddr();
- } else {
- ident = generateIdentifier();
- }
- // Let's create ever increasing subnet-ids. Let's keep those different,
- // so subnet4 != subnet6. Useful for catching cases if the code confuses
- // subnet4 with subnet6.
- static SubnetID subnet4 = 0;
- static SubnetID subnet6 = 100;
- ++subnet4;
- ++subnet6;
- IOAddress addr(address);
- HostPtr host(new Host(&ident[0], ident.size(), id, subnet4, subnet6, addr));
- return (host);
- }
- HostPtr GenericHostDataSourceTest::initializeHost6(std::string address,
- Host::IdentifierType identifier,
- bool prefix,
- bool new_identifier) {
- std::vector<uint8_t> ident;
- switch (identifier) {
- case Host::IDENT_HWADDR:
- ident = generateHWAddr(new_identifier);
- break;
- case Host::IDENT_DUID:
- ident = generateIdentifier(new_identifier);
- break;
- default:
- ADD_FAILURE() << "Unknown IdType: " << identifier;
- return HostPtr();
- }
- // Let's create ever increasing subnet-ids. Let's keep those different,
- // so subnet4 != subnet6. Useful for catching cases if the code confuses
- // subnet4 with subnet6.
- static SubnetID subnet4 = 0;
- static SubnetID subnet6 = 100;
- subnet4++;
- subnet6++;
- HostPtr host(new Host(&ident[0], ident.size(), identifier, subnet4,
- subnet6, IOAddress("0.0.0.0")));
- if (!prefix) {
- // Create IPv6 reservation (for an address)
- IPv6Resrv resv(IPv6Resrv::TYPE_NA, IOAddress(address), 128);
- host->addReservation(resv);
- } else {
- // Create IPv6 reservation for a /64 prefix
- IPv6Resrv resv(IPv6Resrv::TYPE_PD, IOAddress(address), 64);
- host->addReservation(resv);
- }
- return (host);
- }
- void
- GenericHostDataSourceTest::compareHwaddrs(const ConstHostPtr& host1,
- const ConstHostPtr& host2,
- bool expect_match) {
- ASSERT_TRUE(host1);
- ASSERT_TRUE(host2);
- // Compare if both have or have not HWaddress set.
- if ((host1->getHWAddress() && !host2->getHWAddress()) ||
- (!host1->getHWAddress() && host2->getHWAddress())) {
- // One host has hardware address set while the other has not.
- // Let's see if it's a problem.
- if (expect_match) {
- ADD_FAILURE() << "Host comparison failed: host1 hwaddress="
- << host1->getHWAddress() << ", host2 hwaddress="
- << host2->getHWAddress();
- }
- return;
- }
- // Now we know that either both or neither have hw address set.
- // If host1 has it, we can proceed to value comparison.
- if (host1->getHWAddress()) {
- if (expect_match) {
- // Compare the actual address if they match.
- EXPECT_TRUE(*host1->getHWAddress() == *host2->getHWAddress());
- } else {
- EXPECT_FALSE(*host1->getHWAddress() == *host2->getHWAddress());
- }
- if (*host1->getHWAddress() != *host2->getHWAddress()) {
- cout << host1->getHWAddress()->toText(true) << endl;
- cout << host2->getHWAddress()->toText(true) << endl;
- }
- }
- }
- void
- GenericHostDataSourceTest::compareDuids(const ConstHostPtr& host1,
- const ConstHostPtr& host2,
- bool expect_match) {
- ASSERT_TRUE(host1);
- ASSERT_TRUE(host2);
- // compare if both have or have not DUID set
- if ((host1->getDuid() && !host2->getDuid()) ||
- (!host1->getDuid() && host2->getDuid())) {
- // One host has a DUID and the other doesn't.
- // Let's see if it's a problem.
- if (expect_match) {
- ADD_FAILURE() << "DUID comparison failed: host1 duid="
- << host1->getDuid() << ", host2 duid="
- << host2->getDuid();
- }
- return;
- }
- // Now we know that either both or neither have DUID set.
- // If host1 has it, we can proceed to value comparison.
- if (host1->getDuid()) {
- if (expect_match) {
- EXPECT_TRUE(*host1->getDuid() == *host2->getDuid());
- } else {
- EXPECT_FALSE(*host1->getDuid() == *host2->getDuid());
- }
- if (*host1->getDuid() != *host2->getDuid()) {
- cout << host1->getDuid()->toText() << endl;
- cout << host2->getDuid()->toText() << endl;
- }
- }
- }
- void GenericHostDataSourceTest::compareHosts(const ConstHostPtr& host1,
- const ConstHostPtr& host2) {
- // Let's compare HW addresses and expect match.
- compareHwaddrs(host1, host2, true);
- // Now compare DUIDs
- compareDuids(host1, host2, true);
- // Now check that the identifiers returned as vectors are the same
- EXPECT_EQ(host1->getIdentifierType(), host2->getIdentifierType());
- EXPECT_TRUE(host1->getIdentifier() == host2->getIdentifier());
- // Check host parameters
- EXPECT_EQ(host1->getIPv4SubnetID(), host2->getIPv4SubnetID());
- EXPECT_EQ(host1->getIPv6SubnetID(), host2->getIPv6SubnetID());
- EXPECT_EQ(host1->getIPv4Reservation(), host2->getIPv4Reservation());
- EXPECT_EQ(host1->getHostname(), host2->getHostname());
- // Compare IPv6 reservations
- compareReservations6(host1->getIPv6Reservations(),
- host2->getIPv6Reservations());
- // Compare client classification details
- compareClientClasses(host1->getClientClasses4(),
- host2->getClientClasses4());
- compareClientClasses(host1->getClientClasses6(),
- host2->getClientClasses6());
- // Compare DHCPv4 and DHCPv6 options.
- compareOptions(host1->getCfgOption4(), host2->getCfgOption4());
- compareOptions(host1->getCfgOption6(), host2->getCfgOption6());
- }
- DuidPtr
- GenericHostDataSourceTest::HWAddrToDuid(const HWAddrPtr& hwaddr) {
- if (!hwaddr) {
- return (DuidPtr());
- }
- return (DuidPtr(new DUID(hwaddr->hwaddr_)));
- }
- HWAddrPtr
- GenericHostDataSourceTest::DuidToHWAddr(const DuidPtr& duid) {
- if (!duid) {
- return (HWAddrPtr());
- }
- return (HWAddrPtr(new HWAddr(duid->getDuid(), HTYPE_ETHER)));
- }
- void
- GenericHostDataSourceTest::compareReservations6(IPv6ResrvRange resrv1,
- IPv6ResrvRange resrv2) {
- // Compare number of reservations for both hosts
- if (std::distance(resrv1.first, resrv1.second) !=
- std::distance(resrv2.first, resrv2.second)){
- ADD_FAILURE()<< "Reservation comparison failed, "
- "hosts got different number of reservations.";
- return;
- }
- // Iterate over the range of reservations to find a match in the
- // reference range.
- for (IPv6ResrvIterator r1 = resrv1.first; r1 != resrv1.second; ++r1) {
- IPv6ResrvIterator r2 = resrv2.first;
- for (; r2 != resrv2.second; ++r2) {
- // IPv6Resrv object implements equality operator.
- if (r1->second == r2->second) {
- break;
- }
- }
- // If r2 iterator reached the end of the range it means that there
- // is no match.
- if (r2 == resrv2.second) {
- ADD_FAILURE() << "No match found for reservation: "
- << resrv1.first->second.getPrefix().toText();
- }
- }
- if (std::distance(resrv1.first, resrv1.second) > 0) {
- for (; resrv1.first != resrv1.second; resrv1.first++) {
- IPv6ResrvIterator iter = resrv2.first;
- while (iter != resrv2.second) {
- if((resrv1.first->second.getType() == iter->second.getType()) &&
- (resrv1.first->second.getPrefixLen() == iter->second.getPrefixLen()) &&
- (resrv1.first->second.getPrefix() == iter->second.getPrefix())) {
- break;
- }
- iter++;
- if (iter == resrv2.second) {
- ADD_FAILURE()<< "Reservation comparison failed, "
- "no match for reservation: "
- << resrv1.first->second.getPrefix().toText();
- }
- }
- }
- }
- }
- void
- GenericHostDataSourceTest::compareClientClasses(const ClientClasses& /*classes1*/,
- const ClientClasses& /*classes2*/) {
- /// @todo: Implement client classes comparison.
- /// This is part of the work for #4213.
- }
- void
- GenericHostDataSourceTest::compareOptions(const ConstCfgOptionPtr& cfg1,
- const ConstCfgOptionPtr& cfg2) const {
- ASSERT_TRUE(cfg1);
- ASSERT_TRUE(cfg2);
- // Combine option space names with vendor space names in a single list.
- std::list<std::string> option_spaces = cfg2->getOptionSpaceNames();
- std::list<std::string> vendor_spaces = cfg2->getVendorIdsSpaceNames();
- option_spaces.insert(option_spaces.end(), vendor_spaces.begin(),
- vendor_spaces.end());
- // Make sure that the number of option spaces is equal in both
- // configurations.
- EXPECT_EQ(option_spaces.size(), cfg1->getOptionSpaceNames().size());
- EXPECT_EQ(vendor_spaces.size(), cfg1->getVendorIdsSpaceNames().size());
- // Iterate over all option spaces existing in cfg2.
- BOOST_FOREACH(std::string space, option_spaces) {
- // Retrieve options belonging to the current option space.
- OptionContainerPtr options1 = cfg1->getAll(space);
- OptionContainerPtr options2 = cfg2->getAll(space);
- ASSERT_TRUE(options1) << "failed for option space " << space;
- ASSERT_TRUE(options2) << "failed for option space " << space;
- // If number of options doesn't match, the test fails.
- ASSERT_EQ(options1->size(), options2->size())
- << "failed for option space " << space;
- // Iterate over all options within this option space.
- BOOST_FOREACH(OptionDescriptor desc1, *options1) {
- OptionDescriptor desc2 = cfg2->get(space, desc1.option_->getType());
- // Compare persistent flag.
- EXPECT_EQ(desc1.persistent_, desc2.persistent_)
- << "failed for option " << space << "." << desc1.option_->getType();
- // Compare formatted value.
- EXPECT_EQ(desc1.formatted_value_, desc2.formatted_value_)
- << "failed for option " << space << "." << desc1.option_->getType();
- // Retrieve options.
- Option* option1 = desc1.option_.get();
- Option* option2 = desc2.option_.get();
- // Options must be represented by the same C++ class derived from
- // the Option class.
- EXPECT_TRUE(typeid(*option1) == typeid(*option2))
- << "Comapared DHCP options, having option code "
- << desc1.option_->getType() << " and belonging to the "
- << space << " option space, are represented "
- "by different C++ classes: "
- << typeid(*option1).name() << " vs "
- << typeid(*option2).name();
- // Because we use different C++ classes to represent different
- // options, the simplest way to make sure that the options are
- // equal is to simply compare them in wire format.
- OutputBuffer buf1(option1->len());
- ASSERT_NO_THROW(option1->pack(buf1));
- OutputBuffer buf2(option2->len());
- ASSERT_NO_THROW(option2->pack(buf2));
- ASSERT_EQ(buf1.getLength(), buf2.getLength())
- << "failed for option " << space << "." << desc1.option_->getType();
- EXPECT_EQ(0, memcmp(buf1.getData(), buf2.getData(), buf1.getLength()))
- << "failed for option " << space << "." << desc1.option_->getType();
- }
- }
- }
- OptionDescriptor
- GenericHostDataSourceTest::createEmptyOption(const Option::Universe& universe,
- const uint16_t option_type,
- const bool persist) const {
- OptionPtr option(new Option(universe, option_type));
- OptionDescriptor desc(option, persist);
- return (desc);
- }
- OptionDescriptor
- GenericHostDataSourceTest::createVendorOption(const Option::Universe& universe,
- const bool persist,
- const bool formatted,
- const uint32_t vendor_id) const {
- OptionVendorPtr option(new OptionVendor(universe, vendor_id));
- std::ostringstream s;
- if (formatted) {
- // Vendor id comprises vendor-id field, for which we need to
- // assign a value in the textual (formatted) format.
- s << vendor_id;
- }
- OptionDescriptor desc(option, persist, s.str());
- return (desc);
- }
- void
- GenericHostDataSourceTest::addTestOptions(const HostPtr& host,
- const bool formatted,
- const AddedOptions& added_options) const {
- OptionDefSpaceContainer defs;
- if ((added_options == DHCP4_ONLY) || (added_options == DHCP4_AND_DHCP6)) {
- // Add DHCPv4 options.
- CfgOptionPtr opts = host->getCfgOption4();
- opts->add(createOption<OptionString>(Option::V4, DHO_BOOT_FILE_NAME,
- true, formatted, "my-boot-file"),
- DHCP4_OPTION_SPACE);
- opts->add(createOption<OptionUint8>(Option::V4, DHO_DEFAULT_IP_TTL,
- false, formatted, 64),
- DHCP4_OPTION_SPACE);
- opts->add(createOption<OptionUint32>(Option::V4, 1, false, formatted, 312131),
- "vendor-encapsulated-options");
- opts->add(createAddressOption<Option4AddrLst>(254, false, formatted, "192.0.2.3"),
- DHCP4_OPTION_SPACE);
- opts->add(createEmptyOption(Option::V4, 1, true), "isc");
- opts->add(createAddressOption<Option4AddrLst>(2, false, formatted, "10.0.0.5",
- "10.0.0.3", "10.0.3.4"),
- "isc");
- // Add definitions for DHCPv4 non-standard options.
- defs.addItem(OptionDefinitionPtr(new OptionDefinition("vendor-encapsulated-1",
- 1, "uint32")),
- "vendor-encapsulated-options");
- defs.addItem(OptionDefinitionPtr(new OptionDefinition("option-254", 254,
- "ipv4-address", true)),
- DHCP4_OPTION_SPACE);
- defs.addItem(OptionDefinitionPtr(new OptionDefinition("isc-1", 1, "empty")),
- "isc");
- defs.addItem(OptionDefinitionPtr(new OptionDefinition("isc-2", 2,
- "ipv4-address", true)),
- "isc");
- }
- if ((added_options == DHCP6_ONLY) || (added_options == DHCP4_AND_DHCP6)) {
- // Add DHCPv6 options.
- CfgOptionPtr opts = host->getCfgOption6();
- opts->add(createOption<OptionString>(Option::V6, D6O_BOOTFILE_URL,
- true, formatted, "my-boot-file"),
- DHCP6_OPTION_SPACE);
- opts->add(createOption<OptionUint32>(Option::V6, D6O_INFORMATION_REFRESH_TIME,
- false, formatted, 3600),
- DHCP6_OPTION_SPACE);
- opts->add(createVendorOption(Option::V6, false, formatted, 2495),
- DHCP6_OPTION_SPACE);
- opts->add(createAddressOption<Option6AddrLst>(1024, false, formatted,
- "2001:db8:1::1"),
- DHCP6_OPTION_SPACE);
- opts->add(createEmptyOption(Option::V6, 1, true), "isc2");
- opts->add(createAddressOption<Option6AddrLst>(2, false, formatted, "3000::1",
- "3000::2", "3000::3"),
- "isc2");
- // Add definitions for DHCPv6 non-standard options.
- defs.addItem(OptionDefinitionPtr(new OptionDefinition("option-1024", 1024,
- "ipv6-address", true)),
- DHCP6_OPTION_SPACE);
- defs.addItem(OptionDefinitionPtr(new OptionDefinition("option-1", 1, "empty")),
- "isc2");
- defs.addItem(OptionDefinitionPtr(new OptionDefinition("option-2", 2,
- "ipv6-address", true)),
- "isc2");
- }
- // Register created "runtime" option definitions. They will be used by a
- // host data source to convert option data into the appropriate option
- // classes when the options are retrieved.
- LibDHCP::setRuntimeOptionDefs(defs);
- }
- void GenericHostDataSourceTest::testBasic4(const Host::IdentifierType& id) {
- // Make sure we have the pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Create a host reservation.
- HostPtr host = initializeHost4("192.0.2.1", id);
- ASSERT_TRUE(host); // Make sure the host is generate properly.
- SubnetID subnet = host->getIPv4SubnetID();
- // Try to add it to the host data source.
- ASSERT_NO_THROW(hdsptr_->add(host));
- // This should not return anything
- ConstHostPtr from_hds = hdsptr_->get4(subnet, IOAddress("10.10.10.10"));
- ASSERT_FALSE(from_hds);
- // This time it should return a host
- from_hds = hdsptr_->get4(subnet, IOAddress("192.0.2.1"));
- ASSERT_TRUE(from_hds);
- // Finally, let's check if what we got makes any sense.
- compareHosts(host, from_hds);
- }
- void GenericHostDataSourceTest::testGetByIPv4(const Host::IdentifierType& id) {
- // Make sure we have a pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Let's create a couple of hosts...
- HostPtr host1 = initializeHost4("192.0.2.1", id);
- HostPtr host2 = initializeHost4("192.0.2.2", id);
- HostPtr host3 = initializeHost4("192.0.2.3", id);
- HostPtr host4 = initializeHost4("192.0.2.4", id);
- // ... and add them to the data source.
- ASSERT_NO_THROW(hdsptr_->add(host1));
- ASSERT_NO_THROW(hdsptr_->add(host2));
- ASSERT_NO_THROW(hdsptr_->add(host3));
- ASSERT_NO_THROW(hdsptr_->add(host4));
- SubnetID subnet1 = host1->getIPv4SubnetID();
- SubnetID subnet2 = host2->getIPv4SubnetID();
- SubnetID subnet3 = host3->getIPv4SubnetID();
- SubnetID subnet4 = host4->getIPv4SubnetID();
- // And then try to retrieve them back.
- ConstHostPtr from_hds1 = hdsptr_->get4(subnet1, IOAddress("192.0.2.1"));
- ConstHostPtr from_hds2 = hdsptr_->get4(subnet2, IOAddress("192.0.2.2"));
- ConstHostPtr from_hds3 = hdsptr_->get4(subnet3, IOAddress("192.0.2.3"));
- ConstHostPtr from_hds4 = hdsptr_->get4(subnet4, IOAddress("192.0.2.4"));
- // Make sure we got something back.
- ASSERT_TRUE(from_hds1);
- ASSERT_TRUE(from_hds2);
- ASSERT_TRUE(from_hds3);
- ASSERT_TRUE(from_hds4);
- // Then let's check that what we got seems correct.
- compareHosts(host1, from_hds1);
- compareHosts(host2, from_hds2);
- compareHosts(host3, from_hds3);
- compareHosts(host4, from_hds4);
- // Ok, finally let's check that getting by a different address
- // will not work.
- EXPECT_FALSE(hdsptr_->get4(subnet1, IOAddress("192.0.1.5")));
- }
- void
- GenericHostDataSourceTest::testGet4ByIdentifier(const Host::IdentifierType& identifier_type) {
- // Make sure we have a pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- HostPtr host1 = initializeHost4("192.0.2.1", identifier_type);
- HostPtr host2 = initializeHost4("192.0.2.2", identifier_type);
- // Sanity check: make sure the hosts have different identifiers..
- ASSERT_FALSE(host1->getIdentifier() == host2->getIdentifier());
- // Try to add both of them to the host data source.
- ASSERT_NO_THROW(hdsptr_->add(host1));
- ASSERT_NO_THROW(hdsptr_->add(host2));
- SubnetID subnet1 = host1->getIPv4SubnetID();
- SubnetID subnet2 = host2->getIPv4SubnetID();
- ConstHostPtr from_hds1 = hdsptr_->get4(subnet1,
- identifier_type,
- &host1->getIdentifier()[0],
- host1->getIdentifier().size());
- ConstHostPtr from_hds2 = hdsptr_->get4(subnet2,
- identifier_type,
- &host2->getIdentifier()[0],
- host2->getIdentifier().size());
- // Now let's check if we got what we expected.
- ASSERT_TRUE(from_hds1);
- ASSERT_TRUE(from_hds2);
- compareHosts(host1, from_hds1);
- compareHosts(host2, from_hds2);
- }
- void GenericHostDataSourceTest::testHWAddrNotClientId() {
- // Make sure we have a pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Create a host with HW address
- HostPtr host = initializeHost4("192.0.2.1", Host::IDENT_HWADDR);
- ASSERT_TRUE(host->getHWAddress());
- ASSERT_FALSE(host->getDuid());
- // Try to add it to the host data source.
- ASSERT_NO_THROW(hdsptr_->add(host));
- SubnetID subnet = host->getIPv4SubnetID();
- DuidPtr duid = HWAddrToDuid(host->getHWAddress());
- // Get the host by HW address (should succeed)
- ConstHostPtr by_hwaddr = hdsptr_->get4(subnet, Host::IDENT_HWADDR,
- &host->getIdentifier()[0],
- host->getIdentifier().size());
- // Get the host by DUID (should fail)
- ConstHostPtr by_duid = hdsptr_->get4(subnet, Host::IDENT_DUID,
- &host->getIdentifier()[0],
- host->getIdentifier().size());
- // Now let's check if we got what we expected.
- EXPECT_TRUE(by_hwaddr);
- EXPECT_FALSE(by_duid);
- }
- void GenericHostDataSourceTest::testClientIdNotHWAddr() {
- // Make sure we have a pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Create a host with client-id
- HostPtr host = initializeHost4("192.0.2.1", Host::IDENT_DUID);
- ASSERT_FALSE(host->getHWAddress());
- ASSERT_TRUE(host->getDuid());
- // Try to add it to the host data source.
- ASSERT_NO_THROW(hdsptr_->add(host));
- SubnetID subnet = host->getIPv4SubnetID();
- HWAddrPtr hwaddr = DuidToHWAddr(host->getDuid());
- // Get the host by DUID (should succeed)
- ConstHostPtr by_duid = hdsptr_->get4(subnet, Host::IDENT_DUID,
- &host->getIdentifier()[0],
- host->getIdentifier().size());
- // Get the host by HW address (should fail)
- ConstHostPtr by_hwaddr = hdsptr_->get4(subnet, Host::IDENT_HWADDR,
- &host->getIdentifier()[0],
- host->getIdentifier().size());
- // Now let's check if we got what we expected.
- EXPECT_TRUE(by_duid);
- EXPECT_FALSE(by_hwaddr);
- }
- void
- GenericHostDataSourceTest::testHostname(std::string name, int num) {
- // Make sure we have a pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Initialize the address to 192.0.2.0 (this will be bumped
- // up to 192.0.2.1 in the first iteration)
- IOAddress addr("192.0.2.0");
- vector<HostPtr> hosts;
- // Prepare a vector of hosts with unique hostnames
- for (int i = 0; i < num; ++i) {
- addr = IOAddress::increase(addr);
- HostPtr host = initializeHost4(addr.toText(), Host::IDENT_DUID);
- stringstream hostname;
- hostname.str("");
- if (num > 1) {
- hostname << i;
- }
- hostname << name;
- host->setHostname(hostname.str());
- hosts.push_back(host);
- }
- // Now add them all to the host data source.
- for (vector<HostPtr>::const_iterator it = hosts.begin();
- it != hosts.end(); ++it) {
- // Try to add both of the to the host data source.
- ASSERT_NO_THROW(hdsptr_->add(*it));
- }
- // And finally retrieve them one by one and check
- // if the hostname was preserved.
- for (vector<HostPtr>::const_iterator it = hosts.begin();
- it != hosts.end(); ++it) {
- ConstHostPtr from_hds;
- ASSERT_NO_THROW(from_hds = hdsptr_->get4(
- (*it)->getIPv4SubnetID(),
- (*it)->getIPv4Reservation()));
- ASSERT_TRUE(from_hds);
- EXPECT_EQ((*it)->getHostname(), from_hds->getHostname());
- }
- }
- void
- GenericHostDataSourceTest::testMultipleSubnets(int subnets,
- const Host::IdentifierType& id) {
- // Make sure we have a pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- HostPtr host = initializeHost4("192.0.2.1", id);
- for (int i = 0; i < subnets; ++i) {
- host->setIPv4SubnetID(i + 1000);
- host->setIPv6SubnetID(i + 1000);
- // Check that the same host can have reservations in multiple subnets.
- EXPECT_NO_THROW(hdsptr_->add(host));
- }
- // Now check that the reservations can be retrieved by IPv4 address from
- // each subnet separately.
- for (int i = 0; i < subnets; ++i) {
- // Try to retrieve the host by IPv4 address.
- ConstHostPtr from_hds = hdsptr_->get4(i + 1000, host->getIPv4Reservation());
- ASSERT_TRUE(from_hds);
- EXPECT_EQ(i + 1000, from_hds->getIPv4SubnetID());
- // Try to retrieve the host by either HW address of client-id
- from_hds = hdsptr_->get4(i + 1000,
- id, &host->getIdentifier()[0],
- host->getIdentifier().size());
- ASSERT_TRUE(from_hds);
- EXPECT_EQ(i + 1000, from_hds->getIPv4SubnetID());
- }
- // Now check that they can be retrieved all at once, by IPv4 address.
- ConstHostCollection all_by_addr = hdsptr_->getAll4(IOAddress("192.0.2.1"));
- ASSERT_EQ(subnets, all_by_addr.size());
- // Verify that the values returned are proper.
- int i = 0;
- for (ConstHostCollection::const_iterator it = all_by_addr.begin();
- it != all_by_addr.end(); ++it) {
- EXPECT_EQ(IOAddress("192.0.2.1"), (*it)->getIPv4Reservation());
- EXPECT_EQ(1000 + i++, (*it)->getIPv4SubnetID());
- }
- // Finally, check that the hosts can be retrived by HW address or DUID
- ConstHostCollection all_by_id =
- hdsptr_->getAll(id, &host->getIdentifier()[0],
- host->getIdentifier().size());
- ASSERT_EQ(subnets, all_by_id.size());
- // Check that the returned values are as expected.
- i = 0;
- for (ConstHostCollection::const_iterator it = all_by_id.begin();
- it != all_by_id.end(); ++it) {
- EXPECT_EQ(IOAddress("192.0.2.1"), (*it)->getIPv4Reservation());
- EXPECT_EQ(1000 + i++, (*it)->getIPv4SubnetID());
- }
- }
- void GenericHostDataSourceTest::testGet6ByHWAddr() {
- // Make sure we have the pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Create a host reservations.
- HostPtr host1 = initializeHost6("2001:db8::1", Host::IDENT_HWADDR, "hw-address");
- HostPtr host2 = initializeHost6("2001:db8::2", Host::IDENT_HWADDR, "hw-address");
- // Sanity check: make sure the hosts have different HW addresses.
- ASSERT_TRUE(host1->getHWAddress());
- ASSERT_TRUE(host2->getHWAddress());
- compareHwaddrs(host1, host2, false);
- // Try to add both of them to the host data source.
- ASSERT_NO_THROW(hdsptr_->add(host1));
- ASSERT_NO_THROW(hdsptr_->add(host2));
- SubnetID subnet1 = host1->getIPv6SubnetID();
- SubnetID subnet2 = host2->getIPv6SubnetID();
- ConstHostPtr from_hds1 = hdsptr_->get6(subnet1, Host::IDENT_HWADDR,
- &host1->getIdentifier()[0],
- host1->getIdentifier().size());
- ConstHostPtr from_hds2 = hdsptr_->get6(subnet2, Host::IDENT_HWADDR,
- &host2->getIdentifier()[0],
- host2->getIdentifier().size());
- // Now let's check if we got what we expected.
- ASSERT_TRUE(from_hds1);
- ASSERT_TRUE(from_hds2);
- compareHosts(host1, from_hds1);
- compareHosts(host2, from_hds2);
- }
- void GenericHostDataSourceTest::testGet6ByClientId() {
- // Make sure we have the pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Create a host reservations.
- HostPtr host1 = initializeHost6("2001:db8::1", Host::IDENT_DUID, "hw-address");
- HostPtr host2 = initializeHost6("2001:db8::2", Host::IDENT_DUID, "hw-address");
- // Sanity check: make sure the hosts have different HW addresses.
- ASSERT_TRUE(host1->getDuid());
- ASSERT_TRUE(host2->getDuid());
- compareDuids(host1, host2, false);
- // Try to add both of them to the host data source.
- ASSERT_NO_THROW(hdsptr_->add(host1));
- ASSERT_NO_THROW(hdsptr_->add(host2));
- SubnetID subnet1 = host1->getIPv6SubnetID();
- SubnetID subnet2 = host2->getIPv6SubnetID();
- ConstHostPtr from_hds1 = hdsptr_->get6(subnet1, Host::IDENT_DUID,
- &host1->getIdentifier()[0],
- host1->getIdentifier().size());
- ConstHostPtr from_hds2 = hdsptr_->get6(subnet2, Host::IDENT_DUID,
- &host2->getIdentifier()[0],
- host2->getIdentifier().size());
- // Now let's check if we got what we expected.
- ASSERT_TRUE(from_hds1);
- ASSERT_TRUE(from_hds2);
- compareHosts(host1, from_hds1);
- compareHosts(host2, from_hds2);
- }
- void
- GenericHostDataSourceTest::testSubnetId6(int subnets, Host::IdentifierType id) {
- // Make sure we have a pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- HostPtr host;
- IOAddress current_address("2001:db8::0");
- for (int i = 0; i < subnets; ++i) {
- // Last boolean value set to false indicates that the same identifier
- // must be used for each generated host.
- host = initializeHost6(current_address.toText(), id, true, false);
- host->setIPv4SubnetID(i + 1000);
- host->setIPv6SubnetID(i + 1000);
- // Check that the same host can have reservations in multiple subnets.
- EXPECT_NO_THROW(hdsptr_->add(host));
- // Increase address to make sure we don't assign the same address
- // in different subnets.
- current_address = IOAddress::increase(current_address);
- }
- // Check that the reservations can be retrieved from each subnet separately.
- for (int i = 0; i < subnets; ++i) {
- // Try to retrieve the host
- ConstHostPtr from_hds = hdsptr_->get6(i + 1000, id, &host->getIdentifier()[0],
- host->getIdentifier().size());
- ASSERT_TRUE(from_hds) << "failed for i=" << i;
- EXPECT_EQ(i + 1000, from_hds->getIPv6SubnetID());
- }
- // Check that the hosts can all be retrived by HW address or DUID
- ConstHostCollection all_by_id = hdsptr_->getAll(id, &host->getIdentifier()[0],
- host->getIdentifier().size());
- ASSERT_EQ(subnets, all_by_id.size());
- // Check that the returned values are as expected.
- int i = 0;
- for (ConstHostCollection::const_iterator it = all_by_id.begin();
- it != all_by_id.end(); ++it) {
- EXPECT_EQ(IOAddress("0.0.0.0"), (*it)->getIPv4Reservation());
- EXPECT_EQ(1000 + i++, (*it)->getIPv6SubnetID());
- }
- }
- void GenericHostDataSourceTest::testGetByIPv6(Host::IdentifierType id,
- bool prefix) {
- // Make sure we have a pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Let's create a couple of hosts...
- HostPtr host1 = initializeHost6("2001:db8::1", id, prefix);
- HostPtr host2 = initializeHost6("2001:db8::2", id, prefix);
- HostPtr host3 = initializeHost6("2001:db8::3", id, prefix);
- HostPtr host4 = initializeHost6("2001:db8::4", id, prefix);
- // ... and add them to the data source.
- ASSERT_NO_THROW(hdsptr_->add(host1));
- ASSERT_NO_THROW(hdsptr_->add(host2));
- ASSERT_NO_THROW(hdsptr_->add(host3));
- ASSERT_NO_THROW(hdsptr_->add(host4));
- // Are we talking about addresses or prefixes?
- uint8_t len = prefix ? 64 : 128;
- // And then try to retrieve them back.
- ConstHostPtr from_hds1 = hdsptr_->get6(IOAddress("2001:db8::1"), len);
- ConstHostPtr from_hds2 = hdsptr_->get6(IOAddress("2001:db8::2"), len);
- ConstHostPtr from_hds3 = hdsptr_->get6(IOAddress("2001:db8::3"), len);
- ConstHostPtr from_hds4 = hdsptr_->get6(IOAddress("2001:db8::4"), len);
- // Make sure we got something back.
- ASSERT_TRUE(from_hds1);
- ASSERT_TRUE(from_hds2);
- ASSERT_TRUE(from_hds3);
- ASSERT_TRUE(from_hds4);
- // Then let's check that what we got seems correct.
- compareHosts(host1, from_hds1);
- compareHosts(host2, from_hds2);
- compareHosts(host3, from_hds3);
- compareHosts(host4, from_hds4);
- // Ok, finally let's check that getting by a different address
- // will not work.
- EXPECT_FALSE(hdsptr_->get6(IOAddress("2001:db8::5"), len));
- }
- void GenericHostDataSourceTest::testAddDuplicate6WithSameDUID() {
- // Make sure we have the pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Create a host reservations.
- HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_DUID, true);
- // Add this reservation once.
- ASSERT_NO_THROW(hdsptr_->add(host));
- // Then try to add it again, it should throw an exception.
- ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
- }
- void GenericHostDataSourceTest::testAddDuplicate6WithSameHWAddr() {
- // Make sure we have the pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Create a host reservations.
- HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_HWADDR, true);
- // Add this reservation once.
- ASSERT_NO_THROW(hdsptr_->add(host));
- // Then try to add it again, it should throw an exception.
- ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
- }
- void GenericHostDataSourceTest::testAddDuplicate4() {
- // Make sure we have the pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Create a host reservations.
- HostPtr host = initializeHost4("192.0.2.1", Host::IDENT_DUID);
- // Add this reservation once.
- ASSERT_NO_THROW(hdsptr_->add(host));
- // Then try to add it again, it should throw an exception.
- ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
- // This time use a different host identifier and try again.
- // This update should be rejected because of duplicated
- // address.
- ASSERT_NO_THROW(host->setIdentifier("01:02:03:04:05:06", "hw-address"));
- ASSERT_THROW(hdsptr_->add(host), DuplicateEntry);
- // Modify address to avoid its duplication and make sure
- // we can now add the host.
- ASSERT_NO_THROW(host->setIPv4Reservation(IOAddress("192.0.2.3")));
- EXPECT_NO_THROW(hdsptr_->add(host));
- }
- void GenericHostDataSourceTest::testAddr6AndPrefix(){
- // Make sure we have the pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- // Create a host reservations with prefix reservation (prefix = true)
- HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_DUID, true);
- // Create IPv6 reservation (for an address) and add it to the host
- IPv6Resrv resv(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::2"), 128);
- host->addReservation(resv);
- // Add this reservation
- ASSERT_NO_THROW(hdsptr_->add(host));
- // Get this host by DUID
- ConstHostPtr from_hds = hdsptr_->get6(host->getIPv6SubnetID(),
- Host::IDENT_DUID,
- &host->getIdentifier()[0],
- host->getIdentifier().size());
- // Make sure we got something back
- ASSERT_TRUE(from_hds);
- // Check if reservations are the same
- compareReservations6(host->getIPv6Reservations(),
- from_hds->getIPv6Reservations());
- }
- void GenericHostDataSourceTest::testMultipleReservations(){
- // Make sure we have the pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- uint8_t len = 128;
- HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
- // Add some reservations
- IPv6Resrv resv1(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::6"), len);
- IPv6Resrv resv2(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::7"), len);
- IPv6Resrv resv3(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::8"), len);
- IPv6Resrv resv4(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::9"), len);
- host->addReservation(resv1);
- host->addReservation(resv2);
- host->addReservation(resv3);
- host->addReservation(resv4);
- ASSERT_NO_THROW(hdsptr_->add(host));
- ConstHostPtr from_hds = hdsptr_->get6(IOAddress("2001:db8::1"), len);
- // Make sure we got something back
- ASSERT_TRUE(from_hds);
- // Check if hosts are the same
- compareHosts(host, from_hds);
- }
- void GenericHostDataSourceTest::testMultipleReservationsDifferentOrder(){
- // Make sure we have the pointer to the host data source.
- ASSERT_TRUE(hdsptr_);
- uint8_t len = 128;
- HostPtr host1 = initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
- HostPtr host2 = initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
- // Add some reservations
- IPv6Resrv resv1(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::6"), len);
- IPv6Resrv resv2(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::7"), len);
- IPv6Resrv resv3(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::8"), len);
- IPv6Resrv resv4(IPv6Resrv::TYPE_NA, IOAddress("2001:db8::9"), len);
- host1->addReservation(resv1);
- host1->addReservation(resv2);
- host1->addReservation(resv3);
- host1->addReservation(resv4);
- host2->addReservation(resv4);
- host2->addReservation(resv3);
- host2->addReservation(resv2);
- host2->addReservation(resv1);
- // Check if reservations are the same
- compareReservations6(host1->getIPv6Reservations(), host2->getIPv6Reservations());
- }
- void GenericHostDataSourceTest::testOptionsReservations4(const bool formatted) {
- HostPtr host = initializeHost4("192.0.2.5", Host::IDENT_HWADDR);
- // Add a bunch of DHCPv4 and DHCPv6 options for the host.
- ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP4_ONLY));
- // Insert host and the options into respective tables.
- ASSERT_NO_THROW(hdsptr_->add(host));
- // Subnet id will be used in quries to the database.
- SubnetID subnet_id = host->getIPv4SubnetID();
- // getAll4(address)
- ConstHostCollection hosts_by_addr = hdsptr_->getAll4(host->getIPv4Reservation());
- ASSERT_EQ(1, hosts_by_addr.size());
- ASSERT_NO_FATAL_FAILURE(compareHosts(host, *hosts_by_addr.begin()));
- // get4(subnet_id, identifier_type, identifier, identifier_size)
- ConstHostPtr host_by_id = hdsptr_->get4(subnet_id,
- host->getIdentifierType(),
- &host->getIdentifier()[0],
- host->getIdentifier().size());
- ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_id));
- // get4(subnet_id, address)
- ConstHostPtr host_by_addr = hdsptr_->get4(subnet_id, IOAddress("192.0.2.5"));
- ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_addr));
- }
- void GenericHostDataSourceTest::testOptionsReservations6(const bool formatted) {
- HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_DUID, false);
- // Add a bunch of DHCPv4 and DHCPv6 options for the host.
- ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP6_ONLY));
- // Insert host, options and IPv6 reservations into respective tables.
- ASSERT_NO_THROW(hdsptr_->add(host));
- // Subnet id will be used in queries to the database.
- SubnetID subnet_id = host->getIPv6SubnetID();
- // get6(subnet_id, identifier_type, identifier, identifier_size)
- ConstHostPtr host_by_id = hdsptr_->get6(subnet_id, host->getIdentifierType(),
- &host->getIdentifier()[0],
- host->getIdentifier().size());
- ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_id));
- // get6(address, prefix_len)
- ConstHostPtr host_by_addr = hdsptr_->get6(IOAddress("2001:db8::1"), 128);
- ASSERT_NO_FATAL_FAILURE(compareHosts(host, host_by_addr));
- }
- void GenericHostDataSourceTest::testOptionsReservations46(const bool formatted) {
- HostPtr host = initializeHost6("2001:db8::1", Host::IDENT_HWADDR, false);
- // Add a bunch of DHCPv4 and DHCPv6 options for the host.
- ASSERT_NO_THROW(addTestOptions(host, formatted, DHCP4_AND_DHCP6));
- // Insert host, options and IPv6 reservations into respective tables.
- ASSERT_NO_THROW(hdsptr_->add(host));
- // Subnet id will be used in queries to the database.
- SubnetID subnet_id = host->getIPv6SubnetID();
- // getAll(identifier_type, identifier, identifier_size)
- ConstHostCollection hosts_by_id = hdsptr_->getAll(host->getIdentifierType(),
- &host->getIdentifier()[0],
- host->getIdentifier().size());
- ASSERT_EQ(1, hosts_by_id.size());
- ASSERT_NO_FATAL_FAILURE(compareHosts(host, *hosts_by_id.begin()));
- }
- }; // namespace test
- }; // namespace dhcp
- }; // namespace isc
|