"Fossies" - the Fresh Open Source Software Archive

Member "kea-1.7.1/src/lib/yang/adaptor_config.cc" (29 Oct 2019, 19436 Bytes) of package /linux/misc/kea-1.7.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "adaptor_config.cc" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.5.0_vs_1.6.0.

    1 // Copyright (C) 2018-2019 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 <yang/adaptor_config.h>
    8 
    9 using namespace std;
   10 using namespace isc::data;
   11 using namespace isc::dhcp;
   12 
   13 namespace {
   14 const string DHCP4_SPACE = "dhcp4";
   15 const string DHCP6_SPACE = "dhcp6";
   16 }
   17 
   18 namespace isc {
   19 namespace yang {
   20 
   21 AdaptorConfig::AdaptorConfig() {
   22 }
   23 
   24 AdaptorConfig::~AdaptorConfig() {
   25 }
   26 
   27 bool
   28 AdaptorConfig::subnetsCollectID(ConstElementPtr subnets, SubnetIDSet& set) {
   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 
   49 bool
   50 AdaptorConfig::sharedNetworksCollectID(ConstElementPtr networks,
   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 
   82 void
   83 AdaptorConfig::subnetsAssignID(ConstElementPtr subnets, SubnetIDSet& set,
   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 
   96 void
   97 AdaptorConfig::sharedNetworksAssignID(ConstElementPtr networks,
   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 
  118 void
  119 AdaptorConfig::sanitizePools(ConstElementPtr pools) {
  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);
  129         AdaptorPool::canonizePool(pool);
  130     }
  131 }
  132 
  133 void
  134 AdaptorConfig::sanitizePoolsInSubnets(ConstElementPtr subnets) {
  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 
  145 void
  146 AdaptorConfig::sanitizePoolsInSharedNetworks(ConstElementPtr networks,
  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 
  158 void
  159 AdaptorConfig::sanitizeOptionDefList(ConstElementPtr defs,
  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 
  178 void
  179 AdaptorConfig::sanitizeOptionDataList(ConstElementPtr options,
  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 
  196 void
  197 AdaptorConfig::sanitizeOptionClasses(ConstElementPtr classes,
  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 
  236 void
  237 AdaptorConfig::sanitizeOptionPools(ConstElementPtr pools, const string& space,
  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 
  257 void
  258 AdaptorConfig::sanitizeOptionHosts(ConstElementPtr hosts, const string& space,
  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 
  278 void
  279 AdaptorConfig::sanitizeOptionSubnets(ConstElementPtr subnets,
  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 
  334 void
  335 AdaptorConfig::sanitizeOptionSharedNetworks(ConstElementPtr networks,
  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 
  375 void
  376 AdaptorConfig::sanitizeRequireClassesPools(ConstElementPtr pools) {
  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 
  391 void
  392 AdaptorConfig::sanitizeRequireClassesSubnets(ConstElementPtr subnets) {
  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 
  409 void
  410 AdaptorConfig::requireClassesSharedNetworks(ConstElementPtr networks,
  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 
  427 void
  428 AdaptorConfig::sanitizeHostList(ConstElementPtr hosts) {
  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 
  441 void
  442 AdaptorConfig::sanitizeHostSubnets(ConstElementPtr subnets) {
  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 
  454 void
  455 AdaptorConfig::SanitizeHostsInSharedNetworks(ConstElementPtr networks,
  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 
  471 void
  472 AdaptorConfig::sanitizeRelaySubnets(ConstElementPtr subnets) {
  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 
  484 void
  485 AdaptorConfig::sanitizeRelayInSharedNetworks(ConstElementPtr networks,
  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 
  499 void
  500 AdaptorConfig::sanitizeDatabase(ConstElementPtr dhcp) {
  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");
  509     ElementPtr list = Element::createList();
  510     list->add(boost::const_pointer_cast<Element>(database));
  511     mutable_dhcp->set("hosts-databases", list);
  512 }
  513 
  514 void
  515 AdaptorConfig::sanitizeRelaySuppliedOptions(ConstElementPtr dhcp) {
  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 
  525 void
  526 AdaptorConfig::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 
  607     sanitizeRequireClassesSubnets(subnets);
  608     requireClassesSharedNetworks(networks, subsel);
  609 
  610     sanitizeDatabase(dhcp);
  611 
  612     if (space == DHCP6_SPACE) {
  613         sanitizeRelaySuppliedOptions(dhcp);
  614     }
  615 }
  616 
  617 void
  618 AdaptorConfig::preProcess4(ConstElementPtr config) {
  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     if (config->contains("Logging")) {
  626         isc_throw(BadValue, "preProcess4: got Logging object");
  627     }
  628     ConstElementPtr dhcp = config->get("Dhcp4");
  629     if (!dhcp) {
  630         return;
  631     }
  632     ElementPtr mutable_dhcp = boost::const_pointer_cast<Element>(dhcp);
  633     preProcess(mutable_dhcp, "subnet4", DHCP4_SPACE);
  634 }
  635 
  636 void
  637 AdaptorConfig::preProcess6(ConstElementPtr config) {
  638     if (!config) {
  639         isc_throw(BadValue, "preProcess6: null config");
  640     }
  641     if (config->getType() != Element::map) {
  642         isc_throw(BadValue, "preProcess6: not map: " << config->str());
  643     }
  644     if (config->contains("Logging")) {
  645         isc_throw(BadValue, "preProcess6: got Logging object");
  646     }
  647     ConstElementPtr dhcp = config->get("Dhcp6");
  648     if (!dhcp) {
  649         return;
  650     }
  651     ElementPtr mutable_dhcp = boost::const_pointer_cast<Element>(dhcp);
  652     preProcess(mutable_dhcp, "subnet6", DHCP6_SPACE);
  653 }
  654 
  655 }; // end of namespace isc::yang
  656 }; // end of namespace isc