Kea  1.9.9-git
network.cc
Go to the documentation of this file.
1 // Copyright (C) 2017-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 #include <config.h>
8 
9 #include <dhcp/dhcp4.h>
10 #include <dhcp/option_custom.h>
11 #include <dhcp/option_space.h>
12 #include <dhcpsrv/network.h>
13 #include <boost/pointer_cast.hpp>
14 
15 using namespace isc::asiolink;
16 using namespace isc::data;
17 using namespace isc::util;
18 
19 namespace isc {
20 namespace dhcp {
21 
22 void
23 Network::RelayInfo::addAddress(const asiolink::IOAddress& addr) {
24  if (containsAddress(addr)) {
25  isc_throw (BadValue, "RelayInfo already contains address: "
26  << addr.toText());
27  }
28 
29  addresses_.push_back(addr);
30 }
31 
32 bool
33 Network::RelayInfo::hasAddresses() const {
34  return (!addresses_.empty());
35 }
36 
37 bool
38 Network::RelayInfo::containsAddress(const asiolink::IOAddress& addr) const {
39  for (auto address = addresses_.begin(); address != addresses_.end();
40  ++address) {
41  if ((*address) == addr) {
42  return (true);
43  }
44  }
45 
46  return (false);
47 }
48 
49 const IOAddressList&
50 Network::RelayInfo::getAddresses() const {
51  return (addresses_);
52 }
53 
54 void
55 Network::addRelayAddress(const asiolink::IOAddress& addr) {
56  relay_.addAddress(addr);
57 }
58 
59 bool
60 Network::hasRelays() const {
61  return (relay_.hasAddresses());
62 }
63 
64 bool
65 Network::hasRelayAddress(const asiolink::IOAddress& addr) const {
66  return (relay_.containsAddress(addr));
67 }
68 
69 const IOAddressList&
70 Network::getRelayAddresses() const {
71  return (relay_.getAddresses());
72 }
73 
74 bool
75 Network::clientSupported(const isc::dhcp::ClientClasses& classes) const {
76  if (client_class_.empty()) {
77  // There is no class defined for this network, so we do
78  // support everyone.
79  return (true);
80  }
81 
82  return (classes.contains(client_class_));
83 }
84 
85 void
86 Network::allowClientClass(const isc::dhcp::ClientClass& class_name) {
87  client_class_ = class_name;
88 }
89 
90 void
91 Network::requireClientClass(const isc::dhcp::ClientClass& class_name) {
92  if (!required_classes_.contains(class_name)) {
93  required_classes_.insert(class_name);
94  }
95 }
96 
97 const ClientClasses&
98 Network::getRequiredClasses() const {
99  return (required_classes_);
100 }
101 
103 Network::getGlobalProperty(Optional<IOAddress> property,
104  const std::string& global_name,
105  const std::string& /*min_name*/,
106  const std::string& /*max_name*/) const {
107  if (!global_name.empty() && fetch_globals_fn_) {
108  ConstElementPtr globals = fetch_globals_fn_();
109  if (globals && (globals->getType() == Element::map)) {
110  ConstElementPtr global_param = globals->get(global_name);
111  if (global_param) {
112  std::string global_str = global_param->stringValue();
113  if (!global_str.empty()) {
114  return (IOAddress(global_str));
115  }
116  }
117  }
118  }
119  return (property);
120 }
121 
123 Network::toElement() const {
124  ElementPtr map = Element::createMap();
125 
126  // Set user-context
127  contextToElement(map);
128 
129  // Set interface
130  if (!iface_name_.unspecified()) {
131  map->set("interface", Element::create(iface_name_.get()));
132  }
133 
134  ElementPtr relay_map = Element::createMap();
135  ElementPtr address_list = Element::createList();
136  const IOAddressList addresses = getRelayAddresses();
137  for (auto address = addresses.begin(); address != addresses.end(); ++address) {
138  address_list->add(Element::create((*address).toText()));
139  }
140 
141  relay_map->set("ip-addresses", address_list);
142  map->set("relay", relay_map);
143 
144  // Set client-class
145  if (!client_class_.unspecified()) {
146  map->set("client-class", Element::create(client_class_.get()));
147  }
148 
149  // Set require-client-classes
150  const ClientClasses& classes = getRequiredClasses();
151  if (!classes.empty()) {
152  ElementPtr class_list = Element::createList();
153  for (ClientClasses::const_iterator it = classes.cbegin();
154  it != classes.cend(); ++it) {
155  class_list->add(Element::create(*it));
156  }
157  map->set("require-client-classes", class_list);
158  }
159 
160  // T1, T2, and Valid are optional for SharedNetworks, and
161  // T1 and T2 are optional for Subnet4 thus we will only
162  // output them if they are marked as specified.
163  if (!t1_.unspecified()) {
164  map->set("renew-timer",
165  Element::create(static_cast<long long>(t1_.get())));
166  }
167 
168  // Set rebind-timer
169  if (!t2_.unspecified()) {
170  map->set("rebind-timer",
171  Element::create(static_cast<long long>(t2_.get())));
172  }
173 
174  // Set valid-lifetime
175  if (!valid_.unspecified()) {
176  map->set("valid-lifetime",
177  Element::create(static_cast<long long>(valid_.get())));
178  if (valid_.getMin() < valid_.get()) {
179  map->set("min-valid-lifetime",
180  Element::create(static_cast<long long>(valid_.getMin())));
181  }
182  if (valid_.getMax() > valid_.get()) {
183  map->set("max-valid-lifetime",
184  Element::create(static_cast<long long>(valid_.getMax())));
185  }
186  }
187 
188  // Set reservations-global
189  if (!reservations_global_.unspecified()) {
190  map->set("reservations-global",
191  Element::create(reservations_global_.get()));
192  }
193 
194  // Set reservations-in-subnet
195  if (!reservations_in_subnet_.unspecified()) {
196  map->set("reservations-in-subnet",
197  Element::create(reservations_in_subnet_.get()));
198  }
199 
200  // Set reservations-out-of-pool
201  if (!reservations_out_of_pool_.unspecified()) {
202  map->set("reservations-out-of-pool",
203  Element::create(reservations_out_of_pool_.get()));
204  }
205 
206  // Set options
207  ConstCfgOptionPtr opts = getCfgOption();
208  map->set("option-data", opts->toElement());
209 
210  // Output calculate-tee-times and percentages if calculation is enabled.
211  if (!calculate_tee_times_.unspecified()) {
212  map->set("calculate-tee-times", Element::create(calculate_tee_times_));
213  }
214 
215  if (!t1_percent_.unspecified()) {
216  map->set("t1-percent", Element::create(t1_percent_));
217  }
218 
219  if (!t2_percent_.unspecified()) {
220  map->set("t2-percent", Element::create(t2_percent_));
221  }
222 
223  if (!ddns_send_updates_.unspecified()) {
224  map->set("ddns-send-updates", Element::create(ddns_send_updates_));
225  }
226 
227  if (!ddns_override_no_update_.unspecified()) {
228  map->set("ddns-override-no-update", Element::create(ddns_override_no_update_));
229  }
230 
231  if (!ddns_override_client_update_.unspecified()) {
232  map->set("ddns-override-client-update", Element::create(ddns_override_client_update_));
233  }
234 
235  if (!ddns_replace_client_name_mode_.unspecified()) {
236  map->set("ddns-replace-client-name",
237  Element::create(D2ClientConfig::
238  replaceClientNameModeToString(ddns_replace_client_name_mode_)));
239  }
240 
241  if (!ddns_generated_prefix_.unspecified()) {
242  map->set("ddns-generated-prefix", Element::create(ddns_generated_prefix_));
243  }
244 
245  if (!ddns_qualifying_suffix_.unspecified()) {
246  map->set("ddns-qualifying-suffix", Element::create(ddns_qualifying_suffix_));
247  }
248 
249  if (!hostname_char_set_.unspecified()) {
250  map->set("hostname-char-set", Element::create(hostname_char_set_));
251  }
252 
253  if (!hostname_char_replacement_.unspecified()) {
254  map->set("hostname-char-replacement", Element::create(hostname_char_replacement_));
255  }
256 
257  if (!store_extended_info_.unspecified()) {
258  map->set("store-extended-info", Element::create(store_extended_info_));
259  }
260 
261  if (!cache_threshold_.unspecified()) {
262  map->set("cache-threshold", Element::create(cache_threshold_));
263  }
264 
265  if (!cache_max_age_.unspecified()) {
266  map->set("cache-max-age",
267  Element::create(static_cast<long long>(cache_max_age_)));
268  }
269 
270  if (!ddns_update_on_renew_.unspecified()) {
271  map->set("ddns-update-on-renew", Element::create(ddns_update_on_renew_));
272  }
273 
274  if (!ddns_use_conflict_resolution_.unspecified()) {
275  map->set("ddns-use-conflict-resolution", Element::create(ddns_use_conflict_resolution_));
276  }
277 
278  return (map);
279 }
280 
281 void
282 Network4::setSiaddr(const Optional<IOAddress>& siaddr) {
283  if (!siaddr.get().isV4()) {
284  isc_throw(BadValue, "Can't set siaddr to non-IPv4 address "
285  << siaddr);
286  }
287  siaddr_ = siaddr;
288 }
289 
290 void
291 Network4::setSname(const Optional<std::string>& sname) {
292  sname_ = sname;
293 }
294 
295 void
296 Network4::setFilename(const Optional<std::string>& filename) {
297  filename_ = filename;
298 }
299 
301 Network4::toElement() const {
302  ElementPtr map = Network::toElement();
303 
304  // Set match-client-id
305  if (!match_client_id_.unspecified()) {
306  map->set("match-client-id", Element::create(match_client_id_.get()));
307  }
308 
309  // Set authoritative
310  if (!authoritative_.unspecified()) {
311  map->set("authoritative", Element::create(authoritative_.get()));
312  }
313 
314  // Set next-server
315  if (!siaddr_.unspecified()) {
316  map->set("next-server", Element::create(siaddr_.get().toText()));
317  }
318 
319  // Set server-hostname
320  if (!sname_.unspecified()) {
321  map->set("server-hostname", Element::create(sname_.get()));
322  }
323 
324  // Set boot-file-name
325  if (!filename_.unspecified()) {
326  map->set("boot-file-name",Element::create(filename_.get()));
327  }
328 
329  return (map);
330 }
331 
332 IOAddress
333 Network4::getServerId() const {
334  try {
335  OptionCustomPtr opt_server_id = boost::dynamic_pointer_cast<OptionCustom>
336  (cfg_option_->get(DHCP4_OPTION_SPACE, DHO_DHCP_SERVER_IDENTIFIER).option_);
337  if (opt_server_id) {
338  return (opt_server_id->readAddress());
339  }
340  } catch (const std::exception&) {
341  // Ignore any exceptions and simply return empty buffer.
342  }
343 
344  return (IOAddress::IPV4_ZERO_ADDRESS());
345 }
346 
348 Network6::toElement() const {
349  ElementPtr map = Network::toElement();
350 
351  // Set preferred-lifetime
352  if (!preferred_.unspecified()) {
353  map->set("preferred-lifetime",
354  Element::create(static_cast<long long>(preferred_.get())));
355  if (preferred_.getMin() < preferred_.get()) {
356  map->set("min-preferred-lifetime",
357  Element::create(static_cast<long long>(preferred_.getMin())));
358  }
359  if (preferred_.getMax() > preferred_.get()) {
360  map->set("max-preferred-lifetime",
361  Element::create(static_cast<long long>(preferred_.getMax())));
362  }
363  }
364 
365  // Set interface-id
366  if (interface_id_) {
367  std::vector<uint8_t> bin = interface_id_->getData();
368  std::string ifid;
369  ifid.resize(bin.size());
370  if (!bin.empty()) {
371  std::memcpy(&ifid[0], &bin[0], bin.size());
372  }
373  map->set("interface-id", Element::create(ifid));
374  }
375 
376  // Set rapid-commit
377  if (!rapid_commit_.unspecified()) {
378  map->set("rapid-commit", Element::create(rapid_commit_.get()));
379  }
380 
381  return (map);
382 }
383 
384 } // end of namespace isc::dhcp
385 } // end of namespace isc
std::vector< isc::asiolink::IOAddress > IOAddressList
List of IOAddresses.
Definition: network.h:38
boost::shared_ptr< OptionCustom > OptionCustomPtr
A pointer to the OptionCustom object.
boost::shared_ptr< const CfgOption > ConstCfgOptionPtr
Const pointer.
Definition: cfg_option.h:709
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition: edns.h:19
std::list< ClientClass >::const_iterator const_iterator
Type of iterators.
Definition: classify.h:47
bool contains(const ClientClass &x) const
returns if class x belongs to the defined classes
Definition: classify.h:99
const_iterator cend() const
Iterator to the past the end element.
Definition: classify.h:91
Acts as a storage vault for D2 client configuration.
Definition: d2_client_cfg.h:56
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:23
Defines the logger used by the top-level component of kea-dhcp-ddns.
T get() const
Retrieves the encapsulated value.
Definition: optional.h:112
#define DHCP4_OPTION_SPACE
global std option spaces
std::string ClientClass
Defines a single class name.
Definition: classify.h:37
bool empty() const
Check if classes is empty.
Definition: classify.h:73
Option with defined data fields represented as buffers that can be accessed using data field index...
Definition: option_custom.h:32
const_iterator cbegin() const
Iterator to the first element.
Definition: classify.h:86
A template representing an optional value.
Definition: optional.h:36
Container for storing client class names.
Definition: classify.h:43