Kea 3.1.3
radius_parsers.cc
Go to the documentation of this file.
1// Copyright (C) 2018-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#include <config.h>
8
9#include <radius_parsers.h>
10#include <radius_log.h>
11
12#include <cc/data.h>
14#include <dhcpsrv/cfgmgr.h>
15#include <eval/eval_context.h>
16#include <util/encode/encode.h>
17
18#include <limits>
19#include <string>
20#include <cstdlib>
21#include <cstring>
22#include <sstream>
23
24using namespace std;
25using namespace isc;
26using namespace isc::asiolink;
27using namespace isc::data;
28using namespace isc::dhcp;
29using namespace isc::util;
30
31namespace isc {
32namespace radius {
33
35const set<string>
37 "access", "accounting", // services
38 "bindaddr", "canonical-mac-address", "client-id-pop0",
39 "client-id-printable", "deadtime", "dictionary",
40 "extract-duid", "identifier-type4", "identifier-type6",
41 "nas-ports", "realm",
42 "reselect-subnet-address", "reselect-subnet-pool",
43 "retries", "session-history", "thread-pool-size", "timeout",
44 "comment" // not saved for toElement
45};
46
49 { "bindaddr", Element::string, "*" },
50 { "canonical-mac-address", Element::boolean, "false" },
51 { "client-id-pop0", Element::boolean, "false" },
52 { "client-id-printable", Element::boolean, "false" },
53 { "deadtime", Element::integer, "0" },
54 { "dictionary", Element::string, DICTIONARY },
55 { "extract-duid", Element::boolean, "true" },
56 { "identifier-type4", Element::string, "client-id" },
57 { "identifier-type6", Element::string, "duid" },
58 { "realm", Element::string, "" },
59 { "reselect-subnet-address", Element::boolean, "false" },
60 { "reselect-subnet-pool", Element::boolean, "false" },
61 { "retries", Element::integer, "3" },
62 { "session-history", Element::string, "" },
63 { "thread-pool-size", Element::integer, "0" },
64 { "timeout", Element::integer, "10" }
65};
66
69 { PW_USER_NAME, "User-Name", PW_TYPE_STRING },
70 { PW_USER_PASSWORD, "User-Password", PW_TYPE_STRING },
71 { PW_NAS_IP_ADDRESS, "NAS-IP-Address", PW_TYPE_IPADDR },
72 { PW_NAS_PORT, "NAS-Port", PW_TYPE_INTEGER },
73 { PW_SERVICE_TYPE, "Service-Type", PW_TYPE_INTEGER },
74 { PW_FRAMED_IP_ADDRESS, "Framed-IP-Address", PW_TYPE_IPADDR },
75 { PW_REPLY_MESSAGE, "Reply-Message", PW_TYPE_STRING },
76 { PW_CLASS, "Class", PW_TYPE_STRING },
77 { PW_VENDOR_SPECIFIC, "Vendor-Specific", PW_TYPE_VSA },
78 { PW_CALLING_STATION_ID, "Calling-Station-Id", PW_TYPE_STRING },
79 { PW_ACCT_STATUS_TYPE, "Acct-Status-Type", PW_TYPE_INTEGER },
80 { PW_ACCT_DELAY_TIME, "Acct-Delay-Time", PW_TYPE_INTEGER },
81 { PW_ACCT_SESSION_ID, "Acct-Session-Id", PW_TYPE_STRING },
82 { PW_FRAMED_POOL, "Framed-Pool", PW_TYPE_STRING },
83 { PW_NAS_IPV6_ADDRESS, "NAS-IPv6-Address", PW_TYPE_IPV6ADDR },
84 { PW_DELEGATED_IPV6_PREFIX, "Delegated-IPv6-Prefix", PW_TYPE_IPV6PREFIX },
85 { PW_FRAMED_IPV6_ADDRESS, "Framed-IPv6-Address", PW_TYPE_IPV6ADDR }
86};
87
90 { "data", Element::string, "" },
91 { "expr", Element::string, "" },
92 { "raw", Element::string, "" },
93 { "vendor", Element::string, "" }
94};
95
96void
98 try {
100
101 // Set defaults.
103
104 // dictionary (do it first).
105 const ConstElementPtr& dictionary = config->get("dictionary");
106 riref.dictionary_ = dictionary->stringValue();
107
108 // Read the dictionary
109 if (!AttrDefs::instance().getByType(1)) {
110 uint32_t vendor = 0;
111 try {
113 } catch (const exception& ex) {
114 isc_throw(BadValue, "can't read radius dictionary: "
115 << ex.what());
116 }
117 if (vendor != 0) {
118 isc_throw(BadValue, "vendor definitions were not properly "
119 << "closed: vendor " << vendor << " is still open");
120 }
121 }
122
123 // Check it.
125
126 // bindaddr.
127 const ConstElementPtr& bindaddr = config->get("bindaddr");
128 riref.bindaddr_ = bindaddr->stringValue();
129
130 // canonical-mac-address.
131 const ConstElementPtr& canonical = config->get("canonical-mac-address");
132 riref.canonical_mac_address_ = canonical->boolValue();
133
134 // client-id-pop0.
135 const ConstElementPtr& pop0 = config->get("client-id-pop0");
136 riref.clientid_pop0_ = pop0->boolValue();
137
138 // client-id-printable.
139 const ConstElementPtr& try_printable = config->get("client-id-printable");
140 riref.clientid_printable_ = try_printable->boolValue();
141
142 // deadtime.
143 const ConstElementPtr& deadtime = config->get("deadtime");
144 int64_t deadtime64 = deadtime->intValue();
145 if ((deadtime64 < 0) ||
146 (deadtime64 > numeric_limits<unsigned>::max())) {
147 isc_throw(OutOfRange, "bad deadtime " << deadtime64
148 << " not in [0.."
149 << numeric_limits<unsigned>::max() << "]");
150 }
151 riref.deadtime_ = static_cast<unsigned>(deadtime64);
152
153 // extract-duid.
154 const ConstElementPtr& rfc4361 = config->get("extract-duid");
155 riref.extract_duid_ = rfc4361->boolValue();
156
157 // identifier-type4.
158 const ConstElementPtr& id_type4 = config->get("identifier-type4");
159 riref.id_type4_ = Host::getIdentifierType(id_type4->stringValue());
160
161 // identifier-type6.
162 const ConstElementPtr& id_type6 = config->get("identifier-type6");
163 riref.id_type6_ = Host::getIdentifierType(id_type6->stringValue());
164
165 // realm. Ignored.
166
167 // reselect-subnet-address.
168 const ConstElementPtr& resel_addr =
169 config->get("reselect-subnet-address");
170 riref.reselect_subnet_address_ = resel_addr->boolValue();
171
172 // reselect-subnet-pool.
173 const ConstElementPtr& resel_pool =
174 config->get("reselect-subnet-pool");
175 riref.reselect_subnet_pool_ = resel_pool->boolValue();
176
177 // retries.
178 const ConstElementPtr& retries = config->get("retries");
179 int64_t retries64 = retries->intValue();
180 if ((retries64 < 0) ||
181 (retries64 > numeric_limits<unsigned>::max())) {
182 isc_throw(OutOfRange, "bad retries " << retries64
183 << " not in [0.."
184 << numeric_limits<unsigned>::max() << "]");
185 }
186 riref.retries_ = static_cast<unsigned>(retries64);
187
188 // session-history.
189 const ConstElementPtr& session_history = config->get("session-history");
190 riref.session_history_filename_ = session_history->stringValue();
191
192 // thread-pool-size.
193 const ConstElementPtr& thread_pool_size = config->get("thread-pool-size");
194 riref.thread_pool_size_ = thread_pool_size->intValue();
195
196 // timeout.
197 const ConstElementPtr& timeout = config->get("timeout");
198 int64_t timeout64 = timeout->intValue();
199 if ((timeout64 < 0) ||
200 (timeout64 > numeric_limits<long>::max() / 1000)) {
201 isc_throw(OutOfRange, "bad timeout " << timeout64
202 << " not in [0.."
203 << (numeric_limits<long>::max() / 1000) << "]");
204 }
205 riref.timeout_ = static_cast<unsigned>(timeout64);
206
207 // Access service.
208 const ConstElementPtr& access = config->get("access");
209 if (access) {
210 RadiusServiceParser parser;
211 parser.parse(riref.auth_, access);
212 parser.checkAttributes(riref.auth_);
213 }
214
215 // Accounting service.
216 const ConstElementPtr& accounting = config->get("accounting");
217 if (accounting) {
218 RadiusServiceParser parser;
219 parser.parse(riref.acct_, accounting);
220 parser.checkAttributes(riref.acct_);
221 }
222
223 // nas-ports (last so we can return when it is not present.
224 const ConstElementPtr& nas_ports = config->get("nas-ports");
225 if (!nas_ports) {
226 return;
227 }
228 for (auto const& entry : nas_ports->listValue()) {
229 // port is mandatory.
230 const ConstElementPtr& port = entry->get("port");
231 if (!port) {
232 isc_throw(BadValue, "missing port in nas-ports entry: "
233 << entry->str());
234 }
235
236 // By subnet-id.
237 const ConstElementPtr& id = entry->get("subnet-id");
238 if (id) {
239 riref.remap_[id->intValue()] = port->intValue();
240 continue;
241 }
242
243 // By subnet-prefix (to be resolved into an ID).
244 const ConstElementPtr& prefix = entry->get("subnet-prefix");
245 if (prefix) {
246 if (CfgMgr::instance().getFamily() == AF_INET) {
247 auto subnet = CfgMgr::instance().getStagingCfg()->
248 getCfgSubnets4()->getByPrefix(prefix->stringValue());
249 if (!subnet) {
250 isc_throw(BadValue, "can't find subnet for "
251 << entry->str());
252 }
253 riref.remap_[subnet->getID()] = port->intValue();
254 continue;
255 } else {
256 auto subnet = CfgMgr::instance().getStagingCfg()->
257 getCfgSubnets6()->getByPrefix(prefix->stringValue());
258 if (!subnet) {
259 isc_throw(BadValue, "can't find subnet for "
260 << entry->str());
261 }
262 riref.remap_[subnet->getID()] = port->intValue();
263 continue;
264 }
265 }
266
267 // By shared-network-name (to be resolved, add all subnets).
268 const ConstElementPtr& name = entry->get("shared-network-name");
269 if (name) {
270 if (CfgMgr::instance().getFamily() == AF_INET) {
271 auto network = CfgMgr::instance().getStagingCfg()->
272 getCfgSharedNetworks4()->getByName(name->stringValue());
273 if (!network) {
274 isc_throw(BadValue, "can't find shared network for "
275 << entry->str());
276 }
277 for (auto const& subnet : *network->getAllSubnets()) {
278 riref.remap_[subnet->getID()] = port->intValue();
279 }
280 continue;
281 } else {
282 auto network = CfgMgr::instance().getStagingCfg()->
283 getCfgSharedNetworks6()->getByName(name->stringValue());
284 if (!network) {
285 isc_throw(BadValue, "can't find shared network for "
286 << entry->str());
287 }
288 for (auto const& subnet : *network->getAllSubnets()) {
289 riref.remap_[subnet->getID()] = port->intValue();
290 }
291 continue;
292 }
293 }
294
295 // Unknown selector.
296 if (entry->size() > 1) {
297 isc_throw(BadValue, "unknown selector in " << entry->str());
298 }
299
300 // Default is in subnet 0 (SUBNET_ID_DEFAULT).
301 riref.remap_[SUBNET_ID_DEFAULT] = port->intValue();
302 }
303
304 } catch (const ConfigError&) {
305 throw;
306 } catch (const std::exception& ex) {
307 isc_throw(ConfigError, ex.what());
308 }
309}
310
312const set<string>
314 "servers", "attributes", "peer-updates", "max-pending-requests"
315};
316
317void
319 const ConstElementPtr& srv_cfg) {
320 try {
321 // map type.
322 if (srv_cfg->getType() != Element::map) {
323 isc_throw(BadValue, "expected service to be map, but got "
324 << Element::typeToName(srv_cfg->getType())
325 << " instead");
326 }
327
328 // keywords.
329 const set<string> keywords = RadiusServiceParser::SERVICE_KEYWORDS;
330 for (auto const& entry : srv_cfg->mapValue()) {
331 if (keywords.count(entry.first) == 0) {
332 isc_throw(BadValue, "unknown service parameter: "
333 << entry.first);
334 }
335 }
336
337 // servers.
338 const ConstElementPtr& servers = srv_cfg->get("servers");
339 if (servers) {
341 parser.parse(service, servers);
342 if (!service->servers_.empty()) {
343 service->enabled_ = true;
344 }
345 }
346
347 // attributes.
348 const ConstElementPtr& attributes = srv_cfg->get("attributes");
349 if (attributes) {
351 parser.parse(service, attributes);
352 }
353
354 // peer-updates.
355 const ConstElementPtr& peer_updates = srv_cfg->get("peer-updates");
356 if (peer_updates) {
357 if (service->name_ == "access") {
358 isc_throw(BadValue, "peer-updates configured for the access service, but it is "
359 "only supported for the accounting service");
360 }
361 if (peer_updates->getType() != Element::boolean) {
362 isc_throw(BadValue, "expected peer-updates to be boolean, but got "
363 << Element::typeToName(peer_updates->getType())
364 << " instead");
365 }
366 service->peer_updates_ = peer_updates->boolValue();
367 }
368
369 // max-pending-requests.
370 const ConstElementPtr& max_pending_requests =
371 srv_cfg->get("max-pending-requests");
372 if (max_pending_requests) {
373 if (service->name_ == "accounting") {
374 isc_throw(BadValue, "max-pending-requests configured for the "
375 << "accounting service, but it is only supported "
376 << "for the access service");
377 }
378 if (max_pending_requests->getType() != Element::integer) {
379 isc_throw(BadValue, "expected max-pending-requests to be "
380 << "integer, but got "
381 << Element::typeToName(max_pending_requests->getType())
382 << " instead");
383 }
384 if (max_pending_requests->intValue() < 0) {
385 isc_throw(BadValue, "expected max-pending-requests to be "
386 << "positive, but got "
387 << max_pending_requests->intValue()
388 << " instead");
389 }
390 service->max_pending_requests_ = max_pending_requests->intValue();
391 }
392 } catch (const std::exception& ex) {
393 isc_throw(ConfigError, ex.what() << " (parsing "
394 << service->name_ << ")");
395 }
396}
397
398void
400 if (!service->enabled_) {
401 return;
402 }
403
404 const CfgAttributes& cfg_attrs = service->attributes_;
405 const Attributes& attrs = cfg_attrs.getAll();
406 if (service->name_ == "access") {
407 // Nothing yet.
408 } else if (service->name_ == "accounting") {
409 // Expressions have no associated attributes.
410 if (cfg_attrs.size() > attrs.size()) {
412 "Expressions are not yet supported in accounting");
413 }
414 }
415}
416
417void
419 const ConstElementPtr& srv_list) {
420 for (auto const& srv : srv_list->listValue()) {
421 RadiusServerParser parser;
422 parser.parse(service, srv);
423 }
424}
425
426void
428 const ElementPtr& server) {
430
431 // Details will be logged.
432 ostringstream msg;
433
434 // Peer address (was name).
435 IOAddress peer_addr("::");
436 const string& name = getString(server, "name");
437 try {
438 peer_addr = IOAddress(name);
439 } catch (const Exception&) {
440 try {
441 peer_addr = Server::getAddress(name);
442 } catch (const Exception& ex) {
443 isc_throw(ConfigError, "can't resolve '" << name << "': "
444 << ex.what());
445 }
446 }
447 msg << "peer-addr=" << peer_addr.toText();
448
449 // port.
450 uint16_t port;
451 if (server->contains("port")) {
452 port = getUint16(server, "port");
453 } else if (service->name_ == "access") {
454 port = PW_AUTH_UDP_PORT;
455 } else {
456 port = PW_ACCT_UDP_PORT;
457 }
458 msg << " port=" << port;
459
460 // Local address.
461 IOAddress local_addr("::");
462 const string& local = riref.bindaddr_;
463 if (local != "*") {
464 try {
465 local_addr = IOAddress(local);
466 } catch (const Exception& ex) {
467 isc_throw(ConfigError, "bad local address '" << local << "': "
468 << ex.what());
469 }
470 } else {
471 try {
472 local_addr = Server::getSrcAddress(peer_addr);
473 } catch (const Exception& ex) {
474 isc_throw(ConfigError, "can't get local address: " << ex.what());
475 }
476 }
477 msg << " local_addr=" << local_addr;
478
479 // secret.
480 const string& secret = getString(server, "secret");
481 try {
483 } catch (const DefaultCredential& ex) {
484 isc_throw(ConfigError, "illegal use of a default secret");
485 }
486 msg << " secret=*****";
487
488 try {
489 ServerPtr srv(new Server(peer_addr, port, local_addr, secret,
490 riref.timeout_, riref.deadtime_));
491 service->servers_.push_back(srv);
492 } catch (const Exception& ex) {
493 isc_throw(ConfigError, "can't create " << service->name_
494 << " server '" << msg.str() << "': " << ex.what());
495 }
496
497 // Done.
499 .arg(service->name_)
500 .arg(msg.str());
501}
502
503void
505 const ConstElementPtr& attr_list) {
506 for (auto const& attr : attr_list->listValue()) {
508 parser.parse(service, attr);
509 }
510}
511
512void
514 const ElementPtr& attr) {
515 AttrDefPtr def;
516
517 // Set defaults.
519
520 // vendor.
521 uint32_t vendor = 0;
522 const ConstElementPtr& vendor_elem = attr->get("vendor");
523 if (!vendor_elem) {
524 // Should not happen as it is added by setDefaults.
525 isc_throw(Unexpected, "no vendor parameter");
526 } else if (vendor_elem->getType() != Element::string) {
527 // Expected to be a common error.
528 isc_throw(TypeError, "vendor parameter must be a string");
529 }
530 const string& vendor_txt = vendor_elem->stringValue();
531 if (!vendor_txt.empty()) {
532 IntCstDefPtr vendor_cst =
534 if (vendor_cst) {
535 vendor = vendor_cst->value_;
536 } else {
537 try {
538 int64_t val = boost::lexical_cast<int64_t>(vendor_txt);
539 if ((val < numeric_limits<int32_t>::min()) ||
540 (val > numeric_limits<uint32_t>::max())) {
541 isc_throw(Unexpected, "not 32 bit " << vendor_txt);
542 }
543 vendor = static_cast<uint32_t>(val);
544 } catch (...) {
545 isc_throw(ConfigError, "can't parse vendor '"
546 << vendor_txt << "'");
547 }
548 }
549 }
550
551 // name.
552 const ConstElementPtr& name = attr->get("name");
553 if (name) {
554 if (name->stringValue().empty()) {
555 isc_throw(ConfigError, "attribute name is empty");
556 }
557 def = AttrDefs::instance().getByName(name->stringValue(), vendor);
558 if (!def) {
559 ostringstream msg;
560 msg << "attribute '" << name->stringValue() << "'";
561 if (vendor != 0) {
562 msg << " in vendor '" << vendor_txt << "'";
563 }
564 msg << " is unknown";
565 isc_throw(ConfigError, msg.str());
566 }
567 }
568
569 // type.
570 const ConstElementPtr& type = attr->get("type");
571 if (type) {
572 if ((type->intValue() < 0) || (type->intValue() > 255)) {
573 isc_throw(ConfigError, "out of range attribute type "
574 << type->intValue());
575 }
576 uint8_t attrib = static_cast<uint8_t>(type->intValue());
577 if (def && (def->type_ != attrib)) {
578 ostringstream msg;
579 msg << "'" << name->stringValue() << "' attribute";
580 if (vendor != 0) {
581 msg << " in vendor '" << vendor_txt << "'";
582 }
583 msg << " has type " << static_cast<unsigned>(def->type_)
584 << ", not " << static_cast<unsigned>(attrib);
585 isc_throw(ConfigError, msg.str());
586 }
587 if (!def) {
588 def = AttrDefs::instance().getByType(attrib, vendor);
589 }
590 if (!def) {
591 ostringstream msg;
592 msg << "attribute type " << static_cast<unsigned>(attrib);
593 if (vendor != 0) {
594 msg << " in vendor '" << vendor_txt << "'";
595 }
596 msg << " is unknown";
597 isc_throw(ConfigError, msg.str());
598 }
599 }
600
601 // name or type are required.
602 if (!def) {
603 isc_throw(ConfigError, "name or type are required");
604 }
605
606 // data.
607 const string& data_txt = getString(attr, "data");
608
609 // raw.
610 const string& raw_txt = getString(attr, "raw");
611
612 // expr.
613 const string& expr_txt = getString(attr, "expr");
614
616
617 ExpressionPtr expression;
618 if (!expr_txt.empty()) {
619 if (!data_txt.empty() || !raw_txt.empty()) {
620 isc_throw(ConfigError, "data, raw and expr are exclusive");
621 }
622 Option::Universe universe;
623 if (CfgMgr::instance().getFamily() == AF_INET) {
624 universe = Option::V4;
625 } else {
626 universe = Option::V6;
627 }
628 try {
629 EvalContext eval_ctx(universe);
630 eval_ctx.parseString(expr_txt, EvalContext::PARSER_STRING);
631 expression.reset(new Expression());
632 *expression = eval_ctx.expression_;
633 } catch (const std::exception& ex) {
634 isc_throw(ConfigError, "expression: [" << expr_txt
635 << "] error: " << ex.what() << " for "
636 << def->name_ << " attribute");
637 }
638
639 service->attributes_.add(def, AttributePtr(), expression, expr_txt);
640 } else if (!raw_txt.empty()) {
641 if (!data_txt.empty()) {
642 isc_throw(ConfigError, "data and raw are exclusive");
643 }
644 // The decodeHex function expects that the string contains an
645 // even number of digits. If we don't meet this requirement,
646 // we have to insert a leading 0.
647 string padded = raw_txt;
648 if ((padded.size() % 2) != 0) {
649 padded = padded.insert(0, "0");
650 }
651 vector<uint8_t> binary;
652 try {
653 encode::decodeHex(padded, binary);
654 } catch (...) {
655 isc_throw(ConfigError, "can't decode raw: [" << raw_txt
656 << "] for " << def->name_ << " attribute");
657 }
658 try {
659 AttributePtr attribute = Attribute::fromBytes(def, binary);
660 service->attributes_.add(def, attribute);
661 } catch (const Exception& ex) {
662 isc_throw(ConfigError, "can't create " << def->name_
663 << " attribute from raw: [" << raw_txt << "]: "
664 << ex.what());
665 }
666 } else {
667 try {
668 AttributePtr attribute = Attribute::fromText(def, data_txt);
669 service->attributes_.add(def, attribute);
670 } catch (const Exception& ex) {
671 isc_throw(ConfigError, "can't create " << def->name_
672 << " attribute from [" << data_txt << "]: "
673 << ex.what());
674 }
675 }
676}
677
678} // end of namespace isc::radius
679} // end of namespace isc
static std::string typeToName(Element::types type)
Returns the name of the given type as a string.
Definition data.cc:651
@ map
Definition data.h:147
@ integer
Definition data.h:140
@ boolean
Definition data.h:142
@ string
Definition data.h:144
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
An exception that is thrown if an error occurs while configuring any server.
This is a base class for exceptions thrown from the DNS library module.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
A generic exception that is thrown when an unexpected error condition occurs.
Exception thrown on attempt to use a default credential.
static std::string getString(isc::data::ConstElementPtr scope, const std::string &name)
Returns a string parameter from a scope.
uint16_t getUint16(isc::data::ConstElementPtr scope, const std::string &name)
Returns a value converted to uint16_t.
static size_t setDefaults(isc::data::ElementPtr scope, const SimpleDefaults &default_values)
Sets the default values.
A standard Data module exception that is thrown if a function is called for an Element that has a wro...
Definition data.h:36
static CfgMgr & instance()
returns a single instance of Configuration Manager
Definition cfgmgr.cc:29
SrvConfigPtr getStagingCfg()
Returns a pointer to the staging configuration.
Definition cfgmgr.cc:121
IdentifierType getIdentifierType() const
Returns the identifier type.
Definition host.cc:273
Universe
defines option universe DHCPv4 or DHCPv6
Definition option.h:90
Evaluation context, an interface to the expression evaluation.
bool parseString(const std::string &str, ParserType type=PARSER_BOOL)
Run the parser on the string specified.
@ PARSER_STRING
expression is expected to evaluate to string
isc::dhcp::Expression expression_
Parsed expression (output tokens are stored here)
static AttrDefs & instance()
Returns a single instance.
void readDictionary(const std::string &path, uint32_t &vendor, unsigned int depth=0)
Read a dictionary from a file.
AttrDefPtr getByName(const std::string &name, const uint32_t vendor=0) const
Get attribute definition by name and vendor.
void checkStandardDefs(const AttrDefList &defs) const
Check if a list of standard attribute definitions are available and correct.
AttrDefPtr getByType(const uint8_t type, const uint32_t vendor=0) const
Get attribute definition by type and vendor.
static AttributePtr fromBytes(const std::vector< uint8_t > &bytes)
Generic factories.
static AttributePtr fromText(const AttrDefPtr &def, const std::string &value)
From definition generic factories.
Collection of attributes.
size_t size() const
Returns the number of elements.
Attribute data configuration.
Attributes getAll() const
Get all attributes in the configuration.
size_t size() const
Returns the number of elements.
Attribute list parser for Radius.
void parse(const RadiusServicePtr &service, const data::ConstElementPtr &attr_list)
Parses Radius list of attribute configurations.
Attribute configuration parser for Radius.
static const data::SimpleDefaults ATTRIBUTE_DEFAULTS
Defaults for Radius attribute configuration.
void parse(const RadiusServicePtr &service, const data::ElementPtr &attr)
Parses Radius attribute configuration.
static const std::set< std::string > RADIUS_KEYWORDS
Keywords (aka global configuration entry names).
void parse(data::ElementPtr &config)
Parses Radius configuration.
static const data::SimpleDefaults RADIUS_DEFAULTS
Defaults for Radius configuration.
static const AttrDefList USED_STANDARD_ATTR_DEFS
Needed standard attributes definitions.
Radius hooks library implementation.
Definition radius.h:50
unsigned thread_pool_size_
Thread pool size.
Definition radius.h:196
std::string dictionary_
Dictionary path.
Definition radius.h:148
std::string bindaddr_
bindaddr.
Definition radius.h:166
bool clientid_pop0_
Client Id pop leading zero(s).
Definition radius.h:172
dhcp::Host::IdentifierType id_type4_
Identifier type for IPv4.
Definition radius.h:202
bool reselect_subnet_address_
Reselect subnet using address.
Definition radius.h:187
boost::shared_ptr< RadiusAccess > auth_
Definition radius.h:154
bool extract_duid_
Extract Duid from Client Id.
Definition radius.h:181
unsigned timeout_
Timeout.
Definition radius.h:199
dhcp::Host::IdentifierType id_type6_
Identifier type for IPv6.
Definition radius.h:205
bool canonical_mac_address_
Canonical MAC address.
Definition radius.h:169
unsigned deadtime_
Deadtime.
Definition radius.h:178
boost::shared_ptr< RadiusAccounting > acct_
Pointer to accounting (never null).
Definition radius.h:157
unsigned retries_
Retries.
Definition radius.h:190
std::map< uint32_t, uint32_t > remap_
Subnet ID to NAS port map.
Definition radius.h:151
std::string session_history_filename_
Session history filename.
Definition radius.h:193
bool reselect_subnet_pool_
Reselect subnet using pool.
Definition radius.h:184
bool clientid_printable_
Client Id try printable.
Definition radius.h:175
static RadiusImpl & instance()
RadiusImpl is a singleton class.
Definition radius.cc:37
Server list parser for Radius.
void parse(const RadiusServicePtr &service, const data::ConstElementPtr &srv_list)
Parses Radius server list.
Server parser for Radius.
void parse(const RadiusServicePtr &service, const data::ElementPtr &server)
Parses Radius server.
Service parser for Radius.
static const std::set< std::string > SERVICE_KEYWORDS
Keywords (aka service configuration entry names).
void checkAttributes(const RadiusServicePtr &service)
Check Radius attributes.
void parse(const RadiusServicePtr &service, const data::ConstElementPtr &srv_cfg)
Parses Radius service.
RADIUS server class.
static asiolink::IOAddress getSrcAddress(const asiolink::IOAddress &dest)
Get the source address from a destination address.
static asiolink::IOAddress getAddress(const std::string &name)
Get an address from a name.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
std::vector< SimpleDefault > SimpleDefaults
This specifies all default values in a given scope (e.g. a subnet).
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
boost::shared_ptr< Expression > ExpressionPtr
Definition token.h:31
std::vector< TokenPtr > Expression
This is a structure that holds an expression converted to RPN.
Definition token.h:29
boost::shared_ptr< IntCstDef > IntCstDefPtr
Shared pointers to Integer constant definition.
const isc::log::MessageID RADIUS_SERVER_CONFIGURED
@ PW_DELEGATED_IPV6_PREFIX
ipv6prefix.
@ PW_FRAMED_IPV6_ADDRESS
ipv6addr.
std::list< AttrDef > AttrDefList
List of Attribute definitions.
boost::shared_ptr< AttrDef > AttrDefPtr
Shared pointers to Attribute definition.
boost::shared_ptr< Server > ServerPtr
Type of shared pointers to a RADIUS server object.
boost::shared_ptr< RadiusService > RadiusServicePtr
Type of pointers to Radius service.
boost::shared_ptr< Attribute > AttributePtr
isc::log::Logger radius_logger("radius-hooks")
Radius Logger.
Definition radius_log.h:35
vector< uint8_t > pop0(const ClientIdPtr &client_id)
Pop leading zero in a DHCPv4 client-id.
void decodeHex(const string &encoded_str, vector< uint8_t > &output)
Decode a base16 encoded string into binary data.
Definition encode.cc:367
Defines the logger used by the top-level component of kea-lfc.
static void check(const std::string &value)
Check if the value is a default credential.