]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[5377] Support for outbound-interface added.
authorTomek Mrugalski <tomasz@isc.org>
Wed, 4 Oct 2017 21:08:21 +0000 (23:08 +0200)
committerTomek Mrugalski <tomasz@isc.org>
Wed, 4 Oct 2017 21:08:21 +0000 (23:08 +0200)
doc/examples/kea4/advanced.json
src/bin/dhcp4/dhcp4_lexer.ll
src/bin/dhcp4/dhcp4_parser.yy
src/bin/dhcp4/parser_context.cc
src/bin/dhcp4/parser_context.h
src/lib/dhcpsrv/cfg_iface.cc
src/lib/dhcpsrv/cfg_iface.h
src/lib/dhcpsrv/parsers/ifaces_config_parser.cc

index 2a8b76f1448dd1b826fe1798d6530969c0b11049..039b4257e823c672a904dd7ae40da48111f97f48 100644 (file)
         // 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
index 13dbec987356c50506328152655822e35759e162..5a00f81335688e4d41f1ea0bac76e9891b7922fd 100644 (file)
@@ -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:
index 27f6641e20b1f1a8c58d416c6964188308331b6b..a56ab669f9550486020f8ee3e3ee309266c40459 100644 (file)
@@ -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 <ElementPtr> value
 %type <ElementPtr> map_value
 %type <ElementPtr> socket_type
+%type <ElementPtr> outbound_interface_value
 %type <ElementPtr> db_type
 %type <ElementPtr> hr_mode
 %type <ElementPtr> 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);
index 7047cd7e31f66d2b3c56ca01616719bbc4f5d5eb..17c268a9298fa1ead521bb81fe17543d652e3abd 100644 (file)
@@ -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:
index 0791a062708f203dd222c717d438ed8eddc9143c..ee998e05f8fbca7a23e45b82f33af6a29ed08f55 100644 (file)
@@ -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,
 
index c7482b1cc47e932265473a1908bbb5e15ec0e124..e180c4f4ce873f2b3889fe1eafe421c5eac130f8 100644 (file)
@@ -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:
index eea5fdb5a5ab905b0f5f18ca57267cfdc9568201..8293d512e1401f1683166096a8d6766d4e0ea37b 100644 (file)
@@ -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 .
index 87e2fa562d2c0cf8185bc97ec75d08edb0a51cc1..bfa50a199ccd557b40621f9c498b44664bd7b883 100644 (file)
@@ -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