]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
Added explicit parser support for zero-length DHCP options, such as
authorEvan Hunt <each@isc.org>
Wed, 23 Jan 2008 19:19:22 +0000 (19:19 +0000)
committerEvan Hunt <each@isc.org>
Wed, 23 Jan 2008 19:19:22 +0000 (19:19 +0000)
rapid-commit, via format code 'Z' [rt17355]

RELNOTES
common/conflex.c
common/options.c
common/parse.c
common/tables.c
includes/dhctoken.h

index 20547e665a5407531260ba5dfaad0e97a8bfbffd..432ed4e0a0381762c913681a08f926262fb64608 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -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.
 
index 5ac39d8dfa5202992abe32bced0e47e53389f81d..27568d289ce3e032f09659ad81fae65679ca143f 100644 (file)
@@ -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;
index cb46b11fd9d119be4067e31e9bfdf3d440342289..dc8f86abdaedfeb4bacd57f457502c34216a2695 100644 (file)
@@ -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));
index f6bfa131621afe1fa0f1286bfff8dc09939e3b0a..585a3578a8b451ecdfe75d631d13cc5ca1d69ef7 100644 (file)
@@ -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);
index 9259332d3c0b07b51520f667ced4f264e7ffb973..279728358e009a1637e0bb31d86fc695f16ff64d 100644 (file)
@@ -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 */
 
index 568d41123b35c210f5f4aea54337467a2ab9cb4c..2a8fb3f13327231be899c4e042d5d0e854ce07fc 100644 (file)
@@ -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 &&  \