1 // Copyright (C) 2013-2020 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_CLIENT_CFG_H
8 #define D2_CLIENT_CFG_H
9 
10 /// @file d2_client_cfg.h Defines the D2ClientConfig class.
11 /// This file defines the classes Kea uses to manage configuration needed to
12 /// act as a client of the kea-dhcp-ddns module (aka D2).
13 ///
14 
15 #include <asiolink/io_address.h>
16 #include <cc/cfg_to_element.h>
17 #include <cc/user_context.h>
18 #include <dhcp_ddns/ncr_io.h>
19 #include <exceptions/exceptions.h>
20 #include <util/optional.h>
21 
22 #include <boost/shared_ptr.hpp>
23 
24 #include <stdint.h>
25 #include <string>
26 #include <vector>
27 
28 namespace isc {
29 namespace dhcp {
30 
31 /// An exception that is thrown if an error occurs while configuring
32 /// the D2 DHCP DDNS client.
33 class D2ClientError : public isc::Exception {
34 public:
35 
36     /// @brief constructor
37     ///
38     /// @param file name of the file, where exception occurred
39     /// @param line line of the file, where exception occurred
40     /// @param what text description of the issue that caused exception
D2ClientError(const char * file,size_t line,const char * what)41     D2ClientError(const char* file, size_t line, const char* what)
42         : isc::Exception(file, line, what) {}
43 };
44 
45 /// @brief Callback function for @c D2ClientConfig that retrieves globally
46 /// configured parameters.
47 typedef std::function<data::ConstElementPtr()> FetchNetworkGlobalsFn;
48 
49 
50 /// @brief Acts as a storage vault for D2 client configuration
51 ///
52 /// A simple container class for storing and retrieving the configuration
53 /// parameters associated with DHCP-DDNS and acting as a client of D2.
54 /// Instances of this class may be constructed through configuration parsing.
55 ///
56 class D2ClientConfig : public data::UserContext, public isc::data::CfgToElement {
57 public:
58     /// @brief Default configuration constants.
59     static const char* DFT_SERVER_IP;
60     static const size_t DFT_SERVER_PORT;
61     static const char* DFT_V4_SENDER_IP;
62     static const char* DFT_V6_SENDER_IP;
63     static const size_t DFT_SENDER_PORT;
64     static const size_t DFT_MAX_QUEUE_SIZE;
65     static const char* DFT_NCR_PROTOCOL;
66     static const char* DFT_NCR_FORMAT;
67     static const bool DFT_OVERRIDE_NO_UPDATE;
68     static const bool DFT_OVERRIDE_CLIENT_UPDATE;
69     static const char* DFT_REPLACE_CLIENT_NAME_MODE;
70     static const char* DFT_GENERATED_PREFIX;
71     static const char* DFT_HOSTNAME_CHAR_SET;
72     static const char* DFT_HOSTNAME_CHAR_REPLACEMENT;
73 
74     /// @brief Defines the client name replacement modes.
75     enum ReplaceClientNameMode  {
76         RCM_NEVER,
77         RCM_ALWAYS,
78         RCM_WHEN_PRESENT,
79         RCM_WHEN_NOT_PRESENT
80     };
81 
82     /// @brief Constructor
83     ///
84     /// @param enable_updates Enables DHCP-DDNS updates
85     /// @param server_ip IP address of the kea-dhcp-ddns server (IPv4 or IPv6)
86     /// @param server_port IP port of the kea-dhcp-ddns server
87     /// @param sender_ip IP address of the kea-dhcp-ddns server (IPv4 or IPv6)
88     /// @param sender_port IP port of the kea-dhcp-ddns server
89     /// @param max_queue_size  maximum NCRs allowed in sender's queue
90     /// @param ncr_protocol Socket protocol to use with kea-dhcp-ddns
91     /// Currently only UDP is supported.
92     /// @param ncr_format Format of the kea-dhcp-ddns requests.
93     /// Currently only JSON format is supported.
94     /// @c enable_updates is mandatory, other parameters are optional.
95     ///
96     /// @throw D2ClientError if given an invalid protocol or format.
97     D2ClientConfig(const bool enable_updates,
98                    const isc::asiolink::IOAddress& server_ip,
99                    const size_t server_port,
100                    const isc::asiolink::IOAddress& sender_ip,
101                    const size_t sender_port,
102                    const size_t max_queue_size,
103                    const dhcp_ddns::NameChangeProtocol& ncr_protocol,
104                    const dhcp_ddns::NameChangeFormat& ncr_format);
105 
106     /// @brief Default constructor
107     /// The default constructor creates an instance that has updates disabled.
108     D2ClientConfig();
109 
110     /// @brief Destructor
111     virtual ~D2ClientConfig();
112 
113     /// @brief Return whether or not DHCP-DDNS updating is enabled.
getEnableUpdates()114     bool getEnableUpdates() const {
115         return(enable_updates_);
116     }
117 
118     /// @brief Return the IP address of kea-dhcp-ddns (IPv4 or IPv6).
getServerIp()119     const isc::asiolink::IOAddress& getServerIp() const {
120         return(server_ip_);
121     }
122 
123     /// @brief Return the IP port of kea-dhcp-ddns.
getServerPort()124     size_t getServerPort() const {
125         return(server_port_);
126     }
127 
128     /// @brief Return the IP address client should use to send
getSenderIp()129     const isc::asiolink::IOAddress& getSenderIp() const {
130         return(sender_ip_);
131     }
132 
133     /// @brief Return the IP port client should use to send
getSenderPort()134     size_t getSenderPort() const {
135         return(sender_port_);
136     }
137 
138     /// @brief Return Maximum sender queue size
getMaxQueueSize()139     size_t getMaxQueueSize() const {
140         return(max_queue_size_);
141     }
142 
143     /// @brief Return the socket protocol to use with kea-dhcp-ddns.
getNcrProtocol()144     const dhcp_ddns::NameChangeProtocol& getNcrProtocol() const {
145          return(ncr_protocol_);
146     }
147 
148     /// @brief Return the kea-dhcp-ddns request format.
getNcrFormat()149     const dhcp_ddns::NameChangeFormat& getNcrFormat() const {
150         return(ncr_format_);
151     }
152 
153     /// @brief Compares two D2ClientConfigs for equality
154     bool operator == (const D2ClientConfig& other) const;
155 
156     /// @brief Compares two D2ClientConfigs for inequality
157     bool operator != (const D2ClientConfig& other) const;
158 
159     /// @brief Generates a string representation of the class contents.
160     std::string toText() const;
161 
162     /// @brief Sets enable-updates flag to the given value.
163     ///
164     /// This is the only value that may be altered outside the constructor
165     /// as it may be desirable to toggle it off and on when dealing with
166     /// D2 IO errors.
167     ///
168     /// @param enable boolean value to assign to the enable-updates flag
169     void enableUpdates(bool enable);
170 
171     /// @brief Converts labels to  ReplaceClientNameMode enum values.
172     ///
173     /// @param mode_str text to convert to an enum.
174     /// Valid string values: "never", "always", "when-present",
175     /// "when-not-present" (case-insensitive)
176     ///
177     /// @return NameChangeFormat value which maps to the given string.
178     ///
179     /// @throw isc::BadValue if given a string value which does not map to an
180     /// enum value.
181     static ReplaceClientNameMode stringToReplaceClientNameMode(const std::string& mode_str);
182 
183     /// @brief Converts NameChangeFormat enums to text labels.
184     ///
185     /// @param mode enum value to convert to label
186     ///
187     /// @return std:string containing the text label if the value is valid, or
188     /// "unknown" if not.
189     static std::string replaceClientNameModeToString(const ReplaceClientNameMode& mode);
190 
191     /// @brief Unparse a configuration object
192     ///
193     /// @return a pointer to unparsed configuration
194     virtual isc::data::ElementPtr toElement() const;
195 
196     /// @brief Validates member values.
197     ///
198     /// Method is used by the constructor to validate member contents.
199     ///
200     /// @throw D2ClientError if given an invalid protocol or format.
201     virtual void validateContents();
202 
203 private:
204     /// @brief Indicates whether or not DHCP DDNS updating is enabled.
205     bool enable_updates_;
206 
207     /// @brief IP address of the kea-dhcp-ddns server (IPv4 or IPv6).
208     isc::asiolink::IOAddress server_ip_;
209 
210     /// @brief IP port of the kea-dhcp-ddns server.
211     size_t server_port_;
212 
213     /// @brief IP address on which the client should send
214     isc::asiolink::IOAddress sender_ip_;
215 
216     /// @brief IP port on which the client should send
217     size_t sender_port_;
218 
219     /// @brief Maximum number of NCRs allowed to queue waiting to send
220     size_t max_queue_size_;
221 
222     /// @brief The socket protocol to use with kea-dhcp-ddns.
223     /// Currently only UDP is supported.
224     dhcp_ddns::NameChangeProtocol ncr_protocol_;
225 
226     /// @brief Format of the kea-dhcp-ddns requests.
227     /// Currently only JSON format is supported.
228     dhcp_ddns::NameChangeFormat ncr_format_;
229 };
230 
231 std::ostream&
232 operator<<(std::ostream& os, const D2ClientConfig& config);
233 
234 /// @brief Defines a pointer for D2ClientConfig instances.
235 typedef boost::shared_ptr<D2ClientConfig> D2ClientConfigPtr;
236 
237 } // namespace isc
238 } // namespace dhcp
239 
240 #endif
241