Kea 3.1.5
radius_callout.cc
Go to the documentation of this file.
1// Copyright (C) 2020-2025 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7// Functions accessed by the hooks framework use C linkage to avoid the name
8// mangling that accompanies use of the C++ compiler as well as to avoid
9// issues related to namespaces.
10
11#include <config.h>
12
15#include <cc/simple_parser.h>
16#include <hooks/hooks.h>
17#include <dhcp/pkt4.h>
18#include <dhcp/pkt6.h>
19#include <dhcpsrv/lease.h>
20#include <dhcpsrv/subnet.h>
21#include <radius.h>
22#include <dhcpsrv/cfgmgr.h>
23#include <dhcpsrv/host_mgr.h>
24#include <process/daemon.h>
25#include <stats/stats_mgr.h>
26#include <radius_log.h>
27#include <radius_parsers.h>
28#include <radius_access.h>
29#include <radius_accounting.h>
31
32#include <string>
33#include <sstream>
34#include <vector>
35
36using namespace isc;
37using namespace isc::asiolink;
38using namespace isc::config;
39using namespace isc::data;
40using namespace isc::dhcp;
41using namespace isc::hooks;
42using namespace isc::process;
43using namespace isc::radius;
44using namespace isc::stats;
45using namespace isc::util;
46using namespace std;
47
48namespace {
49
54ElementPtr getConfig(LibraryHandle& handle) {
55 const vector<string> names = handle.getParameterNames();
56 const set<string> keywords = RadiusConfigParser::RADIUS_KEYWORDS;
58
59 for (auto const& name : names) {
60 if (keywords.count(name) == 0) {
61 isc_throw(BadValue, "unknown parameter: " << name);
62 }
63 ConstElementPtr value = handle.getParameter(name);
64 if (value) {
65 config->set(name, value);
66 }
67 }
68 return (config);
69}
70
77RadiusAuthHandlerPtr subnet4Select(CalloutHandle& handle,
78 ConstSubnet4Ptr subnet, Pkt4Ptr query) {
80 MultiThreadingLock lock(impl.auth_->requests4_.mutex_);
81
83 uint32_t subnet_id = subnet->getID();
84 uint32_t host_subnet_id =
85 (subnet->getReservationsGlobal() ? SUBNET_ID_GLOBAL : subnet_id);
86 vector<uint8_t> id;
87 string text;
88 if (!impl.auth_->getIdentifier(*query, id, text)) {
89 // What to do?
91 return (handler);
92 }
93
94 // Ask host cache.
95 ConstHostPtr host = HostMgr::instance().get4Any(host_subnet_id,
96 impl.id_type4_,
97 &id[0], id.size());
98 // Check cached subnet reselect.
99 if (host && host->getContext() &&
100 (host->getContext()->getType() == Element::map) &&
101 host->getContext()->contains("subnet-id")) {
102 try {
103 ConstElementPtr reselected = host->getContext()->get("subnet-id");
104 subnet_id = static_cast<uint32_t>(reselected->intValue());
107 .arg(subnet->getID())
108 .arg(subnet_id);
109 // Reselect to null.
110 if (subnet_id == SUBNET_ID_UNUSED) {
111 ConstSubnet4Ptr null_subnet;
112 handle.setArgument("subnet4", null_subnet);
113 return (handler);
114 }
115 // Reselect to an other subnet.
116 uint32_t new_host_subnet_id = host_subnet_id;
117 if (subnet_id != subnet->getID()) {
118 ConstSubnet4Ptr new_subnet =
120 getCfgSubnets4()->getSubnet(subnet_id);
121 if (!new_subnet) {
123 "can't find subnet with id: " << subnet_id);
124 }
125 new_host_subnet_id =
126 (new_subnet->getReservationsGlobal() ?
127 SUBNET_ID_GLOBAL : subnet_id);
128 handle.setArgument("subnet4", new_subnet);
129 }
130 // Get again host cache.
131 if (new_host_subnet_id != host_subnet_id) {
132 host = HostMgr::instance().get4Any(new_host_subnet_id,
133 impl.id_type4_,
134 &id[0], id.size());
135 }
136 } catch (const std::exception&) {
137 // Delete bad entry from cache.
138 HostPtr bad(new Host(*host));
139 static_cast<void>(impl.cache_->remove(bad));
141 return (handler);
142 }
143 }
144
145 // Check cached RADIUS response.
146 if (host && host->getContext() &&
147 (host->getContext()->getType() == Element::map)) {
148 // Yeah! We don't need to ask the Radius server.
149 Attributes attrs =
150 Attributes::fromElement(host->getContext()->get("radius"));
152 .arg(host->toText())
153 .arg(attrs.toText());
154 // 3 cases:
155 // - ip address (is in the host).
156 // - framed pool (put in the query).
157 // - class (todo).
158 if (!host->getIPv4Reservation().isV4Zero()) {
159 // Done!
160 return (handler);
161 }
162 ConstAttributePtr framed_pool = attrs.get(PW_FRAMED_POOL);
163 if (framed_pool && (framed_pool->getValueType() == PW_TYPE_STRING)) {
164 query->addClass(framed_pool->toString());
165 // Done!
166 return (handler);
167 }
168 // todo: class.
169 ConstAttributePtr class_ = attrs.get(PW_CLASS);
170 if (class_ && (class_->getValueType() == PW_TYPE_STRING)) {
171 // todo
172 return (handler);
173 }
174 return (handler);
175 }
176
177 // Get the pending request.
179 impl.auth_->requests4_.get(id);
180
181 // Conflict?
182 if (pending_request) {
184 .arg(query->getLabel())
185 .arg(text);
186 StatsMgr::instance().addValue("pkt4-duplicate",
187 static_cast<int64_t>(1));
188 StatsMgr::instance().addValue("pkt4-receive-drop",
189 static_cast<int64_t>(1));
191 return (handler);
192 }
193
194 // Too many pending requests.
195 size_t max_requests = impl.auth_->max_pending_requests_;
196 if ((max_requests > 0) && (impl.auth_->requests4_.size() >= max_requests)) {
199 .arg(query->getLabel())
200 .arg(text);
201 StatsMgr::instance().addValue("pkt4-queue-full",
202 static_cast<int64_t>(1));
203 StatsMgr::instance().addValue("pkt4-receive-drop",
204 static_cast<int64_t>(1));
206 return (handler);
207 }
208
209 // Ask the Radius server.
210 handler = impl.auth_->buildAuth(*query, subnet_id, id, text);
211 if (!handler) {
212 // Error was logged.
214 return (handler);
215 }
216
217 // Create a new pending access request.
218 impl.auth_->requests4_.set(id, query);
219
220 return (handler);
221}
222
229RadiusAuthHandlerPtr subnet6Select(CalloutHandle& handle,
230 ConstSubnet6Ptr subnet, Pkt6Ptr query) {
232 MultiThreadingLock lock(impl.auth_->requests6_.mutex_);
233
234 RadiusAuthHandlerPtr handler;
235 uint32_t subnet_id = subnet->getID();
236 uint32_t host_subnet_id =
237 (subnet->getReservationsGlobal() ? SUBNET_ID_GLOBAL : subnet_id);
238 vector<uint8_t> id;
239 string text;
240 if (!impl.auth_->getIdentifier(*query, id, text)) {
241 // What to do?
243 return (handler);
244 }
245
246 // Ask host cache.
247 ConstHostPtr host = HostMgr::instance().get6Any(host_subnet_id,
248 impl.id_type6_,
249 &id[0], id.size());
250 // Check cached subnet reselect.
251 if (host && host->getContext() &&
252 (host->getContext()->getType() == Element::map) &&
253 host->getContext()->contains("subnet-id")) {
254 try {
255 ConstElementPtr reselected = host->getContext()->get("subnet-id");
256 subnet_id = static_cast<uint32_t>(reselected->intValue());
259 .arg(subnet->getID())
260 .arg(subnet_id);
261 // Reselect to null.
262 if (subnet_id == SUBNET_ID_UNUSED) {
263 ConstSubnet6Ptr null_subnet;
264 handle.setArgument("subnet6", null_subnet);
265 return (handler);
266 }
267 // Reselect to an other subnet.
268 uint32_t new_host_subnet_id = host_subnet_id;
269 if (subnet_id != subnet->getID()) {
270 ConstSubnet6Ptr new_subnet =
272 getCfgSubnets6()->getSubnet(subnet_id);
273 if (!new_subnet) {
275 "can't find subnet with id: " << subnet_id);
276 }
277 new_host_subnet_id =
278 (new_subnet->getReservationsGlobal() ?
279 SUBNET_ID_GLOBAL : subnet_id);
280 handle.setArgument("subnet6", new_subnet);
281 }
282 // Get again host cache.
283 if (new_host_subnet_id != host_subnet_id) {
284 host = HostMgr::instance().get6Any(new_host_subnet_id,
285 impl.id_type6_,
286 &id[0], id.size());
287 }
288 } catch (const std::exception&) {
289 // Delete bad entry from cache.
290 HostPtr bad(new Host(*host));
291 static_cast<void>(impl.cache_->remove(bad));
293 return (handler);
294 }
295 }
296
297 // Check cached RADIUS response.
298 if (host && host->getContext() &&
299 (host->getContext()->getType() == Element::map)) {
300 // Yeah! We don't need to ask the Radius server.
301 Attributes attrs =
302 Attributes::fromElement(host->getContext()->get("radius"));
304 .arg(host->toText())
305 .arg(attrs.toText());
306 // 4 cases:
307 // - ip address (is in the host).
308 // - delegated prefix (is in the host).
309 // - framed pool (put in the query).
310 // - class (todo).
311 if (host->hasIPv6Reservation()) {
312 // Done!
313 return (handler);
314 }
315 ConstAttributePtr framed_pool = attrs.get(PW_FRAMED_POOL);
316 if (framed_pool && (framed_pool->getValueType() == PW_TYPE_STRING)) {
317 query->addClass(framed_pool->toString());
318 // Done!
319 return (handler);
320 }
321 // todo: class.
322 ConstAttributePtr class_ = attrs.get(PW_CLASS);
323 if (class_ && (class_->getValueType() == PW_TYPE_STRING)) {
324 // todo
325 return (handler);
326 }
327 return (handler);
328 }
329
330 // Get the pending request.
332 impl.auth_->requests6_.get(id);
333
334 // Conflict?
335 if (pending_request) {
337 .arg(query->getLabel())
338 .arg(text);
339 StatsMgr::instance().addValue("pkt6-duplicate",
340 static_cast<int64_t>(1));
341 StatsMgr::instance().addValue("pkt6-receive-drop",
342 static_cast<int64_t>(1));
344 return (handler);
345 }
346
347 // Too many pending requests.
348 size_t max_requests = impl.auth_->max_pending_requests_;
349 if ((max_requests > 0) && (impl.auth_->requests6_.size() >= max_requests)) {
352 .arg(query->getLabel())
353 .arg(text);
354 StatsMgr::instance().addValue("pkt6-queue-full",
355 static_cast<int64_t>(1));
356 StatsMgr::instance().addValue("pkt6-receive-drop",
357 static_cast<int64_t>(1));
359 return (handler);
360 }
361
362 // Ask the Radius server.
363 handler = impl.auth_->buildAuth(*query, subnet_id, id, text);
364 if (!handler) {
365 // Error was logged.
367 return (handler);
368 }
369
370 // Create a new pending access request.
371 impl.auth_->requests6_.set(id, query);
372
373 return (handler);
374}
375
376} // end of anonymous namespace
377
378extern "C" {
379
384int load(LibraryHandle& handle) {
385
386 try {
387 // Make the hook library not loadable by d2 or ca.
388 uint16_t family = CfgMgr::instance().getFamily();
389 const std::string& proc_name = Daemon::getProcName();
390 if (family == AF_INET) {
391 if (proc_name != "kea-dhcp4") {
392 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
393 << ", expected kea-dhcp4");
394 }
395 } else {
396 if (proc_name != "kea-dhcp6") {
397 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
398 << ", expected kea-dhcp6");
399 }
400 }
401
402 // Get and decode configuration.
403 ElementPtr config = getConfig(handle);
405 impl.init(config);
406 } catch (const std::exception& ex) {
408 .arg(ex.what());
409 return (CONTROL_RESULT_ERROR);
410 }
411
413 return (CONTROL_RESULT_SUCCESS);
414}
415
425
430 return (1);
431}
432
444
456
467 if (status == CalloutHandle::NEXT_STEP_DROP ||
469 return (0);
470 }
471
472 InHook in_hook;
474 if (!impl.auth_ || !impl.checkHostBackends()) {
475 return (CONTROL_RESULT_SUCCESS);
476 }
477 Pkt4Ptr query;
478 handle.getArgument("query4", query);
479 ConstSubnet4Ptr subnet;
480 handle.getArgument("subnet4", subnet);
481 if (!query || !subnet || (subnet->getID() == 0)) {
482 return (CONTROL_RESULT_SUCCESS);
483 }
484 ParkingLotHandlePtr parking_lot = handle.getParkingLotHandlePtr();
485 parking_lot->reference(query);
486 try {
487 RadiusAuthHandlerPtr handler = subnet4Select(handle, subnet, query);
488 if (!handler) {
489 parking_lot->dereference(query);
490 return (CONTROL_RESULT_SUCCESS);
491 }
492 handler->start();
494 } catch (...) {
495 parking_lot->dereference(query);
497 }
498
499 return (CONTROL_RESULT_SUCCESS);
500}
501
512 if (status == CalloutHandle::NEXT_STEP_DROP ||
514 return (CONTROL_RESULT_SUCCESS);
515 }
516
517 InHook in_hook;
519 if (!impl.auth_ || !impl.checkHostBackends()) {
520 return (CONTROL_RESULT_SUCCESS);
521 }
522 Pkt6Ptr query;
523 handle.getArgument("query6", query);
524 ConstSubnet6Ptr subnet;
525 handle.getArgument("subnet6", subnet);
526 if (!query || !subnet || (subnet->getID() == 0)) {
527 return (CONTROL_RESULT_SUCCESS);
528 }
529 ParkingLotHandlePtr parking_lot = handle.getParkingLotHandlePtr();
530 parking_lot->reference(query);
531 try {
532 RadiusAuthHandlerPtr handler = subnet6Select(handle, subnet, query);
533 if (!handler) {
534 parking_lot->dereference(query);
535 return (CONTROL_RESULT_SUCCESS);
536 }
537 handler->start();
539 } catch (...) {
540 parking_lot->dereference(query);
542 }
543
544 return (CONTROL_RESULT_SUCCESS);
545}
546
556 if (status == CalloutHandle::NEXT_STEP_DROP ||
558 return (0);
559 }
560
561 InHook in_hook;
563 if (!impl.acct_ || !impl.getIOContext()) {
564 return (CONTROL_RESULT_SUCCESS);
565 }
566
567 bool fake_allocation = false;
568 handle.getArgument("fake_allocation", fake_allocation);
569 if (fake_allocation) {
570 // If this is a discover, there's nothing to do
571 return (CONTROL_RESULT_SUCCESS);
572 }
573
574 Lease4Ptr lease;
575 handle.getArgument("lease4", lease);
576 try {
577 // Start the Accounting-Request transmission.
578 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_CREATE);
579 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
580 } catch (const std::exception& ex) {
582 .arg("lease4_select")
583 .arg(ex.what());
584 }
585 return (CONTROL_RESULT_SUCCESS);
586}
587
597 if (status == CalloutHandle::NEXT_STEP_DROP ||
599 return (0);
600 }
601
602 InHook in_hook;
604 if (!impl.acct_ || !impl.getIOContext()) {
605 return (CONTROL_RESULT_SUCCESS);
606 }
607 Lease4Ptr lease;
608 handle.getArgument("lease4", lease);
609 try {
610 // Start the Accounting-Request transmission.
611 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_RENEW);
612 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
613 } catch (const std::exception& ex) {
615 .arg("lease4_renew")
616 .arg(ex.what());
617 }
618 return (CONTROL_RESULT_SUCCESS);
619}
620
630 if (status == CalloutHandle::NEXT_STEP_DROP ||
632 return (0);
633 }
634
635 InHook in_hook;
637 if (!impl.acct_ || !impl.getIOContext()) {
638 return (CONTROL_RESULT_SUCCESS);
639 }
640 Lease4Ptr lease;
641 handle.getArgument("lease4", lease);
642 try {
643 // Start the Accounting-Request transmission.
644 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_RELEASE);
645 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
646 } catch (const std::exception& ex) {
648 .arg("lease4_release")
649 .arg(ex.what());
650 }
651 return (CONTROL_RESULT_SUCCESS);
652}
653
663 if (status == CalloutHandle::NEXT_STEP_DROP ||
665 return (0);
666 }
667
668 InHook in_hook;
670 if (!impl.acct_ || !impl.getIOContext()) {
671 return (CONTROL_RESULT_SUCCESS);
672 }
673 Lease4Ptr lease;
674 handle.getArgument("lease4", lease);
675 try {
676 // Start the Accounting-Request transmission.
677 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_DECLINE);
678 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
679 } catch (const std::exception& ex) {
681 .arg("lease4_decline")
682 .arg(ex.what());
683 }
684 return (CONTROL_RESULT_SUCCESS);
685}
686
693 if (status == CalloutHandle::NEXT_STEP_DROP ||
695 return (0);
696 }
697
698 InHook in_hook;
700 if (!impl.acct_ || !impl.getIOContext()) {
701 return (CONTROL_RESULT_SUCCESS);
702 }
703 Lease4Ptr lease;
704 handle.getArgument("lease4", lease);
705 try {
706 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_EXPIRE);
707 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
708 } catch (const std::exception& ex) {
710 .arg("lease4_expire")
711 .arg(ex.what());
712 }
713 return (CONTROL_RESULT_SUCCESS);
714}
715
722 if (status == CalloutHandle::NEXT_STEP_DROP ||
724 return (0);
725 }
726
727 InHook in_hook;
729 if (!impl.acct_ || !impl.getIOContext()) {
730 return (CONTROL_RESULT_SUCCESS);
731 }
732 bool fake_allocation;
733 handle.getArgument("fake_allocation", fake_allocation);
734 if (fake_allocation) {
735 return (CONTROL_RESULT_SUCCESS);
736 }
737 Lease6Ptr lease;
738 handle.getArgument("lease6", lease);
739 try {
740 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_CREATE);
741 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
742 } catch (const std::exception& ex) {
744 .arg("lease6_select")
745 .arg(ex.what());
746 }
747 return (CONTROL_RESULT_SUCCESS);
748}
749
756 if (status == CalloutHandle::NEXT_STEP_DROP ||
758 return (0);
759 }
760
761 InHook in_hook;
763 if (!impl.acct_ || !impl.getIOContext()) {
764 return (CONTROL_RESULT_SUCCESS);
765 }
766 Lease6Ptr lease;
767 handle.getArgument("lease6", lease);
768 try {
769 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_RENEW);
770 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
771 } catch (const std::exception& ex) {
773 .arg("lease6_renew")
774 .arg(ex.what());
775 }
776 return (CONTROL_RESULT_SUCCESS);
777}
778
785 if (status == CalloutHandle::NEXT_STEP_DROP ||
787 return (0);
788 }
789
790 InHook in_hook;
792 if (!impl.acct_ || !impl.getIOContext()) {
793 return (CONTROL_RESULT_SUCCESS);
794 }
795 Lease6Ptr lease;
796 handle.getArgument("lease6", lease);
797 try {
798 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_REBIND);
799 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
800 } catch (const std::exception& ex) {
802 .arg("lease6_rebind")
803 .arg(ex.what());
804 }
805 return (CONTROL_RESULT_SUCCESS);
806}
807
814 if (status == CalloutHandle::NEXT_STEP_DROP ||
816 return (0);
817 }
818
819 InHook in_hook;
821 if (!impl.acct_ || !impl.getIOContext()) {
822 return (CONTROL_RESULT_SUCCESS);
823 }
824 Lease6Ptr lease;
825 handle.getArgument("lease6", lease);
826 try {
827 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_RELEASE);
828 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
829 } catch (const std::exception& ex) {
831 .arg("lease6_release")
832 .arg(ex.what());
833 }
834 return (CONTROL_RESULT_SUCCESS);
835}
836
843 if (status == CalloutHandle::NEXT_STEP_DROP ||
845 return (0);
846 }
847
848 InHook in_hook;
850 if (!impl.acct_ || !impl.getIOContext()) {
851 return (CONTROL_RESULT_SUCCESS);
852 }
853 Lease6Ptr lease;
854 handle.getArgument("lease6", lease);
855 try {
856 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_DECLINE);
857 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
858 } catch (const std::exception& ex) {
860 .arg("lease6_decline")
861 .arg(ex.what());
862 }
863 return (CONTROL_RESULT_SUCCESS);
864}
865
872 if (status == CalloutHandle::NEXT_STEP_DROP ||
874 return (0);
875 }
876
877 InHook in_hook;
879 if (!impl.acct_ || !impl.getIOContext()) {
880 return (CONTROL_RESULT_SUCCESS);
881 }
882 Lease6Ptr lease;
883 handle.getArgument("lease6", lease);
884 try {
885 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_EXPIRE);
886 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
887 } catch (const std::exception& ex) {
889 .arg("lease6_expire")
890 .arg(ex.what());
891 }
892 return (CONTROL_RESULT_SUCCESS);
893}
894
903 InHook in_hook;
905 if (!impl.acct_ || !impl.getIOContext()) {
906 return (CONTROL_RESULT_SUCCESS);
907 }
908 string name;
909 ConstElementPtr arguments;
910 ConstElementPtr response;
911 try {
912 handle.getArgument("name", name);
913 handle.getArgument("arguments", arguments);
914 handle.getArgument("response", response);
915 if (!arguments || !response) {
916 // "arguments" and "response" are required for all further actions.
917 // Stop here if they are not set.
918 return (CONTROL_RESULT_SUCCESS);
919 }
920
921 int result = SimpleParser::getInteger(response, "result");
922 if (result != 0) {
923 // Command has failed.
924 return (CONTROL_RESULT_SUCCESS);
925 }
926
927 // Handle peer updates?
928 const ConstElementPtr origin(arguments->get("origin"));
929 if (origin) {
930 // "origin" has a dynamic type. There are commands like ha-sync-complete-notify that set
931 // it to an integer. For simplicity, treat those cases like it is not coming from an HA
932 // partner for now and it will get filtered out by name further down below. We only care
933 // about lease updates.
934 const bool is_from_ha_partner(origin->getType() == Element::string &&
935 origin->stringValue() == "ha-partner");
936 if (!impl.acct_->peer_updates_ && is_from_ha_partner) {
937 return (CONTROL_RESULT_SUCCESS);
938 }
939 }
940
941 RadiusAcctHandlerPtr handler;
942 if (name == "lease4-add") {
943 handler = impl.acct_->buildAcct4(arguments, EVENT_ADD);
944 } else if (name == "lease4-update") {
945 handler = impl.acct_->buildAcct4(arguments, EVENT_UPDATE);
946 } else if (name== "lease4-del") {
947 handler = impl.acct_->buildAcct4(arguments, EVENT_DEL);
948 } else if (name == "lease6-add") {
949 handler = impl.acct_->buildAcct6(arguments, EVENT_ADD);
950 } else if (name == "lease6-update") {
951 handler = impl.acct_->buildAcct6(arguments, EVENT_UPDATE);
952 } else if (name== "lease6-del") {
953 handler = impl.acct_->buildAcct6(arguments, EVENT_DEL);
954 }
955 if (handler) {
956 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync,
957 handler));
958 }
959 } catch (const std::exception& ex) {
960 ostringstream ss;
961 ss << "command_processed: " << name;
963 .arg(ss.str())
964 .arg(ex.what());
965 }
966 return (CONTROL_RESULT_SUCCESS);
967}
968
969} // end extern "C"
CalloutNextStep
Specifies allowed next steps.
@ NEXT_STEP_PARK
park the packet
@ NEXT_STEP_DROP
drop the packet
@ NEXT_STEP_SKIP
skip the next processing step
@ map
Definition data.h:160
@ string
Definition data.h:157
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:354
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown when an unexpected error condition occurs.
static int64_t getInteger(isc::data::ConstElementPtr scope, const std::string &name)
Returns an integer parameter from a scope.
uint16_t getFamily() const
Returns address family.
Definition cfgmgr.h:246
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Definition cfgmgr.cc:116
ConstHostPtr get6Any(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns any host connected to the IPv6 subnet.
Definition host_mgr.cc:590
ConstHostPtr get4Any(const SubnetID &subnet_id, const Host::IdentifierType &identifier_type, const uint8_t *identifier_begin, const size_t identifier_len, const HostMgrOperationTarget target) const
Returns any host connected to the IPv4 subnet.
Definition host_mgr.cc:401
static HostMgr & instance()
Returns a sole instance of the HostMgr.
Definition host_mgr.cc:114
Represents a device with IPv4 and/or IPv6 reservations.
Definition host.h:327
Per-packet callout handle.
ParkingLotHandlePtr getParkingLotHandlePtr() const
Returns pointer to the parking lot handle for this hook point.
CalloutNextStep getStatus() const
Returns the next processing step.
void setStatus(const CalloutNextStep next)
Sets the next processing step.
void getArgument(const std::string &name, T &value) const
Get argument.
void setArgument(const std::string &name, T value)
Set argument.
isc::data::ConstElementPtr getParameter(const std::string &name)
Returns configuration parameter for the library.
std::vector< std::string > getParameterNames()
Returns names of configuration parameters for the library.
static std::string getProcName()
returns the process name This value is used as when forming the default PID file name
Definition daemon.cc:152
Collection of attributes.
std::string toText(size_t indent=0) const
Returns text representation of the collection.
ConstAttributePtr get(const uint8_t type) const
Get instance of the attribute in the collection.
static Attributes fromElement(const data::ConstElementPtr &attr_list)
Parse collection.
InHook class (RAII style).
Definition radius.h:259
static void runAsync(RadiusAcctHandlerPtr handler)
Run asynchronously.
static const std::set< std::string > RADIUS_KEYWORDS
Keywords (aka global configuration entry names).
Radius hooks library implementation.
Definition radius.h:50
void reset()
Reset the state as it was just created.
Definition radius.cc:124
void startServices()
Start the I/O mechanisms.
Definition radius.cc:155
static RadiusImpl & instance()
RadiusImpl is a singleton class.
Definition radius.cc:37
static StatsMgr & instance()
Statistics Manager accessor method.
This file contains several functions and constants that are used for handling commands and responses ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
Definition macros.h:32
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
const int CONTROL_RESULT_ERROR
Status code indicating a general failure.
const int CONTROL_RESULT_SUCCESS
Status code indicating a successful operation.
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
Definition subnet.h:623
boost::shared_ptr< Host > HostPtr
Pointer to the Host object.
Definition host.h:837
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
Definition subnet.h:458
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Definition pkt4.h:556
boost::shared_ptr< Lease6 > Lease6Ptr
Pointer to a Lease6 structure.
Definition lease.h:528
boost::shared_ptr< const Host > ConstHostPtr
Const pointer to the Host object.
Definition host.h:840
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
Definition pkt6.h:31
boost::shared_ptr< Lease4 > Lease4Ptr
Pointer to a Lease4 structure.
Definition lease.h:315
GssTsigImplPtr impl
The GSS-TSIG hook implementation object.
boost::shared_ptr< ParkingLotHandle > ParkingLotHandlePtr
Pointer to the parking lot handle.
boost::shared_ptr< RadiusAcctHandler > RadiusAcctHandlerPtr
Type of pointers to Radius accounting communication handler.
boost::shared_ptr< RadiusAuthPendingRequest< PktPtrType > > RadiusAuthPendingRequestPtr
Pointer to a pending Radius access request.
const isc::log::MessageID RADIUS_ACCESS_CONFLICT
const isc::log::MessageID RADIUS_ACCESS_MAX_PENDING_REQUESTS
boost::shared_ptr< const Attribute > ConstAttributePtr
const isc::log::MessageID RADIUS_INIT_OK
const isc::log::MessageID RADIUS_DEINIT_OK
const int RADIUS_DBG_TRACE
Radius logging levels.
Definition radius_log.h:26
const isc::log::MessageID RADIUS_ACCESS_CACHE_GET
boost::shared_ptr< RadiusAuthHandler > RadiusAuthHandlerPtr
Type of pointers to Radius access communication handler.
isc::log::Logger radius_logger("radius-hooks")
Radius Logger.
Definition radius_log.h:35
const isc::log::MessageID RADIUS_ACCESS_SUBNET_RESELECT
const isc::log::MessageID RADIUS_CONFIGURATION_FAILED
const isc::log::MessageID RADIUS_HOOK_FAILED
Defines the logger used by the top-level component of kea-lfc.
int subnet4_select(CalloutHandle &handle)
This callout tries to retrieve host information from cache.
int lease4_release(CalloutHandle &handle)
This callout is called at the "lease4_release" hook.
int lease4_decline(CalloutHandle &handle)
This callout is called at the "lease4_decline" hook.
int dhcp6_srv_configured(CalloutHandle &)
This function is called by the DHCPv6 server when it is configured.
int dhcp4_srv_configured(CalloutHandle &)
This function is called by the DHCPv4 server when it is configured.
int lease6_release(CalloutHandle &handle)
This callout is called at the "lease6_release" hook.
int command_processed(CalloutHandle &handle)
This callout is called at the "command_processed" hook point.
int lease6_rebind(CalloutHandle &handle)
This callout is called at the "lease6_rebind" hook.
int multi_threading_compatible()
This function is called to retrieve the multi-threading compatibility.
int lease4_renew(CalloutHandle &handle)
This callout is called at the "lease4_renew" hook.
int subnet6_select(CalloutHandle &handle)
This callout tries to retrieve host information from cache.
int lease4_select(CalloutHandle &handle)
This callout is called at the "lease4_select" hook.
int unload()
This function is called when the library is unloaded.
int lease6_expire(CalloutHandle &handle)
This callout is called at the "lease6_expire" hook.
int lease4_expire(CalloutHandle &handle)
This callout is called at the "lease4_expire" hook.
int lease6_select(CalloutHandle &handle)
This callout is called at the "lease6_select" hook.
int load(LibraryHandle &handle)
This function is called when the library is loaded.
int lease6_decline(CalloutHandle &handle)
This callout is called at the "lease6_decline" hook.
int lease6_renew(CalloutHandle &handle)
This callout is called at the "lease6_renew" hook.
RAII lock object to protect the code in the same scope with a mutex.