summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorShawn Routhier <sar@isc.org>2015-07-13 12:06:50 -0700
committerShawn Routhier <sar@isc.org>2015-07-13 12:06:50 -0700
commit45c332f037bf54134df5335ba9c888aea0c24d4d (patch)
tree6e71fbf81a321dd3be279d233b33f5f7fd9a2095 /common
parent3496e9bc0e899e6120b8d4a2a7258fb30b4cf1f1 (diff)
downloadisc-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.c4
-rw-r--r--common/dhcp-eval.517
-rw-r--r--common/execute.c18
-rw-r--r--common/options.c95
-rw-r--r--common/parse.c16
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. */