8 #include <kea_version.h>
42 #include <eval/eval_messages.h>
68 #include <boost/bind.hpp>
69 #include <boost/foreach.hpp>
70 #include <boost/tokenizer.hpp>
71 #include <boost/algorithm/string/erase.hpp>
72 #include <boost/algorithm/string/join.hpp>
73 #include <boost/algorithm/string/split.hpp>
97 int hook_index_buffer6_receive_;
98 int hook_index_pkt6_receive_;
99 int hook_index_subnet6_select_;
100 int hook_index_leases6_committed_;
101 int hook_index_lease6_release_;
102 int hook_index_pkt6_send_;
103 int hook_index_buffer6_send_;
104 int hook_index_lease6_decline_;
105 int hook_index_host6_identifier_;
109 hook_index_buffer6_receive_ = HooksManager::registerHook(
"buffer6_receive");
110 hook_index_pkt6_receive_ = HooksManager::registerHook(
"pkt6_receive");
111 hook_index_subnet6_select_ = HooksManager::registerHook(
"subnet6_select");
112 hook_index_leases6_committed_ = HooksManager::registerHook(
"leases6_committed");
113 hook_index_lease6_release_ = HooksManager::registerHook(
"lease6_release");
114 hook_index_pkt6_send_ = HooksManager::registerHook(
"pkt6_send");
115 hook_index_buffer6_send_ = HooksManager::registerHook(
"buffer6_send");
116 hook_index_lease6_decline_ = HooksManager::registerHook(
"lease6_decline");
117 hook_index_host6_identifier_ = HooksManager::registerHook(
"host6_identifier");
139 createStatusCode(
const Pkt6& pkt,
const uint16_t status_code,
140 const std::string& status_message) {
145 .arg(option_status->dataToText());
146 return (option_status);
164 createStatusCode(
const Pkt6& pkt,
const Option6IA& ia,
const uint16_t status_code,
165 const std::string& status_message) {
171 .arg(option_status->dataToText());
172 return (option_status);
180 const std::string Dhcpv6Srv::VENDOR_CLASS_PREFIX(
"VENDOR_CLASS_");
182 Dhcpv6Srv::Dhcpv6Srv(uint16_t port)
183 : io_service_(new
IOService()), port_(port), serverid_(), shutdown_(true),
184 alloc_engine_(), name_change_reqs_(),
212 }
catch (
const std::exception &e) {
225 }
catch(
const std::exception& ex) {
232 }
catch(
const std::exception& ex) {
242 HooksManager::getHooksManager().unloadLibraries();
268 if (
getServerID()->getData() != server_id->getData()){
270 DHCP6_PACKET_DROP_SERVERID_MISMATCH)
271 .arg(pkt->getLabel())
283 switch (pkt->getType()) {
288 if (pkt->relay_info_.empty() && !pkt->getLocalAddr().isV6Multicast()) {
290 .arg(pkt->getLabel())
291 .arg(pkt->getName());
307 ctx.
duid_ = pkt->getClientId(),
327 cfg->getIdentifierTypes()) {
344 if (HooksManager::calloutsPresent(
Hooks.hook_index_host6_identifier_)) {
348 std::vector<uint8_t> id;
357 callout_handle->setArgument(
"query6", pkt);
358 callout_handle->setArgument(
"id_type", type);
359 callout_handle->setArgument(
"id_value",
id);
362 HooksManager::callCallouts(
Hooks.hook_index_host6_identifier_,
365 callout_handle->getArgument(
"id_type", type);
366 callout_handle->getArgument(
"id_value",
id);
368 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_CONTINUE) &&
388 if (!ctx.
hosts_.empty()) {
389 pkt->addClass(
"KNOWN");
391 .arg(pkt->getLabel())
394 pkt->addClass(
"UNKNOWN");
396 .arg(pkt->getLabel())
409 }
catch (
const std::exception& e) {
433 uint32_t timeout = 1;
444 .arg(query->getRemoteAddr().toText())
445 .arg(query->getRemotePort())
446 .arg(query->getLocalAddr().toText())
447 .arg(query->getLocalPort())
448 .arg(query->getIface());
454 StatsMgr::instance().addValue(
"pkt6-received",
static_cast<int64_t
>(1));
472 }
catch (
const std::exception& e) {
488 }
catch (
const std::exception& e) {
503 DHCP6_PACKET_DROP_DHCP_DISABLED)
504 .arg(query->getLabel());
520 bool skip_unpack =
false;
524 if (HooksManager::calloutsPresent(
Hooks.hook_index_buffer6_receive_)) {
537 callout_handle->setArgument(
"query6", query);
540 HooksManager::callCallouts(
Hooks.hook_index_buffer6_receive_, *callout_handle);
546 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
548 .arg(query->getRemoteAddr().toText())
549 .arg(query->getLocalAddr().toText())
550 .arg(query->getIface());
557 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
559 .arg(query->getRemoteAddr().toText())
560 .arg(query->getLocalAddr().toText())
561 .arg(query->getIface());
564 StatsMgr::instance().addValue(
"pkt6-receive-drop",
565 static_cast<int64_t
>(1));
569 callout_handle->getArgument(
"query6", query);
577 .arg(query->getRemoteAddr().toText())
578 .arg(query->getLocalAddr().toText())
579 .arg(query->getIface());
585 DHCP6_PACKET_OPTIONS_SKIPPED)
587 }
catch (
const std::exception &e) {
590 DHCP6_PACKET_DROP_PARSE_FAIL)
591 .arg(query->getRemoteAddr().toText())
592 .arg(query->getLocalAddr().toText())
593 .arg(query->getIface())
597 StatsMgr::instance().addValue(
"pkt6-parse-failed",
598 static_cast<int64_t
>(1));
599 StatsMgr::instance().addValue(
"pkt6-receive-drop",
600 static_cast<int64_t
>(1));
606 processStatsReceived(query);
613 StatsMgr::instance().addValue(
"pkt6-receive-drop",
static_cast<int64_t
>(1));
623 StatsMgr::instance().addValue(
"pkt6-receive-drop",
static_cast<int64_t
>(1));
631 .arg(query->getLabel())
632 .arg(query->getName())
633 .arg(
static_cast<int>(query->getType()))
634 .arg(query->getRemoteAddr())
635 .arg(query->getLocalAddr())
636 .arg(query->getIface());
638 .arg(query->getLabel())
639 .arg(query->toText());
644 if (HooksManager::calloutsPresent(
Hooks.hook_index_pkt6_receive_)) {
657 callout_handle->setArgument(
"query6", query);
660 HooksManager::callCallouts(
Hooks.hook_index_pkt6_receive_, *callout_handle);
665 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
666 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
668 .arg(query->getLabel());
670 StatsMgr::instance().addValue(
"pkt6-receive-drop",
671 static_cast<int64_t
>(1));
675 callout_handle->getArgument(
"query6", query);
703 switch (query->getType()) {
740 }
catch (
const std::exception& e) {
750 .arg(query->getName())
751 .arg(query->getRemoteAddr().toText())
755 StatsMgr::instance().addValue(
"pkt6-receive-drop",
static_cast<int64_t
>(1));
774 rsp->setRemoteAddr(query->getRemoteAddr());
775 rsp->setLocalAddr(query->getLocalAddr());
777 if (rsp->relay_info_.empty()) {
779 rsp->setRemotePort(DHCP6_CLIENT_PORT);
783 rsp->setRemotePort(relay_port ? relay_port : DHCP6_SERVER_PORT);
786 rsp->setLocalPort(DHCP6_SERVER_PORT);
787 rsp->setIndex(query->getIndex());
788 rsp->setIface(query->getIface());
790 bool packet_park =
false;
794 HooksManager::calloutsPresent(
Hooks.hook_index_leases6_committed_)) {
806 callout_handle->setArgument(
"query6", query);
813 callout_handle->setArgument(
"leases6", new_leases);
818 for (
auto const iac : ctx.
ias_) {
819 if (!iac.old_leases_.empty()) {
820 for (
auto old_lease : iac.old_leases_) {
822 deleted_leases->push_back(old_lease);
827 if ((new_lease->addr_ == old_lease->addr_) &&
828 (new_lease->prefixlen_ == old_lease->prefixlen_)) {
834 deleted_leases->push_back(old_lease);
839 callout_handle->setArgument(
"deleted_leases6", deleted_leases);
842 HooksManager::callCallouts(
Hooks.hook_index_leases6_committed_,
845 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
847 DHCP6_HOOK_LEASES6_COMMITTED_DROP)
848 .arg(query->getLabel());
851 }
else if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_PARK) {
864 DHCP6_HOOK_LEASES6_COMMITTED_PARK)
865 .arg(query->getLabel());
869 HooksManager::park(
"leases6_committed", query,
870 [
this, callout_handle, query, rsp]()
mutable {
893 bool skip_pack =
false;
899 if (HooksManager::calloutsPresent(
Hooks.hook_index_pkt6_send_)) {
911 callout_handle->setArgument(
"query6", query);
914 callout_handle->setArgument(
"response6", rsp);
917 HooksManager::callCallouts(
Hooks.hook_index_pkt6_send_, *callout_handle);
924 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
926 .arg(rsp->getLabel());
931 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
933 .arg(rsp->getLabel());
942 }
catch (
const std::exception& e) {
962 if (HooksManager::calloutsPresent(
Hooks.hook_index_buffer6_send_)) {
974 callout_handle->setArgument(
"response6", rsp);
977 HooksManager::callCallouts(
Hooks.hook_index_buffer6_send_,
983 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
984 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
986 DHCP6_HOOK_BUFFER_SEND_SKIP)
987 .arg(rsp->getLabel());
991 callout_handle->getArgument(
"response6", rsp);
995 .arg(
static_cast<int>(rsp->getType())).arg(rsp->toText());
1002 }
catch (
const std::exception& e) {
1018 tmp << hex << setw(2) << setfill('0') << static_cast<uint16_t>(*it);
1032 answer->addOption(clientid);
1037 if (!question->relay_info_.empty()) {
1038 answer->copyRelayInfo(question);
1056 co_list.push_back(ctx.
currentHost()->getCfgOption6());
1066 resource.first,
false);
1067 if (pool && !pool->getCfgOption()->empty()) {
1068 co_list.push_back(pool->getCfgOption());
1075 if (!ctx.
subnet_->getCfgOption()->empty()) {
1076 co_list.push_back(ctx.
subnet_->getCfgOption());
1081 ctx.
subnet_->getSharedNetwork(network);
1082 if (network && !network->getCfgOption()->empty()) {
1083 co_list.push_back(network->getCfgOption());
1090 cclass != classes.
cend(); ++cclass) {
1093 getClientClassDictionary()->findClass(*cclass);
1098 .arg(question->getLabel())
1105 if (ccdef->getCfgOption()->empty()) {
1110 co_list.push_back(ccdef->getCfgOption());
1124 if (co_list.empty()) {
1128 std::vector<uint16_t> requested_opts;
1132 boost::shared_ptr<OptionIntArray<uint16_t> > option_oro =
1133 boost::dynamic_pointer_cast<OptionIntArray<uint16_t> >
1134 (question->getOption(
D6O_ORO));
1138 requested_opts = option_oro->getValues();
1141 for (CfgOptionList::const_iterator copts = co_list.begin();
1142 copts != co_list.end(); ++copts) {
1150 for (OptionContainerPersistIndex::const_iterator desc = range.first;
1151 desc != range.second; ++desc) {
1153 requested_opts.push_back(desc->option_->getType());
1157 BOOST_FOREACH(uint16_t opt, requested_opts) {
1159 for (CfgOptionList::const_iterator copts = co_list.begin();
1160 copts != co_list.end(); ++copts) {
1164 answer->addOption(desc.
option_);
1187 boost::shared_ptr<OptionVendor> vendor_req =
1188 boost::dynamic_pointer_cast<OptionVendor>(question->getOption(
D6O_VENDOR_OPTS));
1189 if (!vendor_req || co_list.empty()) {
1193 uint32_t vendor_id = vendor_req->getVendorId();
1194 std::vector<uint16_t> requested_opts;
1199 boost::shared_ptr<OptionUint16Array> oro =
1200 boost::dynamic_pointer_cast<OptionUint16Array>(vendor_req->getOption(
DOCSIS3_V6_ORO));
1202 requested_opts = oro->getValues();
1205 for (CfgOptionList::const_iterator copts = co_list.begin();
1206 copts != co_list.end(); ++copts) {
1214 for (OptionContainerPersistIndex::const_iterator desc = range.first;
1215 desc != range.second; ++desc) {
1217 requested_opts.push_back(desc->option_->getType());
1222 if (requested_opts.empty()) {
1231 BOOST_FOREACH(uint16_t opt, requested_opts) {
1232 for (CfgOptionList::const_iterator copts = co_list.begin();
1233 copts != co_list.end(); ++copts) {
1236 vendor_rsp->addOption(desc.
option_);
1244 answer->addOption(vendor_rsp);
1251 switch (pkt->getType()) {
1272 DHCP6_UNKNOWN_MSG_RECEIVED)
1273 .arg(
static_cast<int>(pkt->getType()))
1274 .arg(pkt->getIface());
1279 .arg(pkt->getName())
1280 .arg(pkt->getRemoteAddr().toText())
1286 StatsMgr::instance().addValue(
"pkt6-receive-drop",
static_cast<int64_t
>(1));
1296 if (client_ids.size() != 1) {
1298 << pkt->getName() <<
", but " << client_ids.size()
1305 if (client_ids.size() > 1) {
1307 <<
") client-id options received in " << pkt->getName());
1309 if (!client_ids.empty()) {
1322 if (!server_ids.empty()) {
1324 << server_ids.size() <<
" received in " << pkt->getName());
1329 if (server_ids.size() != 1) {
1331 << server_ids.size() <<
"), exactly 1 expected in message "
1338 if (server_ids.size() > 1) {
1340 <<
") server-id options received in " << pkt->getName());
1342 if (!server_ids.empty()) {
1355 uint16_t len = opt->len() - opt->getHeaderLen();
1358 << len <<
" byte(s) only");
1367 getCfgSubnets6()->selectSubnet(selector);
1370 if (HooksManager::calloutsPresent(
Hooks.hook_index_subnet6_select_)) {
1383 callout_handle->setArgument(
"query6", question);
1384 callout_handle->setArgument(
"subnet6", subnet);
1389 callout_handle->setArgument(
"subnet6collection",
1391 getCfgSubnets6()->getAll());
1394 HooksManager::callCallouts(
Hooks.hook_index_subnet6_select_, *callout_handle);
1400 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
1402 .arg(question->getLabel());
1408 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
1410 .arg(question->getLabel());
1416 callout_handle->getArgument(
"subnet6", subnet);
1422 .arg(question->getLabel())
1423 .arg(subnet->getID());
1427 .arg(question->getLabel())
1428 .arg(subnet->toText());
1432 .arg(question->getLabel());
1457 for (OptionCollection::iterator opt = question->options_.begin();
1458 opt != question->options_.end(); ++opt) {
1459 switch (opt->second->getType()) {
1462 boost::dynamic_pointer_cast<
1465 answer->addOption(answer_opt);
1471 boost::dynamic_pointer_cast<
1474 answer->addOption(answer_opt);
1484 if (ctx.
subnet_ && subnet && (subnet->getID() != ctx.
subnet_->getID())) {
1486 subnet->getSharedNetwork(network);
1489 .arg(question->getLabel())
1490 .arg(subnet->toText())
1492 .arg(network->getName());
1520 .arg(question->getLabel());
1533 .arg(question->getLabel())
1534 .arg(fqdn->toText());
1559 ctx.
hostname_ = fqdn_resp->getDomainName();
1566 .arg(question->getLabel())
1567 .arg(fqdn_resp->toText());
1568 answer->addOption(fqdn_resp);
1584 <<
" encapsulating server's message must not be"
1585 <<
" NULL when creating DNS NameChangeRequest");
1598 bool do_fwd =
false;
1599 bool do_rev =
false;
1602 if (!do_fwd && !do_rev) {
1615 "client identifier is required when creating a new"
1616 " DNS NameChangeRequest");
1623 opt_fqdn->packDomainName(name_buf);
1624 const uint8_t* name_data =
static_cast<const uint8_t*
>(name_buf.
getData());
1627 std::vector<uint8_t> buf_vec(name_data, name_data + name_buf.
getLength());
1634 for (OptionCollection::const_iterator answer_ia =
1635 answer_ias.begin(); answer_ia != answer_ias.end(); ++answer_ia) {
1650 bool extended_only =
false;
1653 if ((*l)->addr_ == iaaddr->getAddress()) {
1654 if ((*l)->hostname_ == opt_fqdn->getDomainName() &&
1655 (*l)->fqdn_fwd_ == do_fwd && (*l)->fqdn_rev_ == do_rev) {
1656 extended_only =
true;
1662 if (extended_only) {
1673 opt_fqdn->getDomainName(),
1674 iaaddr->getAddress().toText(),
1675 dhcid, 0, iaaddr->getValid()));
1678 DHCP6_DDNS_CREATE_ADD_NAME_CHANGE_REQUEST).arg(ncr->toText());
1694 getMACSources().get();
1696 for (CfgMACSources::const_iterator it = mac_sources.begin();
1697 it != mac_sources.end(); ++it) {
1698 hwaddr = pkt->getMAC(*it);
1709 boost::shared_ptr<Option6IA> ia) {
1715 boost::dynamic_pointer_cast<Option6IAAddr>(ia->getOption(
D6O_IAADDR));
1718 hint = hint_opt->getAddress();
1722 .arg(query->getLabel())
1724 .arg(hint_opt ? hint.
toText() :
"(no hint)");
1743 "Server could not select subnet for"
1749 bool do_fwd =
false;
1750 bool do_rev =
false;
1776 if (!leases.empty()) {
1777 lease = *leases.begin();
1789 .arg(query->getLabel())
1790 .arg(lease->addr_.toText())
1791 .arg(ia->getIAID());
1793 .arg(query->getLabel())
1795 .arg(lease->toText());
1797 ia_rsp->setT1(subnet->getT1());
1798 ia_rsp->setT2(subnet->getT2());
1801 lease->preferred_lft_,
1802 lease->valid_lft_));
1803 ia_rsp->addOption(addr);
1815 DHCP6_LEASE_ADVERT_FAIL : DHCP6_LEASE_ALLOC_FAIL)
1816 .arg(query->getLabel())
1817 .arg(ia->getIAID());
1819 ia_rsp->addOption(createStatusCode(*query, *ia_rsp,
1821 "Sorry, no address could be"
1830 boost::shared_ptr<Option6IA> ia) {
1837 boost::dynamic_pointer_cast<Option6IAPrefix>(ia->getOption(
D6O_IAPREFIX));
1840 hint = hint_opt->getAddress();
1844 .arg(query->getLabel())
1846 .arg(hint_opt ? hint.
toText() :
"(no hint)");
1864 "Sorry, no subnet available."));
1880 if (!leases.empty()) {
1882 ia_rsp->setT1(subnet->getT1());
1883 ia_rsp->setT2(subnet->getT2());
1885 const bool pd_exclude_requested = requestedInORO(query,
D6O_PD_EXCLUDE);
1887 for (Lease6Collection::iterator l = leases.begin();
1888 l != leases.end(); ++l) {
1893 DHCP6_PD_LEASE_ADVERT : DHCP6_PD_LEASE_ALLOC)
1894 .arg(query->getLabel())
1895 .arg((*l)->addr_.toText())
1896 .arg(
static_cast<int>((*l)->prefixlen_))
1897 .arg(ia->getIAID());
1899 boost::shared_ptr<Option6IAPrefix>
1901 (*l)->prefixlen_, (*l)->preferred_lft_,
1903 ia_rsp->addOption(addr);
1905 if (pd_exclude_requested) {
1908 Pool6Ptr pool = boost::dynamic_pointer_cast<
1912 if (pd_exclude_option) {
1913 addr->addOption(pd_exclude_option);
1929 DHCP6_PD_LEASE_ADVERT_FAIL : DHCP6_PD_LEASE_ALLOC_FAIL)
1930 .arg(query->getLabel())
1931 .arg(ia->getIAID());
1933 ia_rsp->addOption(createStatusCode(*query, *ia_rsp,
1935 "Sorry, no prefixes could"
1944 boost::shared_ptr<Option6IA> ia) {
1947 .arg(query->getLabel())
1948 .arg(ia->getIAID());
1967 "Sorry, no known leases for this duid/iaid."));
1972 ia_rsp->setT1(subnet->getT1());
1973 ia_rsp->setT2(subnet->getT2());
1976 bool do_fwd =
false;
1977 bool do_rev =
false;
1997 for (OptionCollection::const_iterator it = addrs.begin();
1998 it != addrs.end(); ++it) {
2002 Option6IAAddrPtr iaaddr = boost::dynamic_pointer_cast<Option6IAAddr>(it->second);
2028 for (Lease6Collection::const_iterator l = leases.begin(); l != leases.end(); ++l) {
2030 (*l)->addr_, (*l)->preferred_lft_, (*l)->valid_lft_));
2031 ia_rsp->addOption(iaaddr);
2033 .arg(query->getLabel())
2034 .arg((*l)->addr_.toText())
2035 .arg(ia_rsp->getIAID());
2039 hints.erase(std::remove(hints.begin(), hints.end(), hint_type),
2050 if (
equalValues(query->getClientId(), (*l)->duid_)) {
2052 (*l)->addr_, 0, 0));
2053 ia_rsp->addOption(iaaddr);
2058 hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end());
2062 if (((*l)->hostname_ != ctx.
hostname_) || ((*l)->fqdn_fwd_ != do_fwd) ||
2063 ((*l)->fqdn_rev_ != do_rev)) {
2065 DHCP6_DDNS_LEASE_RENEW_FQDN_CHANGE)
2066 .arg(query->getLabel())
2067 .arg((*l)->toText())
2069 .arg(do_rev ?
"true" :
"false")
2070 .arg(do_fwd ?
"true" :
"false");
2078 for (AllocEngine::HintContainer::const_iterator hint = hints.begin();
2079 hint != hints.end(); ++hint) {
2081 hint->first, 0, 0));
2082 ia_rsp->addOption(iaaddr);
2086 if (leases.empty()) {
2090 ia_rsp->addOption(createStatusCode(*query, *ia_rsp,
2092 "Sorry, no addresses could be"
2093 " assigned at this time."));
2102 boost::shared_ptr<Option6IA> ia) {
2105 .arg(query->getLabel())
2106 .arg(ia->getIAID());
2123 "Sorry, no known PD leases"
2124 " for this duid/iaid."));
2144 " client sending Rebind to extend lifetime of the"
2145 " prefix (DUID=" << duid->toText() <<
", IAID="
2146 << ia->getIAID() <<
")");
2151 ia_rsp->setT1(subnet->getT1());
2152 ia_rsp->setT2(subnet->getT2());
2162 for (OptionCollection::const_iterator it = addrs.begin();
2163 it != addrs.end(); ++it) {
2197 const bool pd_exclude_requested = requestedInORO(query,
D6O_PD_EXCLUDE);
2200 for (Lease6Collection::const_iterator l = leases.begin(); l != leases.end(); ++l) {
2203 (*l)->addr_, (*l)->prefixlen_,
2204 (*l)->preferred_lft_, (*l)->valid_lft_));
2205 ia_rsp->addOption(prf);
2208 if (pd_exclude_requested) {
2211 Pool6Ptr pool = boost::dynamic_pointer_cast<
2216 if (pd_exclude_option) {
2217 prf->addOption(pd_exclude_option);
2224 .arg(query->getLabel())
2225 .arg((*l)->addr_.toText())
2226 .arg(
static_cast<int>((*l)->prefixlen_))
2227 .arg(ia->getIAID());
2231 hints.erase(std::remove(hints.begin(), hints.end(), hint_type),
2242 if (
equalValues(query->getClientId(), (*l)->duid_)) {
2244 (*l)->prefixlen_, 0, 0));
2245 ia_rsp->addOption(prefix);
2250 hints.erase(std::remove(hints.begin(), hints.end(), hint_type), hints.end());
2255 for (AllocEngine::HintContainer::const_iterator prefix = hints.begin();
2256 prefix != hints.end(); ++prefix) {
2261 if (!prefix->first.isV6Zero()) {
2263 prefix->second, 0, 0));
2264 ia_rsp->addOption(prefix_opt);
2269 if (leases.empty()) {
2273 ia_rsp->addOption(createStatusCode(*query, *ia_rsp,
2275 "Sorry, no prefixes could be"
2276 " assigned at this time."));
2294 for (OptionCollection::iterator opt = query->options_.begin();
2295 opt != query->options_.end(); ++opt) {
2296 switch (opt->second->getType()) {
2299 boost::dynamic_pointer_cast<
2302 reply->addOption(answer_opt);
2309 boost::dynamic_pointer_cast<
2312 reply->addOption(answer_opt);
2343 for (OptionCollection::iterator opt = release->options_.begin();
2344 opt != release->options_.end(); ++opt) {
2346 switch (opt->second->getType()) {
2349 boost::dynamic_pointer_cast<Option6IA>(opt->second),
2352 reply->addOption(answer_opt);
2358 boost::dynamic_pointer_cast<Option6IA>(opt->second),
2361 reply->addOption(answer_opt);
2378 reply->addOption(createStatusCode(*release, general_status,
2379 "Summary status for all processed IA_NAs"));
2384 int& general_status, boost::shared_ptr<Option6IA> ia,
2388 .arg(query->getLabel())
2389 .arg(ia->getIAID());
2406 if (!release_addr) {
2408 "You did not include an address in your RELEASE"));
2414 release_addr->getAddress());
2421 "Sorry, no known leases for this duid/iaid, can't release."));
2427 if (!lease->duid_) {
2433 .arg(query->getLabel())
2434 .arg(release_addr->getAddress().toText());
2438 "Database consistency check failed when trying to RELEASE"));
2442 if (*duid != *(lease->duid_)) {
2446 .arg(query->getLabel())
2447 .arg(release_addr->getAddress().toText())
2448 .arg(lease->duid_->toText());
2452 "This address does not belong to you, you can't release it"));
2456 if (ia->getIAID() != lease->iaid_) {
2459 .arg(query->getLabel())
2460 .arg(release_addr->getAddress().toText())
2462 .arg(ia->getIAID());
2464 "This is your address, but you used wrong IAID"));
2474 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease6_release_)) {
2487 callout_handle->deleteAllArguments();
2490 callout_handle->setArgument(
"query6", query);
2493 callout_handle->setArgument(
"lease6", lease);
2496 HooksManager::callCallouts(
Hooks.hook_index_lease6_release_, *callout_handle);
2501 if ((callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) ||
2502 (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP)) {
2505 .arg(query->getLabel());
2510 bool success =
false;
2521 "Server failed to release a lease"));
2524 .arg(query->getLabel())
2525 .arg(lease->addr_.toText())
2534 .arg(query->getLabel())
2535 .arg(lease->addr_.toText())
2538 ia_rsp->addOption(createStatusCode(*query, *ia_rsp,
STATUS_Success,
2539 "Lease released. Thank you, please come again."));
2542 StatsMgr::instance().addValue(
2543 StatsMgr::generateName(
"subnet", lease->subnet_id_,
"assigned-nas"),
2544 static_cast<int64_t
>(-1));
2557 int& general_status, boost::shared_ptr<Option6IA> ia,
2572 boost::shared_ptr<Option6IAPrefix> release_prefix =
2573 boost::dynamic_pointer_cast<Option6IAPrefix>(ia->getOption(
D6O_IAPREFIX));
2574 if (!release_prefix) {
2576 "You did not include a prefix in your RELEASE"));
2582 release_prefix->getAddress());
2589 "Sorry, no known leases for this duid/iaid, can't release."));
2595 if (!lease->duid_) {
2600 .arg(query->getLabel())
2601 .arg(release_prefix->getAddress().toText())
2602 .arg(
static_cast<int>(release_prefix->getLength()));
2606 "Database consistency check failed when trying to RELEASE"));
2610 if (*duid != *(lease->duid_)) {
2613 .arg(query->getLabel())
2614 .arg(release_prefix->getAddress().toText())
2615 .arg(
static_cast<int>(release_prefix->getLength()))
2616 .arg(lease->duid_->toText());
2620 "This address does not belong to you, you can't release it"));
2624 if (ia->getIAID() != lease->iaid_) {
2627 .arg(query->getLabel())
2628 .arg(release_prefix->getAddress().toText())
2629 .arg(
static_cast<int>(release_prefix->getLength()))
2631 .arg(ia->getIAID());
2633 "This is your address, but you used wrong IAID"));
2643 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease6_release_)) {
2656 callout_handle->setArgument(
"query6", query);
2659 callout_handle->setArgument(
"lease6", lease);
2662 HooksManager::callCallouts(
Hooks.hook_index_lease6_release_, *callout_handle);
2664 skip = callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP;
2668 bool success =
false;
2677 .arg(query->getLabel());
2685 "Server failed to release a lease"));
2688 .arg(query->getLabel())
2689 .arg(lease->addr_.toText())
2690 .arg(
static_cast<int>(lease->prefixlen_))
2698 .arg(query->getLabel())
2699 .arg(lease->addr_.toText())
2700 .arg(
static_cast<int>(lease->prefixlen_))
2703 ia_rsp->addOption(createStatusCode(*query, *ia_rsp,
STATUS_Success,
2704 "Lease released. Thank you, please come again."));
2707 StatsMgr::instance().addValue(
2708 StatsMgr::generateName(
"subnet", lease->subnet_id_,
"assigned-pds"),
2709 static_cast<int64_t
>(-1));
2725 if (opt_rapid_commit) {
2728 .arg(solicit->getLabel());
2733 response->addOption(opt_rapid_commit);
2763 updateReservedFqdn(ctx, response);
2793 updateReservedFqdn(ctx, reply);
2794 generateFqdn(reply);
2819 updateReservedFqdn(ctx, reply);
2820 generateFqdn(reply);
2845 updateReservedFqdn(ctx, reply);
2846 generateFqdn(reply);
2878 bool verified =
false;
2887 for (OptionCollection::const_iterator ia = ias.begin();
2888 ia != ias.end(); ++ia) {
2890 for (OptionCollection::const_iterator opt = opts.begin();
2891 opt != opts.end(); ++opt) {
2903 if (subnet && !subnet->inRange(iaaddr->getAddress())) {
2904 std::ostringstream status_msg;
2905 status_msg <<
"Address " << iaaddr->
getAddress()
2906 <<
" is not on link.";
2907 reply->addOption(createStatusCode(*confirm,
2915 " to the Option6IAAddrPtr. This is programming"
2916 " error and should be reported");
2933 "All addresses are on-link"));
2936 "No subnet selected"));
3012 for (OptionCollection::iterator opt = decline->options_.begin();
3013 opt != decline->options_.end(); ++opt) {
3014 switch (opt->second->getType()) {
3017 boost::dynamic_pointer_cast<Option6IA>(opt->second),
3022 reply->addOption(answer_opt);
3043 int& general_status, boost::shared_ptr<Option6IA> ia,
3047 .arg(decline->getLabel())
3048 .arg(ia->getIAID());
3063 int total_addrs = 0;
3064 for (OptionCollection::const_iterator opt = opts.begin(); opt != opts.end();
3074 if (!decline_addr) {
3081 decline_addr->getAddress());
3086 .arg(decline->getLabel()).arg(decline_addr->getAddress().toText());
3094 "Server does not know about such an address."));
3102 if (!lease->duid_) {
3108 .arg(decline->getLabel())
3109 .arg(decline_addr->getAddress().toText());
3112 "Database consistency check failed when attempting Decline."));
3118 if (*duid != *(lease->duid_)) {
3122 .arg(decline->getLabel())
3123 .arg(decline_addr->getAddress().toText())
3124 .arg(lease->duid_->toText());
3127 "This address does not belong to you, you can't decline it"));
3133 if (ia->getIAID() != lease->iaid_) {
3136 .arg(decline->getLabel())
3137 .arg(lease->addr_.toText())
3141 "This is your address, but you used wrong IAID"));
3153 new_leases.push_back(lease);
3157 if (total_addrs == 0) {
3159 "No addresses sent in IA_NA"));
3172 container->addOption(status);
3177 boost::shared_ptr<Option6IA> ia_rsp) {
3188 if (HooksManager::calloutsPresent(
Hooks.hook_index_lease6_decline_)) {
3201 callout_handle->setArgument(
"query6", decline);
3202 callout_handle->setArgument(
"lease6", lease);
3205 HooksManager::callCallouts(
Hooks.hook_index_lease6_decline_,
3211 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_SKIP) {
3213 .arg(decline->getLabel())
3214 .arg(decline->getIface())
3215 .arg(lease->addr_.toText());
3221 if (callout_handle->getStatus() == CalloutHandle::NEXT_STEP_DROP) {
3223 .arg(decline->getLabel())
3224 .arg(decline->getIface())
3225 .arg(lease->addr_.toText());
3236 StatsMgr::instance().addValue(
3237 StatsMgr::generateName(
"subnet", lease->subnet_id_,
"declined-addresses"),
3238 static_cast<int64_t
>(1));
3241 StatsMgr::instance().addValue(
"declined-addresses",
static_cast<int64_t
>(1));
3250 .arg(lease->addr_.toText()).arg(lease->valid_lft_);
3252 ia_rsp->addOption(createStatusCode(*decline, *ia_rsp,
STATUS_Success,
3253 "Lease declined. Hopefully the next one will be better."));
3316 if (!vclass || vclass->getTuplesNum() == 0) {
3336 pkt->addClass(
"ALL");
3337 string classes =
"ALL ";
3351 for (ClientClassDefList::const_iterator it = defs_ptr->cbegin();
3352 it != defs_ptr->cend(); ++it) {
3360 if ((*it)->getRequired()) {
3364 if ((*it)->getDependOnKnown() != depend_on_known) {
3373 .arg((*it)->getName())
3376 pkt->addClass((*it)->getName());
3379 .arg((*it)->getName())
3384 .arg((*it)->getName())
3388 .arg((*it)->getName())
3389 .arg(
"get exception?");
3400 cclass != classes.
cend(); ++cclass) {
3401 pkt->addClass(*cclass);
3406 if (!classes.
empty()) {
3408 .arg(pkt->getLabel())
3422 subnet->getSharedNetwork(network);
3424 const ClientClasses& to_add = network->getRequiredClasses();
3426 cclass != to_add.
cend(); ++cclass) {
3434 cclass != to_add.
cend(); ++cclass) {
3449 cclass != to_add.
cend(); ++cclass) {
3463 cclass != classes.
cend(); ++cclass) {
3486 pkt->addClass(*cclass);
3499 .arg(
"get exception?");
3509 " a message must not be NULL when updating reserved FQDN");
3520 std::string name = fqdn->getDomainName();
3530 qualifyName(ctx.
currentHost()->getHostname(),
true);
3532 if (new_name != name) {
3537 answer->addOption(fqdn);
3543 Dhcpv6Srv::generateFqdn(
const Pkt6Ptr& answer) {
3546 " a message must not be NULL when generating FQDN");
3557 if (!fqdn || !fqdn->getDomainName().empty()) {
3575 std::string generated_name =
3579 .arg(answer->getLabel())
3580 .arg(generated_name);
3592 lease->hostname_ = generated_name;
3597 " for address " << addr <<
", so as it is impossible"
3598 " to update FQDN data. This is a programmatic error"
3599 " as the given address is now being handed to the"
3607 answer->addOption(fqdn);
3611 .arg(answer->getLabel())
3643 arg(result).arg((ncr ? ncr->toText() :
" NULL "));
3655 std::stringstream tmp;
3659 tmp << endl << EXTENDED_VERSION << endl;
3660 tmp <<
"linked with:" << endl;
3661 tmp << Logger::getVersion() << endl;
3662 tmp << CryptoLink::getVersion() << endl;
3663 tmp <<
"database:" << endl;
3683 if (query->relay_info_.empty()) {
3694 for (
int i = query->relay_info_.size(); i > 0 ; --i) {
3696 if (rsoo_container) {
3701 for (OptionCollection::const_iterator opt = rsoo.begin();
3702 opt != rsoo.end(); ++opt) {
3706 if (cfg_rsoo->enabled(opt->second->getType()) &&
3707 !rsp->getOption(opt->second->getType())) {
3708 rsp->addOption(opt->second);
3717 if (query->relay_info_.empty()) {
3725 return (query->getRemotePort());
3731 void Dhcpv6Srv::processStatsReceived(
const Pkt6Ptr& query) {
3735 string stat_name =
"pkt6-unknown-received";
3736 switch (query->getType()) {
3738 stat_name =
"pkt6-solicit-received";
3742 stat_name =
"pkt6-advertise-received";
3745 stat_name =
"pkt6-request-received";
3748 stat_name =
"pkt6-confirm-received";
3751 stat_name =
"pkt6-renew-received";
3754 stat_name =
"pkt6-rebind-received";
3758 stat_name =
"pkt6-reply-received";
3761 stat_name =
"pkt6-release-received";
3764 stat_name =
"pkt6-decline-received";
3767 stat_name =
"pkt6-reconfigure-received";
3770 stat_name =
"pkt6-infrequest-received";
3773 stat_name =
"pkt6-dhcpv4-query-received";
3777 stat_name =
"pkt6-dhcpv4-response-received";
3783 StatsMgr::instance().addValue(stat_name,
static_cast<int64_t
>(1));
3788 StatsMgr::instance().addValue(
"pkt6-sent",
static_cast<int64_t
>(1));
3792 switch (response->getType()) {
3794 stat_name =
"pkt6-advertise-sent";
3797 stat_name =
"pkt6-reply-sent";
3800 stat_name =
"pkt6-dhcpv4-response-sent";
3807 StatsMgr::instance().addValue(stat_name,
static_cast<int64_t
>(1));
3811 return (
Hooks.hook_index_buffer6_send_);
3815 Dhcpv6Srv::requestedInORO(
const Pkt6Ptr& query,
const uint16_t code)
const {
3817 boost::dynamic_pointer_cast<OptionUint16Array>(query->getOption(
D6O_ORO));
3820 const std::vector<uint16_t>& codes = oro->getValues();
3821 return (std::find(codes.begin(), codes.end(), code) != codes.end());
3831 HooksManager::clearParkingLots();