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())
309 .arg(classes.toText());
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));
804 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
807 callout_handle->setArgument(
"query4", query);
808 callout_handle->setArgument(
"subnet4", subnet);
809 callout_handle->setArgument(
"subnet4collection",
810 cfgmgr.getCurrentCfg()->
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();
916 selector.local_address_ = query->getLocalAddr();
917 selector.client_classes_ = query->classes_;
918 selector.iface_name_ = query->getIface();
920 selector.dhcp4o6_ =
true;
922 selector.remote_address_ = query->getRemoteAddr();
923 selector.first_relay_linkaddr_ =
IOAddress(
"::");
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()) {
937 selector.first_relay_linkaddr_ = relay.linkaddr_;
941 selector.interface_id_ =
949 OptionCustomPtr oc = boost::dynamic_pointer_cast<OptionCustom>(sbnsel);
951 selector.option_select_ = oc->readAddress();
956 subnet = cfgmgr.getCurrentCfg()->getCfgSubnets4()->selectSubnet4o6(selector);
968 shared_ptr<ScopedCalloutHandleState> callout_handle_state(
969 std::make_shared<ScopedCalloutHandleState>(callout_handle));
972 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
975 callout_handle->setArgument(
"query4", query);
976 callout_handle->setArgument(
"subnet4", subnet);
977 callout_handle->setArgument(
"subnet4collection",
978 cfgmgr.getCurrentCfg()->
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;
1354 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
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());
1482 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
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);
1736 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
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;
1911 ScopedEnableOptionsCopy<Pkt4> query_resp_options_copy(query, rsp);
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())
1980 ScopedEnableOptionsCopy<Pkt4> resp4_options_copy(rsp);
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());
2064 IOAddress local_addr = ex.getQuery()->getLocalAddr();
2065 Pkt4Ptr query = ex.getQuery();
2067 if (local_addr.isV4Bcast() || query->isDhcp4o6()) {
2073 opt_srvid->writeAddress(local_addr);
2074 ex.getResponse()->addOption(opt_srvid);
2090 const ConstHostPtr& host = ex.getContext()->currentHost();
2091 if (host && !host->getCfgOption4()->empty()) {
2092 co_list.push_back(host->getCfgOption4());
2096 Pkt4Ptr resp = ex.getResponse();
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);
2130 .arg(ex.getQuery()->getLabel())
2137 if (ccdef->getCfgOption()->empty()) {
2142 co_list.push_back(ccdef->getCfgOption());
2166 if (co_list.empty()) {
2170 Pkt4Ptr query = ex.getQuery();
2171 Pkt4Ptr resp = ex.getResponse();
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) {
2234 if (desc.option_ && desc.allowedForClientClasses(cclasses)) {
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()) {
2341 Pkt4Ptr query = ex.getQuery();
2342 Pkt4Ptr resp = ex.getResponse();
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) {
2478 if (desc.option_ && desc.allowedForClientClasses(cclasses)) {
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()) {
2517 Pkt4Ptr resp = ex.getResponse();
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) {
2528 if (desc.option_ && desc.allowedForClientClasses(cclasses)) {
2529 resp->addOption(desc.option_);
2543 Pkt4Ptr query = ex.getQuery();
2544 Pkt4Ptr resp = ex.getResponse();
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();
2570 CfgMgr::instance().getD2ClientMgr().getUpdateDirections(*fqdn, fqdn_fwd, fqdn_rev);
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));
2658 auto ctx = ex.getContext();
2659 ctx->fwd_dns_update_ = fqdn_fwd;
2660 ctx->rev_dns_update_ = fqdn_rev;
2661 ctx->hostname_ = hostname;
2673 .arg(ex.getQuery()->getLabel())
2685 .arg(ex.getQuery()->getLabel())
2686 .arg(fqdn->toText());
2696 *(ex.getContext()->getDdnsParams()));
2701 if (ex.getContext()->currentHost() &&
2702 !ex.getContext()->currentHost()->getHostname().empty()) {
2703 fqdn_resp->setDomainName(d2_mgr.qualifyName(ex.getContext()->currentHost()->getHostname(),
2704 *(ex.getContext()->getDdnsParams()),
true),
2711 *(ex.getContext()->getDdnsParams()));
2727 .arg(ex.getQuery()->getLabel())
2728 .arg(fqdn_resp->toText());
2729 ex.getResponse()->addOption(fqdn_resp);
2738 OptionStringPtr opt_hostname = boost::dynamic_pointer_cast<OptionString>
2743 .arg(ex.getQuery()->getLabel())
2744 .arg(opt_hostname->getValue());
2752 if (ctx->currentHost() && !ctx->currentHost()->getHostname().empty()) {
2754 std::string hostname = d2_mgr.qualifyName(ctx->currentHost()->getHostname(),
2755 *(ex.getContext()->getDdnsParams()),
false);
2757 boost::algorithm::to_lower(hostname);
2759 .arg(ex.getQuery()->getLabel())
2764 ex.getResponse()->addOption(opt_hostname_resp);
2775 ex.getContext()->getDdnsParams()->getReplaceClientNameMode();
2778 if (!opt_hostname) {
2785 .arg(ex.getQuery()->getLabel());
2789 ex.getResponse()->addOption(opt_hostname_resp);
2797 .arg(ex.getQuery()->getLabel())
2798 .arg(opt_hostname->getValue());
2801 unsigned int label_count;
2807 }
catch (
const std::exception& exc) {
2809 .arg(ex.getQuery()->getLabel())
2818 if (label_count == 0) {
2820 .arg(ex.getQuery()->getLabel());
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(
2869 d2_mgr.qualifyName(hostname, *(ex.getContext()->getDdnsParams()),
2877 .arg(ex.getQuery()->getLabel())
2878 .arg(opt_hostname_resp->getValue());
2879 ex.getResponse()->addOption(opt_hostname_resp);
2888 "NULL lease specified when creating NameChangeRequest");
2892 if (!ddns_params.getEnableUpdates()) {
2896 if ((lease->reuseable_valid_lft_ == 0) &&
2897 (!old_lease || ddns_params.getUpdateOnRenew() ||
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);
2947 Pkt4Ptr query = ex.getQuery();
2948 Pkt4Ptr resp = ex.getResponse();
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(),
2972 ex.setIPv6OnlyPreferred(
true);
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())
3013 .arg(hint.toText());
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());
3060 ClientIdPtr client_id = ex.getContext()->clientid_;
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())
3140 .arg(hint.toText());
3142 ex.deleteResponse();
3148 if ((known_client && (lease->addr_ != hint)) ||
3149 (!known_client && authoritative) ||
3150 (!original_subnet)) {
3153 .arg(query->getLabel())
3154 .arg(hint.toText());
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) {
3308 *ex.getContext()->getDdnsParams());
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)");
3343 ex.deleteResponse();
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);
3474 const Pkt4Ptr& query = ex.getQuery();
3478 return (query->getRemotePort());
3489 Pkt4Ptr query = ex.getQuery();
3490 Pkt4Ptr response = ex.getResponse();
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);
3575 Pkt4Ptr query = ex.getQuery();
3576 Pkt4Ptr response = ex.getResponse();
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());
3674 Pkt4Ptr query = ex.getQuery();
3675 Pkt4Ptr response = ex.getResponse();
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();
3742 if (!next_server.isV4Zero()) {
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()),
3780 ex.setReservedMessageFields();
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);
3833 if (!ex.getResponse()) {
3840 if (!ex.getResponse()->getYiaddr().isV4Zero() || ex.getIPv6OnlyPreferred()) {
3843 ex.conditionallySetReservedClientClasses();
3849 .arg(discover->getLabel())
3850 .arg(discover->getName())
3851 .arg(discover->getClasses().toText());
3856 if (ex.getIPv6OnlyPreferred()) {
3860 .arg(discover->getLabel());
3888 context = ex.getContext();
3890 return (ex.getResponse());
3915 Pkt4Ptr response = ex.getResponse();
3919 }
else if (request->inClass(
"BOOTP")) {
3921 response->addClass(
"BOOTP");
3926 if (!response->getYiaddr().isV4Zero() || ex.getIPv6OnlyPreferred()) {
3929 ex.conditionallySetReservedClientClasses();
3935 .arg(request->getLabel())
3936 .arg(request->getName())
3937 .arg(request->getClasses().toText());
3942 if (ex.getIPv6OnlyPreferred()) {
3946 .arg(request->getLabel());
3969 context = ex.getContext();
3971 return (ex.getResponse());
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());
4024 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(release);
4027 callout_handle->setArgument(
"query4", release);
4030 callout_handle->setArgument(
"lease4", lease);
4044 .arg(release->getLabel());
4052 bool success =
false;
4053 bool expired =
false;
4054 auto expiration_cfg =
CfgMgr::instance().getCurrentCfg()->getCfgExpiration();
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));
4102 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
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);
4219 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(decline);
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));
4272 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
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));
4374 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
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);
4438 Pkt4Ptr ack = ex.getResponse();
4442 ex.conditionallySetReservedClientClasses();
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());
4480 return (ex.getResponse());
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());
4898 Pkt4Ptr query = ex.getQuery();
4906 Pkt4Ptr resp = ex.getResponse();
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);
5058 if (d2_mgr.ddnsEnabled()) {
5063 this, ph::_1, ph::_2));
5070 if (d2_mgr.ddnsEnabled()) {
5073 d2_mgr.stopSender();
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.
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.
static IOServiceMgr & instance()
Access the IOServiceMgr singleton instance.
The IOService class is a wrapper for the ASIO io_service class.
static HttpCommandMgr & instance()
HttpCommandMgr is a singleton 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.
static CfgMgr & instance()
returns a single instance of Configuration Manager
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.
Client race avoidance RAII handler.
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.
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
static Dhcp4to6Ipc & instance()
Returns pointer to the sole instance of Dhcp4to6Ipc.
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.
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.
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.
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
isc::dhcp::ConstSubnet4Ptr selectSubnet4o6(const Pkt4Ptr &query, bool &drop, bool sanity_only=false, bool allow_answer_park=true)
Selects a subnet for a given client's DHCP4o6 packet.
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.
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.
isc::dhcp::ConstSubnet4Ptr selectSubnet(const Pkt4Ptr &query, bool &drop, bool sanity_only=false, bool allow_answer_park=true)
Selects a subnet for a given client's packet.
static int getHookIndexSubnet4Select()
Returns the index for "subnet4_select" hook point.
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.
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.
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.
static std::list< std::string > getDBVersions()
Return extended version info for registered backends.
static void create()
Creates new instance of the HostMgr.
IdentifierType
Type of the host identifier.
@ IDENT_FLEX
Flexible host identifier.
std::string getIdentifierAsText() const
Returns host identifier in a textual form.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
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.
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.
static const uint8_t FLAG_S
Bit S.
static const uint8_t FLAG_E
Bit E.
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.
Class which represents an option carrying a single string value.
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.
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,...
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.
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.
Defines classes for storing client class definitions.
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
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_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
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
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 std::string lifetimeToText(uint32_t lifetime)
Print lifetime.
static const uint32_t STATE_DEFAULT
A lease in the default state.
static const 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 ciaddr_
ciaddr from the client's message.