8#include <kea_version.h>
114#include <boost/foreach.hpp>
115#include <boost/pointer_cast.hpp>
116#include <boost/range/adaptor/reversed.hpp>
117#include <boost/shared_ptr.hpp>
131namespace ph = std::placeholders;
137 int hook_index_buffer4_receive_;
138 int hook_index_pkt4_receive_;
139 int hook_index_subnet4_select_;
140 int hook_index_leases4_committed_;
141 int hook_index_lease4_release_;
142 int hook_index_pkt4_send_;
143 int hook_index_buffer4_send_;
144 int hook_index_lease4_decline_;
145 int hook_index_host4_identifier_;
146 int hook_index_ddns4_update_;
147 int hook_index_lease4_offer_;
148 int hook_index_lease4_server_decline_;
169std::set<std::string> dhcp4_statistics = {
171 "pkt4-discover-received",
172 "pkt4-offer-received",
173 "pkt4-request-received",
176 "pkt4-release-received",
177 "pkt4-decline-received",
178 "pkt4-inform-received",
179 "pkt4-lease-query-received",
180 "pkt4-unknown-received",
185 "pkt4-lease-query-response-unassigned-sent",
186 "pkt4-lease-query-response-unknown-sent",
187 "pkt4-lease-query-response-active-sent",
188 "pkt4-service-disabled",
192 "pkt4-rfc-violation",
193 "pkt4-admin-filtered",
195 "pkt4-processing-failed",
196 "pkt4-limit-exceeded",
198 "v4-allocation-fail",
199 "v4-allocation-fail-shared-network",
200 "v4-allocation-fail-subnet",
201 "v4-allocation-fail-no-pools",
202 "v4-allocation-fail-classes",
203 "v4-reservation-conflicts",
223 : alloc_engine_(alloc_engine), query_(query), resp_(),
224 context_(context), ipv6_only_preferred_(false) {
226 if (!alloc_engine_) {
228 " when creating an instance of the Dhcpv4Exchange");
233 " creating an instance of the Dhcpv4Exchange");
242 context_->subnet_ = subnet;
248 if (subnet && !context_->early_global_reservations_lookup_) {
251 context_->clientid_.reset(
new ClientId(opt_clientid->getData()));
257 if (subnet->getReservationsInSubnet() ||
258 subnet->getReservationsGlobal()) {
261 if (!context_->early_global_reservations_lookup_) {
266 alloc_engine->findReservation(*context_);
269 subnet->getSharedNetwork(sn);
279 auto global_host = context_->globalHost();
280 auto current_host = context_->currentHost();
281 if ((!context_->early_global_reservations_lookup_ &&
282 global_host && !global_host->getClientClasses4().empty()) ||
283 (!sn && current_host && !current_host->getClientClasses4().empty())) {
304 if (!context_->hosts_.empty()) {
305 query->addClass(
"KNOWN");
307 .arg(query->getLabel())
310 query->addClass(
"UNKNOWN");
312 .arg(query->getLabel())
321 .arg(query_->getLabel())
325 if (query_->inClass(
"DROP")) {
327 .arg(query_->getHWAddrLabel())
328 .arg(query_->toText());
330 static_cast<int64_t
>(1));
332 static_cast<int64_t
>(1));
339 uint8_t resp_type = 0;
353 resp_.reset(
new Pkt4(resp_type,
getQuery()->getTransid()));
355 copyDefaultOptions();
369 const Pkt6Ptr& query6 = query->getPkt6();
373 if (!query6->relay_info_.empty()) {
374 resp6->copyRelayInfo(query6);
377 resp6->setIface(query6->getIface());
378 resp6->setIndex(query6->getIndex());
379 resp6->setRemoteAddr(query6->getRemoteAddr());
380 resp6->setRemotePort(query6->getRemotePort());
381 resp_.reset(
new Pkt4o6(resp_, resp6));
385Dhcpv4Exchange::copyDefaultFields() {
386 resp_->setIface(query_->getIface());
387 resp_->setIndex(query_->getIndex());
394 resp_->setCiaddr(query_->getCiaddr());
398 resp_->setHops(query_->getHops());
401 resp_->setHWAddr(query_->getHWAddr());
404 resp_->setGiaddr(query_->getGiaddr());
413 HWAddrPtr src_hw_addr = query_->getLocalHWAddr();
415 resp_->setLocalHWAddr(src_hw_addr);
417 HWAddrPtr dst_hw_addr = query_->getRemoteHWAddr();
419 resp_->setRemoteHWAddr(dst_hw_addr);
423 resp_->setFlags(query_->getFlags());
427Dhcpv4Exchange::copyDefaultOptions() {
432 if (client_id && echo) {
433 resp_->addOption(client_id);
446 resp_->addOption(subnet_sel);
459 sao->boolValue() && query_->inClass(
"STASH_AGENT_OPTIONS")) {
462 resp_->addOption(rai);
472 for (
auto const& id_type : cfg->getIdentifierTypes()) {
475 if (context->hwaddr_ && !context->hwaddr_->hwaddr_.empty()) {
476 context->addHostIdentifier(id_type, context->hwaddr_->hwaddr_);
481 if (context->clientid_) {
482 const std::vector<uint8_t>& vec = context->clientid_->getClientId();
487 if ((vec[0] == CLIENT_ID_OPTION_TYPE_DUID) && (vec.size() > 5)) {
489 context->addHostIdentifier(id_type,
490 std::vector<uint8_t>(vec.begin() + 5,
502 if (circuit_id_opt) {
503 const OptionBuffer& circuit_id_vec = circuit_id_opt->getData();
504 if (!circuit_id_vec.empty()) {
505 context->addHostIdentifier(id_type, circuit_id_vec);
513 if (context->clientid_) {
514 const std::vector<uint8_t>& vec = context->clientid_->getClientId();
516 context->addHostIdentifier(id_type, vec);
529 std::vector<uint8_t> id;
538 callout_handle->setArgument(
"query4", context->query_);
539 callout_handle->setArgument(
"id_type", type);
540 callout_handle->setArgument(
"id_value",
id);
546 callout_handle->getArgument(
"id_type", type);
547 callout_handle->getArgument(
"id_value",
id);
553 .arg(context->query_->getLabel())
556 context->addHostIdentifier(type,
id);
571 for (
auto const& def : *defs_ptr) {
575 if (def->getMatchExpr()) {
576 query->classes_.erase(def->getName());
583 if (context->currentHost() && context->query_) {
584 const ClientClasses& classes = context->currentHost()->getClientClasses4();
585 for (
auto const& cclass : classes) {
586 context->query_->addClass(cclass);
593 if (context_->subnet_) {
595 context_->subnet_->getSharedNetwork(shared_network);
596 if (shared_network) {
598 if (host && (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL)) {
610 if (!host->getNextServer().isV4Zero()) {
611 resp_->setSiaddr(host->getNextServer());
614 std::string sname = host->getServerHostname();
615 if (!sname.empty()) {
616 resp_->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
620 std::string bootfile = host->getBootFileName();
621 if (!bootfile.empty()) {
622 resp_->setFile(
reinterpret_cast<const uint8_t*
>(bootfile.c_str()),
630 boost::shared_ptr<OptionString> vendor_class =
642 pkt->addClass(
"ALL");
656 for (
auto const& it : *defs_ptr) {
664 if (it->getAdditional()) {
668 if (it->getDependOnKnown() != depend_on_known) {
671 it->test(pkt, expr_ptr);
678 const bool use_bcast,
const bool direct_response_desired)
684 test_send_responses_to_source_(false) {
686 const char* env = std::getenv(
"KEA_TEST_SEND_RESPONSES_TO_SOURCE");
689 test_send_responses_to_source_ =
true;
717 }
catch (
const std::exception &e) {
733 for (
auto const& it : dhcp4_statistics) {
735 stats_mgr.
setValue(it,
static_cast<int64_t
>(0));
745 }
catch (
const std::exception& ex) {
752 }
catch (
const std::exception& ex) {
771 if (!names.empty()) {
773 for (
size_t i = 1; i < names.size(); ++i) {
774 msg += std::string(
", ") + names[i];
780 io_service_->stopAndPoll();
792 if (query->isDhcp4o6()) {
801 subnet = cfgmgr.
getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
812 shared_ptr<ScopedCalloutHandleState> callout_handle_state(
813 std::make_shared<ScopedCalloutHandleState>(callout_handle));
819 callout_handle->setArgument(
"query4", query);
820 callout_handle->setArgument(
"subnet4", subnet);
821 callout_handle->setArgument(
"subnet4collection",
823 getCfgSubnets4()->getAll());
825 auto const tpl(parkingLimitExceeded(
"subnet4_select"));
826 bool const exceeded(
get<0>(tpl));
828 uint32_t
const limit(
get<1>(tpl));
833 .arg(query->getLabel());
835 static_cast<int64_t
>(1));
837 static_cast<int64_t
>(1));
843 "subnet4_select", query, [
this, query, allow_answer_park, callout_handle_state]() {
845 boost::shared_ptr<function<void()>> callback(
846 boost::make_shared<function<
void()>>(
847 [
this, query, allow_answer_park]()
mutable {
850 callout_handle_state->on_completion_ = [callback]() {
873 .arg(query->getLabel());
886 .arg(query->getLabel());
895 .arg(query->getLabel());
901 callout_handle->getArgument(
"subnet4", subnet);
907 .arg(query->getLabel())
908 .arg(subnet->getID());
912 .arg(query->getLabel())
913 .arg(subnet->toText());
918 .arg(query->getLabel());
926 bool allow_answer_park) {
930 selector.
ciaddr_ = query->getCiaddr();
931 selector.
giaddr_ = query->getGiaddr();
942 Pkt4o6Ptr query4o6 = boost::dynamic_pointer_cast<Pkt4o6>(query);
946 const Pkt6Ptr& query6 = query4o6->getPkt6();
949 if (query6 && !query6->relay_info_.empty()) {
950 for (
auto const& relay : boost::adaptors::reverse(query6->relay_info_)) {
951 if (!relay.linkaddr_.isV6Zero() &&
952 !relay.linkaddr_.isV6LinkLocal()) {
965 OptionCustomPtr oc = boost::dynamic_pointer_cast<OptionCustom>(sbnsel);
972 subnet = cfgmgr.
getCurrentCfg()->getCfgSubnets4()->selectSubnet4o6(selector);
983 shared_ptr<ScopedCalloutHandleState> callout_handle_state(
984 std::make_shared<ScopedCalloutHandleState>(callout_handle));
990 callout_handle->setArgument(
"query4", query);
991 callout_handle->setArgument(
"subnet4", subnet);
992 callout_handle->setArgument(
"subnet4collection",
994 getCfgSubnets4()->getAll());
996 auto const tpl(parkingLimitExceeded(
"subnet4_select"));
997 bool const exceeded(
get<0>(tpl));
999 uint32_t
const limit(
get<1>(tpl));
1004 .arg(query->getLabel());
1006 static_cast<int64_t
>(1));
1008 static_cast<int64_t
>(1));
1014 "subnet4_select", query, [
this, query, allow_answer_park, callout_handle_state]() {
1016 boost::shared_ptr<function<void()>> callback(
1017 boost::make_shared<function<
void()>>(
1018 [
this, query, allow_answer_park]()
mutable {
1021 callout_handle_state->on_completion_ = [callback]() {
1044 .arg(query->getLabel());
1057 .arg(query->getLabel());
1066 .arg(query->getLabel());
1072 callout_handle->getArgument(
"subnet4", subnet);
1079 .arg(query->getLabel())
1080 .arg(subnet->getID());
1085 .arg(query->getLabel())
1086 .arg(subnet->toText());
1091 .arg(query->getLabel());
1111 ctx->query_ = query;
1114 ctx->hwaddr_ = query->getHWAddr();
1128 ctx->early_global_reservations_lookup_ = egrl->boolValue();
1132 if (ctx->early_global_reservations_lookup_) {
1136 ctx->clientid_.reset(
new ClientId(opt_clientid->getData()));
1145 if (global_host && !global_host->getClientClasses4().empty()) {
1150 const ClientClasses& classes = global_host->getClientClasses4();
1151 for (
auto const& cclass : classes) {
1152 query->addClass(cclass);
1161 query->addClass(
"KNOWN");
1163 .arg(query->getLabel())
1170 if (query->inClass(
"DROP")) {
1173 .arg(query->getHWAddrLabel())
1174 .arg(query->toText());
1176 static_cast<int64_t
>(1));
1178 static_cast<int64_t
>(1));
1183 ctx->hosts_[SUBNET_ID_GLOBAL] = global_host;
1197 const char*
interface = getenv(
"KEA_AFL_INTERFACE");
1199 isc_throw(FuzzInitFail,
"no fuzzing interface has been set");
1203 const char* address = getenv(
"KEA_AFL_ADDRESS");
1205 isc_throw(FuzzInitFail,
"no fuzzing address has been set");
1213 while (__AFL_LOOP(fuzzer.maxLoopCount())) {
1225 }
catch (
const std::exception& e) {
1256 uint32_t timeout = 1;
1267 .arg(query->getRemoteAddr().toText())
1268 .arg(query->getRemotePort())
1269 .arg(query->getLocalAddr().toText())
1270 .arg(query->getLocalPort())
1271 .arg(query->getIface());
1278 static_cast<int64_t
>(1));
1294 }
catch (
const std::exception& e) {
1310 .arg(query->getLabel());
1313 static_cast<int64_t
>(1));
1315 static_cast<int64_t
>(1));
1319 query->addPktEvent(
"mt_queued");
1320 typedef function<void()> CallBack;
1321 boost::shared_ptr<CallBack> call_back =
1327 static_cast<int64_t
>(1));
1329 static_cast<int64_t
>(1));
1341 }
catch (
const std::exception& e) {
1343 .arg(query->getLabel())
1346 static_cast<int64_t
>(1));
1348 static_cast<int64_t
>(1));
1351 .arg(query->getLabel());
1353 static_cast<int64_t
>(1));
1355 static_cast<int64_t
>(1));
1373 query->addPktEvent(
"process_started");
1376 query->addClass(
"ALL");
1378 bool skip_unpack =
false;
1395 callout_handle->setArgument(
"query4", query);
1407 .arg(query->getRemoteAddr().toText())
1408 .arg(query->getLocalAddr().toText())
1409 .arg(query->getIface());
1423 .arg(query->getRemoteAddr().toText())
1424 .arg(query->getLocalAddr().toText())
1425 .arg(query->getIface());
1429 callout_handle->getArgument(
"query4", query);
1441 .arg(query->getRemoteAddr().toText())
1442 .arg(query->getLocalAddr().toText())
1443 .arg(query->getIface());
1450 .arg(query->getLabel())
1452 }
catch (
const std::exception& e) {
1455 .arg(query->getLabel())
1456 .arg(query->getRemoteAddr().toText())
1457 .arg(query->getLocalAddr().toText())
1458 .arg(query->getIface())
1460 .arg(query->getHWAddrLabel());
1464 static_cast<int64_t
>(1));
1466 static_cast<int64_t
>(1));
1473 .arg(query->getLabel());
1481 }
catch (
const std::exception&) {
1499 static_cast<int64_t
>(1));
1505 int type = query->getType();
1507 .arg(query->getLabel())
1508 .arg(query->getName())
1510 .arg(query->getRemoteAddr())
1511 .arg(query->getLocalAddr())
1512 .arg(query->getIface());
1514 .arg(query->getLabel())
1515 .arg(query->toText(
true));
1531 callout_handle->setArgument(
"query4", query);
1544 .arg(query->getLabel());
1550 callout_handle->getArgument(
"query4", query);
1558 if (query->inClass(
"DROP")) {
1560 .arg(query->getHWAddrLabel())
1561 .arg(query->toText());
1563 static_cast<int64_t
>(1));
1565 static_cast<int64_t
>(1));
1574 bool allow_answer_park) {
1583 }
catch (
const std::exception& e) {
1585 .arg(query->getLabel())
1588 static_cast<int64_t
>(1));
1590 static_cast<int64_t
>(1));
1593 .arg(query->getLabel());
1595 static_cast<int64_t
>(1));
1597 static_cast<int64_t
>(1));
1614 this, query, allow_answer_park));
1615 if (!client_handler.
tryLock(query, cont)) {
1626 bool rfc_violation =
false;
1635 ctx->subnet_ =
selectSubnet(query, drop, allow_answer_park);
1642 rfc_violation =
true;
1645 }
catch (
const std::exception& e) {
1655 .arg(query->getLabel())
1660 if (!rfc_violation) {
1662 static_cast<int64_t
>(1));
1665 static_cast<int64_t
>(1));
1675 bool allow_answer_park) {
1685 }
catch (
const std::exception& e) {
1687 .arg(query->getLabel())
1690 static_cast<int64_t
>(1));
1692 static_cast<int64_t
>(1));
1695 .arg(query->getLabel());
1697 static_cast<int64_t
>(1));
1699 static_cast<int64_t
>(1));
1705 bool allow_answer_park) {
1713 callout_handle->getContext(
"subnet4", ctx->subnet_);
1723 bool allow_answer_park) {
1730 bool rfc_violation =
false;
1733 switch (query->getType()) {
1764 rfc_violation =
true;
1767 }
catch (
const std::exception& e) {
1777 .arg(query->getLabel())
1782 if (!rfc_violation) {
1784 static_cast<int64_t
>(1));
1787 static_cast<int64_t
>(1));
1795 int hook_idx =
Hooks.hook_index_leases4_committed_;
1796 std::string hook_label =
"leases4_committed";
1800 if (ctx->fake_allocation_) {
1801 hook_idx =
Hooks.hook_index_lease4_offer_;
1802 hook_label =
"lease4_offer";
1832 std::shared_ptr<ScopedCalloutHandleState> callout_handle_state =
1833 std::make_shared<ScopedCalloutHandleState>(callout_handle);
1838 callout_handle->setArgument(
"query4", query);
1842 callout_handle->setArgument(
"response4", rsp);
1846 if (ctx->new_lease_ && (ctx->new_lease_->reuseable_valid_lft_ == 0)) {
1847 new_leases->push_back(ctx->new_lease_);
1849 callout_handle->setArgument(
"leases4", new_leases);
1851 if (ctx->fake_allocation_) {
1853 callout_handle->setArgument(
"offer_lifetime", ctx->offer_lft_);
1854 callout_handle->setArgument(
"old_lease", ctx->old_lease_);
1855 callout_handle->setArgument(
"host", ctx->currentHost());
1859 if (ctx->old_lease_) {
1860 if ((!ctx->new_lease_) || (ctx->new_lease_->addr_ != ctx->old_lease_->addr_)) {
1861 deleted_leases->push_back(ctx->old_lease_);
1864 callout_handle->setArgument(
"deleted_leases4", deleted_leases);
1867 if (allow_answer_park) {
1868 auto const tpl(parkingLimitExceeded(hook_label));
1869 bool const exceeded(
get<0>(tpl));
1871 uint32_t
const limit(
get<1>(tpl));
1875 .arg(query->getLabel());
1877 static_cast<int64_t
>(1));
1879 static_cast<int64_t
>(1));
1889 [
this, callout_handle, query, rsp, callout_handle_state, hook_idx, ctx]()
mutable {
1890 if (hook_idx ==
Hooks.hook_index_lease4_offer_) {
1891 bool offer_address_in_use =
false;
1893 callout_handle->getArgument(
"offer_address_in_use", offer_address_in_use);
1896 .arg(query->getLabel())
1900 if (offer_address_in_use) {
1902 bool lease_exists = (ctx->offer_lft_ > 0);
1904 typedef function<void()> CallBack;
1907 boost::shared_ptr<CallBack> call_back = boost::make_shared<CallBack>(
1909 callout_handle, query, lease, lease_exists));
1910 callout_handle_state->on_completion_ = [call_back]() {
1923 typedef function<void()> CallBack;
1924 boost::shared_ptr<CallBack> call_back = boost::make_shared<CallBack>(
1926 query, rsp, ctx->subnet_));
1927 callout_handle_state->on_completion_ = [call_back]() {
1942 if (allow_answer_park) {
1950 allow_answer_park) {
1952 .arg(query->getLabel());
1963 .arg(query->getLabel());
1985 }
catch (
const std::exception& e) {
1987 .arg(query->getLabel())
1991 .arg(query->getLabel());
1999 query->addPktEvent(
"process_completed");
2005 bool skip_pack =
false;
2021 callout_handle->setArgument(
"query4", query);
2024 callout_handle->setArgument(
"response4", rsp);
2027 callout_handle->setArgument(
"subnet4", subnet);
2040 .arg(query->getLabel());
2047 .arg(rsp->getLabel());
2056 .arg(rsp->getLabel());
2058 }
catch (
const std::exception& e) {
2060 .arg(rsp->getLabel())
2090 callout_handle->setArgument(
"response4", rsp);
2103 .arg(rsp->getLabel());
2107 callout_handle->getArgument(
"response4", rsp);
2111 .arg(rsp->getLabel())
2112 .arg(rsp->getName())
2113 .arg(
static_cast<int>(rsp->getType()))
2114 .arg(rsp->getLocalAddr().isV4Zero() ?
"*" : rsp->getLocalAddr().toText())
2115 .arg(rsp->getLocalPort())
2116 .arg(rsp->getRemoteAddr())
2117 .arg(rsp->getRemotePort())
2118 .arg(rsp->getIface().empty() ?
"to be determined from routing" :
2123 .arg(rsp->getLabel())
2124 .arg(rsp->getName())
2125 .arg(
static_cast<int>(rsp->getType()))
2126 .arg(rsp->toText(
true));
2132 }
catch (
const std::exception& e) {
2134 .arg(rsp->getLabel())
2144 boost::shared_ptr<Option4AddrLst> generated =
2145 boost::dynamic_pointer_cast<Option4AddrLst>(srvid);
2151 if (addrs.size() != 1) {
2153 <<
"Expected to contain a single IPv4 address.");
2156 return (addrs[0].toText());
2174 if (local_addr.
isV4Bcast() || query->isDhcp4o6()) {
2180 opt_srvid->writeAddress(local_addr);
2198 if (host && !host->getCfgOption4()->empty()) {
2199 co_list.push_back(host->getCfgOption4());
2206 addr = resp->getYiaddr();
2210 if (pool && !pool->getCfgOption()->empty()) {
2211 co_list.push_back(pool->getCfgOption());
2216 if (!subnet->getCfgOption()->empty()) {
2217 co_list.push_back(subnet->getCfgOption());
2222 subnet->getSharedNetwork(network);
2223 if (network && !network->getCfgOption()->empty()) {
2224 co_list.push_back(network->getCfgOption());
2229 for (
auto const& cclass : classes) {
2232 getClientClassDictionary()->findClass(cclass);
2244 if (ccdef->getCfgOption()->empty()) {
2249 co_list.push_back(ccdef->getCfgOption());
2273 if (co_list.empty()) {
2279 set<uint8_t> requested_opts;
2288 for (uint16_t code : option_prl->getValues()) {
2289 static_cast<void>(requested_opts.insert(code));
2293 std::set<uint8_t> cancelled_opts;
2294 const auto& cclasses = query->getClasses();
2298 for (
auto const& copts : co_list) {
2306 BOOST_FOREACH(
auto const& desc, prange) {
2309 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2310 static_cast<void>(requested_opts.insert(code));
2316 BOOST_FOREACH(
auto const& desc, crange) {
2319 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2320 static_cast<void>(cancelled_opts.insert(code));
2327 for (uint8_t opt : requested_opts) {
2328 if (cancelled_opts.count(opt) > 0) {
2336 if (!resp->getOption(opt)) {
2338 for (
auto const& copts : co_list) {
2343 resp->addOption(desc.
option_);
2356 set<uint32_t> vendor_ids;
2360 vendor_opts = boost::dynamic_pointer_cast<OptionVendorClass>(opt.second);
2362 uint32_t vendor_id = vendor_opts->getVendorId();
2363 static_cast<void>(vendor_ids.insert(vendor_id));
2367 for (
auto const& copts : co_list) {
2370 if (!desc.option_ || !desc.allowedForClientClasses(cclasses)) {
2374 boost::dynamic_pointer_cast<OptionVendorClass>(desc.option_);
2379 uint32_t vendor_id = vendor_opts->getVendorId();
2380 if (vendor_ids.count(vendor_id) > 0) {
2384 resp->Pkt::addOption(desc.option_);
2385 static_cast<void>(vendor_ids.insert(vendor_id));
2394 set<uint32_t> vendor_ids;
2398 vendor_opts = boost::dynamic_pointer_cast<OptionVendor>(opt.second);
2400 uint32_t vendor_id = vendor_opts->getVendorId();
2401 static_cast<void>(vendor_ids.insert(vendor_id));
2405 for (
auto const& copts : co_list) {
2408 if (!desc.option_ || !desc.allowedForClientClasses(cclasses)) {
2412 boost::dynamic_pointer_cast<OptionVendor>(desc.option_);
2417 uint32_t vendor_id = vendor_opts->getVendorId();
2418 if (vendor_ids.count(vendor_id) > 0) {
2424 resp->Pkt::addOption(vendor_opts);
2425 static_cast<void>(vendor_ids.insert(vendor_id));
2445 if (!subnet || co_list.empty()) {
2451 set<uint32_t> vendor_ids;
2455 map<uint32_t, OptionVendorPtr> vendor_rsps;
2458 vendor_rsp = boost::dynamic_pointer_cast<OptionVendor>(opt.second);
2460 uint32_t vendor_id = vendor_rsp->getVendorId();
2461 vendor_rsps[vendor_id] = vendor_rsp;
2462 static_cast<void>(vendor_ids.insert(vendor_id));
2468 map<uint32_t, OptionVendorPtr> vendor_reqs;
2471 vendor_req = boost::dynamic_pointer_cast<OptionVendor>(opt.second);
2473 uint32_t vendor_id = vendor_req->getVendorId();
2474 vendor_reqs[vendor_id] = vendor_req;
2475 static_cast<void>(vendor_ids.insert(vendor_id));
2483 vendor_class = boost::dynamic_pointer_cast<OptionVendorClass>(opt.second);
2485 uint32_t vendor_id = vendor_class->getVendorId();
2486 static_cast<void>(vendor_ids.insert(vendor_id));
2492 if (vendor_ids.empty()) {
2496 map<uint32_t, set<uint8_t> > requested_opts;
2510 oro = boost::dynamic_pointer_cast<OptionUint8Array>(oro_generic);
2513 set<uint8_t> oro_req_opts;
2514 for (uint8_t code : oro->getValues()) {
2515 static_cast<void>(oro_req_opts.insert(code));
2521 const auto& cclasses = query->getClasses();
2522 for (uint32_t vendor_id : vendor_ids) {
2524 std::set<uint8_t> cancelled_opts;
2528 for (
auto const& copts : co_list) {
2537 BOOST_FOREACH(
auto const& desc, prange) {
2540 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2541 static_cast<void>(requested_opts[vendor_id].insert(code));
2548 BOOST_FOREACH(
auto const& desc, crange) {
2551 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2552 static_cast<void>(cancelled_opts.insert(code));
2562 if (requested_opts[vendor_id].empty()) {
2570 if (vendor_rsps.count(vendor_id) > 0) {
2571 vendor_rsp = vendor_rsps[vendor_id];
2579 for (uint8_t opt : requested_opts[vendor_id]) {
2580 if (cancelled_opts.count(opt) > 0) {
2583 if (!vendor_rsp->getOption(opt)) {
2584 for (
auto const& copts : co_list) {
2588 vendor_rsp->addOption(desc.
option_);
2598 if (added && (vendor_rsps.count(vendor_id) == 0)) {
2599 resp->Pkt::addOption(vendor_rsp);
2608 static const std::vector<uint16_t> required_options = {
2622 if (co_list.empty()) {
2627 const auto& cclasses = ex.
getQuery()->getClasses();
2631 for (
auto const& required : required_options) {
2632 OptionPtr opt = resp->getOption(required);
2635 for (
auto const& copts : co_list) {
2637 required, cclasses);
2639 resp->addOption(desc.
option_);
2659 .arg(query->getLabel());
2660 processClientFqdnOption(ex);
2665 .arg(query->getLabel());
2666 processHostnameOption(ex);
2672 std::string hostname;
2673 bool fqdn_fwd =
false;
2674 bool fqdn_rev =
false;
2677 fqdn = boost::dynamic_pointer_cast<Option4ClientFqdn>(resp->getOption(
DHO_FQDN));
2679 hostname = fqdn->getDomainName();
2682 opt_hostname = boost::dynamic_pointer_cast<OptionString>
2686 hostname = opt_hostname->getValue();
2691 if (hostname ==
".") {
2697 if (ex.
getContext()->getDdnsParams()->getEnableUpdates()) {
2717 callout_handle->setArgument(
"query4", query);
2718 callout_handle->setArgument(
"response4", resp);
2719 callout_handle->setArgument(
"subnet4", subnet);
2720 callout_handle->setArgument(
"hostname", hostname);
2721 callout_handle->setArgument(
"fwd-update", fqdn_fwd);
2722 callout_handle->setArgument(
"rev-update", fqdn_rev);
2723 callout_handle->setArgument(
"ddns-params", ex.
getContext()->getDdnsParams());
2729 string hook_hostname;
2730 bool hook_fqdn_fwd =
false;
2731 bool hook_fqdn_rev =
false;
2732 callout_handle->getArgument(
"hostname", hook_hostname);
2733 callout_handle->getArgument(
"fwd-update", hook_fqdn_fwd);
2734 callout_handle->getArgument(
"rev-update", hook_fqdn_rev);
2738 if ((hostname != hook_hostname) || (fqdn_fwd != hook_fqdn_fwd) ||
2739 (fqdn_rev != hook_fqdn_rev)) {
2741 .arg(hostname).arg(hook_hostname).arg(fqdn_fwd).arg(hook_fqdn_fwd)
2742 .arg(fqdn_rev).arg(hook_fqdn_rev);
2743 hostname = hook_hostname;
2744 fqdn_fwd = hook_fqdn_fwd;
2745 fqdn_rev = hook_fqdn_rev;
2749 OptionStringPtr hostname_opt = boost::dynamic_pointer_cast<OptionString>
2752 hostname_opt->setValue(hook_hostname);
2757 fqdn = boost::dynamic_pointer_cast<Option4ClientFqdn>(resp->getOption(
DHO_FQDN));
2769 ctx->fwd_dns_update_ = fqdn_fwd;
2770 ctx->rev_dns_update_ = fqdn_rev;
2771 ctx->hostname_ = hostname;
2796 .arg(fqdn->toText());
2812 !ex.
getContext()->currentHost()->getHostname().empty()) {
2826 .arg(scrubbed.
what());
2845 .arg(fqdn_resp->
toText());
2850Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
2855 OptionStringPtr opt_hostname = boost::dynamic_pointer_cast<OptionString>
2861 .arg(opt_hostname->getValue());
2869 if (ctx->currentHost() && !ctx->currentHost()->getHostname().empty()) {
2871 std::string hostname = d2_mgr.
qualifyName(ctx->currentHost()->getHostname(),
2874 boost::algorithm::to_lower(hostname);
2892 ex.
getContext()->getDdnsParams()->getReplaceClientNameMode();
2895 if (!opt_hostname) {
2915 .arg(opt_hostname->getValue());
2918 unsigned int label_count;
2924 }
catch (
const std::exception& exc) {
2935 if (label_count == 0) {
2953 || label_count < 2) {
2967 ex.
getContext()->getDdnsParams()->getHostnameSanitizer();
2970 auto tmp = sanitizer->scrub(hostname);
2982 boost::algorithm::to_lower(hostname);
2984 if (label_count == 2) {
2992 opt_hostname_resp.reset(
3003 .arg(opt_hostname_resp->getValue());
3013 "NULL lease specified when creating NameChangeRequest");
3021 if ((lease->reuseable_valid_lft_ == 0) &&
3023 !lease->hasIdenticalFqdn(*old_lease))) {
3041 while (current_subnet) {
3047 subnet = current_subnet;
3051 current_subnet = current_subnet->getNextSubnet(subnet, client_classes);
3055 subnet->getSharedNetwork(network);
3087 bool fake_allocation = (query->getType() ==
DHCPDISCOVER);
3094 auto const& requested_opts = option_prl->getValues();
3095 if ((std::find(requested_opts.cbegin(), requested_opts.cend(),
3099 ctx->subnet_ = subnet;
3101 if (!fake_allocation) {
3102 resp->setCiaddr(query->getCiaddr());
3119 if (opt_requested_address) {
3120 hint = opt_requested_address->readAddress();
3122 }
else if (!query->getCiaddr().isV4Zero()) {
3123 hint = query->getCiaddr();
3130 auto authoritative =
false;
3136 auto init_reboot = (!fake_allocation && !opt_serverid && opt_requested_address);
3140 .arg(query->getLabel())
3145 authoritative = subnet->getAuthoritative();
3151 authoritative = flag->boolValue();
3154 }
else if (fake_allocation) {
3156 .arg(query->getLabel())
3160 .arg(query->getLabel())
3174 if (!fake_allocation && !opt_serverid && !opt_requested_address
3175 && !query->getCiaddr().isV4Zero() && query->getLocalAddr().isV4Bcast()) {
3180 if (!init_reboot || authoritative) {
3183 .arg(query->getLabel())
3184 .arg(query->getRemoteAddr().toText())
3185 .arg(query->getName());
3204 auto const& classes = query->getClasses();
3214 if (original_subnet && client_id) {
3218 if (!leases_client_id.empty()) {
3224 for (
auto const& l : leases_client_id) {
3225 if (l->subnet_id_ == s->getID()) {
3235 s = s->getNextSubnet(original_subnet, classes);
3243 if (original_subnet && !lease && hwaddr) {
3247 if (!leases_hwaddr.empty()) {
3252 for (
auto const& l : leases_hwaddr) {
3253 if (l->subnet_id_ == s->getID()) {
3263 s = s->getNextSubnet(original_subnet, classes);
3272 bool known_client = lease && lease->belongsToClient(hwaddr, client_id);
3273 if (!authoritative && !known_client) {
3276 .arg(query->getLabel())
3285 if ((known_client && (lease->addr_ != hint)) ||
3286 (!known_client && authoritative) ||
3287 (!original_subnet)) {
3290 .arg(query->getLabel())
3302 ctx->requested_address_ = hint;
3303 ctx->fake_allocation_ = fake_allocation;
3304 ctx->callout_handle_ = callout_handle;
3318 bool reprocess_client_name =
false;
3322 auto ddns_params = ex.
getContext()->getDdnsParams();
3323 auto pool = ddns_params->setPoolFromAddress(lease->addr_);
3325 reprocess_client_name = pool->hasDdnsParameters();
3331 if (subnet && ctx->subnet_ && subnet->getID() != ctx->subnet_->getID()) {
3340 subnet->getSharedNetwork(network);
3342 .arg(query->getLabel())
3343 .arg(subnet->toText())
3344 .arg(ctx->subnet_->toText())
3345 .arg(network ? network->getName() :
"<no network?>");
3347 subnet = ctx->subnet_;
3349 reprocess_client_name =
true;
3355 bool client_name_changed =
false;
3357 if (reprocess_client_name) {
3362 ctx->hostname_ =
"";
3363 ctx->fwd_dns_update_ =
false;
3364 ctx->rev_dns_update_ =
false;
3371 if ((lease->hostname_ != ctx->hostname_) ||
3372 (lease->fqdn_fwd_ != ctx->fwd_dns_update_) ||
3373 (lease->fqdn_rev_ != ctx->rev_dns_update_)) {
3374 lease->hostname_ = ctx->hostname_;
3375 lease->fqdn_fwd_ = ctx->fwd_dns_update_;
3376 lease->fqdn_rev_ = ctx->rev_dns_update_;
3377 client_name_changed =
true;
3384 if (fake_allocation) {
3386 .arg(query->getLabel())
3387 .arg(lease->addr_.toText());
3390 .arg(query->getLabel())
3391 .arg(lease->addr_.toText())
3399 if (!ctx->subnet_->getMatchClientId()) {
3401 .arg(ctx->query_->getLabel())
3402 .arg(ctx->subnet_->getID());
3405 resp->setYiaddr(lease->addr_);
3411 if (!fake_allocation) {
3416 resp->setCiaddr(query->getCiaddr());
3425 if (lease->reuseable_valid_lft_ > 0) {
3426 lease->valid_lft_ = lease->reuseable_valid_lft_;
3428 .arg(query->getLabel())
3429 .arg(lease->addr_.toText())
3434 static_cast<int64_t
>(1));
3438 static_cast<int64_t
>(1));
3448 resp->addOption(opt);
3451 resp->addOption(getNetmaskOption(subnet));
3457 if (!fake_allocation) {
3463 .arg(query->getLabel())
3471 if (ctx->unknown_requested_addr_) {
3483 s = s->getNextSubnet(original_subnet);
3491 .arg(query->getLabel())
3492 .arg(query->getCiaddr().toText())
3493 .arg(opt_requested_address ?
3494 opt_requested_address->readAddress().toText() :
"(no address)");
3502 .arg(query->getLabel())
3503 .arg(query->getCiaddr().toText())
3504 .arg(opt_requested_address ?
3505 opt_requested_address->readAddress().toText() :
"(no address)");
3517 const Pkt4Ptr& query,
const Pkt4Ptr& resp,
bool client_name_changed) {
3526 opt_hostname = boost::dynamic_pointer_cast<OptionString>(resp->getOption(
DHO_HOST_NAME));
3527 if (!opt_hostname) {
3534 if (lease->hostname_.empty()) {
3541 .
generateFqdn(lease->addr_, *(ctx->getDdnsParams()),
static_cast<bool>(fqdn));
3544 .arg(query->getLabel())
3545 .arg(lease->hostname_);
3547 client_name_changed =
true;
3550 if (client_name_changed) {
3556 if (!ctx->fake_allocation_ || (ctx->offer_lft_ > 0)) {
3558 lease->reuseable_valid_lft_ = 0;
3571 opt_hostname->setValue(lease->hostname_);
3575 .arg(query->getLabel())
3576 .arg(lease->hostname_)
3586 uint32_t t2_time = 0;
3588 if (!subnet->getT2().unspecified()) {
3589 t2_time = subnet->getT2();
3590 }
else if (subnet->getCalculateTeeTimes()) {
3592 t2_time =
static_cast<uint32_t
>(round(subnet->getT2Percent() * (lease->valid_lft_)));
3597 uint32_t timer_ceiling = lease->valid_lft_;
3598 if (t2_time > 0 && t2_time < timer_ceiling) {
3600 resp->addOption(t2);
3602 timer_ceiling = t2_time;
3605 uint32_t t1_time = 0;
3607 if (!subnet->getT1().unspecified()) {
3608 t1_time = subnet->getT1();
3609 }
else if (subnet->getCalculateTeeTimes()) {
3611 t1_time =
static_cast<uint32_t
>(round(subnet->getT1Percent() * (lease->valid_lft_)));
3616 if (t1_time > 0 && t1_time < timer_ceiling) {
3618 resp->addOption(t1);
3630 return (query->getRemotePort());
3658 }
else if (((query->getType() ==
DHCPINFORM) &&
3659 ((!query->getCiaddr().isV4Zero()) ||
3660 (!query->isRelayed() && !query->getRemoteAddr().isV4Zero()))) ||
3661 ((query->getType() !=
DHCPINFORM) && !query->isRelayed())) {
3662 response->setRemotePort(DHCP4_CLIENT_PORT);
3667 response->setRemotePort(relay_port ? relay_port : DHCP4_SERVER_PORT);
3671 if (query->isRelayed() &&
3677 response->resetIndex();
3679 response->setIface(query->getIface());
3683 IOAddress local_addr = query->getLocalAddr();
3692 if (local_addr.
isV4Bcast() || query->isDhcp4o6()) {
3703 response->setLocalAddr(local_addr);
3712 response->setIndex(query->getIndex());
3713 response->setIface(query->getIface());
3719 response->setLocalPort(DHCP4_SERVER_PORT);
3731 if (query->isDhcp4o6()) {
3732 response->setRemoteAddr(query->getRemoteAddr());
3744 if (!query->getCiaddr().isV4Zero()) {
3745 response->setRemoteAddr(query->getCiaddr());
3752 }
else if (query->isRelayed()) {
3753 response->setRemoteAddr(query->getGiaddr());
3754 response->setFlags(response->getFlags() | BOOTP_BROADCAST);
3759 response->setRemoteAddr(query->getRemoteAddr());
3766 if (query->isRelayed()) {
3775 query->getCiaddr().isV4Zero()) {
3776 response->setFlags(BOOTP_BROADCAST);
3778 response->setRemoteAddr(query->getGiaddr());
3782 }
else if (!query->getCiaddr().isV4Zero()) {
3783 response->setRemoteAddr(query->getCiaddr());
3788 }
else if (response->getType() ==
DHCPNAK) {
3792 }
else if (!response->getYiaddr().isV4Zero()) {
3807 response->setRemoteAddr(response ->getYiaddr());
3815 response->setRemoteAddr(query->getRemoteAddr());
3820 response->setRemoteAddr(query->getRemoteAddr());
3832 IOAddress subnet_next_server = subnet->getSiaddr();
3833 if (!subnet_next_server.
isV4Zero()) {
3834 response->setSiaddr(subnet_next_server);
3837 const string& sname = subnet->getSname();
3838 if (!sname.empty()) {
3844 response->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
3848 const string& filename = subnet->getFilename();
3849 if (!filename.empty()) {
3855 response->setFile(
reinterpret_cast<const uint8_t*
>(filename.c_str()),
3863 if (!classes.
empty()) {
3876 size_t found_cnt = 0;
3877 for (
auto const& name : classes) {
3879 if (found_cnt >= 3) {
3893 next_server = cl->getNextServer();
3895 response->setSiaddr(next_server);
3900 if (sname.empty()) {
3901 sname = cl->getSname();
3902 if (!sname.empty()) {
3908 response->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
3914 if (filename.empty()) {
3915 filename = cl->getFilename();
3916 if (!filename.empty()) {
3922 response->setFile(
reinterpret_cast<const uint8_t*
>(filename.c_str()),
3945tuple<bool, uint32_t>
3946Dhcpv4Srv::parkingLimitExceeded(
string const& hook_label) {
3948 uint32_t parked_packet_limit(0);
3952 parked_packet_limit = ppl->intValue();
3955 if (parked_packet_limit) {
3959 if (parking_lot && parked_packet_limit <= parking_lot->size()) {
3960 return make_tuple(
true, parked_packet_limit);
3963 return make_tuple(
false, parked_packet_limit);
4001 .arg(discover->getLabel())
4002 .arg(discover->getName())
4003 .arg(discover->getClasses().toText());
4012 .arg(discover->getLabel());
4071 }
else if (request->inClass(
"BOOTP")) {
4073 response->addClass(
"BOOTP");
4087 .arg(request->getLabel())
4088 .arg(request->getName())
4089 .arg(request->getClasses().toText());
4098 .arg(request->getLabel());
4151 .arg(release->getLabel())
4152 .arg(release->getCiaddr().toText());
4156 if (!lease->belongsToClient(release->getHWAddr(), client_id)) {
4158 .arg(release->getLabel())
4159 .arg(release->getCiaddr().toText());
4179 callout_handle->setArgument(
"query4", release);
4182 callout_handle->setArgument(
"lease4", lease);
4196 .arg(release->getLabel());
4204 bool success =
false;
4205 bool expired =
false;
4209 if (expiration_cfg->getFlushReclaimedTimerWaitTime() &&
4210 expiration_cfg->getHoldReclaimedTime() &&
4213 lease->valid_lft_ = 0;
4229 context->old_lease_ = lease;
4233 .arg(release->getLabel())
4234 .arg(lease->addr_.toText());
4238 .arg(release->getLabel())
4239 .arg(lease->addr_.toText());
4242 .arg(release->getLabel())
4243 .arg(lease->addr_.toText());
4254 static_cast<int64_t
>(-1));
4258 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4263 static_cast<int64_t
>(-1));
4270 .arg(release->getLabel())
4271 .arg(lease->addr_.toText());
4276 .arg(release->getLabel())
4277 .arg(release->getCiaddr())
4290 if (!opt_requested_address) {
4293 static_cast<int64_t
>(1));
4295 " in DHCPDECLINE sent from " << decline->getLabel());
4297 IOAddress addr(opt_requested_address->readAddress());
4315 .arg(addr.
toText()).arg(decline->getLabel());
4323 client_id.reset(
new ClientId(opt_clientid->getData()));
4332 !lease->belongsToClient(decline->getHWAddr(), client_id)) {
4335 string client_hw = decline->getHWAddr() ?
4336 decline->getHWAddr()->toText(
false) :
"(none)";
4337 string lease_hw = lease->hwaddr_ ?
4338 lease->hwaddr_->toText(
false) :
"(none)";
4341 string client_id_txt = client_id ? client_id->toText() :
"(none)";
4342 string lease_id_txt = lease->client_id_ ?
4343 lease->client_id_->toText() :
"(none)";
4347 .arg(addr.
toText()).arg(decline->getLabel())
4348 .arg(client_hw).arg(lease_hw).arg(client_id_txt).arg(lease_id_txt);
4378 callout_handle->setArgument(
"query4", decline);
4381 callout_handle->setArgument(
"lease4", lease);
4392 .arg(decline->getLabel()).arg(lease->addr_.toText());
4397 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4411 .arg(decline->getLabel())
4412 .arg(lease->addr_.toText())
4426 static_cast<int64_t
>(1));
4430 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4435 static_cast<int64_t
>(1));
4452 context->new_lease_ = lease;
4455 .arg(decline->getLabel()).arg(lease->valid_lft_);
4462 .arg(query->getLabel())
4463 .arg(lease->addr_.toText())
4464 .arg(lease->valid_lft_);
4472 .arg(query->getLabel())
4473 .arg(lease->addr_.toText());
4489 lease_exists =
false;
4493 .arg(query->getLabel())
4494 .arg(lease->addr_.toText());
4499 if (!lease_exists) {
4504 .arg(query->getLabel())
4505 .arg(lease->addr_.toText());
4522 static_cast<int64_t
>(1));
4524 if (!lease_exists) {
4527 static_cast<int64_t
>(1));
4532 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4537 static_cast<int64_t
>(1));
4538 if (!lease_exists) {
4542 static_cast<int64_t
>(1));
4549 if (!lease_exists) {
4563 callout_handle->setArgument(
"query4", query);
4566 callout_handle->setArgument(
"lease4", lease);
4581 .arg(query->getLabel());
4605 .arg(inform->getLabel())
4606 .arg(inform->getName())
4607 .arg(inform->getClasses().toText());
4624 if (ack->getRemoteAddr() != inform->getGiaddr()) {
4626 .arg(inform->getLabel())
4627 .arg(ack->getRemoteAddr())
4628 .arg(ack->getIface());
4642 if (query->getCiaddr().isV4Zero() || !query->getGiaddr().isV4Zero()) {
4659 if (query->inClass(
"STASH_AGENT_OPTIONS")) {
4663 if (!lease || lease->expired()) {
4667 if (!user_context || (user_context->getType() !=
Element::map)) {
4675 if (!relay_agent_info) {
4680 relay_agent_info = relay_agent_info->get(
"sub-options");
4681 if (!relay_agent_info) {
4692 client_id.reset(
new ClientId(opt_clientid->getData()));
4694 if (!lease->belongsToClient(query->getHWAddr(), client_id)) {
4698 string rai_hex = relay_agent_info->stringValue();
4699 if (rai_hex.empty()) {
4702 vector<uint8_t> rai_data;
4707 if (!rai || rai->getOptions().empty()) {
4714 query->addOption(rai);
4715 query->addClass(
"STASH_AGENT_OPTIONS");
4718 .arg(query->getLabel())
4719 .arg(query->getCiaddr())
4720 .arg(rai->toText());
4734 .arg(query->getLabel())
4735 .arg(query->getIface());
4743 .arg(query->getLabel())
4744 .arg(query->getIface());
4754 if (pkt->isRelayed()) {
4759 if (pkt->isDhcp4o6()) {
4769 if (pkt->getRemoteAddr().isV4Zero() &&
4770 pkt->getCiaddr().isV4Zero()) {
4783 static_cast<int64_t
>(1));
4794 type = query->getType();
4798 .arg(query->getLabel())
4799 .arg(query->getIface());
4801 static_cast<int64_t
>(1));
4825 .arg(query->getLabel());
4832 .arg(query->getLabel())
4837 .arg(query->getLabel())
4844 static_cast<int64_t
>(1));
4866 boost::dynamic_pointer_cast<OptionCustom>(option);
4869 if (!option_custom) {
4871 static_cast<int64_t
>(1));
4879 if (option_custom->getDataFieldsNum() != 1) {
4881 static_cast<int64_t
>(1));
4887 IOAddress server_id = option_custom->readAddress();
4888 if (!server_id.
isV4()) {
4890 static_cast<int64_t
>(1));
4899 if (rai_suboption && (server_id.
toBytes() == rai_suboption->toBinary())) {
4906 if (cfg->getIgnoreServerIdentifier()) {
4944 if (cfg_subnets->hasSubnetWithServerId(server_id)) {
4951 if (cfg_networks->hasNetworkWithServerId(server_id)) {
4957 for (
auto const& cclass : classes) {
4960 getClientClassDictionary()->findClass(cclass);
4965 if (ccdef->getCfgOption()->empty()) {
4970 OptionCustomPtr context_opt_server_id = boost::dynamic_pointer_cast<OptionCustom>
4972 if (context_opt_server_id && (context_opt_server_id->readAddress() == server_id)) {
4980 OptionCustomPtr opt_server_id = boost::dynamic_pointer_cast<OptionCustom>
4983 if (opt_server_id && (opt_server_id->readAddress() == server_id)) {
4994 switch (query->getType()) {
5029 static_cast<int64_t
>(1));
5031 <<
" received in message "
5032 << query->getName());
5039 static_cast<int64_t
>(1));
5041 " received in message "
5042 << query->getName());
5052 if (query->getHWAddr() && !query->getHWAddr()->hwaddr_.empty()) {
5061 if (!client_id || client_id->len() == client_id->getHeaderLen()) {
5063 static_cast<int64_t
>(1));
5065 " provided in message "
5066 << query->getName());
5087 addr = resp->getYiaddr();
5092 const ClientClasses& pool_to_add = pool->getAdditionalClasses();
5093 for (
auto const& cclass : pool_to_add) {
5100 const ClientClasses& to_add = subnet->getAdditionalClasses();
5101 for (
auto const& cclass : to_add) {
5107 subnet->getSharedNetwork(network);
5109 const ClientClasses& net_to_add = network->getAdditionalClasses();
5110 for (
auto const& cclass : net_to_add) {
5120 for (
auto const& cclass : classes) {
5135 query->addClass(cclass);
5143 .arg(query->getLabel())
5145 .arg(status ?
"true" :
"false");
5148 query->addClass(cclass);
5152 .arg(query->getLabel())
5162 for (
auto const& code : query->getDeferredOptions()) {
5166 for (
auto const& cclass : classes) {
5170 getClientClassDictionary()->findClass(cclass);
5176 if (!ccdef->getCfgOptionDef()) {
5206 .arg(query->getLabel())
5215 opt = def->optionFactory(
Option::V4, code, buf);
5216 }
catch (
const std::exception& e) {
5220 .arg(query->getLabel())
5225 while (query->delOption(code)) {
5229 query->addOption(opt);
5241 this, ph::_1, ph::_2));
5260 .arg((ncr ? ncr->toText() :
" NULL "));
5269 std::stringstream tmp;
5273 tmp <<
" (" << SOURCE_OF_INSTALLATION <<
")" << endl;
5274 tmp <<
"premium: " << PREMIUM_EXTENDED_VERSION << endl;
5275 tmp <<
"linked with:" << endl;
5280 tmp << endl <<
"lease backends:";
5282 tmp << endl <<
"- " <<
version;
5287 tmp << endl <<
"host backends:";
5289 tmp << endl <<
"- " <<
version;
5294 tmp << endl <<
"forensic backends:";
5296 tmp << endl <<
"- " <<
version;
5309 string stat_name =
"pkt4-unknown-received";
5311 switch (query->getType()) {
5313 stat_name =
"pkt4-discover-received";
5317 stat_name =
"pkt4-offer-received";
5320 stat_name =
"pkt4-request-received";
5324 stat_name =
"pkt4-ack-received";
5328 stat_name =
"pkt4-nak-received";
5331 stat_name =
"pkt4-release-received";
5334 stat_name =
"pkt4-decline-received";
5337 stat_name =
"pkt4-inform-received";
5359 switch (response->getType()) {
5361 stat_name =
"pkt4-offer-sent";
5364 stat_name =
"pkt4-ack-sent";
5367 stat_name =
"pkt4-nak-sent";
5378 return (
Hooks.hook_index_buffer4_receive_);
5382 return (
Hooks.hook_index_pkt4_receive_);
5386 return (
Hooks.hook_index_subnet4_select_);
5390 return (
Hooks.hook_index_lease4_release_);
5394 return (
Hooks.hook_index_pkt4_send_);
5398 return (
Hooks.hook_index_buffer4_send_);
5402 return (
Hooks.hook_index_lease4_decline_);
5412 char const*
const rotate(getenv(
"KEA_DHCP4_FUZZING_ROTATE_PORT"));
5416 while (!locker.
lock()) {
5417 this_thread::sleep_for(1s);
5420 port_file.open(
"/tmp/port4.txt", ios::in);
5423 getline(port_file, line);
5435 port_file.open(
"/tmp/port4.txt", ios::out | ios::trunc);
5436 port_file << to_string(port) << endl;
5446 static std::list<std::list<std::string>>
const list({
5447 {
"config-control",
"config-databases",
"[]"},
5448 {
"hooks-libraries",
"[]",
"parameters",
"*"},
5450 {
"hosts-databases",
"[]"},
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.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
bool isV4Bcast() const
Convenience function to check if it is an IPv4 broadcast address.
void clearIOServices()
Clear the list of IOService objects.
static IOServiceMgr & instance()
Access the IOServiceMgr singleton instance.
size_t pollIOServices()
Poll IOService objects.
The IOService class is a wrapper for the ASIO io_context class.
static std::string getVersion()
Get version string.
DHCPv4 and DHCPv6 allocation engine.
boost::shared_ptr< ClientContext4 > ClientContext4Ptr
Pointer to the ClientContext4.
static uint32_t getValidLft(const ClientContext4 &ctx)
Returns the valid lifetime based on the v4 context.
Implementation of the mechanisms to control the use of the Configuration Backends by the DHCPv4 serve...
@ EARLY_GLOBAL_RESERVATIONS_LOOKUP
@ USE_ROUTING
Server uses routing to determine the right interface to send response.
@ SOCKET_UDP
Datagram socket, i.e. IP/UDP socket.
D2ClientMgr & getD2ClientMgr()
Fetches the DHCP-DDNS manager.
static CfgMgr & instance()
returns a single instance of Configuration Manager
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
static SubnetSelector initSelector(const Pkt4Ptr &query)
Build selector from a client's message.
Container for storing client class names.
void insert(const ClientClass &class_name)
Insert an element.
bool empty() const
Check if classes is empty.
std::string toText(const std::string &separator=", ") const
Returns all class names as text.
Client race avoidance RAII handler.
bool tryLock(Pkt4Ptr query, ContinuationPtr cont=ContinuationPtr())
Tries to acquires a client.
Holds Client identifier or client IPv4 address.
ReplaceClientNameMode
Defines the client name replacement modes.
D2ClientMgr isolates Kea from the details of being a D2 client.
std::string generateFqdn(const asiolink::IOAddress &address, const DdnsParams &ddns_params, const bool trailing_dot=true) const
Builds a FQDN based on the configuration and given IP address.
bool ddnsEnabled()
Convenience method for checking if DHCP-DDNS is enabled.
void getUpdateDirections(const T &fqdn_resp, bool &forward, bool &reverse)
Get directional update flags based on server FQDN flags.
void stop()
Stop the sender.
void suspendUpdates()
Suspends sending requests.
void adjustDomainName(const T &fqdn, T &fqdn_resp, const DdnsParams &ddns_params)
Set server FQDN name based on configuration and a given FQDN.
void stopSender()
Disables sending NameChangeRequests to kea-dhcp-ddns.
void adjustFqdnFlags(const T &fqdn, T &fqdn_resp, const DdnsParams &ddns_params)
Set server FQDN flags based on configuration and a given FQDN.
std::string qualifyName(const std::string &partial_name, const DdnsParams &ddns_params, const bool trailing_dot) const
Adds a qualifying suffix to a given domain name.
void startSender(D2ClientErrorHandler error_handler, const isc::asiolink::IOServicePtr &io_service)
Enables sending NameChangeRequests to kea-dhcp-ddns.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
bool getUpdateOnRenew() const
Returns whether or not DNS should be updated when leases renew.
bool getEnableUpdates() const
Returns whether or not DHCP DDNS updating is enabled.
void close()
Close communication socket.
static Dhcp4to6Ipc & instance()
Returns pointer to the sole instance of Dhcp4to6Ipc.
AllocEngine::ClientContext4Ptr getContext() const
Returns the copy of the context for the Allocation engine.
void deleteResponse()
Removes the response message by resetting the pointer to null.
Pkt4Ptr getQuery() const
Returns the pointer to the query from the client.
static void setHostIdentifiers(AllocEngine::ClientContext4Ptr context)
Set host identifiers within a context.
static void classifyByVendor(const Pkt4Ptr &pkt)
Assign class using vendor-class-identifier option.
void initResponse()
Initializes the instance of the response message.
void setReservedMessageFields()
Sets reserved values of siaddr, sname and file in the server's response.
CfgOptionList & getCfgOptionList()
Returns the configured option list (non-const version)
Pkt4Ptr getResponse() const
Returns the pointer to the server's response.
static void setReservedClientClasses(AllocEngine::ClientContext4Ptr context)
Assigns classes retrieved from host reservation database.
void initResponse4o6()
Initializes the DHCPv6 part of the response message.
static void evaluateClasses(const Pkt4Ptr &pkt, bool depend_on_known)
Evaluate classes.
void setIPv6OnlyPreferred(bool ipv6_only_preferred)
Set the IPv6-Only Preferred flag.
Dhcpv4Exchange(const AllocEnginePtr &alloc_engine, const Pkt4Ptr &query, AllocEngine::ClientContext4Ptr &context, const ConstSubnet4Ptr &subnet, bool &drop)
Constructor.
static void classifyPacket(const Pkt4Ptr &pkt)
Assigns incoming packet to zero or more classes.
static void removeDependentEvaluatedClasses(const Pkt4Ptr &query)
Removed evaluated client classes.
bool getIPv6OnlyPreferred() const
Returns the IPv6-Only Preferred flag.
void conditionallySetReservedClientClasses()
Assigns classes retrieved from host reservation database if they haven't been yet set.
void initContext0(const Pkt4Ptr &query, AllocEngine::ClientContext4Ptr ctx)
Initialize client context (first part).
int run()
Main server processing loop.
void declineLease(const Lease4Ptr &lease, const Pkt4Ptr &decline, AllocEngine::ClientContext4Ptr &context)
Marks lease as declined.
void processPacketAndSendResponse(Pkt4Ptr query)
Process a single incoming DHCPv4 packet and sends the response.
void classifyPacket(const Pkt4Ptr &pkt)
Assigns incoming packet to zero or more classes.
void appendRequestedVendorOptions(Dhcpv4Exchange &ex)
Appends requested vendor options as requested by client.
void adjustIfaceData(Dhcpv4Exchange &ex)
Set IP/UDP and interface parameters for the DHCPv4 response.
static uint16_t checkRelayPort(const Dhcpv4Exchange &ex)
Check if the relay port RAI sub-option was set in the query.
virtual ~Dhcpv4Srv()
Destructor. Used during DHCPv4 service shutdown.
virtual Pkt4Ptr receivePacket(int timeout)
dummy wrapper around IfaceMgr::receive4
bool accept(const Pkt4Ptr &query)
Checks whether received message should be processed or discarded.
void setTeeTimes(const Lease4Ptr &lease, const ConstSubnet4Ptr &subnet, Pkt4Ptr resp)
Adds the T1 and T2 timers to the outbound response as appropriate.
static void appendServerID(Dhcpv4Exchange &ex)
Adds server identifier option to the server's response.
void postAllocateNameUpdate(const AllocEngine::ClientContext4Ptr &ctx, const Lease4Ptr &lease, const Pkt4Ptr &query, const Pkt4Ptr &resp, bool client_name_changed)
Update client name and DNS flags in the lease and response.
bool use_bcast_
Should broadcast be enabled on sockets (if true).
void runOne()
Main server processing step.
void startD2()
Starts DHCP_DDNS client IO if DDNS updates are enabled.
static int getHookIndexBuffer4Receive()
Returns the index for "buffer4_receive" hook point.
Pkt4Ptr processRequest(Pkt4Ptr &request, AllocEngine::ClientContext4Ptr &context)
Processes incoming REQUEST and returns REPLY response.
static void processStatsReceived(const Pkt4Ptr &query)
Class methods for DHCPv4-over-DHCPv6 handler.
static int getHookIndexPkt4Send()
Returns the index for "pkt4_send" hook point.
void processDecline(Pkt4Ptr &decline, AllocEngine::ClientContext4Ptr &context)
Process incoming DHCPDECLINE messages.
Dhcpv4Srv(uint16_t server_port=DHCP4_SERVER_PORT, uint16_t client_port=0, const bool use_bcast=true, const bool direct_response_desired=true)
Default constructor.
static int getHookIndexSubnet4Select()
Returns the index for "subnet4_select" hook point.
isc::dhcp::ConstSubnet4Ptr selectSubnet(const Pkt4Ptr &query, bool &drop, bool allow_answer_park=true)
Selects a subnet for a given client's packet.
static void processStatsSent(const Pkt4Ptr &response)
Updates statistics for transmitted packets.
void shutdown() override
Instructs the server to shut down.
static int getHookIndexLease4Release()
Returns the index for "lease4_release" hook point.
void adjustRemoteAddr(Dhcpv4Exchange &ex)
Sets remote addresses for outgoing packet.
static int getHookIndexPkt4Receive()
Returns the index for "pkt4_receive" hook point.
void assignLease(Dhcpv4Exchange &ex)
Assigns a lease and appends corresponding options.
void evaluateAdditionalClasses(Dhcpv4Exchange &ex)
Evaluates classes in the additional classes lists.
Pkt4Ptr processDhcp4Query(Pkt4Ptr query, bool allow_answer_park)
Process a single incoming DHCPv4 query.
asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service used by the server.
void setFixedFields(Dhcpv4Exchange &ex)
Sets fixed fields of the outgoing packet.
void appendBasicOptions(Dhcpv4Exchange &ex)
Append basic options if they are not present.
void recoverStashedAgentOption(const Pkt4Ptr &query)
Recover stashed agent options from client address lease.
void processClientName(Dhcpv4Exchange &ex)
Processes Client FQDN and Hostname Options sent by a client.
boost::shared_ptr< AllocEngine > alloc_engine_
Allocation Engine.
void serverDecline(hooks::CalloutHandlePtr &callout_handle, Pkt4Ptr &query, Lease4Ptr lease, bool lease_exists)
Renders a lease declined after the server has detected, via ping-check or other means,...
Pkt4Ptr processInform(Pkt4Ptr &inform, AllocEngine::ClientContext4Ptr &context)
Processes incoming DHCPINFORM messages.
uint16_t client_port_
UDP port number to which server sends all responses.
void serverDeclineNoThrow(hooks::CalloutHandlePtr &callout_handle, Pkt4Ptr &query, Lease4Ptr lease, bool lease_exists)
Exception safe wrapper around serverDecline()
void processPacketPktSend(hooks::CalloutHandlePtr &callout_handle, Pkt4Ptr &query, Pkt4Ptr &rsp, ConstSubnet4Ptr &subnet)
Executes pkt4_send callout.
void processPacketAndSendResponseNoThrow(Pkt4Ptr query)
Process a single incoming DHCPv4 packet and sends the response.
std::list< std::list< std::string > > jsonPathsToRedact() const final override
Return a list of all paths that contain passwords or secrets for kea-dhcp4.
static std::string srvidToString(const OptionPtr &opt)
converts server-id to text Converts content of server-id option to a text representation,...
bool acceptServerId(const Pkt4Ptr &pkt) const
Verifies if the server id belongs to our server.
static const std::string VENDOR_CLASS_PREFIX
this is a prefix added to the content of vendor-class option
void createNameChangeRequests(const Lease4Ptr &lease, const Lease4Ptr &old_lease, const DdnsParams &ddns_params)
Creates NameChangeRequests which correspond to the lease which has been acquired.
void appendRequestedOptions(Dhcpv4Exchange &ex)
Appends options requested by client.
void setPacketStatisticsDefaults()
This function sets statistics related to DHCPv4 packets processing to their initial values.
void processLocalizedQuery4AndSendResponse(Pkt4Ptr query, AllocEngine::ClientContext4Ptr &ctx, bool allow_answer_park)
Process a localized incoming DHCPv4 query.
static std::string getVersion(bool extended)
returns Kea version on stdout and exit.
void buildCfgOptionList(Dhcpv4Exchange &ex)
Build the configured option list.
volatile bool shutdown_
Indicates if shutdown is in progress.
uint16_t server_port_
UDP port number on which server listens.
void sendResponseNoThrow(hooks::CalloutHandlePtr &callout_handle, Pkt4Ptr &query, Pkt4Ptr &rsp, ConstSubnet4Ptr &subnet)
Process an unparked DHCPv4 packet and sends the response.
bool earlyGHRLookup(const Pkt4Ptr &query, AllocEngine::ClientContext4Ptr ctx)
Initialize client context and perform early global reservations lookup.
NetworkStatePtr network_state_
Holds information about disabled DHCP service and/or disabled subnet/network scopes.
void processDhcp4QueryAndSendResponse(Pkt4Ptr query, bool allow_answer_park)
Process a single incoming DHCPv4 query.
bool getSendResponsesToSource() const
Returns value of the test_send_responses_to_source_ flag.
Pkt4Ptr processDiscover(Pkt4Ptr &discover, AllocEngine::ClientContext4Ptr &context)
Processes incoming DISCOVER and returns response.
virtual void d2ClientErrorHandler(const dhcp_ddns::NameChangeSender::Result result, dhcp_ddns::NameChangeRequestPtr &ncr)
Implements the error handler for DHCP_DDNS IO errors.
uint16_t getServerPort() const
Get UDP port on which server should listen.
virtual void sendPacket(const Pkt4Ptr &pkt)
dummy wrapper around IfaceMgr::send()
static int getHookIndexBuffer4Send()
Returns the index for "buffer4_send" hook point.
void stopD2()
Stops DHCP_DDNS client IO if DDNS updates are enabled.
static void sanityCheck(const Pkt4Ptr &query)
Verifies if specified packet meets RFC requirements.
bool acceptMessageType(const Pkt4Ptr &query) const
Check if received message type is valid for the server to process.
void discardPackets()
Discards parked packets Clears the packet parking lots of all packets.
isc::dhcp::ConstSubnet4Ptr selectSubnet4o6(const Pkt4Ptr &query, bool &drop, bool allow_answer_park=true)
Selects a subnet for a given client's DHCP4o6 packet.
static int getHookIndexLease4Decline()
Returns the index for "lease4_decline" hook point.
void processRelease(Pkt4Ptr &release, AllocEngine::ClientContext4Ptr &context)
Processes incoming DHCPRELEASE messages.
bool acceptDirectRequest(const Pkt4Ptr &query)
Check if a message sent by directly connected client should be accepted or discarded.
CBControlDHCPv4Ptr cb_control_
Controls access to the configuration backends.
RequirementLevel
defines if certain option may, must or must not appear
Pkt4Ptr processPacket(Pkt4Ptr query, bool allow_answer_park=true)
Process a single incoming DHCPv4 packet.
void processPacketBufferSend(hooks::CalloutHandlePtr &callout_handle, Pkt4Ptr &rsp)
Executes buffer4_send callout and sends the response.
bool assignZero(ConstSubnet4Ptr &subnet, const ClientClasses &client_classes)
Assign the 0.0.0.0 address to an IPv6-Only client.
void deferredUnpack(Pkt4Ptr &query)
Perform deferred option unpacking.
Pkt4Ptr processLocalizedQuery4(AllocEngine::ClientContext4Ptr &ctx, bool allow_answer_park)
Process a localized incoming DHCPv4 query.
Exception thrown when host name sanitizing reduces the domain name to an empty string.
static std::list< std::string > getDBVersions()
Return extended version info for registered backends.
static void create()
Creates new instance of the HostMgr.
std::string getIdentifierAsText() const
Returns host identifier in a textual form.
IdentifierType
Type of the host identifier.
@ IDENT_FLEX
Flexible host identifier.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
bool send(const Pkt6Ptr &pkt)
Sends an IPv6 packet.
void closeSockets()
Closes all open sockets.
void setMatchingPacketFilter(const bool direct_response_desired=false)
Set Packet Filter object to handle send/receive packets.
uint16_t getSocket(const isc::dhcp::Pkt6Ptr &pkt)
Return most suitable socket for transmitting specified IPv6 packet.
static TrackingLeaseMgr & instance()
Return current lease manager.
static std::list< std::string > getDBVersions()
Return extended version info for registered backends.
static void destroy()
Destroy lease manager.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
virtual bool addLease(const Lease4Ptr &lease)=0
Adds an IPv4 lease.
virtual bool deleteLease(const Lease4Ptr &lease)=0
Deletes an IPv4 lease.
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
static std::list< std::string > getDBVersions()
Return extended version info for registered backends.
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
static const OptionDefinition & DHO_DHCP_SERVER_IDENTIFIER_DEF()
Get definition of DHO_DHCP_SERVER_IDENTIFIER option.
static const OptionDefinition & DHO_DHCP_AGENT_OPTIONS_DEF()
Get definition of DHO_DHCP_AGENT_OPTIONS option.
static OptionDefinitionPtr getRuntimeOptionDef(const std::string &space, const uint16_t code)
Returns runtime (non-standard) option definition by space and option code.
static OptionDefinitionPtr getLastResortOptionDef(const std::string &space, const uint16_t code)
Returns last resort option definition by space and option code.
Controls the DHCP service enabling status.
Attempt to update lease that was not there.
std::vector< isc::asiolink::IOAddress > AddressContainer
Defines a collection of IPv4 addresses.
Represents DHCPv4 Client FQDN Option (code 81).
static const uint8_t FLAG_N
Bit N.
bool getFlag(const uint8_t flag) const
Checks if the specified flag of the DHCPv4 Client FQDN Option is set.
static const uint8_t FLAG_S
Bit S.
void setDomainName(const std::string &domain_name, const DomainNameType domain_name_type)
Set new domain-name.
void setFlag(const uint8_t flag, const bool set)
Modifies the value of the specified DHCPv4 Client Fqdn Option flag.
static const uint8_t FLAG_E
Bit E.
virtual std::string toText(int indent=0) const
Returns string representation of the option.
Option with defined data fields represented as buffers that can be accessed using data field index.
static unsigned int getLabelCount(const std::string &text_name)
Return the number of labels in the Name.
Base class representing a DHCP option definition.
OptionPtr option_
Option instance.
bool allowedForClientClasses(const ClientClasses &cclasses) const
Validates an OptionDescriptor's client-classes against a list of classes.
Forward declaration to OptionInt.
This class represents vendor-specific information option.
static const size_t OPTION4_HDR_LEN
length of the usual DHCPv4 option header (there are exceptions)
Represents DHCPv4 packet.
static const uint16_t FLAG_BROADCAST_MASK
Mask for the value of flags field in the DHCPv4 message to check whether client requested broadcast r...
Represents DHCPv4-over-DHCPv6 packet.
Represents a DHCPv6 packet.
An exception that is thrown if a DHCPv6 protocol violation occurs while processing a message (e....
Resource race avoidance RAII handler for DHCPv4.
bool tryLock4(const asiolink::IOAddress &addr)
Tries to acquires a resource.
RAII object enabling copying options retrieved from the packet.
Exception thrown when a call to select is interrupted by a signal.
Exception thrown during option unpacking This exception is thrown when an error has occurred,...
static std::string const & resultToText(Result const &result)
Convert enum to string.
Result
Defines the outcome of an asynchronous NCR send.
@ NEXT_STEP_PARK
park the packet
@ NEXT_STEP_CONTINUE
continue normally
@ NEXT_STEP_DROP
drop the packet
@ NEXT_STEP_SKIP
skip the next processing step
static int registerHook(const std::string &name)
Register Hook.
static bool calloutsPresent(int index)
Are callouts present?
static std::vector< std::string > getLibraryNames()
Return list of loaded libraries.
static bool unloadLibraries()
Unload libraries.
static void park(const std::string &hook_name, T parked_object, std::function< void()> unpark_callback)
Park an object (packet).
static void callCallouts(int index, CalloutHandle &handle)
Calls the callouts for a given hook.
static void prepareUnloadLibraries()
Prepare the unloading of libraries.
static bool drop(const std::string &hook_name, T parked_object)
Removes parked object without calling a callback.
static void clearParkingLots()
Clears any parking packets.
Wrapper class around callout handle which automatically resets handle's state.
static ServerHooks & getServerHooks()
Return ServerHooks object.
static std::string getVersion()
Version.
File-based Interprocess Sync Class.
Interprocess Sync Locker Class.
bool unlock()
Release the lock.
bool lock()
Acquire the lock (blocks if something else has acquired a lock on the same task name)
int getExitValue()
Fetches the exit value.
Statistics Manager class.
static StatsMgr & instance()
Statistics Manager accessor method.
static std::string generateName(const std::string &context, Type index, const std::string &stat_name)
Generates statistic name in a given context.
RAII class creating a critical section.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
ThreadPool< std::function< void()> > & getThreadPool()
Get the dhcp thread pool.
void apply(bool enabled, uint32_t thread_count, uint32_t queue_size)
Apply the multi-threading related settings.
Defines classes for storing client class definitions.
int version()
returns Kea hooks version.
Defines the D2ClientConfig class.
Defines the D2ClientMgr class.
Contains declarations for loggers used by the DHCPv4 server component.
Defines the Dhcp4o6Ipc class.
#define VENDOR_ID_CABLE_LABS
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< OptionUint8Array > OptionUint8ArrayPtr
OptionIntArray< uint8_t > OptionUint8Array
OptionInt< uint32_t > OptionUint32
boost::shared_ptr< OptionUint32 > OptionUint32Ptr
void setValue(const std::string &name, const int64_t value)
Records absolute integer observation.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
int get(CalloutHandle &handle)
The gss-tsig-get command.
When a message is logged with DEBUG severity, the debug level associated with the message is also spe...
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
IOAddress getNetmask4(uint8_t len)
Generates an IPv4 netmask of specified length.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< NameChangeRequest > NameChangeRequestPtr
Defines a pointer to a NameChangeRequest.
const isc::log::MessageID DHCP4_BUFFER_RECEIVE_FAIL
boost::shared_ptr< OptionVendor > OptionVendorPtr
Pointer to a vendor option.
isc::log::Logger ddns4_logger(DHCP4_DDNS_LOGGER_NAME)
Logger for Hostname or FQDN processing.
const isc::log::MessageID DHCP4_PACKET_DROP_0004
const isc::log::MessageID DHCP4_SRV_DHCP4O6_ERROR
const isc::log::MessageID DHCP4_RELEASE_EXCEPTION
const isc::log::MessageID DHCP4_SUBNET_DATA
const isc::log::MessageID DHCP4_INIT_REBOOT
const isc::log::MessageID DHCP4_HOOK_PACKET_SEND_SKIP
const isc::log::MessageID DHCP4_FLEX_ID
const isc::log::MessageID DHCP4_PACKET_DROP_0003
const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_PARKING_LOT_FULL
const isc::log::MessageID DHCP4_DEFERRED_OPTION_UNPACK_FAIL
const isc::log::MessageID DHCP4_PACKET_DROP_0001
const isc::log::MessageID DHCP4_QUERY_DATA
const isc::log::MessageID DHCP4_NO_LEASE_INIT_REBOOT
const isc::log::MessageID DHCP4_INFORM_DIRECT_REPLY
const isc::log::MessageID DHCP4_SERVER_INITIATED_DECLINE_ADD_FAILED
boost::shared_ptr< Lease4Collection > Lease4CollectionPtr
A shared pointer to the collection of IPv4 leases.
const isc::log::MessageID DHCP4_HOOK_LEASE4_OFFER_ARGUMENT_MISSING
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
const isc::log::MessageID DHCP4_CLIENT_FQDN_PROCESS
const isc::log::MessageID DHCP4_DEFERRED_OPTION_MISSING
const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_DROP
@ DHO_DOMAIN_NAME_SERVERS
@ DHO_VENDOR_CLASS_IDENTIFIER
@ DHO_DHCP_REBINDING_TIME
@ DHO_DHCP_SERVER_IDENTIFIER
@ DHO_DHCP_CLIENT_IDENTIFIER
@ DHO_DHCP_REQUESTED_ADDRESS
@ DHO_DHCP_PARAMETER_REQUEST_LIST
const isc::log::MessageID DHCP4_PACKET_PROCESS_EXCEPTION_MAIN
const isc::log::MessageID DHCP4_PACKET_DROP_0008
const isc::log::MessageID DHCP4_RELEASE_EXPIRED
const isc::log::MessageID DHCP4_HOOK_LEASES4_COMMITTED_DROP
const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_4O6_PARKING_LOT_FULL
const isc::log::MessageID DHCP4_DHCP4O6_SUBNET_SELECTION_FAILED
const isc::log::MessageID DHCP4_RELEASE_FAIL_WRONG_CLIENT
const isc::log::MessageID DHCP4_HOOK_LEASES4_COMMITTED_PARKING_LOT_FULL
const isc::log::MessageID DHCP4_HOOK_BUFFER_RCVD_DROP
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
boost::shared_ptr< OptionCustom > OptionCustomPtr
A pointer to the OptionCustom object.
const isc::log::MessageID DHCP4_HOOK_PACKET_RCVD_SKIP
const int DBG_DHCP4_BASIC_DATA
Debug level used to log the traces with some basic data.
const isc::log::MessageID DHCP4_LEASE_ALLOC
const int DBG_DHCP4_DETAIL
Debug level used to trace detailed errors.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
isc::log::Logger lease4_logger(DHCP4_LEASE_LOGGER_NAME)
Logger for lease allocation logic.
const isc::log::MessageID DHCP4_NCR_CREATION_FAILED
const isc::log::MessageID DHCP4_CLIENT_FQDN_SCRUBBED_EMPTY
isc::log::Logger options4_logger(DHCP4_OPTIONS_LOGGER_NAME)
Logger for options parser.
const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_SKIP
const int DBG_DHCP4_DETAIL_DATA
This level is used to log the contents of packets received and sent.
const isc::log::MessageID DHCP4_PACKET_PACK
boost::shared_ptr< AllocEngine > AllocEnginePtr
A pointer to the AllocEngine object.
ContinuationPtr makeContinuation(Continuation &&cont)
Continuation factory.
const isc::log::MessageID DHCP4_DECLINE_FAIL
const isc::log::MessageID DHCP4_RECOVERED_STASHED_RELAY_AGENT_INFO
const isc::log::MessageID DHCP4_LEASE_REUSE
const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_PARK
boost::shared_ptr< const CfgHostOperations > ConstCfgHostOperationsPtr
Pointer to the const object.
boost::shared_ptr< CfgIface > CfgIfacePtr
A pointer to the CfgIface .
const isc::log::MessageID DHCP4_PACKET_PACK_FAIL
boost::shared_ptr< ClientClassDef > ClientClassDefPtr
a pointer to an ClientClassDef
const isc::log::MessageID DHCP4_DDNS_REQUEST_SEND_FAILED
const isc::log::MessageID DHCP4_GENERATE_FQDN
const isc::log::MessageID DHCP4_CLASS_ASSIGNED
const isc::log::MessageID DHCP4_PACKET_PROCESS_STD_EXCEPTION
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
const isc::log::MessageID DHCP4_RESPONSE_HOSTNAME_DATA
const isc::log::MessageID DHCP4_BUFFER_WAIT_SIGNAL
const isc::log::MessageID DHCP4_HOOK_LEASE4_RELEASE_SKIP
const isc::log::MessageID DHCP4_POST_ALLOCATION_NAME_UPDATE_FAIL
const isc::log::MessageID DHCP4_PACKET_NAK_0001
const isc::log::MessageID DHCP4_HOOK_DECLINE_SKIP
const isc::log::MessageID DHCP4_HOOK_LEASE4_OFFER_PARK
const isc::log::MessageID DHCP4_DECLINE_LEASE_MISMATCH
const isc::log::MessageID DHCP4_SRV_UNLOAD_LIBRARIES_ERROR
const isc::log::MessageID DHCP4_ADDITIONAL_CLASS_EVAL_ERROR
const isc::log::MessageID DHCP4_RESPONSE_HOSTNAME_GENERATE
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
const isc::log::MessageID DHCP4_PACKET_DROP_0013
const isc::log::MessageID DHCP4_PACKET_QUEUE_FULL
const isc::log::MessageID DHCP4_LEASE_OFFER
const isc::log::MessageID DHCP4_PACKET_DROP_0009
const isc::log::MessageID DHCP4_PACKET_RECEIVED
boost::shared_ptr< Pkt4o6 > Pkt4o6Ptr
A pointer to Pkt4o6 object.
const isc::log::MessageID DHCP4_RELEASE_DELETED
const isc::log::MessageID DHCP4_BUFFER_UNPACK
const isc::log::MessageID DHCP4_CLIENT_HOSTNAME_DATA
OptionContainer::nth_index< 5 >::type OptionContainerCancelIndex
Type of the index #5 - option cancellation flag.
const isc::log::MessageID DHCP4_CLASSES_ASSIGNED_AFTER_SUBNET_SELECTION
const isc::log::MessageID DHCP4_PACKET_SEND_FAIL
std::pair< OptionContainerPersistIndex::const_iterator, OptionContainerPersistIndex::const_iterator > OptionContainerPersistRange
Pair of iterators to represent the range of options having the same persistency flag.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
const isc::log::MessageID DHCP4_DHCP4O6_SUBNET_DATA
boost::shared_ptr< Option4ClientFqdn > Option4ClientFqdnPtr
A pointer to the Option4ClientFqdn object.
const isc::log::MessageID DHCP4_CLIENTID_IGNORED_FOR_LEASES
const isc::log::MessageID DHCP4_CLIENT_NAME_PROC_FAIL
const isc::log::MessageID DHCP4_CLIENT_HOSTNAME_PROCESS
const isc::log::MessageID DHCP4_HOOK_DDNS_UPDATE
const isc::log::MessageID DHCP4_SRV_CONSTRUCT_ERROR
const isc::log::MessageID DHCP4_SERVER_INITIATED_DECLINE
boost::shared_ptr< Expression > ExpressionPtr
const isc::log::MessageID DHCP4_RELEASE_FAIL
const isc::log::MessageID DHCP4_RELEASE_FAIL_NO_LEASE
const isc::log::MessageID DHCP4_CLIENT_HOSTNAME_MALFORMED
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
boost::shared_ptr< OptionString > OptionStringPtr
Pointer to the OptionString object.
isc::log::Logger bad_packet4_logger(DHCP4_BAD_PACKET_LOGGER_NAME)
Logger for rejected packets.
isc::hooks::CalloutHandlePtr getCalloutHandle(const T &pktptr)
CalloutHandle Store.
const isc::log::MessageID DHCP4_V6_ONLY_PREFERRED_MISSING_IN_ACK
const isc::log::MessageID DHCP4_PACKET_DROP_0006
const int DBG_DHCP4_BASIC
Debug level used to trace basic operations within the code.
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
const isc::log::MessageID DHCP4_SRV_D2STOP_ERROR
const isc::log::MessageID DHCP4_SERVER_INITIATED_DECLINE_UPDATE_FAILED
const isc::log::MessageID DHCP4_RESPONSE_FQDN_DATA
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
boost::shared_ptr< Continuation > ContinuationPtr
Define the type of shared pointers to continuations.
const isc::log::MessageID DHCP4_DECLINE_LEASE_NOT_FOUND
boost::shared_ptr< OptionContainer > OptionContainerPtr
Pointer to the OptionContainer object.
boost::shared_ptr< ClientClassDefList > ClientClassDefListPtr
Defines a pointer to a ClientClassDefList.
const isc::log::MessageID DHCP4_PACKET_DROP_0005
const isc::log::MessageID DHCP4_SUBNET_DYNAMICALLY_CHANGED
const isc::log::MessageID DHCP4_SHUTDOWN_REQUEST
@ DHCP_NOTYPE
Message Type option missing.
const isc::log::MessageID DHCP4_PACKET_NAK_0003
const isc::log::MessageID DHCP4_TESTING_MODE_SEND_TO_SOURCE_ENABLED
boost::shared_ptr< const CfgSubnets4 > ConstCfgSubnets4Ptr
Const pointer.
const isc::log::MessageID DHCP4_BUFFER_RECEIVED
bool evaluateBool(const Expression &expr, Pkt &pkt)
Evaluate a RPN expression for a v4 or v6 packet and return a true or false decision.
const isc::log::MessageID DHCP4_SUBNET_SELECTION_FAILED
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
const isc::log::MessageID DHCP4_RESPONSE_DATA
const isc::log::MessageID DHCP4_ADDITIONAL_CLASS_NO_TEST
isc::log::Logger packet4_logger(DHCP4_PACKET_LOGGER_NAME)
Logger for processed packets.
OptionContainer::nth_index< 2 >::type OptionContainerPersistIndex
Type of the index #2 - option persistency flag.
const isc::log::MessageID DHCP4_DECLINE_LEASE
const isc::log::MessageID DHCP4_PACKET_SEND
boost::shared_ptr< OptionVendorClass > OptionVendorClassPtr
Defines a pointer to the OptionVendorClass.
const isc::log::MessageID DHCP4_RELEASE
const isc::log::MessageID DHCP4_HOOK_LEASE4_OFFER_DROP
const isc::log::MessageID DHCP4_HOOK_BUFFER_RCVD_SKIP
const isc::log::MessageID DHCP4_UNKNOWN_ADDRESS_REQUESTED
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
const isc::log::MessageID DHCP4_PACKET_PROCESS_STD_EXCEPTION_MAIN
const isc::log::MessageID DHCP4_DHCP4O6_HOOK_SUBNET4_SELECT_DROP
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
const isc::log::MessageID DHCP4_OPEN_SOCKET
const isc::log::MessageID DHCP4_PACKET_DROP_0007
boost::shared_ptr< CfgSharedNetworks4 > CfgSharedNetworks4Ptr
Pointer to the configuration of IPv4 shared networks.
const isc::log::MessageID DHCP4_HOOK_PACKET_SEND_DROP
const isc::log::MessageID DHCP4_RESERVED_HOSTNAME_ASSIGNED
isc::log::Logger dhcp4_logger(DHCP4_APP_LOGGER_NAME)
Base logger for DHCPv4 server.
const isc::log::MessageID DHCP4_CLASSES_ASSIGNED
@ RAI_OPTION_SERVER_ID_OVERRIDE
@ RAI_OPTION_AGENT_CIRCUIT_ID
const isc::log::MessageID DHCP4_QUERY_LABEL
bool isClientClassBuiltIn(const ClientClass &client_class)
Check if a client class name is builtin.
const isc::log::MessageID DHCP4_PACKET_NAK_0002
const int DBG_DHCP4_HOOKS
Debug level used to trace hook related operations.
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
const isc::log::MessageID DHCP4_HOOK_BUFFER_SEND_SKIP
const isc::log::MessageID DHCP4_PACKET_PROCESS_EXCEPTION
const isc::log::MessageID DHCP4_V6_ONLY_PREFERRED_MISSING_IN_OFFER
std::pair< OptionContainerCancelIndex::const_iterator, OptionContainerCancelIndex::const_iterator > OptionContainerCancelRange
Pair of iterators to represent the range of options having the same cancellation flag.
const isc::log::MessageID DHCP4_PACKET_OPTIONS_SKIPPED
const isc::log::MessageID DHCP4_EMPTY_HOSTNAME
const isc::log::MessageID DHCP4_REQUEST
const isc::log::MessageID DHCP4_SUBNET_SELECTED
const isc::log::MessageID DHCP4_PACKET_DROP_0010
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
const isc::log::MessageID DHCP4_SERVER_INITIATED_DECLINE_RESOURCE_BUSY
const isc::log::MessageID DHCP4_CLASS_UNCONFIGURED
const isc::log::MessageID DHCP4_DHCP4O6_SUBNET_SELECTED
boost::shared_ptr< Option > OptionPtr
const isc::log::MessageID DHCP4_HOOK_LEASE4_OFFER_PARKING_LOT_FULL
const int DBG_DHCP4_START
Debug level used to log information during server startup.
const isc::log::MessageID DHCP4_HOOK_LEASES4_COMMITTED_PARK
const isc::log::MessageID DHCP4_ADDITIONAL_CLASS_UNDEFINED
const isc::log::MessageID DHCP4_ADDITIONAL_CLASS_EVAL_RESULT
const isc::log::MessageID DHCP4_DHCP4O6_HOOK_SUBNET4_SELECT_SKIP
const isc::log::MessageID DHCP4_PACKET_DROP_0014
std::list< ConstCfgOptionPtr > CfgOptionList
Const pointer list.
const isc::log::MessageID DHCP4_DISCOVER
const isc::log::MessageID DHCP4_CLIENT_HOSTNAME_SCRUBBED_EMPTY
boost::shared_ptr< const CfgOption > ConstCfgOptionPtr
Const pointer.
const isc::log::MessageID DHCP4_PACKET_NAK_0004
const isc::log::MessageID DHCP4_CLIENT_FQDN_DATA
const isc::log::MessageID DHCP4_PACKET_DROP_0002
isc::log::Logger hooks_logger("hooks")
Hooks Logger.
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
boost::shared_ptr< ParkingLot > ParkingLotPtr
Type of the pointer to the parking lot.
const int DBGLVL_TRACE_BASIC
Trace basic operations.
const int DBGLVL_PKT_HANDLING
This debug level is reserved for logging the details of packet handling, such as dropping the packet ...
std::unique_ptr< StringSanitizer > StringSanitizerPtr
Type representing the pointer to the StringSanitizer.
void decodeFormattedHexString(const string &hex_string, vector< uint8_t > &binary)
Converts a formatted string of hexadecimal digits into a vector.
string trim(const string &input)
Trim leading and trailing spaces.
Defines the logger used by the top-level component of kea-lfc.
This file defines abstract classes for exchanging NameChangeRequests.
This file provides the classes needed to embody, compose, and decompose DNS update requests that are ...
Standard implementation of read-write mutexes with writer preference using C++11 mutex and condition ...
#define DHCP4_OPTION_SPACE
global std option spaces
Context information for the DHCPv4 lease allocation.
static const uint32_t INFINITY_LFT
Infinity (means static, i.e. never expire)
static constexpr uint32_t STATE_DEFAULT
A lease in the default state.
static std::string lifetimeToText(uint32_t lifetime)
Print lifetime.
static constexpr uint32_t STATE_RELEASED
Released lease held in the database for lease affinity.
Subnet selector used to specify parameters used to select a subnet.
asiolink::IOAddress local_address_
Address on which the message was received.
bool dhcp4o6_
Specifies if the packet is DHCP4o6.
asiolink::IOAddress option_select_
RAI link select or subnet select option.
std::string iface_name_
Name of the interface on which the message was received.
asiolink::IOAddress ciaddr_
ciaddr from the client's message.
ClientClasses client_classes_
Classes that the client belongs to.
asiolink::IOAddress remote_address_
Source address of the message.
OptionPtr interface_id_
Interface id option.
asiolink::IOAddress first_relay_linkaddr_
First relay link address.
asiolink::IOAddress giaddr_
giaddr from the client's message.
bool add(const WorkItemPtr &item)
add a work item to the thread pool