2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-03 15:56:00 +00:00

Add support for function calls and typed variables.

This commit is contained in:
Ted Lemon
2000-02-05 18:07:17 +00:00
parent f28971d813
commit 08514fb895
2 changed files with 134 additions and 127 deletions

View File

@@ -22,7 +22,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: execute.c,v 1.28 2000/02/02 20:01:41 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; "$Id: execute.c,v 1.29 2000/02/05 18:07:17 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -132,51 +132,10 @@ int execute_statements (packet, lease, in_options, out_options, scope,
break; break;
case eval_statement: case eval_statement:
if (is_boolean_expression (r -> data.eval)) { status = evaluate_expression
status = (evaluate_boolean_expression ((struct binding_value **)0,
(&result, packet, lease, in_options, packet, lease, in_options,
out_options, scope, out_options, scope, r -> data.eval);
r -> data.eval));
} else if (is_numeric_expression (r -> data.eval)) {
status = (evaluate_numeric_expression
(&num, packet, lease, in_options,
out_options, scope,
r -> data.eval));
} else if (is_data_expression (r -> data.eval)) {
memset (&ds, 0, sizeof ds);
status = (evaluate_data_expression
(&ds, packet, lease, in_options,
out_options, scope,
r -> data.eval));
if (status && ds.data)
data_string_forget (&ds, MDL);
} else if (is_dns_expression (r -> data.eval)) {
#if defined (NSUPDATE)
ns_updrec *nut;
nut = 0;
status = (evaluate_dns_expression
(&nut, packet, lease, in_options,
out_options, scope,
r -> data.eval));
if (status) {
if (nut -> r_data) {
dfree (nut -> r_data, MDL);
nut -> r_data =
(unsigned char *)0;
}
if (nut -> r_dname) {
dfree (nut -> r_dname, MDL);
nut -> r_dname = (char *)0;
}
minires_freeupdrec (nut);
}
#endif
} else {
log_error ("%s: invalid expression type: %d",
"execute_statements",
r -> data.eval -> op);
}
#if defined (DEBUG_EXPRESSIONS) #if defined (DEBUG_EXPRESSIONS)
log_debug ("exec: evaluate: %s", log_debug ("exec: evaluate: %s",
(status "succeeded" : "failed")); (status "succeeded" : "failed"));
@@ -235,11 +194,6 @@ int execute_statements (packet, lease, in_options, out_options, scope,
break; break;
case set_statement: case set_statement:
memset (&ds, 0, sizeof ds);
status = (evaluate_data_expression
(&ds, packet, lease, in_options, out_options,
scope, r -> data.set.expr));
binding = find_binding (scope, r -> data.set.name); binding = find_binding (scope, r -> data.set.name);
if (!binding && status) { if (!binding && status) {
binding = dmalloc (sizeof *binding, MDL); binding = dmalloc (sizeof *binding, MDL);
@@ -268,47 +222,39 @@ int execute_statements (packet, lease, in_options, out_options, scope,
} }
} }
if (binding) { if (binding) {
if (binding -> value.data) if (binding -> value)
data_string_forget (&binding -> value, binding_value_dereference
MDL); (&binding -> value, MDL);
if (status) status = (evaluate_expression
data_string_copy (&binding -> value, &ds, (&binding -> value, packet, lease,
MDL); in_options, out_options,
scope, r -> data.set.expr));
} }
if (status)
data_string_forget (&ds, MDL);
#if defined (DEBUG_EXPRESSIONS) #if defined (DEBUG_EXPRESSIONS)
log_debug ("exec: set %s = %s", r -> data.set.name, log_debug ("exec: set %s%s", r -> data.set.name,
(status && binding (binding && status ? "" : " (failed)"));
? print_hex_1 (binding -> value.len,
binding -> value.data, 50)
: "NULL"));
#endif #endif
break; break;
case unset_statement: case unset_statement:
binding = find_binding (scope, r -> data.unset); binding = find_binding (scope, r -> data.unset);
if (binding) { if (binding) {
if (binding -> value.data) if (binding -> value)
data_string_forget (&binding -> value, binding_value_dereference
MDL); (&binding -> value, MDL);
status = 1; status = 1;
} else } else
status = 0; status = 0;
#if defined (DEBUG_EXPRESSIONS) #if defined (DEBUG_EXPRESSIONS)
log_debug ("exec: unset %s: %s", r -> data.unset, log_debug ("exec: unset %s: %s", r -> data.unset,
(status ? "found" : "NULL")); (status ? "found" : "not found"));
#endif #endif
break; break;
case let_statement: case let_statement:
memset (&ds, 0, sizeof ds);
status = (evaluate_data_expression
(&ds, packet, lease, in_options, out_options,
scope, r -> data.let.expr));
ns = (struct binding_scope *)0; ns = (struct binding_scope *)0;
binding_scope_allocate (&ns, MDL); binding_scope_allocate (&ns, MDL);
e = r;
next_let: next_let:
if (ns) { if (ns) {
@@ -319,11 +265,11 @@ int execute_statements (packet, lease, in_options, out_options, scope,
} else { } else {
binding -> name = binding -> name =
dmalloc (strlen dmalloc (strlen
(r -> data.let.name + 1), (e -> data.let.name + 1),
MDL); MDL);
if (binding -> name) if (binding -> name)
strcpy (binding -> name, strcpy (binding -> name,
r -> data.let.name); e -> data.let.name);
else { else {
dfree (binding, MDL); dfree (binding, MDL);
binding = (struct binding *)0; binding = (struct binding *)0;
@@ -331,31 +277,29 @@ int execute_statements (packet, lease, in_options, out_options, scope,
} }
} }
} }
if (ns && binding && status) { if (ns && binding) {
data_string_copy (&binding -> value, &ds, MDL); status = (evaluate_expression
(&binding -> value, packet, lease,
in_options, out_options,
scope, e -> data.set.expr));
binding -> next = ns -> bindings; binding -> next = ns -> bindings;
ns -> bindings = binding; ns -> bindings = binding;
} }
if (status)
data_string_forget (&ds, MDL);
#if defined (DEBUG_EXPRESSIONS) #if defined (DEBUG_EXPRESSIONS)
log_debug ("exec: let %s = %s", r -> data.let.name, log_debug ("exec: let %s%s", e -> data.let.name,
(status && binding (binding && status ? "" : "failed"));
? print_hex_1 (binding -> value.len,
binding -> value.data, 50)
: "NULL"));
#endif #endif
if (!r -> data.let.statements) { if (!e -> data.let.statements) {
} else if (r -> data.let.statements -> op == } else if (e -> data.let.statements -> op ==
let_statement) { let_statement) {
r = r -> data.let.statements; e = e -> data.let.statements;
goto next_let; goto next_let;
} else if (ns) { } else if (ns) {
ns -> outer = scope; ns -> outer = scope;
execute_statements execute_statements
(packet, lease, in_options, out_options, (packet, lease, in_options, out_options,
ns, r -> data.let.statements); ns, e -> data.let.statements);
} }
if (ns) if (ns)
binding_scope_dereference (&ns, MDL); binding_scope_dereference (&ns, MDL);

View File

@@ -22,7 +22,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: parse.c,v 1.62 2000/02/02 17:10:38 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; "$Id: parse.c,v 1.63 2000/02/05 18:04:47 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -1810,7 +1810,9 @@ int parse_boolean_expression (expr, cfile, lose)
(struct expression **)0, expr_none)) (struct expression **)0, expr_none))
return 0; return 0;
if (!is_boolean_expression (*expr)) { if (!is_boolean_expression (*expr) &&
(*expr) -> op != expr_variable_reference &&
(*expr) -> op != expr_funcall) {
parse_warn (cfile, "Expecting a boolean expression."); parse_warn (cfile, "Expecting a boolean expression.");
*lose = 1; *lose = 1;
expression_dereference (expr, MDL); expression_dereference (expr, MDL);
@@ -1845,7 +1847,9 @@ int parse_data_expression (expr, cfile, lose)
(struct expression **)0, expr_none)) (struct expression **)0, expr_none))
return 0; return 0;
if (!is_data_expression (*expr)) { if (!is_data_expression (*expr) &&
(*expr) -> op != expr_variable_reference &&
(*expr) -> op != expr_funcall) {
parse_warn (cfile, "Expecting a data expression."); parse_warn (cfile, "Expecting a data expression.");
*lose = 1; *lose = 1;
return 0; return 0;
@@ -1869,7 +1873,9 @@ int parse_numeric_expression (expr, cfile, lose)
(struct expression **)0, expr_none)) (struct expression **)0, expr_none))
return 0; return 0;
if (!is_numeric_expression (*expr)) { if (!is_numeric_expression (*expr) &&
(*expr) -> op != expr_variable_reference &&
(*expr) -> op != expr_funcall) {
parse_warn (cfile, "Expecting a numeric expression."); parse_warn (cfile, "Expecting a numeric expression.");
*lose = 1; *lose = 1;
return 0; return 0;
@@ -1901,7 +1907,9 @@ int parse_dns_expression (expr, cfile, lose)
(struct expression **)0, expr_none)) (struct expression **)0, expr_none))
return 0; return 0;
if (!is_dns_expression (*expr)) { if (!is_dns_expression (*expr) &&
(*expr) -> op != expr_variable_reference &&
(*expr) -> op != expr_funcall) {
parse_warn (cfile, "Expecting a dns update subexpression."); parse_warn (cfile, "Expecting a dns update subexpression.");
*lose = 1; *lose = 1;
return 0; return 0;
@@ -1921,12 +1929,14 @@ int parse_non_binary (expr, cfile, lose, context)
const char *val; const char *val;
struct collection *col; struct collection *col;
struct option *option; struct option *option;
struct expression *nexp; struct expression *nexp, **ep;
int known; int known;
enum expr_op opcode; enum expr_op opcode;
const char *s; const char *s;
char *cptr;
struct executable_statement *stmt; struct executable_statement *stmt;
int i; int i;
unsigned long u;
token = peek_token (&val, cfile); token = peek_token (&val, cfile);
@@ -2274,41 +2284,48 @@ int parse_non_binary (expr, cfile, lose, context)
} }
if (!strcasecmp (val, "a")) if (!strcasecmp (val, "a"))
i = T_A; u = T_A;
else if (!strcasecmp (val, "ptr")) else if (!strcasecmp (val, "ptr"))
i = T_PTR; u = T_PTR;
else if (!strcasecmp (val, "mx")) else if (!strcasecmp (val, "mx"))
i = T_MX; u = T_MX;
else if (!strcasecmp (val, "cname")) else if (!strcasecmp (val, "cname"))
i = T_CNAME; u = T_CNAME;
else if (!strcasecmp (val, "TXT")) else if (!strcasecmp (val, "TXT"))
i = T_TXT; u = T_TXT;
else { else {
parse_warn (cfile, "unexpected rrtype: %s", val); parse_warn (cfile, "unexpected rrtype: %s", val);
goto badnsupdate; goto badnsupdate;
} }
s = (opcode == expr_ns_add
? "old-dns-update"
: "old-dns-delete");
cptr = dmalloc (strlen (s) + 1, MDL);
if (!cptr)
log_fatal ("can't allocate name for %s", s);
strcpy (cptr, s);
if (!expression_allocate (expr, MDL)) if (!expression_allocate (expr, MDL))
log_fatal ("can't allocate expression"); log_fatal ("can't allocate expression");
#if 0
(*expr) -> op = expr_funcall; (*expr) -> op = expr_funcall;
(*expr) -> data.funcall.context = context_boolean; (*expr) -> data.funcall.name = cptr;
(*expr) -> data.funcall.name =
if (!make_let (&(*expr) -> data.funcall.statements, "rrtype")) /* Fake up a function call. */
log_fatal ("can't allocate rrtype let."); ep = &(*expr) -> data.funcall.arglist;
stmt = (*expr) -> data.funcall.statements; if (!expression_allocate (ep, MDL))
if (!make_const_int (stmt -> data.let.value, i)) log_fatal ("can't allocate expression");
(*ep) -> op = expr_arg;
if (!make_const_int (&(*ep) -> data.arg.val, u))
log_fatal ("can't allocate rrtype value."); log_fatal ("can't allocate rrtype value.");
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (token != COMMA) if (token != COMMA)
goto nocomma; goto nocomma;
ep = &((*ep) -> data.arg.next);
if (!make_let (&stmt -> data.let.statements, "rrname")) if (!expression_allocate (ep, MDL))
log_fatal ("can't allocate rrname let."); log_fatal ("can't allocate expression");
stmt = stmt -> data.let.statements; (*ep) -> op = expr_arg;
if (!(parse_data_expression (&stmt -> data.let.expr, if (!(parse_data_expression (&(*ep) -> data.arg.val,
cfile, lose))) cfile, lose)))
goto nodata; goto nodata;
@@ -2316,10 +2333,11 @@ int parse_non_binary (expr, cfile, lose, context)
if (token != COMMA) if (token != COMMA)
goto nocomma; goto nocomma;
if (!make_let (&stmt -> data.let.statements, "rrdata")) ep = &((*ep) -> data.arg.next);
log_fatal ("can't allocate rrname let."); if (!expression_allocate (ep, MDL))
stmt = stmt -> data.let.statements; log_fatal ("can't allocate expression");
if (!(parse_data_expression (&stmt -> data.let.expr, (*ep) -> op = expr_arg;
if (!(parse_data_expression (&(*ep) -> data.arg.val,
cfile, lose))) cfile, lose)))
goto nodata; goto nodata;
@@ -2328,18 +2346,18 @@ int parse_non_binary (expr, cfile, lose, context)
if (token != COMMA) if (token != COMMA)
goto nocomma; goto nocomma;
if (!make_let (&stmt -> data.let.statements, "ttl")) ep = &((*ep) -> data.arg.next);
log_fatal ("can't allocate rrname let."); if (!expression_allocate (ep, MDL))
stmt = stmt -> data.let.statements; log_fatal ("can't allocate expression");
(*ep) -> op = expr_arg;
if (!(parse_numeric_expression if (!(parse_numeric_expression (&(*ep) -> data.arg.val,
(&stmt -> data.let.expr, cfile, lose))) { cfile, lose))) {
parse_warn (cfile, parse_warn (cfile,
"expecting numeric expression."); "expecting numeric expression.");
goto badnsupdate; goto badnsupdate;
} }
} }
#endif
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (token != RPAREN) if (token != RPAREN)
goto norparen; goto norparen;
@@ -2885,14 +2903,59 @@ int parse_non_binary (expr, cfile, lose, context)
if (token != NAME && token != NUMBER_OR_NAME) if (token != NAME && token != NUMBER_OR_NAME)
return 0; return 0;
token = next_token (&val, cfile);
/* Save the name of the variable being referenced. */
cptr = dmalloc (strlen (val) + 1, MDL);
if (!cptr)
log_fatal ("can't allocate variable name");
strcpy (cptr, val);
/* Simple variable reference, as far as we can tell. */
token = peek_token (&val, cfile);
if (token != LPAREN) {
if (!expression_allocate (expr, MDL))
log_fatal ("can't allocate expression");
(*expr) -> op = expr_variable_reference;
(*expr) -> data.variable = cptr;
break;
}
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (!expression_allocate (expr, MDL)) if (!expression_allocate (expr, MDL))
log_fatal ("can't allocate expression"); log_fatal ("can't allocate expression");
(*expr) -> op = expr_variable_reference; (*expr) -> op = expr_funcall;
(*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL); (*expr) -> data.funcall.name = cptr;
if (!(*expr)->data.variable)
log_fatal ("can't allocate variable name"); /* Now parse the argument list. */
strcpy ((*expr) -> data.variable, val); ep = &(*expr) -> data.funcall.arglist;
do {
if (!expression_allocate (ep, MDL))
log_fatal ("can't allocate expression");
(*ep) -> op = expr_arg;
if (!parse_expression (&(*ep) -> data.arg.val,
cfile, lose, context_any,
(struct expression **)0,
expr_none)) {
if (!*lose) {
parse_warn (cfile,
"expecting expression.");
*lose = 1;
}
skip_to_semi (cfile);
expression_dereference (expr, MDL);
return 0;
}
ep = &((*ep) -> data.arg.next);
token = next_token (&val, cfile);
} while (token == COMMA);
if (token != RPAREN) {
parse_warn (cfile, "Right parenthesis expected.");
skip_to_semi (cfile);
*lose = 1;
expression_dereference (expr, MDL);
return 0;
}
break; break;
} }
return 1; return 1;