8 #include <kea_version.h>
43 #include <eval/eval_messages.h>
65 #include <boost/algorithm/string.hpp>
66 #include <boost/bind.hpp>
67 #include <boost/foreach.hpp>
68 #include <boost/pointer_cast.hpp>
69 #include <boost/shared_ptr.hpp>
87 int hook_index_buffer4_receive_;
88 int hook_index_pkt4_receive_;
89 int hook_index_subnet4_select_;
90 int hook_index_leases4_committed_;
91 int hook_index_lease4_release_;
92 int hook_index_pkt4_send_;
93 int hook_index_buffer4_send_;
94 int hook_index_lease4_decline_;
95 int hook_index_host4_identifier_;
99 hook_index_buffer4_receive_ = HooksManager::registerHook(
"buffer4_receive");
100 hook_index_pkt4_receive_ = HooksManager::registerHook(
"pkt4_receive");
101 hook_index_subnet4_select_ = HooksManager::registerHook(
"subnet4_select");
102 hook_index_leases4_committed_ = HooksManager::registerHook(
"leases4_committed");
103 hook_index_pkt4_send_ = HooksManager::registerHook(
"pkt4_send");
104 hook_index_lease4_release_ = HooksManager::registerHook(
"lease4_release");
105 hook_index_buffer4_send_ = HooksManager::registerHook(
"buffer4_send");
106 hook_index_lease4_decline_ = HooksManager::registerHook(
"lease4_decline");
107 hook_index_host4_identifier_ = HooksManager::registerHook(
"host4_identifier");
126 : alloc_engine_(alloc_engine), query_(query), resp_(),
129 if (!alloc_engine_) {
131 " when creating an instance of the Dhcpv4Exchange");
136 " creating an instance of the Dhcpv4Exchange");
142 context_->subnet_ = subnet;
144 context_->hwaddr_ = query->getHWAddr();
146 context_->query_ = query;
154 context_->clientid_.reset(
new ClientId(opt_clientid->getData()));
161 setHostIdentifiers();
164 alloc_engine->findReservation(*context_);
169 if (!context_->hosts_.empty()) {
170 query->addClass(
"KNOWN");
172 .arg(query->getLabel())
175 query->addClass(
"UNKNOWN");
177 .arg(query->getLabel())
185 if (!classes.
empty()) {
187 .arg(query_->getLabel())
194 uint8_t resp_type = 0;
208 resp_.reset(
new Pkt4(resp_type,
getQuery()->getTransid()));
210 copyDefaultOptions();
224 const Pkt6Ptr& query6 = query->getPkt6();
228 if (!query6->relay_info_.empty()) {
229 resp6->copyRelayInfo(query6);
232 resp6->setIface(query6->getIface());
233 resp6->setIndex(query6->getIndex());
234 resp6->setRemoteAddr(query6->getRemoteAddr());
235 resp6->setRemotePort(query6->getRemotePort());
236 resp_.reset(
new Pkt4o6(resp_, resp6));
240 Dhcpv4Exchange::copyDefaultFields() {
241 resp_->setIface(query_->getIface());
242 resp_->setIndex(query_->getIndex());
249 resp_->setHops(query_->getHops());
252 resp_->setHWAddr(query_->getHWAddr());
255 resp_->setGiaddr(query_->getGiaddr());
264 HWAddrPtr src_hw_addr = query_->getLocalHWAddr();
266 resp_->setLocalHWAddr(src_hw_addr);
268 HWAddrPtr dst_hw_addr = query_->getRemoteHWAddr();
270 resp_->setRemoteHWAddr(dst_hw_addr);
274 resp_->setFlags(query_->getFlags());
278 Dhcpv4Exchange::copyDefaultOptions() {
283 if (client_id && echo) {
284 resp_->addOption(client_id);
290 resp_->addOption(rai);
303 resp_->addOption(subnet_sel);
308 Dhcpv4Exchange::setHostIdentifiers() {
315 cfg->getIdentifierTypes()) {
318 if (context_->hwaddr_ && !context_->hwaddr_->hwaddr_.empty()) {
319 context_->addHostIdentifier(id_type, context_->hwaddr_->hwaddr_);
324 if (context_->clientid_) {
325 const std::vector<uint8_t>& vec = context_->clientid_->getDuid();
330 if ((vec[0] == CLIENT_ID_OPTION_TYPE_DUID) && (vec.size() > 5)) {
332 context_->addHostIdentifier(id_type,
333 std::vector<uint8_t>(vec.begin() + 5,
344 OptionPtr circuit_id_opt = rai->getOption(RAI_OPTION_AGENT_CIRCUIT_ID);
345 if (circuit_id_opt) {
346 const OptionBuffer& circuit_id_vec = circuit_id_opt->getData();
347 if (!circuit_id_vec.empty()) {
348 context_->addHostIdentifier(id_type, circuit_id_vec);
356 if (context_->clientid_) {
357 const std::vector<uint8_t>& vec = context_->clientid_->getDuid();
359 context_->addHostIdentifier(id_type, vec);
365 if (!HooksManager::calloutsPresent(
Hooks.hook_index_host4_identifier_)) {
372 std::vector<uint8_t> id;
381 callout_handle->setArgument(
"query4", context_->query_);
382 callout_handle->setArgument(
"id_type", type);
383 callout_handle->setArgument(
"id_value",
id);
386 HooksManager::callCallouts(
Hooks.hook_index_host4_identifier_,
389 callout_handle->getArgument(
"id_type", type);
390 callout_handle->getArgument(
"id_value",
id);
392 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_CONTINUE) &&
398 context_->addHostIdentifier(type,
id);
410 if (context_->currentHost() && query_) {
411 const ClientClasses& classes = context_->currentHost()->getClientClasses4();
413 cclass != classes.
cend(); ++cclass) {
414 query_->addClass(*cclass);
424 if (!host->getNextServer().isV4Zero()) {
425 resp_->setSiaddr(host->getNextServer());
428 std::string sname = host->getServerHostname();
429 if (!sname.empty()) {
430 resp_->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
434 std::string bootfile = host->getBootFileName();
435 if (!bootfile.empty()) {
436 resp_->setFile(
reinterpret_cast<const uint8_t*
>(bootfile.c_str()),
445 const bool direct_response_desired)
446 : io_service_(new
IOService()), shutdown_(true), alloc_engine_(), port_(port),
473 }
catch (
const std::exception &e) {
488 }
catch(
const std::exception& ex) {
495 }
catch(
const std::exception& ex) {
507 HooksManager::getHooksManager().unloadLibraries();
518 bool sanity_only)
const {
521 if (query->isDhcp4o6()) {
530 subnet = cfgmgr.
getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
535 HooksManager::calloutsPresent(
Hooks.hook_index_subnet4_select_)) {
548 callout_handle->setArgument(
"query4", query);
549 callout_handle->setArgument(
"subnet4", subnet);
550 callout_handle->setArgument(
"subnet4collection",
552 getCfgSubnets4()->getAll());
555 HooksManager::callCallouts(
Hooks.hook_index_subnet4_select_,
561 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
563 DHCP4_HOOK_SUBNET4_SELECT_SKIP)
564 .arg(query->getLabel());
570 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
572 DHCP4_HOOK_SUBNET4_SELECT_DROP)
573 .arg(query->getLabel());
579 callout_handle->getArgument(
"subnet4", subnet);
585 .arg(query->getLabel())
586 .arg(subnet->getID());
590 .arg(query->getLabel())
591 .arg(subnet->toText());
595 DHCP4_SUBNET_SELECTION_FAILED)
596 .arg(query->getLabel());
604 bool sanity_only)
const {
609 selector.
ciaddr_ = query->getCiaddr();
610 selector.
giaddr_ = query->getGiaddr();
621 Pkt4o6Ptr query4o6 = boost::dynamic_pointer_cast<Pkt4o6>(query);
625 const Pkt6Ptr& query6 = query4o6->getPkt6();
628 if (query6 && !query6->relay_info_.empty()) {
644 OptionCustomPtr oc = boost::dynamic_pointer_cast<OptionCustom>(sbnsel);
651 subnet = cfgmgr.
getCurrentCfg()->getCfgSubnets4()->selectSubnet4o6(selector);
656 HooksManager::calloutsPresent(
Hooks.hook_index_subnet4_select_)) {
666 callout_handle->setArgument(
"query4", query);
667 callout_handle->setArgument(
"subnet4", subnet);
668 callout_handle->setArgument(
"subnet4collection",
670 getCfgSubnets4()->getAll());
673 HooksManager::callCallouts(
Hooks.hook_index_subnet4_select_,
679 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
681 DHCP4_HOOK_SUBNET4_SELECT_SKIP)
682 .arg(query->getLabel());
688 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
690 DHCP4_HOOK_SUBNET4_SELECT_DROP)
691 .arg(query->getLabel());
697 callout_handle->getArgument(
"subnet4", subnet);
703 .arg(query->getLabel())
704 .arg(subnet->getID());
708 .arg(query->getLabel())
709 .arg(subnet->toText());
713 DHCP4_SUBNET_SELECTION_FAILED)
714 .arg(query->getLabel());
736 }
catch (
const std::exception& e) {
762 uint32_t timeout = 1;
773 .arg(query->getRemoteAddr().toText())
774 .arg(query->getRemotePort())
775 .arg(query->getLocalAddr().toText())
776 .arg(query->getLocalPort())
777 .arg(query->getIface());
794 }
catch (
const std::exception& e) {
811 }
catch (
const std::exception& e) {
828 DHCP4_PACKET_DROP_0008)
829 .arg(query->getLabel());
850 static_cast<int64_t
>(1));
852 bool skip_unpack =
false;
856 if (HooksManager::calloutsPresent(
Hooks.hook_index_buffer4_receive_)) {
869 callout_handle->setArgument(
"query4", query);
872 HooksManager::callCallouts(
Hooks.hook_index_buffer4_receive_,
878 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
880 DHCP4_HOOK_BUFFER_RCVD_DROP)
881 .arg(query->getRemoteAddr().toText())
882 .arg(query->getLocalAddr().toText())
883 .arg(query->getIface());
891 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
893 DHCP4_HOOK_BUFFER_RCVD_SKIP)
894 .arg(query->getRemoteAddr().toText())
895 .arg(query->getLocalAddr().toText())
896 .arg(query->getIface());
900 callout_handle->getArgument(
"query4", query);
908 .arg(query->getRemoteAddr().toText())
909 .arg(query->getLocalAddr().toText())
910 .arg(query->getIface());
916 DHCP4_PACKET_OPTIONS_SKIPPED)
918 }
catch (
const std::exception& e) {
921 DHCP4_PACKET_DROP_0001)
922 .arg(query->getRemoteAddr().toText())
923 .arg(query->getLocalAddr().toText())
924 .arg(query->getIface())
929 static_cast<int64_t
>(1));
931 static_cast<int64_t
>(1));
952 static_cast<int64_t
>(1));
958 int type = query->getType();
960 .arg(query->getLabel())
961 .arg(query->getName())
963 .arg(query->getRemoteAddr())
964 .arg(query->getLocalAddr())
965 .arg(query->getIface());
967 .arg(query->getLabel())
968 .arg(query->toText());
971 if (HooksManager::calloutsPresent(
Hooks.hook_index_pkt4_receive_)) {
984 callout_handle->setArgument(
"query4", query);
987 HooksManager::callCallouts(
Hooks.hook_index_pkt4_receive_,
993 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
994 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
996 DHCP4_HOOK_PACKET_RCVD_SKIP)
997 .arg(query->getLabel());
1001 callout_handle->getArgument(
"query4", query);
1007 switch (query->getType()) {
1037 }
catch (
const std::exception& e) {
1047 DHCP4_PACKET_DROP_0007)
1048 .arg(query->getLabel())
1053 static_cast<int64_t
>(1));
1056 bool packet_park =
false;
1058 if (ctx && HooksManager::calloutsPresent(
Hooks.hook_index_leases4_committed_)) {
1070 callout_handle->setArgument(
"query4", query);
1073 if (ctx->new_lease_) {
1074 new_leases->push_back(ctx->new_lease_);
1076 callout_handle->setArgument(
"leases4", new_leases);
1079 if (ctx->old_lease_) {
1080 if ((!ctx->new_lease_) || (ctx->new_lease_->addr_ != ctx->old_lease_->addr_)) {
1081 deleted_leases->push_back(ctx->old_lease_);
1084 callout_handle->setArgument(
"deleted_leases4", deleted_leases);
1087 HooksManager::callCallouts(
Hooks.hook_index_leases4_committed_,
1090 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
1092 DHCP4_HOOK_LEASES4_COMMITTED_DROP)
1093 .arg(query->getLabel());
1096 }
else if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_PARK)
1097 && allow_packet_park) {
1110 DHCP4_HOOK_LEASES4_COMMITTED_PARK)
1111 .arg(query->getLabel());
1115 HooksManager::park(
"leases4_committed", query,
1116 [
this, callout_handle, query, rsp]()
mutable {
1139 bool skip_pack =
false;
1142 if (HooksManager::calloutsPresent(
Hooks.hook_index_pkt4_send_)) {
1155 callout_handle->setArgument(
"response4", rsp);
1158 callout_handle->setArgument(
"query4", query);
1161 HooksManager::callCallouts(
Hooks.hook_index_pkt4_send_,
1167 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
1168 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
1170 DHCP4_HOOK_PACKET_SEND_SKIP)
1171 .arg(query->getLabel());
1179 .arg(rsp->getLabel());
1181 }
catch (
const std::exception& e) {
1183 .arg(rsp->getLabel())
1201 if (HooksManager::calloutsPresent(
Hooks.hook_index_buffer4_send_)) {
1213 callout_handle->setArgument(
"response4", rsp);
1216 HooksManager::callCallouts(
Hooks.hook_index_buffer4_send_,
1222 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
1223 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
1225 DHCP4_HOOK_BUFFER_SEND_SKIP)
1226 .arg(rsp->getLabel());
1230 callout_handle->getArgument(
"response4", rsp);
1234 .arg(rsp->getLabel())
1235 .arg(rsp->getName())
1236 .arg(
static_cast<int>(rsp->getType()))
1237 .arg(rsp->getLocalAddr().isV4Zero() ?
"*" : rsp->getLocalAddr().toText())
1238 .arg(rsp->getLocalPort())
1239 .arg(rsp->getRemoteAddr())
1240 .arg(rsp->getRemotePort())
1241 .arg(rsp->getIface().empty() ?
"to be determined from routing" :
1245 DHCP4_RESPONSE_DATA)
1246 .arg(rsp->getLabel())
1247 .arg(rsp->getName())
1248 .arg(
static_cast<int>(rsp->getType()))
1249 .arg(rsp->toText());
1255 }
catch (
const std::exception& e) {
1257 .arg(rsp->getLabel())
1267 boost::shared_ptr<Option4AddrLst> generated =
1268 boost::dynamic_pointer_cast<Option4AddrLst>(srvid);
1274 if (addrs.size() != 1) {
1276 <<
"Expected to contain a single IPv4 address.");
1279 return (addrs[0].toText());
1297 if (local_addr.
isV4Bcast() || query->isDhcp4o6()) {
1299 local_addr = sock_info.
addr_;
1321 if (host && !host->getCfgOption4()->empty()) {
1322 co_list.push_back(host->getCfgOption4());
1329 addr = resp->getYiaddr();
1333 if (pool && !pool->getCfgOption()->empty()) {
1334 co_list.push_back(pool->getCfgOption());
1339 if (!subnet->getCfgOption()->empty()) {
1340 co_list.push_back(subnet->getCfgOption());
1345 subnet->getSharedNetwork(network);
1346 if (network && !network->getCfgOption()->empty()) {
1347 co_list.push_back(network->getCfgOption());
1353 cclass != classes.
cend(); ++cclass) {
1356 getClientClassDictionary()->findClass(*cclass);
1367 if (ccdef->getCfgOption()->empty()) {
1371 co_list.push_back(ccdef->getCfgOption());
1395 if (co_list.empty()) {
1401 std::vector<uint8_t> requested_opts;
1409 requested_opts = option_prl->getValues();
1412 for (CfgOptionList::const_iterator copts = co_list.begin();
1413 copts != co_list.end(); ++copts) {
1421 for (OptionContainerPersistIndex::const_iterator desc = range.first;
1422 desc != range.second; ++desc) {
1424 if (desc->option_) {
1425 uint8_t code =
static_cast<uint8_t
>(desc->option_->getType());
1426 requested_opts.push_back(code);
1433 for (std::vector<uint8_t>::const_iterator opt = requested_opts.begin();
1434 opt != requested_opts.end(); ++opt) {
1436 if (!resp->getOption(*opt)) {
1438 for (CfgOptionList::const_iterator copts = co_list.begin();
1439 copts != co_list.end(); ++copts) {
1443 resp->addOption(desc.
option_);
1466 if (co_list.empty()) {
1471 boost::shared_ptr<OptionVendor> vendor_req = boost::dynamic_pointer_cast<
1478 std::vector<uint8_t> requested_opts;
1484 boost::dynamic_pointer_cast<OptionUint8Array>(vendor_req->getOption(
DOCSIS3_V4_ORO));
1487 requested_opts = oro->getValues();
1490 for (CfgOptionList::const_iterator copts = co_list.begin();
1491 copts != co_list.end(); ++copts) {
1499 for (OptionContainerPersistIndex::const_iterator desc = range.first;
1500 desc != range.second; ++desc) {
1502 if (desc->option_) {
1503 uint8_t code =
static_cast<uint8_t
>(desc->option_->getType());
1504 requested_opts.push_back(code);
1510 if (requested_opts.empty()) {
1518 for (std::vector<uint8_t>::const_iterator code = requested_opts.begin();
1519 code != requested_opts.end(); ++code) {
1520 if (!vendor_rsp->getOption(*code)) {
1521 for (CfgOptionList::const_iterator copts = co_list.begin();
1522 copts != co_list.end(); ++copts) {
1525 vendor_rsp->addOption(desc.
option_);
1543 static const uint16_t required_options[] = {
1549 static size_t required_options_size =
1550 sizeof(required_options) /
sizeof(required_options[0]);
1560 if (co_list.empty()) {
1568 for (
int i = 0; i < required_options_size; ++i) {
1569 OptionPtr opt = resp->getOption(required_options[i]);
1572 for (CfgOptionList::const_iterator copts = co_list.begin();
1573 copts != co_list.end(); ++copts) {
1575 required_options[i]);
1577 resp->addOption(desc.
option_);
1597 processClientFqdnOption(ex);
1601 DHCP4_CLIENT_HOSTNAME_PROCESS)
1603 processHostnameOption(ex);
1628 .arg(fqdn->toText());
1644 !ex.
getContext()->currentHost()->getHostname().empty()) {
1669 .arg(fqdn_resp->toText());
1679 OptionStringPtr opt_hostname = boost::dynamic_pointer_cast<OptionString>
1685 .arg(opt_hostname->getValue());
1692 if (ctx->currentHost() && !ctx->currentHost()->getHostname().empty()) {
1700 bool should_send_hostname =
static_cast<bool>(opt_hostname);
1702 if (!should_send_hostname) {
1704 option_prl = boost::dynamic_pointer_cast<OptionUint8Array>
1709 const std::vector<uint8_t>&
1710 requested_opts = option_prl->getValues();
1711 if (std::find(requested_opts.begin(), requested_opts.end(),
1715 should_send_hostname =
true;
1723 if (should_send_hostname) {
1724 std::string hostname =
1725 d2_mgr.
qualifyName(ctx->currentHost()->getHostname(),
false);
1728 boost::algorithm::to_lower(hostname);
1731 DHCP4_RESERVED_HOSTNAME_ASSIGNED)
1754 if (!opt_hostname) {
1760 DHCP4_GENERATE_FQDN)
1774 .arg(opt_hostname->getValue());
1782 if (label_count == 0) {
1800 || label_count < 2) {
1814 ->getHostnameSanitizer();
1816 hostname = sanitizer->scrub(hostname);
1820 boost::algorithm::to_lower(hostname);
1822 if (label_count == 2) {
1839 .arg(opt_hostname_resp->getValue());
1848 "NULL lease specified when creating NameChangeRequest");
1850 }
else if (!old_lease || !lease->hasIdenticalFqdn(*old_lease)) {
1881 .arg(query->getLabel())
1882 .arg(query->getRemoteAddr().toText())
1883 .arg(query->getName());
1900 if (opt_requested_address) {
1901 hint = opt_requested_address->readAddress();
1903 }
else if (!query->getCiaddr().isV4Zero()) {
1904 hint = query->getCiaddr();
1916 bool fake_allocation = (query->getType() ==
DHCPDISCOVER);
1925 if (!fake_allocation && !opt_serverid && opt_requested_address) {
1928 .arg(query->getLabel())
1929 .arg(hint.toText());
1946 if (!leases_client_id.empty()) {
1952 for (
auto l = leases_client_id.begin(); l != leases_client_id.end(); ++l) {
1953 if ((*l)->subnet_id_ == s->getID()) {
1963 s = s->getNextSubnet(original_subnet, query->getClasses());
1971 if (!lease && hwaddr) {
1975 if (!leases_hwaddr.empty()) {
1980 for (
auto l = leases_hwaddr.begin(); l != leases_hwaddr.end(); ++l) {
1981 if ((*l)->subnet_id_ == s->getID()) {
1991 s = s->getNextSubnet(original_subnet, query->getClasses());
2000 bool authoritative = original_subnet->getAuthoritative();
2001 bool known_client = lease && lease->belongsToClient(hwaddr, client_id);
2002 if (!authoritative && !known_client) {
2004 DHCP4_NO_LEASE_INIT_REBOOT)
2005 .arg(query->getLabel())
2006 .arg(hint.toText());
2014 if ((known_client && (lease->addr_ != hint)) ||
2015 (!known_client && authoritative)) {
2017 DHCP4_PACKET_NAK_0002)
2018 .arg(query->getLabel())
2019 .arg(hint.toText());
2030 std::string hostname;
2031 bool fqdn_fwd =
false;
2032 bool fqdn_rev =
false;
2042 opt_hostname = boost::dynamic_pointer_cast<OptionString>
2046 hostname = opt_hostname->getValue();
2051 if (hostname ==
".") {
2062 ctx->requested_address_ = hint;
2063 ctx->fwd_dns_update_ = fqdn_fwd;
2064 ctx->rev_dns_update_ = fqdn_rev;
2065 ctx->hostname_ = hostname;
2066 ctx->fake_allocation_ = fake_allocation;
2067 ctx->callout_handle_ = callout_handle;
2073 if (subnet->getID() != ctx->subnet_->getID()) {
2075 subnet->getSharedNetwork(network);
2078 .arg(query->getLabel())
2079 .arg(subnet->toText())
2080 .arg(ctx->subnet_->toText())
2081 .arg(network->getName());
2083 subnet = ctx->subnet_;
2090 .arg(query->getLabel())
2091 .arg(lease->addr_.toText());
2097 if (!ctx->subnet_->getMatchClientId()) {
2099 .arg(ctx->query_->getLabel())
2100 .arg(ctx->subnet_->getID());
2103 resp->setYiaddr(lease->addr_);
2109 if (!fake_allocation) {
2114 resp->setCiaddr(query->getCiaddr());
2121 if (fqdn || opt_hostname) {
2122 bool should_update =
false;
2126 if (ctx->currentHost() && !ctx->currentHost()->getHostname().empty()) {
2130 static_cast<bool>(fqdn));
2131 should_update =
true;
2137 }
else if (lease->hostname_.empty()) {
2148 .arg(query->getLabel())
2149 .arg(lease->hostname_);
2151 should_update =
true;
2154 if (should_update) {
2160 if (!fake_allocation) {
2170 fqdn->setDomainName(lease->hostname_,
2172 }
else if (opt_hostname) {
2173 opt_hostname->setValue(lease->hostname_);
2178 .arg(query->getLabel())
2179 .arg(lease->hostname_)
2187 lease->valid_lft_));
2188 resp->addOption(opt);
2191 resp->addOption(getNetmaskOption(subnet));
2197 uint32_t timer_ceiling = lease->valid_lft_;
2198 if ((!subnet->getT2().unspecified()) &&
2199 (subnet->getT2() < timer_ceiling)) {
2203 resp->addOption(t2);
2206 timer_ceiling = subnet->getT2();
2211 if ((!subnet->getT1().unspecified()) &&
2212 (subnet->getT1() < timer_ceiling)) {
2216 resp->addOption(t1);
2225 .arg(query->getLabel());
2230 .arg(query->getLabel())
2239 DHCP4_PACKET_NAK_0003 : DHCP4_PACKET_NAK_0004)
2240 .arg(query->getLabel())
2241 .arg(query->getCiaddr().toText())
2242 .arg(opt_requested_address ?
2243 opt_requested_address->readAddress().toText() :
"(no address)");
2259 if (rai && rai->getOption(RAI_OPTION_RELAY_PORT)) {
2261 return (query->getRemotePort());
2286 ((!query->getCiaddr().isV4Zero()) ||
2287 (!query->isRelayed() && !query->getRemoteAddr().isV4Zero()))) ||
2288 ((query->getType() !=
DHCPINFORM) && !query->isRelayed())) {
2289 response->setRemotePort(DHCP4_CLIENT_PORT);
2294 response->setRemotePort(relay_port ? relay_port : DHCP4_SERVER_PORT);
2298 if (query->isRelayed() &&
2304 response->resetIndex();
2306 response->setIface(query->getIface());
2310 IOAddress local_addr = query->getLocalAddr();
2319 if (local_addr.
isV4Bcast() || query->isDhcp4o6()) {
2321 local_addr = sock_info.
addr_;
2331 response->setLocalAddr(local_addr);
2340 response->setIndex(query->getIndex());
2341 response->setIface(query->getIface());
2344 response->setLocalPort(DHCP4_SERVER_PORT);
2355 if (query->isDhcp4o6()) {
2356 response->setRemoteAddr(query->getRemoteAddr());
2368 if (!query->getCiaddr().isV4Zero()) {
2369 response->setRemoteAddr(query->getCiaddr());
2376 }
else if (query->isRelayed()) {
2377 response->setRemoteAddr(query->getGiaddr());
2378 response->setFlags(response->getFlags() | BOOTP_BROADCAST);
2383 response->setRemoteAddr(query->getRemoteAddr());
2390 if (query->isRelayed()) {
2399 query->getCiaddr().isV4Zero()) {
2400 response->setFlags(BOOTP_BROADCAST);
2402 response->setRemoteAddr(query->getGiaddr());
2406 }
else if (!query->getCiaddr().isV4Zero()) {
2407 response->setRemoteAddr(query->getCiaddr());
2412 }
else if (response->getType() ==
DHCPNAK) {
2416 }
else if (!response->getYiaddr().isV4Zero()) {
2431 response->setRemoteAddr(response ->getYiaddr());
2439 response->setRemoteAddr(query->getRemoteAddr());
2452 IOAddress subnet_next_server = subnet->getSiaddr();
2453 if (!subnet_next_server.
isV4Zero()) {
2454 response->setSiaddr(subnet_next_server);
2457 const string& sname = subnet->getSname();
2458 if (!sname.empty()) {
2464 response->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
2468 const string& filename = subnet->getFilename();
2469 if (!filename.empty()) {
2475 response->setFile(
reinterpret_cast<const uint8_t*
>(filename.c_str()),
2483 if (!classes.
empty()) {
2492 name != classes.
cend(); ++name) {
2503 IOAddress next_server = cl->getNextServer();
2505 response->setSiaddr(next_server);
2508 const string& sname = cl->getSname();
2509 if (!sname.empty()) {
2515 response->setSname(
reinterpret_cast<const uint8_t*
>(sname.c_str()),
2519 const string& filename = cl->getFilename();
2520 if (!filename.empty()) {
2526 response->setFile(
reinterpret_cast<const uint8_t*
>(filename.c_str()),
2538 Dhcpv4Srv::getNetmaskOption(
const Subnet4Ptr& subnet) {
2696 .arg(release->getLabel())
2697 .arg(release->getCiaddr().toText());
2701 if (!lease->belongsToClient(release->getHWAddr(), client_id)) {
2703 .arg(release->getLabel())
2704 .arg(release->getCiaddr().toText());
2711 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease4_release_)) {
2724 callout_handle->setArgument(
"query4", release);
2727 callout_handle->setArgument(
"lease4", lease);
2730 HooksManager::callCallouts(
Hooks.hook_index_lease4_release_,
2736 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
2737 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
2740 DHCP4_HOOK_LEASE4_RELEASE_SKIP)
2741 .arg(release->getLabel());
2753 context->old_lease_ = lease;
2757 .arg(release->getLabel())
2758 .arg(lease->addr_.toText());
2761 StatsMgr::instance().addValue(
2762 StatsMgr::generateName(
"subnet", lease->subnet_id_,
"assigned-addresses"),
2763 static_cast<int64_t
>(-1));
2771 .arg(release->getLabel())
2772 .arg(lease->addr_.toText());
2777 .arg(release->getLabel())
2778 .arg(release->getCiaddr())
2796 if (!opt_requested_address) {
2799 "in DHCPDECLINE sent from " << decline->getLabel());
2801 IOAddress addr(opt_requested_address->readAddress());
2819 .arg(addr.
toText()).arg(decline->getLabel());
2827 client_id.reset(
new ClientId(opt_clientid->getData()));
2831 if (!lease->belongsToClient(decline->getHWAddr(), client_id)) {
2834 string client_hw = decline->getHWAddr() ?
2835 decline->getHWAddr()->toText(
false) :
"(none)";
2836 string lease_hw = lease->hwaddr_ ?
2837 lease->hwaddr_->toText(
false) :
"(none)";
2840 string client_id_txt = client_id ? client_id->toText() :
"(none)";
2841 string lease_id_txt = lease->client_id_ ?
2842 lease->client_id_->toText() :
"(none)";
2846 .arg(addr.
toText()).arg(decline->getLabel())
2847 .arg(client_hw).arg(lease_hw).arg(client_id_txt).arg(lease_id_txt);
2864 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease4_decline_)) {
2877 callout_handle->setArgument(
"lease4", lease);
2878 callout_handle->setArgument(
"query4", decline);
2881 HooksManager::callCallouts(
Hooks.hook_index_lease4_decline_,
2886 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
2887 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
2889 .arg(decline->getLabel()).arg(lease->addr_.toText());
2901 StatsMgr::instance().addValue(
2902 StatsMgr::generateName(
"subnet", lease->subnet_id_,
"declined-addresses"),
2903 static_cast<int64_t
>(1));
2906 StatsMgr::instance().addValue(
"declined-addresses",
static_cast<int64_t
>(1));
2927 context->new_lease_ = lease;
2930 .arg(decline->getLabel()).arg(lease->valid_lft_);
2966 if (ack->getRemoteAddr() != inform->getGiaddr()) {
2968 .arg(inform->getLabel())
2969 .arg(ack->getRemoteAddr())
2970 .arg(ack->getIface());
2993 .arg(query->getLabel())
2994 .arg(query->getIface());
3002 .arg(query->getLabel())
3003 .arg(query->getIface());
3013 if (pkt->isRelayed()) {
3018 if (pkt->isDhcp4o6()) {
3027 if (pkt->getRemoteAddr().isV4Zero() &&
3028 pkt->getCiaddr().isV4Zero()) {
3039 bool result = (!pkt->getLocalAddr().isV4Bcast() ||
3054 type = query->getType();
3058 .arg(query->getLabel())
3059 .arg(query->getIface());
3083 .arg(query->getLabel());
3090 .arg(query->getLabel())
3095 .arg(query->getLabel())
3122 boost::dynamic_pointer_cast<OptionCustom>(option);
3125 if (!option_custom) {
3133 if (option_custom->getDataFieldsNum() != 1) {
3139 IOAddress server_id = option_custom->readAddress();
3140 if (!server_id.
isV4()) {
3181 if (cfg_subnets->hasSubnetWithServerId(server_id)) {
3188 if (cfg_networks->hasNetworkWithServerId(server_id)) {
3195 OptionCustomPtr opt_server_id = boost::dynamic_pointer_cast<OptionCustom>
3198 return (opt_server_id && (opt_server_id->readAddress() == server_id));
3209 << query->getName());
3216 " received in message "
3217 << query->getName());
3227 if (query->getHWAddr() && !query->getHWAddr()->hwaddr_.empty()) {
3236 if (!client_id || client_id->len() == client_id->getHeaderLen()) {
3238 " provided in message "
3239 << query->getName());
3245 boost::shared_ptr<OptionString> vendor_class =
3248 if (!vendor_class) {
3257 pkt->addClass(
"ALL");
3271 for (ClientClassDefList::const_iterator it = defs_ptr->cbegin();
3272 it != defs_ptr->cend(); ++it) {
3280 if ((*it)->getRequired()) {
3284 if ((*it)->getDependOnKnown() != depend_on_known) {
3293 .arg((*it)->getName())
3296 pkt->addClass((*it)->getName());
3299 .arg((*it)->getName())
3304 .arg((*it)->getName())
3308 .arg((*it)->getName())
3309 .arg(
"get exception?");
3323 subnet->getSharedNetwork(network);
3325 const ClientClasses& to_add = network->getRequiredClasses();
3327 cclass != to_add.
cend(); ++cclass) {
3335 cclass != to_add.
cend(); ++cclass) {
3343 addr = resp->getYiaddr();
3350 cclass != to_add.
cend(); ++cclass) {
3364 cclass != classes.
cend(); ++cclass) {
3387 query->addClass(*cclass);
3400 .arg(
"get exception?");
3409 BOOST_FOREACH(
const uint16_t& code, query->getDeferredOptions()) {
3414 cclass != classes.
cend(); ++cclass) {
3418 getClientClassDictionary()->findClass(*cclass);
3424 if (!ccdef->getCfgOptionDef()) {
3455 while (query->delOption(code)) {
3459 opt = def->optionFactory(
Option::V4, code, buf.cbegin(), buf.cend());
3460 query->addOption(opt);
3490 arg(result).arg((ncr ? ncr->toText() :
" NULL "));
3502 std::stringstream tmp;
3506 tmp << endl << EXTENDED_VERSION << endl;
3507 tmp <<
"linked with:" << endl;
3508 tmp << Logger::getVersion() << endl;
3509 tmp << CryptoLink::getVersion() << endl;
3510 tmp <<
"database:" << endl;
3532 string stat_name =
"pkt4-unknown-received";
3534 switch (query->getType()) {
3536 stat_name =
"pkt4-discover-received";
3540 stat_name =
"pkt4-offer-received";
3543 stat_name =
"pkt4-request-received";
3547 stat_name =
"pkt4-ack-received";
3551 stat_name =
"pkt4-nak-received";
3554 stat_name =
"pkt4-release-received";
3557 stat_name =
"pkt4-decline-received";
3560 stat_name =
"pkt4-inform-received";
3574 static_cast<int64_t
>(1));
3580 static_cast<int64_t
>(1));
3584 switch (response->getType()) {
3586 stat_name =
"pkt4-offer-sent";
3589 stat_name =
"pkt4-ack-sent";
3592 stat_name =
"pkt4-nak-sent";
3600 static_cast<int64_t
>(1));
3604 return (
Hooks.hook_index_buffer4_receive_);
3608 return (
Hooks.hook_index_pkt4_receive_);
3612 return (
Hooks.hook_index_subnet4_select_);
3616 return (
Hooks.hook_index_lease4_release_);
3620 return (
Hooks.hook_index_pkt4_send_);
3624 return (
Hooks.hook_index_buffer4_send_);
3628 return (
Hooks.hook_index_lease4_decline_);
3636 HooksManager::clearParkingLots();