Kea 1.5.0
adaptor_config.cc
Go to the documentation of this file.
1// Copyright (C) 2018 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
8
9using namespace std;
10using namespace isc::data;
11using namespace isc::dhcp;
12
13namespace {
14const string DHCP4_SPACE = "dhcp4";
15const string DHCP6_SPACE = "dhcp6";
16}
17
18namespace isc {
19namespace yang {
20
22}
23
25}
26
27bool
29 bool have_ids = true;
30
31 if (!subnets || subnets->empty()) {
32 // There are no subnets defined, so technically there are no ids.
33 // However, the flag is used to determine whether the code later
34 // needs to call assignIDs. Since there is no need to assign
35 // anything, the code returns true here.
36 return (true);
37 }
38
39 // If there are subnets defined, let's go over them one by one and
40 // collect subnet-ids used in them.
41 for (ConstElementPtr subnet : subnets->listValue()) {
42 if (!collectID(subnet, set)) {
43 have_ids = false;
44 }
45 }
46 return (have_ids);
47}
48
49bool
51 SubnetIDSet& set,
52 const string& subsel) {
53 if (!networks || networks->empty()) {
54 // There are no shared networks defined, so technically there are no
55 // ids. However, the flag is used to determine whether the code later
56 // needs to call assignIDs. Since there is no need to assign anything,
57 // the code returns true here.
58 return (true);
59 }
60
61 // This determines if EVERY subnet has subnet-id defined.
62 bool have_ids = true;
63 for (size_t i = 0; i < networks->size(); ++i) {
64 ElementPtr network = networks->getNonConst(i);
65 ConstElementPtr subnets = network->get(subsel);
66 if (subnets) {
67 if (!subnets->empty()) {
68 // If there are subnets, collect their subnet-ids. If any
69 // of them doesn't have a subnet-id, return false.
70 if (!subnetsCollectID(subnets, set)) {
71 have_ids = false;
72 }
73 } else {
74 // There's empty subnets list, so just remove it.
75 network->remove(subsel);
76 }
77 }
78 }
79 return (have_ids);
80}
81
82void
84 SubnetID& next) {
85 if (!subnets || subnets->empty()) {
86 // nothing to do here.
87 return;
88 }
89
90 for (size_t i = 0; i < subnets->size(); ++i) {
91 ElementPtr subnet = subnets->getNonConst(i);
92 assignID(subnet, set, next);
93 }
94}
95
96void
98 SubnetIDSet& set, SubnetID& next,
99 const string& subsel) {
100 if (!networks || networks->empty()) {
101 // nothing to do here.
102 return;
103 }
104
105 for (ConstElementPtr network : networks->listValue()) {
106 ConstElementPtr subnets = network->get(subsel);
107 if (!subnets || subnets->empty()) {
108 continue;
109 }
110
111 for (size_t i = 0; i < subnets->size(); ++i) {
112 ElementPtr subnet = subnets->getNonConst(i);
113 assignID(subnet, set, next);
114 }
115 }
116}
117
118void
120 if (!pools || pools->empty()) {
121 // nothing to do here.
122 return;
123 }
124
125 // Canonize (clean up name, remove extra spaces, add one space where
126 // needed) every pool on the list.
127 for (size_t i = 0; i < pools->size(); ++i) {
128 ElementPtr pool = pools->getNonConst(i);
130 }
131}
132
133void
135 if (!subnets || subnets->empty()) {
136 // nothing to do here.
137 return;
138 }
139
140 for (ConstElementPtr subnet : subnets->listValue()) {
141 sanitizePools(subnet->get("pools"));
142 }
143}
144
145void
147 const string& subsel) {
148 if (!networks || networks->empty()) {
149 // nothing to do here.
150 return;
151 }
152
153 for (ConstElementPtr network : networks->listValue()) {
154 sanitizePoolsInSubnets(network->get(subsel));
155 }
156}
157
158void
160 const string& space,
161 OptionCodes& codes) {
162 if (!defs || defs->empty()) {
163 // nothing to do here.
164 return;
165 }
166
167 // Do sanity checks on every option definition and fill any missing
168 // fields with default values.
169 for (size_t i = 0; i < defs->size(); ++i) {
170 ElementPtr def = defs->getNonConst(i);
171 checkCode(def);
172 checkType(def);
173 setSpace(def, space);
174 collect(def, codes);
175 }
176}
177
178void
180 const string& space,
181 const OptionCodes& codes) {
182 if (!options || options->empty()) {
183 // nothing to do here.
184 return;
185 }
186
187 // Sanitize option-data. The only missing elements we may possibly
188 // need to fill are option space and option code.
189 for (size_t i = 0; i < options->size(); ++i) {
190 ElementPtr option = options->getNonConst(i);
191 setSpace(option, space);
192 setCode(option, codes);
193 }
194}
195
196void
198 const string& space,
199 OptionCodes& codes) {
200 if (!classes || classes->empty()) {
201 // nothing to do here.
202 return;
203 }
204
205 // For every client class defined...
206 for (size_t i = 0; i < classes->size(); ++i) {
207 ElementPtr cclass = classes->getNonConst(i);
208
209 if (space == DHCP4_SPACE) {
210 ConstElementPtr options = cclass->get("option-def");
211 if (options) {
212 if (!options->empty()) {
213 // If present, sanitize it.
214 sanitizeOptionDefList(options, space, codes);
215 } else {
216 // If empty, remove it.
217 cclass->remove("option-def");
218 }
219 }
220 }
221
222 // also sanitize option data.
223 ConstElementPtr options = cclass->get("option-data");
224 if (options) {
225 if (!options->empty()) {
226 // If present, sanitize it.
227 sanitizeOptionDataList(options, space, codes);
228 } else {
229 // If empty, remove it.
230 cclass->remove("option-data");
231 }
232 }
233 }
234}
235
236void
238 const OptionCodes& codes) {
239 if (!pools || pools->empty()) {
240 // nothing to do here.
241 return;
242 }
243
244 for (size_t i = 0; i < pools->size(); ++i) {
245 ElementPtr pool = pools->getNonConst(i);
246 ConstElementPtr options = pool->get("option-data");
247 if (options) {
248 if (!options->empty()) {
249 sanitizeOptionDataList(options, space, codes);
250 } else {
251 pool->remove("option-data");
252 }
253 }
254 }
255}
256
257void
259 const OptionCodes& codes) {
260 if (!hosts || hosts->empty()) {
261 // nothing to do here.
262 return;
263 }
264
265 for (size_t i = 0; i < hosts->size(); ++i) {
266 ElementPtr host = hosts->getNonConst(i);
267 ConstElementPtr options = host->get("option-data");
268 if (options) {
269 if (!options->empty()) {
270 sanitizeOptionDataList(options, space, codes);
271 } else {
272 host->remove("option-data");
273 }
274 }
275 }
276}
277
278void
280 const string& space,
281 const OptionCodes& codes) {
282 if (!subnets || subnets->empty()) {
283 // nothing to do here.
284 return;
285 }
286
287 for (size_t i = 0; i < subnets->size(); ++i) {
288 ElementPtr subnet = subnets->getNonConst(i);
289
290 // Let's try to sanitize option-data first.
291 ConstElementPtr options = subnet->get("option-data");
292 if (options) {
293 if (!options->empty()) {
294 sanitizeOptionDataList(options, space, codes);
295 } else {
296 subnet->remove("option-data");
297 }
298 }
299
300 // Then try to sanitize pools.
301 ConstElementPtr pools = subnet->get("pools");
302 if (pools) {
303 if (!pools->empty()) {
304 sanitizeOptionPools(pools, space, codes);
305 } else {
306 subnet->remove("pools");
307 }
308 }
309
310 // If this is v6, also sanitize pd-pools.
311 if (space == DHCP6_SPACE) {
312 ConstElementPtr pools = subnet->get("pd-pools");
313 if (pools) {
314 if (!pools->empty()) {
315 sanitizeOptionPools(pools, space, codes);
316 } else {
317 subnet->remove("pd-pools");
318 }
319 }
320 }
321
322 // Finally, sanitize host reservations.
323 ConstElementPtr hosts = subnet->get("reservations");
324 if (hosts) {
325 if (!hosts->empty()) {
326 sanitizeOptionHosts(hosts, space, codes);
327 } else {
328 subnet->remove("reservations");
329 }
330 }
331 }
332}
333
334void
336 const string& space,
337 const OptionCodes& codes) {
338 if (!networks || networks->empty()) {
339 // nothing to do here.
340 return;
341 }
342
343 // For every shared network...
344 for (size_t i = 0; i < networks->size(); ++i) {
345 ElementPtr network = networks->getNonConst(i);
346
347 // try to sanitize shared network options first.
348 ConstElementPtr options = network->get("option-data");
349 if (options) {
350 if (!options->empty()) {
351 sanitizeOptionDataList(options, space, codes);
352 } else {
353 network->remove("option-data");
354 }
355 }
356 string subnet = "subnet";
357 if (space == DHCP4_SPACE) {
358 subnet += "4";
359 } else {
360 subnet += "6";
361 }
362
363 // Now try to sanitize subnets.
364 ConstElementPtr subnets = network->get(subnet);
365 if (subnets) {
366 if (!subnets->empty()) {
367 sanitizeOptionSubnets(subnets, space, codes);
368 } else {
369 network->remove(subnet);
370 }
371 }
372 }
373}
374
375void
377 if (!pools || pools->empty()) {
378 // nothing to do here.
379 return;
380 }
381
382 for (size_t i = 0; i < pools->size(); ++i) {
383 ElementPtr pool = pools->getNonConst(i);
384 ConstElementPtr requires = pool->get("require-client-classes");
385 if (requires && requires->empty()) {
386 pool->remove("require-client-classes");
387 }
388 }
389}
390
391void
393 if (!subnets || subnets->empty()) {
394 // nothing to do here.
395 return;
396 }
397
398 for (size_t i = 0; i < subnets->size(); ++i) {
399 ElementPtr subnet = subnets->getNonConst(i);
400 sanitizeRequireClassesPools(subnet->get("pools"));
401 sanitizeRequireClassesPools(subnet->get("pd-pools"));
402 ConstElementPtr requires = subnet->get("require-client-classes");
403 if (requires && requires->empty()) {
404 subnet->remove("require-client-classes");
405 }
406 }
407}
408
409void
411 const string& subsel) {
412 if (!networks || networks->empty()) {
413 // nothing to do here.
414 return;
415 }
416
417 for (size_t i = 0; i < networks->size(); ++i) {
418 ElementPtr network = networks->getNonConst(i);
419 sanitizeRequireClassesSubnets(network->get(subsel));
420 ConstElementPtr requires = network->get("require-client-classes");
421 if (requires && requires->empty()) {
422 network->remove("require-client-classes");
423 }
424 }
425}
426
427void
429
430 if (!hosts || hosts->empty()) {
431 // nothing to do here.
432 return;
433 }
434
435 for (size_t i = 0; i < hosts->size(); ++i) {
436 ElementPtr host = hosts->getNonConst(i);
437 quoteIdentifier(host);
438 }
439}
440
441void
443
444 if (!subnets || subnets->empty()) {
445 // nothing to do here.
446 return;
447 }
448
449 for (ConstElementPtr subnet : subnets->listValue()) {
450 sanitizeHostList(subnet->get("reservations"));
451 }
452}
453
454void
456 const string& space) {
457 if (!networks || networks->empty()) {
458 // nothing to do here.
459 return;
460 }
461
462 for (ConstElementPtr network : networks->listValue()) {
463 if (space == DHCP4_SPACE) {
464 sanitizeHostSubnets(network->get("subnet4"));
465 } else {
466 sanitizeHostSubnets(network->get("subnet6"));
467 }
468 }
469}
470
471void
473 if (!subnets || subnets->empty()) {
474 // nothing to do here.
475 return;
476 }
477
478 for (size_t i = 0; i < subnets->size(); ++i) {
479 ElementPtr subnet = subnets->getNonConst(i);
480 updateRelay(subnet);
481 }
482}
483
484void
486 const string& subsel) {
487 if (!networks || networks->empty()) {
488 // nothing to do here.
489 return;
490 }
491
492 for (size_t i = 0; i < networks->size(); ++i) {
493 ElementPtr network = networks->getNonConst(i);
494 updateRelay(network);
495 sanitizeRelaySubnets(network->get(subsel));
496 }
497}
498
499void
501 ConstElementPtr database = dhcp->get("hosts-database");
502 if (!database) {
503 // nothing to do here.
504 return;
505 }
506
507 ElementPtr mutable_dhcp = boost::const_pointer_cast<Element>(dhcp);
508 mutable_dhcp->remove("hosts-database");
510 list->add(boost::const_pointer_cast<Element>(database));
511 mutable_dhcp->set("hosts-databases", list);
512}
513
514void
516 ConstElementPtr options = dhcp->get("relay-supplied-options");
517 if (!options || !options->empty()) {
518 // nothing to do here.
519 return;
520 }
521 ElementPtr mutable_dhcp = boost::const_pointer_cast<Element>(dhcp);
522 mutable_dhcp->remove("relay-supplied-options");
523}
524
525void
526AdaptorConfig::preProcess(ElementPtr dhcp, const string& subsel,
527 const string& space) {
528 if (!dhcp) {
529 isc_throw(BadValue, "preProcess: null DHCP config");
530 }
531 bool have_ids = true;
532 SubnetIDSet set;
533 ConstElementPtr subnets = dhcp->get(subsel);
534 if (subnets) {
535 if (!subnets->empty()) {
536 if (!subnetsCollectID(subnets, set)) {
537 have_ids = false;
538 }
539 } else {
540 dhcp->remove(subsel);
541 }
542 }
543 ConstElementPtr networks = dhcp->get("shared-networks");
544 if (networks) {
545 if (!networks->empty()) {
546 if (!sharedNetworksCollectID(networks, set, subsel)) {
547 have_ids = false;
548 }
549 } else {
550 dhcp->remove("shared-networks");
551 }
552 }
553
554 if (!have_ids) {
555 SubnetID next(1);
556 subnetsAssignID(subnets, set, next);
557 sharedNetworksAssignID(networks, set, next, subsel);
558 }
559
560 OptionCodes codes;
561 initCodes(codes, space);;
562 ConstElementPtr defs = dhcp->get("option-def");
563 if (defs) {
564 if (!defs->empty()) {
565 sanitizeOptionDefList(defs, space, codes);
566 } else {
567 dhcp->remove("option-def");
568 }
569 }
570 ConstElementPtr options = dhcp->get("option-data");
571 if (options) {
572 if (!options->empty()) {
573 sanitizeOptionDataList(options, space, codes);
574 } else {
575 dhcp->remove("option-data");
576 }
577 }
578 ConstElementPtr classes = dhcp->get("client-classes");
579 if (classes) {
580 if (!classes->empty()) {
581 sanitizeOptionClasses(classes, space, codes);
582 } else {
583 dhcp->remove("client-classes");
584 }
585 }
586 ConstElementPtr hosts = dhcp->get("reservations");
587 if (hosts) {
588 if (!hosts->empty()) {
589 sanitizeHostList(hosts);
590 sanitizeOptionHosts(hosts, space, codes);
591 } else {
592 dhcp->remove("reservations");
593 }
594 }
595 sanitizeOptionSubnets(subnets, space, codes);
596 sanitizeOptionSharedNetworks(networks, space, codes);
597
598 sanitizePoolsInSubnets(subnets);
599 sanitizePoolsInSharedNetworks(networks, subsel);
600
601 sanitizeHostSubnets(subnets);
602 SanitizeHostsInSharedNetworks(networks, space);
603
604 sanitizeRelaySubnets(subnets);
605 sanitizeRelayInSharedNetworks(networks, subsel);
606
608 requireClassesSharedNetworks(networks, subsel);
609
610 sanitizeDatabase(dhcp);
611
612 if (space == DHCP6_SPACE) {
614 }
615}
616
617void
619 if (!config) {
620 isc_throw(BadValue, "preProcess4: null config");
621 }
622 if (config->getType() != Element::map) {
623 isc_throw(BadValue, "preProcess4: not map: " << config->str());
624 }
625 ConstElementPtr dhcp = config->get("Dhcp4");
626 if (!dhcp) {
627 return;
628 }
629 ElementPtr mutable_dhcp = boost::const_pointer_cast<Element>(dhcp);
630 preProcess(mutable_dhcp, "subnet4", DHCP4_SPACE);
631}
632
633void
635 if (!config) {
636 isc_throw(BadValue, "preProcess6: null config");
637 }
638 if (config->getType() != Element::map) {
639 isc_throw(BadValue, "preProcess6: not map: " << config->str());
640 }
641 ConstElementPtr dhcp = config->get("Dhcp6");
642 if (!dhcp) {
643 return;
644 }
645 ElementPtr mutable_dhcp = boost::const_pointer_cast<Element>(dhcp);
646 preProcess(mutable_dhcp, "subnet6", DHCP6_SPACE);
647}
648
649}; // end of namespace isc::yang
650}; // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:263
static void sanitizeRequireClassesPools(isc::data::ConstElementPtr pools)
Process require client classes in a pool list.
static void sanitizeOptionSharedNetworks(isc::data::ConstElementPtr networks, const std::string &space, const OptionCodes &codes)
Set missing option codes to a shared network list.
static void subnetsAssignID(isc::data::ConstElementPtr subnets, SubnetIDSet &set, isc::dhcp::SubnetID &next)
Assigns subnet-id to every subnet in a subnet list.
static void sanitizeRelaySubnets(isc::data::ConstElementPtr subnets)
Sanitizes relay information in subnets in a subnet list.
static void sanitizeHostSubnets(isc::data::ConstElementPtr subnets)
Process host reservations in a subnet list.
static void sanitizeOptionPools(isc::data::ConstElementPtr pools, const std::string &space, const OptionCodes &codes)
Set missing option codes to a pool list.
static void sanitizeDatabase(isc::data::ConstElementPtr dhcp)
Update (hosts) database.
static void preProcess(isc::data::ElementPtr dhcp, const std::string &subsel, const std::string &space)
Pre process a configuration.
static void sharedNetworksAssignID(isc::data::ConstElementPtr networks, SubnetIDSet &set, isc::dhcp::SubnetID &next, const std::string &subsel)
Assigns subnet-id to every subnet in a shared network list.
static void sanitizePoolsInSubnets(isc::data::ConstElementPtr subnets)
Sanitizes all pools in a subnets list.
static void requireClassesSharedNetworks(isc::data::ConstElementPtr networks, const std::string &subsel)
Process require client classes in a shared network list.
static void preProcess4(isc::data::ConstElementPtr config)
Pre process a DHCPv4 configuration.
static bool subnetsCollectID(isc::data::ConstElementPtr subnets, SubnetIDSet &set)
Collects subnet-ids on all subnets.
static void sanitizeOptionHosts(isc::data::ConstElementPtr hosts, const std::string &space, const OptionCodes &codes)
Set missing option codes to a host reservation list.
static void sanitizeHostList(isc::data::ConstElementPtr hosts)
Process host reservation list.
static void SanitizeHostsInSharedNetworks(isc::data::ConstElementPtr networks, const std::string &space)
Process host reservations in a shared network list.
static void sanitizeOptionDefList(isc::data::ConstElementPtr defs, const std::string &space, OptionCodes &codes)
Collect option definitions from an option definition list.
virtual ~AdaptorConfig()
Destructor.
static void sanitizeRequireClassesSubnets(isc::data::ConstElementPtr subnets)
Process require client classes in a subnet list.
static void sanitizeOptionSubnets(isc::data::ConstElementPtr subnets, const std::string &space, const OptionCodes &codes)
Set missing option codes to a subnet list.
static void sanitizePools(isc::data::ConstElementPtr pools)
Sanitizes all pools in a pools list.
static void sanitizePoolsInSharedNetworks(isc::data::ConstElementPtr networks, const std::string &subsel)
Sanitizes all pools in all subnets in a shared network list.
static void sanitizeOptionClasses(isc::data::ConstElementPtr classes, const std::string &space, OptionCodes &codes)
Collect option definitions from a client class list and set missing option codes.
static bool sharedNetworksCollectID(isc::data::ConstElementPtr networks, SubnetIDSet &set, const std::string &subsel)
Collects subnet-ids in all subnets in all shared network list.
static void sanitizeRelaySuppliedOptions(isc::data::ConstElementPtr dhcp)
Update relay supplied options.
static void preProcess6(isc::data::ConstElementPtr config)
Pre process a DHCPv6 configuration.
static void sanitizeOptionDataList(isc::data::ConstElementPtr options, const std::string &space, const OptionCodes &codes)
Set missing option codes to an option data list.
static void sanitizeRelayInSharedNetworks(isc::data::ConstElementPtr networks, const std::string &subsel)
Sanitizes relay information in a shared network list.
static void quoteIdentifier(isc::data::ElementPtr host)
Quote when needed a host identifier.
Definition: adaptor_host.cc:31
static void setCode(isc::data::ElementPtr option, const OptionCodes &codes)
Set code from name and definitions.
static void initCodes(OptionCodes &codes, const std::string &space)
Initialize code map.
static void setSpace(isc::data::ElementPtr option, const std::string &space)
Set space.
static void checkType(isc::data::ConstElementPtr option)
Checks if type is specified in option definition.
static void collect(isc::data::ConstElementPtr option, OptionCodes &codes)
Collect definition.
static void checkCode(isc::data::ConstElementPtr option)
Check if code is specified in option defintion.
static void canonizePool(isc::data::ElementPtr pool)
Canonize pool.
Definition: adaptor_pool.cc:23
static bool collectID(isc::data::ConstElementPtr subnet, SubnetIDSet &set)
Collect a subnet ID.
static void updateRelay(isc::data::ElementPtr subnet)
Update relay.
static void assignID(isc::data::ElementPtr subnet, SubnetIDSet &set, isc::dhcp::SubnetID &next)
Assign subnet ID.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
boost::shared_ptr< Element > ElementPtr
Definition: data.h:22
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
std::set< isc::dhcp::SubnetID > SubnetIDSet
Set of SubnetIDs.
std::map< std::string, uint16_t > OptionCodes
Map for DHCP option definitions handling code and an index built from space and name.
Defines the logger used by the top-level component of kea-dhcp-ddns.