2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-03 15:56:00 +00:00

[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.
This commit is contained in:
Shawn Routhier
2015-07-13 12:06:50 -07:00
parent 3496e9bc0e
commit 45c332f037
9 changed files with 164 additions and 9 deletions

View File

@@ -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

View 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"))

View 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

View 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);
}
@@ -1162,6 +1175,7 @@ int executable_statement_foreach (struct executable_statement *stmt,
case log_statement:
case return_statement:
case execute_statement:
case vendor_opt_statement:
break;
}
}

View 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;
}

View 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. */

View 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

View 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 && \

View 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 {