summaryrefslogtreecommitdiff
path: root/client/clparse.c
diff options
context:
space:
mode:
authorDavid Hankins <dhankins@isc.org>2007-08-23 16:06:09 +0000
committerDavid Hankins <dhankins@isc.org>2007-08-23 16:06:09 +0000
commit0c20eab3c8234f983d1f8af2818e21c3dc6e0013 (patch)
tree97b39dc9b2d3838eb25687a70359a121be19114f /client/clparse.c
parentc6785bb5e1575facc492ffa702417742e3d2b966 (diff)
downloadisc-dhcp-0c20eab3c8234f983d1f8af2818e21c3dc6e0013.tar.gz
- 'request' and 'also request' syntaxes have been added to accomodate
the DHCPv6 client configuration. 'send dhcp6.oro' is no longer necessary. [ISC-Bugs #17023]
Diffstat (limited to 'client/clparse.c')
-rw-r--r--client/clparse.c174
1 files changed, 144 insertions, 30 deletions
diff --git a/client/clparse.c b/client/clparse.c
index ab4839e7..e1c97bd6 100644
--- a/client/clparse.c
+++ b/client/clparse.c
@@ -37,16 +37,8 @@
struct client_config top_level_config;
-u_int32_t default_requested_options [] = {
- DHO_SUBNET_MASK,
- DHO_BROADCAST_ADDRESS,
- DHO_TIME_OFFSET,
- DHO_ROUTERS,
- DHO_DOMAIN_NAME,
- DHO_DOMAIN_NAME_SERVERS,
- DHO_HOST_NAME,
- 0
-};
+#define NUM_DEFAULT_REQUESTED_OPTS 9
+struct option *default_requested_options[NUM_DEFAULT_REQUESTED_OPTS + 1];
static void parse_client_default_duid(struct parse *cfile);
static void parse_client6_lease_statement(struct parse *cfile);
@@ -65,6 +57,62 @@ isc_result_t read_client_conf ()
struct client_config *config;
struct interface_info *ip;
isc_result_t status;
+ unsigned code;
+
+ /* Initialize the default request list. */
+ memset(default_requested_options, 0, sizeof(default_requested_options));
+
+ /* 1 */
+ code = DHO_SUBNET_MASK;
+ option_code_hash_lookup(&default_requested_options[0],
+ dhcp_universe.code_hash, &code, 0, MDL);
+
+ /* 2 */
+ code = DHO_BROADCAST_ADDRESS;
+ option_code_hash_lookup(&default_requested_options[1],
+ dhcp_universe.code_hash, &code, 0, MDL);
+
+ /* 3 */
+ code = DHO_TIME_OFFSET;
+ option_code_hash_lookup(&default_requested_options[2],
+ dhcp_universe.code_hash, &code, 0, MDL);
+
+ /* 4 */
+ code = DHO_ROUTERS;
+ option_code_hash_lookup(&default_requested_options[3],
+ dhcp_universe.code_hash, &code, 0, MDL);
+
+ /* 5 */
+ code = DHO_DOMAIN_NAME;
+ option_code_hash_lookup(&default_requested_options[4],
+ dhcp_universe.code_hash, &code, 0, MDL);
+
+ /* 6 */
+ code = DHO_DOMAIN_NAME_SERVERS;
+ option_code_hash_lookup(&default_requested_options[5],
+ dhcp_universe.code_hash, &code, 0, MDL);
+
+ /* 7 */
+ code = DHO_HOST_NAME;
+ option_code_hash_lookup(&default_requested_options[6],
+ dhcp_universe.code_hash, &code, 0, MDL);
+
+ /* 8 */
+ code = D6O_NAME_SERVERS;
+ option_code_hash_lookup(&default_requested_options[7],
+ dhcpv6_universe.code_hash, &code, 0, MDL);
+
+ /* 9 */
+ code = D6O_DOMAIN_SEARCH;
+ option_code_hash_lookup(&default_requested_options[8],
+ dhcpv6_universe.code_hash, &code, 0, MDL);
+
+ for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) {
+ if (default_requested_options[code] == NULL)
+ log_fatal("Unable to find option definition for "
+ "index %u during default parameter request "
+ "assembly.", code);
+ }
/* Initialize the top level client configuration. */
memset (&top_level_config, 0, sizeof top_level_config);
@@ -231,6 +279,8 @@ void read_client_leases ()
PREPEND option-decl |
APPEND option-decl |
hardware-declaration |
+ ALSO REQUEST option-list |
+ ALSO REQUIRE option-list |
REQUEST option-list |
REQUIRE option-list |
TIMEOUT number |
@@ -259,6 +309,8 @@ void parse_client_statement (cfile, ip, config)
int known;
int tmp, i;
isc_result_t status;
+ int listlen;
+ struct option ***append_list, **new_list, **cat_list;
switch (peek_token (&val, (unsigned *)0, cfile)) {
case INCLUDE:
@@ -297,6 +349,73 @@ void parse_client_statement (cfile, ip, config)
parse_key (cfile);
return;
+ case TOKEN_ALSO:
+ /* consume ALSO */
+ next_token(&val, NULL, cfile);
+
+ /* consume type of ALSO list. */
+ token = next_token(&val, NULL, cfile);
+
+ if (token == REQUEST) {
+ append_list = &config->requested_options;
+ } else if (token == REQUIRE) {
+ append_list = &config->required_options;
+ } else {
+ parse_warn(cfile, "expected REQUEST or REQUIRE list");
+ skip_to_semi(cfile);
+ return;
+ }
+
+ /* If there is no list, cut the concat short. */
+ if (*append_list == NULL) {
+ parse_option_list(cfile, append_list);
+ return;
+ }
+
+ /* Count the length of the existing list. */
+ for (i = 0 ; (*append_list)[i] != NULL ; i++)
+ ; /* This space intentionally left blank. */
+
+ /* If there's no codes on the list, cut the concat short. */
+ if (i == 0) {
+ parse_option_list(cfile, append_list);
+ return;
+ }
+
+ tmp = parse_option_list(cfile, &new_list);
+
+ if (tmp == 0 || new_list == NULL)
+ return;
+
+ /* Allocate 'i + tmp' buckets plus a terminator. */
+ cat_list = dmalloc(sizeof(struct option *) * (i + tmp + 1),
+ MDL);
+
+ if (cat_list == NULL) {
+ log_error("Unable to allocate memory for new "
+ "request list.");
+ skip_to_semi(cfile);
+ return;
+ }
+
+ for (i = 0 ; (*append_list)[i] != NULL ; i++)
+ option_reference(&cat_list[i], (*append_list)[i], MDL);
+
+ tmp = i;
+
+ for (i = 0 ; new_list[i] != 0 ; i++)
+ option_reference(&cat_list[tmp++], new_list[i], MDL);
+
+ cat_list[tmp] = 0;
+
+ /* XXX: We cannot free the old list, because it may have been
+ * XXX: assigned from an outer configuration scope (or may be
+ * XXX: the static default setting).
+ */
+ *append_list = cat_list;
+
+ return;
+
/* REQUIRE can either start a policy statement or a
comma-separated list of names of required options. */
case REQUIRE:
@@ -415,7 +534,7 @@ void parse_client_statement (cfile, ip, config)
case REQUEST:
token = next_token (&val, (unsigned *)0, cfile);
if (config -> requested_options == default_requested_options)
- config -> requested_options = (u_int32_t *)0;
+ config -> requested_options = NULL;
parse_option_list (cfile, &config -> requested_options);
return;
@@ -612,9 +731,8 @@ void parse_client_statement (cfile, ip, config)
/* option-list :== option_name |
option_list COMMA option_name */
-void parse_option_list (cfile, list)
- struct parse *cfile;
- u_int32_t **list;
+int
+parse_option_list(struct parse *cfile, struct option ***list)
{
int ix;
int token;
@@ -634,25 +752,18 @@ void parse_option_list (cfile, list)
parse_warn (cfile, "%s: expected option name.", val);
token = next_token (&val, (unsigned *)0, cfile);
skip_to_semi (cfile);
- return;
+ return 0;
}
status = parse_option_name(cfile, 0, NULL, &option);
if (status != ISC_R_SUCCESS || option == NULL) {
parse_warn (cfile, "%s: expected option name.", val);
- return;
- }
- if (option -> universe != &dhcp_universe) {
- parse_warn (cfile,
- "%s.%s: Only global options allowed.",
- option -> universe -> name, option->name );
- skip_to_semi (cfile);
- option_dereference(&option, MDL);
- return;
+ return 0;
}
r = new_pair (MDL);
if (!r)
log_fatal ("can't allocate pair for option code.");
- r -> car = (caddr_t)(long)option -> code;
+ /* XXX: we should probably carry a reference across this */
+ r->car = (caddr_t)option;
option_dereference(&option, MDL);
r -> cdr = (pair)0;
if (p)
@@ -666,20 +777,21 @@ void parse_option_list (cfile, list)
if (token != SEMI) {
parse_warn (cfile, "expecting semicolon.");
skip_to_semi (cfile);
- return;
+ return 0;
}
/* XXX we can't free the list here, because we may have copied
XXX it from an outer config state. */
- *list = (u_int32_t *)0;
+ *list = NULL;
if (ix) {
- *list = dmalloc ((ix + 1) * sizeof **list, MDL);
+ *list = dmalloc ((ix + 1) * sizeof(struct option *), MDL);
if (!*list)
log_error ("no memory for option list.");
else {
ix = 0;
for (q = p; q; q = q -> cdr)
- (*list) [ix++] = (u_int32_t)(long)q -> car;
- (*list) [ix] = 0;
+ option_reference(&(*list)[ix++],
+ (struct option *)q->car, MDL);
+ (*list)[ix] = NULL;
}
while (p) {
q = p -> cdr;
@@ -687,6 +799,8 @@ void parse_option_list (cfile, list)
p = q;
}
}
+
+ return ix;
}
/* interface-declaration :==