Kea 2.7.4
cfg_iface.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2024 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#include <dhcp/iface_mgr.h>
10#include <dhcpsrv/cfg_iface.h>
11#include <dhcpsrv/timer_mgr.h>
12#include <util/reconnect_ctl.h>
14#include <util/str.h>
15#include <algorithm>
16#include <functional>
17
18using namespace isc::asiolink;
19using namespace isc::data;
20using namespace isc::util;
21namespace ph = std::placeholders;
22
23namespace isc {
24namespace dhcp {
25
26const char* CfgIface::ALL_IFACES_KEYWORD = "*";
27
29
31 : wildcard_used_(false), socket_type_(SOCKET_RAW), re_detect_(false),
32 service_socket_require_all_(false), service_sockets_retry_wait_time_(5000),
33 service_sockets_max_retries_(0),
34 outbound_iface_(SAME_AS_INBOUND) {
35}
36
37void
39 IfaceMgr::instance().closeSockets();
40}
41
42bool
43CfgIface::equals(const CfgIface& other) const {
44 return (iface_set_ == other.iface_set_ &&
45 address_map_ == other.address_map_ &&
46 wildcard_used_ == other.wildcard_used_ &&
47 socket_type_ == other.socket_type_);
48}
49
50bool
51CfgIface::multipleAddressesPerInterfaceActive() {
52 for (auto const& iface : IfaceMgr::instance().getIfaces()) {
53 if (iface->countActive4() > 1) {
54 return (true);
55 }
56 }
57 return (false);
58}
59
60void
61CfgIface::openSockets(const uint16_t family, const uint16_t port,
62 const bool use_bcast) {
63 // Close any open sockets because we're going to modify some properties
64 // of the IfaceMgr. Those modifications require that sockets are closed.
66 // The loopback interface can be used only when:
67 // - UDP socket will be used, i.e. not IPv4 and RAW socket
68 // - the loopback interface is in the interface set or the address map.
69 bool loopback_used_ = false;
70 if ((family == AF_INET6) || (socket_type_ == SOCKET_UDP)) {
71 // Check interface set
72 for (auto const& iface_name : iface_set_) {
73 IfacePtr iface = IfaceMgr::instance().getIface(iface_name);
74 if (iface && iface->flag_loopback_) {
75 loopback_used_ = true;
76 }
77 }
78 // Check address map
79 for (auto const& unicast : address_map_) {
80 IfacePtr iface = IfaceMgr::instance().getIface(unicast.first);
81 if (iface && iface->flag_loopback_) {
82 loopback_used_ = true;
83 }
84 }
85 }
86 // If wildcard interface '*' was not specified, set all interfaces to
87 // inactive state. We will later enable them selectively using the
88 // interface names specified by the user. If wildcard interface was
89 // specified, mark all interfaces active. Mark loopback inactive when
90 // not explicitly allowed.
91 setState(family, !wildcard_used_, !loopback_used_);
92 IfaceMgr& iface_mgr = IfaceMgr::instance();
93 // Remove selection of unicast addresses from all interfaces.
94 iface_mgr.clearUnicasts();
95 // Allow the loopback interface when required.
96 iface_mgr.setAllowLoopBack(loopback_used_);
97 // For the DHCPv4 server, if the user has selected that raw sockets
98 // should be used, we will try to configure the Interface Manager to
99 // support the direct responses to the clients that don't have the
100 // IP address. This should effectively turn on the use of raw
101 // sockets. However, this may be unsupported on some operating
102 // systems, so there is no guarantee.
103 if ((family == AF_INET) && (!IfaceMgr::instance().isTestMode())) {
104 iface_mgr.setMatchingPacketFilter(socket_type_ == SOCKET_RAW);
105 if ((socket_type_ == SOCKET_RAW) &&
106 !iface_mgr.isDirectResponseSupported()) {
108 }
109 }
110 // If there is no wildcard interface specified, we will have to iterate
111 // over the names specified by the caller and enable them.
112 if (!wildcard_used_) {
113 for (auto const& iface_name : iface_set_) {
114 IfacePtr iface = IfaceMgr::instance().getIface(iface_name);
115 // This shouldn't really happen because we are checking the
116 // names of interfaces when they are being added (use()
117 // function). But, if someone has triggered detection of
118 // interfaces since then, some interfaces may have disappeared.
119 if (iface == NULL) {
121 "fail to open socket on interface '"
122 << iface_name << "' as this interface doesn't"
123 " exist");
124
125 } else if (family == AF_INET) {
126 iface->inactive4_ = false;
127 setIfaceAddrsState(family, true, *iface);
128
129 } else {
130 iface->inactive6_ = false;
131 }
132 }
133 }
134
135 // Select unicast sockets for DHCPv6 or activate specific IPv4 addresses
136 // for DHCPv4.
137 for (auto const& unicast : address_map_) {
138 IfacePtr iface = IfaceMgr::instance().getIface(unicast.first);
139 if (iface == NULL) {
141 "fail to open unicast socket on interface '"
142 << unicast.first << "' as this interface doesn't"
143 " exist");
144 }
145 if (family == AF_INET6) {
146 iface->addUnicast(unicast.second);
147 iface->inactive6_ = false;
148
149 } else {
150 iface->setActive(unicast.second, true);
151 iface->inactive4_ = false;
152 }
153 }
154
155 // Use broadcast only if we're using raw sockets. For the UDP sockets,
156 // we only handle the relayed (unicast) traffic.
157 const bool can_use_bcast = use_bcast && (socket_type_ == SOCKET_RAW);
158
159 // Opening multiple raw sockets handling brodcast traffic on the single
160 // interface may lead to processing the same message multiple times.
161 // We don't prohibit such configuration because raw sockets can as well
162 // handle the relayed traffic. We have to issue a warning, however, to
163 // draw administrator's attention.
164 if (family == AF_INET && can_use_bcast && multipleAddressesPerInterfaceActive()) {
166 }
167
168 reconnect_ctl_ = makeReconnectCtl();
169 auto sopen = openSocketsWithRetry(reconnect_ctl_, family, port, can_use_bcast);
170
171 if (!sopen) {
172 // If no socket were opened, log a warning because the server will
173 // not respond to any queries.
175 }
176}
177
178std::pair<bool, bool>
179CfgIface::openSocketsForFamily(const uint16_t family, const uint16_t port,
180 const bool can_use_bcast, const bool skip_opened) {
181 bool no_errors = true;
182
183 // Set the callbacks which are called when the socket fails to open
184 // for some specific interface.
185 auto error_callback = [&no_errors](const std::string& errmsg) {
186 socketOpenErrorHandler(errmsg);
187 no_errors = false;
188 };
189
190 IfaceMgr::instance().detectIfaces(true);
191
192 bool sopen = false;
193 if (family == AF_INET) {
194 sopen = IfaceMgr::instance().openSockets4(port, can_use_bcast,
195 error_callback, skip_opened);
196 } else {
197 // use_bcast is ignored for V6.
198 sopen = IfaceMgr::instance().openSockets6(port, error_callback,
199 skip_opened);
200 }
201
202 return (std::make_pair(sopen, no_errors));
203}
204
205ReconnectCtlPtr CfgIface::makeReconnectCtl() const {
206 // Create unique timer name per instance.
207 std::string timer_name = "SocketReopenTimer";
208
209 auto on_fail_action = OnFailAction::SERVE_RETRY_CONTINUE;
211 on_fail_action = OnFailAction::SERVE_RETRY_EXIT;
212 }
213
214 // Add one attempt for an initial call.
215 auto reconnect_ctl = boost::make_shared<ReconnectCtl>("Socket", timer_name,
218 on_fail_action);
219
220 return (reconnect_ctl);
221}
222
223bool
224CfgIface::openSocketsWithRetry(ReconnectCtlPtr reconnect_ctl,
225 const uint16_t family, const uint16_t port,
226 const bool can_use_bcast) {
228
229 // Skip opened sockets in the retry calls.
230 bool is_initial_call = (reconnect_ctl->retriesLeft() == reconnect_ctl->maxRetries());
231 auto result_pair = openSocketsForFamily(family, port, can_use_bcast, !is_initial_call);
232 bool sopen = result_pair.first;
233 bool has_errors = !result_pair.second;
234
235 auto timer_name = reconnect_ctl->timerName();
236
237 // On the initial call, unregister the previous, pending timer.
238 if (is_initial_call && TimerMgr::instance()->isTimerRegistered(timer_name)) {
239 TimerMgr::instance()->unregisterTimer(timer_name);
240 }
241
242 // Has errors and can retry
243 if (has_errors && reconnect_ctl->retriesLeft() > 0) {
244 // Initial call is excluded from retries counter.
245 reconnect_ctl->checkRetries();
246 // Start the timer.
247 if (!TimerMgr::instance()->isTimerRegistered(timer_name)) {
248 TimerMgr::instance()->registerTimer(timer_name,
249 std::bind(&CfgIface::openSocketsWithRetry,
250 reconnect_ctl, family,
251 port, can_use_bcast),
252 reconnect_ctl->retryInterval(),
254 }
255 TimerMgr::instance()->setup(timer_name);
256 } else {
257 // Cancel the timer.
258 if (TimerMgr::instance()->isTimerRegistered(timer_name)) {
259 TimerMgr::instance()->unregisterTimer(timer_name);
260 }
261 // Has errors but retries exceed
262 if (has_errors) {
264 open_sockets_failed_callback_(reconnect_ctl);
265 }
266 }
267 }
268
269 return (sopen);
270}
271
272void
274 wildcard_used_ = false;
275 iface_set_.clear();
276 address_map_.clear();
277 useSocketType(AF_INET, SOCKET_RAW);
278}
279
280void
281CfgIface::setState(const uint16_t family, const bool inactive,
282 const bool loopback_inactive) const {
283 for (auto const& iface : IfaceMgr::instance().getIfaces()) {
284 bool iface_inactive = iface->flag_loopback_ ? loopback_inactive : inactive;
285 if (family == AF_INET) {
286 iface->inactive4_ = iface_inactive;
287 } else {
288 iface->inactive6_ = iface_inactive;
289 }
290
291 // Activate/deactivate all addresses.
292 setIfaceAddrsState(family, !inactive, *iface);
293 }
294}
295
296void
297CfgIface::setIfaceAddrsState(const uint16_t family, const bool active,
298 Iface& iface) const {
299 // Activate/deactivate all addresses.
300 for (auto const& addr : iface.getAddresses()) {
301 if (addr.get().getFamily() == family) {
302 iface.setActive(addr.get(), active);
303 }
304 }
305}
306
307void
308CfgIface::socketOpenErrorHandler(const std::string& errmsg) {
310}
311
312std::string
314 switch (socket_type_) {
315 case SOCKET_RAW:
316 return ("raw");
317
318 case SOCKET_UDP:
319 return ("udp");
320
321 default:
322 ;
323 }
324
325 isc_throw(Unexpected, "unsupported socket type " << socket_type_);
326}
327
329CfgIface::textToSocketType(const std::string& socket_type_name) const {
330 if (socket_type_name == "udp") {
331 return (SOCKET_UDP);
332
333 } else if (socket_type_name == "raw") {
334 return (SOCKET_RAW);
335
336 } else {
337 isc_throw(InvalidSocketType, "unsupported socket type '"
338 << socket_type_name << "'");
339 }
340}
341
344 return (outbound_iface_);
345}
346
347std::string
349 switch (outbound_iface_) {
350 case SAME_AS_INBOUND:
351 return ("same-as-inbound");
352 case USE_ROUTING:
353 return ("use-routing");
354 default:
355 isc_throw(Unexpected, "unsupported outbound-type " << socket_type_);
356 }
357
358}
359
361CfgIface::textToOutboundIface(const std::string& txt) {
362 if (txt == "same-as-inbound") {
363 return (SAME_AS_INBOUND);
364
365 } else if (txt == "use-routing") {
366 return (USE_ROUTING);
367
368 } else {
369 isc_throw(BadValue, "unsupported outbound interface type '"
370 << txt << "'");
371 }
372}
373
374void
376 outbound_iface_ = outbound_iface;
377}
378
379void
380CfgIface::use(const uint16_t family, const std::string& iface_name) {
381 // The interface name specified may have two formats:
382 // - "interface-name", e.g. eth0
383 // - "interface-name/address", e.g. eth0/10.0.0.1 or eth/2001:db8:1::1
384 // The latter format is used to open unicast socket on the specified
385 // interface. Here we are detecting which format was used and we strip
386 // all extraneous spaces.
387 size_t pos = iface_name.find("/");
388 std::string name;
389 std::string addr_str;
390 // There is no unicast address so the whole string is an interface name.
391 if (pos == std::string::npos) {
392 name = util::str::trim(iface_name);
393 if (name.empty()) {
395 "empty interface name used in configuration");
396
397 } else if (name != ALL_IFACES_KEYWORD) {
398 if (IfaceMgr::instance().getIface(name) == NULL) {
399 isc_throw(NoSuchIface, "interface '" << name
400 << "' doesn't exist in the system");
401 }
402
403 } else if (wildcard_used_) {
404 isc_throw(DuplicateIfaceName, "the wildcard interface '"
405 << ALL_IFACES_KEYWORD << "' can only be specified once");
406
407 } else {
410 wildcard_used_ = true;
411
412 }
413
414 } else {
415 // The interface name includes the address on which the socket should
416 // be opened, and we need to split interface name and the address to
417 // two variables.
418 name = util::str::trim(iface_name.substr(0, pos));
419 addr_str = util::str::trim(iface_name.substr(pos + 1));
420
421 // Interface name must not be empty.
422 if (name.empty()) {
424 "empty interface name specified in the"
425 " interface configuration");
426
427 }
428 // An address following the interface name must not be empty.
429 if (addr_str.empty()) {
431 "empty address specified in the interface"
432 << " configuration");
433
434 }
435
436 // Interface name must not be the wildcard name.
437 if (name == ALL_IFACES_KEYWORD) {
439 "wildcard interface name '" << ALL_IFACES_KEYWORD
440 << "' must not be used in conjunction with an"
441 " address");
442
443 }
444
445 // Interface must exist.
446 IfacePtr iface = IfaceMgr::instance().getIface(name);
447 if (!iface) {
448 isc_throw(NoSuchIface, "interface '" << name
449 << "' doesn't exist in the system");
450
451 }
452
453 // Convert address string. This may throw an exception if the address
454 // is invalid.
455 IOAddress addr(addr_str);
456
457 // Validate V6 address.
458 if (family == AF_INET6) {
459 // Check that the address is a valid unicast address.
460 if (!addr.isV6() || addr.isV6Multicast()) {
461 isc_throw(InvalidIfaceName, "address '" << addr << "' is not"
462 " a valid IPv6 unicast address");
463 }
464
465 // There are valid cases where link local address can be specified to
466 // receive unicast traffic, e.g. sent by relay agent.
467 if (addr.isV6LinkLocal()) {
469 .arg(addr.toText()).arg(name);
470 }
471
472 } else {
473 if (!addr.isV4()) {
474 isc_throw(InvalidIfaceName, "address '" << addr << "' is not"
475 " a valid IPv4 address");
476 }
477 }
478
479 // Interface must have this address assigned.
480 if (!iface->hasAddress(addr)) {
482 "interface '" << name << "' doesn't have address '"
483 << addr << "' assigned");
484 }
485
486 // For the IPv4, if the interface name was specified (instead of the interface-
487 // address tuple) all addresses are already activated. Adding an explicit address
488 // for the interface should result in error.
489 if ((family == AF_INET) && (iface_set_.find(iface->getName()) != iface_set_.end())) {
490 isc_throw(DuplicateIfaceName, "interface '" << iface->getName()
491 << "' has already been selected");
492 }
493
494 // Check if the address hasn't been selected already.
495 std::pair<const std::string, IOAddress> iface_address_tuple(name, addr);
496 if (std::find(address_map_.begin(), address_map_.end(),
497 iface_address_tuple) != address_map_.end()) {
498 isc_throw(DuplicateAddress, "must not select address '"
499 << addr << "' for interface '" << name << "' "
500 "because this address is already selected");
501 }
502
503 if (family == AF_INET6) {
505 .arg(addr.toText()).arg(name);
506
507 } else {
509 .arg(addr.toText()).arg(name);
510 }
511 address_map_.insert(std::pair<std::string, IOAddress>(name, addr));
512 }
513
514 // If interface name was explicitly specified without an address, we will
515 // insert the interface name to the set of enabled interfaces.
516 if ((name != ALL_IFACES_KEYWORD) && addr_str.empty()) {
517 // An interface has been selected or an IPv4 address on this interface
518 // has been selected it is not allowed to select the whole interface.
519 if ((iface_set_.find(name) != iface_set_.end()) ||
520 ((family == AF_INET) && address_map_.count(name) > 0)) {
521 isc_throw(DuplicateIfaceName, "interface '" << name
522 << "' has already been specified");
523 }
524
525 // Log that we're listening on the specific interface and that the
526 // address is not explicitly specified.
527 if (addr_str.empty()) {
529 }
530 iface_set_.insert(name);
531 }
532}
533
534void
535CfgIface::useSocketType(const uint16_t family,
536 const SocketType& socket_type) {
537 if (family != AF_INET) {
538 isc_throw(InvalidSocketType, "socket type must not be specified for"
539 " the DHCPv6 server");
540 }
541 socket_type_ = socket_type;
543 .arg(socketTypeToText());
544}
545
546void
547CfgIface::useSocketType(const uint16_t family,
548 const std::string& socket_type_name) {
549 useSocketType(family, textToSocketType(socket_type_name));
550}
551
555
556 // Set user context
557 contextToElement(result);
558
559 // Set interfaces
561 if (wildcard_used_) {
562 ifaces->add(Element::create(std::string(ALL_IFACES_KEYWORD)));
563 }
564 for (auto const& iface : iface_set_) {
565 ifaces->add(Element::create(iface));
566 }
567 for (auto const& address : address_map_) {
568 std::string spec = address.first + "/" + address.second.toText();
569 ifaces->add(Element::create(spec));
570 }
571 result->set("interfaces", ifaces);
572
573 // Set dhcp-socket-type (no default because it is DHCPv4 specific)
574 // @todo emit raw if and only if DHCPv4
575 if (socket_type_ != SOCKET_RAW) {
576 result->set("dhcp-socket-type", Element::create(std::string("udp")));
577 }
578
579 if (outbound_iface_ != SAME_AS_INBOUND) {
580 result->set("outbound-interface", Element::create(outboundTypeToText()));
581 }
582
583 // Set re-detect
584 result->set("re-detect", Element::create(re_detect_));
585
586 // Set server socket binding
587 if (service_socket_require_all_) {
588 result->set("service-sockets-require-all", Element::create(service_socket_require_all_));
589 }
590
591 if (service_sockets_max_retries_ != 0) {
592 result->set("service-sockets-max-retries", Element::create(static_cast<int>(service_sockets_max_retries_)));
593 // If the max retries parameter is zero, the wait time is not used.
594 result->set("service-sockets-retry-wait-time", Element::create(static_cast<int>(service_sockets_retry_wait_time_)));
595 }
596
597 return (result);
598}
599
600} // end of isc::dhcp namespace
601} // end of isc namespace
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown when an unexpected error condition occurs.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
Represents selection of interfaces for DHCP server.
Definition cfg_iface.h:131
static const char * ALL_IFACES_KEYWORD
Keyword used to enable all interfaces.
Definition cfg_iface.h:155
void closeSockets() const
Convenience function which closes all open sockets.
Definition cfg_iface.cc:38
std::string socketTypeToText() const
Returns the socket type in the textual format.
Definition cfg_iface.cc:313
void reset()
Puts the interface configuration into default state.
Definition cfg_iface.cc:273
uint32_t getServiceSocketsRetryWaitTime() const
Indicates the socket service binding retry interval between attempts.
Definition cfg_iface.h:330
OutboundIface
Indicates how outbound interface is selected for relayed traffic.
Definition cfg_iface.h:143
@ USE_ROUTING
Server uses routing to determine the right interface to send response.
Definition cfg_iface.h:148
@ SAME_AS_INBOUND
Server sends responses over the same interface on which queries are received.
Definition cfg_iface.h:146
OutboundIface getOutboundIface() const
Returns outbound interface selection mode.
Definition cfg_iface.cc:343
CfgIface()
Constructor.
Definition cfg_iface.cc:30
bool getServiceSocketsRequireAll() const
Indicates that Kea must successfully bind all socket services on init.
Definition cfg_iface.h:316
void openSockets(const uint16_t family, const uint16_t port, const bool use_bcast=true)
Tries to open sockets on selected interfaces.
Definition cfg_iface.cc:61
static OutboundIface textToOutboundIface(const std::string &txt)
Converts text to outbound interface selection mode.
Definition cfg_iface.cc:361
void use(const uint16_t family, const std::string &iface_name)
Select interface to be used to receive DHCP traffic.
Definition cfg_iface.cc:380
bool equals(const CfgIface &other) const
Compares two CfgIface objects for equality.
Definition cfg_iface.cc:43
SocketType
Socket type used by the DHCPv4 server.
Definition cfg_iface.h:135
@ SOCKET_UDP
Datagram socket, i.e. IP/UDP socket.
Definition cfg_iface.h:139
@ SOCKET_RAW
Raw socket, used for direct DHCPv4 traffic.
Definition cfg_iface.h:137
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
Definition cfg_iface.cc:553
std::string outboundTypeToText() const
Returns outbound interface selection mode as string.
Definition cfg_iface.cc:348
void setOutboundIface(const OutboundIface &outbound_iface)
Sets outbound interface selection mode.
Definition cfg_iface.cc:375
SocketType textToSocketType(const std::string &socket_type_name) const
Converts the socket type in the textual format to the type represented by the SocketType.
Definition cfg_iface.cc:329
static OpenSocketsFailedCallback open_sockets_failed_callback_
Optional callback function to invoke if all retries of the opening sockets fail.
Definition cfg_iface.h:361
void useSocketType(const uint16_t family, const SocketType &socket_type)
Sets the specified socket type to be used by the server.
Definition cfg_iface.cc:535
std::function< void(util::ReconnectCtlPtr)> OpenSocketsFailedCallback
Represents a callback invoked if all retries of the opening sockets fail.
Definition cfg_iface.h:357
uint32_t getServiceSocketsMaxRetries() const
Indicates the maximum number of service sockets bind attempts.
Definition cfg_iface.h:344
Exception thrown when duplicated address specified.
Definition cfg_iface.h:45
Exception thrown when duplicated interface names specified.
Definition cfg_iface.h:24
Handles network interfaces, transmission and reception.
Definition iface_mgr.h:656
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition iface_mgr.cc:54
Exception thrown when specified interface name is invalid.
Definition cfg_iface.h:31
Exception thrown when invalid socket type has been specified for the given family.
Definition cfg_iface.h:61
Exception thrown when specified unicast address is not assigned to the interface specified.
Definition cfg_iface.h:53
Exception thrown when specified interface doesn't exist in a system.
Definition cfg_iface.h:38
static const TimerMgrPtr & instance()
Returns pointer to the sole instance of the TimerMgr.
Definition timer_mgr.cc:446
RAII class creating a critical section.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
Definition macros.h:20
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Definition macros.h:26
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Definition macros.h:14
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
Definition dhcpsrv_log.h:56
const isc::log::MessageID DHCPSRV_CFGMGR_ADD_IFACE
boost::shared_ptr< Iface > IfacePtr
Type definition for the pointer to an Iface object.
Definition iface_mgr.h:487
const isc::log::MessageID DHCPSRV_CFGMGR_USE_ADDRESS
const isc::log::MessageID DHCPSRV_MULTIPLE_RAW_SOCKETS_PER_IFACE
const isc::log::MessageID DHCPSRV_CFGMGR_SOCKET_TYPE_SELECT
const isc::log::MessageID DHCPSRV_CFGMGR_ALL_IFACES_ACTIVE
const isc::log::MessageID DHCPSRV_CFGMGR_UNICAST_LINK_LOCAL
const isc::log::MessageID DHCPSRV_NO_SOCKETS_OPEN
const isc::log::MessageID DHCPSRV_OPEN_SOCKET_FAIL
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
Definition dhcpsrv_log.h:26
const isc::log::MessageID DHCPSRV_CFGMGR_SOCKET_RAW_UNSUPPORTED
const isc::log::MessageID DHCPSRV_CFGMGR_USE_UNICAST
string trim(const string &input)
Trim leading and trailing spaces.
Definition str.cc:32
boost::shared_ptr< ReconnectCtl > ReconnectCtlPtr
Pointer to an instance of ReconnectCtl.
Defines the logger used by the top-level component of kea-lfc.
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.