8 #include <kea_version.h>
65 #include <boost/algorithm/string.hpp>
66 #include <boost/foreach.hpp>
67 #include <boost/pointer_cast.hpp>
68 #include <boost/shared_ptr.hpp>
85 namespace ph = std::placeholders;
91 int hook_index_buffer4_receive_;
92 int hook_index_pkt4_receive_;
93 int hook_index_subnet4_select_;
94 int hook_index_leases4_committed_;
95 int hook_index_lease4_release_;
96 int hook_index_pkt4_send_;
97 int hook_index_buffer4_send_;
98 int hook_index_lease4_decline_;
99 int hook_index_host4_identifier_;
103 hook_index_buffer4_receive_ = HooksManager::registerHook(
"buffer4_receive");
104 hook_index_pkt4_receive_ = HooksManager::registerHook(
"pkt4_receive");
105 hook_index_subnet4_select_ = HooksManager::registerHook(
"subnet4_select");
106 hook_index_leases4_committed_ = HooksManager::registerHook(
"leases4_committed");
107 hook_index_lease4_release_ = HooksManager::registerHook(
"lease4_release");
108 hook_index_pkt4_send_ = HooksManager::registerHook(
"pkt4_send");
109 hook_index_buffer4_send_ = HooksManager::registerHook(
"buffer4_send");
110 hook_index_lease4_decline_ = HooksManager::registerHook(
"lease4_decline");
111 hook_index_host4_identifier_ = HooksManager::registerHook(
"host4_identifier");
117 std::set<std::string> dhcp4_statistics = {
119 "pkt4-discover-received",
120 "pkt4-offer-received",
121 "pkt4-request-received",
124 "pkt4-release-received",
125 "pkt4-decline-received",
126 "pkt4-inform-received",
127 "pkt4-unknown-received",
151 : alloc_engine_(alloc_engine), query_(query), resp_(),
154 if (!alloc_engine_) {
156 " when creating an instance of the Dhcpv4Exchange");
161 " creating an instance of the Dhcpv4Exchange");
166 context_->subnet_ = subnet;
168 context_->hwaddr_ = query->getHWAddr();
170 context_->query_ = query;
179 context_->clientid_.reset(
new ClientId(opt_clientid->getData()));
183 if (subnet->getReservationsInSubnet() ||
184 subnet->getReservationsGlobal()) {
187 setHostIdentifiers();
190 alloc_engine->findReservation(*context_);
193 subnet->getSharedNetwork(sn);
203 auto global_host = context_->globalHost();
204 auto current_host = context_->currentHost();
205 if ((global_host && !global_host->getClientClasses4().empty()) ||
206 (!sn && current_host && !current_host->getClientClasses4().empty())) {
224 for (
auto def : *defs_ptr) {
228 if (def->getMatchExpr()) {
229 context_->query_->classes_.erase(def->getName());
233 evaluateClasses(context_->query_,
false);
237 if (!context_->hosts_.empty()) {
238 query->addClass(
"KNOWN");
240 .arg(query->getLabel())
243 query->addClass(
"UNKNOWN");
245 .arg(query->getLabel())
250 evaluateClasses(query,
true);
253 if (!classes.
empty()) {
255 .arg(query_->getLabel())
260 if (query_->inClass(
"DROP")) {
262 .arg(query_->toText());
264 static_cast<int64_t>(1));
271 uint8_t resp_type = 0;
285 resp_.reset(
new Pkt4(resp_type,
getQuery()->getTransid()));
287 copyDefaultOptions();
305 if (!query6->relay_info_.empty()) {
306 resp6->copyRelayInfo(query6);
309 resp6->setIface(query6->getIface());
310 resp6->setIndex(query6->getIndex());
311 resp6->setRemoteAddr(query6->getRemoteAddr());
312 resp6->setRemotePort(query6->getRemotePort());
313 resp_.reset(
new Pkt4o6(resp_, resp6));
317 Dhcpv4Exchange::copyDefaultFields() {
318 resp_->setIface(query_->getIface());
319 resp_->setIndex(query_->getIndex());
326 resp_->setCiaddr(query_->getCiaddr());
330 resp_->setHops(query_->getHops());
333 resp_->setHWAddr(query_->getHWAddr());
336 resp_->setGiaddr(query_->getGiaddr());
345 HWAddrPtr src_hw_addr = query_->getLocalHWAddr();
347 resp_->setLocalHWAddr(src_hw_addr);
349 HWAddrPtr dst_hw_addr = query_->getRemoteHWAddr();
351 resp_->setRemoteHWAddr(dst_hw_addr);
355 resp_->setFlags(query_->getFlags());
359 Dhcpv4Exchange::copyDefaultOptions() {
364 if (client_id && echo) {
365 resp_->addOption(client_id);
372 resp_->addOption(rai);
385 resp_->addOption(subnet_sel);
390 Dhcpv4Exchange::setHostIdentifiers() {
397 cfg->getIdentifierTypes()) {
400 if (context_->hwaddr_ && !context_->hwaddr_->hwaddr_.empty()) {
401 context_->addHostIdentifier(id_type, context_->hwaddr_->hwaddr_);
406 if (context_->clientid_) {
407 const std::vector<uint8_t>& vec = context_->clientid_->getDuid();
412 if ((vec[0] == CLIENT_ID_OPTION_TYPE_DUID) && (vec.size() > 5)) {
414 context_->addHostIdentifier(id_type,
415 std::vector<uint8_t>(vec.begin() + 5,
426 OptionPtr circuit_id_opt = rai->getOption(RAI_OPTION_AGENT_CIRCUIT_ID);
427 if (circuit_id_opt) {
428 const OptionBuffer& circuit_id_vec = circuit_id_opt->getData();
429 if (!circuit_id_vec.empty()) {
430 context_->addHostIdentifier(id_type, circuit_id_vec);
438 if (context_->clientid_) {
439 const std::vector<uint8_t>& vec = context_->clientid_->getDuid();
441 context_->addHostIdentifier(id_type, vec);
447 if (!HooksManager::calloutsPresent(Hooks.hook_index_host4_identifier_)) {
454 std::vector<uint8_t> id;
463 callout_handle->setArgument(
"query4", context_->query_);
464 callout_handle->setArgument(
"id_type", type);
465 callout_handle->setArgument(
"id_value",
id);
468 HooksManager::callCallouts(Hooks.hook_index_host4_identifier_,
471 callout_handle->getArgument(
"id_type", type);
472 callout_handle->getArgument(
"id_value",
id);
474 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_CONTINUE) &&
480 context_->addHostIdentifier(type,
id);
492 if (context->currentHost() && context->query_) {
493 const ClientClasses& classes = context->currentHost()->getClientClasses4();
495 cclass != classes.
cend(); ++cclass) {
496 context->query_->addClass(*cclass);
503 if (context_->subnet_) {
505 context_->subnet_->getSharedNetwork(shared_network);
506 if (shared_network) {
508 if (host && (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL)) {
520 if (!host->getNextServer().isV4Zero()) {
521 resp_->setSiaddr(host->getNextServer());
524 std::string sname = host->getServerHostname();
525 if (!sname.empty()) {
526 resp_->setSname(reinterpret_cast<const uint8_t*>(sname.c_str()),
530 std::string bootfile = host->getBootFileName();
531 if (!bootfile.empty()) {
532 resp_->setFile(reinterpret_cast<const uint8_t*>(bootfile.c_str()),
540 boost::shared_ptr<OptionString> vendor_class =
552 pkt->addClass(
"ALL");
558 evaluateClasses(pkt,
false);
561 void Dhcpv4Exchange::evaluateClasses(
const Pkt4Ptr& pkt,
bool depend_on_known) {
566 for (ClientClassDefList::const_iterator it = defs_ptr->cbegin();
567 it != defs_ptr->cend(); ++it) {
575 if ((*it)->getRequired()) {
579 if ((*it)->getDependOnKnown() != depend_on_known) {
588 .arg((*it)->getName())
591 pkt->addClass((*it)->getName());
594 .arg((*it)->getName())
599 .arg((*it)->getName())
603 .arg((*it)->getName())
604 .arg(
"get exception?");
612 const bool use_bcast,
const bool direct_response_desired)
613 : io_service_(new
IOService()), server_port_(server_port),
614 client_port_(client_port), shutdown_(true),
615 alloc_engine_(), use_bcast_(use_bcast),
618 test_send_responses_to_source_(false) {
620 const char* env = std::getenv(
"KEA_TEST_SEND_RESPONSES_TO_SOURCE");
623 test_send_responses_to_source_ =
true;
652 }
catch (
const std::exception &e) {
667 for (
auto it = dhcp4_statistics.begin(); it != dhcp4_statistics.end(); ++it) {
669 stats_mgr.
setValue((*it), static_cast<int64_t>(0));
679 }
catch (
const std::exception& ex) {
686 }
catch (
const std::exception& ex) {
698 HooksManager::prepareUnloadLibraries();
699 if (!HooksManager::unloadLibraries()) {
700 auto names = HooksManager::getLibraryNames();
702 if (!names.empty()) {
704 for (
size_t i = 1; i < names.size(); ++i) {
705 msg += std::string(
", ") + names[i];
720 bool sanity_only)
const {
723 if (query->isDhcp4o6()) {
732 subnet = cfgmgr.
getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
737 HooksManager::calloutsPresent(Hooks.hook_index_subnet4_select_)) {
750 callout_handle->setArgument(
"query4", query);
751 callout_handle->setArgument(
"subnet4", subnet);
752 callout_handle->setArgument(
"subnet4collection",
754 getCfgSubnets4()->getAll());
757 HooksManager::callCallouts(Hooks.hook_index_subnet4_select_,
763 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
766 .arg(query->getLabel());
772 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
775 .arg(query->getLabel());
781 callout_handle->getArgument(
"subnet4", subnet);
787 .arg(query->getLabel())
788 .arg(subnet->getID());
792 .arg(query->getLabel())
793 .arg(subnet->toText());
798 .arg(query->getLabel());
806 bool sanity_only)
const {
811 selector.
ciaddr_ = query->getCiaddr();
812 selector.
giaddr_ = query->getGiaddr();
827 const Pkt6Ptr& query6 = query4o6->getPkt6();
830 if (query6 && !query6->relay_info_.empty()) {
853 subnet = cfgmgr.
getCurrentCfg()->getCfgSubnets4()->selectSubnet4o6(selector);
858 HooksManager::calloutsPresent(Hooks.hook_index_subnet4_select_)) {
868 callout_handle->setArgument(
"query4", query);
869 callout_handle->setArgument(
"subnet4", subnet);
870 callout_handle->setArgument(
"subnet4collection",
872 getCfgSubnets4()->getAll());
875 HooksManager::callCallouts(Hooks.hook_index_subnet4_select_,
881 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
884 .arg(query->getLabel());
890 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
893 .arg(query->getLabel());
899 callout_handle->getArgument(
"subnet4", subnet);
905 .arg(query->getLabel())
906 .arg(subnet->getID());
910 .arg(query->getLabel())
911 .arg(subnet->toText());
916 .arg(query->getLabel());
940 while (__AFL_LOOP(fuzzer.maxLoopCount())) {
950 }
catch (
const std::exception& e) {
967 MultiThreadingMgr::instance().apply(
false, 0, 0);
981 uint32_t timeout = 1;
992 .arg(query->getRemoteAddr().toText())
993 .arg(query->getRemotePort())
994 .arg(query->getLocalAddr().toText())
995 .arg(query->getLocalPort())
996 .arg(query->getIface());
1012 }
catch (
const std::exception& e) {
1028 .arg(query->getLabel());
1031 if (MultiThreadingMgr::instance().getMode()) {
1032 typedef function<void()> CallBack;
1033 boost::shared_ptr<CallBack> call_back =
1036 if (!MultiThreadingMgr::instance().getThreadPool().add(call_back)) {
1049 }
catch (
const std::exception& e) {
1076 static_cast<int64_t>(1));
1078 bool skip_unpack =
false;
1082 if (HooksManager::calloutsPresent(Hooks.hook_index_buffer4_receive_)) {
1095 callout_handle->setArgument(
"query4", query);
1098 HooksManager::callCallouts(Hooks.hook_index_buffer4_receive_,
1104 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
1107 .arg(query->getRemoteAddr().toText())
1108 .arg(query->getLocalAddr().toText())
1109 .arg(query->getIface());
1117 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
1120 .arg(query->getRemoteAddr().toText())
1121 .arg(query->getLocalAddr().toText())
1122 .arg(query->getIface());
1126 callout_handle->getArgument(
"query4", query);
1134 .arg(query->getRemoteAddr().toText())
1135 .arg(query->getLocalAddr().toText())
1136 .arg(query->getIface());
1144 }
catch (
const std::exception& e) {
1148 .arg(query->getRemoteAddr().toText())
1149 .arg(query->getLocalAddr().toText())
1150 .arg(query->getIface())
1155 static_cast<int64_t>(1));
1157 static_cast<int64_t>(1));
1178 static_cast<int64_t>(1));
1184 int type = query->getType();
1186 .arg(query->getLabel())
1187 .arg(query->getName())
1189 .arg(query->getRemoteAddr())
1190 .arg(query->getLocalAddr())
1191 .arg(query->getIface());
1193 .arg(query->getLabel())
1194 .arg(query->toText());
1197 if (HooksManager::calloutsPresent(Hooks.hook_index_pkt4_receive_)) {
1210 callout_handle->setArgument(
"query4", query);
1213 HooksManager::callCallouts(Hooks.hook_index_pkt4_receive_,
1219 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
1220 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
1223 .arg(query->getLabel());
1227 callout_handle->getArgument(
"query4", query);
1231 if (query->inClass(
"DROP")) {
1233 .arg(query->toText());
1235 static_cast<int64_t>(1));
1244 bool allow_packet_park) {
1253 }
catch (
const std::exception& e) {
1263 bool allow_packet_park) {
1268 if (MultiThreadingMgr::instance().getMode() &&
1275 this, query, rsp, allow_packet_park));
1276 if (!client_handler.
tryLock(query, cont)) {
1284 switch (query->getType()) {
1314 }
catch (
const std::exception& e) {
1325 .arg(query->getLabel())
1330 static_cast<int64_t>(1));
1334 if (ctx && HooksManager::calloutsPresent(Hooks.hook_index_leases4_committed_)) {
1344 callout_handle->setArgument(
"query4", query);
1348 if (ctx->new_lease_ && (ctx->new_lease_->reuseable_valid_lft_ == 0)) {
1349 new_leases->push_back(ctx->new_lease_);
1351 callout_handle->setArgument(
"leases4", new_leases);
1354 if (ctx->old_lease_) {
1355 if ((!ctx->new_lease_) || (ctx->new_lease_->addr_ != ctx->old_lease_->addr_)) {
1356 deleted_leases->push_back(ctx->old_lease_);
1359 callout_handle->setArgument(
"deleted_leases4", deleted_leases);
1361 if (allow_packet_park) {
1366 HooksManager::park(
"leases4_committed", query,
1367 [
this, callout_handle, query, rsp]()
mutable {
1368 if (MultiThreadingMgr::instance().getMode()) {
1369 typedef function<void()> CallBack;
1370 boost::shared_ptr<CallBack> call_back =
1372 this, callout_handle, query, rsp));
1373 MultiThreadingMgr::instance().getThreadPool().add(call_back);
1383 HooksManager::callCallouts(Hooks.hook_index_leases4_committed_,
1387 if (allow_packet_park) {
1388 HooksManager::drop(
"leases4_committed", query);
1394 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_PARK)
1395 && allow_packet_park) {
1397 .arg(query->getLabel());
1405 HooksManager::drop(
"leases4_committed", query);
1406 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
1408 .arg(query->getLabel());
1426 }
catch (
const std::exception& e) {
1442 bool skip_pack =
false;
1445 if (HooksManager::calloutsPresent(Hooks.hook_index_pkt4_send_)) {
1458 callout_handle->setArgument(
"query4", query);
1461 callout_handle->setArgument(
"response4", rsp);
1464 HooksManager::callCallouts(Hooks.hook_index_pkt4_send_,
1472 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
1474 .arg(query->getLabel());
1479 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
1481 .arg(rsp->getLabel());
1490 .arg(rsp->getLabel());
1492 }
catch (
const std::exception& e) {
1494 .arg(rsp->getLabel())
1512 if (HooksManager::calloutsPresent(Hooks.hook_index_buffer4_send_)) {
1524 callout_handle->setArgument(
"response4", rsp);
1527 HooksManager::callCallouts(Hooks.hook_index_buffer4_send_,
1533 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
1534 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
1537 .arg(rsp->getLabel());
1541 callout_handle->getArgument(
"response4", rsp);
1545 .arg(rsp->getLabel())
1546 .arg(rsp->getName())
1547 .arg(static_cast<int>(rsp->getType()))
1548 .arg(rsp->getLocalAddr().isV4Zero() ?
"*" : rsp->getLocalAddr().toText())
1549 .arg(rsp->getLocalPort())
1550 .arg(rsp->getRemoteAddr())
1551 .arg(rsp->getRemotePort())
1552 .arg(rsp->getIface().empty() ?
"to be determined from routing" :
1557 .arg(rsp->getLabel())
1558 .arg(rsp->getName())
1559 .arg(static_cast<int>(rsp->getType()))
1560 .arg(rsp->toText());
1566 }
catch (
const std::exception& e) {
1568 .arg(rsp->getLabel())
1578 boost::shared_ptr<Option4AddrLst> generated =
1585 if (addrs.size() != 1) {
1587 <<
"Expected to contain a single IPv4 address.");
1590 return (addrs[0].toText());
1608 if (local_addr.
isV4Bcast() || query->isDhcp4o6()) {
1631 if (host && !host->getCfgOption4()->empty()) {
1632 co_list.push_back(host->getCfgOption4());
1639 addr = resp->getYiaddr();
1643 if (pool && !pool->getCfgOption()->empty()) {
1644 co_list.push_back(pool->getCfgOption());
1649 if (!subnet->getCfgOption()->empty()) {
1650 co_list.push_back(subnet->getCfgOption());
1655 subnet->getSharedNetwork(network);
1656 if (network && !network->getCfgOption()->empty()) {
1657 co_list.push_back(network->getCfgOption());
1663 cclass != classes.
cend(); ++cclass) {
1666 getClientClassDictionary()->findClass(*cclass);
1678 if (ccdef->getCfgOption()->empty()) {
1683 co_list.push_back(ccdef->getCfgOption());
1707 if (co_list.empty()) {
1713 std::vector<uint8_t> requested_opts;
1721 requested_opts = option_prl->getValues();
1724 for (CfgOptionList::const_iterator copts = co_list.begin();
1725 copts != co_list.end(); ++copts) {
1733 for (OptionContainerPersistIndex::const_iterator desc = range.first;
1734 desc != range.second; ++desc) {
1736 if (desc->option_) {
1737 uint8_t code =
static_cast<uint8_t
>(desc->option_->getType());
1738 requested_opts.push_back(code);
1745 for (std::vector<uint8_t>::const_iterator opt = requested_opts.begin();
1746 opt != requested_opts.end(); ++opt) {
1748 if (!resp->getOption(*opt)) {
1750 for (CfgOptionList::const_iterator copts = co_list.begin();
1751 copts != co_list.end(); ++copts) {
1755 resp->addOption(desc.
option_);
1778 if (co_list.empty()) {
1782 uint32_t vendor_id = 0;
1787 boost::shared_ptr<OptionVendor> vendor_req = boost::dynamic_pointer_cast<
1797 boost::shared_ptr<OptionVendor> vendor_rsp = boost::dynamic_pointer_cast<
1803 if (!vendor_req && !vendor_rsp) {
1810 std::vector<uint8_t> requested_opts;
1820 requested_opts = oro->getValues();
1825 for (CfgOptionList::const_iterator copts = co_list.begin();
1826 copts != co_list.end(); ++copts) {
1835 for (OptionContainerPersistIndex::const_iterator desc = range.first;
1836 desc != range.second; ++desc) {
1838 if (desc->option_) {
1839 uint8_t code =
static_cast<uint8_t
>(desc->option_->getType());
1840 requested_opts.push_back(code);
1846 if (requested_opts.empty()) {
1858 for (std::vector<uint8_t>::const_iterator code = requested_opts.begin();
1859 code != requested_opts.end(); ++code) {
1860 if (!vendor_rsp->getOption(*code)) {
1861 for (CfgOptionList::const_iterator copts = co_list.begin();
1862 copts != co_list.end(); ++copts) {
1865 vendor_rsp->addOption(desc.
option_);
1884 static const uint16_t required_options[] = {
1890 static size_t required_options_size =
1891 sizeof(required_options) /
sizeof(required_options[0]);
1901 if (co_list.empty()) {
1909 for (
int i = 0; i < required_options_size; ++i) {
1910 OptionPtr opt = resp->getOption(required_options[i]);
1913 for (CfgOptionList::const_iterator copts = co_list.begin();
1914 copts != co_list.end(); ++copts) {
1916 required_options[i]);
1918 resp->addOption(desc.
option_);
1938 processClientFqdnOption(ex);
1944 processHostnameOption(ex);
1950 std::string hostname;
1951 bool fqdn_fwd =
false;
1952 bool fqdn_rev =
false;
1959 opt_hostname = boost::dynamic_pointer_cast<
OptionString>
1963 hostname = opt_hostname->
getValue();
1968 if (hostname ==
".") {
1974 if (ex.
getContext()->getDdnsParams()->getEnableUpdates()) {
1983 ctx->fwd_dns_update_ = fqdn_fwd;
1984 ctx->rev_dns_update_ = fqdn_rev;
1985 ctx->hostname_ = hostname;
2011 .arg(fqdn->toText());
2027 !ex.
getContext()->currentHost()->getHostname().empty()) {
2054 .arg(fqdn_resp->
toText());
2070 .arg(opt_hostname->getValue());
2078 if (ctx->currentHost() && !ctx->currentHost()->getHostname().empty()) {
2080 std::string hostname = d2_mgr.
qualifyName(ctx->currentHost()->getHostname(),
2083 boost::algorithm::to_lower(hostname);
2101 ex.
getContext()->getDdnsParams()->getReplaceClientNameMode();
2104 if (!opt_hostname) {
2124 .arg(opt_hostname->getValue());
2127 unsigned int label_count;
2133 }
catch (
const std::exception& exc) {
2144 if (label_count == 0) {
2162 || label_count < 2) {
2176 ex.
getContext()->getDdnsParams()->getHostnameSanitizer();
2179 hostname = sanitizer->scrub(hostname);
2183 boost::algorithm::to_lower(hostname);
2185 if (label_count == 2) {
2193 opt_hostname_resp.reset(
2204 .arg(opt_hostname_resp->getValue());
2214 "NULL lease specified when creating NameChangeRequest");
2222 if (!old_lease || ddns_params.
getUpdateOnRenew() || !lease->hasIdenticalFqdn(*old_lease)) {
2253 .arg(query->getLabel())
2254 .arg(query->getRemoteAddr().toText())
2255 .arg(query->getName());
2271 if (opt_requested_address) {
2272 hint = opt_requested_address->readAddress();
2274 }
else if (!query->getCiaddr().isV4Zero()) {
2275 hint = query->getCiaddr();
2287 bool fake_allocation = (query->getType() ==
DHCPDISCOVER);
2296 if (!fake_allocation && !opt_serverid && opt_requested_address) {
2299 .arg(query->getLabel())
2300 .arg(hint.toText());
2317 if (!leases_client_id.empty()) {
2323 for (
auto l = leases_client_id.begin(); l != leases_client_id.end(); ++l) {
2324 if ((*l)->subnet_id_ == s->getID()) {
2334 s = s->getNextSubnet(original_subnet, query->getClasses());
2342 if (!lease && hwaddr) {
2346 if (!leases_hwaddr.empty()) {
2351 for (
auto l = leases_hwaddr.begin(); l != leases_hwaddr.end(); ++l) {
2352 if ((*l)->subnet_id_ == s->getID()) {
2362 s = s->getNextSubnet(original_subnet, query->getClasses());
2371 bool authoritative = original_subnet->getAuthoritative();
2372 bool known_client = lease && lease->belongsToClient(hwaddr, client_id);
2373 if (!authoritative && !known_client) {
2376 .arg(query->getLabel())
2377 .arg(hint.toText());
2385 if ((known_client && (lease->addr_ != hint)) ||
2386 (!known_client && authoritative)) {
2389 .arg(query->getLabel())
2390 .arg(hint.toText());
2401 ctx->requested_address_ = hint;
2402 ctx->fake_allocation_ = fake_allocation;
2403 ctx->callout_handle_ = callout_handle;
2419 bool client_name_changed =
false;
2423 if (subnet->getID() != ctx->subnet_->getID()) {
2425 subnet->getSharedNetwork(network);
2427 .arg(query->getLabel())
2428 .arg(subnet->toText())
2429 .arg(ctx->subnet_->toText())
2430 .arg(network ? network->getName() :
"<no network?>");
2432 subnet = ctx->subnet_;
2447 ctx->hostname_ =
"";
2448 ctx->fwd_dns_update_ =
false;
2449 ctx->rev_dns_update_ =
false;
2456 if ((lease->hostname_ != ctx->hostname_) ||
2457 (lease->fqdn_fwd_ != ctx->fwd_dns_update_) ||
2458 (lease->fqdn_rev_ != ctx->rev_dns_update_)) {
2459 lease->hostname_ = ctx->hostname_;
2460 lease->fqdn_fwd_ = ctx->fwd_dns_update_;
2461 lease->fqdn_rev_ = ctx->rev_dns_update_;
2462 client_name_changed =
true;
2470 if (fake_allocation) {
2472 .arg(query->getLabel())
2473 .arg(lease->addr_.toText());
2476 .arg(query->getLabel())
2477 .arg(lease->addr_.toText())
2485 if (!ctx->subnet_->getMatchClientId()) {
2487 .arg(ctx->query_->getLabel())
2488 .arg(ctx->subnet_->getID());
2491 resp->setYiaddr(lease->addr_);
2497 if (!fake_allocation) {
2502 resp->setCiaddr(query->getCiaddr());
2511 if (lease->reuseable_valid_lft_ > 0) {
2512 lease->valid_lft_ = lease->reuseable_valid_lft_;
2514 .arg(query->getLabel())
2515 .arg(lease->addr_.toText())
2521 lease->valid_lft_));
2522 resp->addOption(opt);
2525 resp->addOption(getNetmaskOption(subnet));
2531 if (!fake_allocation) {
2534 .arg(query->getLabel());
2539 .arg(query->getLabel())
2549 .arg(query->getLabel())
2550 .arg(query->getCiaddr().toText())
2551 .arg(opt_requested_address ?
2552 opt_requested_address->readAddress().toText() :
"(no address)");
2564 const Pkt4Ptr& query,
const Pkt4Ptr& resp,
bool client_name_changed) {
2574 if (!opt_hostname) {
2581 if (lease->hostname_.empty()) {
2588 .
generateFqdn(lease->addr_, *(ctx->getDdnsParams()), static_cast<bool>(fqdn));
2591 .arg(query->getLabel())
2592 .arg(lease->hostname_);
2594 client_name_changed =
true;
2597 if (client_name_changed) {
2602 if (!ctx->fake_allocation_) {
2604 lease->reuseable_valid_lft_ = 0;
2617 opt_hostname->setValue(lease->hostname_);
2621 .arg(query->getLabel())
2622 .arg(lease->hostname_)
2632 uint32_t t2_time = 0;
2634 if (!subnet->getT2().unspecified()) {
2635 t2_time = subnet->getT2();
2636 }
else if (subnet->getCalculateTeeTimes()) {
2638 t2_time =
static_cast<uint32_t
>(round(subnet->getT2Percent() * (lease->valid_lft_)));
2643 uint32_t timer_ceiling = lease->valid_lft_;
2644 if (t2_time > 0 && t2_time < timer_ceiling) {
2646 resp->addOption(t2);
2648 timer_ceiling = t2_time;
2651 uint32_t t1_time = 0;
2653 if (!subnet->getT1().unspecified()) {
2654 t1_time = subnet->getT1();
2655 }
else if (subnet->getCalculateTeeTimes()) {
2657 t1_time =
static_cast<uint32_t
>(round(subnet->getT1Percent() * (lease->valid_lft_)));
2662 if (t1_time > 0 && t1_time < timer_ceiling) {
2664 resp->addOption(t1);
2674 if (rai && rai->getOption(RAI_OPTION_RELAY_PORT)) {
2676 return (query->getRemotePort());
2704 }
else if (((query->getType() ==
DHCPINFORM) &&
2705 ((!query->getCiaddr().isV4Zero()) ||
2706 (!query->isRelayed() && !query->getRemoteAddr().isV4Zero()))) ||
2707 ((query->getType() !=
DHCPINFORM) && !query->isRelayed())) {
2708 response->setRemotePort(DHCP4_CLIENT_PORT);
2713 response->setRemotePort(relay_port ? relay_port : DHCP4_SERVER_PORT);
2717 if (query->isRelayed() &&
2723 response->resetIndex();
2725 response->setIface(query->getIface());
2729 IOAddress local_addr = query->getLocalAddr();
2738 if (local_addr.
isV4Bcast() || query->isDhcp4o6()) {
2749 response->setLocalAddr(local_addr);
2758 response->setIndex(query->getIndex());
2759 response->setIface(query->getIface());
2765 response->setLocalPort(DHCP4_SERVER_PORT);
2777 if (query->isDhcp4o6()) {
2778 response->setRemoteAddr(query->getRemoteAddr());
2790 if (!query->getCiaddr().isV4Zero()) {
2791 response->setRemoteAddr(query->getCiaddr());
2798 }
else if (query->isRelayed()) {
2799 response->setRemoteAddr(query->getGiaddr());
2800 response->setFlags(response->getFlags() | BOOTP_BROADCAST);
2805 response->setRemoteAddr(query->getRemoteAddr());
2812 if (query->isRelayed()) {
2821 query->getCiaddr().isV4Zero()) {
2822 response->setFlags(BOOTP_BROADCAST);
2824 response->setRemoteAddr(query->getGiaddr());
2828 }
else if (!query->getCiaddr().isV4Zero()) {
2829 response->setRemoteAddr(query->getCiaddr());
2834 }
else if (response->getType() ==
DHCPNAK) {
2838 }
else if (!response->getYiaddr().isV4Zero()) {
2853 response->setRemoteAddr(response ->getYiaddr());
2861 response->setRemoteAddr(query->getRemoteAddr());
2866 response->setRemoteAddr(query->getRemoteAddr());
2878 IOAddress subnet_next_server = subnet->getSiaddr();
2879 if (!subnet_next_server.
isV4Zero()) {
2880 response->setSiaddr(subnet_next_server);
2883 const string& sname = subnet->getSname();
2884 if (!sname.empty()) {
2890 response->setSname(reinterpret_cast<const uint8_t*>(sname.c_str()),
2894 const string& filename = subnet->getFilename();
2895 if (!filename.empty()) {
2901 response->setFile(reinterpret_cast<const uint8_t*>(filename.c_str()),
2909 if (!classes.
empty()) {
2922 size_t found_cnt = 0;
2924 name != classes.
cend() && found_cnt < 3; ++name) {
2936 next_server = cl->getNextServer();
2938 response->setSiaddr(next_server);
2943 if (sname.empty()) {
2944 sname = cl->getSname();
2945 if (!sname.empty()) {
2951 response->setSname(reinterpret_cast<const uint8_t*>(sname.c_str()),
2957 if (filename.empty()) {
2958 filename = cl->getFilename();
2959 if (!filename.empty()) {
2965 response->setFile(reinterpret_cast<const uint8_t*>(filename.c_str()),
2979 Dhcpv4Srv::getNetmaskOption(
const Subnet4Ptr& subnet) {
2980 uint32_t netmask =
getNetmask4(subnet->get().second).toUint32();
3008 if (MultiThreadingMgr::instance().getMode()) {
3082 if (MultiThreadingMgr::instance().getMode()) {
3095 }
else if (request->inClass(
"BOOTP")) {
3097 response->addClass(
"BOOTP");
3101 if (!response->getYiaddr().isV4Zero()) {
3164 .arg(release->getLabel())
3165 .arg(release->getCiaddr().toText());
3169 if (!lease->belongsToClient(release->getHWAddr(), client_id)) {
3171 .arg(release->getLabel())
3172 .arg(release->getCiaddr().toText());
3179 if (HooksManager::calloutsPresent(Hooks.hook_index_lease4_release_)) {
3192 callout_handle->setArgument(
"query4", release);
3195 callout_handle->setArgument(
"lease4", lease);
3198 HooksManager::callCallouts(Hooks.hook_index_lease4_release_,
3204 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
3205 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
3209 .arg(release->getLabel());
3221 context->old_lease_ = lease;
3225 .arg(release->getLabel())
3226 .arg(lease->addr_.toText());
3229 StatsMgr::instance().addValue(
3230 StatsMgr::generateName(
"subnet", lease->subnet_id_,
"assigned-addresses"),
3231 static_cast<int64_t>(-1));
3239 .arg(release->getLabel())
3240 .arg(lease->addr_.toText());
3245 .arg(release->getLabel())
3246 .arg(release->getCiaddr())
3263 if (!opt_requested_address) {
3266 " in DHCPDECLINE sent from " << decline->getLabel());
3268 IOAddress addr(opt_requested_address->readAddress());
3286 .arg(addr.toText()).arg(decline->getLabel());
3294 client_id.reset(
new ClientId(opt_clientid->getData()));
3298 if (!lease->belongsToClient(decline->getHWAddr(), client_id)) {
3301 string client_hw = decline->getHWAddr() ?
3302 decline->getHWAddr()->toText(
false) :
"(none)";
3303 string lease_hw = lease->hwaddr_ ?
3304 lease->hwaddr_->toText(
false) :
"(none)";
3307 string client_id_txt = client_id ? client_id->toText() :
"(none)";
3308 string lease_id_txt = lease->client_id_ ?
3309 lease->client_id_->toText() :
"(none)";
3313 .arg(addr.toText()).arg(decline->getLabel())
3314 .arg(client_hw).arg(lease_hw).arg(client_id_txt).arg(lease_id_txt);
3331 if (HooksManager::calloutsPresent(Hooks.hook_index_lease4_decline_)) {
3344 callout_handle->setArgument(
"query4", decline);
3347 callout_handle->setArgument(
"lease4", lease);
3350 HooksManager::callCallouts(Hooks.hook_index_lease4_decline_,
3355 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
3356 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
3358 .arg(decline->getLabel()).arg(lease->addr_.toText());
3363 Lease4Ptr old_values = boost::make_shared<Lease4>(*lease);
3377 .arg(decline->getLabel())
3378 .arg(lease->addr_.toText())
3390 StatsMgr::instance().addValue(
3391 StatsMgr::generateName(
"subnet", lease->subnet_id_,
"declined-addresses"),
3392 static_cast<int64_t>(1));
3395 StatsMgr::instance().addValue(
"declined-addresses", static_cast<int64_t>(1));
3407 context->new_lease_ = lease;
3410 .arg(decline->getLabel()).arg(lease->valid_lft_);
3457 if (ack->getRemoteAddr() != inform->getGiaddr()) {
3459 .arg(inform->getLabel())
3460 .arg(ack->getRemoteAddr())
3461 .arg(ack->getIface());
3484 .arg(query->getLabel())
3485 .arg(query->getIface());
3493 .arg(query->getLabel())
3494 .arg(query->getIface());
3504 if (pkt->isRelayed()) {
3509 if (pkt->isDhcp4o6()) {
3518 if (pkt->getRemoteAddr().isV4Zero() &&
3519 pkt->getCiaddr().isV4Zero()) {
3530 bool result = (!pkt->getLocalAddr().isV4Bcast() ||
3545 type = query->getType();
3549 .arg(query->getLabel())
3550 .arg(query->getIface());
3574 .arg(query->getLabel());
3581 .arg(query->getLabel())
3586 .arg(query->getLabel())
3616 if (!option_custom) {
3624 if (option_custom->getDataFieldsNum() != 1) {
3630 IOAddress server_id = option_custom->readAddress();
3631 if (!server_id.
isV4()) {
3672 if (cfg_subnets->hasSubnetWithServerId(server_id)) {
3679 if (cfg_networks->hasNetworkWithServerId(server_id)) {
3689 return (opt_server_id && (opt_server_id->readAddress() == server_id));
3699 <<
" received in message "
3700 << query->getName());
3707 " received in message "
3708 << query->getName());
3718 if (query->getHWAddr() && !query->getHWAddr()->hwaddr_.empty()) {
3727 if (!client_id || client_id->len() == client_id->getHeaderLen()) {
3729 " provided in message "
3730 << query->getName());
3747 subnet->getSharedNetwork(network);
3749 const ClientClasses& to_add = network->getRequiredClasses();
3751 cclass != to_add.
cend(); ++cclass) {
3759 cclass != to_add.
cend(); ++cclass) {
3767 addr = resp->getYiaddr();
3774 cclass != to_add.
cend(); ++cclass) {
3788 cclass != classes.
cend(); ++cclass) {
3811 query->addClass(*cclass);
3824 .arg(
"get exception?");
3832 BOOST_FOREACH(
const uint16_t& code, query->getDeferredOptions()) {
3837 cclass != classes.
cend(); ++cclass) {
3841 getClientClassDictionary()->findClass(*cclass);
3847 if (!ccdef->getCfgOptionDef()) {
3883 opt = def->optionFactory(
Option::V4, code, buf);
3884 }
catch (
const std::exception& e) {
3892 while (query->delOption(code)) {
3896 query->addOption(opt);
3908 this, ph::_1, ph::_2));
3926 arg(result).arg((ncr ? ncr->toText() :
" NULL "));
3938 std::stringstream tmp;
3942 tmp << endl << EXTENDED_VERSION << endl;
3943 tmp <<
"linked with:" << endl;
3944 tmp << Logger::getVersion() << endl;
3945 tmp << CryptoLink::getVersion() << endl;
3946 tmp <<
"database:" << endl;
3968 string stat_name =
"pkt4-unknown-received";
3970 switch (query->getType()) {
3972 stat_name =
"pkt4-discover-received";
3976 stat_name =
"pkt4-offer-received";
3979 stat_name =
"pkt4-request-received";
3983 stat_name =
"pkt4-ack-received";
3987 stat_name =
"pkt4-nak-received";
3990 stat_name =
"pkt4-release-received";
3993 stat_name =
"pkt4-decline-received";
3996 stat_name =
"pkt4-inform-received";
4010 static_cast<int64_t>(1));
4016 static_cast<int64_t>(1));
4020 switch (response->getType()) {
4022 stat_name =
"pkt4-offer-sent";
4025 stat_name =
"pkt4-ack-sent";
4028 stat_name =
"pkt4-nak-sent";
4036 static_cast<int64_t>(1));
4040 return (Hooks.hook_index_buffer4_receive_);
4044 return (Hooks.hook_index_pkt4_receive_);
4048 return (Hooks.hook_index_subnet4_select_);
4052 return (Hooks.hook_index_lease4_release_);
4056 return (Hooks.hook_index_pkt4_send_);
4060 return (Hooks.hook_index_buffer4_send_);
4064 return (Hooks.hook_index_lease4_decline_);
4069 HooksManager::clearParkingLots();
4073 static std::list<std::list<std::string>>
const list({
4074 {
"config-control",
"config-databases",
"[]"},
4075 {
"hooks-libraries",
"[]",
"parameters",
"*"},
4077 {
"hosts-databases",
"[]"},
const isc::log::MessageID DHCP4_NCR_CREATION_FAILED
RAII class creating a critical section.
static std::string lifetimeToText(uint32_t lifetime)
Print lifetime.
std::string getIdentifierAsText() const
Returns host identifier in a textual form.
void setPacketStatisticsDefaults()
This function sets statistics related to DHCPv4 packets processing to their initial values...
bool isV4Bcast() const
Convenience function to check if it is an IPv4 broadcast address.
asiolink::IOAddress ciaddr_
ciaddr from the client's message.
const isc::log::MessageID DHCP4_DECLINE_FAIL
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
static OptionDefinitionPtr getRuntimeOptionDef(const std::string &space, const uint16_t code)
Returns runtime (non-standard) option definition by space and option code.
void run_one()
Main server processing step.
static int getHookIndexBuffer4Send()
Returns the index for "buffer4_send" hook point.
virtual void updateLease4(const Lease4Ptr &lease4)=0
Updates IPv4 lease.
const isc::log::MessageID DHCP4_CLASS_UNDEFINED
void appendRequestedVendorOptions(Dhcpv4Exchange &ex)
Appends requested vendor options as requested by client.
const isc::log::MessageID DHCP4_SUBNET_SELECTION_FAILED
virtual ~Dhcpv4Srv()
Destructor. Used during DHCPv4 service shutdown.
asiolink::IOAddress remote_address_
Source address of the message.
const isc::log::MessageID DHCP4_PACKET_NAK_0002
const isc::log::MessageID DHCP4_CLIENT_HOSTNAME_DATA
uint16_t server_port_
UDP port number on which server listens.
void processPacketPktSend(hooks::CalloutHandlePtr &callout_handle, Pkt4Ptr &query, Pkt4Ptr &rsp)
Executes pkt4_send callout.
Message Type option missing.
const isc::log::MessageID DHCP4_PACKET_SEND
void processPacketBufferSend(hooks::CalloutHandlePtr &callout_handle, Pkt4Ptr &rsp)
Executes buffer4_send callout and sends the response.
static std::string getDBVersion()
Local version of getDBVersion() class method.
const int DBGLVL_TRACE_BASIC
Trace basic operations.
boost::shared_ptr< OptionCustom > OptionCustomPtr
A pointer to the OptionCustom object.
const isc::log::MessageID DHCP4_PACKET_SEND_FAIL
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
static int getHookIndexBuffer4Receive()
Returns the index for "buffer4_receive" hook point.
Exception thrown during option unpacking This exception is thrown when an error has occurred...
DHCPv4 Option class for handling list of IPv4 addresses.
static SubnetSelector initSelector(const Pkt4Ptr &query)
Build selector from a client's message.
bool acceptMessageType(const Pkt4Ptr &query) const
Check if received message type is valid for the server to process.
std::vector< isc::asiolink::IOAddress > AddressContainer
Defines a collection of IPv4 addresses.
const isc::log::MessageID DHCP4_PACKET_PACK
void adjustDomainName(const T &fqdn, T &fqdn_resp, const DdnsParams &ddns_params)
Set server FQDN name based on configuration and a given FQDN.
void buildCfgOptionList(Dhcpv4Exchange &ex)
Build the configured option list.
static void destroy()
Destroy lease manager.
Pkt6Ptr getPkt6() const
Returns encapsulating DHCPv6 message.
const isc::log::MessageID DHCP4_LEASE_ADVERT
const isc::log::MessageID DHCP4_CLIENTID_IGNORED_FOR_LEASES
const isc::log::MessageID DHCP4_RESPONSE_DATA
const isc::log::MessageID DHCP4_PACKET_QUEUE_FULL
An abstract API for lease database.
boost::shared_ptr< const CfgOption > ConstCfgOptionPtr
Const pointer.
const isc::log::MessageID DHCP4_CLIENT_FQDN_PROCESS
const isc::log::MessageID DHCP4_EMPTY_HOSTNAME
IOAddress getNetmask4(uint8_t len)
Generates an IPv4 netmask of specified length.
void sendResponseNoThrow(hooks::CalloutHandlePtr &callout_handle, Pkt4Ptr &query, Pkt4Ptr &rsp)
Process an unparked DHCPv4 packet and sends the response.
static CfgMgr & instance()
returns a single instance of Configuration Manager
asiolink::IOAddress option_select_
RAI link select or subnet select option.
const isc::log::MessageID DHCP4_PACKET_DROP_0006
void startSender(D2ClientErrorHandler error_handler, isc::asiolink::IOService &io_service)
Enables sending NameChangeRequests to kea-dhcp-ddns.
Result
Defines the outcome of an asynchronous NCR send.
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
const isc::log::MessageID DHCP4_INFORM_DIRECT_REPLY
OptionPtr interface_id_
Interface id option.
boost::shared_ptr< OptionUint8Array > OptionUint8ArrayPtr
std::vector< Lease4Ptr > Lease4Collection
A collection of IPv4 leases.
boost::shared_ptr< Option > OptionPtr
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
void initResponse()
Initializes the instance of the response message.
static void classifyPacket(const Pkt4Ptr &pkt)
Assigns incoming packet to zero or more classes.
AllocEngine::ClientContext4Ptr getContext() const
Returns the copy of the context for the Allocation engine.
const isc::log::MessageID DHCP4_TESTING_MODE_SEND_TO_SOURCE_ENABLED
const isc::log::MessageID DHCP4_SHUTDOWN_REQUEST
void adjustRemoteAddr(Dhcpv4Exchange &ex)
Sets remote addresses for outgoing packet.
boost::shared_ptr< Option4ClientFqdn > Option4ClientFqdnPtr
A pointer to the Option4ClientFqdn object.
Represents a DHCPv6 packet.
boost::shared_ptr< OptionString > OptionStringPtr
Pointer to the OptionString object.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
void classifyPacket(const Pkt4Ptr &pkt)
Assigns incoming packet to zero or more classes.
const isc::log::MessageID DHCP4_INIT_REBOOT
isc::log::Logger bad_packet4_logger(DHCP4_BAD_PACKET_LOGGER_NAME)
Logger for rejected packets.
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Holds information about DHCP service enabling status.
const isc::log::MessageID DHCP4_RELEASE_FAIL_WRONG_CLIENT
virtual void sendPacket(const Pkt4Ptr &pkt)
dummy wrapper around IfaceMgr::send()
const isc::log::MessageID DHCP4_POST_ALLOCATION_NAME_UPDATE_FAIL
const isc::log::MessageID DHCP4_SRV_D2STOP_ERROR
boost::shared_ptr< CfgIface > CfgIfacePtr
A pointer to the CfgIface .
asiolink::IOAddress giaddr_
giaddr from the client's message.
Represents DHCPv4 Client FQDN Option (code 81).
const isc::log::MessageID DHCP4_BUFFER_WAIT_SIGNAL
const isc::log::MessageID DHCP4_RELEASE_FAIL
bool getUpdateOnRenew() const
Returns whether or not DNS should be updated when leases renew.
Forward declaration to OptionInt.
const isc::log::MessageID DHCP4_HOOK_BUFFER_RCVD_SKIP
boost::shared_ptr< Pool > PoolPtr
a pointer to either IPv4 or IPv6 Pool
static Dhcp4to6Ipc & instance()
Returns pointer to the sole instance of Dhcp4to6Ipc.
boost::shared_ptr< NameChangeRequest > NameChangeRequestPtr
Defines a pointer to a NameChangeRequest.
const int DBG_DHCP4_BASIC_DATA
Debug level used to log the traces with some basic data.
isc::log::Logger options4_logger(DHCP4_OPTIONS_LOGGER_NAME)
Logger for options parser.
const int DBG_DHCP4_START
Debug level used to log information during server startup.
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.
int getExitValue()
Fetches the exit value.
void discardPackets()
Discards parked packets Clears the packet parking lots of all packets.
void setDomainName(const std::string &domain_name, const DomainNameType domain_name_type)
Set new domain-name.
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.
boost::shared_ptr< OptionUint32 > OptionUint32Ptr
RAII object enabling copying options retrieved from the packet.
const isc::log::MessageID DHCP4_FLEX_ID
isc::log::Logger packet4_logger(DHCP4_PACKET_LOGGER_NAME)
Logger for processed packets.
void createNameChangeRequests(const Lease4Ptr &lease, const Lease4Ptr &old_lease, const DdnsParams &ddns_params)
Creates NameChangeRequests which correspond to the lease which has been acquired. ...
static std::string getDBVersion()
Local version of getDBVersion() class method.
boost::shared_ptr< AllocEngine > AllocEnginePtr
A pointer to the AllocEngine object.
static int getHookIndexLease4Release()
Returns the index for "lease4_release" hook point.
const isc::log::MessageID DHCP4_CLIENT_HOSTNAME_MALFORMED
static StatsMgr & instance()
Statistics Manager accessor method.
const int DBG_DHCP4_BASIC
Debug level used to trace basic operations within the code.
bool isV4() const
Convenience function to check for an IPv4 address.
boost::shared_ptr< const CfgSubnets4 > ConstCfgSubnets4Ptr
Const pointer.
std::vector< uint8_t > OptionBuffer
buffer types used in DHCP code.
void processRelease(Pkt4Ptr &release, AllocEngine::ClientContext4Ptr &context)
Processes incoming DHCPRELEASE messages.
Statistics Manager class.
ClientClasses client_classes_
Classes that the client belongs to.
static const size_t OPTION4_HDR_LEN
length of the usual DHCPv4 option header (there are exceptions)
The IOService class is a wrapper for the ASIO io_service class.
std::string generateFqdn(const asiolink::IOAddress &address, const DdnsParams &ddns_params, const bool trailing_dot=true) const
Builds a FQDN based on the configuration and given IP address.
const isc::log::MessageID DHCP4_DECLINE_LEASE
const isc::log::MessageID DHCP4_HOOK_BUFFER_RCVD_DROP
std::list< std::list< std::string > > jsonPathsToRedact() const finaloverride
Return a list of all paths that contain passwords or secrets for kea-dhcp4.
Server uses routing to determine the right interface to send response.
const isc::log::MessageID DHCP4_PACKET_DROP_0008
const isc::log::MessageID DHCP4_DECLINE_LEASE_MISMATCH
asiolink::IOAddress first_relay_linkaddr_
First relay link address.
const isc::log::MessageID DHCP4_PACKET_PACK_FAIL
void setFixedFields(Dhcpv4Exchange &ex)
Sets fixed fields of the outgoing packet.
bool send(const Pkt6Ptr &pkt)
Sends an IPv6 packet.
void setMatchingPacketFilter(const bool direct_response_desired=false)
Set Packet Filter object to handle send/receive packets.
Subnet selector used to specify parameters used to select a subnet.
OptionInt< uint32_t > OptionUint32
isc::log::Logger dhcp4_logger(DHCP4_APP_LOGGER_NAME)
Base logger for DHCPv4 server.
const isc::log::MessageID DHCP4_RELEASE_EXCEPTION
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
boost::shared_ptr< CfgSharedNetworks4 > CfgSharedNetworks4Ptr
Pointer to the configuration of IPv4 shared networks.
void queueNCR(const NameChangeType &chg_type, const Lease4Ptr &lease)
Creates name change request from the DHCPv4 lease.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
asiolink::IOServicePtr & getIOService()
Returns pointer to the IO service used by the server.
const isc::log::MessageID DHCP4_CLASS_UNCONFIGURED
virtual void d2ClientErrorHandler(const dhcp_ddns::NameChangeSender::Result result, dhcp_ddns::NameChangeRequestPtr &ncr)
Implements the error handler for DHCP_DDNS IO errors.
std::list< ClientClass >::const_iterator const_iterator
Type of iterators.
std::string getDomainName() const
Returns the domain-name in the text format.
const char *const config_report[]
structure that describes a single relay information
const isc::log::MessageID DHCP4_SRV_UNLOAD_LIBRARIES_ERROR
bool accept(const Pkt4Ptr &query) const
Checks whether received message should be processed or discarded.
Forward declaration to OptionIntArray.
void processDecline(Pkt4Ptr &decline, AllocEngine::ClientContext4Ptr &context)
Process incoming DHCPDECLINE messages.
void setTeeTimes(const Lease4Ptr &lease, const Subnet4Ptr &subnet, Pkt4Ptr resp)
Adds the T1 and T2 timers to the outbound response as appropriate.
const isc::log::MessageID DHCP4_BUFFER_RECEIVE_FAIL
std::list< ConstCfgOptionPtr > CfgOptionList
Const pointer list.
volatile bool shutdown_
Indicates if shutdown is in progress.
bool getEnableUpdates() const
Returns whether or not DHCP DDNS updating is enabled.
Implementation of the mechanisms to control the use of the Configuration Backends by the DHCPv4 serve...
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
static void sanityCheck(const Pkt4Ptr &query, RequirementLevel serverid)
Verifies if specified packet meets RFC requirements.
void processDhcp4QueryAndSendResponse(Pkt4Ptr &query, Pkt4Ptr &rsp, bool allow_packet_park)
Process a single incoming DHCPv4 query.
const_iterator cend() const
Iterator to the past the end element.
static void appendServerID(Dhcpv4Exchange &ex)
Adds server identifier option to the server's response.
const isc::log::MessageID DHCP4_PACKET_DROP_0010
Pkt4Ptr processRequest(Pkt4Ptr &request, AllocEngine::ClientContext4Ptr &context)
Processes incoming REQUEST and returns REPLY response.
void processPacket(Pkt4Ptr &query, Pkt4Ptr &rsp, bool allow_packet_park=true)
Process a single incoming DHCPv4 packet.
void appendRequestedOptions(Dhcpv4Exchange &ex)
Appends options requested by client.
boost::shared_ptr< Lease4Collection > Lease4CollectionPtr
A shared pointer to the collection of IPv4 leases.
boost::shared_ptr< ClientContext4 > ClientContext4Ptr
Pointer to the ClientContext4.
static int getHookIndexLease4Decline()
Returns the index for "lease4_decline" hook point.
static std::string getDBVersion()
Local version of getDBVersion() class method.
std::pair< OptionContainerPersistIndex::const_iterator, OptionContainerPersistIndex::const_iterator > OptionContainerPersistRange
Pair of iterators to represent the range of options having the same persistency flag.
static int getHookIndexSubnet4Select()
Returns the index for "subnet4_select" hook point.
static int getHookIndexPkt4Send()
Returns the index for "pkt4_send" hook point.
const isc::log::MessageID DHCP4_PACKET_DROP_0002
const int DBG_DHCP4_DETAIL_DATA
This level is used to log the contents of packets received and sent.
A generic exception that is thrown when an unexpected error condition occurs.
boost::shared_ptr< ClientClassDictionary > ClientClassDictionaryPtr
Defines a pointer to a ClientClassDictionary.
const isc::log::MessageID DHCP4_LEASE_REUSE
static std::string getDBVersion()
Local version of getDBVersion() class method.
const isc::log::MessageID DHCP4_PACKET_DROP_0013
Pkt4Ptr getQuery() const
Returns the pointer to the query from the client.
Wrapper class around callout handle which automatically resets handle's state.
Pkt4Ptr processInform(Pkt4Ptr &inform)
Processes incoming DHCPINFORM messages.
void stopD2()
Stops DHCP_DDNS client IO if DDNS updates are enabled.
static const IOAddress & IPV4_ZERO_ADDRESS()
Returns an address set to all zeros.
isc::dhcp::Subnet4Ptr selectSubnet4o6(const Pkt4Ptr &query, bool &drop, bool sanity_only=false) const
Selects a subnet for a given client's DHCP4o6 packet.
const isc::log::MessageID DHCP4_PACKET_DROP_0004
const isc::log::MessageID DHCP4_NO_LEASE_INIT_REBOOT
bool ddnsEnabled()
Convenience method for checking if DHCP-DDNS is enabled.
asiolink::IOAddress local_address_
Address on which the message was received.
const isc::log::MessageID DHCP4_PACKET_RECEIVED
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Flexible host identifier.
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
const isc::log::MessageID DHCP4_BUFFER_UNPACK
const char *const * dhcp4_config_report
const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_DROP
const isc::log::MessageID DHCP4_BUFFER_RECEIVED
void processDhcp4Query(Pkt4Ptr &query, Pkt4Ptr &rsp, bool allow_packet_park)
Process a single incoming DHCPv4 query.
const isc::log::MessageID DHCP4_CLASS_UNTESTABLE
static void classifyByVendor(const Pkt4Ptr &pkt)
Assign class using vendor-class-identifier option.
bool isV6Zero() const
Convenience function to check if it is an IPv4 zero address.
bool isV4Zero() const
Convenience function to check if it is an IPv4 zero address.
const isc::log::MessageID DHCP4_RELEASE_FAIL_NO_LEASE
const int DBG_DHCP4_DETAIL
Debug level used to trace detailed errors.
const isc::log::MessageID DHCP4_NCR_CREATE
const isc::log::MessageID DHCP4_SRV_DHCP4O6_ERROR
boost::shared_ptr< ClientId > ClientIdPtr
Shared pointer to a Client ID.
const isc::log::MessageID DHCP4_PACKET_DROP_0005
const isc::log::MessageID DHCP4_HOOK_PACKET_SEND_DROP
const isc::log::MessageID DHCP4_PACKET_DROP_0001
Convenience container for conveying DDNS behavioral parameters It is intended to be created per Packe...
const isc::log::MessageID DHCP4_HOOK_PACKET_SEND_SKIP
static OptionDefinitionPtr getOptionDef(const std::string &space, const uint16_t code)
Return the first option definition matching a particular option code.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
const int DBG_DHCP4_HOOKS
Debug level used to trace hook related operations.
const isc::log::MessageID DHCP4_CLIENT_FQDN_DATA
bool acceptServerId(const Pkt4Ptr &pkt) const
Verifies if the server id belongs to our server.
boost::shared_ptr< ClientClassDef > ClientClassDefPtr
a pointer to an ClientClassDef
OptionPtr option_
Option instance.
virtual Pkt4Ptr receivePacket(int timeout)
dummy wrapper around IfaceMgr::receive4
const isc::log::MessageID DHCP4_RESPONSE_HOSTNAME_DATA
Pkt4Ptr getResponse() const
Returns the pointer to the server's response.
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
const isc::log::MessageID DHCP4_GENERATE_FQDN
const isc::log::MessageID DHCP4_HOOK_PACKET_RCVD_SKIP
void processPacketAndSendResponse(Pkt4Ptr &query)
Process a single incoming DHCPv4 packet and sends the response.
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_OPEN_SOCKET
static void processStatsSent(const Pkt4Ptr &response)
Updates statistics for transmitted packets.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
const isc::log::MessageID DHCP4_HOOK_BUFFER_SEND_SKIP
boost::shared_ptr< AllocEngine > alloc_engine_
Allocation Engine.
Client race avoidance RAII handler.
const isc::log::MessageID DHCP4_PACKET_DROP_0009
This is a base class for exceptions thrown from the DNS library module.
Defines the logger used by the top-level component of kea-dhcp-ddns.
NetworkStatePtr network_state_
Holds information about disabled DHCP service and/or disabled subnet/network scopes.
Datagram socket, i.e. IP/UDP socket.
void startD2()
Starts DHCP_DDNS client IO if DDNS updates are enabled.
const isc::log::MessageID DHCP4_SUBNET_DATA
void declineLease(const Lease4Ptr &lease, const Pkt4Ptr &decline, AllocEngine::ClientContext4Ptr &context)
Marks lease as declined.
Represents DHCPv4 packet.
bool hasOpenSocket(const uint16_t family) const
Checks if there is at least one socket of the specified family open.
D2ClientMgr isolates Kea from the details of being a D2 client.
const isc::log::MessageID DHCP4_CLASS_ASSIGNED
void getUpdateDirections(const T &fqdn_resp, bool &forward, bool &reverse)
Get directional update flags based on server FQDN flags.
static const uint8_t FLAG_E
Bit E.
RequirementLevel
defines if certain option may, must or must not appear
ReplaceClientNameMode
Defines the client name replacement modes.
const isc::log::MessageID DHCP4_CLIENT_HOSTNAME_PROCESS
boost::shared_ptr< ClientClassDefList > ClientClassDefListPtr
Defines a pointer to a ClientClassDefList.
const isc::log::MessageID DHCP4_RELEASE
const isc::log::MessageID DHCP4_PACKET_PROCESS_EXCEPTION
Exception thrown when a call to select is interrupted by a signal.
boost::shared_ptr< CalloutHandle > CalloutHandlePtr
A shared pointer to a CalloutHandle object.
static std::string srvidToString(const OptionPtr &opt)
converts server-id to text Converts content of server-id option to a text representation, e.g.
isc::log::Logger hooks_logger("hooks")
Hooks Logger.
const isc::log::MessageID DHCP4_HOOK_LEASE4_RELEASE_SKIP
const isc::log::MessageID DHCP4_QUERY_DATA
const isc::log::MessageID DHCP4_PACKET_DROP_0007
void requiredClassify(Dhcpv4Exchange &ex)
Assigns incoming packet to zero or more classes (required pass).
bool acceptDirectRequest(const Pkt4Ptr &query) const
Check if a message sent by directly connected client should be accepted or discarded.
const isc::log::MessageID DHCP4_SUBNET_SELECTED
boost::shared_ptr< Pkt4o6 > Pkt4o6Ptr
A pointer to Pkt4o6 object.
void assignLease(Dhcpv4Exchange &ex)
Assigns a lease and appends corresponding options.
static const IOAddress & IPV4_BCAST_ADDRESS()
Returns a "255.255.255.255" broadcast address.
static const std::string VENDOR_CLASS_PREFIX
this is a prefix added to the content of vendor-class option
std::string qualifyName(const std::string &partial_name, const DdnsParams &ddns_params, const bool trailing_dot) const
Adds a qualifying suffix to a given domain name.
const isc::log::MessageID DHCP4_PACKET_PROCESS_STD_EXCEPTION
void closeSockets()
Closes all open sockets.
Holds Client identifier or client IPv4 address.
std::string getValue() const
Returns the string value held by the option.
const isc::log::MessageID DHCP4_PACKET_OPTIONS_SKIPPED
const isc::log::MessageID DHCP4_SRV_CONSTRUCT_ERROR
void initResponse4o6()
Initializes the DHCPv6 part of the response message.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
An exception that is thrown if a DHCPv6 protocol violation occurs while processing a message (e...
#define DHCP4_OPTION_SPACE
global std option spaces
const isc::log::MessageID DHCP4_RESPONSE_FQDN_DATA
boost::shared_ptr< OptionContainer > OptionContainerPtr
Pointer to the OptionContainer object.
const isc::log::MessageID DHCP4_LEASE_ALLOC
bool tryLock(Pkt4Ptr query, ContinuationPtr cont=ContinuationPtr())
Tries to acquires a client.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
void deleteResponse()
Removes the response message by resetting the pointer to NULL.
const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_SKIP
void appendBasicOptions(Dhcpv4Exchange &ex)
Append basic options if they are not present.
std::string iface_name_
Name of the interface on which the message was received.
void processClientName(Dhcpv4Exchange &ex)
Processes Client FQDN and Hostname Options sent by a client.
int run()
Main server processing loop.
CfgOptionList & getCfgOptionList()
Returns the configured option list (non-const version)
static OptionDefinitionPtr getLastResortOptionDef(const std::string &space, const uint16_t code)
Returns last resort option definition by space and option code.
isc::log::Logger ddns4_logger(DHCP4_DDNS_LOGGER_NAME)
Logger for Hostname or FQDN processing.
void conditionallySetReservedClientClasses()
Assigns classes retrieved from host reservation database if they haven't been yet set...
static uint16_t checkRelayPort(const Dhcpv4Exchange &ex)
Check if the relay port RAI sub-option was set in the query.
const isc::log::MessageID DHCP4_PACKET_NAK_0004
uint16_t getSocket(const isc::dhcp::Pkt6Ptr &pkt)
Return most suitable socket for transmitting specified IPv6 packet.
boost::shared_ptr< const CfgHostOperations > ConstCfgHostOperationsPtr
Pointer to the const object.
bool isV6LinkLocal() const
checks whether and address is IPv6 and is link-local
void close()
Close communication socket.
boost::shared_ptr< OptionDefinition > OptionDefinitionPtr
Pointer to option definition object.
const isc::log::MessageID DHCP4_DEFERRED_OPTION_MISSING
void suspendUpdates()
Suspends sending requests.
bool dhcp4o6_
Specifies if the packet is DHCP4o6.
Defines the Dhcp4o6Ipc class.
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress &addr) const =0
Returns an IPv4 lease for specified IPv4 address.
void setReservedMessageFields()
Sets reserved values of siaddr, sname and file in the server's response.
string trim(const string &instring)
Trim Leading and Trailing Spaces.
D2ClientMgr & getD2ClientMgr()
Fetches the DHCP-DDNS manager.
isc::asiolink::IOAddress linkaddr_
fixed field in relay-forw/relay-reply
virtual bool deleteLease(const Lease4Ptr &lease)=0
Deletes an IPv4 lease.
const isc::log::MessageID DHCP4_DEFERRED_OPTION_UNPACK_FAIL
const isc::log::MessageID DHCP4_PACKET_NAK_0001
bool isClientClassBuiltIn(const ClientClass &client_class)
Check if a client class name is builtin.
isc::log::Logger lease4_logger(DHCP4_LEASE_LOGGER_NAME)
Logger for lease allocation logic.
void insert(const ClientClass &class_name)
Insert an element.
virtual std::string toText(int indent=0) const
Returns string representation of the option.
boost::shared_ptr< StringSanitizer > StringSanitizerPtr
bool getFlag(const uint8_t flag) const
Checks if the specified flag of the DHCPv4 Client FQDN Option is set.
void shutdown() override
Instructs the server to shut down.
IdentifierType
Type of the host identifier.
static unsigned int getLabelCount(const std::string &text_name)
Return the number of labels in the Name.
const isc::log::MessageID DHCP4_RESPONSE_HOSTNAME_GENERATE
bool empty() const
Check if classes is empty.
The IOAddress class represents an IP addresses (version agnostic)
static LeaseMgr & instance()
Return current lease manager.
bool isDirectResponseSupported() const
Check if packet be sent directly to the client having no address.
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...
void deferredUnpack(Pkt4Ptr &query)
Perform deferred option unpacking.
isc::hooks::CalloutHandlePtr getCalloutHandle(const T &pktptr)
CalloutHandle Store.
const isc::log::MessageID DHCP4_CLIENT_NAME_PROC_FAIL
const isc::log::MessageID EVAL_RESULT
Option with defined data fields represented as buffers that can be accessed using data field index...
const isc::log::MessageID DHCP4_DECLINE_LEASE_NOT_FOUND
const isc::log::MessageID DHCP4_SUBNET_DYNAMICALLY_CHANGED
const isc::log::MessageID DHCP4_PACKET_NAK_0003
static void setReservedClientClasses(AllocEngine::ClientContext4Ptr context)
Assigns classes retrieved from host reservation database.
static std::string getVersion(bool extended)
returns Kea version on stdout and exit.
uint16_t client_port_
UDP port number to which server sends all responses.
Context information for the DHCPv4 lease allocation.
void processPacketAndSendResponseNoThrow(Pkt4Ptr &query)
Process a single incoming DHCPv4 packet and sends the response.
void adjustIfaceData(Dhcpv4Exchange &ex)
Set IP/UDP and interface parameters for the DHCPv4 response.
const isc::log::MessageID DHCP4_HOOK_LEASES4_COMMITTED_PARK
isc::dhcp::Subnet4Ptr selectSubnet(const Pkt4Ptr &query, bool &drop, bool sanity_only=false) const
Selects a subnet for a given client's packet.
DHCPv4 and DHCPv6 allocation engine.
const_iterator cbegin() const
Iterator to the first element.
static void processStatsReceived(const Pkt4Ptr &query)
Class methods for DHCPv4-over-DHCPv6 handler.
OptionContainer::nth_index< 2 >::type OptionContainerPersistIndex
Type of the index #2 - option persistency flag.
const isc::log::MessageID DHCP4_HOOK_LEASES4_COMMITTED_DROP
const isc::log::MessageID DHCP4_PACKET_DROP_0003
boost::shared_ptr< Continuation > ContinuationPtr
Define the type of shared pointers to continuations.
Class which represents an option carrying a single string value.
Pkt4Ptr processDiscover(Pkt4Ptr &discover)
Processes incoming DISCOVER and returns response.
Container for storing client class names.
Represents DHCPv4-over-DHCPv6 packet.
const isc::log::MessageID DHCP4_HOOK_DECLINE_SKIP
boost::shared_ptr< Expression > ExpressionPtr
Contains declarations for loggers used by the DHCPv4 server component.
This class represents vendor-specific information option.
void setFlag(const uint8_t flag, const bool set)
Modifies the value of the specified DHCPv4 Client Fqdn Option flag.
void setValue(const std::string &name, const int64_t value)
Records absolute integer observation.
static int getHookIndexPkt4Receive()
Returns the index for "pkt4_receive" hook point.
void adjustFqdnFlags(const T &fqdn, T &fqdn_resp, const DdnsParams &ddns_params)
Set server FQDN flags based on configuration and a given FQDN.
bool getSendResponsesToSource() const
Returns value of the test_send_responses_to_source_ flag.
const isc::log::MessageID DHCP4_DDNS_REQUEST_SEND_FAILED
uint32_t getVendorId() const
Returns enterprise identifier.
const isc::log::MessageID DHCP4_RESERVED_HOSTNAME_ASSIGNED
std::string toText(const std::string &separator=", ") const
Returns all class names as text.
void stopSender()
Disables sending NameChangeRequests to kea-dhcp-ddns.
ContinuationPtr makeContinuation(Continuation &&cont)
Continuation factory.