From: Marcin Siodelski Date: Wed, 13 Apr 2016 06:56:28 +0000 (+0200) Subject: [4303] Servers now search for host reservations using any identifier. X-Git-Tag: trac4106_update_base~36^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1f0f7c7d217156cc348fa26f399cfdb987df615d;p=thirdparty%2Fkea.git [4303] Servers now search for host reservations using any identifier. --- diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 98b605c1ba..85bf972f85 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -138,6 +138,44 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine, .arg(subnet->getID()); } } + + // Before we can check for static reservations, we need to prepare a set + // of identifiers to be used for this. + + // HW address. + if (context_->hwaddr_ && !context_->hwaddr_->hwaddr_.empty()) { + context_->host_identifiers_[Host::IDENT_HWADDR] = context_->hwaddr_->hwaddr_; + } + + // Client identifier + if (context_->clientid_) { + const std::vector& vec = context_->clientid_->getDuid(); + if (!vec.empty()) { + // Client identifier type = DUID? Client identifier holding a DUID + // comprises Type (1 byte), IAID (4 bytes), followed by the actual + // DUID. Thus, the minimal length is 6. + if ((vec[0] == CLIENT_ID_OPTION_TYPE_DUID) && (vec.size() > 5)) { + // Extract DUID, skip IAID. + context_->host_identifiers_.insert( + AllocEngine::IdentifierPair(Host::IDENT_DUID, + std::vector(vec.begin() + 5, + vec.end()))); + } + /// @todo Add support for other client identifiers (see #4317). + } + } + // Circuit id + OptionPtr rai = query_->getOption(DHO_DHCP_AGENT_OPTIONS); + if (rai) { + OptionPtr circuit_id_opt = rai->getOption(RAI_OPTION_AGENT_CIRCUIT_ID); + if (circuit_id_opt) { + const OptionBuffer& circuit_id_vec = circuit_id_opt->getData(); + if (!circuit_id_vec.empty()) { + context_->host_identifiers_[Host::IDENT_CIRCUIT_ID] = circuit_id_vec; + } + } + } + // Check for static reservations. alloc_engine->findReservation(*context_); }; diff --git a/src/bin/dhcp4/tests/dhcp4_client.cc b/src/bin/dhcp4/tests/dhcp4_client.cc index 3defe74488..f4926de0df 100644 --- a/src/bin/dhcp4/tests/dhcp4_client.cc +++ b/src/bin/dhcp4/tests/dhcp4_client.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-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 @@ -49,7 +49,8 @@ Dhcp4Client::Dhcp4Client(const Dhcp4Client::State& state) : server_facing_relay_addr_("10.0.0.2"), srv_(boost::shared_ptr(new NakedDhcpv4Srv(0))), state_(state), - use_relay_(false) { + use_relay_(false), + circuit_id_() { } Dhcp4Client::Dhcp4Client(boost::shared_ptr srv, @@ -67,7 +68,8 @@ Dhcp4Client::Dhcp4Client(boost::shared_ptr srv, server_facing_relay_addr_("10.0.0.2"), srv_(srv), state_(state), - use_relay_(false) { + use_relay_(false), + circuit_id_() { } void @@ -468,6 +470,15 @@ Dhcp4Client::sendMsg(const Pkt4Ptr& msg) { msg->setHops(1); msg->setGiaddr(relay_addr_); msg->setLocalAddr(server_facing_relay_addr_); + // Insert RAI + OptionPtr rai(new Option(Option::V4, DHO_DHCP_AGENT_OPTIONS)); + // Insert circuit id, if specified. + if (!circuit_id_.empty()) { + rai->addOption(OptionPtr(new Option(Option::V4, RAI_OPTION_AGENT_CIRCUIT_ID, + OptionBuffer(circuit_id_.begin(), + circuit_id_.end())))); + } + msg->addOption(rai); } // Repack the message to simulate wire-data parsing. msg->pack(); diff --git a/src/bin/dhcp4/tests/dhcp4_client.h b/src/bin/dhcp4/tests/dhcp4_client.h index c67d3b2780..71dc9544ee 100644 --- a/src/bin/dhcp4/tests/dhcp4_client.h +++ b/src/bin/dhcp4/tests/dhcp4_client.h @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-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 @@ -284,6 +284,14 @@ public: const uint8_t option2 = 0, const uint8_t option3 = 0); + /// @brief Sets circuit-id value to be included in the circuit-id + /// sub option of the RAI option. + /// + /// @param circuit_id New circuit-id value. + void setCircuitId(const std::string& circuit_id) { + circuit_id_ = circuit_id; + } + /// @brief Sets destination address for the messages being sent by the /// client. /// @@ -468,6 +476,10 @@ private: /// @brief Enable relaying messages to the server. bool use_relay_; + /// @brief Specifies value to be inserted into circuit-id sub option + /// of the RAI option. + std::string circuit_id_; + /// @brief Extra options the client will send. OptionCollection extra_options_; }; diff --git a/src/bin/dhcp4/tests/dora_unittest.cc b/src/bin/dhcp4/tests/dora_unittest.cc index 6ee86d9407..8f69c67eb7 100644 --- a/src/bin/dhcp4/tests/dora_unittest.cc +++ b/src/bin/dhcp4/tests/dora_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-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 @@ -125,6 +125,14 @@ const char* DORA_CONFIGS[] = { " {" " \"hw-address\": \"aa:bb:cc:dd:ee:ff\"," " \"ip-address\": \"10.0.0.7\"" + " }," + " {" + " \"duid\": \"01:02:03:04:05\"," + " \"ip-address\": \"10.0.0.8\"" + " }," + " {" + " \"circuit-id\": \"'charter950'\"," + " \"ip-address\": \"10.0.0.9\"" " }" " ]" "} ]" @@ -688,6 +696,31 @@ TEST_F(DORATest, reservation) { ASSERT_TRUE(subnet->inPool(Lease::TYPE_V4, clientB.config_.lease_.addr_)); } +// This test checks that it is possible to make a reservation by +// circuit-id inserted by the relay agent.. +TEST_F(DORATest, reservationByCircuitId) { + // Client A is a one which will have a reservation. + Dhcp4Client client(Dhcp4Client::SELECTING); + // Use relay agent so as the circuit-id can be inserted. + client.useRelay(true, IOAddress("10.0.0.1"), IOAddress("10.0.0.2")); + // Specify circuit-id. + client.setCircuitId("charter950"); + + // Configure DHCP server. + configure(DORA_CONFIGS[2], *client.getServer()); + // Client A performs 4-way exchange and should obtain a reserved + // address. + ASSERT_NO_THROW(client.doDORA(boost::shared_ptr< + IOAddress>(new IOAddress("0.0.0.0")))); + // Make sure that the server responded. + ASSERT_TRUE(client.getContext().response_); + Pkt4Ptr resp = client.getContext().response_; + // Make sure that the server has responded with DHCPACK. + ASSERT_EQ(DHCPACK, static_cast(resp->getType())); + // Make sure that the client has got the lease for the reserved address. + ASSERT_EQ("10.0.0.9", client.config_.lease_.addr_.toText()); +} + // This test checks that setting the match-client-id value to false causes // the server to ignore changing client identifier when the client is // using consistent HW address. diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 95fb7eed0b..caa288b968 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -276,9 +276,20 @@ AllocEngine::ClientContext6 Dhcpv6Srv::createContext(const Pkt6Ptr& pkt) { AllocEngine::ClientContext6 ctx; ctx.subnet_ = selectSubnet(pkt); + ctx.query_ = pkt; + + // Collect host identifiers. + // DUID ctx.duid_ = pkt->getClientId(); + if (ctx.duid_) { + ctx.host_identifiers_[Host::IDENT_DUID] = ctx.duid_->getDuid(); + } + // HW Address. ctx.hwaddr_ = getMAC(pkt); - ctx.query_ = pkt; + if (ctx.hwaddr_) { + ctx.host_identifiers_[Host::IDENT_HWADDR] = ctx.hwaddr_->hwaddr_; + } + // And find a host reservation using those identifiers. alloc_engine_->findReservation(ctx); return (ctx); @@ -1321,6 +1332,7 @@ Dhcpv6Srv::assignIA_NA(const Pkt6Ptr& query, const Pkt6Ptr& answer, ctx.hwaddr_ = orig_ctx.hwaddr_; ctx.host_ = orig_ctx.host_; ctx.query_ = orig_ctx.query_; + ctx.host_identifiers_ = orig_ctx.host_identifiers_; Lease6Collection leases = alloc_engine_->allocateLeases6(ctx); @@ -1442,6 +1454,7 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer, ctx.hwaddr_ = orig_ctx.hwaddr_; ctx.host_ = orig_ctx.host_; ctx.query_ = orig_ctx.query_; + ctx.host_identifiers_ = orig_ctx.host_identifiers_; Lease6Collection leases = alloc_engine_->allocateLeases6(ctx); diff --git a/src/bin/dhcp6/tests/dhcp6_client.h b/src/bin/dhcp6/tests/dhcp6_client.h index 39c8d003fe..3bf97d8389 100644 --- a/src/bin/dhcp6/tests/dhcp6_client.h +++ b/src/bin/dhcp6/tests/dhcp6_client.h @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2014-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 @@ -412,6 +412,13 @@ public: iface_name_ = iface_name; } + /// @brief Sets link local address used by the client. + /// + /// @param link_local New link local address. + void setLinkLocal(const asiolink::IOAddress& link_local) { + link_local_ = link_local; + } + /// @brief Set an address hint to be sent to a server. /// /// @param pref_lft Preferred lifetime. diff --git a/src/bin/dhcp6/tests/host_unittest.cc b/src/bin/dhcp6/tests/host_unittest.cc index 519c5d44de..a4f73f1eda 100644 --- a/src/bin/dhcp6/tests/host_unittest.cc +++ b/src/bin/dhcp6/tests/host_unittest.cc @@ -1,15 +1,17 @@ -// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +// 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 +#include #include #include #include using namespace isc; +using namespace isc::asiolink; using namespace isc::dhcp; using namespace isc::dhcp::test; @@ -19,6 +21,8 @@ namespace { /// /// - Configuration 0: /// Single subnet with two reservations, one with a hostname, one without +/// - Configuration 1: +/// Multiple reservations using different host identifiers. const char* CONFIGS[] = { // Configuration 0: "{ " @@ -45,7 +49,35 @@ const char* CONFIGS[] = { " \"ip-addresses\": [ \"2001:db8:1:1::babf\" ]" " } ]" " } ]" + "}", + + // Configuration 1: + "{ " + "\"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"valid-lifetime\": 4000, " + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"mac-sources\": [ \"ipv6-link-local\" ], " + "\"subnet6\": [ " + " { " + " \"subnet\": \"2001:db8:1::/48\", " + " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," + " \"interface\" : \"eth0\" , " + " \"reservations\": [" + " {" + " \"hw-address\": \"38:60:77:d5:ff:ee\"," + " \"ip-addresses\": [ \"2001:db8:1::1\" ]" + " }," + " {" + " \"duid\": \"01:02:03:05\"," + " \"ip-addresses\": [ \"2001:db8:1::2\" ]" + " } ]" + " } ]" "}" + }; /// @brief Test fixture class for testing host reservations @@ -59,6 +91,36 @@ public: iface_mgr_test_config_(true) { } + /// @brief Verifies that the reservation is retrieved by the server + /// using one of the host identifiers. + /// + /// @param client Reference to a client to be used in the test. + /// The client should be preconfigured to insert a specific identifier + /// into the message, e.g. DUID, HW address etc. + /// @param exp_ip_address Expected IPv6 address in the returned + /// reservation. + void testReservationByIdentifier(Dhcp6Client& client, + const std::string exp_ip_address) { + configure(CONFIGS[1], *client.getServer()); + + const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()-> + getCfgSubnets6()->getAll(); + ASSERT_EQ(1, subnets->size()); + + // Configure client to request IA_NA and append IA_NA option + // to the client's message. + client.useNA(); + ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:1:1::dead:beef")); + + // Perform 4-way exchange. + ASSERT_NO_THROW(client.doSARR()); + + // Verify that the client we got the reserved address + ASSERT_EQ(1, client.getLeaseNum()); + Lease6 lease_client = client.getLease(0); + EXPECT_EQ(exp_ip_address, lease_client.addr_.toText()); + } + /// @brief Interface Manager's fake configuration control. IfaceMgrTestConfig iface_mgr_test_config_; }; @@ -246,4 +308,28 @@ TEST_F(HostTest, sarrAndRebind) { EXPECT_EQ("alice", lease_server2->hostname_); } +// This test verfies that the host reservation by DUID is found by the +// server. +TEST_F(HostTest, reservationByDUID) { + Dhcp6Client client; + // Set DUID matching the one used to create host reservations. + client.setDUID("01:02:03:05"); + // Run the actual test. + testReservationByIdentifier(client, "2001:db8:1::2"); +} + +// This test verfies that the host reservation by HW address is found +// by the server. +TEST_F(HostTest, reservationByHWAddress) { + Dhcp6Client client; + // Set link local address for the client which the server will + // use to decode the HW address as 38:60:77:d5:ff:ee. This + // decoded address will be used to search for host reservations. + client.setLinkLocal(IOAddress("fe80::3a60:77ff:fed5:ffee")); + // Run the actual test. + testReservationByIdentifier(client, "2001:db8:1::1"); +} + + + } // end of anonymous namespace diff --git a/src/lib/dhcp/dhcp4.h b/src/lib/dhcp/dhcp4.h index bc5fb5264a..e079e03230 100644 --- a/src/lib/dhcp/dhcp4.h +++ b/src/lib/dhcp/dhcp4.h @@ -283,6 +283,9 @@ static const uint16_t RAI_OPTION_VIRTUAL_SUBNET_SELECT_CTRL = 152; //RFC6607 #endif +/* Client identifier types */ +static const uint8_t CLIENT_ID_OPTION_TYPE_DUID = 255; + } // end of isc::dhcp namespace } // end of isc namespace diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 2b09fcb0aa..7c7feec451 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -309,7 +309,7 @@ AllocEngine::ClientContext6::ClientContext6() : subnet_(), duid_(), iaid_(0), type_(Lease::TYPE_NA), hwaddr_(), hints_(), fwd_dns_update_(false), rev_dns_update_(false), hostname_(""), callout_handle_(), fake_allocation_(false), old_leases_(), host_(), - query_(), ia_rsp_() { + query_(), ia_rsp_(), host_identifiers_() { } AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet, const DuidPtr& duid, @@ -322,7 +322,7 @@ AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet, const Duid subnet_(subnet), duid_(duid), iaid_(iaid), type_(type), hwaddr_(), hints_(), fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns), hostname_(hostname), fake_allocation_(fake_allocation), - old_leases_(), host_(), query_(), ia_rsp_() { + old_leases_(), host_(), query_(), ia_rsp_(), host_identifiers_() { static asiolink::IOAddress any("::"); @@ -331,6 +331,11 @@ AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet, const Duid } // callout_handle, host pointers initiated to NULL by their // respective constructors. + + // Initialize host identifiers. + if (duid) { + host_identifiers_[Host::IDENT_DUID] = duid->getDuid(); + } } @@ -339,6 +344,8 @@ void AllocEngine::findReservation(ClientContext6& ctx) const { return; } + ctx.host_.reset(); + // Check which host reservation mode is supported in this subnet. Subnet::HRMode hr_mode = ctx.subnet_->getHostReservationMode(); @@ -346,11 +353,15 @@ void AllocEngine::findReservation(ClientContext6& ctx) const { // host info only if reservations are not disabled. if (hr_mode != Subnet::HR_DISABLED) { - ctx.host_ = HostMgr::instance().get6(ctx.subnet_->getID(), ctx.duid_, - ctx.hwaddr_); - } else { - // Let's explicitly set it to NULL if reservations are disabled. - ctx.host_.reset(); + BOOST_FOREACH(const IdentifierPair& id, ctx.host_identifiers_) { + ctx.host_ = HostMgr::instance().get6(ctx.subnet_->getID(), + id.first, &id.second[0], + id.second.size()); + // If we found matching host, return. + if (ctx.host_) { + return; + } + } } } @@ -2049,7 +2060,8 @@ AllocEngine::ClientContext4::ClientContext4() requested_address_(IOAddress::IPV4_ZERO_ADDRESS()), fwd_dns_update_(false), rev_dns_update_(false), hostname_(""), callout_handle_(), fake_allocation_(false), - old_lease_(), host_(), conflicting_lease_(), query_() { + old_lease_(), host_(), conflicting_lease_(), query_(), + host_identifiers_() { } AllocEngine::ClientContext4::ClientContext4(const Subnet4Ptr& subnet, @@ -2064,7 +2076,13 @@ AllocEngine::ClientContext4::ClientContext4(const Subnet4Ptr& subnet, requested_address_(requested_addr), fwd_dns_update_(fwd_dns_update), rev_dns_update_(rev_dns_update), hostname_(hostname), callout_handle_(), - fake_allocation_(fake_allocation), old_lease_(), host_() { + fake_allocation_(fake_allocation), old_lease_(), host_(), + host_identifiers_() { + + // Initialize host identifiers. + if (hwaddr) { + host_identifiers_[Host::IDENT_HWADDR] = hwaddr->hwaddr_; + } } Lease4Ptr @@ -2109,10 +2127,15 @@ AllocEngine::findReservation(ClientContext4& ctx) { // Check if there is a host reseravtion for this client. Attempt to // get host information if (hr_mode != Subnet::HR_DISABLED) { - // This method should handle the case when there is neither hwaddr - // nor clientid_ available and simply return NULL. - ctx.host_ = HostMgr::instance().get4(ctx.subnet_->getID(), ctx.hwaddr_, - ctx.clientid_); + BOOST_FOREACH(const IdentifierPair& id, ctx.host_identifiers_) { + ctx.host_ = HostMgr::instance().get4(ctx.subnet_->getID(), + id.first, &id.second[0], + id.second.size()); + // If we found matching host, return. + if (ctx.host_) { + return; + } + } } } } diff --git a/src/lib/dhcpsrv/alloc_engine.h b/src/lib/dhcpsrv/alloc_engine.h index 962562a239..b23f0ad1bf 100644 --- a/src/lib/dhcpsrv/alloc_engine.h +++ b/src/lib/dhcpsrv/alloc_engine.h @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-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 @@ -23,6 +23,7 @@ #include #include +#include namespace isc { namespace dhcp { @@ -251,6 +252,12 @@ public: /// @brief Container for client's hints. typedef std::vector HintContainer; + /// @brief A tuple holding host identifier type and value. + typedef std::pair > IdentifierPair; + + /// @brief Map holding values to be used as host identifiers. + typedef std::map > IdentifierMap; + /// @brief Context information for the DHCPv6 leases allocation. /// /// This structure holds a set of information provided by the DHCPv6 @@ -350,6 +357,10 @@ public: /// @brief A pointer to the IA_NA/IA_PD option to be sent in response Option6IAPtr ia_rsp_; + /// @brief A map holding host identifiers extracted from a message + /// received by the server. + IdentifierMap host_identifiers_; + /// @brief Default constructor. ClientContext6(); @@ -971,6 +982,10 @@ public: /// transaction identification information. Pkt4Ptr query_; + /// @brief A map holding host identifiers extracted from a message + /// received by the server. + IdentifierMap host_identifiers_; + /// @brief Default constructor. ClientContext4(); diff --git a/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc index 22910bf52b..2b09144771 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine4_unittest.cc @@ -1649,6 +1649,8 @@ TEST_F(AllocEngine4Test, findReservation) { AllocEngine::ClientContext4 ctx(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"), false, false, "", false); + ctx.host_identifiers_[Host::IDENT_HWADDR] = hwaddr_->hwaddr_; + ctx.host_identifiers_[Host::IDENT_DUID] = clientid_->getDuid(); // There is no reservation in the database so no host should be // retruned. diff --git a/src/lib/dhcpsrv/tests/alloc_engine_utils.cc b/src/lib/dhcpsrv/tests/alloc_engine_utils.cc index 9d3d3c07e5..9198658fc5 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_utils.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine_utils.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-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 @@ -270,6 +270,7 @@ AllocEngine6Test::simpleAlloc6Test(const Pool6Ptr& pool, const IOAddress& hint, AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, hint, type, false, false, "", fake); ctx.hwaddr_ = hwaddr_; + ctx.host_identifiers_[Host::IDENT_HWADDR] = hwaddr_->hwaddr_; ctx.query_.reset(new Pkt6(fake ? DHCPV6_SOLICIT : DHCPV6_REQUEST, 1234)); findReservation(*engine, ctx);