]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3477] Updated d2 and some UTs
authorFrancis Dupont <fdupont@isc.org>
Thu, 4 Jul 2024 17:47:08 +0000 (19:47 +0200)
committerFrancis Dupont <fdupont@isc.org>
Thu, 1 Aug 2024 07:23:53 +0000 (09:23 +0200)
16 files changed:
src/bin/d2/d2_lexer.cc
src/bin/d2/d2_lexer.ll
src/bin/d2/parser_context.cc
src/bin/d2/parser_context.h
src/bin/d2/tests/d2_cfg_mgr_unittests.cc
src/bin/d2/tests/d2_command_unittest.cc
src/bin/d2/tests/parser_unittest.cc
src/bin/d2/tests/testdata/get_config.json
src/bin/dhcp4/tests/config_parser_unittest.cc
src/bin/dhcp4/tests/get_config_unittest.cc
src/bin/dhcp6/tests/config_parser_unittest.cc
src/bin/dhcp6/tests/get_config_unittest.cc
src/lib/d2srv/d2_cfg_mgr.cc
src/lib/d2srv/d2_cfg_mgr.h
src/lib/d2srv/d2_config.h
src/lib/d2srv/d2_simple_parser.cc

index f060818e6f7552704277b504bf9fb2c30a49f1fc..d4cfcb884d5de7ffac5334ef03d810a728e958c2 100644 (file)
@@ -328,6 +328,7 @@ typedef int16_t flex_int16_t;
 typedef uint16_t flex_uint16_t;
 typedef int32_t flex_int32_t;
 typedef uint32_t flex_uint32_t;
+typedef uint64_t flex_uint64_t;
 #else
 typedef signed char flex_int8_t;
 typedef short int flex_int16_t;
@@ -452,7 +453,7 @@ typedef size_t yy_size_t;
 #endif
 
 /* %if-not-reentrant */
-extern int yyleng;
+extern yy_size_t yyleng;
 /* %endif */
 
 /* %if-c-only */
@@ -505,7 +506,7 @@ struct yy_buffer_state
        /* Number of characters read into yy_ch_buf, not including EOB
         * characters.
         */
-       int yy_n_chars;
+       yy_size_t yy_n_chars;
 
        /* Whether we "own" the buffer - i.e., we know we created it,
         * and can realloc() it to grow it, and should free() it to
@@ -586,8 +587,8 @@ static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
 /* %not-for-header */
 /* yy_hold_char holds the character lost when yytext is formed. */
 static char yy_hold_char;
-static int yy_n_chars;         /* number of characters read into yy_ch_buf */
-int yyleng;
+static yy_size_t yy_n_chars;           /* number of characters read into yy_ch_buf */
+yy_size_t yyleng;
 
 /* Points to current character in buffer. */
 static char *yy_c_buf_p = NULL;
@@ -617,7 +618,7 @@ static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file  );
 
 YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size  );
 YY_BUFFER_STATE yy_scan_string ( const char *yy_str  );
-YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len  );
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len  );
 
 /* %endif */
 
@@ -685,7 +686,7 @@ static void yynoreturn yy_fatal_error ( const char* msg  );
 #define YY_DO_BEFORE_ACTION \
        (yytext_ptr) = yy_bp; \
 /* %% [2.0] code to fiddle yytext and yyleng for yymore() goes here \ */\
-       yyleng = (int) (yy_cp - yy_bp); \
+       yyleng = (yy_size_t) (yy_cp - yy_bp); \
        (yy_hold_char) = *yy_cp; \
        *yy_cp = '\0'; \
 /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\
@@ -1212,7 +1213,7 @@ unsigned int comment_start_line = 0;
 
 /* To avoid the call to exit... oops! */
 #define YY_FATAL_ERROR(msg) isc::d2::D2ParserContext::fatal(msg)
-#line 1215 "d2_lexer.cc"
+#line 1216 "d2_lexer.cc"
 /* noyywrap disables automatic rewinding for the next file to parse. Since we
    always parse only a single string, there's no need to do any wraps. And
    using yywrap requires linking with -lfl, which provides the default yywrap
@@ -1238,8 +1239,8 @@ unsigned int comment_start_line = 0;
    by moving it ahead by yyleng bytes. yyleng specifies the length of the
    currently matched token. */
 #define YY_USER_ACTION  driver.loc_.columns(yyleng);
-#line 1241 "d2_lexer.cc"
 #line 1242 "d2_lexer.cc"
+#line 1243 "d2_lexer.cc"
 
 #define INITIAL 0
 #define COMMENT 1
@@ -1295,7 +1296,7 @@ FILE *yyget_out ( void );
 
 void yyset_out  ( FILE * _out_str  );
 
-                       int yyget_leng ( void );
+                       yy_size_t yyget_leng ( void );
 
 char *yyget_text ( void );
 
@@ -1382,7 +1383,7 @@ static int input ( void );
        if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
                { \
                int c = '*'; \
-               int n; \
+               yy_size_t n; \
                for ( n = 0; n < max_size && \
                             (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
                        buf[n] = (char) c; \
@@ -1559,7 +1560,7 @@ YY_DECL
     }
 
 
-#line 1562 "d2_lexer.cc"
+#line 1563 "d2_lexer.cc"
 
        while ( /*CONSTCOND*/1 )                /* loops until end-of-file is reached */
                {
@@ -2042,9 +2043,9 @@ YY_RULE_SETUP
 {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
-        return isc::d2::D2Parser::make_CONTROL_SOCKET(driver.loc_);
+        return isc::d2::D2Parser::make_CONTROL_SOCKETS(driver.loc_);
     default:
-        return isc::d2::D2Parser::make_STRING("control-socket", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("control-sockets", driver.loc_);
     }
 }
        YY_BREAK
@@ -2137,7 +2138,7 @@ YY_RULE_SETUP
 #line 497 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+    case isc::d2::D2ParserContext::CONTROL_SOCKET:
         return isc::d2::D2Parser::make_AUTHENTICATION(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("authentication", driver.loc_);
@@ -2149,7 +2150,7 @@ YY_RULE_SETUP
 #line 506 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::AUTHENTICATION:
+    case isc::d2::D2ParserContext::AUTHENTICATION:
         return isc::d2::D2Parser::make_TYPE(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("type", driver.loc_);
@@ -2161,7 +2162,7 @@ YY_RULE_SETUP
 #line 515 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::AUTH_TYPE:
+    case isc::d2::D2ParserContext::AUTH_TYPE:
         return isc::d2::D2Parser::make_BASIC(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("basic", driver.loc_);
@@ -2173,7 +2174,7 @@ YY_RULE_SETUP
 #line 524 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::AUTHENTICATION:
+    case isc::d2::D2ParserContext::AUTHENTICATION:
         return isc::d2::D2Parser::make_REALM(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("realm", driver.loc_);
@@ -2185,7 +2186,7 @@ YY_RULE_SETUP
 #line 533 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::AUTHENTICATION:
+    case isc::d2::D2ParserContext::AUTHENTICATION:
         return isc::d2::D2Parser::make_DIRECTORY(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("directory", driver.loc_);
@@ -2197,7 +2198,7 @@ YY_RULE_SETUP
 #line 542 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::AUTHENTICATION:
+    case isc::d2::D2ParserContext::AUTHENTICATION:
         return isc::d2::D2Parser::make_CLIENTS(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("clients", driver.loc_);
@@ -2209,7 +2210,7 @@ YY_RULE_SETUP
 #line 551 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CLIENTS:
+    case isc::d2::D2ParserContext::CLIENTS:
         return isc::d2::D2Parser::make_USER(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("user", driver.loc_);
@@ -2221,7 +2222,7 @@ YY_RULE_SETUP
 #line 560 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CLIENTS:
+    case isc::d2::D2ParserContext::CLIENTS:
         return isc::d2::D2Parser::make_USER_FILE(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("user-file", driver.loc_);
@@ -2233,7 +2234,7 @@ YY_RULE_SETUP
 #line 569 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CLIENTS:
+    case isc::d2::D2ParserContext::CLIENTS:
         return isc::d2::D2Parser::make_PASSWORD(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("password", driver.loc_);
@@ -2245,7 +2246,7 @@ YY_RULE_SETUP
 #line 578 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CLIENTS:
+    case isc::d2::D2ParserContext::CLIENTS:
         return isc::d2::D2Parser::make_PASSWORD_FILE(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("password-file", driver.loc_);
@@ -2257,7 +2258,7 @@ YY_RULE_SETUP
 #line 587 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+    case isc::d2::D2ParserContext::CONTROL_SOCKET:
         return isc::d2::D2Parser::make_TRUST_ANCHOR(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("trust-anchor", driver.loc_);
@@ -2269,7 +2270,7 @@ YY_RULE_SETUP
 #line 596 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+    case isc::d2::D2ParserContext::CONTROL_SOCKET:
         return isc::d2::D2Parser::make_CERT_FILE(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("cert-file", driver.loc_);
@@ -2281,7 +2282,7 @@ YY_RULE_SETUP
 #line 605 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+    case isc::d2::D2ParserContext::CONTROL_SOCKET:
         return isc::d2::D2Parser::make_KEY_FILE(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("key-file", driver.loc_);
@@ -2293,7 +2294,7 @@ YY_RULE_SETUP
 #line 614 "d2_lexer.ll"
 {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+    case isc::d2::D2ParserContext::CONTROL_SOCKET:
         return isc::d2::D2Parser::make_CERT_REQUIRED(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("cert-required", driver.loc_);
@@ -2810,7 +2811,7 @@ YY_RULE_SETUP
 #line 1020 "d2_lexer.ll"
 ECHO;
        YY_BREAK
-#line 2813 "d2_lexer.cc"
+#line 2814 "d2_lexer.cc"
 
        case YY_END_OF_BUFFER:
                {
@@ -3012,7 +3013,7 @@ static int yy_get_next_buffer (void)
 
        else
                {
-                       int num_to_read =
+                       yy_size_t num_to_read =
                        YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
                while ( num_to_read <= 0 )
@@ -3026,7 +3027,7 @@ static int yy_get_next_buffer (void)
 
                        if ( b->yy_is_our_buffer )
                                {
-                               int new_size = b->yy_buf_size * 2;
+                               yy_size_t new_size = b->yy_buf_size * 2;
 
                                if ( new_size <= 0 )
                                        b->yy_buf_size += b->yy_buf_size / 8;
@@ -3084,7 +3085,7 @@ static int yy_get_next_buffer (void)
 
        if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
                /* Extend the array by 50%, plus the number we really need. */
-               int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+               yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
                YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
                        (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size  );
                if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
@@ -3205,7 +3206,7 @@ static int yy_get_next_buffer (void)
 
                else
                        { /* need more input */
-                       int offset = (int) ((yy_c_buf_p) - (yytext_ptr));
+                       yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
                        ++(yy_c_buf_p);
 
                        switch ( yy_get_next_buffer(  ) )
@@ -3648,12 +3649,12 @@ YY_BUFFER_STATE yy_scan_string (const char * yystr )
  * 
  * @return the newly allocated buffer state object.
  */
-YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len )
+YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, yy_size_t  _yybytes_len )
 {
        YY_BUFFER_STATE b;
        char *buf;
        yy_size_t n;
-       int i;
+       yy_size_t i;
     
        /* Get memory for full buffer, including space for trailing EOB's. */
        n = (yy_size_t) (_yybytes_len + 2);
@@ -3700,7 +3701,7 @@ static void yynoreturn yy_fatal_error (const char* msg )
        do \
                { \
                /* Undo effects of setting up yytext. */ \
-        int yyless_macro_arg = (n); \
+        yy_size_t yyless_macro_arg = (n); \
         YY_LESS_LINENO(yyless_macro_arg);\
                yytext[yyleng] = (yy_hold_char); \
                (yy_c_buf_p) = yytext + yyless_macro_arg; \
@@ -3744,7 +3745,7 @@ FILE *yyget_out  (void)
 /** Get the length of the current token.
  * 
  */
-int yyget_leng  (void)
+yy_size_t yyget_leng  (void)
 {
         return yyleng;
 }
index db036352ce9cef7f38c3b62a514599e2b70d3f91..d90cda684eb6029181760051ba4e8e51e8c45436 100644 (file)
@@ -424,9 +424,9 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 \"control-sockets\" {
     switch(driver.ctx_) {
     case isc::d2::D2ParserContext::DHCPDDNS:
-        return isc::d2::D2Parser::make_CONTROL_SOCKET(driver.loc_);
+        return isc::d2::D2Parser::make_CONTROL_SOCKETS(driver.loc_);
     default:
-        return isc::d2::D2Parser::make_STRING("control-socket", driver.loc_);
+        return isc::d2::D2Parser::make_STRING("control-sockets", driver.loc_);
     }
 }
 
@@ -495,7 +495,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"authentication\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+    case isc::d2::D2ParserContext::CONTROL_SOCKET:
         return isc::d2::D2Parser::make_AUTHENTICATION(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("authentication", driver.loc_);
@@ -504,7 +504,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"type\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::AUTHENTICATION:
+    case isc::d2::D2ParserContext::AUTHENTICATION:
         return isc::d2::D2Parser::make_TYPE(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("type", driver.loc_);
@@ -513,7 +513,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"basic\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::AUTH_TYPE:
+    case isc::d2::D2ParserContext::AUTH_TYPE:
         return isc::d2::D2Parser::make_BASIC(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("basic", driver.loc_);
@@ -522,7 +522,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"realm\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::AUTHENTICATION:
+    case isc::d2::D2ParserContext::AUTHENTICATION:
         return isc::d2::D2Parser::make_REALM(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("realm", driver.loc_);
@@ -531,7 +531,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"directory\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::AUTHENTICATION:
+    case isc::d2::D2ParserContext::AUTHENTICATION:
         return isc::d2::D2Parser::make_DIRECTORY(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("directory", driver.loc_);
@@ -540,7 +540,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"clients\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::AUTHENTICATION:
+    case isc::d2::D2ParserContext::AUTHENTICATION:
         return isc::d2::D2Parser::make_CLIENTS(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("clients", driver.loc_);
@@ -549,7 +549,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"user\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CLIENTS:
+    case isc::d2::D2ParserContext::CLIENTS:
         return isc::d2::D2Parser::make_USER(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("user", driver.loc_);
@@ -558,7 +558,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"user-file\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CLIENTS:
+    case isc::d2::D2ParserContext::CLIENTS:
         return isc::d2::D2Parser::make_USER_FILE(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("user-file", driver.loc_);
@@ -567,7 +567,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"password\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CLIENTS:
+    case isc::d2::D2ParserContext::CLIENTS:
         return isc::d2::D2Parser::make_PASSWORD(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("password", driver.loc_);
@@ -576,7 +576,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"password-file\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CLIENTS:
+    case isc::d2::D2ParserContext::CLIENTS:
         return isc::d2::D2Parser::make_PASSWORD_FILE(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("password-file", driver.loc_);
@@ -585,7 +585,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"trust-anchor\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+    case isc::d2::D2ParserContext::CONTROL_SOCKET:
         return isc::d2::D2Parser::make_TRUST_ANCHOR(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("trust-anchor", driver.loc_);
@@ -594,7 +594,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"cert-file\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+    case isc::d2::D2ParserContext::CONTROL_SOCKET:
         return isc::d2::D2Parser::make_CERT_FILE(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("cert-file", driver.loc_);
@@ -603,7 +603,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"key-file\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+    case isc::d2::D2ParserContext::CONTROL_SOCKET:
         return isc::d2::D2Parser::make_KEY_FILE(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("key-file", driver.loc_);
@@ -612,7 +612,7 @@ ControlCharacterFill            [^"\\]|\\["\\/bfnrtu]
 
 \"cert-required\" {
     switch(driver.ctx_) {
-    case isc::dhcp::Parser4Context::CONTROL_SOCKET:
+    case isc::d2::D2ParserContext::CONTROL_SOCKET:
         return isc::d2::D2Parser::make_CERT_REQUIRED(driver.loc_);
     default:
         return isc::d2::D2Parser::make_STRING("cert-required", driver.loc_);
index 26ee144e238db23babb429a220ce216be2abfd6f..ac5a3d4f5e21c2537f88d2c16d688feb98c138d4 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017-2022 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2024 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -188,6 +188,14 @@ D2ParserContext::contextName()
         return("dns-servers");
     case CONTROL_SOCKET:
         return("control-socket");
+    case CONTROL_SOCKET_TYPE:
+        return ("control-socket-type");
+    case AUTHENTICATION:
+        return ("authentication");
+    case AUTH_TYPE:
+        return ("auth-type");
+    case CLIENTS:
+        return ("clients");
     case LOGGERS:
         return ("loggers");
     case OUTPUT_OPTIONS:
index 0bf2a58cd9a397230a1050577d4989fb4edfcc5e..d55a7277a3f0d36f5ad69614e7eac48634c2904d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2017-2023 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2024 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -257,6 +257,18 @@ public:
         ///< Used while parsing content of a control-socket
         CONTROL_SOCKET,
 
+        ///< Used while parsing content of a socket-type
+        CONTROL_SOCKET_TYPE,
+
+        ///< Used while parsing content of an authentication
+        AUTHENTICATION,
+
+        ///< Used while parsing content of an authentication type
+        AUTH_TYPE,
+
+        ///< Used while parsing content of a client
+        CLIENTS,
+
         /// Used while parsing DhcpDdns/loggers structures.
         LOGGERS,
 
index 62a71139702e1854d2304e04c4196e5f7d5f1dc0..96e423e688f787d8e019b1f0e7a0d3e036221b87 100644 (file)
@@ -971,11 +971,29 @@ TEST_F(D2CfgMgrTest, comments) {
                         "\"comment\": \"D2 config\" , "
                         "\"ip-address\" : \"192.168.1.33\" , "
                         "\"port\" : 88 , "
-                        "\"control-socket\": {"
-                        " \"comment\": \"Control channel\" , "
-                        " \"socket-type\": \"unix\" ,"
-                        " \"socket-name\": \"/tmp/d2-ctrl-channel\" "
+                        "\"control-sockets\": ["
+                        "{"
+                        " \"socket-type\": \"unix\","
+                        " \"socket-name\": \"/tmp/d2-ctrl-socket\","
+                        " \"user-context\": { \"comment\":"
+                        "  \"Indirect comment\" }"
                         "},"
+                        "{"
+                        " \"comment\": \"HTTP control socket\","
+                        " \"socket-type\": \"http\","
+                        " \"socket-address\": \"::1\","
+                        " \"socket-port\": 8053,"
+                        " \"authentication\": {"
+                        "  \"comment\": \"basic HTTP authentication\","
+                        "  \"type\": \"basic\","
+                        "  \"clients\": [ {"
+                        "   \"comment\": \"admin is authorized\","
+                        "   \"user\": \"admin\","
+                        "   \"password\": \"1234\""
+                        "  } ]"
+                        " }"
+                        "}"
+                        "],"
                         "\"tsig-keys\": ["
                         "{"
                         "  \"user-context\": { "
@@ -1011,12 +1029,45 @@ TEST_F(D2CfgMgrTest, comments) {
     ASSERT_TRUE(ctx->get("comment"));
     EXPECT_EQ("\"D2 config\"", ctx->get("comment")->str());
 
-    // Check control socket.
-    ConstElementPtr ctrl_sock = d2_context->getControlSocketInfo();
-    ASSERT_TRUE(ctrl_sock);
-    ASSERT_TRUE(ctrl_sock->get("user-context"));
-    EXPECT_EQ("{ \"comment\": \"Control channel\" }",
-              ctrl_sock->get("user-context")->str());
+    // There is a UNIX control socket.
+    ConstElementPtr socket = d2_context->getControlSocketInfo();
+    ASSERT_TRUE(socket);
+    ConstElementPtr ctx_socket = socket->get("user-context");
+    ASSERT_TRUE(ctx_socket);
+    ASSERT_EQ(1, ctx_socket->size());
+    ASSERT_TRUE(ctx_socket->get("comment"));
+    EXPECT_EQ("\"Indirect comment\"", ctx_socket->get("comment")->str());
+
+    // There is a HTTP control socket with authentication.
+    socket = d2_context->getHttpControlSocketInfo();
+    ASSERT_TRUE(socket);
+    ctx_socket = socket->get("user-context");
+    ASSERT_TRUE(ctx_socket);
+    ASSERT_EQ(1, ctx_socket->size());
+    ASSERT_TRUE(ctx_socket->get("comment"));
+    EXPECT_EQ("\"HTTP control socket\"", ctx_socket->get("comment")->str());
+
+    // HTTP authentication.
+    ConstElementPtr auth = socket->get("authentication");
+    ASSERT_TRUE(auth);
+    ConstElementPtr ctx_auth = auth->get("user-context");
+    ASSERT_TRUE(ctx_auth);
+    ASSERT_EQ(1, ctx_auth->size());
+    ASSERT_TRUE(ctx_auth->get("comment"));
+    EXPECT_EQ("\"basic HTTP authentication\"", ctx_auth->get("comment")->str());
+
+    // Authentication client.
+    ConstElementPtr clients = auth->get("clients");
+    ASSERT_TRUE(clients);
+    ASSERT_EQ(1, clients->size());
+    ConstElementPtr client;
+    ASSERT_NO_THROW(client = clients->get(0));
+    ASSERT_TRUE(client);
+    ConstElementPtr ctx_client = client->get("user-context");
+    ASSERT_TRUE(ctx_client);
+    ASSERT_EQ(1, ctx_client->size());
+    ASSERT_TRUE(ctx_client->get("comment"));
+    EXPECT_EQ("\"admin is authorized\"", ctx_client->get("comment")->str());
 
     // Check TSIG keys.
     TSIGKeyInfoMapPtr keys = d2_context->getKeys();
index 8b133b174ae3d3f0702e2a299077c9c4930aa527..6b3a0272b83668916fdffcd1bd5b894af731d4ea 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2018-2023 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2024 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -453,33 +453,7 @@ TEST_F(CtrlChannelD2Test, configure) {
     EXPECT_EQ(1, status);
     ASSERT_TRUE(txt);
     ASSERT_EQ(Element::string, txt->getType());
-    EXPECT_EQ("Mandatory 'socket-type' parameter missing", txt->stringValue());
-    EXPECT_EQ(-1, CommandMgr::instance().getControlSocketFD());
-
-    // bad type.
-    string bad2 =
-        "{"
-        "    \"ip-address\": \"192.168.77.1\","
-        "    \"port\": 777,"
-        "    \"control-socket\": {"
-        "        \"socket-type\": \"bogus\","
-        "        \"socket-name\": \"/tmp/d2.sock\""
-        "    },"
-        "    \"tsig-keys\": [],"
-        "    \"forward-ddns\" : {},"
-        "    \"reverse-ddns\" : {}"
-        "}";
-    ASSERT_NO_THROW(config = parseDHCPDDNS(bad2, true));
-
-    answer = proc->configure(config, false);
-    ASSERT_TRUE(answer);
-
-    status = 0;
-    txt = parseAnswer(status, answer);
-    EXPECT_EQ(1, status);
-    ASSERT_TRUE(txt);
-    ASSERT_EQ(Element::string, txt->getType());
-    EXPECT_EQ("Invalid 'socket-type' parameter value bogus",
+    EXPECT_EQ("'socket-type' parameter is mandatory in control-sockets items",
               txt->stringValue());
     EXPECT_EQ(-1, CommandMgr::instance().getControlSocketFD());
 
index 15b82af56df2ad217810a8f0c6aae4dda1c6c4a7..2ab573119aa53f2a6cb41795de29576634a065dc 100644 (file)
@@ -861,7 +861,22 @@ TEST_F(TrailingCommasTest, tests) {
         "name": "d2.md5.key",
         "secret": "sensitivejdPJI5QxlpnfQ==",
       },
-    ]
+    ],
+    "control-sockets": [
+      {
+        "socket-type": "http",
+        "socket-address": "::1",
+        "authentication": {
+          "clients": [
+            {
+              "password-file": "/tmp/pwd",
+            }
+          ],
+          "type": "basic",
+        },
+        "socket-port": 8053,
+      },
+    ],
   },
 })");
     testParser(txt, D2ParserContext::PARSER_DHCPDDNS, false);
@@ -871,7 +886,12 @@ TEST_F(TrailingCommasTest, tests) {
     addLog("<string>:14.8");
     addLog("<string>:22.45");
     addLog("<string>:23.8");
-    addLog("<string>:25.4");
+    addLog("<string>:32.42");
+    addLog("<string>:35.26");
+    addLog("<string>:37.28");
+    addLog("<string>:38.8");
+    addLog("<string>:39.6");
+    addLog("<string>:40.4");
     EXPECT_TRUE(checkFile());
 
     // Test with many consecutive commas.
index ee3deccbb01d2266c5ff69d1a2e6f766b9db96d9..d3059dde7fef7832e1fa80c4bd9e75d048dd740c 100644 (file)
@@ -1,9 +1,11 @@
 {
     "DhcpDdns": {
-        "control-socket": {
-            "socket-name": "/tmp/kea-ddns-ctrl-socket",
-            "socket-type": "unix"
-        },
+        "control-sockets": [
+            {
+                "socket-name": "/tmp/kea-ddns-ctrl-socket",
+                "socket-type": "unix"
+            }
+        ],
         "dns-server-timeout": 1000,
         "forward-ddns": {
             "ddns-domains": [
index fa96578c8c156590a607588addda3f0727f765ea..2ddcc5e198df3d140e0c8619a5b3ff8a3a9ac077 100644 (file)
@@ -203,11 +203,28 @@ const char* PARSER_CONFIGS[] = {
     "           }"
     "        }"
     "        ],"
-    "    \"control-socket\": {"
-    "        \"socket-type\": \"unix\","
-    "        \"socket-name\": \"/tmp/kea4-ctrl-socket\","
-    "        \"user-context\": { \"comment\": \"Indirect comment\" }"
-    "    },"
+    "    \"control-sockets\": ["
+    "        {"
+    "            \"socket-type\": \"unix\","
+    "            \"socket-name\": \"/tmp/kea4-ctrl-socket\","
+    "            \"user-context\": { \"comment\": \"Indirect comment\" }"
+    "        },"
+    "        {"
+    "            \"comment\": \"HTTP control socket\","
+    "            \"socket-type\": \"http\","
+    "            \"socket-address\": \"::1\","
+    "            \"socket-port\": 8000,"
+    "            \"authentication\": {"
+    "                \"comment\": \"basic HTTP authentication\","
+    "                \"type\": \"basic\","
+    "                \"clients\": [ {"
+    "                    \"comment\": \"admin is authorized\","
+    "                    \"user\": \"admin\","
+    "                    \"password\": \"1234\""
+    "                } ]"
+    "            }"
+    "        }"
+    "    ],"
     "    \"shared-networks\": [ {"
     "        \"comment\": \"A shared network\","
     "        \"name\": \"foo\","
@@ -6781,7 +6798,7 @@ TEST_F(Dhcp4ParserTest, comments) {
     ASSERT_TRUE(ctx_class->get("version"));
     EXPECT_EQ("1", ctx_class->get("version")->str());
 
-    // There is a control socket.
+    // There is a UNIX control socket.
     ConstElementPtr socket =
         CfgMgr::instance().getStagingCfg()->getControlSocketInfo();
     ASSERT_TRUE(socket);
@@ -6790,12 +6807,58 @@ TEST_F(Dhcp4ParserTest, comments) {
     ASSERT_TRUE(socket->get("socket-name"));
     EXPECT_EQ("\"/tmp/kea4-ctrl-socket\"", socket->get("socket-name")->str());
 
-    // Check control socket comment and user context.
+    // Check UNIX control socket comment and user context.
     ConstElementPtr ctx_socket = socket->get("user-context");
+    ASSERT_TRUE(ctx_socket);
     ASSERT_EQ(1, ctx_socket->size());
     ASSERT_TRUE(ctx_socket->get("comment"));
     EXPECT_EQ("\"Indirect comment\"", ctx_socket->get("comment")->str());
 
+    // There is a HTTP control socket with authentication.
+    socket = CfgMgr::instance().getStagingCfg()->getHttpControlSocketInfo();
+    ASSERT_TRUE(socket);
+    ASSERT_TRUE(socket->get("socket-type"));
+    EXPECT_EQ("\"http\"", socket->get("socket-type")->str());
+    ASSERT_TRUE(socket->get("socket-address"));
+    EXPECT_EQ("\"::1\"", socket->get("socket-address")->str());
+    ASSERT_TRUE(socket->get("socket-port"));
+    EXPECT_EQ("8000", socket->get("socket-port")->str());
+
+    // Check HTTP control socket comment.
+    ctx_socket = socket->get("user-context");
+    ASSERT_TRUE(ctx_socket);
+    ASSERT_EQ(1, ctx_socket->size());
+    ASSERT_TRUE(ctx_socket->get("comment"));
+    EXPECT_EQ("\"HTTP control socket\"", ctx_socket->get("comment")->str());
+
+    // HTTP authentication.
+    ConstElementPtr auth = socket->get("authentication");
+    ASSERT_TRUE(auth);
+    ASSERT_TRUE(auth->get("type"));
+    EXPECT_EQ("\"basic\"", auth->get("type")->str());
+    ConstElementPtr ctx_auth = auth->get("user-context");
+    ASSERT_TRUE(ctx_auth);
+    ASSERT_EQ(1, ctx_auth->size());
+    ASSERT_TRUE(ctx_auth->get("comment"));
+    EXPECT_EQ("\"basic HTTP authentication\"", ctx_auth->get("comment")->str());
+
+    // Authentication client.
+    ConstElementPtr clients = auth->get("clients");
+    ASSERT_TRUE(clients);
+    ASSERT_EQ(1, clients->size());
+    ConstElementPtr client;
+    ASSERT_NO_THROW(client = clients->get(0));
+    ASSERT_TRUE(client);
+    ASSERT_TRUE(client->get("user"));
+    ASSERT_EQ("\"admin\"", client->get("user")->str());
+    ASSERT_TRUE(client->get("password"));
+    ASSERT_EQ("\"1234\"", client->get("password")->str());
+    ConstElementPtr ctx_client = client->get("user-context");
+    ASSERT_TRUE(ctx_client);
+    ASSERT_EQ(1, ctx_client->size());
+    ASSERT_TRUE(ctx_client->get("comment"));
+    EXPECT_EQ("\"admin is authorized\"", ctx_client->get("comment")->str());
+
     // Now verify that the shared network was indeed configured.
     const CfgSharedNetworks4Ptr& cfg_net =
         CfgMgr::instance().getStagingCfg()->getCfgSharedNetworks4();
index 891a28881112873cbae99d93776f99d6fd485049..72e7279e111e921173bf1976294a6dd45553cb32 100644 (file)
@@ -2018,13 +2018,38 @@ const char* EXTRACTED_CONFIGS[] = {
 "                }\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"
+"                \"authentication\": {\n"
+"                    \"clients\": [\n"
+"                        {\n"
+"                            \"password\": \"1234\",\n"
+"                            \"user\": \"admin\",\n"
+"                            \"user-context\": {\n"
+"                                \"comment\": \"admin is authorized\"\n"
+"                            }\n"
+"                        }\n"
+"                    ],\n"
+"                    \"type\": \"basic\",\n"
+"                    \"user-context\": {\n"
+"                        \"comment\": \"basic HTTP authentication\"\n"
+"                    }\n"
+"                },\n"
+"                \"socket-address\": \"::1\",\n"
+"                \"socket-port\": 8000,\n"
+"                \"socket-type\": \"http\",\n"
+"                \"user-context\": {\n"
+"                    \"comment\": \"HTTP control socket\"\n"
+"                }\n"
 "            }\n"
-"        },\n"
+"        ],\n"
 "        \"dhcp-ddns\": {\n"
 "            \"enable-updates\": false,\n"
 "            \"user-context\": {\n"
@@ -10902,6 +10927,29 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"user-context\": {\n"
 "                    \"comment\": \"Indirect comment\"\n"
 "                }\n"
+"            },\n"
+"            {\n"
+"                \"authentication\": {\n"
+"                    \"clients\": [\n"
+"                        {\n"
+"                            \"password\": \"1234\",\n"
+"                            \"user\": \"admin\",\n"
+"                            \"user-context\": {\n"
+"                                \"comment\": \"admin is authorized\"\n"
+"                            }\n"
+"                        }\n"
+"                    ],\n"
+"                    \"type\": \"basic\",\n"
+"                    \"user-context\": {\n"
+"                        \"comment\": \"basic HTTP authentication\"\n"
+"                    }\n"
+"                },\n"
+"                \"socket-address\": \"::1\",\n"
+"                \"socket-port\": 8000,\n"
+"                \"socket-type\": \"http\",\n"
+"                \"user-context\": {\n"
+"                    \"comment\": \"HTTP control socket\"\n"
+"                }\n"
 "            }\n"
 "        ],\n"
 "        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
index 6ecc515837dc1b2dae6a6c45bf96586b7683796d..8aefc7d070f4187707bd599872dc1fac7fac4fa8 100644 (file)
@@ -312,11 +312,28 @@ const char* PARSER_CONFIGS[] = {
     "           }"
     "        }"
     "        ],"
-    "    \"control-socket\": {"
-    "        \"socket-type\": \"unix\","
-    "        \"socket-name\": \"/tmp/kea6-ctrl-socket\","
-    "        \"user-context\": { \"comment\": \"Indirect comment\" }"
-    "    },"
+    "    \"control-sockets\": ["
+    "        {"
+    "            \"socket-type\": \"unix\","
+    "            \"socket-name\": \"/tmp/kea6-ctrl-socket\","
+    "            \"user-context\": { \"comment\": \"Indirect comment\" }"
+    "        },"
+    "        {"
+    "            \"comment\": \"HTTP control socket\","
+    "            \"socket-type\": \"http\","
+    "            \"socket-address\": \"127.0.0.1\","
+    "            \"socket-port\": 8000,"
+    "            \"authentication\": {"
+    "                \"comment\": \"basic HTTP authentication\","
+    "                \"type\": \"basic\","
+    "                \"clients\": [ {"
+    "                    \"comment\": \"admin is authorized\","
+    "                    \"user\": \"admin\","
+    "                    \"password\": \"1234\""
+    "                } ]"
+    "            }"
+    "        }"
+    "    ],"
     "    \"shared-networks\": [ {"
     "        \"comment\": \"A shared network\","
     "        \"name\": \"foo\","
@@ -7364,7 +7381,7 @@ TEST_F(Dhcp6ParserTest, comments) {
     ASSERT_TRUE(ctx_class->get("version"));
     EXPECT_EQ("1", ctx_class->get("version")->str());
 
-    // There is a control socket.
+    // There is a UNIX control socket.
     ConstElementPtr socket =
         CfgMgr::instance().getStagingCfg()->getControlSocketInfo();
     ASSERT_TRUE(socket);
@@ -7373,12 +7390,58 @@ TEST_F(Dhcp6ParserTest, comments) {
     ASSERT_TRUE(socket->get("socket-name"));
     EXPECT_EQ("\"/tmp/kea6-ctrl-socket\"", socket->get("socket-name")->str());
 
-    // Check control socket comment and user context.
+    // Check UNIX control socket comment and user context.
     ConstElementPtr ctx_socket = socket->get("user-context");
+    ASSERT_TRUE(ctx_socket);
     ASSERT_EQ(1, ctx_socket->size());
     ASSERT_TRUE(ctx_socket->get("comment"));
     EXPECT_EQ("\"Indirect comment\"", ctx_socket->get("comment")->str());
 
+    // There is a HTTP control socket with authentication.
+    socket = CfgMgr::instance().getStagingCfg()->getHttpControlSocketInfo();
+    ASSERT_TRUE(socket);
+    ASSERT_TRUE(socket->get("socket-type"));
+    EXPECT_EQ("\"http\"", socket->get("socket-type")->str());
+    ASSERT_TRUE(socket->get("socket-address"));
+    EXPECT_EQ("\"127.0.0.1\"", socket->get("socket-address")->str());
+    ASSERT_TRUE(socket->get("socket-port"));
+    EXPECT_EQ("8000", socket->get("socket-port")->str());
+
+    // Check HTTP control socket comment.
+    ctx_socket = socket->get("user-context");
+    ASSERT_TRUE(ctx_socket);
+    ASSERT_EQ(1, ctx_socket->size());
+    ASSERT_TRUE(ctx_socket->get("comment"));
+    EXPECT_EQ("\"HTTP control socket\"", ctx_socket->get("comment")->str());
+
+    // HTTP authentication.
+    ConstElementPtr auth = socket->get("authentication");
+    ASSERT_TRUE(auth);
+    ASSERT_TRUE(auth->get("type"));
+    EXPECT_EQ("\"basic\"", auth->get("type")->str());
+    ConstElementPtr ctx_auth = auth->get("user-context");
+    ASSERT_TRUE(ctx_auth);
+    ASSERT_EQ(1, ctx_auth->size());
+    ASSERT_TRUE(ctx_auth->get("comment"));
+    EXPECT_EQ("\"basic HTTP authentication\"", ctx_auth->get("comment")->str());
+
+    // Authentication client.
+    ConstElementPtr clients = auth->get("clients");
+    ASSERT_TRUE(clients);
+    ASSERT_EQ(1, clients->size());
+    ConstElementPtr client;
+    ASSERT_NO_THROW(client = clients->get(0));
+    ASSERT_TRUE(client);
+    ASSERT_TRUE(client->get("user"));
+    ASSERT_EQ("\"admin\"", client->get("user")->str());
+    ASSERT_TRUE(client->get("password"));
+    ASSERT_EQ("\"1234\"", client->get("password")->str());
+    ConstElementPtr ctx_client = client->get("user-context");
+    ASSERT_TRUE(ctx_client);
+    ASSERT_EQ(1, ctx_client->size());
+    ASSERT_TRUE(ctx_client->get("comment"));
+    EXPECT_EQ("\"admin is authorized\"", ctx_client->get("comment")->str());
+
     // Now verify that the shared network was indeed configured.
     const CfgSharedNetworks6Ptr& cfg_net =
         CfgMgr::instance().getStagingCfg()->getCfgSharedNetworks6();
index 63a7d066909a3f26f7aebc240c777cc32730ae44..2bfd3f10d7cb93b14de02fcf772180eb400056a1 100644 (file)
@@ -1751,13 +1751,38 @@ const char* EXTRACTED_CONFIGS[] = {
 "                }\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"
+"                \"authentication\": {\n"
+"                    \"clients\": [\n"
+"                        {\n"
+"                            \"password\": \"1234\",\n"
+"                            \"user\": \"admin\",\n"
+"                            \"user-context\": {\n"
+"                                \"comment\": \"admin is authorized\"\n"
+"                            }\n"
+"                        }\n"
+"                    ],\n"
+"                    \"type\": \"basic\",\n"
+"                    \"user-context\": {\n"
+"                        \"comment\": \"basic HTTP authentication\"\n"
+"                    }\n"
+"                },\n"
+"                \"socket-address\": \"127.0.0.1\",\n"
+"                \"socket-port\": 8000,\n"
+"                \"socket-type\": \"http\",\n"
+"                \"user-context\": {\n"
+"                    \"comment\": \"HTTP control socket\"\n"
+"                }\n"
 "            }\n"
-"        },\n"
+"        ],\n"
 "        \"dhcp-ddns\": {\n"
 "            \"enable-updates\": false,\n"
 "            \"user-context\": {\n"
@@ -9601,6 +9626,29 @@ const char* UNPARSED_CONFIGS[] = {
 "                \"user-context\": {\n"
 "                    \"comment\": \"Indirect comment\"\n"
 "                }\n"
+"            },\n"
+"            {\n"
+"                \"authentication\": {\n"
+"                    \"clients\": [\n"
+"                        {\n"
+"                            \"password\": \"1234\",\n"
+"                            \"user\": \"admin\",\n"
+"                            \"user-context\": {\n"
+"                                \"comment\": \"admin is authorized\"\n"
+"                            }\n"
+"                        }\n"
+"                    ],\n"
+"                    \"type\": \"basic\",\n"
+"                    \"user-context\": {\n"
+"                        \"comment\": \"basic HTTP authentication\"\n"
+"                    }\n"
+"                },\n"
+"                \"socket-address\": \"127.0.0.1\",\n"
+"                \"socket-port\": 8000,\n"
+"                \"socket-type\": \"http\",\n"
+"                \"user-context\": {\n"
+"                    \"comment\": \"HTTP control socket\"\n"
+"                }\n"
 "            }\n"
 "        ],\n"
 "        \"ddns-conflict-resolution-mode\": \"check-with-dhcid\",\n"
index bf7df10dee855686c17ee41dac3ce8b07fb6915b..eea8ff2237f4fd46eb2a3497dc14f0440b5934b2 100644 (file)
@@ -35,7 +35,8 @@ D2CfgContext::D2CfgContext()
       forward_mgr_(new DdnsDomainListMgr("forward-ddns")),
       reverse_mgr_(new DdnsDomainListMgr("reverse-ddns")),
       keys_(new TSIGKeyInfoMap()),
-      control_socket_(ConstElementPtr()) {
+      unix_control_socket_(ConstElementPtr()),
+      http_control_socket_(ConstElementPtr()) {
 }
 
 D2CfgContext::D2CfgContext(const D2CfgContext& rhs) : ConfigBase(rhs) {
@@ -52,7 +53,9 @@ D2CfgContext::D2CfgContext(const D2CfgContext& rhs) : ConfigBase(rhs) {
 
     keys_ = rhs.keys_;
 
-    control_socket_ = rhs.control_socket_;
+    unix_control_socket_ = rhs.unix_control_socket_;
+
+    http_control_socket_ = rhs.http_control_socket_;
 
     hooks_config_ = rhs.hooks_config_;
 }
@@ -98,9 +101,16 @@ D2CfgContext::toElement() const {
         tsig_keys->add(key.second->toElement());
     }
     d2->set("tsig-keys", tsig_keys);
-    // Set control-socket (skip if null as empty is not legal)
-    if (!isNull(control_socket_)) {
-        d2->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()) {
+        d2->set("control-sockets", control_sockets);
     }
     // Set hooks-libraries
     d2->set("hooks-libraries", hooks_config_.toElement());
@@ -237,6 +247,11 @@ D2CfgMgr::getControlSocketInfo() {
     return (getD2CfgContext()->getControlSocketInfo());
 }
 
+const isc::data::ConstElementPtr
+D2CfgMgr::getHttpControlSocketInfo() {
+    return (getD2CfgContext()->getHttpControlSocketInfo());
+}
+
 std::string
 D2CfgMgr::getConfigSummary(const uint32_t) {
     return (getD2Params()->getConfigSummary());
index eade86cbffab460be2d1a2c5981a465eb92a0631..841684e7250bd75813c7cbefc0a266fc0af3356a 100644 (file)
@@ -91,16 +91,28 @@ public:
         keys_ = keys;
     }
 
-    /// @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 non-const reference to configured hooks libraries.
@@ -142,8 +154,11 @@ private:
     /// @brief Storage for the map of TSIGKeyInfos.
     TSIGKeyInfoMapPtr keys_;
 
-    /// @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/HTTPS control-socket information.
+    isc::data::ConstElementPtr http_control_socket_;
 
     /// @brief Configured hooks libraries.
     isc::hooks::HooksConfig hooks_config_;
@@ -285,11 +300,16 @@ public:
     /// @return reference to const D2ParamsPtr
     const D2ParamsPtr& getD2Params();
 
-    /// @brief Convenience method fetches information about control socket
-    /// from context
+    /// @brief Convenience method fetches information about
+    /// UNIX control socket from context
     /// @return pointer to the Element that holds control-socket map
     const isc::data::ConstElementPtr getControlSocketInfo();
 
+    /// @brief Convenience method fetches information about
+    /// HTTP/HTTPS control socket from context
+    /// @return pointer to the Element that holds control-socket map
+    const isc::data::ConstElementPtr getHttpControlSocketInfo();
+
     /// @brief Returns configuration summary in the textual format.
     ///
     /// @param selection Bitfield which describes the parts of the configuration
index 2b57ddf3871703dc8c7028162f5922ded0543bfa..4653bcbbf9e17875676eab7763055025fcf9db9c 100644 (file)
@@ -75,11 +75,13 @@ namespace d2 {
 ///  "interface" : "eth1" ,
 ///  "ip-address" : "192.168.1.33" ,
 ///  "port" : 88 ,
-///  "control-socket":
-///  {
-///    "socket-type": "unix" ,
-///    "socket-name": "/tmp/kea-ddns-ctrl-socket"
-//// },
+///  "control-sockets":
+///  [
+///    {
+///     "socket-type": "unix" ,
+///     "socket-name": "/tmp/kea-ddns-ctrl-socket"
+///    }
+///  ],
 ///  "tsig-keys":
 //// [
 ///    {
index c86bcd061d3a94dbdc084a54cd2499e03b81eb44..4a6ae88d0406c1c4ba3a86981543e6d77d250edf 100644 (file)
@@ -262,13 +262,61 @@ void D2SimpleParser::parse(const D2CfgContextPtr& ctx,
         ctx->setContext(user);
     }
 
-    ConstElementPtr socket = config->get("control-socket");
-    if (socket) {
-        if (socket->getType() != Element::map) {
-            isc_throw(D2CfgError, "Specified control-socket is expected to be a map"
-                      ", i.e. a structure defined within { }");
+    // Get control sockets.
+    ConstElementPtr control_sockets = config->get("control-sockets");
+    ConstElementPtr control_socket = config->get("control-socket");
+    if (control_socket) {
+        ElementPtr l = Element::createList();
+        l->add(UserContext::toElement(control_socket));
+        control_sockets = l;
+    }
+    if (control_sockets) {
+        if (control_sockets->getType() != Element::list) {
+            // Sanity check: not supposed to fail.
+            isc_throw(D2CfgError,
+                      "Specified control-sockets is expected to be a list");
+        }
+        bool seen_unix(false);
+        bool seen_http(false);
+        for (ConstElementPtr socket : control_sockets->listValue()) {
+            if (socket->getType() != Element::map) {
+                // Sanity check: not supposed to fail.
+                isc_throw(D2CfgError,
+                          "Specified control-sockets is expected to be a list of maps");
+            }
+            ConstElementPtr socket_type = socket->get("socket-type");
+            if (!socket_type) {
+                isc_throw(D2CfgError,
+                          "'socket-type' parameter is mandatory in control-sockets items");
+            }
+            if (socket_type->getType() != Element::string) {
+                // Sanity check: not supposed to fail.
+                isc_throw(D2CfgError,
+                          "'socket-type' parameter is expected to be a string");
+            }
+            std::string type = socket_type->stringValue();
+            if (type == "unix") {
+                if (seen_unix) {
+                    isc_throw(D2CfgError,
+                              "control socket of type 'unix' already configured");
+                }
+                seen_unix = true;
+                ctx->setControlSocketInfo(socket);
+            } else if ((type == "http") || (type == "https")) {
+                if (seen_http) {
+                    isc_throw(D2CfgError,
+                              "control socket of type 'http' or 'https'"
+                              " already configured");
+                }
+                seen_http = true;
+                ctx->setHttpControlSocketInfo(socket);
+            } else {
+                // Sanity check: not supposed to fail.
+                isc_throw(D2CfgError,
+                          "unsupported 'socket-type': '" << type
+                          << "' not 'unix', 'http' or 'https'");
+            }
         }
-        ctx->setControlSocketInfo(socket);
     }
 
     // Finally, let's get the hook libs!