mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-09-01 14:55:30 +00:00
Support variable scoping, let, unset, event ganging, eval, new malloc debug.
This commit is contained in:
315
common/execute.c
315
common/execute.c
@@ -22,23 +22,28 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
static char copyright[] =
|
||||||
"$Id: execute.c,v 1.22 2000/01/08 01:30:29 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
|
"$Id: execute.c,v 1.23 2000/01/25 01:07:00 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"
|
||||||
|
|
||||||
int execute_statements (packet, lease, in_options, out_options, statements)
|
int execute_statements (packet, lease, in_options, out_options, scope,
|
||||||
|
statements)
|
||||||
struct packet *packet;
|
struct packet *packet;
|
||||||
struct lease *lease;
|
struct lease *lease;
|
||||||
struct option_state *in_options;
|
struct option_state *in_options;
|
||||||
struct option_state *out_options;
|
struct option_state *out_options;
|
||||||
|
struct binding_scope *scope;
|
||||||
struct executable_statement *statements;
|
struct executable_statement *statements;
|
||||||
{
|
{
|
||||||
struct executable_statement *r, *e;
|
struct executable_statement *r, *e;
|
||||||
int result;
|
int result;
|
||||||
int status;
|
int status;
|
||||||
|
unsigned long num;
|
||||||
|
struct binding_scope *outer;
|
||||||
struct binding *binding;
|
struct binding *binding;
|
||||||
struct data_string ds;
|
struct data_string ds;
|
||||||
|
struct binding_scope *ns;
|
||||||
|
|
||||||
if (!statements)
|
if (!statements)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -49,8 +54,8 @@ int execute_statements (packet, lease, in_options, out_options, statements)
|
|||||||
#if defined (DEBUG_EXPRESSIONS)
|
#if defined (DEBUG_EXPRESSIONS)
|
||||||
log_debug ("exec: statements");
|
log_debug ("exec: statements");
|
||||||
#endif
|
#endif
|
||||||
status = execute_statements (packet, lease,
|
status = execute_statements (packet, lease, in_options,
|
||||||
in_options, out_options,
|
out_options, scope,
|
||||||
r -> data.statements);
|
r -> data.statements);
|
||||||
#if defined (DEBUG_EXPRESSIONS)
|
#if defined (DEBUG_EXPRESSIONS)
|
||||||
log_debug ("exec: statements returns %d", status);
|
log_debug ("exec: statements returns %d", status);
|
||||||
@@ -66,42 +71,45 @@ int execute_statements (packet, lease, in_options, out_options, statements)
|
|||||||
executable_statement_dereference
|
executable_statement_dereference
|
||||||
(&lease -> on_expiry,
|
(&lease -> on_expiry,
|
||||||
"execute_statements");
|
"execute_statements");
|
||||||
executable_statement_reference
|
if (r -> data.on.statements)
|
||||||
(&lease -> on_expiry,
|
executable_statement_reference
|
||||||
r -> data.on.statements,
|
(&lease -> on_expiry,
|
||||||
"execute_statements");
|
r -> data.on.statements,
|
||||||
|
"execute_statements");
|
||||||
}
|
}
|
||||||
if (r -> data.on.evtypes & ON_RELEASE) {
|
if (r -> data.on.evtypes & ON_RELEASE) {
|
||||||
if (lease -> on_release)
|
if (lease -> on_release)
|
||||||
executable_statement_dereference
|
executable_statement_dereference
|
||||||
(&lease -> on_release,
|
(&lease -> on_release,
|
||||||
"execute_statements");
|
"execute_statements");
|
||||||
executable_statement_reference
|
if (r -> data.on.statements)
|
||||||
(&lease -> on_release,
|
executable_statement_reference
|
||||||
r -> data.on.statements,
|
(&lease -> on_release,
|
||||||
"execute_statements");
|
r -> data.on.statements,
|
||||||
|
"execute_statements");
|
||||||
}
|
}
|
||||||
if (r -> data.on.evtypes & ON_COMMIT) {
|
if (r -> data.on.evtypes & ON_COMMIT) {
|
||||||
if (lease -> on_commit)
|
if (lease -> on_commit)
|
||||||
executable_statement_dereference
|
executable_statement_dereference
|
||||||
(&lease -> on_commit,
|
(&lease -> on_commit,
|
||||||
"execute_statements");
|
"execute_statements");
|
||||||
executable_statement_reference
|
if (r -> data.on.statements)
|
||||||
(&lease -> on_commit,
|
executable_statement_reference
|
||||||
r -> data.on.statements,
|
(&lease -> on_commit,
|
||||||
"execute_statements");
|
r -> data.on.statements,
|
||||||
|
"execute_statements");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case switch_statement:
|
case switch_statement:
|
||||||
e = find_matching_case (packet, lease,
|
e = find_matching_case (packet, lease,
|
||||||
in_options, out_options,
|
in_options, out_options, scope,
|
||||||
r -> data.s_switch.expr,
|
r -> data.s_switch.expr,
|
||||||
r -> data.s_switch.statements);
|
r -> data.s_switch.statements);
|
||||||
if (e && !execute_statements (packet, lease,
|
if (e && !execute_statements (packet, lease,
|
||||||
in_options, out_options,
|
in_options, out_options,
|
||||||
e))
|
scope, e))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* These have no effect when executed. */
|
/* These have no effect when executed. */
|
||||||
@@ -111,8 +119,8 @@ int execute_statements (packet, lease, in_options, out_options, statements)
|
|||||||
|
|
||||||
case if_statement:
|
case if_statement:
|
||||||
status = evaluate_boolean_expression
|
status = evaluate_boolean_expression
|
||||||
(&result, packet, lease,
|
(&result, packet, lease, in_options,
|
||||||
in_options, out_options, r -> data.ie.expr);
|
out_options, scope, r -> data.ie.expr);
|
||||||
|
|
||||||
#if defined (DEBUG_EXPRESSIONS)
|
#if defined (DEBUG_EXPRESSIONS)
|
||||||
log_debug ("exec: if %s", (status
|
log_debug ("exec: if %s", (status
|
||||||
@@ -123,19 +131,60 @@ int execute_statements (packet, lease, in_options, out_options, statements)
|
|||||||
if (!status)
|
if (!status)
|
||||||
result = 0;
|
result = 0;
|
||||||
if (!execute_statements
|
if (!execute_statements
|
||||||
(packet, lease, in_options, out_options,
|
(packet, lease, in_options, out_options, scope,
|
||||||
result ? r -> data.ie.true : r -> data.ie.false))
|
result ? r -> data.ie.true : r -> data.ie.false))
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eval_statement:
|
case eval_statement:
|
||||||
status = evaluate_boolean_expression
|
if (is_boolean_expression (r -> data.eval)) {
|
||||||
(&result, packet, lease,
|
status = (evaluate_boolean_expression
|
||||||
in_options, out_options, r -> data.eval);
|
(&result, packet, lease, in_options,
|
||||||
|
out_options, scope,
|
||||||
|
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, "execute_statements");
|
||||||
|
} else if (is_dns_expression (r -> data.eval)) {
|
||||||
|
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,
|
||||||
|
"execute_statements");
|
||||||
|
nut -> r_data = (char *)0;
|
||||||
|
}
|
||||||
|
if (nut -> r_dname) {
|
||||||
|
dfree (nut -> r_dname,
|
||||||
|
"execute_statements");
|
||||||
|
nut -> r_dname = (char *)0;
|
||||||
|
}
|
||||||
|
res_freeupdrec (nut);
|
||||||
|
}
|
||||||
|
} 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
|
(status "succeeded" : "failed"));
|
||||||
? (result ? "true" : "false") : "NULL"));
|
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -191,26 +240,12 @@ int execute_statements (packet, lease, in_options, out_options, statements)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case set_statement:
|
case set_statement:
|
||||||
if (!lease) {
|
|
||||||
#if defined (DEBUG_EXPRESSIONS)
|
|
||||||
log_debug ("exec: set %s = NULL",
|
|
||||||
r -> data.set.name);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset (&ds, 0, sizeof ds);
|
memset (&ds, 0, sizeof ds);
|
||||||
status = (evaluate_data_expression
|
status = (evaluate_data_expression
|
||||||
(&ds, packet, lease, in_options, out_options,
|
(&ds, packet, lease, in_options, out_options,
|
||||||
r -> data.set.expr));
|
scope, r -> data.set.expr));
|
||||||
|
|
||||||
for (binding = lease -> bindings;
|
binding = find_binding (scope, r -> data.set.name);
|
||||||
binding; binding = binding -> next) {
|
|
||||||
if (!(strcasecmp
|
|
||||||
(lease -> bindings -> name,
|
|
||||||
r -> data.set.name)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!binding && status) {
|
if (!binding && status) {
|
||||||
binding = dmalloc (sizeof *binding,
|
binding = dmalloc (sizeof *binding,
|
||||||
"execute_statements");
|
"execute_statements");
|
||||||
@@ -219,36 +254,124 @@ int execute_statements (packet, lease, in_options, out_options, statements)
|
|||||||
dmalloc (strlen
|
dmalloc (strlen
|
||||||
(r -> data.set.name + 1),
|
(r -> data.set.name + 1),
|
||||||
"execute_statements");
|
"execute_statements");
|
||||||
if (binding -> name)
|
if (binding -> name) {
|
||||||
strcpy (binding -> name,
|
strcpy (binding -> name,
|
||||||
r -> data.set.name);
|
r -> data.set.name);
|
||||||
else
|
if (lease) {
|
||||||
dfree (binding,
|
binding -> next =
|
||||||
"execute_statements");
|
lease -> scope.bindings;
|
||||||
binding -> next = lease -> bindings;
|
lease -> scope.bindings = binding;
|
||||||
lease -> bindings = binding;
|
} else {
|
||||||
} else
|
binding -> next =
|
||||||
status = 0;
|
global_scope.bindings;
|
||||||
|
global_scope.bindings = binding;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
badalloc:
|
||||||
|
dfree (binding, "execute_statements");
|
||||||
|
binding = (struct binding *)0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (binding) {
|
if (binding) {
|
||||||
data_string_forget (&binding -> value,
|
if (binding -> value.data)
|
||||||
"execute_statements");
|
data_string_forget (&binding -> value,
|
||||||
|
"execute_statements");
|
||||||
if (status)
|
if (status)
|
||||||
data_string_copy
|
data_string_copy (&binding -> value, &ds,
|
||||||
(&binding -> value, &ds,
|
"execute_statements");
|
||||||
"execute_statements");
|
|
||||||
}
|
}
|
||||||
if (status)
|
if (status)
|
||||||
data_string_forget (&ds, "execute_statements");
|
data_string_forget (&ds, "execute_statements");
|
||||||
#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
|
(status && binding
|
||||||
? print_hex_1 (binding -> value.len,
|
? print_hex_1 (binding -> value.len,
|
||||||
binding -> value.data, 50)
|
binding -> value.data, 50)
|
||||||
: "NULL"));
|
: "NULL"));
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case unset_statement:
|
||||||
|
binding = find_binding (scope, r -> data.unset);
|
||||||
|
if (binding) {
|
||||||
|
if (binding -> value.data)
|
||||||
|
data_string_forget
|
||||||
|
(&binding -> value,
|
||||||
|
"execute_statements");
|
||||||
|
status = 1;
|
||||||
|
} else
|
||||||
|
status = 0;
|
||||||
|
#if defined (DEBUG_EXPRESSIONS)
|
||||||
|
log_debug ("exec: unset %s: %s", r -> data.unset,
|
||||||
|
(status ? "found" : "NULL"));
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
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;
|
||||||
|
binding_scope_allocate (&ns, "execute_statements");
|
||||||
|
|
||||||
|
next_let:
|
||||||
|
if (ns) {
|
||||||
|
binding = dmalloc (sizeof *binding,
|
||||||
|
"execute_statements");
|
||||||
|
if (!binding) {
|
||||||
|
blb:
|
||||||
|
binding_scope_dereference
|
||||||
|
(&ns, "execute_statements");
|
||||||
|
} else {
|
||||||
|
binding -> name =
|
||||||
|
dmalloc (strlen
|
||||||
|
(r -> data.let.name + 1),
|
||||||
|
"execute_statements");
|
||||||
|
if (binding -> name)
|
||||||
|
strcpy (binding -> name,
|
||||||
|
r -> data.let.name);
|
||||||
|
else {
|
||||||
|
dfree (binding, "execute_statements");
|
||||||
|
binding = (struct binding *)0;
|
||||||
|
goto blb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ns && binding && status) {
|
||||||
|
data_string_copy (&binding -> value, &ds,
|
||||||
|
"execute_statements");
|
||||||
|
binding -> next = ns -> bindings;
|
||||||
|
ns -> bindings = binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status)
|
||||||
|
data_string_forget (&ds, "execute_statements");
|
||||||
|
#if defined (DEBUG_EXPRESSIONS)
|
||||||
|
log_debug ("exec: let %s = %s", r -> data.let.name,
|
||||||
|
(status && binding
|
||||||
|
? print_hex_1 (binding -> value.len,
|
||||||
|
binding -> value.data, 50)
|
||||||
|
: "NULL"));
|
||||||
|
#endif
|
||||||
|
if (!r -> data.let.statements) {
|
||||||
|
} else if (r -> data.let.statements -> op ==
|
||||||
|
let_statement) {
|
||||||
|
r = r -> data.let.statements;
|
||||||
|
goto next_let;
|
||||||
|
} else if (ns) {
|
||||||
|
ns -> outer = scope;
|
||||||
|
execute_statements
|
||||||
|
(packet, lease, in_options, out_options,
|
||||||
|
ns, r -> data.let.statements);
|
||||||
|
}
|
||||||
|
if (ns)
|
||||||
|
binding_scope_dereference
|
||||||
|
(&ns, "execute_statements");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_fatal ("bogus statement type %d\n", r -> op);
|
log_fatal ("bogus statement type %d\n", r -> op);
|
||||||
}
|
}
|
||||||
@@ -265,15 +388,15 @@ int execute_statements (packet, lease, in_options, out_options, statements)
|
|||||||
the most outer scope first. */
|
the most outer scope first. */
|
||||||
|
|
||||||
void execute_statements_in_scope (packet, lease, in_options, out_options,
|
void execute_statements_in_scope (packet, lease, in_options, out_options,
|
||||||
group, limiting_group)
|
scope, group, limiting_group)
|
||||||
struct packet *packet;
|
struct packet *packet;
|
||||||
struct lease *lease;
|
struct lease *lease;
|
||||||
struct option_state *in_options;
|
struct option_state *in_options;
|
||||||
struct option_state *out_options;
|
struct option_state *out_options;
|
||||||
|
struct binding_scope *scope;
|
||||||
struct group *group;
|
struct group *group;
|
||||||
struct group *limiting_group;
|
struct group *limiting_group;
|
||||||
{
|
{
|
||||||
struct group *scope;
|
|
||||||
struct group *limit;
|
struct group *limit;
|
||||||
|
|
||||||
/* If we've recursed as far as we can, return. */
|
/* If we've recursed as far as we can, return. */
|
||||||
@@ -310,10 +433,10 @@ void execute_statements_in_scope (packet, lease, in_options, out_options,
|
|||||||
|
|
||||||
if (group -> next)
|
if (group -> next)
|
||||||
execute_statements_in_scope (packet, lease,
|
execute_statements_in_scope (packet, lease,
|
||||||
in_options, out_options,
|
in_options, out_options, scope,
|
||||||
group -> next, limiting_group);
|
group -> next, limiting_group);
|
||||||
execute_statements (packet, lease,
|
execute_statements (packet, lease, in_options, out_options, scope,
|
||||||
in_options, out_options, group -> statements);
|
group -> statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dereference or free any subexpressions of a statement being freed. */
|
/* Dereference or free any subexpressions of a statement being freed. */
|
||||||
@@ -335,11 +458,24 @@ int executable_statement_dereference (ptr, name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
(*ptr) -> refcnt--;
|
(*ptr) -> refcnt--;
|
||||||
if ((*ptr) -> refcnt) {
|
rc_register (file, line, (*ptr), (*ptr) -> refcnt);
|
||||||
|
if ((*ptr) -> refcnt > 0) {
|
||||||
*ptr = (struct executable_statement *)0;
|
*ptr = (struct executable_statement *)0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((*ptr) -> refcnt < 0) {
|
||||||
|
log_error ("option_state_dereference: negative refcnt!");
|
||||||
|
#if defined (DEBUG_RC_HISTORY)
|
||||||
|
dump_rc_history ();
|
||||||
|
#endif
|
||||||
|
#if defined (POINTER_DEBUG)
|
||||||
|
abort ();
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if ((*ptr) -> next)
|
if ((*ptr) -> next)
|
||||||
executable_statement_dereference
|
executable_statement_dereference
|
||||||
(&(*ptr) -> next, name);
|
(&(*ptr) -> next, name);
|
||||||
@@ -396,6 +532,11 @@ int executable_statement_dereference (ptr, name)
|
|||||||
name);
|
name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case unset_statement:
|
||||||
|
if ((*ptr)->data.unset)
|
||||||
|
dfree ((*ptr)->data.unset, name);
|
||||||
|
break;
|
||||||
|
|
||||||
case supersede_option_statement:
|
case supersede_option_statement:
|
||||||
case default_option_statement:
|
case default_option_statement:
|
||||||
case append_option_statement:
|
case append_option_statement:
|
||||||
@@ -440,21 +581,27 @@ void write_statements (file, statements, indent)
|
|||||||
fprintf (file, "on ");
|
fprintf (file, "on ");
|
||||||
s = "";
|
s = "";
|
||||||
if (r -> data.on.evtypes & ON_EXPIRY) {
|
if (r -> data.on.evtypes & ON_EXPIRY) {
|
||||||
fprintf (file, "expiry");
|
fprintf (file, "%sexpiry", s);
|
||||||
s = "or";
|
s = " or ";
|
||||||
}
|
}
|
||||||
if (r -> data.on.evtypes & ON_COMMIT) {
|
if (r -> data.on.evtypes & ON_COMMIT) {
|
||||||
fprintf (file, "commit");
|
fprintf (file, "%scommit", s);
|
||||||
s = "or";
|
s = "or";
|
||||||
}
|
}
|
||||||
if (r -> data.on.evtypes & ON_RELEASE) {
|
if (r -> data.on.evtypes & ON_RELEASE) {
|
||||||
fprintf (file, "release");
|
fprintf (file, "%srelease", s);
|
||||||
s = "or";
|
s = "or";
|
||||||
}
|
}
|
||||||
write_statements (file, r -> data.on.statements,
|
if (r -> data.on.statements) {
|
||||||
indent + 2);
|
fprintf (file, " {");
|
||||||
indent_spaces (file, indent);
|
write_statements (file,
|
||||||
fprintf (file, "}");
|
r -> data.on.statements,
|
||||||
|
indent + 2);
|
||||||
|
indent_spaces (file, indent);
|
||||||
|
fprintf (file, "}");
|
||||||
|
} else {
|
||||||
|
fprintf (file, ";");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case switch_statement:
|
case switch_statement:
|
||||||
@@ -599,6 +746,15 @@ void write_statements (file, statements, indent)
|
|||||||
" ", "", ";");
|
" ", "", ";");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case unset_statement:
|
||||||
|
indent_spaces (file, indent);
|
||||||
|
fprintf (file, "unset ");
|
||||||
|
col = token_print_indent (file, indent + 6, indent + 6,
|
||||||
|
"", "", r -> data.set.name);
|
||||||
|
col = token_print_indent (file, col, indent + 6,
|
||||||
|
" ", "", ";");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_fatal ("bogus statement type %d\n", r -> op);
|
log_fatal ("bogus statement type %d\n", r -> op);
|
||||||
}
|
}
|
||||||
@@ -611,13 +767,14 @@ void write_statements (file, statements, indent)
|
|||||||
return that (the default statement can precede all the case statements).
|
return that (the default statement can precede all the case statements).
|
||||||
Otherwise, return the null statement. */
|
Otherwise, return the null statement. */
|
||||||
|
|
||||||
struct executable_statement *find_matching_case (packet, lease,
|
struct executable_statement *find_matching_case (packet, lease, in_options,
|
||||||
in_options, out_options,
|
out_options, scope,
|
||||||
expr, stmt)
|
expr, stmt)
|
||||||
struct packet *packet;
|
struct packet *packet;
|
||||||
struct lease *lease;
|
struct lease *lease;
|
||||||
struct option_state *in_options;
|
struct option_state *in_options;
|
||||||
struct option_state *out_options;
|
struct option_state *out_options;
|
||||||
|
struct binding_scope *scope;
|
||||||
struct expression *expr;
|
struct expression *expr;
|
||||||
struct executable_statement *stmt;
|
struct executable_statement *stmt;
|
||||||
{
|
{
|
||||||
@@ -631,14 +788,15 @@ struct executable_statement *find_matching_case (packet, lease,
|
|||||||
memset (&ds, 0, sizeof ds);
|
memset (&ds, 0, sizeof ds);
|
||||||
memset (&cd, 0, sizeof cd);
|
memset (&cd, 0, sizeof cd);
|
||||||
|
|
||||||
status = (evaluate_data_expression
|
status = (evaluate_data_expression (&ds, packet, lease,
|
||||||
(&ds, packet, lease, in_options, out_options, expr));
|
in_options, out_options,
|
||||||
|
scope, expr));
|
||||||
if (status) {
|
if (status) {
|
||||||
for (s = stmt; s; s = s -> next) {
|
for (s = stmt; s; s = s -> next) {
|
||||||
if (s -> op == case_statement) {
|
if (s -> op == case_statement) {
|
||||||
sub = (evaluate_data_expression
|
sub = (evaluate_data_expression
|
||||||
(&cd, packet, lease, in_options,
|
(&cd, packet, lease, in_options,
|
||||||
out_options, s -> data.c_case));
|
out_options, scope, s -> data.c_case));
|
||||||
if (sub && cd.len == ds.len &&
|
if (sub && cd.len == ds.len &&
|
||||||
!memcmp (cd.data, ds.data, cd.len))
|
!memcmp (cd.data, ds.data, cd.len))
|
||||||
{
|
{
|
||||||
@@ -655,15 +813,16 @@ struct executable_statement *find_matching_case (packet, lease,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned long n, c;
|
unsigned long n, c;
|
||||||
status = (evaluate_numeric_expression
|
status = evaluate_numeric_expression (&n, packet, lease,
|
||||||
(&n, packet, lease, in_options, out_options, expr));
|
in_options, out_options,
|
||||||
|
scope, expr);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
for (s = stmt; s; s = s -> next) {
|
for (s = stmt; s; s = s -> next) {
|
||||||
if (s -> op == case_statement) {
|
if (s -> op == case_statement) {
|
||||||
sub = (evaluate_numeric_expression
|
sub = (evaluate_numeric_expression
|
||||||
(&c, packet, lease, in_options,
|
(&c, packet, lease, in_options,
|
||||||
out_options, s -> data.c_case));
|
out_options, scope, s -> data.c_case));
|
||||||
if (sub && n == c)
|
if (sub && n == c)
|
||||||
return s -> next;
|
return s -> next;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user