Kea 3.1.1
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 <radius_log.h>
26#include <radius_parsers.h>
27#include <radius_access.h>
28#include <radius_accounting.h>
30
31#include <string>
32#include <sstream>
33#include <vector>
34
35using namespace isc;
36using namespace isc::asiolink;
37using namespace isc::config;
38using namespace isc::data;
39using namespace isc::dhcp;
40using namespace isc::hooks;
41using namespace isc::process;
42using namespace isc::radius;
43using namespace isc::util;
44using namespace std;
45
46namespace {
47
52ElementPtr getConfig(LibraryHandle& handle) {
53 const vector<string> names = handle.getParameterNames();
54 const set<string> keywords = RadiusConfigParser::RADIUS_KEYWORDS;
56
57 for (auto const& name : names) {
58 if (keywords.count(name) == 0) {
59 isc_throw(BadValue, "unknown parameter: " << name);
60 }
61 ConstElementPtr value = handle.getParameter(name);
62 if (value) {
63 config->set(name, value);
64 }
65 }
66 return (config);
67}
68
75RadiusAuthHandlerPtr subnet4Select(CalloutHandle& handle,
76 ConstSubnet4Ptr subnet, Pkt4Ptr query) {
78 MultiThreadingLock lock(impl.auth_->requests4_.mutex_);
79
81 uint32_t subnet_id = subnet->getID();
82 uint32_t host_subnet_id =
83 (subnet->getReservationsGlobal() ? SUBNET_ID_GLOBAL : subnet_id);
84 vector<uint8_t> id;
85 string text;
86 if (!impl.auth_->getIdentifier(*query, id, text)) {
87 // What to do?
89 return (handler);
90 }
91
92 // Ask host cache.
93 ConstHostPtr host = HostMgr::instance().get4Any(host_subnet_id,
94 impl.id_type4_,
95 &id[0], id.size());
96 // Check cached subnet reselect.
97 if (host && host->getContext() &&
98 (host->getContext()->getType() == Element::map) &&
99 host->getContext()->contains("subnet-id")) {
100 try {
101 ConstElementPtr reselected = host->getContext()->get("subnet-id");
102 subnet_id = static_cast<uint32_t>(reselected->intValue());
105 .arg(subnet->getID())
106 .arg(subnet_id);
107 // Reselect to null.
108 if (subnet_id == SUBNET_ID_UNUSED) {
109 ConstSubnet4Ptr null_subnet;
110 handle.setArgument("subnet4", null_subnet);
111 return (handler);
112 }
113 // Reselect to an other subnet.
114 uint32_t new_host_subnet_id = host_subnet_id;
115 if (subnet_id != subnet->getID()) {
116 ConstSubnet4Ptr new_subnet =
118 getCfgSubnets4()->getSubnet(subnet_id);
119 if (!new_subnet) {
121 "can't find subnet with id: " << subnet_id);
122 }
123 new_host_subnet_id =
124 (new_subnet->getReservationsGlobal() ?
125 SUBNET_ID_GLOBAL : subnet_id);
126 handle.setArgument("subnet4", new_subnet);
127 }
128 // Get again host cache.
129 if (new_host_subnet_id != host_subnet_id) {
130 host = HostMgr::instance().get4Any(new_host_subnet_id,
131 impl.id_type4_,
132 &id[0], id.size());
133 }
134 } catch (const std::exception&) {
135 // Delete bad entry from cache.
136 HostPtr bad(new Host(*host));
137 static_cast<void>(impl.cache_->remove(bad));
139 return (handler);
140 }
141 }
142
143 // Check cached RADIUS response.
144 if (host && host->getContext() &&
145 (host->getContext()->getType() == Element::map)) {
146 // Yeah! We don't need to ask the Radius server.
147 Attributes attrs =
148 Attributes::fromElement(host->getContext()->get("radius"));
150 .arg(host->toText())
151 .arg(attrs.toText());
152 // 3 cases:
153 // - ip address (is in the host).
154 // - framed pool (put in the query).
155 // - class (todo).
156 if (!host->getIPv4Reservation().isV4Zero()) {
157 // Done!
158 return (handler);
159 }
160 ConstAttributePtr framed_pool = attrs.get(PW_FRAMED_POOL);
161 if (framed_pool && (framed_pool->getValueType() == PW_TYPE_STRING)) {
162 query->addClass(framed_pool->toString());
163 // Done!
164 return (handler);
165 }
166 // todo: class.
167 ConstAttributePtr class_ = attrs.get(PW_CLASS);
168 if (class_ && (class_->getValueType() == PW_TYPE_STRING)) {
169 // todo
170 return (handler);
171 }
172 return (handler);
173 }
174
175 // Get the pending request.
177 impl.auth_->requests4_.get(id);
178
179 // Conflict?
180 if (pending_request) {
182 .arg(query->getLabel())
183 .arg(text);
185 return (handler);
186 }
187
188 // Too many pending requests.
189 size_t max_requests = impl.auth_->max_pending_requests_;
190 if ((max_requests > 0) && (impl.auth_->requests4_.size() >= max_requests)) {
193 .arg(query->getLabel())
194 .arg(text);
196 return (handler);
197 }
198
199 // Ask the Radius server.
200 handler = impl.auth_->buildAuth(*query, subnet_id, id, text);
201 if (!handler) {
202 // Error was logged.
204 return (handler);
205 }
206
207 // Create a new pending access request.
208 impl.auth_->requests4_.set(id, query);
209
210 return (handler);
211}
212
219RadiusAuthHandlerPtr subnet6Select(CalloutHandle& handle,
220 ConstSubnet6Ptr subnet, Pkt6Ptr query) {
222 MultiThreadingLock lock(impl.auth_->requests6_.mutex_);
223
224 RadiusAuthHandlerPtr handler;
225 uint32_t subnet_id = subnet->getID();
226 uint32_t host_subnet_id =
227 (subnet->getReservationsGlobal() ? SUBNET_ID_GLOBAL : subnet_id);
228 vector<uint8_t> id;
229 string text;
230 if (!impl.auth_->getIdentifier(*query, id, text)) {
231 // What to do?
233 return (handler);
234 }
235
236 // Ask host cache.
237 ConstHostPtr host = HostMgr::instance().get6Any(host_subnet_id,
238 impl.id_type6_,
239 &id[0], id.size());
240 // Check cached subnet reselect.
241 if (host && host->getContext() &&
242 (host->getContext()->getType() == Element::map) &&
243 host->getContext()->contains("subnet-id")) {
244 try {
245 ConstElementPtr reselected = host->getContext()->get("subnet-id");
246 subnet_id = static_cast<uint32_t>(reselected->intValue());
249 .arg(subnet->getID())
250 .arg(subnet_id);
251 // Reselect to null.
252 if (subnet_id == SUBNET_ID_UNUSED) {
253 ConstSubnet6Ptr null_subnet;
254 handle.setArgument("subnet6", null_subnet);
255 return (handler);
256 }
257 // Reselect to an other subnet.
258 uint32_t new_host_subnet_id = host_subnet_id;
259 if (subnet_id != subnet->getID()) {
260 ConstSubnet6Ptr new_subnet =
262 getCfgSubnets6()->getSubnet(subnet_id);
263 if (!new_subnet) {
265 "can't find subnet with id: " << subnet_id);
266 }
267 new_host_subnet_id =
268 (new_subnet->getReservationsGlobal() ?
269 SUBNET_ID_GLOBAL : subnet_id);
270 handle.setArgument("subnet6", new_subnet);
271 }
272 // Get again host cache.
273 if (new_host_subnet_id != host_subnet_id) {
274 host = HostMgr::instance().get6Any(new_host_subnet_id,
275 impl.id_type6_,
276 &id[0], id.size());
277 }
278 } catch (const std::exception&) {
279 // Delete bad entry from cache.
280 HostPtr bad(new Host(*host));
281 static_cast<void>(impl.cache_->remove(bad));
283 return (handler);
284 }
285 }
286
287 // Check cached RADIUS response.
288 if (host && host->getContext() &&
289 (host->getContext()->getType() == Element::map)) {
290 // Yeah! We don't need to ask the Radius server.
291 Attributes attrs =
292 Attributes::fromElement(host->getContext()->get("radius"));
294 .arg(host->toText())
295 .arg(attrs.toText());
296 // 4 cases:
297 // - ip address (is in the host).
298 // - delegated prefix (is in the host).
299 // - framed pool (put in the query).
300 // - class (todo).
301 if (host->hasIPv6Reservation()) {
302 // Done!
303 return (handler);
304 }
305 ConstAttributePtr framed_pool = attrs.get(PW_FRAMED_POOL);
306 if (framed_pool && (framed_pool->getValueType() == PW_TYPE_STRING)) {
307 query->addClass(framed_pool->toString());
308 // Done!
309 return (handler);
310 }
311 // todo: class.
312 ConstAttributePtr class_ = attrs.get(PW_CLASS);
313 if (class_ && (class_->getValueType() == PW_TYPE_STRING)) {
314 // todo
315 return (handler);
316 }
317 return (handler);
318 }
319
320 // Get the pending request.
322 impl.auth_->requests6_.get(id);
323
324 // Conflict?
325 if (pending_request) {
327 .arg(query->getLabel())
328 .arg(text);
330 return (handler);
331 }
332
333 // Too many pending requests.
334 size_t max_requests = impl.auth_->max_pending_requests_;
335 if ((max_requests > 0) && (impl.auth_->requests6_.size() >= max_requests)) {
338 .arg(query->getLabel())
339 .arg(text);
341 return (handler);
342 }
343
344 // Ask the Radius server.
345 handler = impl.auth_->buildAuth(*query, subnet_id, id, text);
346 if (!handler) {
347 // Error was logged.
349 return (handler);
350 }
351
352 // Create a new pending access request.
353 impl.auth_->requests6_.set(id, query);
354
355 return (handler);
356}
357
358} // end of anonymous namespace
359
360extern "C" {
361
366int load(LibraryHandle& handle) {
367
368 try {
369 // Make the hook library not loadable by d2 or ca.
370 uint16_t family = CfgMgr::instance().getFamily();
371 const std::string& proc_name = Daemon::getProcName();
372 if (family == AF_INET) {
373 if (proc_name != "kea-dhcp4") {
374 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
375 << ", expected kea-dhcp4");
376 }
377 } else {
378 if (proc_name != "kea-dhcp6") {
379 isc_throw(isc::Unexpected, "Bad process name: " << proc_name
380 << ", expected kea-dhcp6");
381 }
382 }
383
384 // Get and decode configuration.
385 ElementPtr config = getConfig(handle);
387 impl.init(config);
388 } catch (const std::exception& ex) {
390 .arg(ex.what());
391 return (CONTROL_RESULT_ERROR);
392 }
393
395 return (CONTROL_RESULT_SUCCESS);
396}
397
407
412 return (1);
413}
414
426
438
449 if (status == CalloutHandle::NEXT_STEP_DROP ||
451 return (0);
452 }
453
454 InHook in_hook;
456 if (!impl.auth_ || !impl.checkHostBackends()) {
457 return (CONTROL_RESULT_SUCCESS);
458 }
459 Pkt4Ptr query;
460 handle.getArgument("query4", query);
461 ConstSubnet4Ptr subnet;
462 handle.getArgument("subnet4", subnet);
463 if (!query || !subnet || (subnet->getID() == 0)) {
464 return (CONTROL_RESULT_SUCCESS);
465 }
466 ParkingLotHandlePtr parking_lot = handle.getParkingLotHandlePtr();
467 parking_lot->reference(query);
468 try {
469 RadiusAuthHandlerPtr handler = subnet4Select(handle, subnet, query);
470 if (!handler) {
471 parking_lot->dereference(query);
472 return (CONTROL_RESULT_SUCCESS);
473 }
474 handler->start();
476 } catch (...) {
477 parking_lot->dereference(query);
479 }
480
481 return (CONTROL_RESULT_SUCCESS);
482}
483
494 if (status == CalloutHandle::NEXT_STEP_DROP ||
496 return (CONTROL_RESULT_SUCCESS);
497 }
498
499 InHook in_hook;
501 if (!impl.auth_ || !impl.checkHostBackends()) {
502 return (CONTROL_RESULT_SUCCESS);
503 }
504 Pkt6Ptr query;
505 handle.getArgument("query6", query);
506 ConstSubnet6Ptr subnet;
507 handle.getArgument("subnet6", subnet);
508 if (!query || !subnet || (subnet->getID() == 0)) {
509 return (CONTROL_RESULT_SUCCESS);
510 }
511 ParkingLotHandlePtr parking_lot = handle.getParkingLotHandlePtr();
512 parking_lot->reference(query);
513 try {
514 RadiusAuthHandlerPtr handler = subnet6Select(handle, subnet, query);
515 if (!handler) {
516 parking_lot->dereference(query);
517 return (CONTROL_RESULT_SUCCESS);
518 }
519 handler->start();
521 } catch (...) {
522 parking_lot->dereference(query);
524 }
525
526 return (CONTROL_RESULT_SUCCESS);
527}
528
538 if (status == CalloutHandle::NEXT_STEP_DROP ||
540 return (0);
541 }
542
543 InHook in_hook;
545 if (!impl.acct_ || !impl.getIOContext()) {
546 return (CONTROL_RESULT_SUCCESS);
547 }
548
549 bool fake_allocation = false;
550 handle.getArgument("fake_allocation", fake_allocation);
551 if (fake_allocation) {
552 // If this is a discover, there's nothing to do
553 return (CONTROL_RESULT_SUCCESS);
554 }
555
556 Lease4Ptr lease;
557 handle.getArgument("lease4", lease);
558 try {
559 // Start the Accounting-Request transmission.
560 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_CREATE);
561 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
562 } catch (const std::exception& ex) {
564 .arg("lease4_select")
565 .arg(ex.what());
566 }
567 return (CONTROL_RESULT_SUCCESS);
568}
569
579 if (status == CalloutHandle::NEXT_STEP_DROP ||
581 return (0);
582 }
583
584 InHook in_hook;
586 if (!impl.acct_ || !impl.getIOContext()) {
587 return (CONTROL_RESULT_SUCCESS);
588 }
589 Lease4Ptr lease;
590 handle.getArgument("lease4", lease);
591 try {
592 // Start the Accounting-Request transmission.
593 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_RENEW);
594 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
595 } catch (const std::exception& ex) {
597 .arg("lease4_renew")
598 .arg(ex.what());
599 }
600 return (CONTROL_RESULT_SUCCESS);
601}
602
612 if (status == CalloutHandle::NEXT_STEP_DROP ||
614 return (0);
615 }
616
617 InHook in_hook;
619 if (!impl.acct_ || !impl.getIOContext()) {
620 return (CONTROL_RESULT_SUCCESS);
621 }
622 Lease4Ptr lease;
623 handle.getArgument("lease4", lease);
624 try {
625 // Start the Accounting-Request transmission.
626 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_RELEASE);
627 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
628 } catch (const std::exception& ex) {
630 .arg("lease4_release")
631 .arg(ex.what());
632 }
633 return (CONTROL_RESULT_SUCCESS);
634}
635
645 if (status == CalloutHandle::NEXT_STEP_DROP ||
647 return (0);
648 }
649
650 InHook in_hook;
652 if (!impl.acct_ || !impl.getIOContext()) {
653 return (CONTROL_RESULT_SUCCESS);
654 }
655 Lease4Ptr lease;
656 handle.getArgument("lease4", lease);
657 try {
658 // Start the Accounting-Request transmission.
659 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_DECLINE);
660 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
661 } catch (const std::exception& ex) {
663 .arg("lease4_decline")
664 .arg(ex.what());
665 }
666 return (CONTROL_RESULT_SUCCESS);
667}
668
675 if (status == CalloutHandle::NEXT_STEP_DROP ||
677 return (0);
678 }
679
680 InHook in_hook;
682 if (!impl.acct_ || !impl.getIOContext()) {
683 return (CONTROL_RESULT_SUCCESS);
684 }
685 Lease4Ptr lease;
686 handle.getArgument("lease4", lease);
687 try {
688 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_EXPIRE);
689 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
690 } catch (const std::exception& ex) {
692 .arg("lease4_expire")
693 .arg(ex.what());
694 }
695 return (CONTROL_RESULT_SUCCESS);
696}
697
704 if (status == CalloutHandle::NEXT_STEP_DROP ||
706 return (0);
707 }
708
709 InHook in_hook;
711 if (!impl.acct_ || !impl.getIOContext()) {
712 return (CONTROL_RESULT_SUCCESS);
713 }
714 bool fake_allocation;
715 handle.getArgument("fake_allocation", fake_allocation);
716 if (fake_allocation) {
717 return (CONTROL_RESULT_SUCCESS);
718 }
719 Lease6Ptr lease;
720 handle.getArgument("lease6", lease);
721 try {
722 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_CREATE);
723 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
724 } catch (const std::exception& ex) {
726 .arg("lease6_select")
727 .arg(ex.what());
728 }
729 return (CONTROL_RESULT_SUCCESS);
730}
731
738 if (status == CalloutHandle::NEXT_STEP_DROP ||
740 return (0);
741 }
742
743 InHook in_hook;
745 if (!impl.acct_ || !impl.getIOContext()) {
746 return (CONTROL_RESULT_SUCCESS);
747 }
748 Lease6Ptr lease;
749 handle.getArgument("lease6", lease);
750 try {
751 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_RENEW);
752 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
753 } catch (const std::exception& ex) {
755 .arg("lease6_renew")
756 .arg(ex.what());
757 }
758 return (CONTROL_RESULT_SUCCESS);
759}
760
767 if (status == CalloutHandle::NEXT_STEP_DROP ||
769 return (0);
770 }
771
772 InHook in_hook;
774 if (!impl.acct_ || !impl.getIOContext()) {
775 return (CONTROL_RESULT_SUCCESS);
776 }
777 Lease6Ptr lease;
778 handle.getArgument("lease6", lease);
779 try {
780 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_REBIND);
781 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
782 } catch (const std::exception& ex) {
784 .arg("lease6_rebind")
785 .arg(ex.what());
786 }
787 return (CONTROL_RESULT_SUCCESS);
788}
789
796 if (status == CalloutHandle::NEXT_STEP_DROP ||
798 return (0);
799 }
800
801 InHook in_hook;
803 if (!impl.acct_ || !impl.getIOContext()) {
804 return (CONTROL_RESULT_SUCCESS);
805 }
806 Lease6Ptr lease;
807 handle.getArgument("lease6", lease);
808 try {
809 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_RELEASE);
810 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
811 } catch (const std::exception& ex) {
813 .arg("lease6_release")
814 .arg(ex.what());
815 }
816 return (CONTROL_RESULT_SUCCESS);
817}
818
825 if (status == CalloutHandle::NEXT_STEP_DROP ||
827 return (0);
828 }
829
830 InHook in_hook;
832 if (!impl.acct_ || !impl.getIOContext()) {
833 return (CONTROL_RESULT_SUCCESS);
834 }
835 Lease6Ptr lease;
836 handle.getArgument("lease6", lease);
837 try {
838 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_DECLINE);
839 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
840 } catch (const std::exception& ex) {
842 .arg("lease6_decline")
843 .arg(ex.what());
844 }
845 return (CONTROL_RESULT_SUCCESS);
846}
847
854 if (status == CalloutHandle::NEXT_STEP_DROP ||
856 return (0);
857 }
858
859 InHook in_hook;
861 if (!impl.acct_ || !impl.getIOContext()) {
862 return (CONTROL_RESULT_SUCCESS);
863 }
864 Lease6Ptr lease;
865 handle.getArgument("lease6", lease);
866 try {
867 RadiusAcctHandlerPtr handler = impl.acct_->buildAcct(lease, EVENT_EXPIRE);
868 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync, handler));
869 } catch (const std::exception& ex) {
871 .arg("lease6_expire")
872 .arg(ex.what());
873 }
874 return (CONTROL_RESULT_SUCCESS);
875}
876
885 InHook in_hook;
887 if (!impl.acct_ || !impl.getIOContext()) {
888 return (CONTROL_RESULT_SUCCESS);
889 }
890 string name;
891 ConstElementPtr arguments;
892 ConstElementPtr response;
893 try {
894 handle.getArgument("name", name);
895 handle.getArgument("arguments", arguments);
896 handle.getArgument("response", response);
897 if (!arguments || !response) {
898 // "arguments" and "response" are required for all further actions.
899 // Stop here if they are not set.
900 return (CONTROL_RESULT_SUCCESS);
901 }
902
903 int result = SimpleParser::getInteger(response, "result");
904 if (result != 0) {
905 // Command has failed.
906 return (CONTROL_RESULT_SUCCESS);
907 }
908
909 // Handle peer updates?
910 const ConstElementPtr origin(arguments->get("origin"));
911 if (origin) {
912 // "origin" has a dynamic type. There are commands like ha-sync-complete-notify that set
913 // it to an integer. For simplicity, treat those cases like it is not coming from an HA
914 // partner for now and it will get filtered out by name further down below. We only care
915 // about lease updates.
916 const bool is_from_ha_partner(origin->getType() == Element::string &&
917 origin->stringValue() == "ha-partner");
918 if (!impl.acct_->peer_updates_ && is_from_ha_partner) {
919 return (CONTROL_RESULT_SUCCESS);
920 }
921 }
922
923 RadiusAcctHandlerPtr handler;
924 if (name == "lease4-add") {
925 handler = impl.acct_->buildAcct4(arguments, EVENT_ADD);
926 } else if (name == "lease4-update") {
927 handler = impl.acct_->buildAcct4(arguments, EVENT_UPDATE);
928 } else if (name== "lease4-del") {
929 handler = impl.acct_->buildAcct4(arguments, EVENT_DEL);
930 } else if (name == "lease6-add") {
931 handler = impl.acct_->buildAcct6(arguments, EVENT_ADD);
932 } else if (name == "lease6-update") {
933 handler = impl.acct_->buildAcct6(arguments, EVENT_UPDATE);
934 } else if (name== "lease6-del") {
935 handler = impl.acct_->buildAcct6(arguments, EVENT_DEL);
936 }
937 if (handler) {
938 impl.getIOContext()->post(std::bind(&RadiusAccounting::runAsync,
939 handler));
940 }
941 } catch (const std::exception& ex) {
942 ostringstream ss;
943 ss << "command_processed: " << name;
945 .arg(ss.str())
946 .arg(ex.what());
947 }
948 return (CONTROL_RESULT_SUCCESS);
949}
950
951} // 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:147
@ string
Definition data.h:144
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
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:151
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
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.
#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:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
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.