Browse Source

[5017] Support for several v4 specific keywords implemented:

 - next-server, server-hostname, boof-file-name, echo-client-id,
   match-client-id
Tomek Mrugalski 8 years ago
parent
commit
1c5c135452

+ 9 - 3
doc/examples/kea4/classify.json

@@ -51,10 +51,16 @@
 
 # Let's pick VoIP phones. Those that send their class identifiers
 # as Aastra, should belong to VoIP class. For a list of all options,
-# see www.iana.org/assignments/bootp-dhcp-parameters/
+# see www.iana.org/assignments/bootp-dhcp-parameters/.
+# In this particular class, we want to set specific values
+# of certain DHCPv4 fields. If the incoming packet matches the
+# test, those fields will be set in outgoing responses.
   {
       "name": "VoIP",
-      "test": "substring(option[60].hex,0,6) == 'Aastra'"
+      "test": "substring(option[60].hex,0,6) == 'Aastra'",
+      "next-server": "192.0.2.254",
+      "server-hostname": "hal9000",
+      "boot-file-name": "/dev/null"
   }
 
   ],
@@ -65,7 +71,7 @@
 # to that class are allowed for that subnet.
   "subnet4": [
     {
-# This one is for VoIP devices only.          
+# This one is for VoIP devices only.
         "pools": [ { "pool":  "192.0.2.1 - 192.0.2.200" } ],
         "subnet": "192.0.2.0/24",
         "client-class": "VoIP",

+ 10 - 0
doc/examples/kea4/reservations.json

@@ -106,6 +106,16 @@
                      "data": "10.1.1.202,10.1.1.203"
                  }
              ]
+         },
+# This reservation is for a client that needs specific DHCPv4 fields to be
+# set. Three supported fields are next-server, server-hostname and
+# boot-file-name
+         {
+             "client-id": "01:0a:0b:0c:0d:0e:of",
+             "ip-address": "192.0.2.205",
+             "next-server": "192.0.2.1",
+             "server-hostname": "hal9000",
+             "boot-file-name": "/dev/null"
          }
        ]
     }

+ 52 - 0
src/bin/dhcp4/dhcp4_lexer.ll

@@ -851,6 +851,58 @@ ControlCharacterFill            [^"\\]|\\{JSONEscapeSequence}
     }
 }
 
+\"echo-client-id\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser4Context::SUBNET4:
+        return isc::dhcp::Dhcp4Parser::make_ECHO_CLIENT_ID(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp4Parser::make_STRING("echo-client-id", driver.loc_);
+    }
+}
+
+\"match-client-id\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser4Context::SUBNET4:
+        return isc::dhcp::Dhcp4Parser::make_MATCH_CLIENT_ID(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp4Parser::make_STRING("match-client-id", driver.loc_);
+    }
+}
+
+\"next-server\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser4Context::SUBNET4:
+    case isc::dhcp::Parser4Context::RESERVATIONS:
+    case isc::dhcp::Parser4Context::CLIENT_CLASSES:
+        return isc::dhcp::Dhcp4Parser::make_NEXT_SERVER(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp4Parser::make_STRING("next-server", driver.loc_);
+    }
+}
+
+\"server-hostname\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser4Context::SUBNET4:
+    case isc::dhcp::Parser4Context::RESERVATIONS:
+    case isc::dhcp::Parser4Context::CLIENT_CLASSES:
+        return isc::dhcp::Dhcp4Parser::make_SERVER_HOSTNAME(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp4Parser::make_STRING("server-hostname", driver.loc_);
+    }
+}
+
+\"boot-file-name\" {
+    switch(driver.ctx_) {
+    case isc::dhcp::Parser4Context::SUBNET4:
+    case isc::dhcp::Parser4Context::RESERVATIONS:
+    case isc::dhcp::Parser4Context::CLIENT_CLASSES:
+        return isc::dhcp::Dhcp4Parser::make_BOOT_FILE_NAME(driver.loc_);
+    default:
+        return isc::dhcp::Dhcp4Parser::make_STRING("boot-file-name", driver.loc_);
+    }
+}
+
+
 
 {JSONString} {
     // A string has been matched. It contains the actual string and single quotes.

+ 52 - 0
src/bin/dhcp4/dhcp4_parser.yy

@@ -53,6 +53,12 @@ using namespace std;
   INTERFACES_CONFIG "interfaces-config"
   INTERFACES "interfaces"
 
+  ECHO_CLIENT_ID "echo-client-id"
+  MATCH_CLIENT_ID "match-client-id"
+  NEXT_SERVER "next-server"
+  SERVER_HOSTNAME "server-hostname"
+  BOOT_FILE_NAME "boot-file-name"
+
   LEASE_DATABASE "lease-database"
   HOSTS_DATABASE "hosts-database"
   TYPE "type"
@@ -365,6 +371,9 @@ global_param: valid_lifetime
             | version
             | control_socket
             | dhcp_ddns
+            | echo_client_id
+            | match_client_id
+            | next_server
             | unknown_map_entry
             ;
 
@@ -388,6 +397,17 @@ decline_probation_period: DECLINE_PROBATION_PERIOD COLON INTEGER {
     ctx.stack_.back()->set("decline-probation-period", dpp);
 };
 
+echo_client_id: ECHO_CLIENT_ID COLON BOOLEAN {
+    ElementPtr echo(new BoolElement($3, ctx.loc2pos(@1)));
+    ctx.stack_.back()->set("echo-client-id", echo);
+};
+
+match_client_id: MATCH_CLIENT_ID COLON BOOLEAN {
+    ElementPtr match(new BoolElement($3, ctx.loc2pos(@1)));
+    ctx.stack_.back()->set("match-client-id", match);
+};
+
+
 interfaces_config: INTERFACES_CONFIG {
     ElementPtr i(new MapElement(ctx.loc2pos(@1)));
     ctx.stack_.back()->set("interfaces-config", i);
@@ -1083,13 +1103,42 @@ reservation_param: duid
                  | hw_address
                  | hostname
                  | option_data_list
+                 | next_server
+                 | server_hostname
+                 | boot_file_name
                  | unknown_map_entry
                  ;
 
+next_server: NEXT_SERVER {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    ElementPtr next_server(new StringElement($4, ctx.loc2pos(@1)));
+    ctx.stack_.back()->set("next-server", next_server);
+    ctx.leave();
+};
+
+server_hostname: SERVER_HOSTNAME {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    ElementPtr srv(new StringElement($4, ctx.loc2pos(@1)));
+    ctx.stack_.back()->set("server-hostname", srv);
+    ctx.leave();
+};
+
+boot_file_name: BOOT_FILE_NAME {
+    ctx.enter(ctx.NO_KEYWORD);
+} COLON STRING {
+    ElementPtr bootfile(new StringElement($4, ctx.loc2pos(@1)));
+    ctx.stack_.back()->set("boot-file-name", bootfile);
+    ctx.leave();
+};
+
 ip_address: IP_ADDRESS {
+    ctx.enter(ctx.NO_KEYWORD);
 } COLON STRING {
     ElementPtr addr(new StringElement($4, ctx.loc2pos(@1)));
     ctx.stack_.back()->set("ip-address", addr);
+    ctx.leave();
 };
 
 duid: DUID {
@@ -1200,6 +1249,9 @@ not_empty_client_class_params: client_class_param
 client_class_param: client_class_name
                   | client_class_test
                   | option_data_list
+                  | next_server
+                  | server_hostname
+                  | boot_file_name
                   | unknown_map_entry
                   ;