mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-31 06:15:55 +00:00
-n [master]
[rt27912] Add code to suppor on {commit expiry release} statements for DHCPv6. There are several pieces to this change 1) Add space in the iasubopt structure to hold the statement pointers 2) Update the execute code to fill in the structures as necessary 3) Execute the statements when appropriate Many of the changes in the non-v6 code are to pass the v6 structures around to the execute code.
This commit is contained in:
168
common/execute.c
168
common/execute.c
@@ -39,7 +39,8 @@
|
||||
#include <sys/wait.h>
|
||||
|
||||
int execute_statements (result, packet, lease, client_state,
|
||||
in_options, out_options, scope, statements)
|
||||
in_options, out_options, scope, statements,
|
||||
on_star)
|
||||
struct binding_value **result;
|
||||
struct packet *packet;
|
||||
struct lease *lease;
|
||||
@@ -48,6 +49,7 @@ int execute_statements (result, packet, lease, client_state,
|
||||
struct option_state *out_options;
|
||||
struct binding_scope **scope;
|
||||
struct executable_statement *statements;
|
||||
struct on_star *on_star;
|
||||
{
|
||||
struct executable_statement *r, *e, *next;
|
||||
int rc;
|
||||
@@ -59,14 +61,14 @@ int execute_statements (result, packet, lease, client_state,
|
||||
if (!statements)
|
||||
return 1;
|
||||
|
||||
r = (struct executable_statement *)0;
|
||||
next = (struct executable_statement *)0;
|
||||
e = (struct executable_statement *)0;
|
||||
r = NULL;
|
||||
next = NULL;
|
||||
e = NULL;
|
||||
executable_statement_reference (&r, statements, MDL);
|
||||
while (r && !(result && *result)) {
|
||||
if (r -> next)
|
||||
executable_statement_reference (&next, r -> next, MDL);
|
||||
switch (r -> op) {
|
||||
if (r->next)
|
||||
executable_statement_reference (&next, r->next, MDL);
|
||||
switch (r->op) {
|
||||
case statements_statement:
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: statements");
|
||||
@@ -74,7 +76,8 @@ int execute_statements (result, packet, lease, client_state,
|
||||
status = execute_statements (result, packet, lease,
|
||||
client_state, in_options,
|
||||
out_options, scope,
|
||||
r -> data.statements);
|
||||
r->data.statements,
|
||||
on_star);
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: statements returns %d", status);
|
||||
#endif
|
||||
@@ -83,42 +86,50 @@ int execute_statements (result, packet, lease, client_state,
|
||||
break;
|
||||
|
||||
case on_statement:
|
||||
if (lease) {
|
||||
if (r -> data.on.evtypes & ON_EXPIRY) {
|
||||
/*
|
||||
* if we haven't been passed an on_star block but
|
||||
* do have a lease, use the one from the lease
|
||||
* This handles the previous v4 calls.
|
||||
*/
|
||||
if ((on_star == NULL) && (lease != NULL))
|
||||
on_star = &lease->on_star;
|
||||
|
||||
if (on_star != NULL) {
|
||||
if (r->data.on.evtypes & ON_EXPIRY) {
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: on expiry");
|
||||
#endif
|
||||
if (lease -> on_expiry)
|
||||
if (on_star->on_expiry)
|
||||
executable_statement_dereference
|
||||
(&lease -> on_expiry, MDL);
|
||||
if (r -> data.on.statements)
|
||||
(&on_star->on_expiry, MDL);
|
||||
if (r->data.on.statements)
|
||||
executable_statement_reference
|
||||
(&lease -> on_expiry,
|
||||
r -> data.on.statements, MDL);
|
||||
(&on_star->on_expiry,
|
||||
r->data.on.statements, MDL);
|
||||
}
|
||||
if (r -> data.on.evtypes & ON_RELEASE) {
|
||||
if (r->data.on.evtypes & ON_RELEASE) {
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: on release");
|
||||
#endif
|
||||
if (lease -> on_release)
|
||||
if (on_star->on_release)
|
||||
executable_statement_dereference
|
||||
(&lease -> on_release, MDL);
|
||||
if (r -> data.on.statements)
|
||||
(&on_star->on_release, MDL);
|
||||
if (r->data.on.statements)
|
||||
executable_statement_reference
|
||||
(&lease -> on_release,
|
||||
r -> data.on.statements, MDL);
|
||||
(&on_star->on_release,
|
||||
r->data.on.statements, MDL);
|
||||
}
|
||||
if (r -> data.on.evtypes & ON_COMMIT) {
|
||||
if (r->data.on.evtypes & ON_COMMIT) {
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: on commit");
|
||||
#endif
|
||||
if (lease -> on_commit)
|
||||
if (on_star->on_commit)
|
||||
executable_statement_dereference
|
||||
(&lease -> on_commit, MDL);
|
||||
if (r -> data.on.statements)
|
||||
(&on_star->on_commit, MDL);
|
||||
if (r->data.on.statements)
|
||||
executable_statement_reference
|
||||
(&lease -> on_commit,
|
||||
r -> data.on.statements, MDL);
|
||||
(&on_star->on_commit,
|
||||
r->data.on.statements, MDL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -130,15 +141,16 @@ int execute_statements (result, packet, lease, client_state,
|
||||
status = (find_matching_case
|
||||
(&e, packet, lease, client_state,
|
||||
in_options, out_options, scope,
|
||||
r -> data.s_switch.expr,
|
||||
r -> data.s_switch.statements));
|
||||
r->data.s_switch.expr,
|
||||
r->data.s_switch.statements));
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: switch: case %lx", (unsigned long)e);
|
||||
#endif
|
||||
if (status) {
|
||||
if (!(execute_statements
|
||||
(result, packet, lease, client_state,
|
||||
in_options, out_options, scope, e))) {
|
||||
in_options, out_options, scope, e,
|
||||
on_star))) {
|
||||
executable_statement_dereference
|
||||
(&e, MDL);
|
||||
return 0;
|
||||
@@ -156,7 +168,7 @@ int execute_statements (result, packet, lease, client_state,
|
||||
status = (evaluate_boolean_expression
|
||||
(&rc, packet,
|
||||
lease, client_state, in_options,
|
||||
out_options, scope, r -> data.ie.expr));
|
||||
out_options, scope, r->data.ie.expr));
|
||||
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: if %s", (status
|
||||
@@ -169,15 +181,15 @@ int execute_statements (result, packet, lease, client_state,
|
||||
if (!execute_statements
|
||||
(result, packet, lease, client_state,
|
||||
in_options, out_options, scope,
|
||||
rc ? r -> data.ie.tc : r -> data.ie.fc))
|
||||
rc ? r->data.ie.tc : r->data.ie.fc,
|
||||
on_star))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case eval_statement:
|
||||
status = evaluate_expression
|
||||
((struct binding_value **)0,
|
||||
packet, lease, client_state, in_options,
|
||||
out_options, scope, r -> data.eval, MDL);
|
||||
(NULL, packet, lease, client_state, in_options,
|
||||
out_options, scope, r->data.eval, MDL);
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: evaluate: %s",
|
||||
(status ? "succeeded" : "failed"));
|
||||
@@ -281,11 +293,11 @@ int execute_statements (result, packet, lease, client_state,
|
||||
|
||||
case add_statement:
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: add %s", (r -> data.add -> name
|
||||
? r -> data.add -> name
|
||||
log_debug ("exec: add %s", (r->data.add->name
|
||||
? r->data.add->name
|
||||
: "<unnamed class>"));
|
||||
#endif
|
||||
classify (packet, r -> data.add);
|
||||
classify (packet, r->data.add);
|
||||
break;
|
||||
|
||||
case break_statement:
|
||||
@@ -298,35 +310,35 @@ int execute_statements (result, packet, lease, client_state,
|
||||
case send_option_statement:
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: %s option %s.%s",
|
||||
(r -> op == supersede_option_statement
|
||||
(r->op == supersede_option_statement
|
||||
? "supersede" : "send"),
|
||||
r -> data.option -> option -> universe -> name,
|
||||
r -> data.option -> option -> name);
|
||||
r->data.option->option->universe->name,
|
||||
r->data.option->option->name);
|
||||
goto option_statement;
|
||||
#endif
|
||||
case default_option_statement:
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: default option %s.%s",
|
||||
r -> data.option -> option -> universe -> name,
|
||||
r -> data.option -> option -> name);
|
||||
r->data.option->option->universe->name,
|
||||
r->data.option->option->name);
|
||||
goto option_statement;
|
||||
#endif
|
||||
case append_option_statement:
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: append option %s.%s",
|
||||
r -> data.option -> option -> universe -> name,
|
||||
r -> data.option -> option -> name);
|
||||
r->data.option->option->universe->name,
|
||||
r->data.option->option->name);
|
||||
goto option_statement;
|
||||
#endif
|
||||
case prepend_option_statement:
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: prepend option %s.%s",
|
||||
r -> data.option -> option -> universe -> name,
|
||||
r -> data.option -> option -> name);
|
||||
r->data.option->option->universe->name,
|
||||
r->data.option->option->name);
|
||||
option_statement:
|
||||
#endif
|
||||
set_option (r -> data.option -> option -> universe,
|
||||
out_options, r -> data.option, r -> op);
|
||||
set_option (r->data.option->option->universe,
|
||||
out_options, r->data.option, r->op);
|
||||
break;
|
||||
|
||||
case set_statement:
|
||||
@@ -407,16 +419,16 @@ int execute_statements (result, packet, lease, client_state,
|
||||
case unset_statement:
|
||||
if (!scope || !*scope)
|
||||
break;
|
||||
binding = find_binding (*scope, r -> data.unset);
|
||||
binding = find_binding (*scope, r->data.unset);
|
||||
if (binding) {
|
||||
if (binding -> value)
|
||||
if (binding->value)
|
||||
binding_value_dereference
|
||||
(&binding -> value, MDL);
|
||||
(&binding->value, MDL);
|
||||
status = 1;
|
||||
} else
|
||||
status = 0;
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: unset %s: %s", r -> data.unset,
|
||||
log_debug ("exec: unset %s: %s", r->data.unset,
|
||||
(status ? "found" : "not found"));
|
||||
#else
|
||||
POST(status);
|
||||
@@ -482,10 +494,9 @@ int execute_statements (result, packet, lease, client_state,
|
||||
binding_scope_reference(&ns->outer,
|
||||
*scope, MDL);
|
||||
execute_statements
|
||||
(result, packet, lease,
|
||||
client_state,
|
||||
(result, packet, lease, client_state,
|
||||
in_options, out_options,
|
||||
&ns, e->data.let.statements);
|
||||
&ns, e->data.let.statements, on_star);
|
||||
}
|
||||
if (ns)
|
||||
binding_scope_dereference(&ns, MDL);
|
||||
@@ -496,15 +507,14 @@ int execute_statements (result, packet, lease, client_state,
|
||||
status = (evaluate_data_expression
|
||||
(&ds, packet,
|
||||
lease, client_state, in_options,
|
||||
out_options, scope, r -> data.log.expr,
|
||||
MDL));
|
||||
out_options, scope, r->data.log.expr, MDL));
|
||||
|
||||
#if defined (DEBUG_EXPRESSIONS)
|
||||
log_debug ("exec: log");
|
||||
#endif
|
||||
|
||||
if (status) {
|
||||
switch (r -> data.log.priority) {
|
||||
switch (r->data.log.priority) {
|
||||
case log_priority_fatal:
|
||||
log_fatal ("%.*s", (int)ds.len,
|
||||
ds.data);
|
||||
@@ -550,7 +560,7 @@ int execute_statements (result, packet, lease, client_state,
|
||||
|
||||
void execute_statements_in_scope (result, packet,
|
||||
lease, client_state, in_options, out_options,
|
||||
scope, group, limiting_group)
|
||||
scope, group, limiting_group, on_star)
|
||||
struct binding_value **result;
|
||||
struct packet *packet;
|
||||
struct lease *lease;
|
||||
@@ -560,6 +570,7 @@ void execute_statements_in_scope (result, packet,
|
||||
struct binding_scope **scope;
|
||||
struct group *group;
|
||||
struct group *limiting_group;
|
||||
struct on_star *on_star;
|
||||
{
|
||||
struct group *limit;
|
||||
|
||||
@@ -599,9 +610,10 @@ void execute_statements_in_scope (result, packet,
|
||||
execute_statements_in_scope (result, packet,
|
||||
lease, client_state,
|
||||
in_options, out_options, scope,
|
||||
group -> next, limiting_group);
|
||||
group->next, limiting_group,
|
||||
on_star);
|
||||
execute_statements (result, packet, lease, client_state, in_options,
|
||||
out_options, scope, group -> statements);
|
||||
out_options, scope, group->statements, on_star);
|
||||
}
|
||||
|
||||
/* Dereference or free any subexpressions of a statement being freed. */
|
||||
@@ -1033,14 +1045,14 @@ int find_matching_case (struct executable_statement **ep,
|
||||
sub = (evaluate_data_expression
|
||||
(&cd, packet, lease, client_state,
|
||||
in_options, out_options,
|
||||
scope, s -> data.c_case, MDL));
|
||||
scope, s->data.c_case, MDL));
|
||||
if (sub && cd.len == ds.len &&
|
||||
!memcmp (cd.data, ds.data, cd.len))
|
||||
{
|
||||
data_string_forget (&cd, MDL);
|
||||
data_string_forget (&ds, MDL);
|
||||
executable_statement_reference
|
||||
(ep, s -> next, MDL);
|
||||
(ep, s->next, MDL);
|
||||
return 1;
|
||||
}
|
||||
data_string_forget (&cd, MDL);
|
||||
@@ -1056,15 +1068,15 @@ int find_matching_case (struct executable_statement **ep,
|
||||
scope, expr);
|
||||
|
||||
if (status) {
|
||||
for (s = stmt; s; s = s -> next) {
|
||||
for (s = stmt; s; s = s->next) {
|
||||
if (s -> op == case_statement) {
|
||||
sub = (evaluate_numeric_expression
|
||||
(&c, packet, lease, client_state,
|
||||
in_options, out_options,
|
||||
scope, s -> data.c_case));
|
||||
scope, s->data.c_case));
|
||||
if (sub && n == c) {
|
||||
executable_statement_reference
|
||||
(ep, s -> next, MDL);
|
||||
(ep, s->next, MDL);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1074,11 +1086,11 @@ int find_matching_case (struct executable_statement **ep,
|
||||
|
||||
/* If we didn't find a matching case statement, look for a default
|
||||
statement and return the statement following it. */
|
||||
for (s = stmt; s; s = s -> next)
|
||||
if (s -> op == default_statement)
|
||||
for (s = stmt; s; s = s->next)
|
||||
if (s->op == default_statement)
|
||||
break;
|
||||
if (s) {
|
||||
executable_statement_reference (ep, s -> next, MDL);
|
||||
executable_statement_reference (ep, s->next, MDL);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -1093,17 +1105,17 @@ int executable_statement_foreach (struct executable_statement *stmt,
|
||||
struct executable_statement *foo;
|
||||
int ok = 0;
|
||||
|
||||
for (foo = stmt; foo; foo = foo -> next) {
|
||||
for (foo = stmt; foo; foo = foo->next) {
|
||||
if ((*callback) (foo, vp, condp) != 0)
|
||||
ok = 1;
|
||||
switch (foo -> op) {
|
||||
switch (foo->op) {
|
||||
case null_statement:
|
||||
break;
|
||||
case if_statement:
|
||||
if (executable_statement_foreach (foo -> data.ie.tc,
|
||||
if (executable_statement_foreach (foo->data.ie.tc,
|
||||
callback, vp, 1))
|
||||
ok = 1;
|
||||
if (executable_statement_foreach (foo -> data.ie.fc,
|
||||
if (executable_statement_foreach (foo->data.ie.fc,
|
||||
callback, vp, 1))
|
||||
ok = 1;
|
||||
break;
|
||||
@@ -1125,17 +1137,17 @@ int executable_statement_foreach (struct executable_statement *stmt,
|
||||
break;
|
||||
case statements_statement:
|
||||
if ((executable_statement_foreach
|
||||
(foo -> data.statements, callback, vp, condp)))
|
||||
(foo->data.statements, callback, vp, condp)))
|
||||
ok = 1;
|
||||
break;
|
||||
case on_statement:
|
||||
if ((executable_statement_foreach
|
||||
(foo -> data.on.statements, callback, vp, 1)))
|
||||
(foo->data.on.statements, callback, vp, 1)))
|
||||
ok = 1;
|
||||
break;
|
||||
case switch_statement:
|
||||
if ((executable_statement_foreach
|
||||
(foo -> data.s_switch.statements, callback, vp, 1)))
|
||||
(foo->data.s_switch.statements, callback, vp, 1)))
|
||||
ok = 1;
|
||||
break;
|
||||
case case_statement:
|
||||
@@ -1148,7 +1160,7 @@ int executable_statement_foreach (struct executable_statement *stmt,
|
||||
break;
|
||||
case let_statement:
|
||||
if ((executable_statement_foreach
|
||||
(foo -> data.let.statements, callback, vp, 0)))
|
||||
(foo->data.let.statements, callback, vp, 0)))
|
||||
ok = 1;
|
||||
break;
|
||||
case define_statement:
|
||||
|
Reference in New Issue
Block a user