"ncr-format": "JSON",
// Command control socket configuration parameters for Kea DHCP-DDNS server.
- "control-socket": {
+ "control-sockets": [
+ {
+ // Control socket type used by the Kea DHCP-DDNS server.
+ // Must be unix, http or https.
+ "socket-type": "unix",
+
+ // Location of the UNIX domain socket file the DHCP-DDNS
+ // server uses to receive control commands from the
+ // local server administrator.
+ "socket-name": "/tmp/kea-ddns-ctrl-socket"
+ },
+ {
+ // Control socket type used by the Kea DHCP-DDNS server.
+ // Must be unix, http or https.
+ "socket-type": "https",
+
+ // Address of the HTTPS socket the Kea DHCP-DDNS server should
+ // listen for incoming queries. In fact an alias of
+ // socket-name.
+ "socket-address": "127.0.0.1",
+
+ // Port of the HTTPS socket the Kea DHCP-DDNS server
+ // should listen for incoming queries.
+ "socket-port": 8053,
+
+ // TLS trust anchor (Certificate Authority). This is a
+ // file name or a directory path. Make sense with other
+ // TLS parameters only for the https control socket type.
+ "trust-anchor": "my-ca",
+
+ // TLS server certificate file name.
+ "cert-file": "my-cert",
+
+ // TLS server private key file name.
+ "key-file": "my-key",
+
+ // TLS require client certificates flag. Default is
+ // true and means require client certificates. False
+ // means they are optional.
+ "cert-required": true,
+
+ // Optional authentication.
+ "authentication": {
+ // Required authentication type. The only supported
+ // value is basic for the basic HTTP authentication.
+ "type": "basic",
+
+ // An optional parameter is the basic HTTP
+ // authentication realm. Its default is
+ // "kea-dhcp-ddns-server"
+ "realm": "kea-dhcp-ddns-server",
+
+ // This optional parameter can be used to specify a common
+ // prefix for files handling client credentials.
+ "directory": "/tmp/kea-creds",
+
+ // This list specifies the user ids and passwords to
+ // use for basic HTTP authentication. If empty or not
+ // present any client is authorized.
+ "clients": [
+ // This specifies an authorized client.
+ {
+ // The user id must not be empty or contain
+ // the ':' character. It is a mandatoryparameter.
+ "user": "admin",
- // Location of the UNIX domain socket file the DHCP-DDNS server uses
- // to receive control commands from the Kea Control Agent or the
- // local server administrator.
- "socket-name": "/tmp/kea-ddns-ctrl-socket",
+ // If password is not specified an empty
+ // password is used.
+ "password": "1234"
+ },
- // Control socket type used by the Kea DHCP-DDNS server.
- // The 'unix' socket is currently the only supported type.
- "socket-type": "unix"
- },
+ // This specifies a hidden client.
+ {
+ // The user id is the content of the
+ // file /tmp/kea-creds/hiddenu.
+ "user-file": "hiddenu",
+
+ // The password is the content of the
+ // file /tmp/kea-creds/hiddenp.
+ "password-file": "hiddenp"
+ },
+
+ // This specifies a hidden client using a secret
+ // in a file.
+ {
+ // The secret is the content of the file
+ // /tmp/kea-creds/hiddens which must be in
+ // the <user-id>:<password> format.
+ "password-file": "hiddens"
+ }
+ ]
+ }
+ }
+ ],
// List of hook libraries and their specific configuration parameters
// to be loaded by Kea DHCP-DDNS server.
"port": 53001,
"dns-server-timeout" : 1000,
- "control-socket":
- {
- "comment": "Control channel",
- "socket-type": "unix",
- "socket-name": "/tmp/kea-ddns-ctrl-socket"
- },
+ // In control sockets.
+ "control-sockets": [
+ {
+ "socket-type": "unix",
+ "socket-name": "/tmp/kea-ddns-ctrl-socket",
+ "user-context": { "comment": "Indirect comment" }
+ },
+ {
+ "comment": "HTTP control socket",
+ "socket-type": "http",
+ "socket-address": "::1",
+ "socket-port": 8053,
+ // In authentication
+ "authentication": {
+ "comment": "basic HTTP authentication",
+ "type": "basic",
+ // In basic HTTP authentication clients
+ "clients": [ {
+ "comment": "admin is authorized",
+ "user": "admin",
+ "password": "1234"
+ } ]
+ }
+ }
+ ],
"forward-ddns":
{
}
],
-
// Specifies a prefix to be prepended to the generated Client FQDN.
// It may be specified at the global, shared-network, and subnet levels.
"ddns-generated-prefix": "myhost",
"lenient-option-parsing": true
},
- // Command control socket configuration parameters for the Kea DHCPv4 server.
+ // Command control socket configuration parameters for the Kea DHCPv6 server.
"control-sockets": [
{
- // Control socket type used by the Kea DHCPv4 server.
+ // Control socket type used by the Kea DHCPv6 server.
// Must be unix, http or https.
"socket-type": "unix",
- // Location of the UNIX domain socket file the DHCPv4
+ // Location of the UNIX domain socket file the DHCPv6
// server uses to receive control commands from the
// local server administrator.
- "socket-name": "/tmp/kea4-ctrl-socket"
+ "socket-name": "/tmp/kea6-ctrl-socket"
},
{
- // Control socket type used by the Kea DHCPv4 server.
+ // Control socket type used by the Kea DHCPv6 server.
// Must be unix, http or https.
"socket-type": "https",
- // Address of the HTTPS socket the Kea DHCPv4 server should
+ // Address of the HTTPS socket the Kea DHCPv6 server should
// listen for incoming queries. In fact an alias of
// socket-name.
"socket-address": "::1",
- // Port of the HTTPS socket the Kea DHCPv4 server
+ // Port of the HTTPS socket the Kea DHCPv6 server
// should listen for incoming queries. If enabling HA
// and multi-threading, the 8000 port is used by the
// HA hook library http listener. When using HA hook
// An optional parameter is the basic HTTP
// authentication realm. Its default is
- // "kea-dhcpv4-server"
- "realm": "kea-dhcpv4-server",
+ // "kea-dhcpv6-server"
+ "realm": "kea-dhcpv6-server",
// This optional parameter can be used to specify a common
// prefix for files handling client credentials.
}
],
-
// Specifies a prefix to be prepended to the generated Client FQDN.
// It may be specified at the global, shared-network, and subnet levels.
"ddns-generated-prefix": "myhost",
"control-sockets": [
{
"socket-type": "unix",
- "socket-name": "/tmp/kea4-ctrl-socket",
+ "socket-name": "/tmp/kea6-ctrl-socket",
"user-context": { "comment": "Indirect comment" }
},
{
case isc::d2::D2ParserContext::TSIG_KEY:
case isc::d2::D2ParserContext::TSIG_KEYS:
case isc::d2::D2ParserContext::CONTROL_SOCKET:
+ case isc::d2::D2ParserContext::AUTHENTICATION:
+ case isc::d2::D2ParserContext::CLIENTS:
case isc::d2::D2ParserContext::LOGGERS:
return isc::d2::D2Parser::make_USER_CONTEXT(driver.loc_);
default:
case isc::d2::D2ParserContext::TSIG_KEY:
case isc::d2::D2ParserContext::TSIG_KEYS:
case isc::d2::D2ParserContext::CONTROL_SOCKET:
+ case isc::d2::D2ParserContext::AUTHENTICATION:
+ case isc::d2::D2ParserContext::CLIENTS:
case isc::d2::D2ParserContext::LOGGERS:
return isc::d2::D2Parser::make_COMMENT(driver.loc_);
default:
}
}
+\"control-sockets\" {
+ switch(driver.ctx_) {
+ case isc::d2::D2ParserContext::DHCPDDNS:
+ return isc::d2::D2Parser::make_CONTROL_SOCKET(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("control-socket", driver.loc_);
+ }
+}
+
\"socket-type\" {
switch(driver.ctx_) {
case isc::d2::D2ParserContext::CONTROL_SOCKET:
}
}
+\"unix\" {
+ switch(driver.ctx_) {
+ case isc::d2::D2ParserContext::CONTROL_SOCKET_TYPE:
+ return isc::d2::D2Parser::make_UNIX(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("unix", driver.loc_);
+ }
+}
+
+\"http\" {
+ switch(driver.ctx_) {
+ case isc::d2::D2ParserContext::CONTROL_SOCKET_TYPE:
+ return isc::d2::D2Parser::make_HTTP(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("http", driver.loc_);
+ }
+}
+
+\"https\" {
+ switch(driver.ctx_) {
+ case isc::d2::D2ParserContext::CONTROL_SOCKET_TYPE:
+ return isc::d2::D2Parser::make_HTTPS(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("https", driver.loc_);
+ }
+}
+
\"socket-name\" {
switch(driver.ctx_) {
case isc::d2::D2ParserContext::CONTROL_SOCKET:
}
}
+\"socket-address\" {
+ switch(driver.ctx_) {
+ case isc::d2::D2ParserContext::CONTROL_SOCKET:
+ return isc::d2::D2Parser::make_SOCKET_ADDRESS(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("socket-address", driver.loc_);
+ }
+}
+
+\"socket-port\" {
+ switch(driver.ctx_) {
+ case isc::d2::D2ParserContext::CONTROL_SOCKET:
+ return isc::d2::D2Parser::make_SOCKET_PORT(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("socket-port", driver.loc_);
+ }
+}
+
+\"authentication\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+ return isc::d2::D2Parser::make_AUTHENTICATION(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("authentication", driver.loc_);
+ }
+}
+
+\"type\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::AUTHENTICATION:
+ return isc::d2::D2Parser::make_TYPE(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("type", driver.loc_);
+ }
+}
+
+\"basic\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::AUTH_TYPE:
+ return isc::d2::D2Parser::make_BASIC(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("basic", driver.loc_);
+ }
+}
+
+\"realm\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::AUTHENTICATION:
+ return isc::d2::D2Parser::make_REALM(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("realm", driver.loc_);
+ }
+}
+
+\"directory\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::AUTHENTICATION:
+ return isc::d2::D2Parser::make_DIRECTORY(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("directory", driver.loc_);
+ }
+}
+
+\"clients\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::AUTHENTICATION:
+ return isc::d2::D2Parser::make_CLIENTS(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("clients", driver.loc_);
+ }
+}
+
+\"user\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::CLIENTS:
+ return isc::d2::D2Parser::make_USER(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("user", driver.loc_);
+ }
+}
+
+\"user-file\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::CLIENTS:
+ return isc::d2::D2Parser::make_USER_FILE(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("user-file", driver.loc_);
+ }
+}
+
+\"password\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::CLIENTS:
+ return isc::d2::D2Parser::make_PASSWORD(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("password", driver.loc_);
+ }
+}
+
+\"password-file\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::CLIENTS:
+ return isc::d2::D2Parser::make_PASSWORD_FILE(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("password-file", driver.loc_);
+ }
+}
+
+\"trust-anchor\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+ return isc::d2::D2Parser::make_TRUST_ANCHOR(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("trust-anchor", driver.loc_);
+ }
+}
+
+\"cert-file\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+ return isc::d2::D2Parser::make_CERT_FILE(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("cert-file", driver.loc_);
+ }
+}
+
+\"key-file\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+ return isc::d2::D2Parser::make_KEY_FILE(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("key-file", driver.loc_);
+ }
+}
+
+\"cert-required\" {
+ switch(driver.ctx_) {
+ case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+ return isc::d2::D2Parser::make_CERT_REQUIRED(driver.loc_);
+ default:
+ return isc::d2::D2Parser::make_STRING("cert-required", driver.loc_);
+ }
+}
+
\"hooks-libraries\" {
switch(driver.ctx_) {
case isc::d2::D2ParserContext::DHCPDDNS:
SECRET_FILE "secret-file"
CONTROL_SOCKET "control-socket"
+ CONTROL_SOCKETS "control-sockets"
SOCKET_TYPE "socket-type"
+ UNIX "unix"
+ HTTP "http"
+ HTTPS "https"
SOCKET_NAME "socket-name"
+ SOCKET_ADDRESS "socket-address"
+ SOCKET_PORT "socket-port"
+ AUTHENTICATION "authentication"
+ BASIC "basic"
+ REALM "realm"
+ DIRECTORY "directory"
+ CLIENTS "clients"
+ USER_FILE "user-file"
+ PASSWORD_FILE "password-file"
+ CERT_REQUIRED "cert-required"
HOOKS_LIBRARIES "hooks-libraries"
LIBRARY "library"
%type <ElementPtr> value
%type <ElementPtr> map_value
%type <ElementPtr> ncr_protocol_value
+%type <ElementPtr> control_socket_type_value
+%type <ElementPtr> auth_type_value
%printer { yyoutput << $$; } <*>;
| reverse_ddns
| tsig_keys
| control_socket
+ | control_sockets
| hooks_libraries
| loggers
| user_context
// --- end of tsig-keys ---------------------------------
-// --- control socket ----------------------------------------
+// --- control sockets ----------------------------------------
control_socket: CONTROL_SOCKET {
ctx.unique("control-socket", ctx.loc2pos(@1));
+ ctx.unique("control-sockets", ctx.loc2pos(@1));
ElementPtr m(new MapElement(ctx.loc2pos(@1)));
ctx.stack_.back()->set("control-socket", m);
ctx.stack_.push_back(m);
ctx.leave();
};
+control_sockets: CONTROL_SOCKETS {
+ ctx.unique("control-sockets", ctx.loc2pos(@1));
+ ctx.unique("control-socket", ctx.loc2pos(@1));
+ ElementPtr l(new ListElement(ctx.loc2pos(@1)));
+ ctx.stack_.back()->set("control-sockets", l);
+ ctx.stack_.push_back(l);
+ ctx.enter(ctx.CONTROL_SOCKET);
+} COLON LSQUARE_BRACKET control_socket_list RSQUARE_BRACKET {
+ ctx.stack_.pop_back();
+ ctx.leave();
+};
+
+control_socket_list: %empty
+ | not_empty_control_socket_list
+ ;
+
+not_empty_control_socket_list: control_socket_entry
+ | not_empty_control_socket_list COMMA control_socket_entry
+ | not_empty_control_socket_list COMMA {
+ ctx.warnAboutExtraCommas(@2);
+ }
+ ;
+
+control_socket_entry: LCURLY_BRACKET {
+ ElementPtr m(new MapElement(ctx.loc2pos(@1)));
+ ctx.stack_.back()->add(m);
+ ctx.stack_.push_back(m);
+} control_socket_params RCURLY_BRACKET {
+ ctx.stack_.pop_back();
+};
+
control_socket_params: control_socket_param
| control_socket_params COMMA control_socket_param
| control_socket_params COMMA {
control_socket_param: control_socket_type
| control_socket_name
+ | control_socket_address
+ | control_socket_port
+ | authentication
+ | trust_anchor
+ | cert_file
+ | key_file
+ | cert_required
| user_context
| comment
| unknown_map_entry
control_socket_type: SOCKET_TYPE {
ctx.unique("socket-type", ctx.loc2pos(@1));
- ctx.enter(ctx.NO_KEYWORD);
-} COLON STRING {
- ElementPtr stype(new StringElement($4, ctx.loc2pos(@4)));
- ctx.stack_.back()->set("socket-type", stype);
+ ctx.enter(ctx.CONTROL_SOCKET_TYPE);
+} COLON control_socket_type_value {
+ ctx.stack_.back()->set("socket-type", $4);
ctx.leave();
};
+control_socket_type_value:
+ UNIX { $$ = ElementPtr(new StringElement("unix", ctx.loc2pos(@1))); }
+ | HTTP { $$ = ElementPtr(new StringElement("http", ctx.loc2pos(@1))); }
+ | HTTPS { $$ = ElementPtr(new StringElement("https", ctx.loc2pos(@1))); }
+ ;
+
control_socket_name: SOCKET_NAME {
ctx.unique("socket-name", ctx.loc2pos(@1));
ctx.enter(ctx.NO_KEYWORD);
ctx.leave();
};
+control_socket_address: SOCKET_ADDRESS {
+ ctx.unique("socket-address", ctx.loc2pos(@1));
+ ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+ ElementPtr address(new StringElement($4, ctx.loc2pos(@4)));
+ ctx.stack_.back()->set("socket-address", address);
+ ctx.leave();
+};
+
+control_socket_port: SOCKET_PORT COLON INTEGER {
+ ctx.unique("socket-port", ctx.loc2pos(@1));
+ ElementPtr port(new IntElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("socket-port", port);
+};
+
+cert_required: CERT_REQUIRED COLON BOOLEAN {
+ ctx.unique("cert-required", ctx.loc2pos(@1));
+ ElementPtr req(new BoolElement($3, ctx.loc2pos(@3)));
+ ctx.stack_.back()->set("cert-required", req);
+};
+
+// --- authentication ---------------------------------------------
+
+authentication: AUTHENTICATION {
+ ctx.unique("authentication", ctx.loc2pos(@1));
+ ElementPtr m(new MapElement(ctx.loc2pos(@1)));
+ ctx.stack_.back()->set("authentication", m);
+ ctx.stack_.push_back(m);
+ ctx.enter(ctx.AUTHENTICATION);
+} COLON LCURLY_BRACKET auth_params RCURLY_BRACKET {
+ // The type parameter is required
+ ctx.require("type", ctx.loc2pos(@4), ctx.loc2pos(@6));
+ ctx.stack_.pop_back();
+ ctx.leave();
+};
+
+auth_params: auth_param
+ | auth_params COMMA auth_param
+ | auth_params COMMA {
+ ctx.warnAboutExtraCommas(@2);
+ }
+ ;
+
+auth_param: auth_type
+ | realm
+ | directory
+ | clients
+ | comment
+ | user_context
+ | unknown_map_entry
+ ;
+
+auth_type: TYPE {
+ ctx.unique("type", ctx.loc2pos(@1));
+ ctx.enter(ctx.AUTH_TYPE);
+} COLON auth_type_value {
+ ctx.stack_.back()->set("type", $4);
+ ctx.leave();
+};
+
+auth_type_value: BASIC { $$ = ElementPtr(new StringElement("basic", ctx.loc2pos(@1))); }
+ ;
+
+realm: REALM {
+ ctx.unique("realm", ctx.loc2pos(@1));
+ ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+ ElementPtr realm(new StringElement($4, ctx.loc2pos(@4)));
+ ctx.stack_.back()->set("realm", realm);
+ ctx.leave();
+};
+
+directory: DIRECTORY {
+ ctx.unique("directory", ctx.loc2pos(@1));
+ ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+ ElementPtr directory(new StringElement($4, ctx.loc2pos(@4)));
+ ctx.stack_.back()->set("directory", directory);
+ ctx.leave();
+};
+
+clients: CLIENTS {
+ ctx.unique("clients", ctx.loc2pos(@1));
+ ElementPtr l(new ListElement(ctx.loc2pos(@1)));
+ ctx.stack_.back()->set("clients", l);
+ ctx.stack_.push_back(l);
+ ctx.enter(ctx.CLIENTS);
+} COLON LSQUARE_BRACKET clients_list RSQUARE_BRACKET {
+ ctx.stack_.pop_back();
+ ctx.leave();
+};
+
+clients_list: %empty
+ | not_empty_clients_list
+ ;
+
+not_empty_clients_list: basic_auth
+ | not_empty_clients_list COMMA basic_auth
+ | not_empty_clients_list COMMA {
+ ctx.warnAboutExtraCommas(@2);
+ }
+ ;
+
+basic_auth: LCURLY_BRACKET {
+ ElementPtr m(new MapElement(ctx.loc2pos(@1)));
+ ctx.stack_.back()->add(m);
+ ctx.stack_.push_back(m);
+} clients_params RCURLY_BRACKET {
+ ctx.stack_.pop_back();
+};
+
+clients_params: clients_param
+ | clients_params COMMA clients_param
+ | clients_params COMMA {
+ ctx.warnAboutExtraCommas(@2);
+ }
+ ;
+
+clients_param: user
+ | user_file
+ | password
+ | password_file
+ | user_context
+ | comment
+ | unknown_map_entry
+ ;
+
+user_file: USER_FILE {
+ ctx.unique("user-file", ctx.loc2pos(@1));
+ ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+ ElementPtr user(new StringElement($4, ctx.loc2pos(@4)));
+ ctx.stack_.back()->set("user-file", user);
+ ctx.leave();
+};
+
+password_file: PASSWORD_FILE {
+ ctx.unique("password-file", ctx.loc2pos(@1));
+ ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+ ElementPtr password(new StringElement($4, ctx.loc2pos(@4)));
+ ctx.stack_.back()->set("password-file", password);
+ ctx.leave();
+};
+
// --- hooks libraries -----------------------------------------
hooks_libraries: HOOKS_LIBRARIES {