From: Evan Hunt Date: Wed, 27 Jun 2007 18:25:15 +0000 (+0000) Subject: Fixed a bug parsing ipv6 addresses in host-identifier statements. [rt16860] X-Git-Tag: v4_0_0a2~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b55d0d5f5381dd439091465690fd94fd664391f6;p=thirdparty%2Fdhcp.git Fixed a bug parsing ipv6 addresses in host-identifier statements. [rt16860] --- diff --git a/RELNOTES b/RELNOTES index d018275f2..57e691595 100644 --- a/RELNOTES +++ b/RELNOTES @@ -85,6 +85,8 @@ suggested fixes to . - All binaries (client, server, relay) now change directories to / before going into daemon mode, so as not to hold $CWD open +- Fixed a bug parsing DHCPv6 client-id's in host-identifier statements + Changes since 4.0.0-20070413 - Old (expired) leases are now cleaned. diff --git a/common/parse.c b/common/parse.c index 59297492c..f418bb358 100644 --- a/common/parse.c +++ b/common/parse.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: parse.c,v 1.128 2007/06/20 10:38:55 shane Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n"; +"$Id: parse.c,v 1.129 2007/06/27 18:25:15 each Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -3351,7 +3351,6 @@ int parse_non_binary (expr, cfile, lose, context) enum expr_op opcode; const char *s; char *cptr; - struct executable_statement *stmt; int i; unsigned long u; isc_result_t status, code; @@ -4823,62 +4822,24 @@ int parse_expression (expr, cfile, lose, context, plhs, binop) goto new_rhs; } -/* option-statement :== identifier DOT identifier SEMI - | identifier SEMI - Option syntax is handled specially through format strings, so it - would be painful to come up with BNF for it. However, it always - starts as above and ends in a SEMI. */ - -int parse_option_statement (result, cfile, lookups, option, op) - struct executable_statement **result; - struct parse *cfile; - int lookups; - struct option *option; - enum statement_op op; +int parse_option_data (expr, cfile, lookups, option) +struct expression **expr; +struct parse *cfile; +int lookups; +struct option *option; { const char *val; - enum dhcp_token token; const char *fmt = NULL; - struct expression *expr = (struct expression *)0; struct expression *tmp; - int lose; - struct executable_statement *stmt; - int ftt = 1; - - token = peek_token (&val, (unsigned *)0, cfile); - if (token == SEMI) { - /* Eat the semicolon... */ - token = next_token (&val, (unsigned *)0, cfile); - goto done; - } - - if (token == EQUAL) { - /* Eat the equals sign. */ - token = next_token (&val, (unsigned *)0, cfile); - - /* Parse a data expression and use its value for the data. */ - if (!parse_data_expression (&expr, cfile, &lose)) { - /* In this context, we must have an executable - statement, so if we found something else, it's - still an error. */ - if (!lose) { - parse_warn (cfile, - "expecting a data expression."); - skip_to_semi (cfile); - } - return 0; - } - - /* We got a valid expression, so use it. */ - goto done; - } + enum dhcp_token token; - /* Parse the option data... */ do { - /* Set a flag if this is an array of a simple type (i.e., - not an array of pairs of IP addresses, or something - like that. */ + /* + * Set a flag if this is an array of a simple type (i.e., + * not an array of pairs of IP addresses, or something like + * that. + */ int uniform = option -> format [1] == 'A'; and_again: @@ -4898,20 +4859,21 @@ int parse_option_statement (result, cfile, lookups, option, op) break; if (*fmt == 'o') continue; - tmp = expr; - expr = (struct expression *)0; - if (!parse_option_token (&expr, cfile, &fmt, - tmp, uniform, lookups)) { + + tmp = *expr; + *expr = NULL; + if (!parse_option_token(expr, cfile, &fmt, tmp, + uniform, lookups)) { if (fmt [1] != 'o') { if (tmp) expression_dereference (&tmp, MDL); return 0; } - expr = tmp; - tmp = (struct expression *)0; + *expr = tmp; + tmp = NULL; } - if (tmp) + if (tmp) expression_dereference (&tmp, MDL); } if ((*fmt == 'A') || (*fmt == 'a')) { @@ -4934,17 +4896,75 @@ int parse_option_statement (result, cfile, lookups, option, op) } } while ((*fmt == 'A') || (*fmt == 'a')); + return 1; +} + +/* option-statement :== identifier DOT identifier SEMI + | identifier SEMI + + Option syntax is handled specially through format strings, so it + would be painful to come up with BNF for it. However, it always + starts as above and ends in a SEMI. */ + +int parse_option_statement (result, cfile, lookups, option, op) + struct executable_statement **result; + struct parse *cfile; + int lookups; + struct option *option; + enum statement_op op; +{ + const char *val; + enum dhcp_token token; + struct expression *expr = (struct expression *)0; + int lose; + int ftt = 1; + + token = peek_token (&val, (unsigned *)0, cfile); + if (token == SEMI) { + /* Eat the semicolon... */ + token = next_token (&val, (unsigned *)0, cfile); + goto done; + } + + if (token == EQUAL) { + /* Eat the equals sign. */ + token = next_token (&val, (unsigned *)0, cfile); + + /* Parse a data expression and use its value for the data. */ + if (!parse_data_expression (&expr, cfile, &lose)) { + /* In this context, we must have an executable + statement, so if we found something else, it's + still an error. */ + if (!lose) { + parse_warn (cfile, + "expecting a data expression."); + skip_to_semi (cfile); + } + return 0; + } + + /* We got a valid expression, so use it. */ + goto done; + } + + /* Parse the option data... */ + if (! parse_option_data(&expr, cfile, lookups, option)) + return 0; + done: if (!parse_semi (cfile)) return 0; if (!executable_statement_allocate (result, MDL)) log_fatal ("no memory for option statement."); - (*result) -> op = op; - if (expr && !option_cache (&(*result) -> data.option, - (struct data_string *)0, expr, option, MDL)) + + (*result)->op = op; + if (expr && !option_cache (&(*result)->data.option, + NULL, expr, option, MDL)) log_fatal ("no memory for option cache"); + if (expr) expression_dereference (&expr, MDL); + return 1; } @@ -5010,11 +5030,12 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups) (const unsigned char *)val, len, 1, 1, MDL)) log_fatal ("No memory for \"%s\"", val); - } else if ((*fmt) [1] != 'o') { - parse_warn (cfile, "expecting string %s.", - "or hexadecimal data"); - skip_to_semi (cfile); } else { + if ((*fmt) [1] != 'o') { + parse_warn (cfile, "expecting string " + "or hexadecimal data."); + skip_to_semi (cfile); + } return 0; } } diff --git a/server/confpars.c b/server/confpars.c index 383619202..90eb546ce 100644 --- a/server/confpars.c +++ b/server/confpars.c @@ -34,7 +34,7 @@ #ifndef lint static char copyright[] = -"$Id: confpars.c,v 1.168 2007/06/19 17:06:03 shane Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n"; +"$Id: confpars.c,v 1.169 2007/06/27 18:25:15 each Exp $ Copyright (c) 2004-2007 Internet Systems Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -1733,8 +1733,7 @@ void parse_host_declaration (cfile, group) isc_result_t status; int known; struct option *option; - struct expression *expr; - const char *tmp_format; + struct expression *expr = NULL; name = parse_host_name (cfile); if (!name) { @@ -1867,6 +1866,7 @@ void parse_host_declaration (cfile, group) break; continue; } + if (token == HOST_IDENTIFIER) { if (host->host_id_option != NULL) { parse_warn(cfile, @@ -1897,33 +1897,12 @@ void parse_host_declaration (cfile, group) break; } - /* XXX: we're always using "lookups" */ - expr = NULL; - tmp_format = option->format; - /* - * XXX: using parse_option_token() is not ideal here, - * as it does not handle things like arrays and - * such. - */ - if (!parse_option_token(&expr, cfile, &tmp_format, - NULL, 1, 1)) { - skip_to_rbrace(cfile, 1); - option_dereference(&option, MDL); - break; - } - - /* I think this is guaranteed, but a check - won't hurt. -Shane */ - if (expr->op != expr_const_data) { - parse_warn(cfile, - "options for host-identifier " - "must have a constant value"); - skip_to_rbrace(cfile, 1); - expression_dereference(&expr, MDL); - option_dereference(&option, MDL); - break; - } - + if (! parse_option_data(&expr, cfile, 1, option)) { + skip_to_rbrace(cfile, 1); + option_dereference(&option, MDL); + break; + } + if (!parse_semi(cfile)) { skip_to_rbrace(cfile, 1); expression_dereference(&expr, MDL); @@ -1939,9 +1918,8 @@ void parse_host_declaration (cfile, group) continue; } - declaration = parse_statement (cfile, host -> group, - HOST_DECL, host, - declaration); + declaration = parse_statement(cfile, host->group, HOST_DECL, + host, declaration); } while (1); if (deleted) {