From 0a4241e98c7b0fd2300d33b11335f973111109a5 Mon Sep 17 00:00:00 2001 From: Shawn Routhier Date: Tue, 13 Nov 2012 13:08:41 -0800 Subject: [PATCH] [v4_1_esv] The client now passes information about the options it requested from the server to the script code via environment variables. These variables are of the form requested_=1 with the option name being the same as used in the new_* and old_* variables. [ISC-Bugs #29068] --- RELNOTES | 7 +++++++ client/dhc6.c | 35 +++++++++++++++++++++++++++++++++++ client/dhclient-script.8 | 23 +++++++++++++++-------- client/dhclient.c | 31 +++++++++++++++++++++++++++++++ includes/dhcpd.h | 1 + 5 files changed, 89 insertions(+), 8 deletions(-) diff --git a/RELNOTES b/RELNOTES index 2addf170d..4c1ac86de 100644 --- a/RELNOTES +++ b/RELNOTES @@ -86,6 +86,13 @@ work on other platforms. Please report any problems and suggested fixes to currently defaults to disabled. [ISC-Bugs #25689] +- The client now passes information about the options it requested + from the server to the script code via environment variables. + These variables are of the form requested_=1 with + the option name being the same as used in the new_* and old_* + variables. + [ISC-Bugs #29068] + Changes since 4.1-ESV-R6 - Existing legacy unit-tests have been migrated to Automated Test diff --git a/client/dhc6.c b/client/dhc6.c index e9053d846..07e784ce1 100644 --- a/client/dhc6.c +++ b/client/dhc6.c @@ -109,6 +109,7 @@ static void make_client6_options(struct client_state *client, static void script_write_params6(struct client_state *client, const char *prefix, struct option_state *options); +static void script_write_requested6(struct client_state *client); static isc_boolean_t active_prefix(struct client_state *client); static int check_timing6(struct client_state *client, u_int8_t msg_type, @@ -4332,6 +4333,7 @@ start_bound(struct client_state *client) dhc6_marshall_values("old_", client, old, oldia, oldaddr); dhc6_marshall_values("new_", client, lease, ia, addr); + script_write_requested6(client); script_go(client); } @@ -4348,6 +4350,7 @@ start_bound(struct client_state *client) dhc6_marshall_values("new_", client, lease, ia, NULL); + script_write_requested6(client); script_go(client); } @@ -4364,6 +4367,7 @@ start_bound(struct client_state *client) old->bindings->addrs : NULL); dhc6_marshall_values("new_", client, lease, NULL, NULL); + script_write_requested6(client); script_go(client); } @@ -4642,6 +4646,7 @@ do_depref(void *input) script_init(client, "DEPREF6", NULL); dhc6_marshall_values("cur_", client, lease, ia, addr); + script_write_requested6(client); script_go(client); addr->flags |= DHC6_ADDR_DEPREFFED; @@ -4693,6 +4698,7 @@ do_expire(void *input) script_init(client, "EXPIRE6", NULL); dhc6_marshall_values("old_", client, lease, ia, addr); + script_write_requested6(client); script_go(client); addr->flags |= DHC6_ADDR_EXPIRED; @@ -4755,6 +4761,7 @@ unconfigure6(struct client_state *client, const char *reason) if (client->active_lease != NULL) script_write_params6(client, "old_", client->active_lease->options); + script_write_requested6(client); script_go(client); return; } @@ -4770,6 +4777,7 @@ unconfigure6(struct client_state *client, const char *reason) script_init(client, reason, NULL); dhc6_marshall_values("old_", client, client->active_lease, ia, addr); + script_write_requested6(client); script_go(client); if ((ia->ia_type == D6O_IA_NA) && @@ -4861,6 +4869,7 @@ start_informed(struct client_state *client) script_write_params6(client, "old_", client->old_lease->options); script_write_params6(client, "new_", client->active_lease->options); + script_write_requested6(client); script_go(client); go_daemon(); @@ -5087,6 +5096,32 @@ script_write_params6(struct client_state *client, const char *prefix, } } +/* + * A clone of the DHCPv4 routine. + * Write out the environment variables for the objects that the + * client requested. If the object was requested the variable will be: + * requested_=1 + * If it wasn't requested there won't be a variable. + */ +static void script_write_requested6(client) + struct client_state *client; +{ + int i; + struct option **req; + char name[256]; + req = client->config->requested_options; + + if (req == NULL) + return; + + for (i = 0 ; req[i] != NULL ; i++) { + if ((req[i]->universe == &dhcpv6_universe) && + dhcp_option_ev_name (name, sizeof(name), req[i])) { + client_envadd(client, "requested_", name, "%d", 1); + } + } +} + /* * Check if there is something not fully defined in the active lease. */ diff --git a/client/dhclient-script.8 b/client/dhclient-script.8 index 4c5a907b2..4c7b20913 100644 --- a/client/dhclient-script.8 +++ b/client/dhclient-script.8 @@ -1,5 +1,6 @@ .\" dhclient-script.8 .\" +.\" Copyright (c) 2012 by Internet Systems Consortium, Inc. ("ISC") .\" Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC") .\" Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC") .\" Copyright (c) 1996-2003 by Internet Software Consortium @@ -125,7 +126,13 @@ options acquired from the server are passed using the option name described in \fBdhcp-options\fR, except that dashes (\'-\') are replaced by underscores (\'_\') in order to make valid shell variables, and the variable names start with new_. So for example, the new subnet mask -would be passed in $new_subnet_mask. +would be passed in $new_subnet_mask. The options that the client +explicitly requested via a PRL or ORO option are passed with the same +option name as above but prepended with requested_ and with a value of 1, +or example requested_subnet_mask=1. No such variable is defined for +options not requested by the client or options that don't require a +request option, such as the ip address (*_ip_address) or expiration +time (*_expiry). .PP Before actually configuring the address, dhclient-script should somehow ARP for it and exit with a nonzero status if it receives a @@ -152,13 +159,13 @@ address not be used if it is identical to the bound IP address in this case. .SH RENEW When a binding has been renewed, the script is called as in BOUND, -except that in addition to all the variables starting with $new_, -there is another set of variables starting with $old_. Persistent -settings that may have changed need to be deleted - for example, if a -local route to the bound address is being configured, the old local -route should be deleted. If the default route has changed, the old default -route should be deleted. If the static routes have changed, the old -ones should be deleted. Otherwise, processing can be done as with +except that in addition to all the variables starting with $new_, and +$requested_ there is another set of variables starting with $old_. +Persistent settings that may have changed need to be deleted - for +example, if a local route to the bound address is being configured, +the old local route should be deleted. If the default route has changed, +the old default route should be deleted. If the static routes have changed, +the old ones should be deleted. Otherwise, processing can be done as with BOUND. .SH REBIND The DHCP client has rebound to a new DHCP server. This can be handled diff --git a/client/dhclient.c b/client/dhclient.c index 6008a7e4b..57946813d 100644 --- a/client/dhclient.c +++ b/client/dhclient.c @@ -1190,6 +1190,7 @@ void bind_lease (client) if (client -> active && client -> state != S_REBOOTING) script_write_params (client, "old_", client -> active); script_write_params (client, "new_", client -> new); + script_write_requested(client); if (client -> alias) script_write_params (client, "alias_", client -> alias); @@ -1295,6 +1296,7 @@ void state_stop (cpp) if (client->active) { script_init(client, "STOP", client->active->medium); script_write_params(client, "old_", client->active); + script_write_requested(client); if (client->alias) script_write_params(client, "alias_", client->alias); script_go(client); @@ -1769,6 +1771,7 @@ void dhcpnak (packet) */ script_init(client, "EXPIRE", NULL); script_write_params(client, "old_", client->active); + script_write_requested(client); if (client->alias) script_write_params(client, "alias_", client->alias); script_go(client); @@ -1937,6 +1940,7 @@ void state_panic (cpp) script_init (client, "TIMEOUT", client -> active -> medium); script_write_params (client, "new_", client -> active); + script_write_requested(client); if (client -> alias) script_write_params (client, "alias_", client -> alias); @@ -2075,6 +2079,7 @@ void send_request (cpp) /* Run the client script with the new parameters. */ script_init (client, "EXPIRE", (struct string_list *)0); script_write_params (client, "old_", client -> active); + script_write_requested(client); if (client -> alias) script_write_params (client, "alias_", client -> alias); @@ -3250,6 +3255,31 @@ void script_write_params (client, prefix, lease) client_envadd (client, prefix, "expiry", "%d", (int)(lease -> expiry)); } +/* + * Write out the environment variables for the objects that the + * client requested. If the object was requested the variable will be: + * requested_=1 + * If it wasn't requested there won't be a variable. + */ +void script_write_requested(client) + struct client_state *client; +{ + int i; + struct option **req; + char name[256]; + req = client->config->requested_options; + + if (req == NULL) + return; + + for (i = 0 ; req[i] != NULL ; i++) { + if ((req[i]->universe == &dhcp_universe) && + dhcp_option_ev_name(name, sizeof(name), req[i])) { + client_envadd(client, "requested_", name, "%d", 1); + } + } +} + int script_go (client) struct client_state *client; { @@ -3557,6 +3587,7 @@ void do_release(client) script_write_params (client, "alias_", client -> alias); script_write_params (client, "old_", client -> active); + script_write_requested(client); script_go (client); } diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 71fde49f6..f24c27d46 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -2527,6 +2527,7 @@ void client_option_envadd (struct option_cache *, struct packet *, struct binding_scope **, struct universe *, void *); void script_write_params (struct client_state *, const char *, struct client_lease *); +void script_write_requested (struct client_state *); int script_go (struct client_state *); void client_envadd (struct client_state *, const char *, const char *, const char *, ...) -- 2.47.3