supported by ISC; however it may be useful to some users.
[ISC-Bugs #20680]
+- Add support in v6 for on-commit, on-expire and on-release.
+ [ISC-Bugs #27912
+
Changes since 4.2.5
- Address static analysis warnings.
/* dhc6.c - DHCPv6 client routines. */
/*
- * Copyright (c) 2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2012-2013 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2006-2010 by Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and distribute this software for any
lease ? lease->options : NULL,
*op, &global_scope,
client->config->on_transmission,
- NULL);
+ NULL, NULL);
/* Rapid-commit is only for SOLICITs. */
if (message != DHCPV6_SOLICIT)
}
}
- execute_statements_in_scope ((struct binding_value **)0,
- (struct packet *)packet,
- (struct lease *)0, client,
- lease -> options, lease -> options,
- &global_scope,
- client -> config -> on_receipt,
- (struct group *)0);
+ execute_statements_in_scope(NULL, (struct packet *)packet, NULL,
+ client, lease->options, lease->options,
+ &global_scope, client->config->on_receipt,
+ NULL, NULL);
return lease;
}
}
/* Run statements that need to be run on transmission. */
- if (client -> config -> on_transmission)
- execute_statements_in_scope
- ((struct binding_value **)0,
- (struct packet *)0, (struct lease *)0, client,
- (lease ? lease -> options : (struct option_state *)0),
- *op, &global_scope,
- client -> config -> on_transmission,
- (struct group *)0);
+ if (client->config->on_transmission)
+ execute_statements_in_scope(NULL, NULL, NULL, client,
+ (lease ? lease->options : NULL),
+ *op, &global_scope,
+ client->config->on_transmission,
+ NULL, NULL);
}
void make_discover (client, lease)
#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;
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;
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");
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
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;
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;
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
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"));
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:
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:
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);
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);
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);
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;
struct binding_scope **scope;
struct group *group;
struct group *limiting_group;
+ struct on_star *on_star;
{
struct group *limit;
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. */
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);
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;
}
}
/* 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;
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;
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:
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:
status = (execute_statements
(&bv, packet,
lease, client_state, in_options, cfg_options, &ns,
- binding -> value -> value.fundef -> statements));
+ binding->value->value.fundef->statements, NULL));
binding_scope_dereference (&ns, MDL);
if (!bv)
/* FTS_LAST is the highest value that is valid for a lease binding state. */
#define FTS_LAST FTS_BACKUP
+/*
+ * A block for the on statements so we can share the structure
+ * between v4 and v6
+ */
+struct on_star {
+ struct executable_statement *on_expiry;
+ struct executable_statement *on_commit;
+ struct executable_statement *on_release;
+};
+
/* A dhcp lease declaration structure. */
struct lease {
OMAPI_OBJECT_PREAMBLE;
struct class *billing_class;
struct option_chain_head *agent_options;
- struct executable_statement *on_expiry;
- struct executable_statement *on_commit;
- struct executable_statement *on_release;
+ /* insert the structure directly */
+ struct on_star on_star;
unsigned char *uid;
unsigned short uid_len;
*/
struct dhcp_ddns_cb *ddns_cb;
+ /* space for the on * executable statements */
+ struct on_star on_star;
};
struct ia_xx {
struct option_state *,
struct option_state *,
struct binding_scope **,
- struct expression *, const char *, int);
+ struct expression *,
+ const char *, int);
int evaluate_numeric_expression (unsigned long *, struct packet *,
struct lease *, struct client_state *,
struct option_state *, struct option_state *,
struct client_state *,
struct option_state *, struct option_state *,
struct binding_scope **,
- struct executable_statement *);
+ struct executable_statement *,
+ struct on_star *);
void execute_statements_in_scope (struct binding_value **result,
struct packet *, struct lease *,
struct client_state *,
struct option_state *,
struct option_state *,
struct binding_scope **,
- struct group *, struct group *);
+ struct group *, struct group *,
+ struct on_star *);
int executable_statement_dereference (struct executable_statement **,
const char *, int);
void write_statements (FILE *, struct executable_statement *, int);
BOOTP Protocol support. */
/*
- * Copyright (c) 2009,2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009,2012-2013 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2004,2005,2007 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
option_state_allocate (&options, MDL);
/* Execute the subnet statements. */
- execute_statements_in_scope ((struct binding_value **)0,
- packet, lease, (struct client_state *)0,
- packet -> options, options,
- &lease -> scope, lease -> subnet -> group,
- (struct group *)0);
+ execute_statements_in_scope (NULL, packet, lease, NULL,
+ packet->options, options,
+ &lease->scope, lease->subnet->group,
+ NULL, NULL);
/* Execute statements from class scopes. */
for (i = packet -> class_count; i > 0; i--) {
- execute_statements_in_scope
- ((struct binding_value **)0,
- packet, lease, (struct client_state *)0,
- packet -> options, options,
- &lease -> scope, packet -> classes [i - 1] -> group,
- lease -> subnet -> group);
+ execute_statements_in_scope(NULL, packet, lease, NULL,
+ packet->options, options,
+ &lease->scope,
+ packet->classes[i - 1]->group,
+ lease->subnet->group, NULL);
}
/* Execute the host statements. */
if (hp != NULL) {
execute_statements_in_scope (NULL, packet, lease, NULL,
packet->options, options,
- &lease->scope,
- hp->group, lease->subnet->group);
+ &lease->scope, hp->group,
+ lease->subnet->group, NULL);
}
/* Drop the request if it's not allowed for this client. */
}
/* Execute the commit statements, if there are any. */
- execute_statements ((struct binding_value **)0,
- packet, lease, (struct client_state *)0,
- packet -> options,
- options, &lease -> scope, lease -> on_commit);
+ execute_statements (NULL, packet, lease, NULL, packet->options,
+ options, &lease->scope, lease->on_star.on_commit,
+ NULL);
/* We're done with the option state. */
option_state_dereference (&options, MDL);
Handling for client classes. */
/*
- * Copyright (c) 2009,2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009,2012-2013 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1998-2003 by Internet Software Consortium
*
void classify_client (packet)
struct packet *packet;
{
- execute_statements ((struct binding_value **)0, packet,
- (struct lease *)0, (struct client_state *)0,
- packet -> options, (struct option_state *)0,
- &global_scope, default_classification_rules);
+ execute_statements (NULL, packet, NULL, NULL, packet->options, NULL,
+ &global_scope, default_classification_rules, NULL);
}
int check_collection (packet, lease, collection)
return 0;
}
seenbit = 0;
- if ((on -> data.on.evtypes & ON_EXPIRY) &&
- on -> data.on.statements) {
+ if ((on->data.on.evtypes & ON_EXPIRY) &&
+ on->data.on.statements) {
seenbit |= 16384;
executable_statement_reference
- (&lease -> on_expiry,
- on -> data.on.statements, MDL);
+ (&lease->on_star.on_expiry,
+ on->data.on.statements, MDL);
}
- if ((on -> data.on.evtypes & ON_RELEASE) &&
- on -> data.on.statements) {
+ if ((on->data.on.evtypes & ON_RELEASE) &&
+ on->data.on.statements) {
seenbit |= 32768;
executable_statement_reference
- (&lease -> on_release,
- on -> data.on.statements, MDL);
+ (&lease->on_star.on_release,
+ on->data.on.statements, MDL);
}
executable_statement_dereference (&on, MDL);
break;
/* If no binding state is specified, make one up. */
if (!(seenmask & 256)) {
- if (lease -> ends > cur_time ||
- lease -> on_expiry || lease -> on_release)
- lease -> binding_state = FTS_ACTIVE;
+ if (lease->ends > cur_time ||
+ lease->on_star.on_expiry || lease->on_star.on_release)
+ lease->binding_state = FTS_ACTIVE;
#if defined (FAILOVER_PROTOCOL)
- else if (lease -> pool && lease -> pool -> failover_peer)
- lease -> binding_state = FTS_EXPIRED;
+ else if (lease->pool && lease->pool->failover_peer)
+ lease->binding_state = FTS_EXPIRED;
#endif
else
- lease -> binding_state = FTS_FREE;
- if (lease -> binding_state == FTS_ACTIVE) {
+ lease->binding_state = FTS_FREE;
+ if (lease->binding_state == FTS_ACTIVE) {
#if defined (FAILOVER_PROTOCOL)
- if (lease -> pool && lease -> pool -> failover_peer)
- lease -> next_binding_state = FTS_EXPIRED;
+ if (lease->pool && lease->pool->failover_peer)
+ lease->next_binding_state = FTS_EXPIRED;
else
#endif
- lease -> next_binding_state = FTS_FREE;
+ lease->next_binding_state = FTS_FREE;
} else
- lease -> next_binding_state = lease -> binding_state;
+ lease->next_binding_state = lease->binding_state;
/* The most conservative rewind state implies no rewind. */
lease->rewind_binding_state = lease->binding_state;
}
if (!(seenmask & 65536))
- lease -> tstp = lease -> ends;
+ lease->tstp = lease->ends;
lease_reference (lp, lease, MDL);
lease_dereference (&lease, MDL);
struct ipv6_pool *pool;
char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
isc_boolean_t newbinding;
- struct binding_scope *scope=NULL;
+ struct binding_scope *scope = NULL;
struct binding *bnd;
- struct binding_value *nv=NULL;
+ struct binding_value *nv = NULL;
+ struct executable_statement *on_star[2] = {NULL, NULL};
+ int lose, i;
if (local_family != AF_INET6) {
parse_warn(cfile, "IA_NA is only supported in DHCPv6 mode.");
parse_semi(cfile);
break;
+ case ON:
+ lose = 0;
+ /*
+ * Depending on the user config we may
+ * have one or two on statements. We
+ * need to save information about both
+ * of them until we allocate the
+ * iasubopt to hold them.
+ */
+ if (on_star[0] == NULL) {
+ if (!parse_on_statement (&on_star[0],
+ cfile,
+ &lose)) {
+ parse_warn(cfile,
+ "corrupt lease "
+ "file; bad ON "
+ "statement");
+ skip_to_rbrace (cfile, 1);
+ return;
+ }
+ } else {
+ if (!parse_on_statement (&on_star[1],
+ cfile,
+ &lose)) {
+ parse_warn(cfile,
+ "corrupt lease "
+ "file; bad ON "
+ "statement");
+ skip_to_rbrace (cfile, 1);
+ return;
+ }
+ }
+
+ break;
+
default:
parse_warn(cfile, "corrupt lease file; "
"expecting ia_na contents, "
binding_scope_dereference(&scope, MDL);
}
+ /*
+ * Check on both on statements. Because of how we write the
+ * lease file we know which is which if we have two but it's
+ * easier to write the code to be independent. We do assume
+ * that the statements won't overlap.
+ */
+ for (i = 0;
+ (i < 2) && on_star[i] != NULL ;
+ i++) {
+ if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
+ on_star[i]->data.on.statements) {
+ executable_statement_reference
+ (&iaaddr->on_star.on_expiry,
+ on_star[i]->data.on.statements, MDL);
+ }
+ if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
+ on_star[i]->data.on.statements) {
+ executable_statement_reference
+ (&iaaddr->on_star.on_release,
+ on_star[i]->data.on.statements, MDL);
+ }
+ executable_statement_dereference (&on_star[i], MDL);
+ }
+
/* find the pool this address is in */
pool = NULL;
if (find_ipv6_pool(&pool, D6O_IA_NA,
struct ipv6_pool *pool;
char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
isc_boolean_t newbinding;
- struct binding_scope *scope=NULL;
+ struct binding_scope *scope = NULL;
struct binding *bnd;
- struct binding_value *nv=NULL;
+ struct binding_value *nv = NULL;
+ struct executable_statement *on_star[2] = {NULL, NULL};
+ int lose, i;
if (local_family != AF_INET6) {
parse_warn(cfile, "IA_TA is only supported in DHCPv6 mode.");
parse_semi(cfile);
break;
+ case ON:
+ lose = 0;
+ /*
+ * Depending on the user config we may
+ * have one or two on statements. We
+ * need to save information about both
+ * of them until we allocate the
+ * iasubopt to hold them.
+ */
+ if (on_star[0] == NULL) {
+ if (!parse_on_statement (&on_star[0],
+ cfile,
+ &lose)) {
+ parse_warn(cfile,
+ "corrupt lease "
+ "file; bad ON "
+ "statement");
+ skip_to_rbrace (cfile, 1);
+ return;
+ }
+ } else {
+ if (!parse_on_statement (&on_star[1],
+ cfile,
+ &lose)) {
+ parse_warn(cfile,
+ "corrupt lease "
+ "file; bad ON "
+ "statement");
+ skip_to_rbrace (cfile, 1);
+ return;
+ }
+ }
+
+ break;
+
default:
parse_warn(cfile, "corrupt lease file; "
"expecting ia_ta contents, "
binding_scope_dereference(&scope, MDL);
}
+ /*
+ * Check on both on statements. Because of how we write the
+ * lease file we know which is which if we have two but it's
+ * easier to write the code to be independent. We do assume
+ * that the statements won't overlap.
+ */
+ for (i = 0;
+ (i < 2) && on_star[i] != NULL ;
+ i++) {
+ if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
+ on_star[i]->data.on.statements) {
+ executable_statement_reference
+ (&iaaddr->on_star.on_expiry,
+ on_star[i]->data.on.statements, MDL);
+ }
+ if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
+ on_star[i]->data.on.statements) {
+ executable_statement_reference
+ (&iaaddr->on_star.on_release,
+ on_star[i]->data.on.statements, MDL);
+ }
+ executable_statement_dereference (&on_star[i], MDL);
+ }
+
/* find the pool this address is in */
pool = NULL;
if (find_ipv6_pool(&pool, D6O_IA_TA,
struct ipv6_pool *pool;
char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
isc_boolean_t newbinding;
- struct binding_scope *scope=NULL;
+ struct binding_scope *scope = NULL;
struct binding *bnd;
- struct binding_value *nv=NULL;
+ struct binding_value *nv = NULL;
+ struct executable_statement *on_star[2] = {NULL, NULL};
+ int lose, i;
if (local_family != AF_INET6) {
parse_warn(cfile, "IA_PD is only supported in DHCPv6 mode.");
parse_semi(cfile);
break;
+ case ON:
+ lose = 0;
+ /*
+ * Depending on the user config we may
+ * have one or two on statements. We
+ * need to save information about both
+ * of them until we allocate the
+ * iasubopt to hold them.
+ */
+ if (on_star[0] == NULL) {
+ if (!parse_on_statement (&on_star[0],
+ cfile,
+ &lose)) {
+ parse_warn(cfile,
+ "corrupt lease "
+ "file; bad ON "
+ "statement");
+ skip_to_rbrace (cfile, 1);
+ return;
+ }
+ } else {
+ if (!parse_on_statement (&on_star[1],
+ cfile,
+ &lose)) {
+ parse_warn(cfile,
+ "corrupt lease "
+ "file; bad ON "
+ "statement");
+ skip_to_rbrace (cfile, 1);
+ return;
+ }
+ }
+
+ break;
+
default:
parse_warn(cfile, "corrupt lease file; "
"expecting ia_pd contents, "
binding_scope_dereference(&scope, MDL);
}
+ /*
+ * Check on both on statements. Because of how we write the
+ * lease file we know which is which if we have two but it's
+ * easier to write the code to be independent. We do assume
+ * that the statements won't overlap.
+ */
+ for (i = 0;
+ (i < 2) && on_star[i] != NULL ;
+ i++) {
+ if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
+ on_star[i]->data.on.statements) {
+ executable_statement_reference
+ (&iapref->on_star.on_expiry,
+ on_star[i]->data.on.statements, MDL);
+ }
+ if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
+ on_star[i]->data.on.statements) {
+ executable_statement_reference
+ (&iapref->on_star.on_release,
+ on_star[i]->data.on.statements, MDL);
+ }
+ executable_statement_dereference (&on_star[i], MDL);
+ }
+
/* find the pool this address is in */
pool = NULL;
if (find_ipv6_pool(&pool, D6O_IA_PD,
Persistent database management routines for DHCPD... */
/*
- * Copyright (c) 2004-2010,2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2012,2013 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium
*
* Permission to use, copy, modify, and distribute this software for any
} else
++errors;
}
- if (lease -> on_expiry) {
+ if (lease->on_star.on_expiry) {
errno = 0;
fprintf (db_file, "\n on expiry%s {",
- lease -> on_expiry == lease -> on_release
+ lease->on_star.on_expiry == lease->on_star.on_release
? " or release" : "");
- write_statements (db_file, lease -> on_expiry, 4);
+ write_statements (db_file, lease->on_star.on_expiry, 4);
/* XXX */
fprintf (db_file, "\n }");
if (errno)
++errors;
}
- if (lease -> on_release && lease -> on_release != lease -> on_expiry) {
+ if (lease->on_star.on_release &&
+ lease->on_star.on_release != lease->on_star.on_expiry) {
errno = 0;
fprintf (db_file, "\n on release {");
- write_statements (db_file, lease -> on_release, 4);
+ write_statements (db_file, lease->on_star.on_release, 4);
/* XXX */
fprintf (db_file, "\n }");
if (errno)
}
+ if (iasubopt->on_star.on_expiry) {
+ if (fprintf(db_file, "\n on expiry%s {",
+ iasubopt->on_star.on_expiry ==
+ iasubopt->on_star.on_release
+ ? " or release" : "") < 0)
+ goto error_exit;
+ write_statements(db_file,
+ iasubopt->on_star.on_expiry, 6);
+ if (fprintf(db_file, "\n }") < 0)
+ goto error_exit;
+ }
+
+ if (iasubopt->on_star.on_release &&
+ iasubopt->on_star.on_release !=
+ iasubopt->on_star.on_expiry) {
+ if (fprintf(db_file, "\n on release {") < 0)
+ goto error_exit;
+ write_statements(db_file,
+ iasubopt->on_star.on_release, 6);
+ if (fprintf(db_file, "\n }") < 0)
+ goto error_exit;
+ }
+
if (fprintf(db_file, "\n }\n") < 0)
goto error_exit;
}
/*
*
- * Copyright (c) 2009-2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 2009-2013 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2000-2003 by Internet Software Consortium
*
So if the expiry and release events look like
they're the same, run them. This should delete
the old DDNS data. */
- if (old -> on_expiry == old -> on_release) {
+ if (old->on_star.on_expiry ==
+ old->on_star.on_release) {
execute_statements(NULL, NULL, lease, NULL,
NULL, NULL, scope,
- old->on_expiry);
- if (old -> on_expiry)
+ old->on_star.on_expiry,
+ NULL);
+ if (old->on_star.on_expiry)
executable_statement_dereference
- (&old -> on_expiry, MDL);
- if (old -> on_release)
+ (&old->on_star.on_expiry,
+ MDL);
+ if (old->on_star.on_release)
executable_statement_dereference
- (&old -> on_release, MDL);
+ (&old->on_star.on_release,
+ MDL);
/* Now, install the DDNS data the new way. */
goto in;
}
/* Execute statements in scope starting with the subnet scope. */
if (lease)
- execute_statements_in_scope ((struct binding_value **)0,
- packet, (struct lease *)0,
- (struct client_state *)0,
- packet -> options, options,
- &global_scope,
- lease -> subnet -> group,
- (struct group *)0);
+ execute_statements_in_scope(NULL, packet, NULL, NULL,
+ packet->options, options,
+ &global_scope,
+ lease->subnet->group,
+ NULL, NULL);
/* Execute statements in the class scopes. */
for (i = packet -> class_count; i > 0; i--) {
execute_statements_in_scope
- ((struct binding_value **)0, packet, (struct lease *)0,
- (struct client_state *)0, packet -> options, options,
- &global_scope, packet -> classes [i - 1] -> group,
- lease ? lease -> subnet -> group : (struct group *)0);
+ (NULL, packet, NULL, NULL, packet->options, options,
+ &global_scope, packet->classes[i - 1]->group,
+ lease ? lease->subnet->group : NULL, NULL);
}
/* Drop the request if dhcpdeclines are being ignored. */
/* Execute statements in scope starting with the subnet scope. */
if (subnet)
- execute_statements_in_scope ((struct binding_value **)0,
- packet, (struct lease *)0,
- (struct client_state *)0,
- packet -> options, options,
- &global_scope, subnet -> group,
- (struct group *)0);
+ execute_statements_in_scope (NULL, packet, NULL, NULL,
+ packet->options, options,
+ &global_scope, subnet->group,
+ NULL, NULL);
/* Execute statements in the class scopes. */
for (i = packet -> class_count; i > 0; i--) {
- execute_statements_in_scope
- ((struct binding_value **)0, packet, (struct lease *)0,
- (struct client_state *)0, packet -> options, options,
- &global_scope, packet -> classes [i - 1] -> group,
- subnet ? subnet -> group : (struct group *)0);
+ execute_statements_in_scope(NULL, packet, NULL, NULL,
+ packet->options, options,
+ &global_scope,
+ packet->classes[i - 1]->group,
+ subnet ? subnet->group : NULL,
+ NULL);
}
/* Figure out the filename. */
REQUEST our offer, it will expire in 2 minutes, overriding the
expire time in the currently in force lease. We want the expire
events to be executed at that point. */
- if (lease -> ends <= cur_time && offer != DHCPOFFER) {
+ if (lease->ends <= cur_time && offer != DHCPOFFER) {
/* Get rid of any old expiry or release statements - by
executing the statements below, we will be inserting new
ones if there are any to insert. */
- if (lease -> on_expiry)
- executable_statement_dereference (&lease -> on_expiry,
- MDL);
- if (lease -> on_commit)
- executable_statement_dereference (&lease -> on_commit,
- MDL);
- if (lease -> on_release)
- executable_statement_dereference (&lease -> on_release,
- MDL);
+ if (lease->on_star.on_expiry)
+ executable_statement_dereference
+ (&lease->on_star.on_expiry, MDL);
+ if (lease->on_star.on_commit)
+ executable_statement_dereference
+ (&lease->on_star.on_commit, MDL);
+ if (lease->on_star.on_release)
+ executable_statement_dereference
+ (&lease->on_star.on_release, MDL);
}
/* Execute statements in scope starting with the subnet scope. */
- execute_statements_in_scope ((struct binding_value **)0,
- packet, lease, (struct client_state *)0,
- packet -> options,
- state -> options, &lease -> scope,
- lease -> subnet -> group,
- (struct group *)0);
+ execute_statements_in_scope (NULL, packet, lease,
+ NULL, packet->options,
+ state->options, &lease->scope,
+ lease->subnet->group, NULL, NULL);
/* If the lease is from a pool, run the pool scope. */
- if (lease -> pool)
- (execute_statements_in_scope
- ((struct binding_value **)0, packet, lease,
- (struct client_state *)0, packet -> options,
- state -> options, &lease -> scope, lease -> pool -> group,
- lease -> pool -> shared_network -> group));
+ if (lease->pool)
+ (execute_statements_in_scope(NULL, packet, lease, NULL,
+ packet->options, state->options,
+ &lease->scope, lease->pool->group,
+ lease->pool->
+ shared_network->group,
+ NULL));
/* Execute statements from class scopes. */
for (i = packet -> class_count; i > 0; i--) {
- execute_statements_in_scope
- ((struct binding_value **)0,
- packet, lease, (struct client_state *)0,
- packet -> options, state -> options,
- &lease -> scope, packet -> classes [i - 1] -> group,
- (lease -> pool
- ? lease -> pool -> group
- : lease -> subnet -> group));
+ execute_statements_in_scope(NULL, packet, lease, NULL,
+ packet->options, state->options,
+ &lease->scope,
+ packet->classes[i - 1]->group,
+ (lease->pool ? lease->pool->group
+ : lease->subnet->group),
+ NULL);
}
/* See if the client is only supposed to have one lease at a time,
host_dereference(&hp, MDL);
}
if (!host) {
- find_hosts_by_option(&hp, packet, packet->options, MDL);
+ find_hosts_by_option(&hp, packet,
+ packet->options, MDL);
for (h = hp; h; h = h -> n_ipaddr) {
if (!h -> fixed_addr)
break;
/* If we have a host_decl structure, run the options associated
with its group. Whether the host decl struct is old or not. */
if (host)
- execute_statements_in_scope ((struct binding_value **)0,
- packet, lease,
- (struct client_state *)0,
- packet -> options,
- state -> options, &lease -> scope,
- host -> group,
- (lease -> pool
- ? lease -> pool -> group
- : lease -> subnet -> group));
+ execute_statements_in_scope (NULL, packet, lease, NULL,
+ packet->options, state->options,
+ &lease->scope, host->group,
+ (lease->pool
+ ? lease->pool->group
+ : lease->subnet->group),
+ NULL);
/* Drop the request if it's not allowed for this client. By
default, unknown clients are allowed. */
/* If there are statements to execute when the lease is
committed, execute them. */
- if (lease -> on_commit && (!offer || offer == DHCPACK)) {
- execute_statements ((struct binding_value **)0,
- packet, lt, (struct client_state *)0,
- packet -> options,
- state -> options, < -> scope,
- lease -> on_commit);
- if (lease -> on_commit)
- executable_statement_dereference (&lease -> on_commit,
- MDL);
+ if (lease->on_star.on_commit && (!offer || offer == DHCPACK)) {
+ execute_statements (NULL, packet, lt, NULL, packet->options,
+ state->options, <->scope,
+ lease->on_star.on_commit, NULL);
+ if (lease->on_star.on_commit)
+ executable_statement_dereference
+ (&lease->on_star.on_commit, MDL);
}
#ifdef NSUPDATE
packet->options, sid_options,
&global_scope,
packet->shared_network->subnets->group,
- NULL);
+ NULL, NULL);
} else {
execute_statements_in_scope(NULL, packet, NULL, NULL,
packet->options, sid_options,
&global_scope,
packet->shared_network->group,
- NULL);
+ NULL, NULL);
}
/* do the pool if there is one */
packet->options, sid_options,
&global_scope,
packet->shared_network->pools->group,
- packet->shared_network->group);
+ packet->shared_network->group,
+ NULL);
}
/* currently we don't bother with classes or hosts as
/* Now try to get the lease file name. */
option_state_allocate (&options, MDL);
- execute_statements_in_scope ((struct binding_value **)0,
- (struct packet *)0,
- (struct lease *)0,
- (struct client_state *)0,
- (struct option_state *)0,
- options, &global_scope,
- root_group,
- (struct group *)0);
+ execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
+ options, &global_scope, root_group,
+ NULL, NULL);
memset (&db, 0, sizeof db);
oc = lookup_option (&server_universe, options, SV_LEASE_FILE_NAME);
if (oc &&
/*
- * Copyright (C) 2011-2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2011-2013 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2006-2007,2009 by Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and distribute this software for any
return;
}
- execute_statements_in_scope(NULL,
- packet,
- NULL,
- NULL,
- packet->options,
- options,
- &global_scope,
- relay_group,
- NULL);
+ execute_statements_in_scope(NULL, packet, NULL, NULL, packet->options,
+ options, &global_scope, relay_group,
+ NULL, NULL);
for (i=packet->class_count-1; i>=0; i--) {
- execute_statements_in_scope(NULL,
- packet,
- NULL,
- NULL,
- packet->options,
- options,
+ execute_statements_in_scope(NULL, packet, NULL, NULL,
+ packet->options, options,
&global_scope,
packet->classes[i]->group,
- relay_group);
+ relay_group, NULL);
}
/*
}
execute_statements_in_scope(NULL, lq.packet, NULL, NULL,
lq.packet->options, lq.reply_opts,
- &global_scope, root_group, NULL);
+ &global_scope, root_group, NULL, NULL);
lq.buf.reply.msg_type = DHCPV6_LEASEQUERY_REPLY;
/* Index into the data field that has been consumed. */
unsigned cursor;
+ /* Space for the on commit statements for a fixed host */
+ struct on_star on_star;
+
union reply_buffer {
unsigned char data[65536];
struct dhcpv6_packet reply;
}
execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL,
- opt_state, &global_scope, root_group, NULL);
+ opt_state, &global_scope, root_group,
+ NULL, NULL);
oc = lookup_option(&dhcpv6_universe, opt_state, D6O_SERVERID);
if (oc == NULL) {
}
execute_statements_in_scope(NULL, packet, NULL, NULL,
packet->options, *opt_state,
- &global_scope, root_group, NULL);
+ &global_scope, root_group, NULL, NULL);
/*
* A small bit of special handling for Solicit messages.
execute_statements_in_scope(NULL, reply.packet, NULL, NULL,
reply.packet->options,
reply.opt_state, &global_scope,
- reply.shared->group, root_group);
+ reply.shared->group, root_group,
+ NULL);
/* Bring in any configuration from a host record. */
if (reply.host != NULL)
- execute_statements_in_scope(NULL, reply.packet, NULL,
- NULL, reply.packet->options,
+ execute_statements_in_scope(NULL, reply.packet,
+ NULL, NULL,
+ reply.packet->options,
reply.opt_state,
&global_scope,
reply.host->group,
- reply.shared->group);
+ reply.shared->group, NULL);
}
/*
renew_lease6(tmp->ipv6_pool, tmp);
schedule_lease_timeout(tmp->ipv6_pool);
+ /* If we have anything to do on commit do it now */
+ if (tmp->on_star.on_commit != NULL) {
+ execute_statements(NULL, reply->packet,
+ NULL, NULL,
+ reply->packet->options,
+ reply->opt_state,
+ &reply->lease->scope,
+ tmp->on_star.on_commit,
+ &tmp->on_star);
+ executable_statement_dereference
+ (&tmp->on_star.on_commit, MDL);
+ }
+
#if defined (NSUPDATE)
/*
* Perform ddns updates.
write_ia(reply->ia);
}
+ /*
+ * If this would be a hard binding for a static lease
+ * run any commit statements that we have
+ */
+ if ((status != ISC_R_CANCELED) && reply->static_lease &&
+ (reply->buf.reply.msg_type == DHCPV6_REPLY) &&
+ (reply->on_star.on_commit != NULL)) {
+ execute_statements(NULL, reply->packet, NULL, NULL,
+ reply->packet->options, reply->opt_state,
+ NULL, reply->on_star.on_commit, NULL);
+ executable_statement_dereference
+ (&reply->on_star.on_commit, MDL);
+ }
+
cleanup:
if (packet_ia != NULL)
option_state_dereference(&packet_ia, MDL);
data_string_forget(&reply->fixed, MDL);
if (reply->subnet != NULL)
subnet_dereference(&reply->subnet, MDL);
+ if (reply->on_star.on_expiry != NULL)
+ executable_statement_dereference
+ (&reply->on_star.on_expiry, MDL);
+ if (reply->on_star.on_release != NULL)
+ executable_statement_dereference
+ (&reply->on_star.on_release, MDL);
/*
* ISC_R_CANCELED is a status code used by the addr processing to
renew_lease6(tmp->ipv6_pool, tmp);
schedule_lease_timeout(tmp->ipv6_pool);
+ /* If we have anything to do on commit do it now */
+ if (tmp->on_star.on_commit != NULL) {
+ execute_statements(NULL, reply->packet,
+ NULL, NULL,
+ reply->packet->options,
+ reply->opt_state,
+ &reply->lease->scope,
+ tmp->on_star.on_commit,
+ &tmp->on_star);
+ executable_statement_dereference
+ (&tmp->on_star.on_commit, MDL);
+ }
+
#if defined (NSUPDATE)
/*
* Perform ddns updates.
isc_result_t status = ISC_R_SUCCESS;
struct data_string data;
struct option_cache *oc;
+ struct option_state *tmp_options = NULL;
+ struct on_star *on_star;
/* Initialize values we will cleanup. */
memset(&data, 0, sizeof(data));
+ /*
+ * Find the proper on_star block to use. We use the
+ * one in the lease if we have a lease or the one in
+ * the reply if we don't have a lease because this is
+ * a static instance
+ */
+ if (reply->lease) {
+ on_star = &reply->lease->on_star;
+ } else {
+ on_star = &reply->on_star;
+ }
+
+ /*
+ * Bring in the root configuration. We only do this to bring
+ * in the on * statements, as we didn't have the lease available
+ * we did it the first time.
+ */
+ option_state_allocate(&tmp_options, MDL);
+ execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
+ reply->packet->options, tmp_options,
+ &global_scope, root_group, NULL,
+ on_star);
+ if (tmp_options != NULL) {
+ option_state_dereference(&tmp_options, MDL);
+ }
+
/*
* Bring configured options into the root packet level cache - start
* with the lease's closest enclosing group (passed in by the caller
*/
execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
reply->packet->options, reply->opt_state,
- scope, group, root_group);
+ scope, group, root_group, on_star);
/*
* If there is a host record, over-ride with values configured there,
execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
reply->packet->options,
reply->opt_state, scope,
- reply->host->group, group);
+ reply->host->group, group,
+ on_star);
/* Determine valid lifetime. */
if (reply->client_valid == 0)
/* Bring a copy of the relevant options into the IA scope. */
execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
reply->packet->options, reply->reply_ia,
- scope, group, root_group);
+ scope, group, root_group, NULL);
/*
* And bring in host record configuration, if any, but not to overlap
execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
reply->packet->options,
reply->reply_ia, scope,
- reply->host->group, group);
+ reply->host->group, group, NULL);
cleanup:
if (data.data != NULL)
/* Commit 'hard' bindings. */
renew_lease6(tmp->ipv6_pool, tmp);
schedule_lease_timeout(tmp->ipv6_pool);
+
+ /* If we have anything to do on commit do it now */
+ if (tmp->on_star.on_commit != NULL) {
+ execute_statements(NULL, reply->packet,
+ NULL, NULL,
+ reply->packet->options,
+ reply->opt_state,
+ &reply->lease->scope,
+ tmp->on_star.on_commit,
+ &tmp->on_star);
+ executable_statement_dereference
+ (&tmp->on_star.on_commit, MDL);
+ }
}
/* Remove any old ia from the hash. */
write_ia(reply->ia);
}
+ /*
+ * If this would be a hard binding for a static lease
+ * run any commit statements that we have
+ */
+ if ((status != ISC_R_CANCELED) && reply->static_prefixes != 0 &&
+ (reply->buf.reply.msg_type == DHCPV6_REPLY) &&
+ (reply->on_star.on_commit != NULL)) {
+ execute_statements(NULL, reply->packet, NULL, NULL,
+ reply->packet->options, reply->opt_state,
+ NULL, reply->on_star.on_commit, NULL);
+ executable_statement_dereference
+ (&reply->on_star.on_commit, MDL);
+ }
+
cleanup:
if (packet_ia != NULL)
option_state_dereference(&packet_ia, MDL);
ia_dereference(&reply->old_ia, MDL);
if (reply->lease != NULL)
iasubopt_dereference(&reply->lease, MDL);
+ if (reply->on_star.on_expiry != NULL)
+ executable_statement_dereference
+ (&reply->on_star.on_expiry, MDL);
+ if (reply->on_star.on_release != NULL)
+ executable_statement_dereference
+ (&reply->on_star.on_release, MDL);
/*
* ISC_R_CANCELED is a status code used by the prefix processing to
isc_result_t status = ISC_R_SUCCESS;
struct data_string data;
struct option_cache *oc;
+ struct option_state *tmp_options = NULL;
+ struct on_star *on_star;
/* Initialize values we will cleanup. */
memset(&data, 0, sizeof(data));
+ /*
+ * Find the proper on_star block to use. We use the
+ * one in the lease if we have a lease or the one in
+ * the reply if we don't have a lease because this is
+ * a static instance
+ */
+ if (reply->lease) {
+ on_star = &reply->lease->on_star;
+ } else {
+ on_star = &reply->on_star;
+ }
+
+ /*
+ * Bring in the root configuration. We only do this to bring
+ * in the on * statements, as we didn't have the lease available
+ * we we did it the first time.
+ */
+ option_state_allocate(&tmp_options, MDL);
+ execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
+ reply->packet->options, tmp_options,
+ &global_scope, root_group, NULL,
+ on_star);
+ if (tmp_options != NULL) {
+ option_state_dereference(&tmp_options, MDL);
+ }
+
/*
* Bring configured options into the root packet level cache - start
* with the lease's closest enclosing group (passed in by the caller
*/
execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
reply->packet->options, reply->opt_state,
- scope, group, root_group);
+ scope, group, root_group, on_star);
/*
* If there is a host record, over-ride with values configured there,
execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
reply->packet->options,
reply->opt_state, scope,
- reply->host->group, group);
+ reply->host->group, group,
+ on_star);
/* Determine valid lifetime. */
if (reply->client_valid == 0)
/* Bring a copy of the relevant options into the IA_PD scope. */
execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
reply->packet->options, reply->reply_ia,
- scope, group, root_group);
+ scope, group, root_group, NULL);
/*
* And bring in host record configuration, if any, but not to overlap
execute_statements_in_scope(NULL, reply->packet, NULL, NULL,
reply->packet->options,
reply->reply_ia, scope,
- reply->host->group, group);
+ reply->host->group, group, NULL);
cleanup:
if (data.data != NULL)
}
execute_statements_in_scope(NULL, packet, NULL, NULL,
packet->options, opt_state,
- &global_scope, root_group, NULL);
+ &global_scope, root_group, NULL, NULL);
/*
* RFC 3315, section 18.2.7 tells us which options to include.
}
execute_statements_in_scope(NULL, packet, NULL, NULL,
packet->options, opt_state,
- &global_scope, root_group, NULL);
+ &global_scope, root_group, NULL, NULL);
/*
* Loop through the IA_PD reported by the client, and deal with
options = NULL;
option_state_allocate (&options, MDL);
- execute_statements_in_scope ((struct binding_value **) NULL,
- (struct packet *) NULL, (struct lease *) NULL,
- (struct client_state *) NULL, (struct option_state *) NULL,
- options, &global_scope, root_group, (struct group *) NULL);
+ execute_statements_in_scope (NULL, NULL, NULL, NULL, NULL
+ options, &global_scope, root_group,
+ NULL, NULL);
ldap_server = _do_lookup_dhcp_string_option (options, SV_LDAP_SERVER);
ldap_dhcp_server_cn = _do_lookup_dhcp_string_option (options,
comp -> client_hostname = lease -> client_hostname;
lease -> client_hostname = (char *)0;
- if (lease -> on_expiry) {
- if (comp -> on_expiry)
- executable_statement_dereference (&comp -> on_expiry,
- MDL);
- executable_statement_reference (&comp -> on_expiry,
- lease -> on_expiry,
+ if (lease->on_star.on_expiry) {
+ if (comp->on_star.on_expiry)
+ executable_statement_dereference
+ (&comp->on_star.on_expiry, MDL);
+ executable_statement_reference (&comp->on_star.on_expiry,
+ lease->on_star.on_expiry,
MDL);
}
- if (lease -> on_commit) {
- if (comp -> on_commit)
- executable_statement_dereference (&comp -> on_commit,
- MDL);
- executable_statement_reference (&comp -> on_commit,
- lease -> on_commit,
+ if (lease->on_star.on_commit) {
+ if (comp->on_star.on_commit)
+ executable_statement_dereference
+ (&comp->on_star.on_commit, MDL);
+ executable_statement_reference (&comp->on_star.on_commit,
+ lease->on_star.on_commit,
MDL);
}
- if (lease -> on_release) {
- if (comp -> on_release)
- executable_statement_dereference (&comp -> on_release,
- MDL);
- executable_statement_reference (&comp -> on_release,
- lease -> on_release, MDL);
+ if (lease->on_star.on_release) {
+ if (comp->on_star.on_release)
+ executable_statement_dereference
+ (&comp->on_star.on_release, MDL);
+ executable_statement_reference (&comp->on_star.on_release,
+ lease->on_star.on_release,
+ MDL);
}
/* Record the lease in the uid hash if necessary. */
#if defined (NSUPDATE)
(void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
#endif
- if (lease -> on_expiry) {
- execute_statements ((struct binding_value **)0,
- (struct packet *)0, lease,
- (struct client_state *)0,
- (struct option_state *)0,
- (struct option_state *)0, /* XXX */
- &lease -> scope,
- lease -> on_expiry);
- if (lease -> on_expiry)
+ if (lease->on_star.on_expiry) {
+ execute_statements(NULL, NULL, lease,
+ NULL, NULL, NULL,
+ &lease->scope,
+ lease->on_star.on_expiry,
+ NULL);
+ if (lease->on_star.on_expiry)
executable_statement_dereference
- (&lease -> on_expiry, MDL);
+ (&lease->on_star.on_expiry, MDL);
}
/* No sense releasing a lease after it's expired. */
- if (lease -> on_release)
- executable_statement_dereference (&lease -> on_release,
- MDL);
+ if (lease->on_star.on_release)
+ executable_statement_dereference
+ (&lease->on_star.on_release, MDL);
/* Get rid of client-specific bindings that are only
correct when the lease is active. */
if (lease -> billing_class)
*/
(void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
#endif
- if (lease -> on_release) {
- execute_statements ((struct binding_value **)0,
- (struct packet *)0, lease,
- (struct client_state *)0,
- (struct option_state *)0,
- (struct option_state *)0, /* XXX */
- &lease -> scope,
- lease -> on_release);
- executable_statement_dereference (&lease -> on_release,
- MDL);
+ if (lease->on_star.on_release) {
+ execute_statements(NULL, NULL, lease,
+ NULL, NULL, NULL,
+ &lease->scope,
+ lease->on_star.on_release,
+ NULL);
+ executable_statement_dereference
+ (&lease->on_star.on_release, MDL);
}
/* A released lease can't expire. */
- if (lease -> on_expiry)
- executable_statement_dereference (&lease -> on_expiry,
- MDL);
+ if (lease->on_star.on_expiry)
+ executable_statement_dereference
+ (&lease->on_star.on_expiry, MDL);
/* Get rid of client-specific bindings that are only
correct when the lease is active. */
class_reference (< -> billing_class,
lease -> billing_class, file, line);
lt -> hardware_addr = lease -> hardware_addr;
- if (lease -> on_expiry)
- executable_statement_reference (< -> on_expiry,
- lease -> on_expiry,
+ if (lease->on_star.on_expiry)
+ executable_statement_reference (<->on_star.on_expiry,
+ lease->on_star.on_expiry,
file, line);
- if (lease -> on_commit)
- executable_statement_reference (< -> on_commit,
- lease -> on_commit,
+ if (lease->on_star.on_commit)
+ executable_statement_reference (<->on_star.on_commit,
+ lease->on_star.on_commit,
file, line);
- if (lease -> on_release)
- executable_statement_reference (< -> on_release,
- lease -> on_release,
+ if (lease->on_star.on_release)
+ executable_statement_reference (<->on_star.on_release,
+ lease->on_star.on_release,
file, line);
lt->flags = lease->flags;
lt->tstp = lease->tstp;
#if defined (NSUPDATE)
(void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
#endif
- if (lease -> on_release) {
- execute_statements ((struct binding_value **)0,
- packet, lease, (struct client_state *)0,
- packet -> options,
- (struct option_state *)0, /* XXX */
- &lease -> scope, lease -> on_release);
- if (lease -> on_release)
- executable_statement_dereference (&lease -> on_release,
- MDL);
+ if (lease->on_star.on_release) {
+ execute_statements (NULL, packet, lease,
+ NULL, packet->options,
+ NULL, &lease->scope,
+ lease->on_star.on_release, NULL);
+ if (lease->on_star.on_release)
+ executable_statement_dereference
+ (&lease->on_star.on_release, MDL);
}
/* We do either the on_release or the on_expiry events, but
not both (it's possible that they could be the same,
in any case). */
- if (lease -> on_expiry)
- executable_statement_dereference (&lease -> on_expiry, MDL);
+ if (lease->on_star.on_expiry)
+ executable_statement_dereference
+ (&lease->on_star.on_expiry, MDL);
if (lease -> binding_state != FTS_FREE &&
lease -> binding_state != FTS_BACKUP &&
lease -> binding_state != FTS_RELEASED &&
lease -> binding_state != FTS_EXPIRED &&
lease -> binding_state != FTS_RESET) {
- if (lease -> on_commit)
- executable_statement_dereference (&lease -> on_commit,
- MDL);
+ if (lease->on_star.on_commit)
+ executable_statement_dereference
+ (&lease->on_star.on_commit, MDL);
/* Blow away any bindings. */
if (lease -> scope)
/*
- * Copyright (C) 2007-2012 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2007-2013 by Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
if (tmp->scope != NULL) {
binding_scope_dereference(&tmp->scope, file, line);
}
+
+ if (tmp->on_star.on_expiry != NULL) {
+ executable_statement_dereference
+ (&tmp->on_star.on_expiry, MDL);
+ }
+ if (tmp->on_star.on_commit != NULL) {
+ executable_statement_dereference
+ (&tmp->on_star.on_commit, MDL);
+ }
+ if (tmp->on_star.on_release != NULL) {
+ executable_statement_dereference
+ (&tmp->on_star.on_release, MDL);
+ }
+
dfree(tmp, file, line);
}
old_heap_index = lease->heap_index;
insert_result = isc_heap_insert(pool->inactive_timeouts, lease);
if (insert_result == ISC_R_SUCCESS) {
+ /*
+ * Handle expire and release statements
+ * To get here we must be active and have done a commit so
+ * we should run the proper statements if they exist, though
+ * that will change when we remove the inactive heap.
+ * In addition we get rid of the references for both as we
+ * can only do one (expire or release) on a lease
+ */
+ if (lease->on_star.on_expiry != NULL) {
+ if (state == FTS_EXPIRED) {
+ execute_statements(NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ &lease->scope,
+ lease->on_star.on_expiry,
+ &lease->on_star);
+ }
+ executable_statement_dereference
+ (&lease->on_star.on_expiry, MDL);
+ }
+
+ if (lease->on_star.on_release != NULL) {
+ if (state == FTS_RELEASED) {
+ execute_statements(NULL, NULL, NULL,
+ NULL, NULL, NULL,
+ &lease->scope,
+ lease->on_star.on_release,
+ &lease->on_star);
+ }
+ executable_statement_dereference
+ (&lease->on_star.on_release, MDL);
+ }
+
#if defined (NSUPDATE)
/* Process events upon expiration. */
if (pool->pool_type != D6O_IA_PD) {
{
struct lease *lease;
- if (h -> type != dhcp_type_lease)
+ if (h->type != dhcp_type_lease)
return DHCP_R_INVALIDARG;
lease = (struct lease *)h;
- if (lease -> uid)
+ if (lease-> uid)
uid_hash_delete (lease);
hw_hash_delete (lease);
- if (lease -> on_release)
- executable_statement_dereference (&lease -> on_release,
+ if (lease->on_star.on_release)
+ executable_statement_dereference (&lease->on_star.on_release,
file, line);
- if (lease -> on_expiry)
- executable_statement_dereference (&lease -> on_expiry,
+ if (lease->on_star.on_expiry)
+ executable_statement_dereference (&lease->on_star.on_expiry,
file, line);
- if (lease -> on_commit)
- executable_statement_dereference (&lease -> on_commit,
+ if (lease->on_star.on_commit)
+ executable_statement_dereference (&lease->on_star.on_commit,
file, line);
- if (lease -> scope)
- binding_scope_dereference (&lease -> scope, file, line);
+ if (lease->scope)
+ binding_scope_dereference (&lease->scope, file, line);
- if (lease -> agent_options)
- option_chain_head_dereference (&lease -> agent_options,
+ if (lease->agent_options)
+ option_chain_head_dereference (&lease->agent_options,
file, line);
- if (lease -> uid && lease -> uid != lease -> uid_buf) {
- dfree (lease -> uid, MDL);
- lease -> uid = &lease -> uid_buf [0];
- lease -> uid_len = 0;
+ if (lease->uid && lease->uid != lease->uid_buf) {
+ dfree (lease->uid, MDL);
+ lease->uid = &lease->uid_buf [0];
+ lease->uid_len = 0;
}
- if (lease -> client_hostname) {
- dfree (lease -> client_hostname, MDL);
- lease -> client_hostname = (char *)0;
+ if (lease->client_hostname) {
+ dfree (lease->client_hostname, MDL);
+ lease->client_hostname = (char *)0;
}
- if (lease -> host)
- host_dereference (&lease -> host, file, line);
- if (lease -> subnet)
- subnet_dereference (&lease -> subnet, file, line);
- if (lease -> pool)
- pool_dereference (&lease -> pool, file, line);
+ if (lease->host)
+ host_dereference (&lease->host, file, line);
+ if (lease->subnet)
+ subnet_dereference (&lease->subnet, file, line);
+ if (lease->pool)
+ pool_dereference (&lease->pool, file, line);
- if (lease -> state) {
- free_lease_state (lease -> state, file, line);
- lease -> state = (struct lease_state *)0;
+ if (lease->state) {
+ free_lease_state (lease->state, file, line);
+ lease->state = (struct lease_state *)0;
cancel_timeout (lease_ping_timeout, lease);
--outstanding_pings; /* XXX */
}
- if (lease -> billing_class)
+ if (lease->billing_class)
class_dereference
- (&lease -> billing_class, file, line);
+ (&lease->billing_class, file, line);
#if defined (DEBUG_MEMORY_LEAKAGE) || \
defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
/* XXX we should never be destroying a lease with a next
XXX pointer except on exit... */
- if (lease -> next)
- lease_dereference (&lease -> next, file, line);
- if (lease -> n_hw)
- lease_dereference (&lease -> n_hw, file, line);
- if (lease -> n_uid)
- lease_dereference (&lease -> n_uid, file, line);
- if (lease -> next_pending)
- lease_dereference (&lease -> next_pending, file, line);
+ if (lease->next)
+ lease_dereference (&lease->next, file, line);
+ if (lease->n_hw)
+ lease_dereference (&lease->n_hw, file, line);
+ if (lease->n_uid)
+ lease_dereference (&lease->n_uid, file, line);
+ if (lease->next_pending)
+ lease_dereference (&lease->next_pending, file, line);
#endif
return ISC_R_SUCCESS;