diff options
author | Evan Hunt <each@isc.org> | 2008-01-23 19:19:22 +0000 |
---|---|---|
committer | Evan Hunt <each@isc.org> | 2008-01-23 19:19:22 +0000 |
commit | 4cafb815437c88938502ad45393a2be70f448511 (patch) | |
tree | da8ef6656190863aad1c9945a45d6fefb61264e9 | |
parent | 771484ac0449ca6c0e3b4263c69f84dc1b5b00f2 (diff) | |
download | isc-dhcp-4cafb815437c88938502ad45393a2be70f448511.tar.gz |
Added explicit parser support for zero-length DHCP options, such as
rapid-commit, via format code 'Z' [rt17355]
-rw-r--r-- | RELNOTES | 3 | ||||
-rw-r--r-- | common/conflex.c | 2 | ||||
-rw-r--r-- | common/options.c | 2 | ||||
-rw-r--r-- | common/parse.c | 47 | ||||
-rw-r--r-- | common/tables.c | 5 | ||||
-rw-r--r-- | includes/dhctoken.h | 3 |
6 files changed, 48 insertions, 14 deletions
@@ -55,6 +55,9 @@ suggested fixes to <dhcp-users@isc.org>. Changes since 4.0.0 +- Added explicit parser support for zero-length DHCP options, such as + rapid-commit, via format code 'Z' + - Exit with warning when DHCPv6-specific statements are used in the config file but -6 is not specified. diff --git a/common/conflex.c b/common/conflex.c index 5ac39d8d..27568d28 100644 --- a/common/conflex.c +++ b/common/conflex.c @@ -1422,6 +1422,8 @@ intern(char *atom, enum dhcp_token dfv) { return NS_YXRRSET; break; case 'z': + if (!strcasecmp (atom + 1, "erolen")) + return ZEROLEN; if (!strcasecmp (atom + 1, "one")) return ZONE; break; diff --git a/common/options.c b/common/options.c index cb46b11f..dc8f86ab 100644 --- a/common/options.c +++ b/common/options.c @@ -2660,7 +2660,7 @@ append_option(struct data_string *dst, struct universe *universe, { struct data_string tmp; - if (src->len == 0) + if (src->len == 0 && option->format[0] != 'Z') return 0; memset(&tmp, 0, sizeof(tmp)); diff --git a/common/parse.c b/common/parse.c index f6bfa131..585a3578 100644 --- a/common/parse.c +++ b/common/parse.c @@ -1666,6 +1666,18 @@ int parse_option_code_definition (cfile, option) has_encapsulation = 1; break; + case ZEROLEN: + type = 'Z'; + if (arrayp) { + parse_warn (cfile, "array incompatible with zerolen."); + skip_to_rbrace (cfile, recordp); + if (recordp) + skip_to_semi (cfile); + return 0; + } + no_more_in_record = 1; + break; + default: parse_warn (cfile, "unknown data type %s", val); skip_to_rbrace (cfile, recordp); @@ -4902,7 +4914,7 @@ struct option *option; fmt = option->format; /* 'a' means always uniform */ - if ((fmt[0] != '\0') && (tolower((int)fmt[1]) == 'a')) + if ((fmt[0] != 'Z') && (tolower((int)fmt[1]) == 'a')) uniform = 1; do { @@ -4913,8 +4925,9 @@ struct option *option; tmp = *expr; *expr = NULL; + if (!parse_option_token(expr, cfile, &fmt, tmp, - uniform, lookups)) { + uniform, lookups)) { if (fmt [1] != 'o') { if (tmp) expression_dereference (&tmp, @@ -4924,12 +4937,10 @@ struct option *option; *expr = tmp; tmp = NULL; } - if (tmp) + if (tmp) expression_dereference (&tmp, MDL); - if (*fmt != '\0') - fmt++; - + fmt++; } while (*fmt != '\0'); if ((*fmt == 'A') || (*fmt == 'a')) { @@ -4975,7 +4986,7 @@ int parse_option_statement (result, cfile, lookups, option, op) int lose; token = peek_token (&val, (unsigned *)0, cfile); - if ((token == SEMI) && (option->format[0] != '\0')) { + if ((token == SEMI) && (option->format[0] != 'Z')) { /* Eat the semicolon... */ /* * XXXSK: I'm not sure why we should ever get here, but we @@ -5261,8 +5272,13 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups) return 0; break; - case '\0': /* Zero-length option. */ - buf[0] = '\0'; + case 'Z': /* Zero-length option. */ + token = peek_token (&val, (unsigned *)0, cfile); + if (token != SEMI) { + parse_warn(cfile, "semicolon expected."); + skip_to_semi(cfile); + } + buf[0] = '\0'; if (!make_const_data(&t, /* expression */ buf, /* buffer */ 0, /* length */ @@ -5273,7 +5289,7 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups) break; default: - parse_warn (cfile, "Bad format %c in parse_option_token.", + parse_warn (cfile, "Bad format '%c' in parse_option_token.", **fmt); skip_to_semi (cfile); return 0; @@ -5511,6 +5527,17 @@ int parse_option_decl (oc, cfile) dp = buf; goto alloc; + case 'Z': /* Zero-length option */ + token = next_token(&val, (unsigned *)0, cfile); + if (token != SEMI) { + parse_warn(cfile, + "semicolon expected."); + goto parse_exit; + } + len = 0; + buf[0] = '\0'; + break; + default: log_error ("parse_option_param: Bad format %c", *fmt); diff --git a/common/tables.c b/common/tables.c index 9259332d..27972835 100644 --- a/common/tables.c +++ b/common/tables.c @@ -92,6 +92,7 @@ HASH_FUNCTIONS (option_code, const unsigned *, struct option, d - Domain name (i.e., FOO or FOO.BAR). D - Domain list (i.e., example.com eng.example.com) c - When following a 'D' atom, enables compression pointers. + Z - Zero-length option */ struct universe dhcp_universe; @@ -341,7 +342,7 @@ static struct option dhcpv6_options[] = { #endif { "unicast", "6", &dhcpv6_universe, 12, 1 }, { "status-code", "Nstatus-codes.to", &dhcpv6_universe, 13, 1 }, - { "rapid-commit", "", &dhcpv6_universe, 14, 1 }, + { "rapid-commit", "Z", &dhcpv6_universe, 14, 1 }, #if 0 /* XXX: user-class contents are of the form "StA" where the * integer describes the length of the text field. We don't have @@ -354,7 +355,7 @@ static struct option dhcpv6_options[] = { { "vendor-opts", "Evsio.", &dhcpv6_universe, 17, 1 }, { "interface-id", "X", &dhcpv6_universe, 18, 1 }, { "reconf-msg", "Ndhcpv6-messages.", &dhcpv6_universe, 19, 1 }, - { "reconf-accept", "", &dhcpv6_universe, 20, 1 }, + { "reconf-accept", "Z", &dhcpv6_universe, 20, 1 }, /* RFC3319 OPTIONS */ diff --git a/includes/dhctoken.h b/includes/dhctoken.h index 568d4112..2a8fb3f1 100644 --- a/includes/dhctoken.h +++ b/includes/dhctoken.h @@ -348,7 +348,8 @@ enum dhcp_token { RANGE6 = 651, WHITESPACE = 652, TOKEN_ALSO = 653, - AFTER = 654 + AFTER = 654, + ZEROLEN = 655 }; #define is_identifier(x) ((x) >= FIRST_TOKEN && \ |