Browse Source

[5033] Ported flex/bison stuff to DHCPv6

Francis Dupont 8 years ago
parent
commit
0a30a27a56

+ 228 - 1
src/bin/dhcp6/dhcp6_lexer.ll

@@ -1,4 +1,4 @@
-/* Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2016-2017 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
@@ -123,6 +123,8 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
             return isc::dhcp::Dhcp6Parser::make_SUB_OPTION_DATA(driver.loc_);
         case Parser6Context::PARSER_HOOKS_LIBRARY:
             return isc::dhcp::Dhcp6Parser::make_SUB_HOOKS_LIBRARY(driver.loc_);
+        case Parser6Context::PARSER_DHCP_DDNS:
+            return isc::dhcp::Dhcp6Parser::make_SUB_DHCP_DDNS(driver.loc_);
         }
     }
 %}
@@ -171,6 +173,231 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
 }
 
 
+\"enable-updates\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_ENABLE_UPDATES(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("enable-updates", driver.loc_);
+    }
+}
+
+\"qualifying-suffix\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_QUALIFYING_SUFFIX(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("qualifying-suffix", driver.loc_);
+    }
+}
+
+\"server-ip\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_SERVER_IP(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("server-ip", driver.loc_);
+    }
+}
+
+\"server-port\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_SERVER_PORT(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("server-port", driver.loc_);
+    }
+}
+
+\"sender-ip\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_SENDER_IP(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("sender-ip", driver.loc_);
+    }
+}
+
+\"sender-port\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_SENDER_PORT(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("sender-port", driver.loc_);
+    }
+}
+
+\"max-queue-size\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_MAX_QUEUE_SIZE(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("max-queue-size", driver.loc_);
+    }
+}
+
+\"ncr-protocol\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_NCR_PROTOCOL(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("ncr-protocol", driver.loc_);
+    }
+}
+
+\"ncr-format\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_NCR_FORMAT(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("ncr-format", driver.loc_);
+    }
+}
+
+\"always-include-fqdn\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_ALWAYS_INCLUDE_FQDN(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("always-include-fqdn", driver.loc_);
+    }
+}
+
+\"allow-client-update\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_ALLOW_CLIENT_UPDATE(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("allow-client-update", driver.loc_);
+    }
+}
+
+\"override-no-update\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_OVERRIDE_NO_UPDATE(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("override-no-update", driver.loc_);
+    }
+}
+
+\"override-client-update\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_OVERRIDE_CLIENT_UPDATE(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("override-client-update", driver.loc_);
+    }
+}
+
+\"replace-client-name\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_REPLACE_CLIENT_NAME(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("replace-client-name", driver.loc_);
+    }
+}
+
+\"generated-prefix\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser6Context::DHCP_DDNS:
+        return isc::dhcp::Dhcp6Parser::make_GENERATED_PREFIX(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp6Parser::make_STRING("generated-prefix", driver.loc_);
+    }
+}
+
+(?i:\"UDP\") {
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::dhcp::Parser6Context::NCR_PROTOCOL) {
+        return isc::dhcp::Dhcp6Parser::make_UDP(driver.loc_);
+    }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::dhcp::Dhcp6Parser::make_STRING(tmp, driver.loc_);
+}
+
+(?i:\"TCP\") {
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::dhcp::Parser6Context::NCR_PROTOCOL) {
+        return isc::dhcp::Dhcp6Parser::make_TCP(driver.loc_);
+    }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::dhcp::Dhcp6Parser::make_STRING(tmp, driver.loc_);
+}
+
+(?i:\"JSON\") {
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::dhcp::Parser6Context::NCR_FORMAT) {
+        return isc::dhcp::Dhcp6Parser::make_JSON(driver.loc_);
+    }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::dhcp::Dhcp6Parser::make_STRING(tmp, driver.loc_);
+}
+
+(?i:\"when-present\") {
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::dhcp::Parser6Context::REPLACE_CLIENT_NAME) {
+        return isc::dhcp::Dhcp6Parser::make_WHEN_PRESENT(driver.loc_);
+    }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::dhcp::Dhcp6Parser::make_STRING(tmp, driver.loc_);
+}
+
+(?i:\"true\") {
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::dhcp::Parser6Context::REPLACE_CLIENT_NAME) {
+        return isc::dhcp::Dhcp6Parser::make_WHEN_PRESENT(driver.loc_);
+    }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::dhcp::Dhcp6Parser::make_STRING(tmp, driver.loc_);
+}
+
+(?i:\"never\") {
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::dhcp::Parser6Context::REPLACE_CLIENT_NAME) {
+        return isc::dhcp::Dhcp6Parser::make_NEVER(driver.loc_);
+    }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::dhcp::Dhcp6Parser::make_STRING(tmp, driver.loc_);
+}
+
+(?i:\"false\") {
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::dhcp::Parser6Context::REPLACE_CLIENT_NAME) {
+        return isc::dhcp::Dhcp6Parser::make_NEVER(driver.loc_);
+    }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::dhcp::Dhcp6Parser::make_STRING(tmp, driver.loc_);
+}
+
+(?i:\"always\") {
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::dhcp::Parser6Context::REPLACE_CLIENT_NAME) {
+        return isc::dhcp::Dhcp6Parser::make_ALWAYS(driver.loc_);
+    }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::dhcp::Dhcp6Parser::make_STRING(tmp, driver.loc_);
+}
+
+(?i:\"when-not-present\") {
+    /* dhcp-ddns value keywords are case insensitive */
+    if (driver.ctx_ == isc::dhcp::Parser6Context::REPLACE_CLIENT_NAME) {
+        return isc::dhcp::Dhcp6Parser::make_WHEN_NOT_PRESENT(driver.loc_);
+    }
+    std::string tmp(yytext+1);
+    tmp.resize(tmp.size() - 1);
+    return isc::dhcp::Dhcp6Parser::make_STRING(tmp, driver.loc_);
+}
+
 \"Dhcp6\"  {
     switch(driver.ctx_) {
     case isc::dhcp::Parser6Context::CONFIG:

+ 177 - 23
src/bin/dhcp6/dhcp6_parser.yy

@@ -1,4 +1,4 @@
-/* Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
+/* Copyright (C) 2016-2017 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
@@ -133,26 +133,28 @@ using namespace std;
   SOCKET_NAME "socket-name"
 
   DHCP_DDNS "dhcp-ddns"
-
- /// @todo: Implement proper parsing for those parameters in Dhcp6/dhcp-ddns/*.
- /// This should be part of the #5043 ticket. Listing the keywords here for
- /// completeness.
-
- // These are tokens defined in Dhcp6/dhcp-ddns/*
- // They're not
- //  ENABLE_UPDATES "enable-updates"
- //  SERVER_IP "server-ip"
- //  SENDER_IP "sender-ip"
- //  SENDER_PORT "sender-port"
- //  MAX_QUEUE_SIZE "max-queue-size"
- //  NCR_PROTOCOL "ncr-protocol"
- //  NCR_FORMAT "ncr-format"
- //  ALWAYS_INCLUDE_FQDN "always-include-fqdn"
- //  OVERRDIDE_NO_UPDATE "override-no-update"
- //  OVERRDIDE_CLIENT_UPDATE "override-client-update"
- //  REPLACE_CLIENT_NAME "replace-client-name"
- //  GENERATED_PREFIX "generated-prefix"
- //  QUALIFYING_SUFFIX "qualifying-suffix"
+  ENABLE_UPDATES "enable-updates"
+  QUALIFYING_SUFFIX "qualifying-suffix"
+  SERVER_IP "server-ip"
+  SERVER_PORT "server-port"
+  SENDER_IP "sender-ip"
+  SENDER_PORT "sender-port"
+  MAX_QUEUE_SIZE "max-queue-size"
+  NCR_PROTOCOL "ncr-protocol"
+  NCR_FORMAT "ncr-format"
+  ALWAYS_INCLUDE_FQDN "always-include-fqdn"
+  ALLOW_CLIENT_UPDATE "allow-client-update"
+  OVERRIDE_NO_UPDATE "override-no-update"
+  OVERRIDE_CLIENT_UPDATE "override-client-update"
+  REPLACE_CLIENT_NAME "replace-client-name"
+  GENERATED_PREFIX "generated-prefix"
+  UDP "UDP"
+  TCP "TCP"
+  JSON "JSON"
+  WHEN_PRESENT "when-present"
+  NEVER "never"
+  ALWAYS "always"
+  WHEN_NOT_PRESENT "when-not-present"
 
   LOGGING "Logging"
   LOGGERS "loggers"
@@ -177,6 +179,7 @@ using namespace std;
   SUB_OPTION_DEF
   SUB_OPTION_DATA
   SUB_HOOKS_LIBRARY
+  SUB_DHCP_DDNS
 ;
 
 %token <std::string> STRING "constant string"
@@ -185,6 +188,8 @@ using namespace std;
 %token <bool> BOOLEAN "boolean"
 
 %type <ElementPtr> value
+%type <ElementPtr> ncr_protocol_value
+%type <ElementPtr> replace_client_name_value
 
 %printer { yyoutput << $$; } <*>;
 
@@ -206,6 +211,7 @@ start: TOPLEVEL_JSON { ctx.ctx_ = ctx.NO_KEYWORD; } sub_json
      | SUB_OPTION_DEF { ctx.ctx_ = ctx.OPTION_DEF; } sub_option_def
      | SUB_OPTION_DATA { ctx.ctx_ = ctx.OPTION_DATA; } sub_option_data
      | SUB_HOOKS_LIBRARY { ctx.ctx_ = ctx.HOOKS_LIBRARIES; } sub_hooks_library
+     | SUB_DHCP_DDNS { ctx.ctx_ = ctx.DHCP_DDNS; } sub_dhcp_ddns
      ;
 
 // ---- generic JSON parser ---------------------------------
@@ -1409,12 +1415,160 @@ dhcp_ddns: DHCP_DDNS {
     ElementPtr m(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->set("dhcp-ddns", m);
     ctx.stack_.push_back(m);
-    ctx.enter(ctx.NO_KEYWORD);
-} COLON LCURLY_BRACKET not_empty_map RCURLY_BRACKET {
+    ctx.enter(ctx.DHCP_DDNS);
+} COLON LCURLY_BRACKET dhcp_ddns_params RCURLY_BRACKET {
     ctx.stack_.pop_back();
     ctx.leave();
 };
 
+sub_dhcp_ddns: LCURLY_BRACKET {
+    // Parse the dhcp-ddns map
+    ElementPtr m(new MapElement(ctx.loc2pos(@1)));
+    ctx.stack_.push_back(m);
+} dhcp_ddns_params RCURLY_BRACKET {
+    // parsing completed
+};
+
+dhcp_ddns_params: dhcp_ddns_param
+                | dhcp_ddns_params COMMA dhcp_ddns_param
+                ;
+
+dhcp_ddns_param: enable_updates
+               | qualifying_suffix
+               | server_ip
+               | server_port
+               | sender_ip
+               | sender_port
+               | max_queue_size
+               | ncr_protocol
+               | ncr_format
+               | always_include_fqdn
+               | allow_client_update
+               | override_no_update
+               | override_client_update
+               | replace_client_name
+               | generated_prefix
+               | unknown_map_entry
+               ;
+
+enable_updates: ENABLE_UPDATES COLON BOOLEAN {
+    ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("enable-updates", b);
+};
+
+qualifying_suffix: QUALIFYING_SUFFIX {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
+    ctx.stack_.back()->set("qualifying-suffix", s);
+    ctx.leave();
+};
+
+server_ip: SERVER_IP {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
+    ctx.stack_.back()->set("server-ip", s);
+    ctx.leave();
+};
+
+server_port: SERVER_PORT COLON INTEGER {
+    ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("server-port", i);
+};
+
+sender_ip: SENDER_IP {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
+    ctx.stack_.back()->set("sender-ip", s);
+    ctx.leave();
+};
+
+sender_port: SENDER_PORT COLON INTEGER {
+    ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("sender-port", i);
+};
+
+max_queue_size: MAX_QUEUE_SIZE COLON INTEGER {
+    ElementPtr i(new IntElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("max-queue-size", i);
+};
+
+ncr_protocol: NCR_PROTOCOL {
+    ctx.enter(ctx.NCR_PROTOCOL);
+} COLON ncr_protocol_value {
+    ctx.stack_.back()->set("ncr-protocol", $4);
+    ctx.leave();
+};
+
+ncr_protocol_value:
+    UDP { $$ = ElementPtr(new StringElement("UDP", ctx.loc2pos(@1))); }
+  | TCP { $$ = ElementPtr(new StringElement("TCP", ctx.loc2pos(@1))); }
+  ;
+
+ncr_format: NCR_FORMAT {
+    ctx.enter(ctx.NCR_FORMAT);
+} COLON JSON {
+    ElementPtr json(new StringElement("JSON", ctx.loc2pos(@4)));
+    ctx.stack_.back()->set("ncr-format", json);
+    ctx.leave();
+};
+
+always_include_fqdn: ALWAYS_INCLUDE_FQDN COLON BOOLEAN {
+    ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("always-include-fqdn", b);
+};
+
+allow_client_update: ALLOW_CLIENT_UPDATE COLON BOOLEAN {
+    ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("allow-client-update",  b);
+};
+
+override_no_update: OVERRIDE_NO_UPDATE COLON BOOLEAN {
+    ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("override-no-update", b);
+};
+
+override_client_update: OVERRIDE_CLIENT_UPDATE COLON BOOLEAN {
+    ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
+    ctx.stack_.back()->set("override-client-update", b);
+};
+
+replace_client_name: REPLACE_CLIENT_NAME {
+    ctx.enter(ctx.REPLACE_CLIENT_NAME);
+} COLON replace_client_name_value {
+    ctx.stack_.back()->set("replace-client-name", $4);
+    ctx.leave();
+};
+
+replace_client_name_value:
+    WHEN_PRESENT {
+      $$ = ElementPtr(new StringElement("when-present", ctx.loc2pos(@1))); 
+      }
+  | NEVER {
+      $$ = ElementPtr(new StringElement("never", ctx.loc2pos(@1)));
+      }
+  | ALWAYS {
+      $$ = ElementPtr(new StringElement("always", ctx.loc2pos(@1)));
+      }
+  | WHEN_NOT_PRESENT {
+      $$ = ElementPtr(new StringElement("when-not-present", ctx.loc2pos(@1)));
+      }
+  | BOOLEAN  {
+      error(@1, "boolean values for the replace-client-name are "
+                "no longer supported");
+      }
+  ;
+
+generated_prefix: GENERATED_PREFIX {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    ElementPtr s(new StringElement($4, ctx.loc2pos(@4)));
+    ctx.stack_.back()->set("generated-prefix", s);
+    ctx.leave();
+};
+
 // JSON entries for Dhcp4 and DhcpDdns
 
 dhcp4_json_object: DHCP4 {

+ 6 - 0
src/bin/dhcp6/parser_context.cc

@@ -165,6 +165,12 @@ Parser6Context::contextName()
         return ("output-options");
     case DHCP_DDNS:
         return ("dhcp-ddns");
+    case NCR_PROTOCOL:
+        return ("ncr-protocol");
+    case NCR_FORMAT:
+        return ("ncr-format");
+    case REPLACE_CLIENT_NAME:
+        return ("replace-client-name");
     default:
         return ("__unknown__");
     }

+ 13 - 3
src/bin/dhcp6/parser_context.h

@@ -190,7 +190,7 @@ public:
         ///< Used while parsing content of Dhcp6.
         DHCP6,
 
-        // not yet DHCP4,
+        // not yet Dhcp4, DhcpDdns,
 
         ///< Used while parsing content of Logging
         LOGGING,
@@ -254,8 +254,18 @@ public:
         /// Used while parsing Logging/loggers/output_options structures.
         OUTPUT_OPTIONS,
 
-        /// Used while parsing Dhcp6/dhcp-ddns
-        DHCP_DDNS
+        /// Used while parsing Dhcp6/dhcp-ddns.
+        DHCP_DDNS,
+
+        /// Used while parsing Dhcp6/dhcp-ddns/ncr-protocol
+        NCR_PROTOCOL,
+
+        /// Used while parsing Dhcp6/dhcp-ddns/ncr-format
+        NCR_FORMAT,
+
+        /// Used while parsing Dhcp6/dhcp-ddns/replace-client-name.
+        REPLACE_CLIENT_NAME
+
     } ParserContext;
 
     /// @brief File name

+ 1 - 1
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc

@@ -276,7 +276,7 @@ TEST_F(Dhcpv6SrvTest, DUID) {
     case DUID::DUID_LLT: {
         // DUID must contain at least 6 bytes long MAC
         // + 8 bytes of fixed header
-        EXPECT_GE(14, len);
+        EXPECT_GE(len, 14);
 
         uint16_t hw_type = data.readUint16();
         // there's no real way to find out "correct"