ConstElementPtr control_socket = mutable_cfg->get("control-socket");
if (control_socket) {
- parameter_name = "control-socket";
- ControlSocketParser parser;
- parser.parse(*srv_config, control_socket);
+ mutable_cfg->remove("control-socket");
+ ElementPtr l = Element::createList();
+ l->add(UserContext::toElement(control_socket));
+ mutable_cfg->set("control-sockets", l);
+ }
+
+ ConstElementPtr control_sockets = mutable_cfg->get("control-sockets");
+ if (control_sockets) {
+ parameter_name = "control-sockets";
+ ControlSocketsParser parser;
+ parser.parse(*srv_config, control_sockets);
}
ConstElementPtr multi_threading = mutable_cfg->get("multi-threading");
" }\n"
" }\n"
" ],\n"
-" \"control-socket\": {\n"
-" \"socket-name\": \"/tmp/kea4-ctrl-socket\",\n"
-" \"socket-type\": \"unix\",\n"
-" \"user-context\": {\n"
-" \"comment\": \"Indirect comment\"\n"
+" \"control-sockets\": [\n"
+" {\n"
+" \"socket-name\": \"/tmp/kea4-ctrl-socket\",\n"
+" \"socket-type\": \"unix\",\n"
+" \"user-context\": {\n"
+" \"comment\": \"Indirect comment\"\n"
+" }\n"
" }\n"
-" },\n"
+" ],\n"
" \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
" \"ddns-generated-prefix\": \"myhost\",\n"
" \"ddns-override-client-update\": false,\n"
ConstElementPtr control_socket = mutable_cfg->get("control-socket");
if (control_socket) {
- parameter_name = "control-socket";
- ControlSocketParser parser;
- parser.parse(*srv_config, control_socket);
+ mutable_cfg->remove("control-socket");
+ ElementPtr l = Element::createList();
+ l->add(UserContext::toElement(control_socket));
+ mutable_cfg->set("control-sockets", l);
}
+ ConstElementPtr control_sockets = mutable_cfg->get("control-sockets");
+ if (control_sockets) {
+ parameter_name = "control-sockets";
+ ControlSocketsParser parser;
+ parser.parse(*srv_config, control_sockets);
+ }
ConstElementPtr multi_threading = mutable_cfg->get("multi-threading");
if (multi_threading) {
parameter_name = "multi-threading";
" }\n"
" }\n"
" ],\n"
-" \"control-socket\": {\n"
-" \"socket-name\": \"/tmp/kea6-ctrl-socket\",\n"
-" \"socket-type\": \"unix\",\n"
-" \"user-context\": {\n"
-" \"comment\": \"Indirect comment\"\n"
+" \"control-sockets\": [\n"
+" {\n"
+" \"socket-name\": \"/tmp/kea6-ctrl-socket\",\n"
+" \"socket-type\": \"unix\",\n"
+" \"user-context\": {\n"
+" \"comment\": \"Indirect comment\"\n"
+" }\n"
" }\n"
-" },\n"
+" ],\n"
" \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
" \"ddns-generated-prefix\": \"myhost\",\n"
" \"ddns-override-client-update\": false,\n"
addLog("<string>:40.12");
addLog("<string>:42.28");
addLog("<string>:43.8");
- addLog("<string>:54.37");
+ addLog("<string>:54.38");
addLog("<string>:55.12");
addLog("<string>:58.16");
addLog("<string>:59.8");
}
}
-// ******************** ControlSocketParser *************************
-void ControlSocketParser::parse(SrvConfig& srv_cfg, isc::data::ConstElementPtr value) {
- if (!value) {
+// ******************** ControlSocketsParser *************************
+void ControlSocketsParser::parse(SrvConfig& srv_cfg, ConstElementPtr value) {
+ if (value->getType() != Element::list) {
// Sanity check: not supposed to fail.
- isc_throw(DhcpConfigError, "Logic error: specified control-socket is null");
+ isc_throw(DhcpConfigError,
+ "Specified control-sockets is expected to be a list");
}
-
- if (value->getType() != Element::map) {
- // Sanity check: not supposed to fail.
- isc_throw(DhcpConfigError, "Specified control-socket is expected to be a map"
- ", i.e. a structure defined within { }");
+ bool seen_unix(false);
+ bool seen_http(false);
+ for (ConstElementPtr socket : value->listValue()) {
+ if (socket->getType() != Element::map) {
+ // Sanity check: not supposed to fail.
+ isc_throw(DhcpConfigError,
+ "Specified control-sockets is expected to be a list of maps");
+ }
+ ConstElementPtr socket_type = socket->get("socket-type");
+ if (!socket_type) {
+ isc_throw(DhcpConfigError,
+ "'socket-type' parameter is mandatory in control-sockets items");
+ }
+ if (socket_type->getType() != Element::string) {
+ // Sanity check: not supposed to fail.
+ isc_throw(DhcpConfigError,
+ "'socket-type' parameter is expected to be a string");
+ }
+ string type = socket_type->stringValue();
+ if (type == "unix") {
+ if (seen_unix) {
+ isc_throw(DhcpConfigError,
+ "control socket of type 'unix' already configured");
+ }
+ seen_unix = true;
+ srv_cfg.setControlSocketInfo(socket);
+ } else if ((type == "http") || (type == "https")) {
+ if (seen_http) {
+ isc_throw(DhcpConfigError,
+ "control socket of type 'http' or 'https'"
+ " already configured");
+ }
+ seen_http = true;
+ srv_cfg.setHttpControlSocketInfo(socket);
+ } else {
+ // Sanity check: not supposed to fail.
+ isc_throw(DhcpConfigError,
+ "unsupported 'socket-type': '" << type
+ << "' not 'unix', 'http' or 'https'");
+ }
}
- srv_cfg.setControlSocketInfo(value);
}
// ******************************** OptionDefParser ****************************
void parse(CfgMACSource& mac_sources, isc::data::ConstElementPtr value);
};
-/// @brief Parser for the control-socket structure
+/// @brief Parser for the control-sockets structure
///
-/// It does not parse anything, simply stores the element in
+/// It does not parse anything, simply stores elements in
/// the staging config.
-class ControlSocketParser : public isc::data::SimpleParser {
+class ControlSocketsParser : public isc::data::SimpleParser {
public:
- /// @brief "Parses" control-socket structure
+ /// @brief "Parses" control-sockets structure
///
- /// Since the SrvConfig structure takes the socket definition
+ /// Since the SrvConfig structure takes the socket definitions
/// as ConstElementPtr, there's really nothing to parse here.
/// It only does basic sanity checks and throws DhcpConfigError
- /// if the value is null or is not a map.
+ /// if the syntax is not valid.
///
/// @param srv_cfg parsed values will be stored here
/// @param value pointer to the content of parsed values
{ "hooks-libraries", Element::list },
{ "expired-leases-processing", Element::map },
{ "dhcp4o6-port", Element::integer },
- { "control-socket", Element::map },
{ "control-sockets", Element::list },
{ "dhcp-queue-control", Element::map },
{ "dhcp-ddns", Element::map },
{ "expired-leases-processing", Element::map },
{ "server-id", Element::map },
{ "dhcp4o6-port", Element::integer },
- { "control-socket", Element::map },
{ "control-sockets", Element::list },
{ "dhcp-queue-control", Element::map },
{ "dhcp-ddns", Element::map },
parser.parse(compatibility, *this);
addConfiguredGlobal("compatibility", compatibility);
}
- ConstElementPtr control_socket = config->get("control-socket");
- parameter_name = "control-socket";
- if (control_socket) {
- ControlSocketParser parser;
- parser.parse(*this, control_socket);
- addConfiguredGlobal("control-socket", control_socket);
- }
ElementPtr dhcp_ddns = boost::const_pointer_cast<Element>(config->get("dhcp-ddns"));
parameter_name = "dhcp-ddns";
if (dhcp_ddns) {
if (family == AF_INET6) {
dhcp->set("mac-sources", cfg_mac_source_.toElement());
}
- // Set control-socket (skip if null as empty is not legal)
- if (!isNull(control_socket_)) {
- dhcp->set("control-socket", UserContext::toElement(control_socket_));
+ // Set control-sockets.
+ ElementPtr control_sockets = Element::createList();
+ if (!isNull(unix_control_socket_)) {
+ control_sockets->add(UserContext::toElement(unix_control_socket_));
+ }
+ if (!isNull(http_control_socket_)) {
+ control_sockets->add(UserContext::toElement(http_control_socket_));
+ }
+ if (!control_sockets->empty()) {
+ dhcp->set("control-sockets", control_sockets);
}
// Set client-classes
ConstElementPtr client_classes = class_dictionary_->toElement();
return (cfg_mac_source_);
}
- /// @brief Returns information about control socket
+ /// @brief Returns information about UNIX control socket
///
/// @return pointer to the Element that holds control-socket map
const isc::data::ConstElementPtr getControlSocketInfo() const {
- return (control_socket_);
+ return (unix_control_socket_);
}
- /// @brief Sets information about the control socket
+ /// @brief Sets information about the UNIX control socket
///
/// @param control_socket Element that holds control-socket map
void setControlSocketInfo(const isc::data::ConstElementPtr& control_socket) {
- control_socket_ = control_socket;
+ unix_control_socket_ = control_socket;
+ }
+
+ /// @brief Returns information about HTTP/HTTPS control socket
+ ///
+ /// @return pointer to the Element that holds control-socket map
+ const isc::data::ConstElementPtr getHttpControlSocketInfo() const {
+ return (http_control_socket_);
+ }
+
+ /// @brief Sets information about the HTTP/HTTPS control socket
+ ///
+ /// @param control_socket Element that holds control-socket map
+ void setHttpControlSocketInfo(const isc::data::ConstElementPtr& control_socket) {
+ http_control_socket_ = control_socket;
}
/// @brief Returns DHCP queue control information
ignore_dhcp_server_identifier_ = false;
ignore_rai_link_selection_ = false;
exclude_first_last_24_ = false;
- control_socket_.reset();
+ unix_control_socket_.reset();
+ http_control_socket_.reset();
d2_client_config_.reset(new D2ClientConfig());
cfg_expiration_.reset(new CfgExpiration());
dhcp_multi_threading_.reset();
/// DHCPv6.
CfgHostOperationsPtr cfg_host_operations6_;
- /// @brief Pointer to the control-socket information
- isc::data::ConstElementPtr control_socket_;
+ /// @brief Pointer to the UNIX control-socket information
+ isc::data::ConstElementPtr unix_control_socket_;
+
+ /// @brief Pointer to the HTTP control-socket information
+ isc::data::ConstElementPtr http_control_socket_;
/// @brief Pointer to the dhcp-queue-control information
isc::data::ConstElementPtr dhcp_queue_control_;