8#include <kea_version.h>
68#include <boost/algorithm/string.hpp>
69#include <boost/foreach.hpp>
70#include <boost/range/adaptor/reversed.hpp>
71#include <boost/pointer_cast.hpp>
72#include <boost/shared_ptr.hpp>
90namespace ph = std::placeholders;
96 int hook_index_buffer4_receive_;
97 int hook_index_pkt4_receive_;
98 int hook_index_subnet4_select_;
99 int hook_index_leases4_committed_;
100 int hook_index_lease4_release_;
101 int hook_index_pkt4_send_;
102 int hook_index_buffer4_send_;
103 int hook_index_lease4_decline_;
104 int hook_index_host4_identifier_;
105 int hook_index_ddns4_update_;
106 int hook_index_lease4_offer_;
107 int hook_index_lease4_server_decline_;
128std::set<std::string> dhcp4_statistics = {
130 "pkt4-discover-received",
131 "pkt4-offer-received",
132 "pkt4-request-received",
135 "pkt4-release-received",
136 "pkt4-decline-received",
137 "pkt4-inform-received",
138 "pkt4-unknown-received",
145 "v4-allocation-fail",
146 "v4-allocation-fail-shared-network",
147 "v4-allocation-fail-subnet",
148 "v4-allocation-fail-no-pools",
149 "v4-allocation-fail-classes",
150 "v4-reservation-conflicts",
170 : alloc_engine_(alloc_engine), query_(query), resp_(),
171 context_(context), ipv6_only_preferred_(false) {
173 if (!alloc_engine_) {
175 " when creating an instance of the Dhcpv4Exchange");
180 " creating an instance of the Dhcpv4Exchange");
189 context_->subnet_ = subnet;
195 if (subnet && !context_->early_global_reservations_lookup_) {
196 OptionPtr opt_clientid = query->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
198 context_->clientid_.reset(
new ClientId(opt_clientid->getData()));
204 if (subnet->getReservationsInSubnet() ||
205 subnet->getReservationsGlobal()) {
208 if (!context_->early_global_reservations_lookup_) {
213 alloc_engine->findReservation(*context_);
216 subnet->getSharedNetwork(sn);
226 auto global_host = context_->globalHost();
227 auto current_host = context_->currentHost();
228 if ((!context_->early_global_reservations_lookup_ &&
229 global_host && !global_host->getClientClasses4().empty()) ||
230 (!sn && current_host && !current_host->getClientClasses4().empty())) {
251 if (!context_->hosts_.empty()) {
252 query->addClass(
"KNOWN");
254 .arg(query->getLabel())
257 query->addClass(
"UNKNOWN");
259 .arg(query->getLabel())
268 .arg(query_->getLabel())
269 .arg(classes.toText());
272 if (query_->inClass(
"DROP")) {
274 .arg(query_->getHWAddrLabel())
275 .arg(query_->toText());
277 static_cast<int64_t
>(1));
284 uint8_t resp_type = 0;
298 resp_.reset(
new Pkt4(resp_type,
getQuery()->getTransid()));
300 copyDefaultOptions();
314 const Pkt6Ptr& query6 = query->getPkt6();
318 if (!query6->relay_info_.empty()) {
319 resp6->copyRelayInfo(query6);
322 resp6->setIface(query6->getIface());
323 resp6->setIndex(query6->getIndex());
324 resp6->setRemoteAddr(query6->getRemoteAddr());
325 resp6->setRemotePort(query6->getRemotePort());
326 resp_.reset(
new Pkt4o6(resp_, resp6));
330Dhcpv4Exchange::copyDefaultFields() {
331 resp_->setIface(query_->getIface());
332 resp_->setIndex(query_->getIndex());
339 resp_->setCiaddr(query_->getCiaddr());
343 resp_->setHops(query_->getHops());
346 resp_->setHWAddr(query_->getHWAddr());
349 resp_->setGiaddr(query_->getGiaddr());
358 HWAddrPtr src_hw_addr = query_->getLocalHWAddr();
360 resp_->setLocalHWAddr(src_hw_addr);
362 HWAddrPtr dst_hw_addr = query_->getRemoteHWAddr();
364 resp_->setRemoteHWAddr(dst_hw_addr);
368 resp_->setFlags(query_->getFlags());
372Dhcpv4Exchange::copyDefaultOptions() {
376 OptionPtr client_id = query_->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
377 if (client_id && echo) {
378 resp_->addOption(client_id);
391 resp_->addOption(subnet_sel);
404 sao->boolValue() && query_->inClass(
"STASH_AGENT_OPTIONS")) {
407 resp_->addOption(rai);
417 for (
auto const& id_type : cfg->getIdentifierTypes()) {
420 if (context->hwaddr_ && !context->hwaddr_->hwaddr_.empty()) {
421 context->addHostIdentifier(id_type, context->hwaddr_->hwaddr_);
426 if (context->clientid_) {
427 const std::vector<uint8_t>& vec = context->clientid_->getClientId();
432 if ((vec[0] == CLIENT_ID_OPTION_TYPE_DUID) && (vec.size() > 5)) {
434 context->addHostIdentifier(id_type,
435 std::vector<uint8_t>(vec.begin() + 5,
447 if (circuit_id_opt) {
448 const OptionBuffer& circuit_id_vec = circuit_id_opt->getData();
449 if (!circuit_id_vec.empty()) {
450 context->addHostIdentifier(id_type, circuit_id_vec);
458 if (context->clientid_) {
459 const std::vector<uint8_t>& vec = context->clientid_->getClientId();
461 context->addHostIdentifier(id_type, vec);
474 std::vector<uint8_t> id;
483 callout_handle->setArgument(
"query4", context->query_);
484 callout_handle->setArgument(
"id_type", type);
485 callout_handle->setArgument(
"id_value",
id);
491 callout_handle->getArgument(
"id_type", type);
492 callout_handle->getArgument(
"id_value",
id);
498 .arg(context->query_->getLabel())
501 context->addHostIdentifier(type,
id);
516 for (
auto const& def : *defs_ptr) {
520 if (def->getMatchExpr()) {
521 query->classes_.erase(def->getName());
528 if (context->currentHost() && context->query_) {
529 const ClientClasses& classes = context->currentHost()->getClientClasses4();
530 for (
auto const& cclass : classes) {
531 context->query_->addClass(cclass);
538 if (context_->subnet_) {
540 context_->subnet_->getSharedNetwork(shared_network);
541 if (shared_network) {
543 if (host && (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL)) {
555 if (!host->getNextServer().isV4Zero()) {
556 resp_->setSiaddr(host->getNextServer());
559 std::string sname = host->getServerHostname();
560 if (!sname.empty()) {
561 resp_->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
565 std::string bootfile = host->getBootFileName();
566 if (!bootfile.empty()) {
567 resp_->setFile(
reinterpret_cast<const uint8_t*
>(bootfile.c_str()),
575 boost::shared_ptr<OptionString> vendor_class =
587 pkt->addClass(
"ALL");
601 for (
auto const& it : *defs_ptr) {
609 if (it->getRequired()) {
613 if (it->getDependOnKnown() != depend_on_known) {
616 it->test(pkt, expr_ptr);
623 const bool use_bcast,
const bool direct_response_desired)
624 : io_service_(new
IOService()), server_port_(server_port),
625 client_port_(client_port), shutdown_(true),
626 alloc_engine_(), use_bcast_(use_bcast),
629 test_send_responses_to_source_(false) {
631 const char* env = std::getenv(
"KEA_TEST_SEND_RESPONSES_TO_SOURCE");
634 test_send_responses_to_source_ =
true;
662 }
catch (
const std::exception &e) {
677 for (
auto const& it : dhcp4_statistics) {
679 stats_mgr.setValue(it,
static_cast<int64_t
>(0));
689 }
catch (
const std::exception& ex) {
696 }
catch (
const std::exception& ex) {
712 if (!names.empty()) {
714 for (
size_t i = 1; i < names.size(); ++i) {
715 msg += std::string(
", ") + names[i];
721 io_service_->stopAndPoll();
732 bool sanity_only,
bool allow_answer_park) {
735 if (query->isDhcp4o6()) {
744 subnet = cfgmgr.getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
756 shared_ptr<ScopedCalloutHandleState> callout_handle_state(
757 std::make_shared<ScopedCalloutHandleState>(callout_handle));
760 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
763 callout_handle->setArgument(
"query4", query);
764 callout_handle->setArgument(
"subnet4", subnet);
765 callout_handle->setArgument(
"subnet4collection",
766 cfgmgr.getCurrentCfg()->
767 getCfgSubnets4()->getAll());
769 auto const tpl(parkingLimitExceeded(
"subnet4_select"));
770 bool const exceeded(get<0>(tpl));
772 uint32_t
const limit(get<1>(tpl));
777 .arg(query->getLabel());
783 "subnet4_select", query, [
this, query, allow_answer_park, callout_handle_state]() {
785 boost::shared_ptr<function<void()>> callback(
786 boost::make_shared<function<
void()>>(
787 [
this, query, allow_answer_park]()
mutable {
790 callout_handle_state->on_completion_ = [callback]() {
813 .arg(query->getLabel());
826 .arg(query->getLabel());
835 .arg(query->getLabel());
841 callout_handle->getArgument(
"subnet4", subnet);
847 .arg(query->getLabel())
848 .arg(subnet->getID());
852 .arg(query->getLabel())
853 .arg(subnet->toText());
858 .arg(query->getLabel());
866 bool sanity_only,
bool allow_answer_park) {
870 selector.
ciaddr_ = query->getCiaddr();
871 selector.giaddr_ = query->getGiaddr();
872 selector.local_address_ = query->getLocalAddr();
873 selector.client_classes_ = query->classes_;
874 selector.iface_name_ = query->getIface();
876 selector.dhcp4o6_ =
true;
878 selector.remote_address_ = query->getRemoteAddr();
879 selector.first_relay_linkaddr_ =
IOAddress(
"::");
882 Pkt4o6Ptr query4o6 = boost::dynamic_pointer_cast<Pkt4o6>(query);
886 const Pkt6Ptr& query6 = query4o6->getPkt6();
889 if (query6 && !query6->relay_info_.empty()) {
890 for (
auto const& relay : boost::adaptors::reverse(query6->relay_info_)) {
891 if (!relay.linkaddr_.isV6Zero() &&
892 !relay.linkaddr_.isV6LinkLocal()) {
893 selector.first_relay_linkaddr_ = relay.linkaddr_;
897 selector.interface_id_ =
905 OptionCustomPtr oc = boost::dynamic_pointer_cast<OptionCustom>(sbnsel);
907 selector.option_select_ = oc->readAddress();
912 subnet = cfgmgr.getCurrentCfg()->getCfgSubnets4()->selectSubnet4o6(selector);
924 shared_ptr<ScopedCalloutHandleState> callout_handle_state(
925 std::make_shared<ScopedCalloutHandleState>(callout_handle));
928 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
931 callout_handle->setArgument(
"query4", query);
932 callout_handle->setArgument(
"subnet4", subnet);
933 callout_handle->setArgument(
"subnet4collection",
934 cfgmgr.getCurrentCfg()->
935 getCfgSubnets4()->getAll());
937 auto const tpl(parkingLimitExceeded(
"subnet4_select"));
938 bool const exceeded(get<0>(tpl));
940 uint32_t
const limit(get<1>(tpl));
945 .arg(query->getLabel());
951 "subnet4_select", query, [
this, query, allow_answer_park, callout_handle_state]() {
953 boost::shared_ptr<function<void()>> callback(
954 boost::make_shared<function<
void()>>(
955 [
this, query, allow_answer_park]()
mutable {
958 callout_handle_state->on_completion_ = [callback]() {
981 .arg(query->getLabel());
994 .arg(query->getLabel());
1003 .arg(query->getLabel());
1009 callout_handle->getArgument(
"subnet4", subnet);
1016 .arg(query->getLabel())
1017 .arg(subnet->getID());
1022 .arg(query->getLabel())
1023 .arg(subnet->toText());
1028 .arg(query->getLabel());
1048 ctx->query_ = query;
1051 ctx->hwaddr_ = query->getHWAddr();
1065 ctx->early_global_reservations_lookup_ = egrl->boolValue();
1069 if (ctx->early_global_reservations_lookup_) {
1071 OptionPtr opt_clientid = query->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
1073 ctx->clientid_.reset(
new ClientId(opt_clientid->getData()));
1082 if (global_host && !global_host->getClientClasses4().empty()) {
1087 const ClientClasses& classes = global_host->getClientClasses4();
1088 for (
auto const& cclass : classes) {
1089 query->addClass(cclass);
1098 query->addClass(
"KNOWN");
1100 .arg(query->getLabel())
1107 if (query->inClass(
"DROP")) {
1110 .arg(query->getHWAddrLabel())
1111 .arg(query->toText());
1113 static_cast<int64_t
>(1));
1118 ctx->hosts_[SUBNET_ID_GLOBAL] = global_host;
1133 while (__AFL_LOOP(fuzzer.maxLoopCount())) {
1145 }
catch (
const std::exception& e) {
1176 uint32_t timeout = 1;
1187 .arg(query->getRemoteAddr().toText())
1188 .arg(query->getRemotePort())
1189 .arg(query->getLocalAddr().toText())
1190 .arg(query->getLocalPort())
1191 .arg(query->getIface());
1207 }
catch (
const std::exception& e) {
1223 .arg(query->getLabel());
1227 query->addPktEvent(
"mt_queued");
1228 typedef function<void()> CallBack;
1229 boost::shared_ptr<CallBack> call_back =
1245 }
catch (
const std::exception& e) {
1247 .arg(query->getLabel())
1268 query->addPktEvent(
"process_started");
1271 query->addClass(
"ALL");
1278 static_cast<int64_t
>(1));
1280 bool skip_unpack =
false;
1294 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
1297 callout_handle->setArgument(
"query4", query);
1309 .arg(query->getRemoteAddr().toText())
1310 .arg(query->getLocalAddr().toText())
1311 .arg(query->getIface());
1322 .arg(query->getRemoteAddr().toText())
1323 .arg(query->getLocalAddr().toText())
1324 .arg(query->getIface());
1328 callout_handle->getArgument(
"query4", query);
1336 .arg(query->getRemoteAddr().toText())
1337 .arg(query->getLocalAddr().toText())
1338 .arg(query->getIface());
1345 .arg(query->getLabel())
1347 }
catch (
const std::exception& e) {
1350 .arg(query->getLabel())
1351 .arg(query->getRemoteAddr().toText())
1352 .arg(query->getLocalAddr().toText())
1353 .arg(query->getIface())
1355 .arg(query->getHWAddrLabel());
1359 static_cast<int64_t
>(1));
1361 static_cast<int64_t
>(1));
1368 .arg(query->getLabel());
1376 }
catch (
const std::exception&) {
1393 static_cast<int64_t
>(1));
1399 int type = query->getType();
1401 .arg(query->getLabel())
1402 .arg(query->getName())
1404 .arg(query->getRemoteAddr())
1405 .arg(query->getLocalAddr())
1406 .arg(query->getIface());
1408 .arg(query->getLabel())
1409 .arg(query->toText());
1422 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
1425 callout_handle->setArgument(
"query4", query);
1438 .arg(query->getLabel());
1442 callout_handle->getArgument(
"query4", query);
1446 if (query->inClass(
"DROP")) {
1448 .arg(query->getHWAddrLabel())
1449 .arg(query->toText());
1451 static_cast<int64_t
>(1));
1460 bool allow_answer_park) {
1469 }
catch (
const std::exception& e) {
1471 .arg(query->getLabel())
1491 this, query, allow_answer_park));
1492 if (!client_handler.tryLock(query, cont)) {
1508 ctx->subnet_ =
selectSubnet(query, drop,
false, allow_answer_park);
1514 }
catch (
const std::exception& e) {
1524 .arg(query->getLabel())
1529 static_cast<int64_t
>(1));
1538 bool allow_answer_park) {
1548 }
catch (
const std::exception& e) {
1550 .arg(query->getLabel())
1559 bool allow_answer_park) {
1567 callout_handle->getContext(
"subnet4", ctx->subnet_);
1577 bool allow_answer_park) {
1584 switch (query->getType()) {
1614 }
catch (
const std::exception& e) {
1624 .arg(query->getLabel())
1629 static_cast<int64_t
>(1));
1636 int hook_idx =
Hooks.hook_index_leases4_committed_;
1637 std::string hook_label =
"leases4_committed";
1641 if (ctx->fake_allocation_) {
1642 hook_idx =
Hooks.hook_index_lease4_offer_;
1643 hook_label =
"lease4_offer";
1673 std::shared_ptr<ScopedCalloutHandleState> callout_handle_state =
1674 std::make_shared<ScopedCalloutHandleState>(callout_handle);
1676 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(query);
1679 callout_handle->setArgument(
"query4", query);
1683 if (ctx->new_lease_ && (ctx->new_lease_->reuseable_valid_lft_ == 0)) {
1684 new_leases->push_back(ctx->new_lease_);
1686 callout_handle->setArgument(
"leases4", new_leases);
1688 if (ctx->fake_allocation_) {
1690 callout_handle->setArgument(
"offer_lifetime", ctx->offer_lft_);
1691 callout_handle->setArgument(
"old_lease", ctx->old_lease_);
1695 if (ctx->old_lease_) {
1696 if ((!ctx->new_lease_) || (ctx->new_lease_->addr_ != ctx->old_lease_->addr_)) {
1697 deleted_leases->push_back(ctx->old_lease_);
1700 callout_handle->setArgument(
"deleted_leases4", deleted_leases);
1703 if (allow_answer_park) {
1704 auto const tpl(parkingLimitExceeded(hook_label));
1705 bool const exceeded(get<0>(tpl));
1707 uint32_t
const limit(get<1>(tpl));
1711 .arg(query->getLabel());
1713 static_cast<int64_t
>(1));
1723 [
this, callout_handle, query, rsp, callout_handle_state, hook_idx, ctx]()
mutable {
1724 if (hook_idx ==
Hooks.hook_index_lease4_offer_) {
1725 bool offer_address_in_use = false;
1727 callout_handle->getArgument(
"offer_address_in_use", offer_address_in_use);
1730 .arg(query->getLabel())
1734 if (offer_address_in_use) {
1736 bool lease_exists = (ctx->offer_lft_ > 0);
1738 typedef function<void()> CallBack;
1741 boost::shared_ptr<CallBack> call_back = boost::make_shared<CallBack>(
1743 callout_handle, query, lease, lease_exists));
1744 callout_handle_state->on_completion_ = [call_back]() {
1757 typedef function<void()> CallBack;
1758 boost::shared_ptr<CallBack> call_back = boost::make_shared<CallBack>(
1760 query, rsp, ctx->subnet_));
1761 callout_handle_state->on_completion_ = [call_back]() {
1776 if (allow_answer_park) {
1784 allow_answer_park) {
1786 .arg(query->getLabel());
1797 .arg(query->getLabel());
1818 }
catch (
const std::exception& e) {
1820 .arg(query->getLabel())
1830 query->addPktEvent(
"process_completed");
1836 bool skip_pack =
false;
1849 ScopedEnableOptionsCopy<Pkt4> query_resp_options_copy(query, rsp);
1852 callout_handle->setArgument(
"query4", query);
1855 callout_handle->setArgument(
"response4", rsp);
1858 callout_handle->setArgument(
"subnet4", subnet);
1871 .arg(query->getLabel());
1878 .arg(rsp->getLabel());
1887 .arg(rsp->getLabel());
1889 }
catch (
const std::exception& e) {
1891 .arg(rsp->getLabel())
1918 ScopedEnableOptionsCopy<Pkt4> resp4_options_copy(rsp);
1921 callout_handle->setArgument(
"response4", rsp);
1934 .arg(rsp->getLabel());
1938 callout_handle->getArgument(
"response4", rsp);
1942 .arg(rsp->getLabel())
1943 .arg(rsp->getName())
1944 .arg(
static_cast<int>(rsp->getType()))
1945 .arg(rsp->getLocalAddr().isV4Zero() ?
"*" : rsp->getLocalAddr().toText())
1946 .arg(rsp->getLocalPort())
1947 .arg(rsp->getRemoteAddr())
1948 .arg(rsp->getRemotePort())
1949 .arg(rsp->getIface().empty() ?
"to be determined from routing" :
1954 .arg(rsp->getLabel())
1955 .arg(rsp->getName())
1956 .arg(
static_cast<int>(rsp->getType()))
1957 .arg(rsp->toText());
1963 }
catch (
const std::exception& e) {
1965 .arg(rsp->getLabel())
1975 boost::shared_ptr<Option4AddrLst> generated =
1976 boost::dynamic_pointer_cast<Option4AddrLst>(srvid);
1982 if (addrs.size() != 1) {
1984 <<
"Expected to contain a single IPv4 address.");
1987 return (addrs[0].toText());
2002 IOAddress local_addr = ex.getQuery()->getLocalAddr();
2003 Pkt4Ptr query = ex.getQuery();
2005 if (local_addr.isV4Bcast() || query->isDhcp4o6()) {
2011 ex.getResponse()->addOption(opt_srvid);
2019 Subnet4Ptr subnet = ex.getContext()->subnet_;
2027 const ConstHostPtr& host = ex.getContext()->currentHost();
2028 if (host && !host->getCfgOption4()->empty()) {
2029 co_list.push_back(host->getCfgOption4());
2033 Pkt4Ptr resp = ex.getResponse();
2036 addr = resp->getYiaddr();
2040 if (pool && !pool->getCfgOption()->empty()) {
2041 co_list.push_back(pool->getCfgOption());
2046 if (!subnet->getCfgOption()->empty()) {
2047 co_list.push_back(subnet->getCfgOption());
2052 subnet->getSharedNetwork(network);
2053 if (network && !network->getCfgOption()->empty()) {
2054 co_list.push_back(network->getCfgOption());
2059 for (
auto const& cclass : classes) {
2062 getClientClassDictionary()->findClass(cclass);
2067 .arg(ex.getQuery()->getLabel())
2074 if (ccdef->getCfgOption()->empty()) {
2079 co_list.push_back(ccdef->getCfgOption());
2092 Subnet4Ptr subnet = ex.getContext()->subnet_;
2103 if (co_list.empty()) {
2107 Pkt4Ptr query = ex.getQuery();
2108 Pkt4Ptr resp = ex.getResponse();
2109 set<uint8_t> requested_opts;
2118 for (uint16_t code : option_prl->getValues()) {
2119 static_cast<void>(requested_opts.insert(code));
2123 std::set<uint8_t> cancelled_opts;
2127 for (
auto const& copts : co_list) {
2135 BOOST_FOREACH(
auto const& desc, prange) {
2138 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2139 static_cast<void>(requested_opts.insert(code));
2145 BOOST_FOREACH(
auto const& desc, crange) {
2148 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2149 static_cast<void>(cancelled_opts.insert(code));
2156 for (uint8_t opt : requested_opts) {
2157 if (cancelled_opts.count(opt) > 0) {
2165 if (!resp->getOption(opt)) {
2167 for (
auto const& copts : co_list) {
2171 resp->addOption(desc.option_);
2184 set<uint32_t> vendor_ids;
2188 vendor_opts = boost::dynamic_pointer_cast<OptionVendorClass>(opt.second);
2190 uint32_t vendor_id = vendor_opts->getVendorId();
2191 static_cast<void>(vendor_ids.insert(vendor_id));
2195 for (
auto const& copts : co_list) {
2198 if (!desc.option_) {
2202 boost::dynamic_pointer_cast<OptionVendorClass>(desc.option_);
2207 uint32_t vendor_id = vendor_opts->getVendorId();
2208 if (vendor_ids.count(vendor_id) > 0) {
2212 resp->Pkt::addOption(desc.option_);
2213 static_cast<void>(vendor_ids.insert(vendor_id));
2222 set<uint32_t> vendor_ids;
2226 vendor_opts = boost::dynamic_pointer_cast<OptionVendor>(opt.second);
2228 uint32_t vendor_id = vendor_opts->getVendorId();
2229 static_cast<void>(vendor_ids.insert(vendor_id));
2233 for (
auto const& copts : co_list) {
2236 if (!desc.option_) {
2240 boost::dynamic_pointer_cast<OptionVendor>(desc.option_);
2245 uint32_t vendor_id = vendor_opts->getVendorId();
2246 if (vendor_ids.count(vendor_id) > 0) {
2252 resp->Pkt::addOption(vendor_opts);
2253 static_cast<void>(vendor_ids.insert(vendor_id));
2262 Subnet4Ptr subnet = ex.getContext()->subnet_;
2273 if (!subnet || co_list.empty()) {
2277 Pkt4Ptr query = ex.getQuery();
2278 Pkt4Ptr resp = ex.getResponse();
2279 set<uint32_t> vendor_ids;
2283 map<uint32_t, OptionVendorPtr> vendor_rsps;
2286 vendor_rsp = boost::dynamic_pointer_cast<OptionVendor>(opt.second);
2288 uint32_t vendor_id = vendor_rsp->getVendorId();
2289 vendor_rsps[vendor_id] = vendor_rsp;
2290 static_cast<void>(vendor_ids.insert(vendor_id));
2296 map<uint32_t, OptionVendorPtr> vendor_reqs;
2299 vendor_req = boost::dynamic_pointer_cast<OptionVendor>(opt.second);
2301 uint32_t vendor_id = vendor_req->getVendorId();
2302 vendor_reqs[vendor_id] = vendor_req;
2303 static_cast<void>(vendor_ids.insert(vendor_id));
2311 vendor_class = boost::dynamic_pointer_cast<OptionVendorClass>(opt.second);
2313 uint32_t vendor_id = vendor_class->getVendorId();
2314 static_cast<void>(vendor_ids.insert(vendor_id));
2320 if (vendor_ids.empty()) {
2324 map<uint32_t, set<uint8_t> > requested_opts;
2338 oro = boost::dynamic_pointer_cast<OptionUint8Array>(oro_generic);
2341 set<uint8_t> oro_req_opts;
2342 for (uint8_t code : oro->getValues()) {
2343 static_cast<void>(oro_req_opts.insert(code));
2349 for (uint32_t vendor_id : vendor_ids) {
2351 std::set<uint8_t> cancelled_opts;
2355 for (
auto const& copts : co_list) {
2364 BOOST_FOREACH(
auto const& desc, prange) {
2367 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2368 static_cast<void>(requested_opts[vendor_id].insert(code));
2375 BOOST_FOREACH(
auto const& desc, crange) {
2378 uint8_t code =
static_cast<uint8_t
>(desc.option_->getType());
2379 static_cast<void>(cancelled_opts.insert(code));
2389 if (requested_opts[vendor_id].empty()) {
2397 if (vendor_rsps.count(vendor_id) > 0) {
2398 vendor_rsp = vendor_rsps[vendor_id];
2406 for (uint8_t opt : requested_opts[vendor_id]) {
2407 if (cancelled_opts.count(opt) > 0) {
2410 if (!vendor_rsp->getOption(opt)) {
2411 for (
auto const& copts : co_list) {
2414 vendor_rsp->addOption(desc.option_);
2424 if (added && (vendor_rsps.count(vendor_id) == 0)) {
2425 resp->Pkt::addOption(vendor_rsp);
2434 static const std::vector<uint16_t> required_options = {
2441 Subnet4Ptr subnet = ex.getContext()->subnet_;
2448 if (co_list.empty()) {
2452 Pkt4Ptr resp = ex.getResponse();
2456 for (
auto const& required : required_options) {
2457 OptionPtr opt = resp->getOption(required);
2460 for (
auto const& copts : co_list) {
2463 resp->addOption(desc.option_);
2477 Pkt4Ptr query = ex.getQuery();
2478 Pkt4Ptr resp = ex.getResponse();
2483 .arg(query->getLabel());
2484 processClientFqdnOption(ex);
2489 .arg(query->getLabel());
2490 processHostnameOption(ex);
2496 std::string hostname;
2497 bool fqdn_fwd =
false;
2498 bool fqdn_rev =
false;
2501 fqdn = boost::dynamic_pointer_cast<Option4ClientFqdn>(resp->getOption(
DHO_FQDN));
2503 hostname = fqdn->getDomainName();
2504 CfgMgr::instance().getD2ClientMgr().getUpdateDirections(*fqdn, fqdn_fwd, fqdn_rev);
2506 opt_hostname = boost::dynamic_pointer_cast<OptionString>
2510 hostname = opt_hostname->getValue();
2515 if (hostname ==
".") {
2521 if (ex.getContext()->getDdnsParams()->getEnableUpdates()) {
2540 Subnet4Ptr subnet = ex.getContext()->subnet_;
2541 callout_handle->setArgument(
"query4", query);
2542 callout_handle->setArgument(
"response4", resp);
2543 callout_handle->setArgument(
"subnet4", subnet);
2544 callout_handle->setArgument(
"hostname", hostname);
2545 callout_handle->setArgument(
"fwd-update", fqdn_fwd);
2546 callout_handle->setArgument(
"rev-update", fqdn_rev);
2547 callout_handle->setArgument(
"ddns-params", ex.getContext()->getDdnsParams());
2553 string hook_hostname;
2554 bool hook_fqdn_fwd =
false;
2555 bool hook_fqdn_rev =
false;
2556 callout_handle->getArgument(
"hostname", hook_hostname);
2557 callout_handle->getArgument(
"fwd-update", hook_fqdn_fwd);
2558 callout_handle->getArgument(
"rev-update", hook_fqdn_rev);
2562 if ((hostname != hook_hostname) || (fqdn_fwd != hook_fqdn_fwd) ||
2563 (fqdn_rev != hook_fqdn_rev)) {
2565 .arg(hostname).arg(hook_hostname).arg(fqdn_fwd).arg(hook_fqdn_fwd)
2566 .arg(fqdn_rev).arg(hook_fqdn_rev);
2567 hostname = hook_hostname;
2568 fqdn_fwd = hook_fqdn_fwd;
2569 fqdn_rev = hook_fqdn_rev;
2573 OptionStringPtr hostname_opt = boost::dynamic_pointer_cast<OptionString>
2576 hostname_opt->setValue(hook_hostname);
2581 fqdn = boost::dynamic_pointer_cast<Option4ClientFqdn>(resp->getOption(
DHO_FQDN));
2592 auto ctx = ex.getContext();
2593 ctx->fwd_dns_update_ = fqdn_fwd;
2594 ctx->rev_dns_update_ = fqdn_rev;
2595 ctx->hostname_ = hostname;
2607 .arg(ex.getQuery()->getLabel())
2619 .arg(ex.getQuery()->getLabel())
2620 .arg(fqdn->toText());
2630 *(ex.getContext()->getDdnsParams()));
2635 if (ex.getContext()->currentHost() &&
2636 !ex.getContext()->currentHost()->getHostname().empty()) {
2637 fqdn_resp->setDomainName(d2_mgr.qualifyName(ex.getContext()->currentHost()->getHostname(),
2638 *(ex.getContext()->getDdnsParams()),
true),
2645 *(ex.getContext()->getDdnsParams()));
2661 .arg(ex.getQuery()->getLabel())
2662 .arg(fqdn_resp->toText());
2663 ex.getResponse()->addOption(fqdn_resp);
2672 OptionStringPtr opt_hostname = boost::dynamic_pointer_cast<OptionString>
2677 .arg(ex.getQuery()->getLabel())
2678 .arg(opt_hostname->getValue());
2686 if (ctx->currentHost() && !ctx->currentHost()->getHostname().empty()) {
2688 std::string hostname = d2_mgr.qualifyName(ctx->currentHost()->getHostname(),
2689 *(ex.getContext()->getDdnsParams()),
false);
2691 boost::algorithm::to_lower(hostname);
2693 .arg(ex.getQuery()->getLabel())
2698 ex.getResponse()->addOption(opt_hostname_resp);
2709 ex.getContext()->getDdnsParams()->getReplaceClientNameMode();
2712 if (!opt_hostname) {
2719 .arg(ex.getQuery()->getLabel());
2723 ex.getResponse()->addOption(opt_hostname_resp);
2731 .arg(ex.getQuery()->getLabel())
2732 .arg(opt_hostname->getValue());
2735 unsigned int label_count;
2741 }
catch (
const std::exception& exc) {
2743 .arg(ex.getQuery()->getLabel())
2752 if (label_count == 0) {
2754 .arg(ex.getQuery()->getLabel());
2770 || label_count < 2) {
2784 ex.getContext()->getDdnsParams()->getHostnameSanitizer();
2787 hostname = sanitizer->scrub(hostname);
2791 boost::algorithm::to_lower(hostname);
2793 if (label_count == 2) {
2801 opt_hostname_resp.reset(
2803 d2_mgr.qualifyName(hostname, *(ex.getContext()->getDdnsParams()),
2811 .arg(ex.getQuery()->getLabel())
2812 .arg(opt_hostname_resp->getValue());
2813 ex.getResponse()->addOption(opt_hostname_resp);
2822 "NULL lease specified when creating NameChangeRequest");
2826 if (!ddns_params.getEnableUpdates()) {
2830 if (!old_lease || ddns_params.getUpdateOnRenew() || !lease->hasIdenticalFqdn(*old_lease)) {
2847 while (current_subnet) {
2853 subnet = current_subnet;
2857 current_subnet = current_subnet->getNextSubnet(subnet, client_classes);
2861 subnet->getSharedNetwork(network);
2878 Pkt4Ptr query = ex.getQuery();
2879 Pkt4Ptr resp = ex.getResponse();
2893 bool fake_allocation = (query->getType() ==
DHCPDISCOVER);
2899 auto const& requested_opts = option_prl->getValues();
2900 if ((std::find(requested_opts.cbegin(), requested_opts.cend(),
2903 ex.setIPv6OnlyPreferred(
true);
2904 ctx->subnet_ = subnet;
2906 if (!fake_allocation) {
2907 resp->setCiaddr(query->getCiaddr());
2923 if (opt_requested_address) {
2924 hint = opt_requested_address->readAddress();
2926 }
else if (!query->getCiaddr().isV4Zero()) {
2927 hint = query->getCiaddr();
2934 auto authoritative =
false;
2940 auto init_reboot = (!fake_allocation && !opt_serverid && opt_requested_address);
2943 .arg(query->getLabel())
2944 .arg(hint.toText());
2948 authoritative = subnet->getAuthoritative();
2954 authoritative = flag->boolValue();
2957 }
else if (fake_allocation) {
2959 .arg(query->getLabel())
2963 .arg(query->getLabel())
2971 if (!subnet && (!init_reboot || authoritative)) {
2978 .arg(query->getLabel())
2979 .arg(query->getRemoteAddr().toText())
2980 .arg(query->getName());
2991 ClientIdPtr client_id = ex.getContext()->clientid_;
2998 auto const& classes = query->getClasses();
3008 if (original_subnet && client_id) {
3012 if (!leases_client_id.empty()) {
3018 for (
auto const& l : leases_client_id) {
3019 if (l->subnet_id_ == s->getID()) {
3029 s = s->getNextSubnet(original_subnet, classes);
3037 if (original_subnet && !lease && hwaddr) {
3041 if (!leases_hwaddr.empty()) {
3046 for (
auto const& l : leases_hwaddr) {
3047 if (l->subnet_id_ == s->getID()) {
3057 s = s->getNextSubnet(original_subnet, classes);
3066 bool known_client = lease && lease->belongsToClient(hwaddr, client_id);
3067 if (!authoritative && !known_client) {
3070 .arg(query->getLabel())
3071 .arg(hint.toText());
3073 ex.deleteResponse();
3079 if ((known_client && (lease->addr_ != hint)) ||
3080 (!known_client && authoritative) ||
3081 (!original_subnet)) {
3084 .arg(query->getLabel())
3085 .arg(hint.toText());
3096 ctx->requested_address_ = hint;
3097 ctx->fake_allocation_ = fake_allocation;
3098 ctx->callout_handle_ = callout_handle;
3114 bool client_name_changed =
false;
3118 if (subnet && ctx->subnet_ && subnet->getID() != ctx->subnet_->getID()) {
3120 subnet->getSharedNetwork(network);
3122 .arg(query->getLabel())
3123 .arg(subnet->toText())
3124 .arg(ctx->subnet_->toText())
3125 .arg(network ? network->getName() :
"<no network?>");
3127 subnet = ctx->subnet_;
3142 ctx->hostname_ =
"";
3143 ctx->fwd_dns_update_ =
false;
3144 ctx->rev_dns_update_ =
false;
3151 if ((lease->hostname_ != ctx->hostname_) ||
3152 (lease->fqdn_fwd_ != ctx->fwd_dns_update_) ||
3153 (lease->fqdn_rev_ != ctx->rev_dns_update_)) {
3154 lease->hostname_ = ctx->hostname_;
3155 lease->fqdn_fwd_ = ctx->fwd_dns_update_;
3156 lease->fqdn_rev_ = ctx->rev_dns_update_;
3157 client_name_changed =
true;
3165 if (fake_allocation) {
3167 .arg(query->getLabel())
3168 .arg(lease->addr_.toText());
3171 .arg(query->getLabel())
3172 .arg(lease->addr_.toText())
3180 if (!ctx->subnet_->getMatchClientId()) {
3182 .arg(ctx->query_->getLabel())
3183 .arg(ctx->subnet_->getID());
3186 resp->setYiaddr(lease->addr_);
3192 if (!fake_allocation) {
3197 resp->setCiaddr(query->getCiaddr());
3206 if (lease->reuseable_valid_lft_ > 0) {
3207 lease->valid_lft_ = lease->reuseable_valid_lft_;
3209 .arg(query->getLabel())
3210 .arg(lease->addr_.toText())
3227 resp->addOption(opt);
3230 resp->addOption(getNetmaskOption(subnet));
3236 if (!fake_allocation) {
3239 *ex.getContext()->getDdnsParams());
3242 .arg(query->getLabel())
3250 if (ctx->unknown_requested_addr_) {
3262 s = s->getNextSubnet(original_subnet);
3270 .arg(query->getLabel())
3271 .arg(query->getCiaddr().toText())
3272 .arg(opt_requested_address ?
3273 opt_requested_address->readAddress().toText() :
"(no address)");
3274 ex.deleteResponse();
3281 .arg(query->getLabel())
3282 .arg(query->getCiaddr().toText())
3283 .arg(opt_requested_address ?
3284 opt_requested_address->readAddress().toText() :
"(no address)");
3296 const Pkt4Ptr& query,
const Pkt4Ptr& resp,
bool client_name_changed) {
3305 opt_hostname = boost::dynamic_pointer_cast<OptionString>(resp->getOption(
DHO_HOST_NAME));
3306 if (!opt_hostname) {
3313 if (lease->hostname_.empty()) {
3320 .generateFqdn(lease->addr_, *(ctx->getDdnsParams()),
static_cast<bool>(fqdn));
3323 .arg(query->getLabel())
3324 .arg(lease->hostname_);
3326 client_name_changed =
true;
3329 if (client_name_changed) {
3335 if (!ctx->fake_allocation_ || (ctx->offer_lft_ > 0)) {
3337 lease->reuseable_valid_lft_ = 0;
3350 opt_hostname->setValue(lease->hostname_);
3354 .arg(query->getLabel())
3355 .arg(lease->hostname_)
3365 uint32_t t2_time = 0;
3367 if (!subnet->getT2().unspecified()) {
3368 t2_time = subnet->getT2();
3369 }
else if (subnet->getCalculateTeeTimes()) {
3371 t2_time =
static_cast<uint32_t
>(round(subnet->getT2Percent() * (lease->valid_lft_)));
3376 uint32_t timer_ceiling = lease->valid_lft_;
3377 if (t2_time > 0 && t2_time < timer_ceiling) {
3379 resp->addOption(t2);
3381 timer_ceiling = t2_time;
3384 uint32_t t1_time = 0;
3386 if (!subnet->getT1().unspecified()) {
3387 t1_time = subnet->getT1();
3388 }
else if (subnet->getCalculateTeeTimes()) {
3390 t1_time =
static_cast<uint32_t
>(round(subnet->getT1Percent() * (lease->valid_lft_)));
3395 if (t1_time > 0 && t1_time < timer_ceiling) {
3397 resp->addOption(t1);
3405 const Pkt4Ptr& query = ex.getQuery();
3409 return (query->getRemotePort());
3420 Pkt4Ptr query = ex.getQuery();
3421 Pkt4Ptr response = ex.getResponse();
3437 }
else if (((query->getType() ==
DHCPINFORM) &&
3438 ((!query->getCiaddr().isV4Zero()) ||
3439 (!query->isRelayed() && !query->getRemoteAddr().isV4Zero()))) ||
3440 ((query->getType() !=
DHCPINFORM) && !query->isRelayed())) {
3441 response->setRemotePort(DHCP4_CLIENT_PORT);
3446 response->setRemotePort(relay_port ? relay_port : DHCP4_SERVER_PORT);
3450 if (query->isRelayed() &&
3456 response->resetIndex();
3458 response->setIface(query->getIface());
3462 IOAddress local_addr = query->getLocalAddr();
3471 if (local_addr.isV4Bcast() || query->isDhcp4o6()) {
3482 response->setLocalAddr(local_addr);
3491 response->setIndex(query->getIndex());
3492 response->setIface(query->getIface());
3498 response->setLocalPort(DHCP4_SERVER_PORT);
3506 Pkt4Ptr query = ex.getQuery();
3507 Pkt4Ptr response = ex.getResponse();
3510 if (query->isDhcp4o6()) {
3511 response->setRemoteAddr(query->getRemoteAddr());
3523 if (!query->getCiaddr().isV4Zero()) {
3524 response->setRemoteAddr(query->getCiaddr());
3531 }
else if (query->isRelayed()) {
3532 response->setRemoteAddr(query->getGiaddr());
3533 response->setFlags(response->getFlags() | BOOTP_BROADCAST);
3538 response->setRemoteAddr(query->getRemoteAddr());
3545 if (query->isRelayed()) {
3554 query->getCiaddr().isV4Zero()) {
3555 response->setFlags(BOOTP_BROADCAST);
3557 response->setRemoteAddr(query->getGiaddr());
3561 }
else if (!query->getCiaddr().isV4Zero()) {
3562 response->setRemoteAddr(query->getCiaddr());
3567 }
else if (response->getType() ==
DHCPNAK) {
3571 }
else if (!response->getYiaddr().isV4Zero()) {
3586 response->setRemoteAddr(response ->getYiaddr());
3594 response->setRemoteAddr(query->getRemoteAddr());
3599 response->setRemoteAddr(query->getRemoteAddr());
3605 Pkt4Ptr query = ex.getQuery();
3606 Pkt4Ptr response = ex.getResponse();
3609 Subnet4Ptr subnet = ex.getContext()->subnet_;
3611 IOAddress subnet_next_server = subnet->getSiaddr();
3612 if (!subnet_next_server.isV4Zero()) {
3613 response->setSiaddr(subnet_next_server);
3616 const string& sname = subnet->getSname();
3617 if (!sname.empty()) {
3623 response->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
3627 const string& filename = subnet->getFilename();
3628 if (!filename.empty()) {
3634 response->setFile(
reinterpret_cast<const uint8_t*
>(filename.c_str()),
3642 if (!classes.empty()) {
3655 size_t found_cnt = 0;
3656 for (
auto const& name : classes) {
3658 if (found_cnt >= 3) {
3672 next_server = cl->getNextServer();
3673 if (!next_server.isV4Zero()) {
3674 response->setSiaddr(next_server);
3679 if (sname.empty()) {
3680 sname = cl->getSname();
3681 if (!sname.empty()) {
3687 response->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
3693 if (filename.empty()) {
3694 filename = cl->getFilename();
3695 if (!filename.empty()) {
3701 response->setFile(
reinterpret_cast<const uint8_t*
>(filename.c_str()),
3711 ex.setReservedMessageFields();
3715Dhcpv4Srv::getNetmaskOption(
const Subnet4Ptr& subnet) {
3724tuple<bool, uint32_t>
3725Dhcpv4Srv::parkingLimitExceeded(
string const& hook_label) {
3727 uint32_t parked_packet_limit(0);
3731 parked_packet_limit = ppl->intValue();
3734 if (parked_packet_limit) {
3738 if (parking_lot && parked_packet_limit <= parking_lot->size()) {
3739 return make_tuple(
true, parked_packet_limit);
3742 return make_tuple(
false, parked_packet_limit);
3764 if (!ex.getResponse()) {
3771 if (!ex.getResponse()->getYiaddr().isV4Zero() || ex.getIPv6OnlyPreferred()) {
3774 ex.conditionallySetReservedClientClasses();
3780 .arg(discover->getLabel())
3781 .arg(discover->getName())
3782 .arg(discover->getClasses().toText());
3787 if (ex.getIPv6OnlyPreferred()) {
3791 .arg(discover->getLabel());
3819 context = ex.getContext();
3821 return (ex.getResponse());
3846 Pkt4Ptr response = ex.getResponse();
3850 }
else if (request->inClass(
"BOOTP")) {
3852 response->addClass(
"BOOTP");
3857 if (!response->getYiaddr().isV4Zero() || ex.getIPv6OnlyPreferred()) {
3860 ex.conditionallySetReservedClientClasses();
3866 .arg(request->getLabel())
3867 .arg(request->getName())
3868 .arg(request->getClasses().toText());
3873 if (ex.getIPv6OnlyPreferred()) {
3877 .arg(request->getLabel());
3900 context = ex.getContext();
3902 return (ex.getResponse());
3918 OptionPtr opt = release->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
3930 .arg(release->getLabel())
3931 .arg(release->getCiaddr().toText());
3935 if (!lease->belongsToClient(release->getHWAddr(), client_id)) {
3937 .arg(release->getLabel())
3938 .arg(release->getCiaddr().toText());
3955 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(release);
3958 callout_handle->setArgument(
"query4", release);
3961 callout_handle->setArgument(
"lease4", lease);
3975 .arg(release->getLabel());
3983 bool success =
false;
3984 bool expired =
false;
3985 auto expiration_cfg =
CfgMgr::instance().getCurrentCfg()->getCfgExpiration();
3988 if (expiration_cfg->getFlushReclaimedTimerWaitTime() &&
3989 expiration_cfg->getHoldReclaimedTime() &&
3992 lease->valid_lft_ = 0;
4008 context->old_lease_ = lease;
4012 .arg(release->getLabel())
4013 .arg(lease->addr_.toText());
4017 .arg(release->getLabel())
4018 .arg(lease->addr_.toText());
4021 .arg(release->getLabel())
4022 .arg(lease->addr_.toText());
4031 static_cast<int64_t
>(-1));
4033 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
4035 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4040 static_cast<int64_t
>(-1));
4047 .arg(release->getLabel())
4048 .arg(lease->addr_.toText());
4053 .arg(release->getLabel())
4054 .arg(release->getCiaddr())
4067 if (!opt_requested_address) {
4070 " in DHCPDECLINE sent from " << decline->getLabel());
4072 IOAddress addr(opt_requested_address->readAddress());
4090 .arg(addr.
toText()).arg(decline->getLabel());
4095 OptionPtr opt_clientid = decline->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
4098 client_id.reset(
new ClientId(opt_clientid->getData()));
4102 if (!lease->belongsToClient(decline->getHWAddr(), client_id)) {
4105 string client_hw = decline->getHWAddr() ?
4106 decline->getHWAddr()->toText(
false) :
"(none)";
4107 string lease_hw = lease->hwaddr_ ?
4108 lease->hwaddr_->toText(
false) :
"(none)";
4111 string client_id_txt = client_id ? client_id->toText() :
"(none)";
4112 string lease_id_txt = lease->client_id_ ?
4113 lease->client_id_->toText() :
"(none)";
4117 .arg(addr.
toText()).arg(decline->getLabel())
4118 .arg(client_hw).arg(lease_hw).arg(client_id_txt).arg(lease_id_txt);
4145 ScopedEnableOptionsCopy<Pkt4> query4_options_copy(decline);
4148 callout_handle->setArgument(
"query4", decline);
4151 callout_handle->setArgument(
"lease4", lease);
4162 .arg(decline->getLabel()).arg(lease->addr_.toText());
4167 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
4181 .arg(decline->getLabel())
4182 .arg(lease->addr_.toText())
4196 static_cast<int64_t
>(1));
4198 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
4200 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4205 static_cast<int64_t
>(1));
4222 context->new_lease_ = lease;
4225 .arg(decline->getLabel()).arg(lease->valid_lft_);
4232 .arg(query->getLabel())
4233 .arg(lease->addr_.toText())
4234 .arg(lease->valid_lft_);
4242 .arg(query->getLabel())
4243 .arg(lease->addr_.toText());
4259 lease_exists =
false;
4263 .arg(query->getLabel())
4264 .arg(lease->addr_.toText());
4269 if (!lease_exists) {
4274 .arg(query->getLabel())
4275 .arg(lease->addr_.toText());
4292 static_cast<int64_t
>(1));
4294 if (!lease_exists) {
4297 static_cast<int64_t
>(1));
4300 auto const& subnet =
CfgMgr::instance().getCurrentCfg()->getCfgSubnets4()->getBySubnetId(lease->subnet_id_);
4302 auto const& pool = subnet->getPool(
Lease::TYPE_V4, lease->addr_,
false);
4307 static_cast<int64_t
>(1));
4308 if (!lease_exists) {
4312 static_cast<int64_t
>(1));
4319 if (!lease_exists) {
4333 callout_handle->setArgument(
"query4", query);
4336 callout_handle->setArgument(
"lease4", lease);
4364 Pkt4Ptr ack = ex.getResponse();
4368 ex.conditionallySetReservedClientClasses();
4373 .arg(inform->getLabel())
4374 .arg(inform->getName())
4375 .arg(inform->getClasses().toText());
4392 if (ack->getRemoteAddr() != inform->getGiaddr()) {
4394 .arg(inform->getLabel())
4395 .arg(ack->getRemoteAddr())
4396 .arg(ack->getIface());
4405 return (ex.getResponse());
4410 if (query->getCiaddr().isV4Zero() || !query->getGiaddr().isV4Zero()) {
4427 if (query->inClass(
"STASH_AGENT_OPTIONS")) {
4431 if (!lease || lease->expired()) {
4435 if (!user_context || (user_context->getType() !=
Element::map)) {
4443 if (!relay_agent_info) {
4448 relay_agent_info = relay_agent_info->get(
"sub-options");
4449 if (!relay_agent_info) {
4458 OptionPtr opt_clientid = query->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
4460 client_id.reset(
new ClientId(opt_clientid->getData()));
4462 if (!lease->belongsToClient(query->getHWAddr(), client_id)) {
4466 string rai_hex = relay_agent_info->stringValue();
4467 if (rai_hex.empty()) {
4470 vector<uint8_t> rai_data;
4475 if (!rai || rai->getOptions().empty()) {
4482 query->addOption(rai);
4483 query->addClass(
"STASH_AGENT_OPTIONS");
4486 .arg(query->getLabel())
4487 .arg(query->getCiaddr())
4488 .arg(rai->toText());
4502 .arg(query->getLabel())
4503 .arg(query->getIface());
4511 .arg(query->getLabel())
4512 .arg(query->getIface());
4522 if (pkt->isRelayed()) {
4527 if (pkt->isDhcp4o6()) {
4536 if (pkt->getRemoteAddr().isV4Zero() &&
4537 pkt->getCiaddr().isV4Zero()) {
4548 bool result = (!pkt->getLocalAddr().isV4Bcast() ||
4563 type = query->getType();
4567 .arg(query->getLabel())
4568 .arg(query->getIface());
4592 .arg(query->getLabel());
4599 .arg(query->getLabel())
4604 .arg(query->getLabel())
4631 boost::dynamic_pointer_cast<OptionCustom>(option);
4634 if (!option_custom) {
4642 if (option_custom->getDataFieldsNum() != 1) {
4648 IOAddress server_id = option_custom->readAddress();
4649 if (!server_id.isV4()) {
4658 if (rai_suboption && (server_id.toBytes() == rai_suboption->toBinary())) {
4665 if (cfg->getIgnoreServerIdentifier()) {
4703 if (cfg_subnets->hasSubnetWithServerId(server_id)) {
4710 if (cfg_networks->hasNetworkWithServerId(server_id)) {
4716 for (
auto const& cclass : classes) {
4719 getClientClassDictionary()->findClass(cclass);
4724 if (ccdef->getCfgOption()->empty()) {
4729 OptionCustomPtr context_opt_server_id = boost::dynamic_pointer_cast<OptionCustom>
4731 if (context_opt_server_id && (context_opt_server_id->readAddress() == server_id)) {
4739 OptionCustomPtr opt_server_id = boost::dynamic_pointer_cast<OptionCustom>
4742 return (opt_server_id && (opt_server_id->readAddress() == server_id));
4747 switch (query->getType()) {
4782 <<
" received in message "
4783 << query->getName());
4790 " received in message "
4791 << query->getName());
4801 if (query->getHWAddr() && !query->getHWAddr()->hwaddr_.empty()) {
4807 OptionPtr client_id = query->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
4810 if (!client_id || client_id->len() == client_id->getHeaderLen()) {
4812 " provided in message "
4813 << query->getName());
4823 Pkt4Ptr query = ex.getQuery();
4825 Subnet4Ptr subnet = ex.getContext()->subnet_;
4830 subnet->getSharedNetwork(network);
4832 const ClientClasses& to_add = network->getRequiredClasses();
4833 for (
auto const& cclass : to_add) {
4840 for (
auto const& cclass : to_add) {
4845 Pkt4Ptr resp = ex.getResponse();
4848 addr = resp->getYiaddr();
4853 const ClientClasses& pool_to_add = pool->getRequiredClasses();
4854 for (
auto const& cclass : pool_to_add) {
4867 for (
auto const& cclass : classes) {
4887 .arg(query->getLabel())
4891 query->addClass(cclass);
4894 .arg(query->getLabel())
4900 .arg(query->getLabel())
4905 .arg(query->getLabel())
4907 .arg(
"get exception?");
4915 for (
auto const& code : query->getDeferredOptions()) {
4919 for (
auto const& cclass : classes) {
4923 getClientClassDictionary()->findClass(cclass);
4929 if (!ccdef->getCfgOptionDef()) {
4959 .arg(query->getLabel())
4968 opt = def->optionFactory(
Option::V4, code, buf);
4969 }
catch (
const std::exception& e) {
4973 .arg(query->getLabel())
4978 while (query->delOption(code)) {
4982 query->addOption(opt);
4989 if (d2_mgr.ddnsEnabled()) {
4994 this, ph::_1, ph::_2));
5001 if (d2_mgr.ddnsEnabled()) {
5004 d2_mgr.stopSender();
5013 arg(result).arg((ncr ? ncr->toText() :
" NULL "));
5022 std::stringstream tmp;
5026 tmp <<
" (" << EXTENDED_VERSION <<
")" << endl;
5027 tmp <<
"premium: " << PREMIUM_EXTENDED_VERSION << endl;
5028 tmp <<
"linked with:" << endl;
5031 tmp <<
"backends:" << endl;
5050 string stat_name =
"pkt4-unknown-received";
5052 switch (query->getType()) {
5054 stat_name =
"pkt4-discover-received";
5058 stat_name =
"pkt4-offer-received";
5061 stat_name =
"pkt4-request-received";
5065 stat_name =
"pkt4-ack-received";
5069 stat_name =
"pkt4-nak-received";
5072 stat_name =
"pkt4-release-received";
5075 stat_name =
"pkt4-decline-received";
5078 stat_name =
"pkt4-inform-received";
5092 static_cast<int64_t
>(1));
5098 static_cast<int64_t
>(1));
5102 switch (response->getType()) {
5104 stat_name =
"pkt4-offer-sent";
5107 stat_name =
"pkt4-ack-sent";
5110 stat_name =
"pkt4-nak-sent";
5118 static_cast<int64_t
>(1));
5122 return (
Hooks.hook_index_buffer4_receive_);
5126 return (
Hooks.hook_index_pkt4_receive_);
5130 return (
Hooks.hook_index_subnet4_select_);
5134 return (
Hooks.hook_index_lease4_release_);
5138 return (
Hooks.hook_index_pkt4_send_);
5142 return (
Hooks.hook_index_buffer4_send_);
5146 return (
Hooks.hook_index_lease4_decline_);
5155 static std::list<std::list<std::string>>
const list({
5156 {
"config-control",
"config-databases",
"[]"},
5157 {
"hooks-libraries",
"[]",
"parameters",
"*"},
5159 {
"hosts-databases",
"[]"},
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 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.
Dhcpv4Exchange(const AllocEnginePtr &alloc_engine, const Pkt4Ptr &query, AllocEngine::ClientContext4Ptr &context, const Subnet4Ptr &subnet, bool &drop)
Constructor.
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.
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.
isc::dhcp::Subnet4Ptr 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.
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.
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.
isc::dhcp::Subnet4Ptr selectSubnet(const Pkt4Ptr &query, bool &drop, bool sanity_only=false, bool allow_answer_park=true)
Selects a subnet for a given client's packet.
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.
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.
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,...
void requiredClassify(Dhcpv4Exchange &ex)
Assigns incoming packet to zero or more classes (required pass).
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 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 sendResponseNoThrow(hooks::CalloutHandlePtr &callout_handle, Pkt4Ptr &query, Pkt4Ptr &rsp, Subnet4Ptr &subnet)
Process an unparked DHCPv4 packet and sends the response.
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.
bool assignZero(Subnet4Ptr &subnet, const ClientClasses &client_classes)
Assign the 0.0.0.0 address to an IPv6-Only client.
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.
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 setTeeTimes(const Lease4Ptr &lease, const Subnet4Ptr &subnet, Pkt4Ptr resp)
Adds the T1 and T2 timers to the outbound response as appropriate.
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.
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.
void processPacketPktSend(hooks::CalloutHandlePtr &callout_handle, Pkt4Ptr &query, Pkt4Ptr &rsp, Subnet4Ptr &subnet)
Executes pkt4_send callout.
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.
void deferredUnpack(Pkt4Ptr &query)
Perform deferred option unpacking.
Pkt4Ptr processLocalizedQuery4(AllocEngine::ClientContext4Ptr &ctx, bool allow_answer_park)
Process a localized incoming DHCPv4 query.
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 void destroy()
Destroy lease manager.
static std::string getDBVersion()
Class method to return extended version info This class method must be redeclared and redefined in de...
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_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.
static std::string getDBVersion()
Local version of getDBVersion() class method.
Controls the DHCP service enabling status.
Attempt to update lease that was not there.
DHCPv4 Option class for handling list of IPv4 addresses.
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)
static std::string getDBVersion()
Local version of getDBVersion() class method.
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.
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.
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
An abstract API for lease database.
#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
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
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 EVAL_RESULT
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< 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_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.
const isc::log::MessageID DHCP4_CLASS_UNTESTABLE
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
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_CLASS_UNDEFINED
const isc::log::MessageID DHCP4_HOOK_LEASES4_COMMITTED_PARK
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.
#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_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.