]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
[master] Add code to parse a vendor option as directed by the user.
authorShawn Routhier <sar@isc.org>
Mon, 13 Jul 2015 19:06:50 +0000 (12:06 -0700)
committerShawn Routhier <sar@isc.org>
Mon, 13 Jul 2015 19:06:50 +0000 (12:06 -0700)
Add code to parse a vendor option.  It is structured as an action
in the config language.  When the statement is executed it attempts
to find a vendor option in the packet and a vendor option space
specified by the admin for use with that packet.  It then calls
the proper parse routine to do the parsing.

RELNOTES
common/conflex.c
common/dhcp-eval.5
common/execute.c
common/options.c
common/parse.c
includes/dhcpd.h
includes/dhctoken.h
includes/statement.h

index bec9bc2f2bbd22173da6a2433213848d679a8428..dca0795df67fc8036d918a05f32a8f6759191e75 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -157,6 +157,11 @@ by Eric Young (eay@cryptsoft.com).
   itself.
   [ISC-Bugs #38329]
 
+- Add a new action expression "parse_vendor_options", which can be used
+  to parse a vendor-encapsualted-option received by the server based on
+  the encoding specified by the vendor-option-space statement.
+  [ISC-Bugs #36449]
+
                        Changes since 4.3.2rc2
 - None
 
index 093ac036d5e475e6240ce2d4d6587fc1ba2cf3dc..391101601384a0b299d750d7ebd7ef83cced6cc0 100644 (file)
@@ -3,7 +3,7 @@
    Lexical scanner for dhcpd config file... */
 
 /*
- * Copyright (c) 2004-2014 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2015 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -1214,6 +1214,8 @@ intern(char *atom, enum dhcp_token dfv) {
                        return OWNER;
                break;
              case 'p':
+               if (!strcasecmp (atom + 1, "arse-vendor-option"))
+                       return PARSE_VENDOR_OPT;
                if (!strcasecmp (atom + 1, "repend"))
                        return PREPEND;
                if (!strcasecmp(atom + 1, "referred-life"))
index 1ba2e449240618140cfc216f2aa3761688000d3b..7dd526139be4e8c8814d5d3a79c8ef8b0d5108fe 100644 (file)
@@ -1,6 +1,6 @@
 .\"    $Id: dhcp-eval.5,v 1.33 2012/05/17 15:50:14 sar Exp $
 .\"
-.\" Copyright (c) 2009-2012,2014 by Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (c) 2009-2012,2014-2015 by Internet Systems Consortium, Inc. ("ISC")
 .\" Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
 .\" Copyright (c) 1996-2003 by Internet Software Consortium
 .\"
@@ -557,6 +557,21 @@ It is possible to use the execute statement in any context, not only
 on events.  If you put it in a regular scope in the configuration file
 you will execute that command every time a scope is evaluated.
 .RE
+.PP
+.B parse-vendor-option;\fR
+.RS 0.25i
+.PP
+The \fBparse-vendor-option\fR statement attempts to parse a vendor
+option (code 43).  It is only useful while processing a packet on the server
+and requires that the administrator has already used the
+\fBvendor-option-space\fR statement to select a valid vendor space.
+.PP
+This functionality may be used if the server needs to take different
+actions depending on the values the client placed in the vendor option
+and the sub-options are not at fixed locations.  It is handled as an
+action to allow an administrator to examine the incoming options and
+choose the correct vendor space.
+.RE
 .SH REFERENCE: DYNAMIC DNS UPDATES
 .PP
 See the dhcpd.conf and dhclient.conf man pages for more information
index 3c5699dfb815ce3898b058e8e6e4a222ac73cde6..bd8505ff880f9e6f91ae20a07212b6e1bb10e0ae 100644 (file)
@@ -3,7 +3,7 @@
    Support for executable statements. */
 
 /*
- * Copyright (c) 2009,2013,2014 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009,2013-2015 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1998-2003 by Internet Software Consortium
  *
@@ -531,6 +531,14 @@ int execute_statements (result, packet, lease, client_state,
 
                        break;
 
+                     case vendor_opt_statement:
+                       /* If possible parse any options in a vendor option
+                        * encapsulation, this may add options to the in_options
+                        * option state */
+                       parse_vendor_option(packet, lease, client_state,
+                                           in_options, out_options, scope);
+                       break;
+
                      default:
                        log_error ("bogus statement type %d", r -> op);
                        break;
@@ -1000,6 +1008,11 @@ void write_statements (file, statements, indent)
 #endif /* ENABLE_EXECUTE */
                         break;
                        
+                     case vendor_opt_statement:
+                       indent_spaces (file, indent);
+                       fprintf (file, "parse-vendor-option;");
+                       break;
+
                      default:
                        log_fatal ("bogus statement type %d\n", r -> op);
                }
@@ -1161,7 +1174,8 @@ int executable_statement_foreach (struct executable_statement *stmt,
                break;
              case log_statement:
              case return_statement:
-              case execute_statement:
+             case execute_statement:
+             case vendor_opt_statement:
                break;
            }
        }
index faeb3efbccdc383ae289ce7a35b1d7f817d54f1a..74f1fb54e3b812be24096d7833fe1b7d6f02e78c 100644 (file)
@@ -3,7 +3,7 @@
    DHCP options parsing and reassembly. */
 
 /*
- * Copyright (c) 2004-2012,2014 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2012,2014-2015 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1995-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -4285,3 +4285,96 @@ int validate_packet(struct packet *packet)
 
        return (1);
 }
+/*!
+ *
+ * \brief Parse a vendor option (option 43)
+ *
+ * After the server has parsed most of the options and presented the result
+ * to the user the user can set the proper vendor option space using
+ * vendor-option-space in the config file and then cause this routine to be
+ * called via parse-vendor-option in the config file.  This routine will
+ * then try and find the proper universe for the vendor-option-space and
+ * parse the vendor option string based on that universe.
+ *
+ * If the information isn't available (no vendor space, no universe for the
+ * vendor space, no vendor option in the options) or the decode fails we
+ * simply ignore the option and continue processing.
+ *
+ * \param packet      - structure to hold information about the packet being
+ *                      processed
+ * \param lease       - lease structure
+ * \param client_state
+ * \param in_options  - The incoming options, we expect to find the
+ *                      vendor-option (option 43, containing the string
+ *                      to parse) there.  We shall attach decoded options
+ *                      there.
+ * \param out_options - The options we have added as we process the packet.
+ *                      We expect to find the vendor-option-space there and
+ *                      use that to find the name of the vendor universe to use
+ * \param scope
+ *
+ * \return - void as there isn't much we can do about failures.
+ */
+void parse_vendor_option(packet, lease, client_state, in_options,
+                        out_options, scope)
+       struct packet *packet;
+       struct lease *lease;
+       struct client_state *client_state;
+       struct option_state *in_options;
+       struct option_state *out_options;
+       struct binding_scope **scope;
+{
+       struct option_cache *oc = NULL;
+       struct data_string name;
+       struct option *option = NULL;
+       unsigned int code = DHO_VENDOR_ENCAPSULATED_OPTIONS;
+
+       /* check if we are processing a packet, if not we can return */
+       if ((packet == NULL) || (in_options == NULL) || (out_options == NULL))
+               return;
+
+       /* Do we have any vendor option spaces? */
+       if (vendor_cfg_option == NULL)
+               return;
+
+       /* See if the admin has set a vendor option space name */
+       oc = lookup_option(vendor_cfg_option->universe,
+                          out_options, vendor_cfg_option->code);
+       if (oc == NULL)
+               return;
+
+       memset(&name, 0, sizeof(name));
+       evaluate_option_cache(&name, packet, lease, client_state,
+                             in_options, out_options, scope, oc, MDL);
+
+       /* No name, all done */
+       if (name.len == 0)
+               return;
+
+       /* Get any vendor option information from the request */
+       oc = lookup_option(&dhcp_universe, in_options, code);
+
+       /* No vendor option, all done */
+       if ((oc == NULL) || (oc->data.len == 0)) {
+               data_string_forget(&name, MDL);
+               return;
+       }
+
+       /* Get the proper option to pass to the parse routine */
+       option_code_hash_lookup(&option, dhcp_universe.code_hash,
+                               &code, 0, MDL);
+
+       /* Now that we have the data from the vendor option and a vendor
+        * option space try to parse things.  On success the parsed options
+        * will be added to the in_options list for future use.  A return
+        * return of 1 indicates success, but not much we can do on error */
+       (void) parse_encapsulated_suboptions(in_options, option,
+                                            oc->data.data, oc->data.len,
+                                            &dhcp_universe,
+                                            (const char *)name.data);
+
+       /* Lastly clean up any left overs */
+       data_string_forget(&name, MDL);
+       option_dereference(&option, MDL);
+       return;
+}
index 94395cb6647f80e6b46db865c7eaea79a53dfa3d..22e7d58210f2ae280be2634948bda686ecffca68 100644 (file)
@@ -2640,6 +2640,22 @@ int parse_executable_statement (result, cfile, lose, case_context)
                }
                break;
 
+             case PARSE_VENDOR_OPT:
+               /* The parse-vendor-option; The statement has no arguments.
+                * We simply set up the statement and when it gets executed it
+                * will find all information it needs in the packet and options.
+                */
+               skip_token(&val, NULL, cfile);
+               if (!parse_semi(cfile)) {
+                       *lose = 1;
+                       return (0);
+               }
+
+               if (!executable_statement_allocate(result, MDL))
+                       log_fatal("no memory for execute statement.");
+               (*result)->op = vendor_opt_statement;
+               break;
+
                /* Not really a statement, but we parse it here anyway
                   because it's appropriate for all DHCP agents with
                   parsers. */
index 378459b9d5fb5f0a0e3bb27e77b002349cbdce55..916e18eb37b0e2e1816171c6da4d563a5ac9c5ac 100644 (file)
@@ -2016,6 +2016,13 @@ int add_option(struct option_state *options,
               void *data,
               unsigned int data_len);
 
+void parse_vendor_option(struct packet *packet,
+                        struct lease *lease,
+                        struct client_state *client_state,
+                        struct option_state *in_options,
+                        struct option_state *out_options,
+                        struct binding_scope **scope);
+
 /* dhcpd.c */
 extern struct timeval cur_tv;
 #define cur_time cur_tv.tv_sec
index 0915a111fa9e932f6da2c248f57a64950358d1eb..c4b77a7c3a70a2bab073a9c9e158ff85796ea5fd 100644 (file)
@@ -3,7 +3,7 @@
    Tokens for config file lexer and parser. */
 
 /*
- * Copyright (c) 2011-2014 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2011-2015 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 2004,2007-2009 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
@@ -367,7 +367,8 @@ enum dhcp_token {
        TOKEN_INFINIBAND = 668,
        POOL6 = 669,
        V6RELAY = 670,
-       V6RELOPT = 671
+       V6RELOPT = 671,
+       PARSE_VENDOR_OPT = 672
 };
 
 #define is_identifier(x)       ((x) >= FIRST_TOKEN &&  \
index 3acdd79c55614d1edb63ed9c1b3aa08a45e238c9..0660b407bb56f9e563ee4536e5f7c288260e9ee6 100644 (file)
@@ -3,7 +3,8 @@
    Definitions for executable statements... */
 
 /*
- * Copyright (c) 2004,2007,2009,2014 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2014-2015 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
  * Copyright (c) 1996-2003 by Internet Software Consortium
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -51,7 +52,8 @@ struct executable_statement {
                define_statement,
                log_statement,
                return_statement,
-               execute_statement
+               execute_statement,
+               vendor_opt_statement
        } op;
        union {
                struct {