From: Tomek Mrugalski Date: Wed, 4 Oct 2017 21:08:21 +0000 (+0200) Subject: [5377] Support for outbound-interface added. X-Git-Tag: trac5297_base~15^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=42d213909325316f7f9313c56d4ecdcc801803ed;p=thirdparty%2Fkea.git [5377] Support for outbound-interface added. --- diff --git a/doc/examples/kea4/advanced.json b/doc/examples/kea4/advanced.json index 2a8b76f144..039b4257e8 100644 --- a/doc/examples/kea4/advanced.json +++ b/doc/examples/kea4/advanced.json @@ -31,6 +31,14 @@ // Ethernet/IP stack processing. "dhcp-socket-type": "udp", + // Typically the DHCP server will send its response back on the same + // interface the query came in. This is the default ("same-as-inbound"). + // However, sometimes it is useful to have the ability to send the + // packet as plain UDP packet and let the kernel and the routing tables + // to determine the right interface ("use-routing"). This option is + // expected to work only for dhcp-socket-type set to udp. + "outbound-interface": "use-routing", + // This makes interfaces to be re-detected at each (re-)configuration. // By default it is true. "re-detect": true diff --git a/src/bin/dhcp4/dhcp4_lexer.ll b/src/bin/dhcp4/dhcp4_lexer.ll index 13dbec9873..5a00f81335 100644 --- a/src/bin/dhcp4/dhcp4_lexer.ll +++ b/src/bin/dhcp4/dhcp4_lexer.ll @@ -225,6 +225,33 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} } } +\"outbound-interface\" { + switch(driver.ctx_) { + case Parser4Context::INTERFACES_CONFIG: + return isc::dhcp::Dhcp4Parser::make_OUTBOUND_INTERFACE(driver.loc_); + default: + return isc::dhcp::Dhcp4Parser::make_STRING("outbound-interface", driver.loc_); + } +} + +\"same-as-inbound\" { + switch(driver.ctx_) { + case Parser4Context::OUTBOUND_INTERFACE: + return Dhcp4Parser::make_SAME_AS_INBOUND(driver.loc_); + default: + return Dhcp4Parser::make_STRING("same-as-inbound", driver.loc_); + } +} + +\"use-routing\" { + switch(driver.ctx_) { + case Parser4Context::OUTBOUND_INTERFACE: + return Dhcp4Parser::make_USE_ROUTING(driver.loc_); + default: + return Dhcp4Parser::make_STRING("use-routing", driver.loc_); + } +} + \"interfaces\" { switch(driver.ctx_) { case isc::dhcp::Parser4Context::INTERFACES_CONFIG: diff --git a/src/bin/dhcp4/dhcp4_parser.yy b/src/bin/dhcp4/dhcp4_parser.yy index 27f6641e20..a56ab669f9 100644 --- a/src/bin/dhcp4/dhcp4_parser.yy +++ b/src/bin/dhcp4/dhcp4_parser.yy @@ -55,6 +55,9 @@ using namespace std; DHCP_SOCKET_TYPE "dhcp-socket-type" RAW "raw" UDP "udp" + OUTBOUND_INTERFACE "outbound-interface" + SAME_AS_INBOUND "same-as-inbound" + USE_ROUTING "use-routing" RE_DETECT "re-detect" ECHO_CLIENT_ID "echo-client-id" @@ -212,6 +215,7 @@ using namespace std; %type value %type map_value %type socket_type +%type outbound_interface_value %type db_type %type hr_mode %type ncr_protocol_value @@ -477,6 +481,7 @@ interfaces_config_params: interfaces_config_param interfaces_config_param: interfaces_list | dhcp_socket_type + | outbound_interface | re_detect ; @@ -510,6 +515,19 @@ socket_type: RAW { $$ = ElementPtr(new StringElement("raw", ctx.loc2pos(@1))); } | UDP { $$ = ElementPtr(new StringElement("udp", ctx.loc2pos(@1))); } ; +outbound_interface: OUTBOUND_INTERFACE { + ctx.enter(ctx.OUTBOUND_INTERFACE); +} COLON outbound_interface_value { + ctx.stack_.back()->set("outbound-interface", $4); + ctx.leave(); +} + +outbound_interface_value: SAME_AS_INBOUND { + $$ = ElementPtr(new StringElement("same-as-inbound", ctx.loc2pos(@1))); +} | USE_ROUTING { + $$ = ElementPtr(new StringElement("use-routing", ctx.loc2pos(@1))); + } ; + re_detect: RE_DETECT COLON BOOLEAN { ElementPtr b(new BoolElement($3, ctx.loc2pos(@3))); ctx.stack_.back()->set("re-detect", b); diff --git a/src/bin/dhcp4/parser_context.cc b/src/bin/dhcp4/parser_context.cc index 7047cd7e31..17c268a929 100644 --- a/src/bin/dhcp4/parser_context.cc +++ b/src/bin/dhcp4/parser_context.cc @@ -144,6 +144,8 @@ Parser4Context::contextName() return ("interfaces-config"); case DHCP_SOCKET_TYPE: return ("dhcp-socket-type"); + case OUTBOUND_INTERFACE: + return ("outbound-interface"); case LEASE_DATABASE: return ("lease-database"); case HOSTS_DATABASE: diff --git a/src/bin/dhcp4/parser_context.h b/src/bin/dhcp4/parser_context.h index 0791a06270..ee998e05f8 100644 --- a/src/bin/dhcp4/parser_context.h +++ b/src/bin/dhcp4/parser_context.h @@ -214,6 +214,9 @@ public: /// Used while parsing Dhcp4/interfaces/dhcp-socket-type structures. DHCP_SOCKET_TYPE, + /// Used while parsing Dhcp4/interfaces/outbound-interface structures. + OUTBOUND_INTERFACE, + /// Used while parsing Dhcp4/lease-database structures. LEASE_DATABASE, diff --git a/src/lib/dhcpsrv/cfg_iface.cc b/src/lib/dhcpsrv/cfg_iface.cc index c7482b1cc4..e180c4f4ce 100644 --- a/src/lib/dhcpsrv/cfg_iface.cc +++ b/src/lib/dhcpsrv/cfg_iface.cc @@ -22,7 +22,8 @@ namespace dhcp { const char* CfgIface::ALL_IFACES_KEYWORD = "*"; CfgIface::CfgIface() - : wildcard_used_(false), socket_type_(SOCKET_RAW), re_detect_(false) { + : wildcard_used_(false), socket_type_(SOCKET_RAW), re_detect_(false), + outbound_iface_(SAME_AS_INBOUND) { } void @@ -226,6 +227,35 @@ CfgIface::textToSocketType(const std::string& socket_type_name) const { } } +std::string +CfgIface::outboundTypeToText() const { + switch (outbound_iface_) { + case SAME_AS_INBOUND: return ("same-as-inbound"); + case USE_ROUTING: return ("use-routing"); + default: isc_throw(Unexpected, "unsupported outbound-type " << socket_type_); + } + +} + +CfgIface::OutboundIface +CfgIface::textToOutboundIface(const std::string& txt) { + if (txt == "same-as-inbound") { + return (SAME_AS_INBOUND); + + } else if (txt == "use-routing") { + return (USE_ROUTING); + + } else { + isc_throw(InvalidSocketType, "unsupported socket type '" + << txt << "'"); + } +} + +void +CfgIface::setOutboundIface(const OutboundIface& traffic_type) { + outbound_iface_ = traffic_type; +} + void CfgIface::use(const uint16_t family, const std::string& iface_name) { // The interface name specified may have two formats: diff --git a/src/lib/dhcpsrv/cfg_iface.h b/src/lib/dhcpsrv/cfg_iface.h index eea5fdb5a5..8293d512e1 100644 --- a/src/lib/dhcpsrv/cfg_iface.h +++ b/src/lib/dhcpsrv/cfg_iface.h @@ -137,6 +137,12 @@ public: SOCKET_UDP }; + enum OutboundIface { + SAME_AS_INBOUND, + + USE_ROUTING + }; + /// @brief Keyword used to enable all interfaces. /// /// This keyword can be used instead of the interface name to specify @@ -227,6 +233,14 @@ public: /// @brief Returns the socket type in the textual format. std::string socketTypeToText() const; + void setOutboundIface(const OutboundIface& traffic_type); + + OutboundIface getOutboundIface() const; + + std::string outboundTypeToText() const; + + static OutboundIface textToOutboundIface(const std::string& txt); + /// @brief Converts the socket type in the textual format to the type /// represented by the @c SocketType. /// @@ -340,6 +354,8 @@ private: /// @brief A boolean value which reflects current re-detect setting bool re_detect_; + + OutboundIface outbound_iface_; }; /// @brief A pointer to the @c CfgIface . diff --git a/src/lib/dhcpsrv/parsers/ifaces_config_parser.cc b/src/lib/dhcpsrv/parsers/ifaces_config_parser.cc index 87e2fa562d..bfa50a199c 100644 --- a/src/lib/dhcpsrv/parsers/ifaces_config_parser.cc +++ b/src/lib/dhcpsrv/parsers/ifaces_config_parser.cc @@ -76,6 +76,18 @@ IfacesConfigParser::parse(const CfgIfacePtr& cfg, } } + if (element.first == "outbound-interface") { + if (protocol_ == AF_INET) { + CfgIface::OutboundIface type = + CfgIface::textToOutboundIface(element.second->stringValue()); + cfg->setOutboundIface(type); + continue; + } else { + isc_throw(DhcpConfigError, + "outbound-interface is not supported in DHCPv6"); + } + } + // This should never happen as the input produced by the parser // see (src/bin/dhcpX/dhcpX_parser.yy) should not produce any // other parameter, so this case is only to catch bugs in