1 // Copyright (C) 2014-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 DHCPSRV_CONFIG_H
8 #define DHCPSRV_CONFIG_H
9 
10 #include <cc/cfg_to_element.h>
11 #include <dhcpsrv/cfg_db_access.h>
12 #include <dhcpsrv/cfg_duid.h>
13 #include <dhcpsrv/cfg_expiration.h>
14 #include <dhcpsrv/cfg_host_operations.h>
15 #include <dhcpsrv/cfg_hosts.h>
16 #include <dhcpsrv/cfg_iface.h>
17 #include <dhcpsrv/cfg_option.h>
18 #include <dhcpsrv/cfg_option_def.h>
19 #include <dhcpsrv/cfg_rsoo.h>
20 #include <dhcpsrv/cfg_shared_networks.h>
21 #include <dhcpsrv/cfg_subnets4.h>
22 #include <dhcpsrv/cfg_subnets6.h>
23 #include <dhcpsrv/cfg_mac_source.h>
24 #include <dhcpsrv/cfg_consistency.h>
25 #include <dhcpsrv/client_class_def.h>
26 #include <dhcpsrv/d2_client_cfg.h>
27 #include <process/config_base.h>
28 #include <hooks/hooks_config.h>
29 #include <cc/data.h>
30 #include <cc/user_context.h>
31 #include <cc/simple_parser.h>
32 #include <util/strutil.h>
33 
34 #include <boost/shared_ptr.hpp>
35 #include <vector>
36 #include <stdint.h>
37 
38 namespace isc {
39 namespace dhcp {
40 
41 class CfgMgr;
42 
43 /// @brief Convenience container for conveying DDNS behavioral parameters
44 /// It is intended to be created per Packet exchange using the selected
45 /// subnet passed into functions that require them
46 class DdnsParams {
47 public:
48     /// @brief Default constructor
DdnsParams()49     DdnsParams() : subnet_(), d2_client_enabled_(false) {};
50 
51     /// @brief Constructor for DHPCv4 subnets
52     ///
53     /// @param subnet Pointer to Subnet4 instance to use for fetching
54     /// parameter values (typically this is the selected subnet).
55     /// @param d2_client_enabled flag which indicates whether or not
56     /// D2Client is enabled (typically the value should come from
57     /// global D2Client configuration).
DdnsParams(const Subnet4Ptr & subnet,bool d2_client_enabled)58     DdnsParams(const Subnet4Ptr& subnet, bool d2_client_enabled)
59         : subnet_(boost::dynamic_pointer_cast<Subnet>(subnet)),
60           d2_client_enabled_(d2_client_enabled) {}
61 
62     /// @brief Constructor for DHPCv6 subnets
63     ///
64     /// @param subnet Pointer to Subnet6 instance to use for fetching
65     /// parameter values (typically this is the selected subnet).
66     /// @param d2_client_enabled flag which indicates whether or not
67     /// D2Client is enabled (typically the value should come from
68     /// global D2Client configuration).
DdnsParams(const Subnet6Ptr & subnet,bool d2_client_enabled)69     DdnsParams(const Subnet6Ptr& subnet, bool d2_client_enabled)
70         : subnet_(boost::dynamic_pointer_cast<Subnet>(subnet)),
71           d2_client_enabled_(d2_client_enabled) {}
72 
73     /// @brief Returns whether or not DHCP DDNS updating is enabled.
74     /// The value is the logical AND of d2_client_enabled_ and
75     /// the value returned by subnet_'s getDdnsSendUpdates().  It
76     /// @return True if updates are enabled, false otherwise or if
77     /// subnet_ is empty.
78     bool getEnableUpdates() const;
79 
80     /// @brief Returns whether or not Kea should perform updates, even if
81     /// client requested no updates.
82     /// @return The value from the subnet_ or false if subnet_ is empty.
83     bool getOverrideNoUpdate() const;
84 
85     /// @brief Returns whether or not Kea should perform updates, even if
86     /// client requested delegation.
87     /// @return The value from the subnet_ or false if subnet_ is empty.
88     bool getOverrideClientUpdate() const;
89 
90     /// @brief Returns how Kea should handle the domain-name supplied by
91     /// the client.
92     /// @return The value from the subnet_ or RCM_NEVER if subnet_ is empty.
93     D2ClientConfig::ReplaceClientNameMode getReplaceClientNameMode() const;
94 
95     /// @brief Returns the Prefix Kea should use when generating domain-names.
96     /// @return The value from the subnet_ or an empty string if subnet_ is empty.
97     std::string getGeneratedPrefix() const;
98 
99     /// @brief Returns the suffix Kea should use when to qualify partial
100     /// domain-names.
101     /// @return The value from the subnet_ or an empty string if subnet_ is empty.
102     std::string getQualifyingSuffix() const;
103 
104     /// @brief Returns the regular expression describing invalid characters
105     /// for client hostnames.  If empty, host name scrubbing should not be done.
106     /// @return The value from the subnet_ or an empty string if subnet_ is empty.
107     std::string getHostnameCharSet() const;
108 
109     /// @brief Returns the string to replace invalid characters when scrubbing
110     /// hostnames. Meaningful only if hostname_char_set_ is not empty.
111     /// @return The value from the subnet_ or an empty string if subnet_ is empty.
112     std::string getHostnameCharReplacement() const;
113 
114     /// @brief Returns a regular expression string sanitizer
115     ///
116     /// If the value returned by getHostnameCharSet() is not empty, then it is
117     /// used in conjunction the value returned by getHostnameCharReplacment()
118     /// (which may be empty) to create and return a StringSanitizer instance.
119     /// Otherwise it will return an empty pointer.
120     ///
121     /// @return pointer to the StringSanitizer instance or an empty pointer
122     /// @throw BadValue if the compilation fails.
123     isc::util::str::StringSanitizerPtr getHostnameSanitizer() const;
124 
125     /// @brief Returns whether or not DNS should be updated when leases renew.
126     ///
127     /// If this is true, DNS should always be updated when leases are
128     /// extended (i.e. renewed/rebound) even if the DNS information
129     /// has not changed.
130     ///
131     /// @return True if updates should always be performed.
132     bool getUpdateOnRenew() const;
133 
134     /// @brief Returns whether or not keah-dhcp-ddns should use conflict resolution
135     ///
136     /// This value is communicated to D2 via the NCR.  When true, D2 should follow
137     /// follow conflict resolution steps described in RFC 4703.  If not, it should
138     /// simple add or remove entries.
139     ///
140     /// @return True if conflict resolution should be used.
141     bool getUseConflictResolution() const;
142 
143     /// @brief Returns the subnet-id of the subnet associated with these parameters
144     /// @return value of subnet-id (or 0 if no subnet is associated)
getSubnetId()145     SubnetID getSubnetId() const {
146         if (subnet_){
147             return subnet_->getID();
148         } else {
149             return 0;
150         }
151     }
152 
153 private:
154     /// @brief Subnet from which values should be fetched.
155     SubnetPtr subnet_;
156 
157     /// @brief Flag indicating whether or not the D2Client is enabled.
158     bool d2_client_enabled_;
159 };
160 
161 /// @brief Defines a pointer for DdnsParams instances.
162 typedef boost::shared_ptr<DdnsParams> DdnsParamsPtr;
163 
164 /// @brief Specifies current DHCP configuration
165 ///
166 /// @todo Migrate all other configuration parameters from cfgmgr.h here
167 class SrvConfig : public process::ConfigBase {
168 public:
169     /// @name Constants for selection of parameters returned by @c getConfigSummary
170     ///
171     //@{
172     /// Nothing selected
173     static const uint32_t CFGSEL_NONE    = 0x00000000;
174     /// Number of IPv4 subnets
175     static const uint32_t CFGSEL_SUBNET4 = 0x00000001;
176     /// Number of IPv6 subnets
177     static const uint32_t CFGSEL_SUBNET6 = 0x00000002;
178     /// Number of enabled ifaces
179     static const uint32_t CFGSEL_IFACE4  = 0x00000004;
180     /// Number of v6 ifaces
181     static const uint32_t CFGSEL_IFACE6  = 0x00000008;
182     /// DDNS enabled/disabled
183     static const uint32_t CFGSEL_DDNS    = 0x00000010;
184     /// Number of all subnets
185     static const uint32_t CFGSEL_SUBNET  = 0x00000003;
186     /// Configured globals
187     static const uint32_t CFGSEL_GLOBALS = 0x00000020;
188     /// Config control info
189     static const uint32_t CFGSEL_CFG_CTL = 0x00000040;
190     /// IPv4 related config
191     static const uint32_t CFGSEL_ALL4    = 0x00000035;
192     /// IPv6 related config
193     static const uint32_t CFGSEL_ALL6    = 0x0000003A;
194     /// Whole config
195     static const uint32_t CFGSEL_ALL     = 0xFFFFFFFF;
196     //@}
197 
198     /// @brief Default constructor.
199     ///
200     /// This constructor sets configuration sequence number to 0.
201     SrvConfig();
202 
203     /// @brief Constructor.
204     ///
205     /// Sets arbitrary configuration sequence number.
206     SrvConfig(const uint32_t sequence);
207 
208     /// @brief Returns summary of the configuration in the textual format.
209     ///
210     /// This method returns the brief text describing the current configuration.
211     /// It may be used for logging purposes, e.g. when the new configuration is
212     /// committed to notify a user about the changes in configuration.
213     ///
214     /// @todo Currently this method uses @c CfgMgr accessors to get the
215     /// configuration parameters. Once these parameters are migrated from the
216     /// @c CfgMgr this method will have to be modified accordingly.
217     ///
218     /// @todo Implement reporting a summary of interfaces being used for
219     /// receiving and sending DHCP messages. This will be implemented with
220     /// ticket #3512.
221     ///
222     /// @param selection Is a bitfield which describes the parts of the
223     /// configuration to be returned.
224     ///
225     /// @return Summary of the configuration in the textual format.
226     std::string getConfigSummary(const uint32_t selection) const;
227 
228     /// @brief Returns configuration sequence number.
getSequence()229     uint32_t getSequence() const {
230         return (sequence_);
231     }
232 
233     /// @brief Compares configuration sequence with other sequence.
234     ///
235     /// This method compares sequence numbers of two configurations for
236     /// equality. The sequence numbers are meant to be unique, so if
237     /// they are equal it means that they point to the same configuration.
238     ///
239     /// @param other Configuration which sequence number should be
240     /// compared with the sequence number of this configuration.
241     ///
242     /// @return true if sequence numbers are equal.
243     bool sequenceEquals(const SrvConfig& other);
244 
245     /// @brief Returns non-const pointer to interface configuration.
246     ///
247     /// This function returns a non-const pointer to the interface
248     /// configuration.
249     ///
250     /// @return Object representing configuration of interfaces.
getCfgIface()251     CfgIfacePtr getCfgIface() {
252         return (cfg_iface_);
253     }
254 
255     /// @brief Returns const pointer to interface configuration.
256     ///
257     /// This function returns a const pointer to the interface
258     /// configuration.
259     ///
260     /// @return Object representing configuration of interfaces.
getCfgIface()261     ConstCfgIfacePtr getCfgIface() const {
262         return (cfg_iface_);
263     }
264 
265     /// @brief Return pointer to non-const object representing user-defined
266     /// option definitions.
267     ///
268     /// This function returns a pointer to the object which represents the
269     /// user defined option definitions grouped by option space name.
270     ///
271     /// @return Pointer to an object holding option definitions.
getCfgOptionDef()272     CfgOptionDefPtr getCfgOptionDef() {
273         return (cfg_option_def_);
274     }
275 
276     /// @brief Returns pointer to the const object representing user-defined
277     /// option definitions.
278     ///
279     /// This function returns a pointer to the object which represents the
280     /// user defined option definitions grouped by option space name.
281     ///
282     /// @return Pointer to an object holding option definitions.
getCfgOptionDef()283     ConstCfgOptionDefPtr getCfgOptionDef() const {
284         return (cfg_option_def_);
285     }
286 
287     /// @brief Returns pointer to the non-const object holding options.
288     ///
289     /// This method returns a pointer to the object which holds instances
290     /// of the options to be returned to the clients belonging to any subnet.
291     ///
292     /// @return Pointer to the object holding options.
getCfgOption()293     CfgOptionPtr getCfgOption() {
294         return (cfg_option_);
295     }
296 
297     /// @brief Returns pointer to the const object holding options.
298     ///
299     /// This method returns a pointer to the object which holds instances
300     /// of the options to be returned to the clients belonging to any subnet.
301     ///
302     /// @return Pointer to the object holding options.
getCfgOption()303     const ConstCfgOptionPtr getCfgOption() const {
304         return (cfg_option_);
305     }
306 
307     /// @brief Returns pointer to non-const object holding subnets configuration
308     /// for DHCPv4.
309     ///
310     /// @return Pointer to the object holding subnets configuration for DHCPv4.
getCfgSubnets4()311     CfgSubnets4Ptr getCfgSubnets4() {
312         return (cfg_subnets4_);
313     }
314 
315     /// @brief Returns pointer to non-const object holding configuration of
316     /// shared networks in DHCPv4;
317     ///
318     /// @return Pointer to the object holding shared networks configuration
319     /// for DHCPv4.
getCfgSharedNetworks4()320     CfgSharedNetworks4Ptr getCfgSharedNetworks4() const {
321         return (cfg_shared_networks4_);
322     }
323 
324     /// @brief Returns pointer to non-const object holding configuration of
325     /// shared networks in DHCPv6.
326     ///
327     /// @return Pointer to the object holding shared networks configuration
328     /// for DHCPv6.
getCfgSharedNetworks6()329     CfgSharedNetworks6Ptr getCfgSharedNetworks6() const {
330         return (cfg_shared_networks6_);
331     }
332 
333     /// @brief Returns pointer to const object holding subnets configuration for
334     /// DHCPv4.
335     ///
336     /// @return Pointer to the object holding subnets configuration for DHCPv4.
getCfgSubnets4()337     ConstCfgSubnets4Ptr getCfgSubnets4() const {
338         return (cfg_subnets4_);
339     }
340 
341     /// @brief Returns pointer to non-const object holding subnets configuration
342     /// for DHCPv6.
343     ///
344     /// @return Pointer to the object holding subnets configuration for DHCPv6.
getCfgSubnets6()345     CfgSubnets6Ptr getCfgSubnets6() {
346         return (cfg_subnets6_);
347     }
348 
349     /// @brief Returns pointer to const object holding subnets configuration for
350     /// DHCPv6.
351     ///
352     /// @return Pointer to the object holding subnets configuration for DHCPv6.
getCfgSubnets6()353     ConstCfgSubnets6Ptr getCfgSubnets6() const {
354         return (cfg_subnets6_);
355     }
356 
357     /// @brief Returns pointer to the non-const objects representing host
358     /// reservations for different IPv4 and IPv6 subnets.
359     ///
360     /// @return Pointer to the non-const object holding host reservations.
getCfgHosts()361     CfgHostsPtr getCfgHosts() {
362         return (cfg_hosts_);
363     }
364 
365     /// @brief Returns pointer to the const objects representing host
366     /// reservations for different IPv4 and IPv6 subnets.
367     ///
368     /// @return Pointer to the const object holding host reservations.
getCfgHosts()369     ConstCfgHostsPtr getCfgHosts() const {
370         return (cfg_hosts_);
371     }
372 
373     /// @brief Returns pointer to the non-const object representing
374     /// set of RSOO-enabled options.
375     ///
376     /// @return Pointer to the non-const object holding RSOO-enabled
377     /// options.
getCfgRSOO()378     CfgRSOOPtr getCfgRSOO() {
379         return (cfg_rsoo_);
380     }
381 
382     /// @brief Returns pointer to the const object representing set
383     /// of RSOO-enabled options.
384     ///
385     /// @return Pointer to the const object holding RSOO-enabled
386     /// options.
getCfgRSOO()387     ConstCfgRSOOPtr getCfgRSOO() const {
388         return (cfg_rsoo_);
389     }
390 
391     /// @brief Returns pointer to the object holding configuration pertaining
392     /// to processing expired leases.
getCfgExpiration()393     CfgExpirationPtr getCfgExpiration() {
394         return (cfg_expiration_);
395     }
396 
397     /// @brief Returns pointer to the const object holding configuration
398     /// pertaining to processing expired leases.
getCfgExpiration()399     ConstCfgExpirationPtr getCfgExpiration() const {
400         return (cfg_expiration_);
401     }
402 
403     /// @brief Returns pointer to the object holding configuration of the
404     /// server identifier.
getCfgDUID()405     CfgDUIDPtr getCfgDUID() {
406         return (cfg_duid_);
407     }
408 
409     /// @brief Returns const pointer to the object holding configuration
410     /// of the server identifier.
getCfgDUID()411     ConstCfgDUIDPtr getCfgDUID() const {
412         return (cfg_duid_);
413     }
414 
415     /// @brief Returns pointer to the object holding configuration of the
416     /// lease and host database connection parameters.
getCfgDbAccess()417     CfgDbAccessPtr getCfgDbAccess() {
418         return (cfg_db_access_);
419     }
420 
421     /// @brief Returns const pointer to the object holding configuration of
422     /// the lease and host database connection parameters.
getCfgDbAccess()423     ConstCfgDbAccessPtr getCfgDbAccess() const {
424         return (cfg_db_access_);
425     }
426 
427     /// @brief Returns pointer to the object holding general configuration
428     /// for host reservations in DHCPv4.
getCfgHostOperations4()429     CfgHostOperationsPtr getCfgHostOperations4() {
430         return (cfg_host_operations4_);
431     }
432 
433     /// @brief Returns const pointer to the object holding general
434     /// configuration for host reservations in DHCPv4
getCfgHostOperations4()435     ConstCfgHostOperationsPtr getCfgHostOperations4() const {
436         return (cfg_host_operations4_);
437     }
438 
439     /// @brief Returns pointer to the object holding general configuration
440     /// for host reservations in DHCPv6.
getCfgHostOperations6()441     CfgHostOperationsPtr getCfgHostOperations6() {
442         return (cfg_host_operations6_);
443     }
444 
445     /// @brief Returns const pointer to the object holding general
446     /// configuration for host reservations in DHCPv6
getCfgHostOperations6()447     ConstCfgHostOperationsPtr getCfgHostOperations6() const {
448         return (cfg_host_operations6_);
449     }
450 
451     /// @brief Returns const pointer to object holding sanity checks flags
getConsistency()452     CfgConsistencyPtr getConsistency() {
453         return (cfg_consist_);
454     }
455 
456     //@}
457 
458     /// @brief Returns non-const reference to an array that stores
459     ///        MAC/hardware address sources.
460     ///
461     /// @return non-const reference to MAC/hardware address sources
getMACSources()462     CfgMACSource& getMACSources() {
463         return (cfg_mac_source_);
464     }
465 
466     /// @brief Returns const reference to an array that stores
467     ///        MAC/hardware address sources.
468     ///
469     /// @return const reference to MAC/hardware address sources
getMACSources()470     const CfgMACSource& getMACSources() const {
471         return (cfg_mac_source_);
472     }
473 
474     /// @brief Returns information about control socket
475     /// @return pointer to the Element that holds control-socket map
getControlSocketInfo()476     const isc::data::ConstElementPtr getControlSocketInfo() const {
477         return (control_socket_);
478     }
479 
480     /// @brief Sets information about the control socket
481     /// @param control_socket Element that holds control-socket map
setControlSocketInfo(const isc::data::ConstElementPtr & control_socket)482     void setControlSocketInfo(const isc::data::ConstElementPtr& control_socket) {
483         control_socket_ = control_socket;
484     }
485 
486     /// @brief Returns DHCP queue control information
487     /// @return pointer to the DHCP queue control information
getDHCPQueueControl()488     const isc::data::ConstElementPtr getDHCPQueueControl() const {
489         return (dhcp_queue_control_);
490     }
491 
492     /// @brief Sets information about the dhcp queue control
493     /// @param dhcp_queue_control new dhcp queue control information
setDHCPQueueControl(const isc::data::ConstElementPtr dhcp_queue_control)494     void setDHCPQueueControl(const isc::data::ConstElementPtr dhcp_queue_control) {
495         dhcp_queue_control_ = dhcp_queue_control;
496     }
497 
498     /// @brief Returns DHCP multi threading information
499     /// @return pointer to the DHCP multi threading information
getDHCPMultiThreading()500     const isc::data::ConstElementPtr getDHCPMultiThreading() const {
501         return (dhcp_multi_threading_);
502     }
503 
504     /// @brief Sets information about the dhcp multi threading
505     /// @param dhcp_multi_threading new dhcp multi threading information
setDHCPMultiThreading(const isc::data::ConstElementPtr dhcp_multi_threading)506     void setDHCPMultiThreading(const isc::data::ConstElementPtr dhcp_multi_threading) {
507         dhcp_multi_threading_ = dhcp_multi_threading;
508     }
509 
510     /// @brief Returns pointer to the dictionary of global client
511     /// class definitions
getClientClassDictionary()512     ClientClassDictionaryPtr getClientClassDictionary() {
513         return (class_dictionary_);
514     }
515 
516     /// @brief Returns pointer to const dictionary of global client
517     /// class definitions
getClientClassDictionary()518     const ClientClassDictionaryPtr getClientClassDictionary() const {
519         return (class_dictionary_);
520     }
521 
522     /// @brief Sets the client class dictionary
523     /// @param dictionary pointer to the new class dictionary
setClientClassDictionary(const ClientClassDictionaryPtr & dictionary)524     void setClientClassDictionary(const ClientClassDictionaryPtr& dictionary) {
525         class_dictionary_ = dictionary;
526     }
527 
528     /// @brief Returns non-const reference to configured hooks libraries.
529     ///
530     /// @return non-const reference to configured hooks libraries.
getHooksConfig()531     isc::hooks::HooksConfig& getHooksConfig() {
532         return (hooks_config_);
533     }
534 
535     /// @brief Returns const reference to configured hooks libraries.
536     ///
537     /// @return const reference to configured hooks libraries.
getHooksConfig()538     const isc::hooks::HooksConfig& getHooksConfig() const {
539         return (hooks_config_);
540     }
541 
542     /// @brief Fetches the DDNS parameters for a given DHCPv4 subnet.
543     ///
544     /// Creates a DdnsParams structure which retain and thereafter
545     /// use the given subnet to fetch DDNS behavioral parameters.
546     /// The values are fetched with the inheritance scope mode
547     /// of Network::ALL.
548     ///
549     /// @param subnet DHCPv4 Subnet for which DDNS parameters are desired.
550     /// @return pointer to DddnParams instance
551     DdnsParamsPtr getDdnsParams(const Subnet4Ptr& subnet) const;
552 
553     /// @brief Fetches the DDNS parameters for a given DHCPv6 subnet.
554     ///
555     /// Creates a DdnsParams structure which retain and thereafter
556     /// use the given subnet to fetch DDNS behavioral parameters.
557     /// The values are fetched with the inheritance scope mode
558     /// of Network::ALL.
559     ///
560     /// @param subnet DHCPv6 Subnet for which DDNS parameters are desired.
561     /// @return pointer to DddnParams instance
562     DdnsParamsPtr getDdnsParams(const Subnet6Ptr& subnet) const;
563 
564     /// @brief Copies the current configuration to a new configuration.
565     ///
566     /// This method copies the parameters stored in the configuration to
567     /// an object passed as parameter. The configuration sequence is not
568     /// copied.
569     ///
570     /// @warning Some of the configuration objects are not copied at
571     /// this point, e.g. subnets. This is because they contain quite complex
572     /// data structures and they make use of pointers, so in many cases
573     /// the default copy constructors can't be used. Implementing this
574     /// requires quite a lot of time so this is left as is for now.
575     /// The lack of ability to copy the entire configuration makes
576     /// revert function of the @c CfgMgr unusable.
577     ///
578     /// @param [out] new_config An object to which the configuration will
579     /// be copied.
580     void copy(SrvConfig& new_config) const;
581 
582     /// @name Methods and operators used to compare configurations.
583     ///
584     //@{
585     ///
586     /// @brief Compares two objects for equality.
587     ///
588     /// It ignores the configuration sequence number when checking for
589     /// equality of objects.
590     ///
591     /// @param other An object to be compared with this object.
592     ///
593     /// @return true if two objects are equal, false otherwise.
594     bool equals(const SrvConfig& other) const;
595 
596     /// @brief Compares two objects for inequality.
597     ///
598     /// It ignores the configuration sequence number when checking for
599     /// inequality of objects.
600     ///
601     /// @param other An object to be compared with this object.
602     ///
603     /// @return true if two objects are not equal, false otherwise.
nequals(const SrvConfig & other)604     bool nequals(const SrvConfig& other) const {
605         return (!equals(other));
606     }
607 
608     /// @brief Equality operator.
609     ///
610     /// It ignores the configuration sequence number when checking for
611     /// equality of objects.
612     ///
613     /// @param other An object to be compared with this object.
614     ///
615     /// @return true if two objects are equal, false otherwise.
616     bool operator==(const SrvConfig& other) const {
617         return (equals(other));
618     }
619 
620     /// @brief other An object to be compared with this object.
621     ///
622     /// It ignores the configuration sequence number when checking for
623     /// inequality of objects.
624     ///
625     /// @param other An object to be compared with this object.
626     ///
627     /// @return true if two objects are not equal, false otherwise.
628     bool operator!=(const SrvConfig& other) const {
629         return (nequals(other));
630     }
631 
632     //@}
633 
634     /// @brief Merges the configuration specified as a parameter into
635     /// this configuration.
636     ///
637     /// This method is used when two or more configurations held in the
638     /// @c SrvConfig objects need to be combined into a single configuration.
639     /// Specifically, when the configuration backend is used, then part of
640     /// the server configuration comes from the configuration file and
641     /// stored in the staging configuration. The other part of the
642     /// configuration comes from the database. The configuration fetched
643     /// from the database is stored in a separate @c SrvConfig instance
644     /// and then merged into the staging configuration prior to committing
645     /// it.
646     ///
647     /// The merging strategy depends on the underlying data being merged.
648     /// For example: subnets are merged using the algorithm implemented
649     /// in the @c CfgSubnets4. Other data structures are merged using the
650     /// algorithms implemented in their respective configuration
651     /// containers.
652     ///
653     /// The general rule is that the configuration data from the @c other
654     /// object replaces configuration data held in this object instance.
655     /// The data that do not overlap between the two objects is simply
656     /// inserted into this configuration.
657     ///
658     /// Due to the nature of the client classes, i.e. they are ordered and
659     /// depend on each other, individual classes are not merged. Instead,
660     /// the new list of classes entirely replaces the existing list. It
661     /// implies that client classes should not be defined in a config
662     /// file if there are classes defined in the config backend for this
663     /// server.
664     ///
665     /// @warning The call to @c merge may modify the data in the @c other
666     /// object. Therefore, the caller must not rely on the data held
667     /// in the @c other object after the call to @c merge. Also, the
668     /// data held in @c other must not be modified after the call to
669     /// @c merge because it may affect the merged configuration.
670     ///
671     /// The @c other parameter must be a @c SrvConfig or its derivation.
672     ///
673     /// This method calls either @c merge4 or @c merge6 based on
674     ///
675     /// Currently, the following parts of the configuration are merged:
676     /// - globals
677     /// - option definitions
678     /// - options
679     /// - client classes
680     /// - via @c merge4 or @c merge6 depending on @c CfgMgr::family_:
681     ///     - shared networks
682     ///     - subnets
683     ///
684     /// @todo Add support for merging other configuration elements.
685     ///
686     /// @param other An object holding the configuration to be merged
687     /// into this configuration.
688     virtual void merge(ConfigBase& other);
689 
690     /// @brief Updates statistics.
691     ///
692     /// This method calls appropriate methods in child objects that update
693     /// related statistics. See @ref CfgSubnets4::updateStatistics and
694     /// @ref CfgSubnets6::updateStatistics for details.
695     void updateStatistics();
696 
697     /// @brief Removes statistics.
698     ///
699     /// This method calls appropriate methods in child objects that remove
700     /// related statistics. See @ref CfgSubnets4::removeStatistics and
701     /// @ref CfgSubnets6::removeStatistics for details.
702     void removeStatistics();
703 
704     /// @brief Sets decline probation-period
705     ///
706     /// Probation-period is the timer, expressed, in seconds, that specifies how
707     /// long a lease is unavailable after reported as declined.
708     ///
709     /// @param decline_timer number of seconds after declined lease is restored
setDeclinePeriod(const uint32_t decline_timer)710     void setDeclinePeriod(const uint32_t decline_timer) {
711         decline_timer_ = decline_timer;
712     }
713 
714     /// @brief Returns probation-period
715     ///
716     /// See @ref setDeclinePeriod for brief discussion.
717     /// @return value of probation-period, expressed in seconds
getDeclinePeriod()718     uint32_t getDeclinePeriod() const {
719         return (decline_timer_);
720     }
721 
722     /// @brief Sets whether server should send back client-id in DHCPv4
723     ///
724     /// This is a compatibility flag. The default (true) is compliant with
725     /// RFC6842. False is for backward compatibility.
726     ///
727     /// @param echo should the client-id be sent or not
setEchoClientId(const bool echo)728     void setEchoClientId(const bool echo) {
729         echo_v4_client_id_ = echo;
730     }
731 
732     /// @brief Returns whether server should send back client-id in DHCPv4.
733     /// @return true if client-id should be returned, false otherwise.
getEchoClientId()734     bool getEchoClientId() const {
735         return (echo_v4_client_id_);
736     }
737 
738     /// @brief Sets DHCP4o6 IPC port
739     ///
740     /// DHCPv4-over-DHCPv6 uses a UDP socket for interserver communication,
741     /// this socket is bound and connected to this port and port + 1
742     ///
743     /// @param port port and port + 1 to use
setDhcp4o6Port(uint16_t port)744     void setDhcp4o6Port(uint16_t port) {
745         dhcp4o6_port_ = port;
746     }
747 
748     /// @brief Returns DHCP4o6 IPC port
749     ///
750     /// See @ref setDhcp4o6Port for brief discussion.
751     /// @return value of DHCP4o6 IPC port
getDhcp4o6Port()752     uint16_t getDhcp4o6Port() const {
753         return (dhcp4o6_port_);
754     }
755 
756     /// @brief Returns pointer to the D2 client configuration
getD2ClientConfig()757     D2ClientConfigPtr getD2ClientConfig() {
758         return (d2_client_config_);
759     }
760 
761     /// @brief Returns pointer to const D2 client configuration
getD2ClientConfig()762     const D2ClientConfigPtr getD2ClientConfig() const {
763         return (d2_client_config_);
764     }
765 
766     /// @brief Sets the D2 client configuration
767     /// @param d2_client_config pointer to the new D2 client configuration
setD2ClientConfig(const D2ClientConfigPtr & d2_client_config)768     void setD2ClientConfig(const D2ClientConfigPtr& d2_client_config) {
769         d2_client_config_ = d2_client_config;
770     }
771 
772     /// @brief Returns pointer to configured global parameters
getConfiguredGlobals()773     isc::data::ConstElementPtr getConfiguredGlobals() const {
774         return (isc::data::ConstElementPtr(configured_globals_));
775     }
776 
777     /// @brief Returns pointer to a given configured global parameter
778     /// @param name name of the parameter to fetch
779     /// @return Pointer to the parameter if it exists, otherwise an
780     /// empty pointer.
781     isc::data::ConstElementPtr getConfiguredGlobal(std::string name) const;
782 
783     /// @brief Removes all configured global parameters.
784     /// @note This removes the default values too so either
785     /// @c applyDefaultsConfiguredGlobals and @c mergeGlobals,
786     /// or @c isc::data::SimpleParser::setDefaults and
787     /// @c extractConfiguredGlobals should be called after.
788     void clearConfiguredGlobals();
789 
790     /// @brief Applies defaults to global parameters.
791     /// @param defaults vector of (name, type, value) defaults to apply.
792     void applyDefaultsConfiguredGlobals(const isc::data::SimpleDefaults& defaults);
793 
794     /// @brief Saves scalar elements from the global scope of a configuration
795     void extractConfiguredGlobals(isc::data::ConstElementPtr config);
796 
797     /// @brief Adds a parameter to the collection configured globals
798     /// @param name std::string name of the global to add
799     /// @param value ElementPtr containing the value of the global
addConfiguredGlobal(const std::string & name,isc::data::ConstElementPtr value)800     void addConfiguredGlobal(const std::string& name, isc::data::ConstElementPtr value) {
801         configured_globals_->set(name, value);
802     }
803 
804     /// @brief Conducts sanity checks on global lifetime parameters.
805     ///
806     /// @param name Base name of the lifetime parameter.
807     void sanityChecksLifetime(const std::string& name) const;
808 
809     /// @brief Conducts sanity checks on global lifetime parameters
810     /// before merge from the external configuration to the target one.
811     ///
812     /// @param target_config Target configuration.
813     /// @param name Base name of the lifetime parameter.
814     void sanityChecksLifetime(const SrvConfig& target_config,
815                               const std::string& name) const;
816 
817     /// @brief Moves deprecated parameters from dhcp-ddns element to global element
818     ///
819     /// Given a server configuration element map, the following parameters are moved
820     /// from dhcp-ddns to top-level (i.e. global) element if they do not already
821     /// exist there:
822     ///
823     /// @code
824     /// From dhcp-ddns:            To (global):
825     /// ------------------------------------------------------
826     /// override-no-update         ddns-override-no-update
827     /// override-client-update     ddns-override-client-update
828     /// replace-client-name        ddns-replace-client-name
829     /// generated-prefix           ddns-generated-prefix
830     /// qualifying-suffix          ddns-qualifying-suffix
831     /// hostname-char-set          hostname-char-set
832     /// hostname-char-replacement  hostname-char-replacement
833     /// @endcode
834     ///
835     /// Note that the whether or not the deprecated parameters are added
836     /// to the global element, they are always removed from the dhcp-ddns
837     /// element.
838     ///
839     /// @param srv_elem server top level map to alter
840     static void moveDdnsParams(isc::data::ElementPtr srv_elem);
841 
842     /// @brief Configures the server to allow or disallow specifying multiple
843     /// hosts with the same IP address/subnet.
844     ///
845     /// This setting is applied in @c CfgDbAccess and @c CfgHosts. This function
846     /// should be called when the server is being configured using the configuration
847     /// file, config-set command or via the configuration backend.
848     ///
849     /// @param unique Boolean value indicating if it is allowed (when false)
850     /// or disallowed to specify multiple hosts with the same IP reservation.
851     void setIPReservationsUnique(const bool unique);
852 
853     /// @brief Unparse a configuration object
854     ///
855     /// @return a pointer to unparsed configuration
856     virtual isc::data::ElementPtr toElement() const;
857 
858     /// @brief Set lenient option parsing compatibility flag.
859     ///
860     /// @param value the boolean value to be set when configuring lenient option
861     /// parsing
setLenientOptionParsing(bool const value)862     void setLenientOptionParsing(bool const value) {
863         lenient_option_parsing_ = value;
864     }
865 
866     /// @brief Get lenient option parsing compatibility flag.
867     ///
868     /// @return the configured value for lenient option parsing
getLenientOptionParsing()869     bool getLenientOptionParsing() const {
870         return lenient_option_parsing_;
871     }
872 
873     /// @brief Convenience method to propagate configuration parameters through
874     /// inversion of control.
875     ///
876     /// To be used as a last resort when CfgMgr::instance().getCurrentCfg()
877     /// can't be easily called from where the configuration parameter is used,
878     /// usually because that particular library is lower in the dependency tree.
879     /// Happens on configuration commit.
880     void configureLowerLevelLibraries() const;
881 
882 private:
883 
884     /// @brief Merges the DHCPv4 configuration specified as a parameter into
885     /// this configuration.
886     ///
887     /// This is called by @c merge() to handle v4 specifics, such as
888     /// networks and subnets.
889     ///
890     /// @param other An object holding the configuration to be merged
891     /// into this configuration.
892     void merge4(SrvConfig& other);
893 
894     /// @brief Merges the DHCPv6 configuration specified as a parameter into
895     /// this configuration.
896     ///
897     /// This is called by @c merge() to handle v4 specifics, such as
898     /// networks and subnets.
899     ///
900     /// @param other An object holding the configuration to be merged
901     /// into this configuration.
902     void merge6(SrvConfig& other);
903 
904     /// @brief Merges the globals specified in the given configuration
905     /// into this configuration.
906     ///
907     /// Configurable global values may be specified either via JSON
908     /// configuration (e.g. "echo-client-id":true) or as global parameters
909     /// within a configuration back end.  Regardless of the source, these
910     /// values once provided, are stored in @c SrvConfig::configured_globals_.
911     /// Any such value that does not have an explicit specification should be
912     /// considered "unspecified" at the global scope.
913     ///
914     /// This function adds the configured globals from the "other" config
915     /// into this config's configured globals.  If a value already exists
916     /// in this config, it will be overwritten with the value from the
917     /// "other" config.
918     ///
919     /// It then iterates over this merged list of globals, setting
920     /// any of the corresponding SrvConfig members that map to a
921     /// a configurable parameter (e.g. c@ SrvConfig::echo_client_id_,
922     /// @c SrvConfig::server_tag_).
923     ///
924     /// @param other An object holding the configuration to be merged
925     /// into this configuration.
926     void mergeGlobals(SrvConfig& other);
927 
928     /// @brief Sequence number identifying the configuration.
929     uint32_t sequence_;
930 
931     /// @brief Interface configuration.
932     ///
933     /// Used to select interfaces on which the DHCP server will listen to
934     /// queries.
935     CfgIfacePtr cfg_iface_;
936 
937     /// @brief Pointer to option definitions configuration.
938     ///
939     /// This object holds the user-defined option definitions grouped
940     /// by option space name.
941     CfgOptionDefPtr cfg_option_def_;
942 
943     /// @brief Pointer to options (data) configuration.
944     ///
945     /// This object holds the instances of the options to be sent to clients
946     /// connected to any subnet.
947     CfgOptionPtr cfg_option_;
948 
949     /// @brief Pointer to subnets configuration for IPv4.
950     CfgSubnets4Ptr cfg_subnets4_;
951 
952     /// @brief Pointer to subnets configuration for IPv6.
953     CfgSubnets6Ptr cfg_subnets6_;
954 
955     /// @brief Pointer to IPv4 shared networks configuration.
956     CfgSharedNetworks4Ptr cfg_shared_networks4_;
957 
958     /// @brief Pointer to IPv4 shared networks configuration.
959     CfgSharedNetworks6Ptr cfg_shared_networks6_;
960 
961     /// @brief Pointer to the configuration for hosts reservation.
962     ///
963     /// This object holds a list of @c Host objects representing host
964     /// reservations for different IPv4 and IPv6 subnets.
965     CfgHostsPtr cfg_hosts_;
966 
967     /// @brief A list of configured MAC sources.
968     CfgMACSource cfg_mac_source_;
969 
970     /// @brief Pointer to the configuration for RSOO-enabled options.
971     ///
972     /// This object holds a set of RSOO-enabled options. See
973     /// RFC 6422 for the definition of the RSOO-enabled option.
974     CfgRSOOPtr cfg_rsoo_;
975 
976     /// @brief Pointer to the configuration pertaining to processing of
977     /// expired leases.
978     CfgExpirationPtr cfg_expiration_;
979 
980     /// @brief Pointer to the configuration of the server identifier.
981     CfgDUIDPtr cfg_duid_;
982 
983     /// @brief Pointer to the configuration of the lease and host database
984     /// connection parameters.
985     CfgDbAccessPtr cfg_db_access_;
986 
987     /// @brief Pointer to the general configuration for host reservations in
988     /// DHCPv4.
989     CfgHostOperationsPtr cfg_host_operations4_;
990 
991     /// @brief Pointer to the general configuration for host reservations in
992     /// DHCPv6.
993     CfgHostOperationsPtr cfg_host_operations6_;
994 
995     /// @brief Pointer to the control-socket information
996     isc::data::ConstElementPtr control_socket_;
997 
998     /// @brief Pointer to the dhcp-queue-control information
999     isc::data::ConstElementPtr dhcp_queue_control_;
1000 
1001     /// @brief Pointer to the multi-threading information
1002     isc::data::ConstElementPtr dhcp_multi_threading_;
1003 
1004     /// @brief Pointer to the dictionary of global client class definitions
1005     ClientClassDictionaryPtr class_dictionary_;
1006 
1007     /// @brief Configured hooks libraries.
1008     isc::hooks::HooksConfig hooks_config_;
1009 
1010     /// @brief Decline Period time
1011     ///
1012     /// This timer specifies decline probation period, the time after a declined
1013     /// lease is recovered back to available state. Expressed in seconds.
1014     uint32_t decline_timer_;
1015 
1016     /// @brief Indicates whether v4 server should send back client-id
1017     bool echo_v4_client_id_;
1018 
1019     /// @brief DHCP4o6 IPC port
1020     ///
1021     /// DHCPv4-over-DHCPv6 uses a UDP socket for interserver communication,
1022     /// this socket is bound and connected to this port and port + 1
1023     uint16_t dhcp4o6_port_;
1024 
1025     /// @brief Stores D2 client configuration
1026     D2ClientConfigPtr d2_client_config_;
1027 
1028     /// @brief Stores the global parameters specified via configuration
1029     isc::data::ElementPtr configured_globals_;
1030 
1031     /// @brief Pointer to the configuration consistency settings
1032     CfgConsistencyPtr cfg_consist_;
1033 
1034     /// @brief Compatibility flags
1035     /// @{
1036     bool lenient_option_parsing_;
1037     /// @}
1038 };
1039 
1040 /// @name Pointers to the @c SrvConfig object.
1041 ///
1042 //@{
1043 /// @brief Non-const pointer to the @c SrvConfig.
1044 typedef boost::shared_ptr<SrvConfig> SrvConfigPtr;
1045 
1046 /// @brief Const pointer to the @c SrvConfig.
1047 typedef boost::shared_ptr<const SrvConfig> ConstSrvConfigPtr;
1048 //@}
1049 
1050 }  // namespace dhcp
1051 }  // namespace isc
1052 
1053 #endif // DHCPSRV_CONFIG_H
1054