// 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
}
}
+\"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:
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"
%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
interfaces_config_param: interfaces_list
| dhcp_socket_type
+ | outbound_interface
| re_detect
;
| 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);
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:
/// 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,
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
}
}
+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:
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
/// @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.
///
/// @brief A boolean value which reflects current re-detect setting
bool re_detect_;
+
+ OutboundIface outbound_iface_;
};
/// @brief A pointer to the @c CfgIface .
}
}
+ 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