diff options
author | Shawn Routhier <sar@isc.org> | 2015-07-13 12:06:50 -0700 |
---|---|---|
committer | Shawn Routhier <sar@isc.org> | 2015-07-13 12:06:50 -0700 |
commit | 45c332f037bf54134df5335ba9c888aea0c24d4d (patch) | |
tree | 6e71fbf81a321dd3be279d233b33f5f7fd9a2095 /common | |
parent | 3496e9bc0e899e6120b8d4a2a7258fb30b4cf1f1 (diff) | |
download | isc-dhcp-45c332f037bf54134df5335ba9c888aea0c24d4d.tar.gz |
[master] Add code to parse a vendor option as directed by the user.
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.
Diffstat (limited to 'common')
-rw-r--r-- | common/conflex.c | 4 | ||||
-rw-r--r-- | common/dhcp-eval.5 | 17 | ||||
-rw-r--r-- | common/execute.c | 18 | ||||
-rw-r--r-- | common/options.c | 95 | ||||
-rw-r--r-- | common/parse.c | 16 |
5 files changed, 145 insertions, 5 deletions
diff --git a/common/conflex.c b/common/conflex.c index 093ac036..39110160 100644 --- a/common/conflex.c +++ b/common/conflex.c @@ -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")) diff --git a/common/dhcp-eval.5 b/common/dhcp-eval.5 index 1ba2e449..7dd52613 100644 --- a/common/dhcp-eval.5 +++ b/common/dhcp-eval.5 @@ -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 diff --git a/common/execute.c b/common/execute.c index 3c5699df..bd8505ff 100644 --- a/common/execute.c +++ b/common/execute.c @@ -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; } } diff --git a/common/options.c b/common/options.c index faeb3efb..74f1fb54 100644 --- a/common/options.c +++ b/common/options.c @@ -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; +} diff --git a/common/parse.c b/common/parse.c index 94395cb6..22e7d582 100644 --- a/common/parse.c +++ b/common/parse.c @@ -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. */ |