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 D2_CFG_MGR_H
8 #define D2_CFG_MGR_H
9 
10 #include <asiolink/io_service.h>
11 #include <cc/data.h>
12 #include <exceptions/exceptions.h>
13 #include <d2srv/d2_config.h>
14 #include <hooks/hooks_config.h>
15 #include <process/d_cfg_mgr.h>
16 
17 #include <stdint.h>
18 #include <string>
19 
20 namespace isc {
21 namespace d2 {
22 
23 class D2CfgContext;
24 /// @brief Pointer to a configuration context.
25 typedef boost::shared_ptr<D2CfgContext> D2CfgContextPtr;
26 
27 /// @brief  DHCP-DDNS Configuration Context
28 ///
29 /// Implements the storage container for configuration context.
30 /// It provides a single enclosure for the storage of configuration parameters
31 /// and any other DHCP-DDNS specific information that needs to be accessible
32 /// during configuration parsing as well as to the application as a whole.
33 /// It is derived from the context base class, ConfigBase.
34 class D2CfgContext : public process::ConfigBase {
35 public:
36     /// @brief Constructor
37     D2CfgContext();
38 
39     /// @brief Destructor
40     virtual ~D2CfgContext();
41 
42     /// @brief Creates a clone of this context object.
43     ///
44     /// @return returns a pointer to the new clone.
clone()45     virtual process::ConfigPtr clone() {
46         return (process::ConfigPtr(new D2CfgContext(*this)));
47     }
48 
49     /// @brief Fetches a reference to the D2Params
getD2Params()50     D2ParamsPtr& getD2Params() {
51         return (d2_params_);
52     }
53 
54     /// @brief Fetches the forward DNS domain list manager.
55     ///
56     /// @return returns a pointer to the forward manager.
getForwardMgr()57     DdnsDomainListMgrPtr getForwardMgr() {
58         return (forward_mgr_);
59     }
60 
61     /// @brief Sets the forward domain list manager
62     /// @param forward_mgr pointer to the new forward manager
setForwardMgr(DdnsDomainListMgrPtr forward_mgr)63     void setForwardMgr(DdnsDomainListMgrPtr forward_mgr) {
64         forward_mgr_ = forward_mgr;
65     }
66 
67     /// @brief Fetches the reverse DNS domain list manager.
68     ///
69     /// @return returns a pointer to the reverse manager.
getReverseMgr()70     DdnsDomainListMgrPtr getReverseMgr() {
71         return (reverse_mgr_);
72     }
73 
74     /// @brief Sets the reverse domain list manager
75     /// @param reverse_mgr pointer to the new reverse manager
setReverseMgr(DdnsDomainListMgrPtr reverse_mgr)76     void setReverseMgr(DdnsDomainListMgrPtr reverse_mgr) {
77         reverse_mgr_ = reverse_mgr;
78     }
79 
80     /// @brief Fetches the map of TSIG keys.
81     ///
82     /// @return returns a pointer to the key map.
getKeys()83     TSIGKeyInfoMapPtr getKeys() {
84         return (keys_);
85     }
86 
87     /// @brief Sets the map of TSIG keys
88     ///
89     /// @param keys pointer to the new TSIG key map
setKeys(const TSIGKeyInfoMapPtr & keys)90     void setKeys(const TSIGKeyInfoMapPtr& keys) {
91         keys_ = keys;
92     }
93 
94     /// @brief Returns information about control socket
95     /// @return pointer to the Element that holds control-socket map
getControlSocketInfo()96     const isc::data::ConstElementPtr getControlSocketInfo() const {
97         return (control_socket_);
98     }
99 
100     /// @brief Sets information about the control socket
101     /// @param control_socket Element that holds control-socket map
setControlSocketInfo(const isc::data::ConstElementPtr & control_socket)102     void setControlSocketInfo(const isc::data::ConstElementPtr& control_socket) {
103         control_socket_ = control_socket;
104     }
105 
106     /// @brief Returns non-const reference to configured hooks libraries.
107     ///
108     /// @return non-const reference to configured hooks libraries.
getHooksConfig()109     isc::hooks::HooksConfig& getHooksConfig() {
110         return (hooks_config_);
111     }
112 
113     /// @brief Returns const reference to configured hooks libraries.
114     ///
115     /// @return const reference to configured hooks libraries.
getHooksConfig()116     const isc::hooks::HooksConfig& getHooksConfig() const {
117         return (hooks_config_);
118     }
119 
120     /// @brief Unparse a configuration object
121     ///
122     /// @return a pointer to a configuration
123     virtual isc::data::ElementPtr toElement() const;
124 
125 protected:
126     /// @brief Copy constructor for use by derivations in clone().
127     D2CfgContext(const D2CfgContext& rhs);
128 
129 private:
130     /// @brief Private assignment operator to avoid potential for slicing.
131     D2CfgContext& operator=(const D2CfgContext& rhs);
132 
133     /// @brief Global level parameter storage
134     D2ParamsPtr d2_params_;
135 
136     /// @brief Forward domain list manager.
137     DdnsDomainListMgrPtr forward_mgr_;
138 
139     /// @brief Reverse domain list manager.
140     DdnsDomainListMgrPtr reverse_mgr_;
141 
142     /// @brief Storage for the map of TSIGKeyInfos.
143     TSIGKeyInfoMapPtr keys_;
144 
145     /// @brief Pointer to the control-socket information.
146     isc::data::ConstElementPtr control_socket_;
147 
148     /// @brief Configured hooks libraries.
149     isc::hooks::HooksConfig hooks_config_;
150 };
151 
152 /// @brief Defines a pointer for DdnsDomain instances.
153 typedef boost::shared_ptr<DdnsDomainListMgr> DdnsDomainListMgrPtr;
154 
155 /// @brief DHCP-DDNS Configuration Manager
156 ///
157 /// Provides the mechanisms for managing the DHCP-DDNS application's
158 /// configuration.  This includes services for parsing sets of configuration
159 /// values, storing the parsed information in its converted form,
160 /// and retrieving the information on demand.
161 class D2CfgMgr : public process::DCfgMgrBase {
162 public:
163     /// @brief Reverse zone suffix added to IPv4 addresses for reverse lookups
164     /// @todo This should be configurable.
165     static const char* IPV4_REV_ZONE_SUFFIX;
166 
167     /// @brief Reverse zone suffix added to IPv6 addresses for reverse lookups
168     /// @todo This should be configurable.
169     static const char* IPV6_REV_ZONE_SUFFIX;
170 
171     /// @brief Constructor
172     D2CfgMgr();
173 
174     /// @brief Destructor
175     virtual ~D2CfgMgr();
176 
177     /// @brief Convenience method that returns the D2 configuration context.
178     ///
179     /// @return returns a pointer to the configuration context.
getD2CfgContext()180     D2CfgContextPtr getD2CfgContext() {
181         return (boost::dynamic_pointer_cast<D2CfgContext>(getContext()));
182     }
183 
184     /// @brief Returns whether or not forward updates are enabled.
185     ///
186     /// This method currently uses the presence or absence of Forward DDNS
187     /// Domains to determine if forward updates are enabled or disabled.
188     /// @todo This could be expanded to include the check of a configurable
189     /// boolean value.
190     ///
191     /// @return true if forward updates are enabled, false otherwise.
192     bool forwardUpdatesEnabled();
193 
194     /// @brief Returns whether or not reverse updates are enabled.
195     ///
196     /// This method currently uses the presence or absence of Reverse DDNS
197     /// Domains to determine if reverse updates are enabled or disabled.
198     /// @todo This could be expanded to include the check of a configurable
199     /// boolean value.
200     ///
201     /// @return true if reverse updates are enabled, false otherwise.
202     bool reverseUpdatesEnabled();
203 
204     /// @brief Matches a given FQDN to a forward domain.
205     ///
206     /// This calls the matchDomain method of the forward domain manager to
207     /// match the given FQDN to a forward domain.
208     ///
209     /// @param fqdn is the name for which to look.
210     /// @param domain receives the matching domain. Note that it will be reset
211     /// upon entry and only set if a match is subsequently found.
212     ///
213     /// @return returns true if a match is found, false otherwise.
214     /// @throw throws D2CfgError if given an invalid fqdn.
215     bool matchForward(const std::string& fqdn, DdnsDomainPtr& domain);
216 
217     /// @brief Matches a given IP address to a reverse domain.
218     ///
219     /// This calls the matchDomain method of the reverse domain manager to
220     /// match the given IPv4 or IPv6 address to a reverse domain.
221     ///
222     /// @param ip_address is the name for which to look.
223     /// @param domain receives the matching domain. Note that it will be reset
224     /// upon entry and only set if a match is subsequently found.
225     ///
226     /// @return returns true if a match is found, false otherwise.
227     /// @throw throws D2CfgError if given an invalid fqdn.
228     bool matchReverse(const std::string& ip_address, DdnsDomainPtr& domain);
229 
230     /// @brief Generate a reverse order string for the given IP address
231     ///
232     /// This method creates a string containing the given IP address
233     /// contents in reverse order.  This format is used for matching
234     /// against reverse DDNS domains in DHCP_DDNS configuration.
235     /// After reversing the syllables of the address, it appends the
236     /// appropriate suffix.
237     ///
238     /// @param address string containing a valid IPv4 or IPv6 address.
239     ///
240     /// @return a std::string containing the reverse order address.
241     ///
242     /// @throw D2CfgError if given an invalid address.
243     static std::string reverseIpAddress(const std::string& address);
244 
245     /// @brief Generate a reverse order string for the given IP address
246     ///
247     /// This method creates a string containing the given IP address
248     /// contents in reverse order.  This format is used for matching
249     /// against reverse DDNS domains in DHCP_DDNS configuration.
250     /// After reversing the syllables of the address, it appends the
251     /// appropriate suffix.
252     ///
253     /// Example:
254     ///   input:  192.168.1.15
255     ///  output:  15.1.168.192.in-addr.arpa.
256     ///
257     /// @param ioaddr is the IPv4 IOaddress to convert
258     ///
259     /// @return a std::string containing the reverse order address.
260     ///
261     /// @throw D2CfgError if not given an IPv4  address.
262     static std::string reverseV4Address(const isc::asiolink::IOAddress& ioaddr);
263 
264     /// @brief Generate a reverse order string for the given IP address
265     ///
266     /// This method creates a string containing the given IPv6 address
267     /// contents in reverse order.  This format is used for matching
268     /// against reverse DDNS domains in DHCP_DDNS configuration.
269     /// After reversing the syllables of the address, it appends the
270     /// appropriate suffix.
271     ///
272     /// IPv6 example:
273     /// input:  2001:db8:302:99::
274     /// output:
275     ///0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.9.9.0.0.2.0.3.0.8.B.D.0.1.0.0.2.ip6.arpa.
276     ///
277     /// @param ioaddr string containing a valid IPv6 address.
278     ///
279     /// @return a std::string containing the reverse order address.
280     ///
281     /// @throw D2CfgError if not given an IPv6 address.
282     static std::string reverseV6Address(const isc::asiolink::IOAddress& ioaddr);
283 
284     /// @brief Convenience method fetches the D2Params from context
285     /// @return reference to const D2ParamsPtr
286     const D2ParamsPtr& getD2Params();
287 
288     /// @brief Convenience method fetches information about control socket
289     /// from context
290     /// @return pointer to the Element that holds control-socket map
291     const isc::data::ConstElementPtr getControlSocketInfo();
292 
293     /// @brief Returns configuration summary in the textual format.
294     ///
295     /// @param selection Bitfield which describes the parts of the configuration
296     /// to be returned. This parameter is ignored for the D2.
297     ///
298     /// @return Summary of the configuration in the textual format.
299     virtual std::string getConfigSummary(const uint32_t selection) override;
300 
301     std::list<std::list<std::string>> jsonPathsToRedact() const final override;
302 
303 protected:
304     /// @brief Parses configuration of the D2.
305     ///
306     /// @param config Pointer to a configuration specified for D2.
307     /// @param check_only Boolean flag indicating if this method should
308     /// only verify correctness of the provided configuration.
309     /// @return Pointer to a result of configuration parsing.
310     virtual isc::data::ConstElementPtr
311     parse(isc::data::ConstElementPtr config, bool check_only) override;
312 
313     /// @brief Adds default values to the given config
314     ///
315     /// Adds the D2 default values to the configuration Element map. This
316     /// method is invoked by @c DCfgMgrBase::parseConfig().
317     ///
318     /// @param mutable_config - configuration to which defaults should be added
319     virtual void setCfgDefaults(isc::data::ElementPtr mutable_config) override;
320 
321     /// @brief Creates an new, blank D2CfgContext context
322     ///
323     /// This method is used at the beginning of configuration process to
324     /// create a fresh, empty copy of a D2CfgContext. This new context will
325     /// be populated during the configuration process and will replace the
326     /// existing context provided the configuration process completes without
327     /// error.
328     ///
329     /// @return Returns a ConfigPtr to the new context instance.
330     virtual process::ConfigPtr createNewContext() override;
331 };
332 
333 /// @brief Defines a shared pointer to D2CfgMgr.
334 typedef boost::shared_ptr<D2CfgMgr> D2CfgMgrPtr;
335 
336 } // end of isc::d2 namespace
337 } // end of isc namespace
338 
339 #endif // D2_CFG_MGR_H
340