1 // Copyright (C) 2017-2021 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 #ifndef NETWORK_H
8 #define NETWORK_H
9 
10 #include <cc/cfg_to_element.h>
11 #include <cc/data.h>
12 #include <cc/element_value.h>
13 #include <cc/stamped_element.h>
14 #include <cc/user_context.h>
15 #include <dhcp/classify.h>
16 #include <dhcp/option.h>
17 #include <dhcpsrv/cfg_option.h>
18 #include <dhcpsrv/cfg_4o6.h>
19 #include <dhcpsrv/d2_client_cfg.h>
20 #include <dhcpsrv/triplet.h>
21 #include <util/optional.h>
22 #include <boost/shared_ptr.hpp>
23 #include <boost/weak_ptr.hpp>
24 #include <cstdint>
25 #include <functional>
26 #include <string>
27 
28 /// @brief Template to ignore unused arguments.
29 namespace {
30 template <typename... Args>
unused(Args const &...)31 inline void unused(Args const& ...) {}
32 } // end of anonymous namespace
33 
34 namespace isc {
35 namespace dhcp {
36 
37 /// List of IOAddresses
38 typedef std::vector<isc::asiolink::IOAddress> IOAddressList;
39 
40 class Network;
41 
42 /// @brief Pointer to the @ref Network object.
43 typedef boost::shared_ptr<Network> NetworkPtr;
44 
45 /// @brief Weak pointer to the @ref Network object.
46 typedef boost::weak_ptr<Network> WeakNetworkPtr;
47 
48 /// @brief Callback function for @c Network that retrieves globally
49 /// configured parameters.
50 typedef std::function<data::ConstElementPtr()> FetchNetworkGlobalsFn;
51 
52 /// @brief Common interface representing a network to which the DHCP clients
53 /// are connected.
54 ///
55 /// The most common type of network, in Kea's terminology, is a subnet. The
56 /// @ref Subnet derives from this class. Another types of objects implementing
57 /// this interface are @ref SharedNetwork4 and @ref SharedNetwork6 objects.
58 /// They group multiple subnets together to provide means for
59 /// extending available address pools (a single client may obtain IP
60 /// address from any of the pools belonging to subnets in the shared
61 /// network), or for selecting a subnet on a given link, depending on the
62 /// class of the client (e.g. cable network case: different subnet is
63 /// selected for cable modems, different one for routers).
64 ///
65 /// The subnets and shared networks share many data structures, e.g. DHCP
66 /// options, local interface name, address manipulation methods. Both subnets
67 /// and shared networks derive from this class to provide the common
68 /// functionality.
69 ///
70 /// The DHCP server configuration is complex because many parameters may
71 /// be specified at different levels of hierarchy. The lower level values,
72 /// e.g. subnet specific values, take precedence over upper level values,
73 /// e.g. shared network specific ones. For historical reasons, the DHCP
74 /// servers expect that the appropriate values are inherited from the
75 /// upper configuration levels to the lower configuration levels upon
76 /// the reconfiguration. For example: if a user didn't specify
77 /// valid-lifetime for a subnet, calling @c Subnet4::getValid() should
78 /// result in returning a global value of valid-lifetime. In the early
79 /// Kea days it was achieved by the configuration parsers which would
80 /// explicitly assign the global valid lifetime to the @c Subnet4
81 /// instances for which the subnet specific value was not provided. This
82 /// approach has a major benefit that it is fast. However, it makes
83 /// the subnets tightly dependent on the global values (and shared
84 /// network specific values). Modification of the global value must
85 /// result in modification of this value in all subnets for which
86 /// there is no explicit value provided. This issue became a serious
87 /// road block during the implementation of the Configuration Backend.
88 ///
89 /// The @c Network object has been modified to address the problem of
90 /// inheritance of global, shared network specific and subnet specific
91 /// parameters in a generic way, at the same time minimizing the need to
92 /// change the existing server logic.
93 ///
94 /// The @c Network object now holds the pointer to the "parent" @c Network
95 /// object. Thus subnets which belong to a shared network will have
96 /// that shared network as its parent. Stand-alone subnets, will have
97 /// no parent.
98 ///
99 /// The general idea is that the accessor functions of the network
100 /// will first check if the accessed value is specified or not (that
101 /// is handled by @c util::Optional object). If the value is specified
102 /// it is returned. Otherwise, the object will check if there is a
103 /// parent object it belongs to and will call the appropriate method
104 /// of that object. If the value is present it is returned. Otherwise
105 /// the global value is returned.
106 ///
107 /// Accessing global values from the @c Network object is troublesome.
108 /// There is no uniform way to access those values. For example, the
109 /// given network may be in a staging or current configuration and
110 /// it really has no means to know in which of the two it belongs.
111 /// In fact, an attempt to pass the pointer to the @c SrvConfig object
112 /// would cause a circular dependency between the @c Network and the
113 /// @c SrvConfig. Even if it was possible and the @c Network had
114 /// access to the specific @c SrvConfig instance, it doesn't handle
115 /// the cases when the @c SrvConfig instance was modified.
116 ///
117 /// To deal with the problem of accessing the global parameters in a
118 /// flexible manner, we elected to use an optional callback function
119 /// which can be associated with the @c Network object. This callback
120 /// implements the logic to retrieve global parameters and return them
121 /// in a well known form, so as the @c Network accessors can use them.
122 class Network : public virtual isc::data::StampedElement,
123                 public virtual isc::data::UserContext,
124                 public isc::data::CfgToElement {
125 public:
126     /// @brief Holds optional information about relay.
127     ///
128     /// In some cases it is beneficial to have additional information about
129     /// a relay configured in the subnet. For now, the structure holds only
130     /// IP addresses, but there may potentially be additional parameters added
131     /// later, e.g. relay interface-id or relay-id.
132     class RelayInfo {
133     public:
134 
135         /// @brief Adds an address to the list of addresses
136         ///
137         /// @param addr address to add
138         /// @throw BadValue if the address is already in the list
139         void addAddress(const asiolink::IOAddress& addr);
140 
141         /// @brief Returns const reference to the list of addresses
142         ///
143         /// @return const reference to the list of addresses
144         const IOAddressList& getAddresses() const;
145 
146         /// @brief Indicates whether or not the address list has entries
147         ///
148         /// @return True if the address list is not empty
149         bool hasAddresses() const;
150 
151         /// @brief Checks the address list for the given address
152         ///
153         /// @return True if the address is found in the address list
154         bool containsAddress(const asiolink::IOAddress& addr) const;
155 
156     private:
157         /// @brief List of relay IP addresses
158         IOAddressList addresses_;
159     };
160 
161     /// @brief Inheritance "mode" used when fetching an optional @c Network
162     /// parameter.
163     ///
164     /// The following modes are currently supported:
165     /// - NONE: no inheritance is used, the network specific value is returned
166     ///   regardless if it is specified or not.
167     /// - PARENT_NETWORK: parent network specific value is returned or unspecified
168     ///   if the parent network doesn't exist.
169     /// - GLOBAL: global specific value is returned.
170     /// - ALL: inheritance is used on all levels: network specific value takes
171     ///   precedence over parent specific value over the global value.
172     enum class Inheritance {
173         NONE,
174         PARENT_NETWORK,
175         GLOBAL,
176         ALL
177     };
178 
179     /// Pointer to the RelayInfo structure
180     typedef boost::shared_ptr<Network::RelayInfo> RelayInfoPtr;
181 
182     /// @brief Constructor.
Network()183     Network()
184         : iface_name_(), client_class_(), t1_(), t2_(), valid_(),
185           reservations_global_(false, true), reservations_in_subnet_(true, true),
186           reservations_out_of_pool_(false, true), cfg_option_(new CfgOption()),
187           calculate_tee_times_(), t1_percent_(), t2_percent_(),
188           ddns_send_updates_(), ddns_override_no_update_(), ddns_override_client_update_(),
189           ddns_replace_client_name_mode_(), ddns_generated_prefix_(), ddns_qualifying_suffix_(),
190           hostname_char_set_(), hostname_char_replacement_(), store_extended_info_(),
191           cache_threshold_(), cache_max_age_(), ddns_update_on_renew_(),
192           ddns_use_conflict_resolution_() {
193     }
194 
195     /// @brief Virtual destructor.
196     ///
197     /// Does nothing at the moment.
~Network()198     virtual ~Network() { };
199 
200     /// @brief Sets the optional callback function used to fetch globally
201     /// configured parameters.
202     ///
203     /// @param fetch_globals_fn Pointer to the function.
setFetchGlobalsFn(FetchNetworkGlobalsFn fetch_globals_fn)204     void setFetchGlobalsFn(FetchNetworkGlobalsFn fetch_globals_fn) {
205         fetch_globals_fn_ = fetch_globals_fn;
206     }
207 
208     /// @brief Checks if the network is associated with a function used to
209     /// fetch globally configured parameters.
210     ///
211     /// @return true if it is associated, false otherwise.
hasFetchGlobalsFn()212     bool hasFetchGlobalsFn() const {
213         return (static_cast<bool>(fetch_globals_fn_));
214     }
215 
216     /// @brief Sets local name of the interface for which this network is
217     /// selected.
218     ///
219     /// If the interface is specified, the server will use the network
220     /// associated with this local interface to allocate IP addresses and
221     /// other resources to a client.
222     ///
223     /// @param iface_name Interface name.
setIface(const util::Optional<std::string> & iface_name)224     void setIface(const util::Optional<std::string>& iface_name) {
225         iface_name_ = iface_name;
226     }
227 
228     /// @brief Returns name of the local interface for which this network is
229     /// selected.
230     ///
231     /// @param inheritance inheritance mode to be used.
232     /// @return Interface name as text.
233     util::Optional<std::string>
234     getIface(const Inheritance& inheritance = Inheritance::ALL) const {
235         return (getProperty<Network>(&Network::getIface, iface_name_,
236                                      inheritance));
237     };
238 
239     /// @brief Sets information about relay
240     ///
241     /// In some situations where there are shared subnets (i.e. two different
242     /// subnets are available on the same physical link), there is only one
243     /// relay that handles incoming requests from clients. In such a case,
244     /// the usual subnet selection criteria based on relay belonging to the
245     /// subnet being selected are no longer sufficient and we need to explicitly
246     /// specify a relay. One notable example of such uncommon, but valid
247     /// scenario is a cable network, where there is only one CMTS (one relay),
248     /// but there are 2 distinct subnets behind it: one for cable modems
249     /// and another one for CPEs and other user equipment behind modems.
250     /// From manageability perspective, it is essential that modems get addresses
251     /// from different subnet, so users won't tinker with their modems.
252     ///
253     /// Setting this parameter is not needed in most deployments.
254     /// This structure holds IP address only for now, but it is expected to
255     /// be extended in the future.
256     ///
257     /// @param relay structure that contains relay information
setRelayInfo(const RelayInfo & relay)258     void setRelayInfo(const RelayInfo& relay) {
259         relay_ = relay;
260     }
261 
262     /// @brief Returns const reference to relay information
263     ///
264     /// @note The returned reference is only valid as long as the object
265     /// returned it is valid.
266     ///
267     /// @return const reference to the relay information
getRelayInfo()268     const RelayInfo& getRelayInfo() const {
269         return (relay_);
270     }
271 
272     /// @brief Adds an address to the list addresses in the network's relay info
273     ///
274     /// @param addr address of the relay
275     /// @throw BadValue if the address is already in the list
276     void addRelayAddress(const asiolink::IOAddress& addr);
277 
278     /// @brief Returns the list of relay addresses from the network's relay info
279     ///
280     /// @return const reference to the list of addresses
281     const IOAddressList& getRelayAddresses() const;
282 
283     /// @brief Indicates if network's relay info has relay addresses
284     ///
285     /// @return True the relay list is not empty, false otherwise
286     bool hasRelays() const;
287 
288     /// @brief Tests if the network's relay info contains the given address
289     ///
290     /// @param address address to search for in the relay list
291     /// @return True if a relay with the given address is found, false otherwise
292     bool hasRelayAddress(const asiolink::IOAddress& address) const;
293 
294     /// @brief Checks whether this network supports client that belongs to
295     /// specified classes.
296     ///
297     /// This method checks whether a client that belongs to given classes can
298     /// use this network. For example, if this class is reserved for client
299     /// class "foo" and the client belongs to classes "foo", "bar" and "baz",
300     /// it is supported. On the other hand, client belonging to classes
301     /// "foobar" and "zyxxy" is not supported.
302     ///
303     /// @note: changed the planned white and black lists idea to a simple
304     /// client class name.
305     ///
306     /// @param client_classes list of all classes the client belongs to
307     /// @return true if client can be supported, false otherwise
308     virtual bool
309     clientSupported(const isc::dhcp::ClientClasses& client_classes) const;
310 
311     /// @brief Sets the supported class to class class_name
312     ///
313     /// @param class_name client class to be supported by this network
314     void allowClientClass(const isc::dhcp::ClientClass& class_name);
315 
316     /// @brief Adds class class_name to classes required to be evaluated.
317     ///
318     /// @param class_name client class required to be evaluated
319     void requireClientClass(const isc::dhcp::ClientClass& class_name);
320 
321     /// @brief Returns classes which are required to be evaluated
322     const ClientClasses& getRequiredClasses() const;
323 
324     /// @brief returns the client class
325     ///
326     /// @note The returned reference is only valid as long as the object
327     /// returned it is valid.
328     ///
329     /// @param inheritance inheritance mode to be used.
330     /// @return client class @ref client_class_
331     util::Optional<ClientClass>
332     getClientClass(const Inheritance& inheritance = Inheritance::ALL) const {
333         return (getProperty<Network>(&Network::getClientClass, client_class_,
334                                      inheritance));
335     }
336 
337     /// @brief Return valid-lifetime for addresses in that prefix
338     ///
339     /// @param inheritance inheritance mode to be used.
340     Triplet<uint32_t> getValid(const Inheritance& inheritance = Inheritance::ALL) const {
341         return (getProperty<Network>(&Network::getValid, valid_, inheritance,
342                                      "valid-lifetime", "min-valid-lifetime",
343                                      "max-valid-lifetime"));
344     }
345 
346     /// @brief Sets new valid lifetime for a network.
347     ///
348     /// @param valid New valid lifetime in seconds.
setValid(const Triplet<uint32_t> & valid)349     void setValid(const Triplet<uint32_t>& valid) {
350         valid_ = valid;
351     }
352 
353     /// @brief Returns T1 (renew timer), expressed in seconds
354     ///
355     /// @param inheritance inheritance mode to be used.
356     Triplet<uint32_t> getT1(const Inheritance& inheritance = Inheritance::ALL) const {
357         return (getProperty<Network>(&Network::getT1, t1_, inheritance, "renew-timer"));
358     }
359 
360     /// @brief Sets new renew timer for a network.
361     ///
362     /// @param t1 New renew timer value in seconds.
setT1(const Triplet<uint32_t> & t1)363     void setT1(const Triplet<uint32_t>& t1) {
364         t1_ = t1;
365     }
366 
367     /// @brief Returns T2 (rebind timer), expressed in seconds
368     ///
369     /// @param inheritance inheritance mode to be used.
370     Triplet<uint32_t> getT2(const Inheritance& inheritance = Inheritance::ALL) const {
371         return (getProperty<Network>(&Network::getT2, t2_, inheritance, "rebind-timer"));
372     }
373 
374     /// @brief Sets new rebind timer for a network.
375     ///
376     /// @param t2 New rebind timer value in seconds.
setT2(const Triplet<uint32_t> & t2)377     void setT2(const Triplet<uint32_t>& t2) {
378         t2_ = t2;
379     }
380 
381     /// @brief Returns whether global reservations should be fetched.
382     ///
383     /// @param inheritance inheritance mode to be used.
384     util::Optional<bool>
385     getReservationsGlobal(const Inheritance& inheritance = Inheritance::ALL) const {
386         return (getProperty<Network>(&Network::getReservationsGlobal,
387                                      reservations_global_,
388                                      inheritance,
389                                      "reservations-global"));
390     }
391 
392     /// @brief Sets whether global reservations should be fetched.
393     ///
394     /// @param reservations_global new value of enabled/disabled.
setReservationsGlobal(const util::Optional<bool> & reservations_global)395     void setReservationsGlobal(const util::Optional<bool>& reservations_global) {
396         reservations_global_ = reservations_global;
397     }
398 
399     /// @brief Returns whether subnet reservations should be fetched.
400     ///
401     /// @param inheritance inheritance mode to be used.
402     util::Optional<bool>
403     getReservationsInSubnet(const Inheritance& inheritance = Inheritance::ALL) const {
404         return (getProperty<Network>(&Network::getReservationsInSubnet,
405                                      reservations_in_subnet_,
406                                      inheritance,
407                                      "reservations-in-subnet"));
408     }
409 
410     /// @brief Sets whether subnet reservations should be fetched.
411     ///
412     /// @param reservations_in_subnet new value of enabled/disabled.
setReservationsInSubnet(const util::Optional<bool> & reservations_in_subnet)413     void setReservationsInSubnet(const util::Optional<bool>& reservations_in_subnet) {
414         reservations_in_subnet_ = reservations_in_subnet;
415     }
416 
417     /// @brief Returns whether only out-of-pool reservations are allowed.
418     ///
419     /// @param inheritance inheritance mode to be used.
420     util::Optional<bool>
421     getReservationsOutOfPool(const Inheritance& inheritance = Inheritance::ALL) const {
422         return (getProperty<Network>(&Network::getReservationsOutOfPool,
423                                      reservations_out_of_pool_,
424                                      inheritance,
425                                      "reservations-out-of-pool"));
426     }
427 
428     /// @brief Sets whether only out-of-pool reservations are allowed.
429     ///
430     /// @param reservations_out_of_pool new value of enabled/disabled.
setReservationsOutOfPool(const util::Optional<bool> & reservations_out_of_pool)431     void setReservationsOutOfPool(const util::Optional<bool>& reservations_out_of_pool) {
432         reservations_out_of_pool_ = reservations_out_of_pool;
433     }
434 
435     /// @brief Returns pointer to the option data configuration for this network.
getCfgOption()436     CfgOptionPtr getCfgOption() {
437         return (cfg_option_);
438     }
439 
440     /// @brief Returns const pointer to the option data configuration for this
441     /// network.
getCfgOption()442     ConstCfgOptionPtr getCfgOption() const {
443         return (cfg_option_);
444     }
445 
446     /// @brief Returns whether or not T1/T2 calculation is enabled.
447     ///
448     /// @param inheritance inheritance mode to be used.
449     util::Optional<bool>
450     getCalculateTeeTimes(const Inheritance& inheritance = Inheritance::ALL) const {
451         return (getProperty<Network>(&Network::getCalculateTeeTimes,
452                                      calculate_tee_times_,
453                                      inheritance,
454                                      "calculate-tee-times"));
455     }
456 
457     /// @brief Sets whether or not T1/T2 calculation is enabled.
458     ///
459     /// @param calculate_tee_times new value of enabled/disabled.
setCalculateTeeTimes(const util::Optional<bool> & calculate_tee_times)460     void setCalculateTeeTimes(const util::Optional<bool>& calculate_tee_times) {
461         calculate_tee_times_ = calculate_tee_times;
462     }
463 
464     /// @brief Returns percentage to use when calculating the T1 (renew timer).
465     ///
466     /// @param inheritance inheritance mode to be used.
467     util::Optional<double>
468     getT1Percent(const Inheritance& inheritance = Inheritance::ALL) const {
469         return (getProperty<Network>(&Network::getT1Percent, t1_percent_,
470                                      inheritance, "t1-percent"));
471     }
472 
473     /// @brief Sets new percentage for calculating T1 (renew timer).
474     ///
475     /// @param t1_percent New percentage to use.
setT1Percent(const util::Optional<double> & t1_percent)476     void setT1Percent(const util::Optional<double>& t1_percent) {
477         t1_percent_ = t1_percent;
478     }
479 
480     /// @brief Returns percentage to use when calculating the T2 (rebind timer).
481     ///
482     /// @param inheritance inheritance mode to be used.
483     util::Optional<double>
484     getT2Percent(const Inheritance& inheritance = Inheritance::ALL) const {
485         return (getProperty<Network>(&Network::getT2Percent, t2_percent_,
486                                      inheritance, "t2-percent"));
487     }
488 
489     /// @brief Sets new percentage for calculating T2 (rebind timer).
490     ///
491     /// @param t2_percent New percentage to use.
setT2Percent(const util::Optional<double> & t2_percent)492     void setT2Percent(const util::Optional<double>& t2_percent) {
493         t2_percent_ = t2_percent;
494     }
495 
496     /// @brief Returns ddns-send-updates
497     ///
498     /// @param inheritance inheritance mode to be used.
499     util::Optional<bool>
500     getDdnsSendUpdates(const Inheritance& inheritance = Inheritance::ALL) const {
501         return (getProperty<Network>(&Network::getDdnsSendUpdates, ddns_send_updates_,
502                                      inheritance, "ddns-send-updates"));
503     }
504 
505     /// @brief Sets new ddns-send-updates
506     ///
507     /// @param ddns_send_updates New value to use.
setDdnsSendUpdates(const util::Optional<bool> & ddns_send_updates)508     void setDdnsSendUpdates(const util::Optional<bool>& ddns_send_updates) {
509         ddns_send_updates_ = ddns_send_updates;
510     }
511 
512     /// @brief Returns ddns-override-no-update
513     ///
514     /// @param inheritance inheritance mode to be used.
515     util::Optional<bool>
516     getDdnsOverrideNoUpdate(const Inheritance& inheritance = Inheritance::ALL) const {
517         return (getProperty<Network>(&Network::getDdnsOverrideNoUpdate,
518                                      ddns_override_no_update_,
519                                      inheritance, "ddns-override-no-update"));
520     }
521 
522     /// @brief Sets new ddns-override-no-update
523     ///
524     /// @param ddns_override_no_update New value to use.
setDdnsOverrideNoUpdate(const util::Optional<bool> & ddns_override_no_update)525     void setDdnsOverrideNoUpdate(const util::Optional<bool>& ddns_override_no_update) {
526         ddns_override_no_update_ = ddns_override_no_update;
527     }
528 
529     /// @brief Returns ddns-override-client-update
530     ///
531     /// @param inheritance inheritance mode to be used.
532     util::Optional<bool>
533     getDdnsOverrideClientUpdate(const Inheritance& inheritance = Inheritance::ALL) const {
534         return (getProperty<Network>(&Network::getDdnsOverrideClientUpdate,
535                                      ddns_override_client_update_,
536                                      inheritance, "ddns-override-client-update"));
537     }
538 
539     /// @brief Sets new ddns-override-client-update
540     ///
541     /// @param ddns_override_client_update New value to use.
setDdnsOverrideClientUpdate(const util::Optional<bool> & ddns_override_client_update)542     void setDdnsOverrideClientUpdate(const util::Optional<bool>&
543                                      ddns_override_client_update) {
544         ddns_override_client_update_ = ddns_override_client_update;
545     }
546 
547     /// @brief Returns ddns-replace-client-name-mode
548     ///
549     /// @param inheritance inheritance mode to be used.
550     util::Optional<D2ClientConfig::ReplaceClientNameMode>
551     getDdnsReplaceClientNameMode(const Inheritance& inheritance = Inheritance::ALL) const {
552         // Inheritance for ddns-replace-client-name is a little different than for other
553         // parameters. The value at the global level is given as a string.
554         // Thus we call getProperty here without a global name to check if it
555         // is specified on network level only.
556         const util::Optional<D2ClientConfig::ReplaceClientNameMode>& mode =
557             getProperty<Network>(&Network::getDdnsReplaceClientNameMode,
558                                  ddns_replace_client_name_mode_, inheritance);
559 
560         // If it is not specified at network level we need this special
561         // case code to convert the global string value to an enum.
562         if (mode.unspecified() && (inheritance != Inheritance::NONE) &&
563             (inheritance != Inheritance::PARENT_NETWORK)) {
564             // Get global mode.
565             util::Optional<std::string> mode_label;
566             mode_label = getGlobalProperty(mode_label, "ddns-replace-client-name");
567             if (!mode_label.unspecified()) {
568                 try {
569                     // If the mode is globally configured, convert it to an enum.
570                     return (D2ClientConfig::stringToReplaceClientNameMode(mode_label.get()));
catch(...)571                 } catch (...) {
572                     // This should not really happen because the configuration
573                     // parser should have already verified the globally configured
574                     // mode. However, we want to be 100% sure that this
575                     // method doesn't throw. Let's just return unspecified.
576                     return (mode);
577                 }
578             }
579         }
580         return (mode);
581     }
582 
583     /// @brief Sets new ddns-replace-client-name-mode
584     ///
585     /// @param ddns_replace_client_name_mode New value to use.
586     void
setDdnsReplaceClientNameMode(const util::Optional<D2ClientConfig::ReplaceClientNameMode> & ddns_replace_client_name_mode)587     setDdnsReplaceClientNameMode(const util::Optional<D2ClientConfig::ReplaceClientNameMode>&
588                                  ddns_replace_client_name_mode) {
589         ddns_replace_client_name_mode_ = ddns_replace_client_name_mode;
590     }
591 
592     /// @brief Returns ddns-generated-prefix
593     ///
594     /// @param inheritance inheritance mode to be used.
595     util::Optional<std::string>
596     getDdnsGeneratedPrefix(const Inheritance& inheritance = Inheritance::ALL) const {
597         return (getProperty<Network>(&Network::getDdnsGeneratedPrefix,
598                                      ddns_generated_prefix_,
599                                      inheritance, "ddns-generated-prefix"));
600     }
601 
602     /// @brief Sets new ddns-generated-prefix
603     ///
604     /// @param ddns_generated_prefix New value to use.
setDdnsGeneratedPrefix(const util::Optional<std::string> & ddns_generated_prefix)605     void setDdnsGeneratedPrefix(const util::Optional<std::string>& ddns_generated_prefix) {
606         ddns_generated_prefix_ = ddns_generated_prefix;
607     }
608 
609     /// @brief Returns ddns-qualifying-suffix
610     ///
611     /// @param inheritance inheritance mode to be used.
612     util::Optional<std::string>
613     getDdnsQualifyingSuffix(const Inheritance& inheritance = Inheritance::ALL) const {
614         return (getProperty<Network>(&Network::getDdnsQualifyingSuffix,
615                                      ddns_qualifying_suffix_,
616                                      inheritance, "ddns-qualifying-suffix"));
617     }
618 
619     /// @brief Sets new ddns-qualifying-suffix
620     ///
621     /// @param ddns_qualifying_suffix New value to use.
setDdnsQualifyingSuffix(const util::Optional<std::string> & ddns_qualifying_suffix)622     void setDdnsQualifyingSuffix(const util::Optional<std::string>& ddns_qualifying_suffix) {
623         ddns_qualifying_suffix_ = ddns_qualifying_suffix;
624     }
625 
626     /// @brief Return the char set regexp used to sanitize client hostnames.
627     util::Optional<std::string>
628     getHostnameCharSet(const Inheritance& inheritance = Inheritance::ALL) const {
629         return (getProperty<Network>(&Network::getHostnameCharSet, hostname_char_set_,
630                                      inheritance, "hostname-char-set"));
631     }
632 
633     /// @brief Sets new hostname-char-set
634     ///
635     /// @param hostname_char_set New value to use.
setHostnameCharSet(const util::Optional<std::string> & hostname_char_set)636     void setHostnameCharSet(const util::Optional<std::string>& hostname_char_set) {
637         hostname_char_set_ = hostname_char_set;
638     }
639 
640     /// @brief Return the invalid char replacement used to sanitize client hostnames.
641     util::Optional<std::string>
642     getHostnameCharReplacement(const Inheritance& inheritance = Inheritance::ALL) const {
643         return (getProperty<Network>(&Network::getHostnameCharReplacement,
644                                      hostname_char_replacement_,
645                                      inheritance, "hostname-char-replacement"));
646     }
647 
648     /// @brief Sets new hostname-char-replacement
649     ///
650     /// @param hostname_char_replacement New value to use.
setHostnameCharReplacement(const util::Optional<std::string> & hostname_char_replacement)651     void setHostnameCharReplacement(const util::Optional<std::string>&
652                                     hostname_char_replacement) {
653         hostname_char_replacement_ = hostname_char_replacement;
654     }
655 
656     /// @brief Returns store-extended-info
657     ///
658     /// @param inheritance inheritance mode to be used.
659     util::Optional<bool>
660     getStoreExtendedInfo(const Inheritance& inheritance = Inheritance::ALL) const {
661         return (getProperty<Network>(&Network::getStoreExtendedInfo,
662                                      store_extended_info_,
663                                      inheritance, "store-extended-info"));
664     }
665 
666     /// @brief Sets new store-extended-info
667     ///
668     /// @param store_extended_info New value to use.
setStoreExtendedInfo(const util::Optional<bool> & store_extended_info)669     void setStoreExtendedInfo(const util::Optional<bool>& store_extended_info) {
670         store_extended_info_ = store_extended_info;
671     }
672 
673     /// @brief Returns percentage to use as cache threshold.
674     ///
675     /// @param inheritance inheritance mode to be used.
676     util::Optional<double>
677     getCacheThreshold(const Inheritance& inheritance = Inheritance::ALL) const {
678         return (getProperty<Network>(&Network::getCacheThreshold,
679                                      cache_threshold_,
680                                      inheritance, "cache-threshold"));
681     }
682 
683     /// @brief Sets cache threshold for a network.
684     ///
685     /// @param cache_threshold New cache threshold percentage to use.
setCacheThreshold(const util::Optional<double> & cache_threshold)686     void setCacheThreshold(const util::Optional<double>& cache_threshold) {
687         cache_threshold_ = cache_threshold;
688     }
689 
690     /// @brief Returns value in seconds to use as cache maximum age.
691     ///
692     /// @param inheritance inheritance mode to be used.
693     util::Optional<uint32_t>
694     getCacheMaxAge(const Inheritance& inheritance = Inheritance::ALL) const {
695         return (getProperty<Network>(&Network::getCacheMaxAge, cache_max_age_,
696                                      inheritance, "cache-max-age"));
697     }
698 
699     /// @brief Sets cache max for a network.
700     ///
701     /// @param cache_max_age New cache maximum value in seconds to use.
setCacheMaxAge(const util::Optional<uint32_t> & cache_max_age)702     void setCacheMaxAge(const util::Optional<uint32_t>& cache_max_age) {
703         cache_max_age_ = cache_max_age;
704     }
705 
706     /// @brief Returns ddns-update-on-renew
707     ///
708     /// @param inheritance inheritance mode to be used.
709     util::Optional<bool>
710     getDdnsUpdateOnRenew(const Inheritance& inheritance = Inheritance::ALL) const {
711         return (getProperty<Network>(&Network::getDdnsUpdateOnRenew,
712                                      ddns_update_on_renew_,
713                                      inheritance, "ddns-update-on-renew"));
714     }
715 
716     /// @brief Sets new ddns-update-on-renew
717     ///
718     /// @param ddns_update_on_renew New value to use.
setDdnsUpdateOnRenew(const util::Optional<bool> & ddns_update_on_renew)719     void setDdnsUpdateOnRenew(const util::Optional<bool>& ddns_update_on_renew) {
720         ddns_update_on_renew_ = ddns_update_on_renew;
721     }
722 
723     /// @brief Returns ddns-use-conflict-resolution
724     ///
725     /// @param inheritance inheritance mode to be used.
726     util::Optional<bool>
727     getDdnsUseConflictResolution(const Inheritance& inheritance = Inheritance::ALL) const {
728         return (getProperty<Network>(&Network::getDdnsUseConflictResolution,
729                                      ddns_use_conflict_resolution_,
730                                      inheritance, "ddns-use-conflict-resolution"));
731     }
732 
733     /// @brief Sets new ddns-use-conflict-resolution
734     ///
735     /// @param ddns_use_conflict_resolution New value to use.
setDdnsUseConflictResolution(const util::Optional<bool> & ddns_use_conflict_resolution)736     void setDdnsUseConflictResolution(const util::Optional<bool>& ddns_use_conflict_resolution) {
737         ddns_use_conflict_resolution_ = ddns_use_conflict_resolution;
738     }
739 
740     /// @brief Unparses network object.
741     ///
742     /// @return A pointer to unparsed network configuration.
743     virtual data::ElementPtr toElement() const;
744 
745 protected:
746 
747     /// @brief Gets the optional callback function used to fetch globally
748     /// configured parameters.
749     ///
750     /// @return Pointer to the function.
getFetchGlobalsFn()751     FetchNetworkGlobalsFn getFetchGlobalsFn() const {
752         return (fetch_globals_fn_);
753     }
754 
755     /// @brief Returns a value of global configuration parameter with
756     /// a given name.
757     ///
758     /// If the @c ferch_globals_fn_ function is non-null, this method will
759     /// invoke this function to retrieve a global value having the given
760     /// name. Typically, this method is invoked by @c getProperty when
761     /// network specific value of the parameter is not found. In some cases
762     /// it may be called by other methods. One such example is the
763     /// @c getDdnsReplaceClientNameMode which needs to call @c getGlobalProperty
764     /// explicitly to convert the global replace client name mode value from
765     /// a string to an enum.
766     ///
767     /// @tparam ReturnType Type of the returned value, e.g.
768     /// @c Optional<std::string>.
769     ///
770     /// @param property Value to be returned when it is specified or when
771     /// no global value is found.
772     /// @param global_name Name of the global parameter which value should
773     /// be returned
774     /// @param min_name Name of the min global parameter which value should
775     /// be returned for triplets
776     /// @param max_name Name of the max global parameter which value should
777     /// be returned for triplets
778     ///
779     /// @return Optional value fetched from the global level or the value
780     /// of @c property.
781     template<typename ReturnType>
782     ReturnType getGlobalProperty(ReturnType property,
783                                  const std::string& global_name,
784                                  const std::string& min_name = "",
785                                  const std::string& max_name = "") const {
786         unused(min_name, max_name);
787         if (!global_name.empty() && fetch_globals_fn_) {
788             data::ConstElementPtr globals = fetch_globals_fn_();
789             if (globals && (globals->getType() == data::Element::map)) {
790                 data::ConstElementPtr global_param = globals->get(global_name);
791                 if (global_param) {
792                     // If there is a global parameter, convert it to the
793                     // optional value of the given type and return.
794                     return (data::ElementValue<typename ReturnType::ValueType>()(global_param));
795                 }
796             }
797         }
798         return (property);
799     }
800 
801     /// @brief The @c getGlobalProperty specialization for Triplet<T>.
802     ///
803     /// @note: use overloading vs specialization because full specialization
804     /// is not allowed in this scope.
805     ///
806     /// @tparam NumType Type of the encapsulated value(s).
807     ///
808     /// @param property Value to be returned when it is specified or when
809     /// no global value is found.
810     /// @param global_name Name of the global parameter which value should
811     /// be returned
812     /// @param min_name Name of the min global parameter which value should
813     /// be returned for triplets
814     /// @param max_name Name of the max global parameter which value should
815     /// be returned for triplets
816     ///
817     /// @return Optional value fetched from the global level or the value
818     /// of @c property.
819     template<typename NumType>
820     Triplet<NumType> getGlobalProperty(Triplet<NumType> property,
821                                        const std::string& global_name,
822                                        const std::string& min_name = "",
823                                        const std::string& max_name = "") const {
824 
825         if (!global_name.empty() && fetch_globals_fn_) {
826             data::ConstElementPtr globals = fetch_globals_fn_();
827             if (globals && (globals->getType() == data::Element::map)) {
828                 data::ConstElementPtr param = globals->get(global_name);
829                 if (param) {
830                     NumType def_value = static_cast<NumType>(param->intValue());
831                     if (min_name.empty() || max_name.empty()) {
832                         return (def_value);
833                     } else {
834                         NumType min_value = def_value;
835                         NumType max_value = def_value;
836                         data::ConstElementPtr min_param = globals->get(min_name);
837                         if (min_param) {
838                             min_value = static_cast<NumType>(min_param->intValue());
839                         }
840                         data::ConstElementPtr max_param = globals->get(max_name);
841                         if (max_param) {
842                             max_value = static_cast<NumType>(max_param->intValue());
843                         }
844                         return (Triplet<NumType>(min_value, def_value, max_value));
845                     }
846                 }
847             }
848         }
849         return (property);
850     }
851 
852     /// @brief The @c getGlobalProperty specialization for Optional<IOAddress>.
853     ///
854     /// This does two things:
855     ///  - uses the string value of the parameter
856     ///  - falls back when the value is empty
857     ///
858     /// @note: use overloading vs specialization because full specialization
859     /// is not allowed in this scope.
860     ///
861     /// @param property Value to be returned when it is specified or when
862     /// no global value is found.
863     /// @param global_name Name of the global parameter which value should
864     /// be returned
865     /// @param min_name Name of the min global parameter which value should
866     /// be returned for triplets
867     /// @param max_name Name of the max global parameter which value should
868     /// be returned for triplets
869     ///
870     /// @return Optional value fetched from the global level or the value
871     /// of @c property.
872     util::Optional<asiolink::IOAddress>
873     getGlobalProperty(util::Optional<asiolink::IOAddress> property,
874                       const std::string& global_name,
875                       const std::string& min_name = "",
876                       const std::string& max_name = "") const;
877 
878     /// @brief Returns a value associated with a network using inheritance.
879     ///
880     /// This template method provides a generic mechanism to retrieve a
881     /// network parameter using inheritance. It is called from public
882     /// accessor methods which return an @c OptionalValue or @c Triplet.
883     ///
884     /// @tparam BaseType Type of this instance, e.g. @c Network, @c Network4
885     /// etc, which exposes a method to be called.
886     /// @tparam ReturnType Type of the returned value, e.g.
887     /// @c Optional<std::string>.
888     ///
889     /// @param MethodPointer Pointer to the method of the base class which
890     /// should be called on the parent network instance (typically on
891     /// @c SharedNetwork4 or @c SharedNetwork6) to fetch the parent specific
892     /// value if the value is unspecified for this instance.
893     /// @param property Value to be returned when it is specified or when
894     /// no explicit value is specified on upper inheritance levels.
895     /// @param inheritance inheritance mode to be used.
896     /// @param global_name Optional name of the global parameter which value
897     /// should be returned if the given parameter is not specified on network
898     /// level. This value is empty by default, which indicates that the
899     /// global value for the given parameter is not supported and shouldn't
900     /// be fetched.
901     /// @param min_name Name of the min global parameter which value should
902     /// be returned for triplets
903     /// @param max_name Name of the max global parameter which value should
904     /// be returned for triplets
905     ///
906     /// @return Optional value fetched from this instance level, parent
907     /// network level or global level
908     template<typename BaseType, typename ReturnType>
ReturnType(BaseType::* MethodPointer)909     ReturnType getProperty(ReturnType(BaseType::*MethodPointer)(const Inheritance&) const,
910                            ReturnType property,
911                            const Inheritance& inheritance,
912                            const std::string& global_name = "",
913                            const std::string& min_name = "",
914                            const std::string& max_name = "") const {
915 
916         // If no inheritance is to be used, return the value for this
917         // network regardless if it is specified or not.
918         if (inheritance == Inheritance::NONE) {
919             return (property);
920 
921         } else if (inheritance == Inheritance::PARENT_NETWORK) {
922             ReturnType parent_property;
923 
924             // Check if this instance has a parent network.
925             auto parent = boost::dynamic_pointer_cast<BaseType>(parent_network_.lock());
926             if (parent) {
927                 parent_property = ((*parent).*MethodPointer)(Network::Inheritance::NONE);
928             }
929             return (parent_property);
930 
931         // If global value requested, return it.
932         } else if (inheritance == Inheritance::GLOBAL) {
933             return (getGlobalProperty(ReturnType(), global_name, min_name, max_name));
934         }
935 
936         // We use inheritance and the value is not specified on the network level.
937         // Hence, we need to get the parent network specific value or global value.
938         if (property.unspecified()) {
939             // Check if this instance has a parent network.
940             auto parent = boost::dynamic_pointer_cast<BaseType>(parent_network_.lock());
941             // If the parent network exists, let's fetch the parent specific
942             // value.
943             if (parent) {
944                 // We're using inheritance so ask for the parent specific network
945                 // and return it only if it is specified.
946                 auto parent_property = ((*parent).*MethodPointer)(inheritance);
947                 if (!parent_property.unspecified()) {
948                     return (parent_property);
949                 }
950             }
951 
952             // The value is not specified on network level. If the value
953             // can be specified on global level and there is a callback
954             // that returns the global values, try to find this parameter
955             // at the global scope.
956             return (getGlobalProperty(property, global_name, min_name, max_name));
957         }
958 
959         // We haven't found the value at any level, so return the unspecified.
960         return (property);
961     }
962 
963     /// @brief Returns option pointer associated with a network using inheritance.
964     ///
965     /// This template method provides a generic mechanism to retrieve a
966     /// network parameter using inheritance. It is called from public
967     /// accessor methods which return an @c OptionPtr.
968     ///
969     /// @tparam BaseType Type of this instance, e.g. @c Network, @c Network4
970     /// etc, which exposes a method to be called.
971     ///
972     /// @param MethodPointer Pointer to the method of the base class which
973     /// should be called on the parent network instance (typically on
974     /// @c SharedNetwork4 or @c SharedNetwork6) to fetch the parent specific
975     /// value if the value is unspecified for this instance.
976     /// @param property the value to return when inheritance mode is NONE, or
977     /// when the mode is PARENT_NETWORK and the property has not been specified
978     /// by a parent network.
979     /// @param inheritance inheritance mode to be used.
980     ///
981     /// @return Option pointer fetched from this instance level or parent
982     /// network level.
983     template<typename BaseType>
984     OptionPtr
getOptionProperty(OptionPtr (BaseType::* MethodPointer)(const Inheritance & inheritance)const,OptionPtr property,const Inheritance & inheritance)985     getOptionProperty(OptionPtr(BaseType::*MethodPointer)(const Inheritance& inheritance) const,
986                       OptionPtr property,
987                       const Inheritance& inheritance) const {
988         if (inheritance == Network::Inheritance::NONE) {
989             return (property);
990 
991         } else if (inheritance == Network::Inheritance::PARENT_NETWORK) {
992             OptionPtr parent_property;
993             // Check if this instance has a parent network.
994             auto parent = boost::dynamic_pointer_cast<BaseType>(parent_network_.lock());
995             // If the parent network exists, let's fetch the parent specific
996             // value.
997             if (parent) {
998                 parent_property = ((*parent).*MethodPointer)(Network::Inheritance::NONE);
999             }
1000             return (parent_property);
1001 
1002         } else if (inheritance == Network::Inheritance::GLOBAL) {
1003             return (OptionPtr());
1004         }
1005 
1006         // We use inheritance and the value is not specified on the network level.
1007         // Hence, we need to get the parent network specific value.
1008         if (!property) {
1009             // Check if this instance has a parent network.
1010             auto parent = boost::dynamic_pointer_cast<BaseType>(parent_network_.lock());
1011             if (parent) {
1012                 // We're using inheritance so ask for the parent specific network
1013                 // and return it only if it is specified.
1014                 OptionPtr parent_property = (((*parent).*MethodPointer)(inheritance));
1015                 if (parent_property) {
1016                     return (parent_property);
1017                 }
1018             }
1019         }
1020 
1021         // We haven't found the value at any level, so return the unspecified.
1022         return (property);
1023     }
1024 
1025     /// @brief Holds interface name for which this network is selected.
1026     util::Optional<std::string> iface_name_;
1027 
1028     /// @brief Relay information
1029     ///
1030     /// See @ref RelayInfo for detailed description.
1031     RelayInfo relay_;
1032 
1033     /// @brief Optional definition of a client class
1034     ///
1035     /// If defined, only clients belonging to that class will be allowed to use
1036     /// this particular network. The default value for this is an empty string,
1037     /// which means that any client is allowed, regardless of its class.
1038     util::Optional<ClientClass> client_class_;
1039 
1040     /// @brief Required classes
1041     ///
1042     /// If the network is selected these classes will be added to the
1043     /// incoming packet and their evaluation will be required.
1044     ClientClasses required_classes_;
1045 
1046     /// @brief a Triplet (min/default/max) holding allowed renew timer values
1047     Triplet<uint32_t> t1_;
1048 
1049     /// @brief a Triplet (min/default/max) holding allowed rebind timer values
1050     Triplet<uint32_t> t2_;
1051 
1052     /// @brief a Triplet (min/default/max) holding allowed valid lifetime values
1053     Triplet<uint32_t> valid_;
1054 
1055     /// @brief Enables global reservations.
1056     util::Optional<bool> reservations_global_;
1057 
1058     /// @brief Enables subnet reservations.
1059     util::Optional<bool> reservations_in_subnet_;
1060 
1061     /// @brief Enables out-of-pool reservations optimization.
1062     ///
1063     /// When true only out-of-pool reservations are allowed. This allows
1064     /// AllocEngine to skip reservation checks when dealing with addresses
1065     /// that are in pool.
1066     util::Optional<bool> reservations_out_of_pool_;
1067 
1068     /// @brief Pointer to the option data configuration for this subnet.
1069     CfgOptionPtr cfg_option_;
1070 
1071     /// @brief Enables calculation of T1 and T2 timers
1072     util::Optional<bool> calculate_tee_times_;
1073 
1074     /// @brief Percentage of the lease lifetime to use when calculating T1 timer
1075     util::Optional<double> t1_percent_;
1076 
1077     /// @brief Percentage of the lease lifetime to use when calculating T2 timer
1078     util::Optional<double> t2_percent_;
1079 
1080     /// @brief Should Kea perform DNS updates. Used to provide scoped enabling
1081     /// and disabling of updates.
1082     util::Optional<bool> ddns_send_updates_;
1083 
1084     /// @brief Should Kea perform updates, even if client requested no updates.
1085     /// Overrides the client request for no updates via the N flag.
1086     util::Optional<bool> ddns_override_no_update_;
1087 
1088     /// @brief Should Kea perform updates, even if client requested delegation.
1089     util::Optional<bool> ddns_override_client_update_;
1090 
1091     /// @brief How Kea should handle the domain-name supplied by the client.
1092     util::Optional<D2ClientConfig::ReplaceClientNameMode> ddns_replace_client_name_mode_;
1093 
1094     /// @brief Prefix Kea should use when generating domain-names.
1095     util::Optional<std::string> ddns_generated_prefix_;
1096 
1097     /// @brief Suffix Kea should use when to qualify partial domain-names.
1098     util::Optional<std::string> ddns_qualifying_suffix_;
1099 
1100     /// @brief Regular expression describing invalid characters for client
1101     /// hostnames.
1102     util::Optional<std::string> hostname_char_set_;
1103 
1104     /// @brief A string to replace invalid characters when scrubbing hostnames.
1105     /// Meaningful only if hostname_char_set_ is not empty.
1106     util::Optional<std::string> hostname_char_replacement_;
1107 
1108     /// @brief Should Kea store additional client query data (e.g. relay-agent-info)
1109     /// on the lease.
1110     util::Optional<bool> store_extended_info_;
1111 
1112     /// @brief Percentage of the lease lifetime to use as cache threshold.
1113     util::Optional<double> cache_threshold_;
1114 
1115     /// @brief Value in seconds to use as cache maximal age.
1116     util::Optional<uint32_t> cache_max_age_;
1117 
1118     /// @brief Should Kea perform updates when leases are extended
1119     util::Optional<bool> ddns_update_on_renew_;
1120 
1121     /// @brief Used to to tell kea-dhcp-ddns whether or not to use conflict resolution.
1122     util::Optional<bool> ddns_use_conflict_resolution_;
1123 
1124     /// @brief Pointer to another network that this network belongs to.
1125     ///
1126     /// The most common case is that this instance is a subnet which belongs
1127     /// to a shared network and the @c parent_network_ points to the shared
1128     /// network object. If the network instance (subnet) doesn't belong to
1129     /// a shared network this pointer is null.
1130     WeakNetworkPtr parent_network_;
1131 
1132     /// @brief Pointer to the optional callback used to fetch globally
1133     /// configured parameters inherited to the @c Network object.
1134     FetchNetworkGlobalsFn fetch_globals_fn_;
1135 };
1136 
1137 /// @brief Specialization of the @ref Network object for DHCPv4 case.
1138 class Network4 : public virtual Network {
1139 public:
1140 
1141     /// @brief Constructor.
Network4()1142     Network4()
1143         : Network(), match_client_id_(true, true), authoritative_(),
1144           siaddr_(), sname_(), filename_() {
1145     }
1146 
1147     /// @brief Returns the flag indicating if the client identifiers should
1148     /// be used to identify the client's lease.
1149     ///
1150     /// @param inheritance inheritance mode to be used.
1151     /// @return true if client identifiers should be used, false otherwise.
1152     util::Optional<bool>
1153     getMatchClientId(const Inheritance& inheritance = Inheritance::ALL) const {
1154         return (getProperty<Network4>(&Network4::getMatchClientId,
1155                                       match_client_id_,
1156                                       inheritance,
1157                                       "match-client-id"));
1158     }
1159 
1160     /// @brief Sets the flag indicating if the client identifier should be
1161     /// used to identify the client's lease.
1162     ///
1163     /// @param match If this value is true, the client identifiers are not
1164     /// used for lease lookup.
setMatchClientId(const util::Optional<bool> & match)1165     void setMatchClientId(const util::Optional<bool>& match) {
1166         match_client_id_ = match;
1167     }
1168 
1169     /// @brief Returns the flag indicating if requests for unknown IP addresses
1170     /// should be rejected with DHCPNAK instead of ignored.
1171     ///
1172     /// @param inheritance inheritance mode to be used.w
1173     /// @return true if requests for unknown IP addresses should be rejected,
1174     /// false otherwise.
1175     util::Optional<bool>
1176     getAuthoritative(const Inheritance& inheritance = Inheritance::ALL) const {
1177         return (getProperty<Network4>(&Network4::getAuthoritative, authoritative_,
1178                                       inheritance, "authoritative"));
1179     }
1180 
1181     /// @brief Sets the flag indicating if requests for unknown IP addresses
1182     /// should be rejected with DHCPNAK instead of ignored.
1183     ///
1184     /// @param authoritative If this value is true, the requests for unknown IP
1185     /// addresses will be rejected with DHCPNAK messages
setAuthoritative(const util::Optional<bool> & authoritative)1186     void setAuthoritative(const util::Optional<bool>& authoritative) {
1187         authoritative_ = authoritative;
1188     }
1189 
1190     /// @brief Sets siaddr for the network.
1191     ///
1192     /// Will be used for siaddr field (the next server) that typically is used
1193     /// as TFTP server. If not specified, the default value of 0.0.0.0 is
1194     /// used.
1195     void setSiaddr(const util::Optional<asiolink::IOAddress>& siaddr);
1196 
1197     /// @brief Returns siaddr for this network.
1198     ///
1199     /// @return siaddr value
1200     util::Optional<asiolink::IOAddress>
1201     getSiaddr(const Inheritance& inheritance = Inheritance::ALL) const {
1202         return (getProperty<Network4>(&Network4::getSiaddr, siaddr_,
1203                                       inheritance, "next-server"));
1204     }
1205 
1206     /// @brief Sets server hostname for the network.
1207     ///
1208     /// Will be used for server hostname field (may be empty if not defined)
1209     void setSname(const util::Optional<std::string>& sname);
1210 
1211     /// @brief Returns server hostname for this network.
1212     ///
1213     /// @param inheritance inheritance mode to be used.
1214     /// @return server hostname value
1215     util::Optional<std::string>
1216     getSname(const Inheritance& inheritance = Inheritance::ALL) const {
1217         return (getProperty<Network4>(&Network4::getSname, sname_,
1218                                       inheritance, "server-hostname"));
1219     }
1220 
1221     /// @brief Sets boot file name for the network.
1222     ///
1223     /// Will be used for boot file name (may be empty if not defined)
1224     void setFilename(const util::Optional<std::string>& filename);
1225 
1226     /// @brief Returns boot file name for this subnet
1227     ///
1228     /// @param inheritance inheritance mode to be used.
1229     /// @return boot file name value
1230     util::Optional<std::string>
1231     getFilename(const Inheritance& inheritance = Inheritance::ALL) const {
1232         return (getProperty<Network4>(&Network4::getFilename, filename_,
1233                                       inheritance, "boot-file-name"));
1234     }
1235 
1236     /// @brief Unparses network object.
1237     ///
1238     /// @return A pointer to unparsed network configuration.
1239     virtual data::ElementPtr toElement() const;
1240 
1241     /// @brief Returns binary representation of the dhcp-server-identifier option (54).
1242     ///
1243     /// @return Server identifier option as IPv4 address. Zero IPv4 address
1244     /// indicates that server identifier hasn't been specified.
1245     virtual asiolink::IOAddress getServerId() const;
1246 
1247 private:
1248 
1249     /// @brief Should server use client identifiers for client lease
1250     /// lookup.
1251     util::Optional<bool> match_client_id_;
1252 
1253     /// @brief Should requests for unknown IP addresses be rejected.
1254     util::Optional<bool> authoritative_;
1255 
1256     /// @brief siaddr value for this subnet
1257     util::Optional<asiolink::IOAddress> siaddr_;
1258 
1259     /// @brief server hostname for this subnet
1260     util::Optional<std::string> sname_;
1261 
1262     /// @brief boot file name for this subnet
1263     util::Optional<std::string> filename_;
1264 };
1265 
1266 /// @brief Specialization of the @ref Network object for DHCPv6 case.
1267 class Network6 : public virtual Network {
1268 public:
1269 
1270     /// @brief Constructor.
Network6()1271     Network6()
1272         : Network(), preferred_(), interface_id_(), rapid_commit_() {
1273     }
1274 
1275     /// @brief Returns preferred lifetime (in seconds)
1276     ///
1277     /// @param inheritance inheritance mode to be used.
1278     /// @return a triplet with preferred lifetime
1279     Triplet<uint32_t>
1280     getPreferred(const Inheritance& inheritance = Inheritance::ALL) const {
1281         return (getProperty<Network6>(&Network6::getPreferred, preferred_,
1282                                       inheritance, "preferred-lifetime",
1283                                       "min-preferred-lifetime",
1284                                       "max-preferred-lifetime"));
1285     }
1286 
1287     /// @brief Sets new preferred lifetime for a network.
1288     ///
1289     /// @param preferred New preferred lifetime in seconds.
setPreferred(const Triplet<uint32_t> & preferred)1290     void setPreferred(const Triplet<uint32_t>& preferred) {
1291         preferred_ = preferred;
1292     }
1293 
1294     /// @brief Returns interface-id value (if specified)
1295     ///
1296     /// @param inheritance inheritance mode to be used.
1297     /// @return interface-id option (if defined)
1298     OptionPtr getInterfaceId(const Inheritance& inheritance = Inheritance::ALL) const {
1299         return (getOptionProperty<Network6>(&Network6::getInterfaceId, interface_id_,
1300                                             inheritance));
1301     }
1302 
1303     /// @brief sets interface-id option (if defined)
1304     ///
1305     /// @param ifaceid pointer to interface-id option
setInterfaceId(const OptionPtr & ifaceid)1306     void setInterfaceId(const OptionPtr& ifaceid) {
1307         interface_id_ = ifaceid;
1308     }
1309 
1310     /// @brief Returns boolean value indicating that the Rapid Commit option
1311     /// is supported or unsupported for the subnet.
1312     ///
1313     /// @param inheritance inheritance mode to be used.
1314     /// @return true if the Rapid Commit option is supported, false otherwise.
1315     util::Optional<bool>
1316     getRapidCommit(const Inheritance& inheritance = Inheritance::ALL) const {
1317 
1318         return (getProperty<Network6>(&Network6::getRapidCommit, rapid_commit_,
1319                                       inheritance, "rapid-commit"));
1320     }
1321 
1322     /// @brief Enables or disables Rapid Commit option support for the subnet.
1323     ///
1324     /// @param rapid_commit A boolean value indicating that the Rapid Commit
1325     /// option support is enabled (if true), or disabled (if false).
setRapidCommit(const util::Optional<bool> & rapid_commit)1326     void setRapidCommit(const util::Optional<bool>& rapid_commit) {
1327         rapid_commit_ = rapid_commit;
1328     };
1329 
1330     /// @brief Unparses network object.
1331     ///
1332     /// @return A pointer to unparsed network configuration.
1333     virtual data::ElementPtr toElement() const;
1334 
1335 private:
1336 
1337     /// @brief a triplet with preferred lifetime (in seconds)
1338     Triplet<uint32_t> preferred_;
1339 
1340     /// @brief specifies optional interface-id
1341     OptionPtr interface_id_;
1342 
1343     /// @brief A flag indicating if Rapid Commit option is supported
1344     /// for this network.
1345     ///
1346     /// It's default value is false, which indicates that the Rapid
1347     /// Commit is disabled for the subnet.
1348     util::Optional<bool> rapid_commit_;
1349 };
1350 
1351 } // end of namespace isc::dhcp
1352 } // end of namespace isc
1353 
1354 #endif // NETWORK_H
1355