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:
5
RELNOTES
5
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
|
||||
|
||||
|
@@ -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"))
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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. */
|
||||
|
@@ -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
|
||||
|
@@ -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 && \
|
||||
|
@@ -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 {
|
||||
|
Reference in New Issue
Block a user