Kea  1.5.0
d2_client_cfg.cc
Go to the documentation of this file.
1 // Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <dhcp_ddns/ncr_udp.h>
10 #include <dhcpsrv/d2_client_cfg.h>
11 #include <dhcpsrv/dhcpsrv_log.h>
12 
13 #include <boost/algorithm/string/predicate.hpp>
14 
15 #include <string>
16 
17 using namespace std;
18 using namespace isc::asiolink;
19 using namespace isc::data;
20 
21 namespace isc {
22 namespace dhcp {
23 
25 const char* D2ClientConfig::DFT_SERVER_IP = "127.0.0.1";
26 const size_t D2ClientConfig::DFT_SERVER_PORT = 53001;
27 const char* D2ClientConfig::DFT_V4_SENDER_IP = "0.0.0.0";
28 const char* D2ClientConfig::DFT_V6_SENDER_IP = "::";
29 const size_t D2ClientConfig::DFT_SENDER_PORT = 0;
30 const size_t D2ClientConfig::DFT_MAX_QUEUE_SIZE = 1024;
31 const char* D2ClientConfig::DFT_NCR_PROTOCOL = "UDP";
32 const char* D2ClientConfig::DFT_NCR_FORMAT = "JSON";
33 const bool D2ClientConfig::DFT_OVERRIDE_NO_UPDATE = false;
34 const bool D2ClientConfig::DFT_OVERRIDE_CLIENT_UPDATE = false;
35 const char* D2ClientConfig::DFT_REPLACE_CLIENT_NAME_MODE = "NEVER";
36 const char* D2ClientConfig::DFT_GENERATED_PREFIX = "myhost";
37 const char* D2ClientConfig::DFT_HOSTNAME_CHAR_SET = "";
38 const char* D2ClientConfig::DFT_HOSTNAME_CHAR_REPLACEMENT = "";
39 
40 D2ClientConfig::ReplaceClientNameMode
41 D2ClientConfig::stringToReplaceClientNameMode(const std::string& mode_str) {
42  if (boost::iequals(mode_str, "never")) {
43  return (D2ClientConfig::RCM_NEVER);
44  }
45 
46  if (boost::iequals(mode_str, "always")) {
47  return (D2ClientConfig::RCM_ALWAYS);
48  }
49 
50  if (boost::iequals(mode_str, "when-present")) {
51  return (D2ClientConfig::RCM_WHEN_PRESENT);
52  }
53 
54  if (boost::iequals(mode_str, "when-not-present")) {
55  return (D2ClientConfig::RCM_WHEN_NOT_PRESENT);
56  }
57 
59  "Invalid ReplaceClientNameMode: " << mode_str);
60 }
61 
62 std::string
63 D2ClientConfig::replaceClientNameModeToString(const ReplaceClientNameMode& mode) {
64  switch (mode) {
65  case D2ClientConfig::RCM_NEVER:
66  return ("never");
67  case D2ClientConfig::RCM_ALWAYS:
68  return ("always");
69  case D2ClientConfig::RCM_WHEN_PRESENT:
70  return ("when-present");
71  case D2ClientConfig::RCM_WHEN_NOT_PRESENT:
72  return ("when-not-present");
73  default:
74  break;
75  }
76 
77  std::ostringstream stream;
78  stream << "unknown(" << mode << ")";
79  return (stream.str());
80 }
81 
82 D2ClientConfig::D2ClientConfig(const bool enable_updates,
83  const isc::asiolink::IOAddress& server_ip,
84  const size_t server_port,
85  const isc::asiolink::IOAddress& sender_ip,
86  const size_t sender_port,
87  const size_t max_queue_size,
88  const dhcp_ddns::
89  NameChangeProtocol& ncr_protocol,
90  const dhcp_ddns::
91  NameChangeFormat& ncr_format,
92  const bool override_no_update,
93  const bool override_client_update,
94  const ReplaceClientNameMode replace_client_name_mode,
95  const std::string& generated_prefix,
96  const std::string& qualifying_suffix,
97  const std::string& hostname_char_set,
98  const std::string& hostname_char_replacement)
99  : enable_updates_(enable_updates),
100  server_ip_(server_ip),
101  server_port_(server_port),
102  sender_ip_(sender_ip),
103  sender_port_(sender_port),
104  max_queue_size_(max_queue_size),
105  ncr_protocol_(ncr_protocol),
106  ncr_format_(ncr_format),
107  override_no_update_(override_no_update),
108  override_client_update_(override_client_update),
109  replace_client_name_mode_(replace_client_name_mode),
110  generated_prefix_(generated_prefix),
111  qualifying_suffix_(qualifying_suffix),
112  hostname_char_set_(hostname_char_set),
113  hostname_char_replacement_(hostname_char_replacement),
114  hostname_sanitizer_(0) {
116 }
117 
119  : enable_updates_(false),
120  server_ip_(isc::asiolink::IOAddress(DFT_SERVER_IP)),
121  server_port_(DFT_SERVER_PORT),
122  sender_ip_(isc::asiolink::IOAddress(DFT_V4_SENDER_IP)),
123  sender_port_(DFT_SENDER_PORT),
124  max_queue_size_(DFT_MAX_QUEUE_SIZE),
125  ncr_protocol_(dhcp_ddns::stringToNcrProtocol(DFT_NCR_PROTOCOL)),
126  ncr_format_(dhcp_ddns::stringToNcrFormat(DFT_NCR_FORMAT)),
127  override_no_update_(DFT_OVERRIDE_NO_UPDATE),
128  override_client_update_(DFT_OVERRIDE_CLIENT_UPDATE),
129  replace_client_name_mode_(stringToReplaceClientNameMode(DFT_REPLACE_CLIENT_NAME_MODE)),
130  generated_prefix_(DFT_GENERATED_PREFIX),
131  qualifying_suffix_(""),
132  hostname_char_set_(DFT_HOSTNAME_CHAR_SET),
133  hostname_char_replacement_(DFT_HOSTNAME_CHAR_SET),
134  hostname_sanitizer_(0) {
136 }
137 
139 
140 void
142  enable_updates_ = enable;
143 }
144 
145 void
147  if (ncr_format_ != dhcp_ddns::FMT_JSON) {
148  isc_throw(D2ClientError, "D2ClientConfig: NCR Format: "
149  << dhcp_ddns::ncrFormatToString(ncr_format_)
150  << " is not yet supported");
151  }
152 
153  if (ncr_protocol_ != dhcp_ddns::NCR_UDP) {
154  isc_throw(D2ClientError, "D2ClientConfig: NCR Protocol: "
155  << dhcp_ddns::ncrProtocolToString(ncr_protocol_)
156  << " is not yet supported");
157  }
158 
159  if (sender_ip_.getFamily() != server_ip_.getFamily()) {
160  isc_throw(D2ClientError, "D2ClientConfig: address family mismatch: "
161  << "server-ip: " << server_ip_.toText()
162  << " is: " << (server_ip_.isV4() ? "IPv4" : "IPv6")
163  << " while sender-ip: " << sender_ip_.toText()
164  << " is: " << (sender_ip_.isV4() ? "IPv4" : "IPv6"));
165  }
166 
167  if (server_ip_ == sender_ip_ && server_port_ == sender_port_) {
168  isc_throw(D2ClientError, "D2ClientConfig: server and sender cannot"
169  " share the exact same IP address/port: "
170  << server_ip_.toText() << "/" << server_port_);
171  }
172 
173  if (!hostname_char_set_.empty()) {
174  try {
175  hostname_sanitizer_.reset(new isc::util::str::StringSanitizer(hostname_char_set_,
176  hostname_char_replacement_));
177  } catch (const std::exception& ex) {
178  isc_throw(D2ClientError, "D2ClientConfig: hostname-char-set"
179  " is not a valid regular expression");
180  }
181  }
182 
185 }
186 
187 bool
189  return ((enable_updates_ == other.enable_updates_) &&
190  (server_ip_ == other.server_ip_) &&
191  (server_port_ == other.server_port_) &&
192  (sender_ip_ == other.sender_ip_) &&
193  (sender_port_ == other.sender_port_) &&
194  (max_queue_size_ == other.max_queue_size_) &&
195  (ncr_protocol_ == other.ncr_protocol_) &&
196  (ncr_format_ == other.ncr_format_) &&
197  (override_no_update_ == other.override_no_update_) &&
198  (override_client_update_ == other.override_client_update_) &&
199  (replace_client_name_mode_ == other.replace_client_name_mode_) &&
200  (generated_prefix_ == other.generated_prefix_) &&
201  (qualifying_suffix_ == other.qualifying_suffix_) &&
202  (hostname_char_set_ == other.hostname_char_set_) &&
203  (hostname_char_replacement_ == other.hostname_char_replacement_));
204 }
205 
206 bool
208  return (!(*this == other));
209 }
210 
211 std::string
213  std::ostringstream stream;
214 
215  stream << "enable_updates: " << (enable_updates_ ? "yes" : "no");
216  if (enable_updates_) {
217  stream << ", server-ip: " << server_ip_.toText()
218  << ", server-port: " << server_port_
219  << ", sender-ip: " << sender_ip_.toText()
220  << ", sender-port: " << sender_port_
221  << ", max-queue-size: " << max_queue_size_
222  << ", ncr-protocol: " << ncrProtocolToString(ncr_protocol_)
223  << ", ncr-format: " << ncrFormatToString(ncr_format_)
224  << ", override-no-update: " << (override_no_update_ ?
225  "yes" : "no")
226  << ", override-client-update: " << (override_client_update_ ?
227  "yes" : "no")
228  << ", replace-client-name: "
229  << replaceClientNameModeToString(replace_client_name_mode_)
230  << ", generated-prefix: [" << generated_prefix_ << "]"
231  << ", qualifying-suffix: [" << qualifying_suffix_ << "]"
232  << ", hostname-char-set: [" << hostname_char_set_ << "]"
233  << ", hostname-char-replacement: [" << hostname_char_replacement_ << "]";
234  }
235 
236  return (stream.str());
237 }
238 
241  ElementPtr result = Element::createMap();
242  // Set user context
243  contextToElement(result);
244  // Set enable-updates
245  result->set("enable-updates", Element::create(enable_updates_));
246  // Set qualifying-suffix
247  result->set("qualifying-suffix", Element::create(qualifying_suffix_));
248  // Set server-ip
249  result->set("server-ip", Element::create(server_ip_.toText()));
250  // Set server-port
251  result->set("server-port", Element::create(static_cast<long long>(server_port_)));
252  // Set sender-ip
253  result->set("sender-ip", Element::create(sender_ip_.toText()));
254  // Set sender-port
255  result->set("sender-port", Element::create(static_cast<long long>(sender_port_)));
256  // Set max-queue-size
257  result->set("max-queue-size", Element::create(static_cast<long long>(max_queue_size_)));
258  // Set ncr-protocol
259  result->set("ncr-protocol", Element::create(dhcp_ddns::ncrProtocolToString(ncr_protocol_)));
260  // Set ncr-format
261  result->set("ncr-format", Element::create(dhcp_ddns::ncrFormatToString(ncr_format_)));
262  // Set override-no-update
263  result->set("override-no-update", Element::create(override_no_update_));
264  // Set override-client-update
265  result->set("override-client-update", Element::create(override_client_update_));
266  // Set replace-client-name
267  result->set("replace-client-name",
268  Element::create(replaceClientNameModeToString(replace_client_name_mode_)));
269  // Set generated-prefix
270  result->set("generated-prefix", Element::create(generated_prefix_));
271  // Set hostname-char-set
272  result->set("hostname-char-set", Element::create(hostname_char_set_));
273  // Set hostname-char-replacement
274  result->set("hostname-char-replacement", Element::create(hostname_char_replacement_));
275  return (result);
276 }
277 
278 std::ostream&
279 operator<<(std::ostream& os, const D2ClientConfig& config) {
280  os << config.toText();
281  return (os);
282 }
283 
284 }; // namespace dhcp
285 
286 }; // namespace isc
isc::dhcp::D2ClientConfig::replaceClientNameModeToString
static std::string replaceClientNameModeToString(const ReplaceClientNameMode &mode)
Converts NameChangeFormat enums to text labels.
Definition: d2_client_cfg.cc:63
isc::dhcp::D2ClientConfig::operator==
bool operator==(const D2ClientConfig &other) const
Compares two D2ClientConfigs for equality.
Definition: d2_client_cfg.cc:188
d2_client_cfg.h
isc::dhcp::D2ClientConfig::validateContents
virtual void validateContents()
Validates member values.
Definition: d2_client_cfg.cc:146
isc::data
Definition: cfg_to_element.h:25
isc::dhcp::D2ClientConfig::enableUpdates
void enableUpdates(bool enable)
Sets enable-updates flag to the given value.
Definition: d2_client_cfg.cc:141
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc::dhcp::D2ClientConfig::ReplaceClientNameMode
ReplaceClientNameMode
Defines the client name replacement modes.
Definition: d2_client_cfg.h:72
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
isc::dhcp::D2ClientConfig::toElement
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition: d2_client_cfg.cc:240
dhcpsrv_log.h
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition: exceptions/exceptions.h:132
isc::dhcp::D2ClientConfig
Acts as a storage vault for D2 client configuration.
Definition: d2_client_cfg.h:53
isc::dhcp::D2ClientConfig::D2ClientConfig
D2ClientConfig()
Default constructor The default constructor creates an instance that has updates disabled.
Definition: d2_client_cfg.cc:118
isc::dhcp::D2ClientConfig::operator!=
bool operator!=(const D2ClientConfig &other) const
Compares two D2ClientConfigs for inequality.
Definition: d2_client_cfg.cc:207
isc::dhcp::D2ClientConfig::~D2ClientConfig
virtual ~D2ClientConfig()
Destructor.
Definition: d2_client_cfg.cc:138
isc::dhcp_ddns::FMT_JSON
@ FMT_JSON
Definition: ncr_msg.h:61
isc::util::str::StringSanitizer
Implements a regular expression based string scrubber.
Definition: strutil.h:268
isc::dhcp_ddns::NCR_UDP
@ NCR_UDP
Definition: ncr_io.h:67
isc::data::UserContext::contextToElement
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
Definition: user_context.cc:15
isc::dhcp_ddns::stringToNcrFormat
NameChangeFormat stringToNcrFormat(const std::string &fmt_str)
Function which converts labels to NameChangeFormat enum values.
Definition: ncr_msg.cc:27
isc::dhcp_ddns::ncrProtocolToString
std::string ncrProtocolToString(NameChangeProtocol protocol)
Function which converts NameChangeProtocol enums to text labels.
Definition: ncr_io.cc:30
isc::dhcp::D2ClientConfig::toText
std::string toText() const
Generates a string representation of the class contents.
Definition: d2_client_cfg.cc:212
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
isc::dhcp::operator<<
std::ostream & operator<<(std::ostream &os, const OpaqueDataTuple &tuple)
Inserts the OpaqueDataTuple as a string into stream.
Definition: opaque_data_tuple.cc:95
isc::dhcp::D2ClientError
An exception that is thrown if an error occurs while configuring the D2 DHCP DDNS client.
Definition: d2_client_cfg.h:34
isc::dhcp_ddns::ncrFormatToString
std::string ncrFormatToString(NameChangeFormat format)
Function which converts NameChangeFormat enums to text labels.
Definition: ncr_msg.cc:36
isc::dhcp_ddns::stringToNcrProtocol
NameChangeProtocol stringToNcrProtocol(const std::string &protocol_str)
Function which converts labels to NameChangeProtocol enum values.
Definition: ncr_io.cc:17
isc::dhcp_ddns::NameChangeFormat
NameChangeFormat
Defines the list of data wire formats supported.
Definition: ncr_msg.h:60
isc::dhcp_ddns::NameChangeProtocol
NameChangeProtocol
Defines the list of socket protocols supported.
Definition: ncr_io.h:66
ncr_udp.h
This file provides UDP socket based implementation for sending and receiving NameChangeRequests.