17 namespace ph = std::placeholders;
22 const char* CfgIface::ALL_IFACES_KEYWORD =
"*";
25 : wildcard_used_(false), socket_type_(SOCKET_RAW), re_detect_(false),
26 outbound_iface_(SAME_AS_INBOUND) {
36 return (iface_set_ == other.iface_set_ &&
37 address_map_ == other.address_map_ &&
38 wildcard_used_ == other.wildcard_used_ &&
39 socket_type_ == other.socket_type_);
43 CfgIface::multipleAddressesPerInterfaceActive()
const {
45 if (iface->countActive4() > 1) {
54 const bool use_bcast)
const {
61 bool loopback_used_ =
false;
62 if ((family == AF_INET6) || (socket_type_ ==
SOCKET_UDP)) {
64 for (IfaceSet::const_iterator iface_name = iface_set_.begin();
65 iface_name != iface_set_.end(); ++iface_name) {
67 if (iface && iface->flag_loopback_) {
68 loopback_used_ =
true;
72 for (ExplicitAddressMap::const_iterator unicast = address_map_.begin();
73 unicast != address_map_.end(); ++unicast) {
75 if (iface && iface->flag_loopback_) {
76 loopback_used_ =
true;
85 setState(family, !wildcard_used_, !loopback_used_);
106 if (!wildcard_used_) {
107 for (IfaceSet::const_iterator iface_name = iface_set_.begin();
108 iface_name != iface_set_.end(); ++iface_name) {
116 "fail to open socket on interface '"
117 << *iface_name <<
"' as this interface doesn't"
120 }
else if (family == AF_INET) {
121 iface->inactive4_ =
false;
122 setIfaceAddrsState(family,
true, *iface);
125 iface->inactive6_ =
false;
132 for (ExplicitAddressMap::const_iterator unicast = address_map_.begin();
133 unicast != address_map_.end(); ++unicast) {
137 "fail to open unicast socket on interface '"
138 << unicast->first <<
"' as this interface doesn't"
141 if (family == AF_INET6) {
142 iface->addUnicast(unicast->second);
143 iface->inactive6_ =
false;
146 iface->setActive(unicast->second,
true);
147 iface->inactive4_ =
false;
155 std::bind(&CfgIface::socketOpenErrorHandler, ph::_1);
157 if (family == AF_INET) {
160 const bool can_use_bcast = use_bcast && (socket_type_ ==
SOCKET_RAW);
166 if (can_use_bcast && multipleAddressesPerInterfaceActive()) {
184 wildcard_used_ =
false;
186 address_map_.clear();
191 CfgIface::setState(
const uint16_t family,
const bool inactive,
192 const bool loopback_inactive)
const {
194 bool iface_inactive = iface->flag_loopback_ ? loopback_inactive : inactive;
195 if (family == AF_INET) {
196 iface->inactive4_ = iface_inactive;
198 iface->inactive6_ = iface_inactive;
202 setIfaceAddrsState(family, !inactive, *iface);
207 CfgIface::setIfaceAddrsState(
const uint16_t family,
const bool active,
208 Iface& iface)
const {
211 if (addr.get().getFamily() == family) {
212 iface.setActive(addr.get(), active);
218 CfgIface::socketOpenErrorHandler(
const std::string& errmsg) {
224 switch (socket_type_) {
240 if (socket_type_name ==
"udp") {
243 }
else if (socket_type_name ==
"raw") {
248 << socket_type_name <<
"'");
254 return (outbound_iface_);
259 switch (outbound_iface_) {
261 return (
"same-as-inbound");
263 return (
"use-routing");
272 if (txt ==
"same-as-inbound") {
275 }
else if (txt ==
"use-routing") {
286 outbound_iface_ = outbound_iface;
297 size_t pos = iface_name.find(
"/");
299 std::string addr_str;
301 if (pos == std::string::npos) {
305 "empty interface name used in configuration");
310 <<
"' doesn't exist in the system");
313 }
else if (wildcard_used_) {
320 wildcard_used_ =
true;
334 "empty interface name specified in the"
335 " interface configuration");
339 if (addr_str.empty()) {
341 "empty address specified in the interface"
342 <<
" configuration");
350 <<
"' must not be used in conjunction with an"
359 <<
"' doesn't exist in the system");
368 if (family == AF_INET6) {
372 " a valid IPv6 unicast address");
379 .arg(addr.
toText()).arg(name);
385 " a valid IPv4 address");
390 if (!iface->hasAddress(addr)) {
392 "interface '" << name <<
"' doesn't have address '"
393 << addr <<
"' assigned");
399 if ((family == AF_INET) && (iface_set_.find(iface->getName()) != iface_set_.end())) {
401 <<
"' has already been selected");
405 std::pair<const std::string, IOAddress> iface_address_tuple(name, addr);
406 if (std::find(address_map_.begin(), address_map_.end(),
407 iface_address_tuple) != address_map_.end()) {
409 << addr <<
"' for interface '" << name <<
"' "
410 "because this address is already selected");
413 if (family == AF_INET6) {
415 .arg(addr.
toText()).arg(name);
419 .arg(addr.
toText()).arg(name);
421 address_map_.insert(std::pair<std::string, IOAddress>(name, addr));
429 if ((iface_set_.find(name) != iface_set_.end()) ||
430 ((family == AF_INET) && address_map_.count(name) > 0)) {
432 <<
"' has already been specified");
437 if (addr_str.empty()) {
440 iface_set_.insert(name);
447 if (family != AF_INET) {
449 " the DHCPv6 server");
451 socket_type_ = socket_type;
458 const std::string& socket_type_name) {
471 if (wildcard_used_) {
474 for (IfaceSet::const_iterator iface = iface_set_.cbegin();
475 iface != iface_set_.cend(); ++iface) {
476 ifaces->add(Element::create(*iface));
478 for (ExplicitAddressMap::const_iterator address = address_map_.cbegin();
479 address != address_map_.cend(); ++address) {
480 std::string spec = address->first +
"/" + address->second.toText();
481 ifaces->add(Element::create(spec));
483 result->set(
"interfaces", ifaces);
488 result->set(
"dhcp-socket-type", Element::create(std::string(
"udp")));
496 result->set(
"re-detect", Element::create(re_detect_));
const isc::log::MessageID DHCPSRV_NO_SOCKETS_OPEN
IfacePtr getIface(int ifindex)
Returns interface specified interface index.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
Exception thrown when invalid socket type has been specified for the given family.
void setAllowLoopBack(const bool allow_loopback)
Allows or disallows the loopback interface.
const isc::log::MessageID DHCPSRV_CFGMGR_ADD_IFACE
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
static OutboundIface textToOutboundIface(const std::string &txt)
Converts text to outbound interface selection mode.
Exception thrown when specified interface name is invalid.
boost::shared_ptr< Iface > IfacePtr
Type definition for the pointer to an Iface object.
virtual isc::data::ElementPtr toElement() const
Unparse a configuration object.
SocketType
Socket type used by the DHCPv4 server.
Raw socket, used for direct DHCPv4 traffic.
boost::shared_ptr< Element > ElementPtr
std::string socketTypeToText() const
Returns the socket type in the textual format.
bool openSockets6(const uint16_t port=DHCP6_SERVER_PORT, IfaceMgrErrorMsgCallback error_handler=0)
Opens IPv6 sockets on detected interfaces.
std::function< void(const std::string &errmsg)> IfaceMgrErrorMsgCallback
This type describes the callback function invoked when error occurs in the IfaceMgr.
Exception thrown when specified unicast address is not assigned to the interface specified.
Handles network interfaces, transmission and reception.
Exception thrown when specified interface doesn't exist in a system.
void contextToElement(data::ElementPtr map) const
Merge unparse a user_context object.
bool isV4() const
Convenience function to check for an IPv4 address.
Server uses routing to determine the right interface to send response.
bool equals(const CfgIface &other) const
Compares two CfgIface objects for equality.
void setMatchingPacketFilter(const bool direct_response_desired=false)
Set Packet Filter object to handle send/receive packets.
#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...
A generic exception that is thrown when an unexpected error condition occurs.
static const char * ALL_IFACES_KEYWORD
Keyword used to enable all interfaces.
void use(const uint16_t family, const std::string &iface_name)
Select interface to be used to receive DHCP traffic.
void clearUnicasts()
Clears unicast addresses on all interfaces.
void useSocketType(const uint16_t family, const SocketType &socket_type)
Sets the specified socket type to be used by the server.
const isc::log::MessageID DHCPSRV_CFGMGR_USE_UNICAST
Defines the logger used by the top-level component of kea-dhcp-ddns.
Datagram socket, i.e. IP/UDP socket.
const isc::log::MessageID DHCPSRV_CFGMGR_USE_ADDRESS
util::Optional< asiolink::IOAddress > Address
Address type.
void reset()
Puts the interface configuration into default state.
const isc::log::MessageID DHCPSRV_OPEN_SOCKET_FAIL
void closeSockets()
Closes all open sockets.
Exception thrown when duplicated interface names specified.
const isc::log::MessageID DHCPSRV_CFGMGR_SOCKET_TYPE_SELECT
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Server sends responses over the same interface on which queries are received.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
std::string toText() const
Convert the address to a string.
const isc::log::MessageID DHCPSRV_CFGMGR_UNICAST_LINK_LOCAL
const int DHCPSRV_DBG_TRACE
DHCP server library logging levels.
void openSockets(const uint16_t family, const uint16_t port, const bool use_bcast=true) const
Tries to open sockets on selected interfaces.
Exception thrown when duplicated address specified.
const isc::log::MessageID DHCPSRV_CFGMGR_ALL_IFACES_ACTIVE
bool isV6LinkLocal() const
checks whether and address is IPv6 and is link-local
void setOutboundIface(const OutboundIface &outbound_iface)
Sets outbound interface selection mode.
bool isV6() const
Convenience function to check for an IPv6 address.
string trim(const string &instring)
Trim Leading and Trailing Spaces.
isc::log::Logger dhcpsrv_logger("dhcpsrv")
DHCP server library Logger.
bool isV6Multicast() const
checks whether and address is IPv6 and is multicast
SocketType textToSocketType(const std::string &socket_type_name) const
Converts the socket type in the textual format to the type represented by the SocketType.
The IOAddress class represents an IP addresses (version agnostic)
bool isDirectResponseSupported() const
Check if packet be sent directly to the client having no address.
std::string outboundTypeToText() const
Returns outbound interface selection mode as string.
const isc::log::MessageID DHCPSRV_CFGMGR_SOCKET_RAW_UNSUPPORTED
const isc::log::MessageID DHCPSRV_MULTIPLE_RAW_SOCKETS_PER_IFACE
bool openSockets4(const uint16_t port=DHCP4_SERVER_PORT, const bool use_bcast=true, IfaceMgrErrorMsgCallback error_handler=0)
Opens IPv4 sockets on detected interfaces.
void closeSockets() const
Convenience function which closes all open sockets.
OutboundIface getOutboundIface() const
Returns outbound interface selection mode.
OutboundIface
Indicates how outbound interface is selected for relayed traffic.