mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-09-03 07:45:20 +00:00
- Add support for user-defined encapsulations.
- 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.
This commit is contained in:
159
common/parse.c
159
common/parse.c
@@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
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 */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@@ -893,11 +893,10 @@ void parse_option_space_decl (cfile)
|
|||||||
nu -> lookup_func = lookup_hashed_option;
|
nu -> lookup_func = lookup_hashed_option;
|
||||||
nu -> option_state_dereference =
|
nu -> option_state_dereference =
|
||||||
hashed_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 -> save_func = save_hashed_option;
|
||||||
nu -> delete_func = delete_hashed_option;
|
nu -> delete_func = delete_hashed_option;
|
||||||
nu -> encapsulate = hashed_option_space_encapsulate;
|
nu -> encapsulate = hashed_option_space_encapsulate;
|
||||||
|
nu -> decode = parse_option_buffer;
|
||||||
nu -> length_size = 1;
|
nu -> length_size = 1;
|
||||||
nu -> tag_size = 1;
|
nu -> tag_size = 1;
|
||||||
nu -> store_tag = putUChar;
|
nu -> store_tag = putUChar;
|
||||||
@@ -950,7 +949,8 @@ void parse_option_space_decl (cfile)
|
|||||||
UNSIGNED INTEGER NUMBER |
|
UNSIGNED INTEGER NUMBER |
|
||||||
IP-ADDRESS |
|
IP-ADDRESS |
|
||||||
TEXT |
|
TEXT |
|
||||||
STRING */
|
STRING |
|
||||||
|
ENCAPSULATE identifier */
|
||||||
|
|
||||||
int parse_option_code_definition (cfile, option)
|
int parse_option_code_definition (cfile, option)
|
||||||
struct parse *cfile;
|
struct parse *cfile;
|
||||||
@@ -967,6 +967,7 @@ int parse_option_code_definition (cfile, option)
|
|||||||
int code;
|
int code;
|
||||||
int is_signed;
|
int is_signed;
|
||||||
char *s;
|
char *s;
|
||||||
|
int has_encapsulation = 0;
|
||||||
|
|
||||||
/* Parse the option code. */
|
/* Parse the option code. */
|
||||||
token = next_token (&val, cfile);
|
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. */
|
/* At this point we're expecting a data type. */
|
||||||
next_type:
|
next_type:
|
||||||
|
if (has_encapsulation) {
|
||||||
|
parse_warn (cfile,
|
||||||
|
"encapsulate must always be the last item.");
|
||||||
|
skip_to_semi (cfile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case ARRAY:
|
case ARRAY:
|
||||||
if (arrayp) {
|
if (arrayp) {
|
||||||
@@ -1098,6 +1106,23 @@ int parse_option_code_definition (cfile, option)
|
|||||||
type = 'X';
|
type = 'X';
|
||||||
goto no_arrays;
|
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:
|
default:
|
||||||
parse_warn (cfile, "unknown data type %s", val);
|
parse_warn (cfile, "unknown data type %s", val);
|
||||||
skip_to_rbrace (cfile, recordp);
|
skip_to_rbrace (cfile, recordp);
|
||||||
@@ -1107,6 +1132,7 @@ int parse_option_code_definition (cfile, option)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tokix == sizeof tokbuf) {
|
if (tokix == sizeof tokbuf) {
|
||||||
|
toobig:
|
||||||
parse_warn (cfile, "too many types in record.");
|
parse_warn (cfile, "too many types in record.");
|
||||||
skip_to_rbrace (cfile, recordp);
|
skip_to_rbrace (cfile, recordp);
|
||||||
if (recordp)
|
if (recordp)
|
||||||
@@ -1156,10 +1182,22 @@ int parse_option_code_definition (cfile, option)
|
|||||||
skip_to_semi (cfile);
|
skip_to_semi (cfile);
|
||||||
return 0;
|
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)
|
if (!s)
|
||||||
log_fatal ("no memory for option format.");
|
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)
|
if (arrayp)
|
||||||
s [tokix++] = (arrayp > recordp) ? 'a' : 'A';
|
s [tokix++] = (arrayp > recordp) ? 'a' : 'A';
|
||||||
s [tokix] = 0;
|
s [tokix] = 0;
|
||||||
@@ -2739,9 +2777,12 @@ int parse_non_binary (expr, cfile, lose, context)
|
|||||||
cfile, lose)) {
|
cfile, lose)) {
|
||||||
nodata:
|
nodata:
|
||||||
expression_dereference (expr, MDL);
|
expression_dereference (expr, MDL);
|
||||||
parse_warn (cfile, "expecting data expression.");
|
if (!*lose) {
|
||||||
skip_to_semi (cfile);
|
parse_warn (cfile,
|
||||||
*lose = 1;
|
"expecting data expression.");
|
||||||
|
skip_to_semi (cfile);
|
||||||
|
*lose = 1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3220,9 +3261,10 @@ int parse_non_binary (expr, cfile, lose, context)
|
|||||||
if (!(parse_numeric_expression
|
if (!(parse_numeric_expression
|
||||||
(&(*expr) -> data.ns_add.ttl, cfile,
|
(&(*expr) -> data.ns_add.ttl, cfile,
|
||||||
lose))) {
|
lose))) {
|
||||||
|
if (!*lose)
|
||||||
parse_warn (cfile,
|
parse_warn (cfile,
|
||||||
"expecting data expression.");
|
"expecting numeric expression.");
|
||||||
goto badnsupdate;
|
goto badnsupdate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3382,9 +3424,12 @@ int parse_non_binary (expr, cfile, lose, context)
|
|||||||
|
|
||||||
if (!parse_data_expression (&(*expr) -> data.extract_int,
|
if (!parse_data_expression (&(*expr) -> data.extract_int,
|
||||||
cfile, lose)) {
|
cfile, lose)) {
|
||||||
parse_warn (cfile, "expecting data expression.");
|
if (!*lose) {
|
||||||
skip_to_semi (cfile);
|
parse_warn (cfile,
|
||||||
*lose = 1;
|
"expecting data expression.");
|
||||||
|
skip_to_semi (cfile);
|
||||||
|
*lose = 1;
|
||||||
|
}
|
||||||
expression_dereference (expr, MDL);
|
expression_dereference (expr, MDL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -3678,15 +3723,15 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
|
|||||||
enum dhcp_token token;
|
enum dhcp_token token;
|
||||||
const char *val;
|
const char *val;
|
||||||
struct expression *rhs = (struct expression *)0, *tmp;
|
struct expression *rhs = (struct expression *)0, *tmp;
|
||||||
struct expression *lhs;
|
struct expression *lhs = (struct expression *)0;
|
||||||
enum expr_op next_op;
|
enum expr_op next_op;
|
||||||
|
enum expression_context lhs_context, rhs_context;
|
||||||
|
|
||||||
/* Consume the left hand side we were passed. */
|
/* Consume the left hand side we were passed. */
|
||||||
if (plhs) {
|
if (plhs) {
|
||||||
lhs = *plhs;
|
expression_reference (&lhs, *plhs, MDL);
|
||||||
*plhs = (struct expression *)0;
|
expression_dereference (plhs, MDL);
|
||||||
} else
|
}
|
||||||
lhs = (struct expression *)0;
|
|
||||||
|
|
||||||
new_rhs:
|
new_rhs:
|
||||||
if (!parse_non_binary (&rhs, cfile, lose, context)) {
|
if (!parse_non_binary (&rhs, cfile, lose, context)) {
|
||||||
@@ -3723,50 +3768,62 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
next_op = expr_not_equal;
|
next_op = expr_not_equal;
|
||||||
|
lhs_context = rhs_context = context_any;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EQUAL:
|
case EQUAL:
|
||||||
next_op = expr_equal;
|
next_op = expr_equal;
|
||||||
|
lhs_context = rhs_context = context_any;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AND:
|
case AND:
|
||||||
next_op = expr_and;
|
next_op = expr_and;
|
||||||
|
lhs_context = rhs_context = context_boolean;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OR:
|
case OR:
|
||||||
next_op = expr_or;
|
next_op = expr_or;
|
||||||
|
lhs_context = rhs_context = context_boolean;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PLUS:
|
case PLUS:
|
||||||
next_op = expr_add;
|
next_op = expr_add;
|
||||||
|
lhs_context = rhs_context = context_numeric;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MINUS:
|
case MINUS:
|
||||||
next_op = expr_subtract;
|
next_op = expr_subtract;
|
||||||
|
lhs_context = rhs_context = context_numeric;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SLASH:
|
case SLASH:
|
||||||
next_op = expr_divide;
|
next_op = expr_divide;
|
||||||
|
lhs_context = rhs_context = context_numeric;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASTERISK:
|
case ASTERISK:
|
||||||
next_op = expr_multiply;
|
next_op = expr_multiply;
|
||||||
|
lhs_context = rhs_context = context_numeric;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PERCENT:
|
case PERCENT:
|
||||||
next_op = expr_remainder;
|
next_op = expr_remainder;
|
||||||
|
lhs_context = rhs_context = context_numeric;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AMPERSAND:
|
case AMPERSAND:
|
||||||
next_op = expr_binary_and;
|
next_op = expr_binary_and;
|
||||||
|
lhs_context = rhs_context = context_numeric;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PIPE:
|
case PIPE:
|
||||||
next_op = expr_binary_or;
|
next_op = expr_binary_or;
|
||||||
|
lhs_context = rhs_context = context_numeric;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CARET:
|
case CARET:
|
||||||
next_op = expr_binary_xor;
|
next_op = expr_binary_xor;
|
||||||
|
lhs_context = rhs_context = context_numeric;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -3828,6 +3885,62 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
|
|||||||
next_op = expr_none;
|
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. */
|
/* Now combine the LHS and the RHS using binop. */
|
||||||
tmp = (struct expression *)0;
|
tmp = (struct expression *)0;
|
||||||
if (!expression_allocate (&tmp, MDL))
|
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);
|
log_fatal ("No memory for %s", val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
fmt = strchr (fmt, '.');
|
||||||
|
if (!fmt) {
|
||||||
|
parse_warn (cfile,
|
||||||
|
"malformed encapsulation format (bug!)");
|
||||||
|
skip_to_semi (cfile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
case 'X':
|
case 'X':
|
||||||
token = peek_token (&val, cfile);
|
token = peek_token (&val, cfile);
|
||||||
if (token == NUMBER_OR_NAME || token == NUMBER) {
|
if (token == NUMBER_OR_NAME || token == NUMBER) {
|
||||||
|
Reference in New Issue
Block a user