8#include <kea_version.h>
113#include <boost/foreach.hpp>
114#include <boost/pointer_cast.hpp>
115#include <boost/range/adaptor/reversed.hpp>
116#include <boost/shared_ptr.hpp>
130namespace ph = std::placeholders;
136 int hook_index_buffer4_receive_;
137 int hook_index_pkt4_receive_;
138 int hook_index_subnet4_select_;
139 int hook_index_leases4_committed_;
140 int hook_index_lease4_release_;
141 int hook_index_pkt4_send_;
142 int hook_index_buffer4_send_;
143 int hook_index_lease4_decline_;
144 int hook_index_host4_identifier_;
145 int hook_index_ddns4_update_;
146 int hook_index_lease4_offer_;
147 int hook_index_lease4_server_decline_;
168std::set<std::string> dhcp4_statistics = {
170 "pkt4-discover-received",
171 "pkt4-offer-received",
172 "pkt4-request-received",
175 "pkt4-release-received",
176 "pkt4-decline-received",
177 "pkt4-inform-received",
178 "pkt4-unknown-received",
185 "v4-allocation-fail",
186 "v4-allocation-fail-shared-network",
187 "v4-allocation-fail-subnet",
188 "v4-allocation-fail-no-pools",
189 "v4-allocation-fail-classes",
190 "v4-reservation-conflicts",
210 : alloc_engine_(alloc_engine), query_(query), resp_(),
211 context_(context), ipv6_only_preferred_(false) {
213 if (!alloc_engine_) {
215 " when creating an instance of the Dhcpv4Exchange");
220 " creating an instance of the Dhcpv4Exchange");
229 context_->subnet_ = subnet;
235 if (subnet && !context_->early_global_reservations_lookup_) {
236 OptionPtr opt_clientid = query->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
238 context_->clientid_.reset(
new ClientId(opt_clientid->getData()));
244 if (subnet->getReservationsInSubnet() ||
245 subnet->getReservationsGlobal()) {
248 if (!context_->early_global_reservations_lookup_) {
253 alloc_engine->findReservation(*context_);
256 subnet->getSharedNetwork(sn);
266 auto global_host = context_->globalHost();
267 auto current_host = context_->currentHost();
268 if ((!context_->early_global_reservations_lookup_ &&
269 global_host && !global_host->getClientClasses4().empty()) ||
270 (!sn && current_host && !current_host->getClientClasses4().empty())) {
291 if (!context_->hosts_.empty()) {
292 query->addClass(
"KNOWN");
294 .arg(query->getLabel())
297 query->addClass(
"UNKNOWN");
299 .arg(query->getLabel())
308 .arg(query_->getLabel())
312 if (query_->inClass(
"DROP")) {
314 .arg(query_->getHWAddrLabel())
315 .arg(query_->toText());
317 static_cast<int64_t
>(1));
324 uint8_t resp_type = 0;
338 resp_.reset(
new Pkt4(resp_type,
getQuery()->getTransid()));
340 copyDefaultOptions();
354 const Pkt6Ptr& query6 = query->getPkt6();
358 if (!query6->relay_info_.empty()) {
359 resp6->copyRelayInfo(query6);
362 resp6->setIface(query6->getIface());
363 resp6->setIndex(query6->getIndex());
364 resp6->setRemoteAddr(query6->getRemoteAddr());
365 resp6->setRemotePort(query6->getRemotePort());
366 resp_.reset(
new Pkt4o6(resp_, resp6));
370Dhcpv4Exchange::copyDefaultFields() {
371 resp_->setIface(query_->getIface());
372 resp_->setIndex(query_->getIndex());
379 resp_->setCiaddr(query_->getCiaddr());
383 resp_->setHops(query_->getHops());
386 resp_->setHWAddr(query_->getHWAddr());
389 resp_->setGiaddr(query_->getGiaddr());
398 HWAddrPtr src_hw_addr = query_->getLocalHWAddr();
400 resp_->setLocalHWAddr(src_hw_addr);
402 HWAddrPtr dst_hw_addr = query_->getRemoteHWAddr();
404 resp_->setRemoteHWAddr(dst_hw_addr);
408 resp_->setFlags(query_->getFlags());
412Dhcpv4Exchange::copyDefaultOptions() {
416 OptionPtr client_id = query_->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
417 if (client_id && echo) {
418 resp_->addOption(client_id);
431 resp_->addOption(subnet_sel);
444 sao->boolValue() && query_->inClass(
"STASH_AGENT_OPTIONS")) {
447 resp_->addOption(rai);
457 for (
auto const& id_type : cfg->getIdentifierTypes()) {
460 if (context->hwaddr_ && !context->hwaddr_->hwaddr_.empty()) {
461 context->addHostIdentifier(id_type, context->hwaddr_->hwaddr_);
466 if (context->clientid_) {
467 const std::vector<uint8_t>& vec = context->clientid_->getClientId();
472 if ((vec[0] == CLIENT_ID_OPTION_TYPE_DUID) && (vec.size() > 5)) {
474 context->addHostIdentifier(id_type,
475 std::vector<uint8_t>(vec.begin() + 5,
487 if (circuit_id_opt) {
488 const OptionBuffer& circuit_id_vec = circuit_id_opt->getData();
489 if (!circuit_id_vec.empty()) {
490 context->addHostIdentifier(id_type, circuit_id_vec);
498 if (context->clientid_) {
499 const std::vector<uint8_t>& vec = context->clientid_->getClientId();
501 context->addHostIdentifier(id_type, vec);
514 std::vector<uint8_t> id;
523 callout_handle->setArgument(
"query4", context->query_);
524 callout_handle->setArgument(
"id_type", type);
525 callout_handle->setArgument(
"id_value",
id);
531 callout_handle->getArgument(
"id_type", type);
532 callout_handle->getArgument(
"id_value",
id);
538 .arg(context->query_->getLabel())
541 context->addHostIdentifier(type,
id);
556 for (
auto const& def : *defs_ptr) {
560 if (def->getMatchExpr()) {
561 query->classes_.erase(def->getName());
568 if (context->currentHost() && context->query_) {
569 const ClientClasses& classes = context->currentHost()->getClientClasses4();
570 for (
auto const& cclass : classes) {
571 context->query_->addClass(cclass);
578 if (context_->subnet_) {
580 context_->subnet_->getSharedNetwork(shared_network);
581 if (shared_network) {
583 if (host && (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL)) {
595 if (!host->getNextServer().isV4Zero()) {
596 resp_->setSiaddr(host->getNextServer());
599 std::string sname = host->getServerHostname();
600 if (!sname.empty()) {
601 resp_->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
605 std::string bootfile = host->getBootFileName();
606 if (!bootfile.empty()) {
607 resp_->setFile(
reinterpret_cast<const uint8_t*
>(bootfile.c_str()),
615 boost::shared_ptr<OptionString> vendor_class =
627 pkt->addClass(
"ALL");
641 for (
auto const& it : *defs_ptr) {
649 if (it->getAdditional()) {
653 if (it->getDependOnKnown() != depend_on_known) {
656 it->test(pkt, expr_ptr);
663 const bool use_bcast,
const bool direct_response_desired)
664 : io_service_(new
IOService()), server_port_(server_port),
665 client_port_(client_port), shutdown_(true),
666 alloc_engine_(), use_bcast_(use_bcast),
669 test_send_responses_to_source_(false) {
671 const char* env = std::getenv(
"KEA_TEST_SEND_RESPONSES_TO_SOURCE");
674 test_send_responses_to_source_ =
true;
702 }
catch (
const std::exception &e) {
718 for (
auto const& it : dhcp4_statistics) {
720 stats_mgr.
setValue(it,
static_cast<int64_t
>(0));
730 }
catch (
const std::exception& ex) {
737 }
catch (
const std::exception& ex) {
756 if (!names.empty()) {
758 for (
size_t i = 1; i < names.size(); ++i) {
759 msg += std::string(
", ") + names[i];
765 io_service_->stopAndPoll();
776 bool sanity_only,
bool allow_answer_park) {
779 if (query->isDhcp4o6()) {
788 subnet = cfgmgr.
getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
800 shared_ptr<ScopedCalloutHandleState> callout_handle_state(
801 std::make_shared<ScopedCalloutHandleState>(callout_handle));
807 callout_handle->setArgument(
"query4", query);
808 callout_handle->setArgument(
"subnet4", subnet);
809 callout_handle->setArgument(
"subnet4collection",
811 getCfgSubnets4()->getAll());
813 auto const tpl(parkingLimitExceeded(
"subnet4_select"));
814 bool const exceeded(get<0>(tpl));
816 uint32_t
const limit(get<1>(tpl));
821 .arg(query->getLabel());
827 "subnet4_select", query, [
this, query, allow_answer_park, callout_handle_state]() {
829 boost::shared_ptr<function<void()>> callback(
830 boost::make_shared<function<
void()>>(
831 [
this, query, allow_answer_park]()
mutable {
834 callout_handle_state->on_completion_ = [callback]() {
857 .arg(query->getLabel());
870 .arg(query->getLabel());
879 .arg(query->getLabel());
885 callout_handle->getArgument(
"subnet4", subnet);
891 .arg(query->getLabel())
892 .arg(subnet->getID());
896 .arg(query->getLabel())
897 .arg(subnet->toText());
902 .arg(query->getLabel());
910 bool sanity_only,
bool allow_answer_park) {
914 selector.
ciaddr_ = query->getCiaddr();
915 selector.
giaddr_ = query->getGiaddr();
926 Pkt4o6Ptr query4o6 = boost::dynamic_pointer_cast<Pkt4o6>(query);
930 const Pkt6Ptr& query6 = query4o6->getPkt6();
933 if (query6 && !query6->relay_info_.empty()) {
934 for (
auto const& relay : boost::adaptors::reverse(query6->relay_info_)) {
935 if (!relay.linkaddr_.isV6Zero() &&
936 !relay.linkaddr_.isV6LinkLocal()) {
949 OptionCustomPtr oc = boost::dynamic_pointer_cast<OptionCustom>(sbnsel);
956 subnet = cfgmgr.
getCurrentCfg()->getCfgSubnets4()->selectSubnet4o6(selector);
968 shared_ptr<ScopedCalloutHandleState> callout_handle_state(
969 std::make_shared<ScopedCalloutHandleState>(callout_handle));
975 callout_handle->setArgument(
"query4", query);
976 callout_handle->setArgument(
"subnet4", subnet);
977 callout_handle->setArgument(
"subnet4collection",
979 getCfgSubnets4()->getAll());
981 auto const tpl(parkingLimitExceeded(
"subnet4_select"));
982 bool const exceeded(get<0>(tpl));
984 uint32_t
const limit(get<1>(tpl));
989 .arg(query->getLabel());
995 "subnet4_select", query, [
this, query, allow_answer_park, callout_handle_state]() {
997 boost::shared_ptr<function<void()>> callback(
998 boost::make_shared<function<
void()>>(
999 [
this, query, allow_answer_park]()
mutable {
1002 callout_handle_state->on_completion_ = [callback]() {
1025 .arg(query->getLabel());
1038 .arg(query->getLabel());
1047 .arg(query->getLabel());
1053 callout_handle->getArgument(
"subnet4", subnet);
1060 .arg(query->getLabel())
1061 .arg(subnet->getID());
1066 .arg(query->getLabel())
1067 .arg(subnet->toText());
1072 .arg(query->getLabel());
1092 ctx->query_ = query;
1095 ctx->hwaddr_ = query->getHWAddr();
1109 ctx->early_global_reservations_lookup_ = egrl->boolValue();
1113 if (ctx->early_global_reservations_lookup_) {
1115 OptionPtr opt_clientid = query->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
1117 ctx->clientid_.reset(
new ClientId(opt_clientid->getData()));
1126 if (global_host && !global_host->getClientClasses4().empty()) {
1131 const ClientClasses& classes = global_host->getClientClasses4();
1132 for (
auto const& cclass : classes) {
1133 query->addClass(cclass);
1142 query->addClass(
"KNOWN");
1144 .arg(query->getLabel())
1151 if (query->inClass(
"DROP")) {
1154 .arg(query->getHWAddrLabel())
1155 .arg(query->toText());
1157 static_cast<int64_t
>(1));
1162 ctx->hosts_[SUBNET_ID_GLOBAL] = global_host;
1176 const char*
interface = getenv(
"KEA_AFL_INTERFACE");
1178 isc_throw(FuzzInitFail,
"no fuzzing interface has been set");
1182 const char* address = getenv(
"KEA_AFL_ADDRESS");
1184 isc_throw(FuzzInitFail,
"no fuzzing address has been set");
1192 while (__AFL_LOOP(fuzzer.maxLoopCount())) {
1205 }
catch (
const std::exception& e) {
1236 uint32_t timeout = 1;
1247 .arg(query->getRemoteAddr().toText())
1248 .arg(query->getRemotePort())
1249 .arg(query->getLocalAddr().toText())
1250 .arg(query->getLocalPort())
1251 .arg(query->getIface());
1267 }
catch (
const std::exception& e) {
1283 .arg(query->getLabel());
1287 query->addPktEvent(
"mt_queued");
1288 typedef function<void()> CallBack;
1289 boost::shared_ptr<CallBack> call_back =
1305 }
catch (
const std::exception& e) {
1307 .arg(query->getLabel())
1328 query->addPktEvent(
"process_started");
1331 query->addClass(
"ALL");
1338 static_cast<int64_t
>(1));
1340 bool skip_unpack =
false;
1357 callout_handle->setArgument(
"query4", query);
1369 .arg(query->getRemoteAddr().toText())
1370 .arg(query->getLocalAddr().toText())
1371 .arg(query->getIface());
1382 .arg(query->getRemoteAddr().toText())
1383 .arg(query->getLocalAddr().toText())
1384 .arg(query->getIface());
1388 callout_handle->getArgument(
"query4", query);
1396 .arg(query->getRemoteAddr().toText())
1397 .arg(query->getLocalAddr().toText())
1398 .arg(query->getIface());
1405 .arg(query->getLabel())
1407 }
catch (
const std::exception& e) {
1410 .arg(query->getLabel())
1411 .arg(query->getRemoteAddr().toText())
1412 .arg(query->getLocalAddr().toText())
1413 .arg(query->getIface())
1415 .arg(query->getHWAddrLabel());
1419 static_cast<int64_t
>(1));
1421 static_cast<int64_t
>(1));
1428 .arg(query->getLabel());
1436 }
catch (
const std::exception&) {
1453 static_cast<int64_t
>(1));
1459 int type = query->getType();
1461 .arg(query->getLabel())
1462 .arg(query->getName())
1464 .arg(query->getRemoteAddr())
1465 .arg(query->getLocalAddr())
1466 .arg(query->getIface());
1468 .arg(query->getLabel())
1469 .arg(query->toText());
1485 callout_handle->setArgument(
"query4", query);
1498 .arg(query->getLabel());
1502 callout_handle->getArgument(
"query4", query);
1506 if (query->inClass(
"DROP")) {
1508 .arg(query->getHWAddrLabel())
1509 .arg(query->toText());
1511 static_cast<int64_t
>(1));
1520 bool allow_answer_park) {
1529 }
catch (
const std::exception& e) {
1531 .arg(query->getLabel())
1551 this, query, allow_answer_park));
1552 if (!client_handler.
tryLock(query, cont)) {
1568 ctx->subnet_ =
selectSubnet(query, drop,
false, allow_answer_park);
1574 }
catch (
const std::exception& e) {
1584 .arg(query->getLabel())
1589 static_cast<int64_t
>(1));
1598 bool allow_answer_park) {
1608 }
catch (
const std::exception& e) {
1610 .arg(query->getLabel())
1619 bool allow_answer_park) {
1627 callout_handle->getContext(
"subnet4", ctx->subnet_);
1637 bool allow_answer_park) {
1644 switch (query->getType()) {
1674 }
catch (
const std::exception& e) {
1684 .arg(query->getLabel())
1689 static_cast<int64_t
>(1));
1696 int hook_idx =
Hooks.hook_index_leases4_committed_;
1697 std::string hook_label =
"leases4_committed";
1701 if (ctx->fake_allocation_) {
1702 hook_idx =
Hooks.hook_index_lease4_offer_;
1703 hook_label =
"lease4_offer";
1733 std::shared_ptr<ScopedCalloutHandleState> callout_handle_state =
1734 std::make_shared<ScopedCalloutHandleState>(callout_handle);
1739 callout_handle->setArgument(
"query4", query);
1743 if (ctx->new_lease_ && (ctx->new_lease_->reuseable_valid_lft_ == 0)) {
1744 new_leases->push_back(ctx->new_lease_);
1746 callout_handle->setArgument(
"leases4", new_leases);
1748 if (ctx->fake_allocation_) {
1750 callout_handle->setArgument(
"offer_lifetime", ctx->offer_lft_);
1751 callout_handle->setArgument(
"old_lease", ctx->old_lease_);
1755 if (ctx->old_lease_) {
1756 if ((!ctx->new_lease_) || (ctx->new_lease_->addr_ != ctx->old_lease_->addr_)) {
1757 deleted_leases->push_back(ctx->old_lease_);
1760 callout_handle->setArgument(
"deleted_leases4", deleted_leases);
1763 if (allow_answer_park) {
1764 auto const tpl(parkingLimitExceeded(hook_label));
1765 bool const exceeded(get<0>(tpl));
1767 uint32_t
const limit(get<1>(tpl));
1771 .arg(query->getLabel());
1773 static_cast<int64_t
>(1));
1783 [
this, callout_handle, query, rsp, callout_handle_state, hook_idx, ctx]()
mutable {
1784 if (hook_idx ==
Hooks.hook_index_lease4_offer_) {
1785 bool offer_address_in_use =
false;
1787 callout_handle->getArgument(
"offer_address_in_use", offer_address_in_use);
1790 .arg(query->getLabel())
1794 if (offer_address_in_use) {
1796 bool lease_exists = (ctx->offer_lft_ > 0);
1798 typedef function<void()> CallBack;
1801 boost::shared_ptr<CallBack> call_back = boost::make_shared<CallBack>(
1803 callout_handle, query, lease, lease_exists));
1804 callout_handle_state->on_completion_ = [call_back]() {
1817 typedef function<void()> CallBack;
1818 boost::shared_ptr<CallBack> call_back = boost::make_shared<CallBack>(
1820 query, rsp, ctx->subnet_));
1821 callout_handle_state->on_completion_ = [call_back]() {
1836 if (allow_answer_park) {
1844 allow_answer_park) {
1846 .arg(query->getLabel());
1857 .arg(query->getLabel());
1879 }
catch (
const std::exception& e) {
1881 .arg(query->getLabel())
1892 query->addPktEvent(
"process_completed");
1898 bool skip_pack =
false;
1914 callout_handle->setArgument(
"query4", query);
1917 callout_handle->setArgument(
"response4", rsp);
1920 callout_handle->setArgument(
"subnet4", subnet);
1933 .arg(query->getLabel());
1940 .arg(rsp->getLabel());
1949 .arg(rsp->getLabel());
1951 }
catch (
const std::exception& e) {
1953 .arg(rsp->getLabel())
1983 callout_handle->setArgument(
"response4", rsp);
1996 .arg(rsp->getLabel());
2000 callout_handle->getArgument(
"response4", rsp);
2004 .arg(rsp->getLabel())
2005 .arg(rsp->getName())
2006 .arg(
static_cast<int>(rsp->getType()))
2007 .arg(rsp->getLocalAddr().isV4Zero() ?
"*" : rsp->getLocalAddr().toText())
2008 .arg(rsp->getLocalPort())
2009 .arg(rsp->getRemoteAddr())
2010 .arg(rsp->getRemotePort())
2011 .arg(rsp->getIface().empty() ?
"to be determined from routing" :
2016 .arg(rsp->getLabel())
2017 .arg(rsp->getName())
2018 .arg(
static_cast<int>(rsp->getType()))
2019 .arg(rsp->toText());
2025 }
catch (
const std::exception& e) {
2027 .arg(rsp->getLabel())
2037 boost::shared_ptr<Option4AddrLst> generated =
2038 boost::dynamic_pointer_cast<Option4AddrLst>(srvid);
2044 if (addrs.size() != 1) {
2046 <<
"Expected to contain a single IPv4 address.");
2049 return (addrs[0].toText());
2067 if (local_addr.
isV4Bcast() || query->isDhcp4o6()) {
2073 opt_srvid->writeAddress(local_addr);
2091 if (host && !host->getCfgOption4()->empty()) {
2092 co_list.push_back(host->getCfgOption4());
2099 addr = resp->getYiaddr();
2103 if (pool && !pool->getCfgOption()->empty()) {
2104 co_list.push_back(pool->getCfgOption());
2109 if (!subnet->getCfgOption()->empty()) {
2110 co_list.push_back(subnet->getCfgOption());
2115 subnet->getSharedNetwork(network);
2116 if (network && !network->getCfgOption()->empty()) {
2117 co_list.push_back(network->getCfgOption());
2122 for (
auto const& cclass : classes) {
2125 getClientClassDictionary()->findClass(cclass);
2137 if (ccdef->getCfgOption()->empty()) {
2142 co_list.push_back(ccdef->getCfgOption());
2166 if (co_list.empty()) {
2172 set<uint8_t> requested_opts;
2181 for (uint16_t code : option_prl->getValues()) {
2182 static_cast<void>(requested_opts.insert(code));
2186 std::set<uint8_t> cancelled_opts;
2187 const auto& cclasses = query->getClasses();
2191 for (
auto const& copts : co_list) {
2199 BOOST_FOREACH(
auto const& desc, prange) {
2202 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2203 static_cast<void>(requested_opts.insert(code));
2209 BOOST_FOREACH(
auto const& desc, crange) {
2212 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2213 static_cast<void>(cancelled_opts.insert(code));
2220 for (uint8_t opt : requested_opts) {
2221 if (cancelled_opts.count(opt) > 0) {
2229 if (!resp->getOption(opt)) {
2231 for (
auto const& copts : co_list) {
2235 resp->addOption(desc.
option_);
2248 set<uint32_t> vendor_ids;
2252 vendor_opts = boost::dynamic_pointer_cast<OptionVendorClass>(opt.second);
2254 uint32_t vendor_id = vendor_opts->getVendorId();
2255 static_cast<void>(vendor_ids.insert(vendor_id));
2259 for (
auto const& copts : co_list) {
2262 if (!desc.option_ || !desc.allowedForClientClasses(cclasses)) {
2266 boost::dynamic_pointer_cast<OptionVendorClass>(desc.option_);
2271 uint32_t vendor_id = vendor_opts->getVendorId();
2272 if (vendor_ids.count(vendor_id) > 0) {
2276 resp->Pkt::addOption(desc.option_);
2277 static_cast<void>(vendor_ids.insert(vendor_id));
2286 set<uint32_t> vendor_ids;
2290 vendor_opts = boost::dynamic_pointer_cast<OptionVendor>(opt.second);
2292 uint32_t vendor_id = vendor_opts->getVendorId();
2293 static_cast<void>(vendor_ids.insert(vendor_id));
2297 for (
auto const& copts : co_list) {
2300 if (!desc.option_ || !desc.allowedForClientClasses(cclasses)) {
2304 boost::dynamic_pointer_cast<OptionVendor>(desc.option_);
2309 uint32_t vendor_id = vendor_opts->getVendorId();
2310 if (vendor_ids.count(vendor_id) > 0) {
2316 resp->Pkt::addOption(vendor_opts);
2317 static_cast<void>(vendor_ids.insert(vendor_id));
2337 if (!subnet || co_list.empty()) {
2343 set<uint32_t> vendor_ids;
2347 map<uint32_t, OptionVendorPtr> vendor_rsps;
2350 vendor_rsp = boost::dynamic_pointer_cast<OptionVendor>(opt.second);
2352 uint32_t vendor_id = vendor_rsp->getVendorId();
2353 vendor_rsps[vendor_id] = vendor_rsp;
2354 static_cast<void>(vendor_ids.insert(vendor_id));
2360 map<uint32_t, OptionVendorPtr> vendor_reqs;
2363 vendor_req = boost::dynamic_pointer_cast<OptionVendor>(opt.second);
2365 uint32_t vendor_id = vendor_req->getVendorId();
2366 vendor_reqs[vendor_id] = vendor_req;
2367 static_cast<void>(vendor_ids.insert(vendor_id));
2375 vendor_class = boost::dynamic_pointer_cast<OptionVendorClass>(opt.second);
2377 uint32_t vendor_id = vendor_class->getVendorId();
2378 static_cast<void>(vendor_ids.insert(vendor_id));
2384 if (vendor_ids.empty()) {
2388 map<uint32_t, set<uint8_t> > requested_opts;
2402 oro = boost::dynamic_pointer_cast<OptionUint8Array>(oro_generic);
2405 set<uint8_t> oro_req_opts;
2406 for (uint8_t code : oro->getValues()) {
2407 static_cast<void>(oro_req_opts.insert(code));
2413 const auto& cclasses = query->getClasses();
2414 for (uint32_t vendor_id : vendor_ids) {
2416 std::set<uint8_t> cancelled_opts;
2420 for (
auto const& copts : co_list) {
2429 BOOST_FOREACH(
auto const& desc, prange) {
2432 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2433 static_cast<void>(requested_opts[vendor_id].insert(code));
2440 BOOST_FOREACH(
auto const& desc, crange) {
2443 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2444 static_cast<void>(cancelled_opts.insert(code));
2454 if (requested_opts[vendor_id].empty()) {
2462 if (vendor_rsps.count(vendor_id) > 0) {
2463 vendor_rsp = vendor_rsps[vendor_id];
2471 for (uint8_t opt : requested_opts[vendor_id]) {
2472 if (cancelled_opts.count(opt) > 0) {
2475 if (!vendor_rsp->getOption(opt)) {
2476 for (
auto const& copts : co_list) {
2479 vendor_rsp->addOption(desc.
option_);
2489 if (added && (vendor_rsps.count(vendor_id) == 0)) {
2490 resp->Pkt::addOption(vendor_rsp);
2499 static const std::vector<uint16_t> required_options = {
2513 if (co_list.empty()) {
2518 const auto& cclasses = ex.
getQuery()->getClasses();
2522 for (
auto const& required : required_options) {
2523 OptionPtr opt = resp->getOption(required);
2526 for (
auto const& copts : co_list) {
2529 resp->addOption(desc.
option_);
2549 .arg(query->getLabel());
2550 processClientFqdnOption(ex);
2555 .arg(query->getLabel());
2556 processHostnameOption(ex);
2562 std::string hostname;
2563 bool fqdn_fwd =
false;
2564 bool fqdn_rev =
false;
2567 fqdn = boost::dynamic_pointer_cast<Option4ClientFqdn>(resp->getOption(
DHO_FQDN));
2569 hostname = fqdn->getDomainName();
2572 opt_hostname = boost::dynamic_pointer_cast<OptionString>
2576 hostname = opt_hostname->getValue();
2581 if (hostname ==
".") {
2587 if (ex.
getContext()->getDdnsParams()->getEnableUpdates()) {
2607 callout_handle->setArgument(
"query4", query);
2608 callout_handle->setArgument(
"response4", resp);
2609 callout_handle->setArgument(
"subnet4", subnet);
2610 callout_handle->setArgument(
"hostname", hostname);
2611 callout_handle->setArgument(
"fwd-update", fqdn_fwd);
2612 callout_handle->setArgument(
"rev-update", fqdn_rev);
2613 callout_handle->setArgument(
"ddns-params", ex.
getContext()->getDdnsParams());
2619 string hook_hostname;
2620 bool hook_fqdn_fwd =
false;
2621 bool hook_fqdn_rev =
false;
2622 callout_handle->getArgument(
"hostname", hook_hostname);
2623 callout_handle->getArgument(
"fwd-update", hook_fqdn_fwd);
2624 callout_handle->getArgument(
"rev-update", hook_fqdn_rev);
2628 if ((hostname != hook_hostname) || (fqdn_fwd != hook_fqdn_fwd) ||
2629 (fqdn_rev != hook_fqdn_rev)) {
2631 .arg(hostname).arg(hook_hostname).arg(fqdn_fwd).arg(hook_fqdn_fwd)
2632 .arg(fqdn_rev).arg(hook_fqdn_rev);
2633 hostname = hook_hostname;
2634 fqdn_fwd = hook_fqdn_fwd;
2635 fqdn_rev = hook_fqdn_rev;
2639 OptionStringPtr hostname_opt = boost::dynamic_pointer_cast<OptionString>
2642 hostname_opt->setValue(hook_hostname);
2647 fqdn = boost::dynamic_pointer_cast<Option4ClientFqdn>(resp->getOption(
DHO_FQDN));
2659 ctx->fwd_dns_update_ = fqdn_fwd;
2660 ctx->rev_dns_update_ = fqdn_rev;
2661 ctx->hostname_ = hostname;
2686 .arg(fqdn->toText());
2702 !ex.
getContext()->currentHost()->getHostname().empty()) {
2728 .arg(fqdn_resp->
toText());
2738 OptionStringPtr opt_hostname = boost::dynamic_pointer_cast<OptionString>
2744 .arg(opt_hostname->getValue());
2752 if (ctx->currentHost() && !ctx->currentHost()->getHostname().empty()) {
2754 std::string hostname = d2_mgr.
qualifyName(ctx->currentHost()->getHostname(),
2757 boost::algorithm::to_lower(hostname);
2775 ex.
getContext()->getDdnsParams()->getReplaceClientNameMode();
2778 if (!opt_hostname) {
2798 .arg(opt_hostname->getValue());
2801 unsigned int label_count;
2807 }
catch (
const std::exception& exc) {
2818 if (label_count == 0) {
2836 || label_count < 2) {
2850 ex.
getContext()->getDdnsParams()->getHostnameSanitizer();
2853 hostname = sanitizer->scrub(hostname);
2857 boost::algorithm::to_lower(hostname);
2859 if (label_count == 2) {
2867 opt_hostname_resp.reset(
2878 .arg(opt_hostname_resp->getValue());
2888 "NULL lease specified when creating NameChangeRequest");
2896 if ((lease->reuseable_valid_lft_ == 0) &&
2898 !lease->hasIdenticalFqdn(*old_lease))) {
2916 while (current_subnet) {
2922 subnet = current_subnet;
2926 current_subnet = current_subnet->getNextSubnet(subnet, client_classes);
2930 subnet->getSharedNetwork(network);
2962 bool fake_allocation = (query->getType() ==
DHCPDISCOVER);
2968 auto const& requested_opts = option_prl->getValues();
2969 if ((std::find(requested_opts.cbegin(), requested_opts.cend(),
2973 ctx->subnet_ = subnet;
2975 if (!fake_allocation) {
2976 resp->setCiaddr(query->getCiaddr());
2992 if (opt_requested_address) {
2993 hint = opt_requested_address->readAddress();
2995 }
else if (!query->getCiaddr().isV4Zero()) {
2996 hint = query->getCiaddr();
3003 auto authoritative =
false;
3009 auto init_reboot = (!fake_allocation && !opt_serverid && opt_requested_address);
3012 .arg(query->getLabel())
3017 authoritative = subnet->getAuthoritative();
3023 authoritative = flag->boolValue();
3026 }
else if (fake_allocation) {
3028 .arg(query->getLabel())
3032 .arg(query->getLabel())
3040 if (!subnet && (!init_reboot || authoritative)) {
3047 .arg(query->getLabel())
3048 .arg(query->getRemoteAddr().toText())
3049 .arg(query->getName());
3067 auto const& classes = query->getClasses();
3077 if (original_subnet && client_id) {
3081 if (!leases_client_id.empty()) {
3087 for (
auto const& l : leases_client_id) {
3088 if (l->subnet_id_ == s->getID()) {
3098 s = s->getNextSubnet(original_subnet, classes);
3106 if (original_subnet && !lease && hwaddr) {
3110 if (!leases_hwaddr.empty()) {
3115 for (
auto const& l : leases_hwaddr) {
3116 if (l->subnet_id_ == s->getID()) {
3126 s = s->getNextSubnet(original_subnet, classes);
3135 bool known_client = lease && lease->belongsToClient(hwaddr, client_id);
3136 if (!authoritative && !known_client) {
3139 .arg(query->getLabel())
3148 if ((known_client && (lease->addr_ != hint)) ||
3149 (!known_client && authoritative) ||
3150 (!original_subnet)) {
3153 .arg(query->getLabel())
3165 ctx->requested_address_ = hint;
3166 ctx->fake_allocation_ = fake_allocation;
3167 ctx->callout_handle_ = callout_handle;
3183 bool client_name_changed =
false;
3187 if (subnet && ctx->subnet_ && subnet->getID() != ctx->subnet_->getID()) {
3189 subnet->getSharedNetwork(network);
3191 .arg(query->getLabel())
3192 .arg(subnet->toText())
3193 .arg(ctx->subnet_->toText())
3194 .arg(network ? network->getName() :
"<no network?>");
3196 subnet = ctx->subnet_;
3211 ctx->hostname_ =
"";
3212 ctx->fwd_dns_update_ =
false;
3213 ctx->rev_dns_update_ =
false;
3220 if ((lease->hostname_ != ctx->hostname_) ||
3221 (lease->fqdn_fwd_ != ctx->fwd_dns_update_) ||
3222 (lease->fqdn_rev_ != ctx->rev_dns_update_)) {
3223 lease->hostname_ = ctx->hostname_;
3224 lease->fqdn_fwd_ = ctx->fwd_dns_update_;
3225 lease->fqdn_rev_ = ctx->rev_dns_update_;
3226 client_name_changed =
true;
3234 if (fake_allocation) {
3236 .arg(query->getLabel())
3237 .arg(lease->addr_.toText());
3240 .arg(query->getLabel())
3241 .arg(lease->addr_.toText())
3249 if (!ctx->subnet_->getMatchClientId()) {
3251 .arg(ctx->query_->getLabel())
3252 .arg(ctx->subnet_->getID());
3255 resp->setYiaddr(lease->addr_);
3261 if (!fake_allocation) {
3266 resp->setCiaddr(query->getCiaddr());
3275 if (lease->reuseable_valid_lft_ > 0) {
3276 lease->valid_lft_ = lease->reuseable_valid_lft_;
3278 .arg(query->getLabel())
3279 .arg(lease->addr_.toText())
3296 resp->addOption(opt);
3299 resp->addOption(getNetmaskOption(subnet));
3305 if (!fake_allocation) {
3311 .arg(query->getLabel())
3319 if (ctx->unknown_requested_addr_) {
3331 s = s->getNextSubnet(original_subnet);
3339 .arg(query->getLabel())
3340 .arg(query->getCiaddr().toText())
3341 .arg(opt_requested_address ?
3342 opt_requested_address->readAddress().toText() :
"(no address)");
3350 .arg(query->getLabel())
3351 .arg(query->getCiaddr().toText())
3352 .arg(opt_requested_address ?
3353 opt_requested_address->readAddress().toText() :
"(no address)");
3365 const Pkt4Ptr& query,
const Pkt4Ptr& resp,
bool client_name_changed) {
3374 opt_hostname = boost::dynamic_pointer_cast<OptionString>(resp->getOption(
DHO_HOST_NAME));
3375 if (!opt_hostname) {
3382 if (lease->hostname_.empty()) {
3389 .
generateFqdn(lease->addr_, *(ctx->getDdnsParams()),
static_cast<bool>(fqdn));
3392 .arg(query->getLabel())
3393 .arg(lease->hostname_);
3395 client_name_changed =
true;
3398 if (client_name_changed) {
3404 if (!ctx->fake_allocation_ || (ctx->offer_lft_ > 0)) {
3406 lease->reuseable_valid_lft_ = 0;
3419 opt_hostname->setValue(lease->hostname_);
3423 .arg(query->getLabel())
3424 .arg(lease->hostname_)
3434 uint32_t t2_time = 0;
3436 if (!subnet->getT2().unspecified()) {
3437 t2_time = subnet->getT2();
3438 }
else if (subnet->getCalculateTeeTimes()) {
3440 t2_time =
static_cast<uint32_t
>(round(subnet->getT2Percent() * (lease->valid_lft_)));
3445 uint32_t timer_ceiling = lease->valid_lft_;
3446 if (t2_time > 0 && t2_time < timer_ceiling) {
3448 resp->addOption(t2);
3450 timer_ceiling = t2_time;
3453 uint32_t t1_time = 0;
3455 if (!subnet->getT1().unspecified()) {
3456 t1_time = subnet->getT1();
3457 }
else if (subnet->getCalculateTeeTimes()) {
3459 t1_time =
static_cast<uint32_t
>(round(subnet->getT1Percent() * (lease->valid_lft_)));
3464 if (t1_time > 0 && t1_time < timer_ceiling) {
3466 resp->addOption(t1);
3478 return (query->getRemotePort());
3506 }
else if (((query->getType() ==
DHCPINFORM) &&
3507 ((!query->getCiaddr().isV4Zero()) ||
3508 (!query->isRelayed() && !query->getRemoteAddr().isV4Zero()))) ||
3509 ((query->getType() !=
DHCPINFORM) && !query->isRelayed())) {
3510 response->setRemotePort(DHCP4_CLIENT_PORT);
3515 response->setRemotePort(relay_port ? relay_port : DHCP4_SERVER_PORT);
3519 if (query->isRelayed() &&
3525 response->resetIndex();
3527 response->setIface(query->getIface());
3531 IOAddress local_addr = query->getLocalAddr();
3540 if (local_addr.
isV4Bcast() || query->isDhcp4o6()) {
3551 response->setLocalAddr(local_addr);
3560 response->setIndex(query->getIndex());
3561 response->setIface(query->getIface());
3567 response->setLocalPort(DHCP4_SERVER_PORT);
3579 if (query->isDhcp4o6()) {
3580 response->setRemoteAddr(query->getRemoteAddr());
3592 if (!query->getCiaddr().isV4Zero()) {
3593 response->setRemoteAddr(query->getCiaddr());
3600 }
else if (query->isRelayed()) {
3601 response->setRemoteAddr(query->getGiaddr());
3602 response->setFlags(response->getFlags() | BOOTP_BROADCAST);
3607 response->setRemoteAddr(query->getRemoteAddr());
3614 if (query->isRelayed()) {
3623 query->getCiaddr().isV4Zero()) {
3624 response->setFlags(BOOTP_BROADCAST);
3626 response->setRemoteAddr(query->getGiaddr());
3630 }
else if (!query->getCiaddr().isV4Zero()) {
3631 response->setRemoteAddr(query->getCiaddr());
3636 }
else if (response->getType() ==
DHCPNAK) {
3640 }
else if (!response->getYiaddr().isV4Zero()) {
3655 response->setRemoteAddr(response ->getYiaddr());
3663 response->setRemoteAddr(query->getRemoteAddr());
3668 response->setRemoteAddr(query->getRemoteAddr());
3680 IOAddress subnet_next_server = subnet->getSiaddr();
3681 if (!subnet_next_server.
isV4Zero()) {
3682 response->setSiaddr(subnet_next_server);
3685 const string& sname = subnet->getSname();
3686 if (!sname.empty()) {
3692 response->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
3696 const string& filename = subnet->getFilename();
3697 if (!filename.empty()) {
3703 response->setFile(
reinterpret_cast<const uint8_t*
>(filename.c_str()),
3711 if (!classes.
empty()) {
3724 size_t found_cnt = 0;
3725 for (
auto const& name : classes) {
3727 if (found_cnt >= 3) {
3741 next_server = cl->getNextServer();
3743 response->setSiaddr(next_server);
3748 if (sname.empty()) {
3749 sname = cl->getSname();
3750 if (!sname.empty()) {
3756 response->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
3762 if (filename.empty()) {
3763 filename = cl->getFilename();
3764 if (!filename.empty()) {
3770 response->setFile(
reinterpret_cast<const uint8_t*
>(filename.c_str()),
3793tuple<bool, uint32_t>
3794Dhcpv4Srv::parkingLimitExceeded(
string const& hook_label) {
3796 uint32_t parked_packet_limit(0);
3800 parked_packet_limit = ppl->intValue();
3803 if (parked_packet_limit) {
3807 if (parking_lot && parked_packet_limit <= parking_lot->size()) {
3808 return make_tuple(
true, parked_packet_limit);
3811 return make_tuple(
false, parked_packet_limit);
3849 .arg(discover->getLabel())
3850 .arg(discover->getName())
3851 .arg(discover->getClasses().toText());
3860 .arg(discover->getLabel());
3919 }
else if (request->inClass(
"BOOTP")) {
3921 response->addClass(
"BOOTP");
3935 .arg(request->getLabel())
3936 .arg(request->getName())
3937 .arg(request->getClasses().toText());
3946 .arg(request->getLabel());
3987 OptionPtr opt = release->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
3999 .arg(release->getLabel())
4000 .arg(release->getCiaddr().toText());
4004 if (!lease->belongsToClient(release->getHWAddr(), client_id)) {
4006 .arg(release->getLabel())
4007 .arg(release->getCiaddr().toText());
4027 callout_handle->setArgument(
"query4", release);
4030 callout_handle->setArgument(
"lease4", lease);
4044 .arg(release->getLabel());
4052 bool success =
false;
4053 bool expired =
false;
4057 if (expiration_cfg->getFlushReclaimedTimerWaitTime() &&
4058 expiration_cfg->getHoldReclaimedTime() &&
4061 lease->valid_lft_ = 0;
4077 context->old_lease_ = lease;
4081 .arg(release->getLabel())
4082 .arg(lease->addr_.toText());
4086 .arg(release->getLabel())
4087 .arg(lease->addr_.toText());
4090 .arg(release->getLabel())
4091 .arg(lease->addr_.toText());
4100 static_cast<int64_t
>(-1));
4104 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4109 static_cast<int64_t
>(-1));
4116 .arg(release->getLabel())
4117 .arg(lease->addr_.toText());
4122 .arg(release->getLabel())
4123 .arg(release->getCiaddr())
4136 if (!opt_requested_address) {
4139 " in DHCPDECLINE sent from " << decline->getLabel());
4141 IOAddress addr(opt_requested_address->readAddress());
4159 .arg(addr.
toText()).arg(decline->getLabel());
4164 OptionPtr opt_clientid = decline->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
4167 client_id.reset(
new ClientId(opt_clientid->getData()));
4176 !lease->belongsToClient(decline->getHWAddr(), client_id)) {
4179 string client_hw = decline->getHWAddr() ?
4180 decline->getHWAddr()->toText(
false) :
"(none)";
4181 string lease_hw = lease->hwaddr_ ?
4182 lease->hwaddr_->toText(
false) :
"(none)";
4185 string client_id_txt = client_id ? client_id->toText() :
"(none)";
4186 string lease_id_txt = lease->client_id_ ?
4187 lease->client_id_->toText() :
"(none)";
4191 .arg(addr.
toText()).arg(decline->getLabel())
4192 .arg(client_hw).arg(lease_hw).arg(client_id_txt).arg(lease_id_txt);
4222 callout_handle->setArgument(
"query4", decline);
4225 callout_handle->setArgument(
"lease4", lease);
4236 .arg(decline->getLabel()).arg(lease->addr_.toText());
4241 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4255 .arg(decline->getLabel())
4256 .arg(lease->addr_.toText())
4270 static_cast<int64_t
>(1));
4274 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4279 static_cast<int64_t
>(1));
4296 context->new_lease_ = lease;
4299 .arg(decline->getLabel()).arg(lease->valid_lft_);
4306 .arg(query->getLabel())
4307 .arg(lease->addr_.toText())
4308 .arg(lease->valid_lft_);
4316 .arg(query->getLabel())
4317 .arg(lease->addr_.toText());
4333 lease_exists =
false;
4337 .arg(query->getLabel())
4338 .arg(lease->addr_.toText());
4343 if (!lease_exists) {
4348 .arg(query->getLabel())
4349 .arg(lease->addr_.toText());
4366 static_cast<int64_t
>(1));
4368 if (!lease_exists) {
4371 static_cast<int64_t
>(1));
4376 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4381 static_cast<int64_t
>(1));
4382 if (!lease_exists) {
4386 static_cast<int64_t
>(1));
4393 if (!lease_exists) {
4407 callout_handle->setArgument(
"query4", query);
4410 callout_handle->setArgument(
"lease4", lease);
4448 .arg(inform->getLabel())
4449 .arg(inform->getName())
4450 .arg(inform->getClasses().toText());
4467 if (ack->getRemoteAddr() != inform->getGiaddr()) {
4469 .arg(inform->getLabel())
4470 .arg(ack->getRemoteAddr())
4471 .arg(ack->getIface());
4485 if (query->getCiaddr().isV4Zero() || !query->getGiaddr().isV4Zero()) {
4502 if (query->inClass(
"STASH_AGENT_OPTIONS")) {
4506 if (!lease || lease->expired()) {
4510 if (!user_context || (user_context->getType() !=
Element::map)) {
4518 if (!relay_agent_info) {
4523 relay_agent_info = relay_agent_info->get(
"sub-options");
4524 if (!relay_agent_info) {
4533 OptionPtr opt_clientid = query->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
4535 client_id.reset(
new ClientId(opt_clientid->getData()));
4537 if (!lease->belongsToClient(query->getHWAddr(), client_id)) {
4541 string rai_hex = relay_agent_info->stringValue();
4542 if (rai_hex.empty()) {
4545 vector<uint8_t> rai_data;
4550 if (!rai || rai->getOptions().empty()) {
4557 query->addOption(rai);
4558 query->addClass(
"STASH_AGENT_OPTIONS");
4561 .arg(query->getLabel())
4562 .arg(query->getCiaddr())
4563 .arg(rai->toText());
4577 .arg(query->getLabel())
4578 .arg(query->getIface());
4586 .arg(query->getLabel())
4587 .arg(query->getIface());
4597 if (pkt->isRelayed()) {
4602 if (pkt->isDhcp4o6()) {
4611 if (pkt->getRemoteAddr().isV4Zero() &&
4612 pkt->getCiaddr().isV4Zero()) {
4623 bool result = (!pkt->getLocalAddr().isV4Bcast() ||
4638 type = query->getType();
4642 .arg(query->getLabel())
4643 .arg(query->getIface());
4667 .arg(query->getLabel());
4674 .arg(query->getLabel())
4679 .arg(query->getLabel())
4706 boost::dynamic_pointer_cast<OptionCustom>(option);
4709 if (!option_custom) {
4717 if (option_custom->getDataFieldsNum() != 1) {
4723 IOAddress server_id = option_custom->readAddress();
4724 if (!server_id.
isV4()) {
4733 if (rai_suboption && (server_id.
toBytes() == rai_suboption->toBinary())) {
4740 if (cfg->getIgnoreServerIdentifier()) {
4778 if (cfg_subnets->hasSubnetWithServerId(server_id)) {
4785 if (cfg_networks->hasNetworkWithServerId(server_id)) {
4791 for (
auto const& cclass : classes) {
4794 getClientClassDictionary()->findClass(cclass);
4799 if (ccdef->getCfgOption()->empty()) {
4804 OptionCustomPtr context_opt_server_id = boost::dynamic_pointer_cast<OptionCustom>
4806 if (context_opt_server_id && (context_opt_server_id->readAddress() == server_id)) {
4814 OptionCustomPtr opt_server_id = boost::dynamic_pointer_cast<OptionCustom>
4817 return (opt_server_id && (opt_server_id->readAddress() == server_id));
4822 switch (query->getType()) {
4857 <<
" received in message "
4858 << query->getName());
4865 " received in message "
4866 << query->getName());
4876 if (query->getHWAddr() && !query->getHWAddr()->hwaddr_.empty()) {
4882 OptionPtr client_id = query->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
4885 if (!client_id || client_id->len() == client_id->getHeaderLen()) {
4887 " provided in message "
4888 << query->getName());
4909 addr = resp->getYiaddr();
4914 const ClientClasses& pool_to_add = pool->getAdditionalClasses();
4915 for (
auto const& cclass : pool_to_add) {
4922 const ClientClasses& to_add = subnet->getAdditionalClasses();
4923 for (
auto const& cclass : to_add) {
4929 subnet->getSharedNetwork(network);
4931 const ClientClasses& net_to_add = network->getAdditionalClasses();
4932 for (
auto const& cclass : net_to_add) {
4942 for (
auto const& cclass : classes) {
4957 query->addClass(cclass);
4965 .arg(query->getLabel())
4967 .arg(status ?
"true" :
"false");
4970 query->addClass(cclass);
4974 .arg(query->getLabel())
4984 for (
auto const& code : query->getDeferredOptions()) {
4988 for (
auto const& cclass : classes) {
4992 getClientClassDictionary()->findClass(cclass);
4998 if (!ccdef->getCfgOptionDef()) {
5028 .arg(query->getLabel())
5037 opt = def->optionFactory(
Option::V4, code, buf);
5038 }
catch (
const std::exception& e) {
5042 .arg(query->getLabel())
5047 while (query->delOption(code)) {
5051 query->addOption(opt);
5063 this, ph::_1, ph::_2));
5082 arg(result).arg((ncr ? ncr->toText() :
" NULL "));
5091 std::stringstream tmp;
5095 tmp <<
" (" << EXTENDED_VERSION <<
")" << endl;
5096 tmp <<
"premium: " << PREMIUM_EXTENDED_VERSION << endl;
5097 tmp <<
"linked with:" << endl;
5102 tmp << endl <<
"lease backends:";
5104 tmp << endl <<
"- " <<
version;
5109 tmp << endl <<
"host backends:";
5111 tmp << endl <<
"- " <<
version;
5124 string stat_name =
"pkt4-unknown-received";
5126 switch (query->getType()) {
5128 stat_name =
"pkt4-discover-received";
5132 stat_name =
"pkt4-offer-received";
5135 stat_name =
"pkt4-request-received";
5139 stat_name =
"pkt4-ack-received";
5143 stat_name =
"pkt4-nak-received";
5146 stat_name =
"pkt4-release-received";
5149 stat_name =
"pkt4-decline-received";
5152 stat_name =
"pkt4-inform-received";
5166 static_cast<int64_t
>(1));
5172 static_cast<int64_t
>(1));
5176 switch (response->getType()) {
5178 stat_name =
"pkt4-offer-sent";
5181 stat_name =
"pkt4-ack-sent";
5184 stat_name =
"pkt4-nak-sent";
5192 static_cast<int64_t
>(1));
5196 return (
Hooks.hook_index_buffer4_receive_);
5200 return (
Hooks.hook_index_pkt4_receive_);
5204 return (
Hooks.hook_index_subnet4_select_);
5208 return (
Hooks.hook_index_lease4_release_);
5212 return (
Hooks.hook_index_pkt4_send_);
5216 return (
Hooks.hook_index_buffer4_send_);
5220 return (
Hooks.hook_index_lease4_decline_);
5230 char const*
const rotate(getenv(
"KEA_DHCP4_FUZZING_ROTATE_PORT"));
5234 while (!locker.
lock()) {
5235 this_thread::sleep_for(1s);
5238 port_file.open(
"/tmp/port4.txt", ios::in);
5241 getline(port_file, line);
5253 port_file.open(
"/tmp/port4.txt", ios::out | ios::trunc);
5254 port_file << to_string(port) << endl;
5264 static std::list<std::list<std::string>>
const list({
5265 {
"config-control",
"config-databases",
"[]"},
5266 {
"hooks-libraries",
"[]",
"parameters",
"*"},
5268 {
"hosts-databases",
"[]"},
int version()
returns Kea hooks version.
Defines elements for storing the names of client classes.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown when an unexpected error condition occurs.
The IOAddress class represents an IP addresses (version agnostic)
static const IOAddress & IPV4_ZERO_ADDRESS()
Returns an address set to all zeros.
bool isV4Zero() const
Convenience function to check if it is an IPv4 zero address.
std::string toText() const
Convert the address to a string.
static const IOAddress & IPV4_BCAST_ADDRESS()
Returns a "255.255.255.255" broadcast address.
uint32_t toUint32() const
Converts IPv4 address to uint32_t.
bool isV4() const
Convenience function to check for an IPv4 address.