]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
- Add support for user-defined encapsulations.
authorTed Lemon <source@isc.org>
Tue, 10 Oct 2000 22:45:25 +0000 (22:45 +0000)
committerTed Lemon <source@isc.org>
Tue, 10 Oct 2000 22:45:25 +0000 (22:45 +0000)
- Add code to detect impossible or unlikely tests and flag them with
  warnings, but don't enable this code until after the 3.0 release.
  For example, it would flag a warning on this code:

if (substring (foo, 0, 3) = 01:02:03:04) { ...

  because this comparison can never succeed.

common/parse.c

index c3ad345f54fc1e2cca332c820e226c69d8c59ef9..1689d3e62150cbf1ff47b9d1cbd8ca4a01aa5958 100644 (file)
@@ -43,7 +43,7 @@
 
 #ifndef lint
 static char copyright[] =
-"$Id: parse.c,v 1.88 2000/10/04 18:47:41 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
+"$Id: parse.c,v 1.89 2000/10/10 22:45:25 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium.  All rights reserved.\n";
 #endif /* not lint */
 
 #include "dhcpd.h"
@@ -893,11 +893,10 @@ void parse_option_space_decl (cfile)
        nu -> lookup_func = lookup_hashed_option;
        nu -> option_state_dereference =
                hashed_option_state_dereference;
-       nu -> get_func = hashed_option_get;
-       nu -> set_func = hashed_option_set;
        nu -> save_func = save_hashed_option;
        nu -> delete_func = delete_hashed_option;
        nu -> encapsulate = hashed_option_space_encapsulate;
+       nu -> decode = parse_option_buffer;
        nu -> length_size = 1;
        nu -> tag_size = 1;
        nu -> store_tag = putUChar;
@@ -950,7 +949,8 @@ void parse_option_space_decl (cfile)
                        UNSIGNED INTEGER NUMBER |
                        IP-ADDRESS |
                        TEXT |
-                       STRING */
+                       STRING |
+                       ENCAPSULATE identifier */
 
 int parse_option_code_definition (cfile, option)
        struct parse *cfile;
@@ -967,6 +967,7 @@ int parse_option_code_definition (cfile, option)
        int code;
        int is_signed;
        char *s;
+       int has_encapsulation = 0;
        
        /* Parse the option code. */
        token = next_token (&val, cfile);
@@ -1004,6 +1005,13 @@ int parse_option_code_definition (cfile, option)
 
        /* At this point we're expecting a data type. */
       next_type:
+       if (has_encapsulation) {
+               parse_warn (cfile,
+                           "encapsulate must always be the last item.");
+               skip_to_semi (cfile);
+               return 0;
+       }
+
        switch (token) {
              case ARRAY:
                if (arrayp) {
@@ -1098,6 +1106,23 @@ int parse_option_code_definition (cfile, option)
                type = 'X';
                goto no_arrays;
 
+             case ENCAPSULATE:
+               token = next_token (&val, cfile);
+               if (!is_identifier (token)) {
+                       parse_warn (cfile,
+                                   "expecting option space identifier");
+                       skip_to_semi (cfile);
+                       return 0;
+               }
+               if (strlen (val) + tokix + 2 > sizeof (tokbuf))
+                       goto toobig;
+               tokbuf [tokix++] = 'E';
+               strcpy (&tokbuf [tokix], val);
+               tokix += strlen (val);
+               type = '.';
+               has_encapsulation = 1;
+               break;
+
              default:
                parse_warn (cfile, "unknown data type %s", val);
                skip_to_rbrace (cfile, recordp);
@@ -1107,6 +1132,7 @@ int parse_option_code_definition (cfile, option)
        }
 
        if (tokix == sizeof tokbuf) {
+             toobig:
                parse_warn (cfile, "too many types in record.");
                skip_to_rbrace (cfile, recordp);
                if (recordp)
@@ -1156,10 +1182,22 @@ int parse_option_code_definition (cfile, option)
                        skip_to_semi (cfile);
                return 0;
        }
-       s = dmalloc (tokix + ((arrayp) ? 1 : 0) + 1, MDL);
+       if (has_encapsulation && arrayp) {
+               parse_warn (cfile,
+                           "Arrays of encapsulations don't make sense.");
+               return 0;
+       }
+       if (has_encapsulation && tokbuf [0] == 'E')
+               has_encapsulation = 0;
+       s = dmalloc (tokix +
+                    (arrayp ? 1 : 0) +
+                    (has_encapsulation ? 1 : 0) + 1, MDL);
        if (!s)
                log_fatal ("no memory for option format.");
-       memcpy (s, tokbuf, tokix);
+       if (has_encapsulation)
+               s [0] = 'e';
+       memcpy (s + has_encapsulation, tokbuf, tokix);
+       tokix += has_encapsulation;
        if (arrayp)
                s [tokix++] = (arrayp > recordp) ? 'a' : 'A';
        s [tokix] = 0;
@@ -2739,9 +2777,12 @@ int parse_non_binary (expr, cfile, lose, context)
                                            cfile, lose)) {
                      nodata:
                        expression_dereference (expr, MDL);
-                       parse_warn (cfile, "expecting data expression.");
-                       skip_to_semi (cfile);
-                       *lose = 1;
+                       if (!*lose) {
+                               parse_warn (cfile,
+                                           "expecting data expression.");
+                               skip_to_semi (cfile);
+                               *lose = 1;
+                       }
                        return 0;
                }
 
@@ -3220,9 +3261,10 @@ int parse_non_binary (expr, cfile, lose, context)
                        if (!(parse_numeric_expression
                              (&(*expr) -> data.ns_add.ttl, cfile,
                               lose))) {
+                           if (!*lose)
                                parse_warn (cfile,
-                                           "expecting data expression.");
-                               goto badnsupdate;
+                                           "expecting numeric expression.");
+                           goto badnsupdate;
                        }
                }
 
@@ -3382,9 +3424,12 @@ int parse_non_binary (expr, cfile, lose, context)
 
                if (!parse_data_expression (&(*expr) -> data.extract_int,
                                            cfile, lose)) {
-                       parse_warn (cfile, "expecting data expression.");
-                       skip_to_semi (cfile);
-                       *lose = 1;
+                       if (!*lose) {
+                               parse_warn (cfile,
+                                           "expecting data expression.");
+                               skip_to_semi (cfile);
+                               *lose = 1;
+                       }
                        expression_dereference (expr, MDL);
                        return 0;
                }
@@ -3678,15 +3723,15 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
        enum dhcp_token token;
        const char *val;
        struct expression *rhs = (struct expression *)0, *tmp;
-       struct expression *lhs;
+       struct expression *lhs = (struct expression *)0;
        enum expr_op next_op;
+       enum expression_context lhs_context, rhs_context;
 
        /* Consume the left hand side we were passed. */
        if (plhs) {
-               lhs = *plhs;
-               *plhs = (struct expression *)0;
-       } else
-               lhs = (struct expression *)0;
+               expression_reference (&lhs, *plhs, MDL);
+               expression_dereference (plhs, MDL);
+       }
 
       new_rhs:
        if (!parse_non_binary (&rhs, cfile, lose, context)) {
@@ -3723,50 +3768,62 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
                        return 0;
                }
                next_op = expr_not_equal;
+               lhs_context = rhs_context = context_any;
                break;
 
              case EQUAL:
                next_op = expr_equal;
+               lhs_context = rhs_context = context_any;
                break;
 
              case AND:
                next_op = expr_and;
+               lhs_context = rhs_context = context_boolean;
                break;
 
              case OR:
                next_op = expr_or;
+               lhs_context = rhs_context = context_boolean;
                break;
 
              case PLUS:
                next_op = expr_add;
+               lhs_context = rhs_context = context_numeric;
                break;
 
              case MINUS:
                next_op = expr_subtract;
+               lhs_context = rhs_context = context_numeric;
                break;
 
              case SLASH:
                next_op = expr_divide;
+               lhs_context = rhs_context = context_numeric;
                break;
 
              case ASTERISK:
                next_op = expr_multiply;
+               lhs_context = rhs_context = context_numeric;
                break;
 
              case PERCENT:
                next_op = expr_remainder;
+               lhs_context = rhs_context = context_numeric;
                break;
 
              case AMPERSAND:
                next_op = expr_binary_and;
+               lhs_context = rhs_context = context_numeric;
                break;
 
              case PIPE:
                next_op = expr_binary_or;
+               lhs_context = rhs_context = context_numeric;
                break;
 
              case CARET:
                next_op = expr_binary_xor;
+               lhs_context = rhs_context = context_numeric;
                break;
 
              default:
@@ -3828,6 +3885,62 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
                next_op = expr_none;
        }
 
+#if defined (NOTYET)           /* Post 3.0 final */
+       /* Make sure rhs and lhs can be combined using binop. */
+       if (!expr_valid_for_context (lhs, lhs_context)) {
+               if (!*lose) {
+                       parse_warn (cfile,
+                                   "lhs type is not valid for operator.");
+                       *lose = 1;
+               }
+       }
+       if (!expr_valid_for_context (rhs, rhs_context) || *lose) {
+               if (!*lose) {
+                       parse_warn (cfile,
+                                   "lhs type is not valid for operator.");
+                       *lose = 1;
+               }
+               return 0;
+       }
+
+       /* Do a little nosing about in comparisons. */
+       if (binop == expr_equal || binop == expr_not_equal) {
+               int lrhs, llhs, crhs, clhs;
+
+               /* If the subexpressions have lengths that are computable
+                  at parse time, see if they're the same, and barf if they
+                  aren't. */
+               clhs = data_subexpression_length (&llhs, lhs);
+               crhs = data_subexpression_length (&lrhs, rhs);
+               if (clhs == 2 || crhs == 2) {
+                       if (clhs == crhs &&
+                           (llhs != lrhs ||
+                            (clhs == 2 && llhs > lrhs) ||
+                            (crhs == 2 && lrhs > llhs))) {
+                               parse_warn (cfile,
+                                           "comparison will always be %s",
+                                           (binop == expr_equal ?
+                                            "true" : "false"));
+                       } else if (llhs != lrhs) {
+                               log_error ("warning: %s will normally be %d%s",
+                                          (clhs == 1
+                                           ? "left-hand side"
+                                           : "right-hand side"),
+                                          (clhs == 1 ? llhs : lrhs),
+                                          " bytes");
+                               log_error ("...and %s will always be %d%s",
+                                          (clhs == 1
+                                           ? "right-hand side"
+                                           : "left-hand side"),
+                                          (clhs == 1 ? lrhs : llhs),
+                                          " bytes");
+                               log_error ("so this may not work the way%s",
+                                          " you intended");
+                       }
+               }
+       }
+#endif /* NOTYET */
+
        /* Now combine the LHS and the RHS using binop. */
        tmp = (struct expression *)0;
        if (!expression_allocate (&tmp, MDL))
@@ -4010,6 +4123,14 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
                        log_fatal ("No memory for %s", val);
                break;
 
+             case 'E':
+               fmt = strchr (fmt, '.');
+               if (!fmt) {
+                       parse_warn (cfile,
+                                   "malformed encapsulation format (bug!)");
+                       skip_to_semi (cfile);
+                       return 0;
+               }
              case 'X':
                token = peek_token (&val, cfile);
                if (token == NUMBER_OR_NAME || token == NUMBER) {