mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-22 09:57:20 +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:
parent
8cd88e202b
commit
a7341359cc
3
RELNOTES
3
RELNOTES
@ -69,6 +69,9 @@ work on other platforms. Please report any problems and suggested fixes to
|
||||
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.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* 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
|
||||
@ -4947,7 +4947,7 @@ make_client6_options(struct client_state *client, struct option_state **op,
|
||||
lease ? lease->options : NULL,
|
||||
*op, &global_scope,
|
||||
client->config->on_transmission,
|
||||
NULL);
|
||||
NULL, NULL);
|
||||
|
||||
/* Rapid-commit is only for SOLICITs. */
|
||||
if (message != DHCPV6_SOLICIT)
|
||||
|
@ -1727,13 +1727,10 @@ struct client_lease *packet_to_lease (packet, client)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -2377,14 +2374,12 @@ make_client_options(struct client_state *client, struct client_lease *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)
|
||||
|
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:
|
||||
|
@ -618,7 +618,7 @@ int evaluate_expression (result, packet, lease, client_state,
|
||||
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)
|
||||
|
@ -497,6 +497,16 @@ typedef u_int8_t binding_state_t;
|
||||
/* 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;
|
||||
@ -513,9 +523,8 @@ struct lease {
|
||||
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;
|
||||
@ -1503,6 +1512,8 @@ struct iasubopt {
|
||||
*/
|
||||
struct dhcp_ddns_cb *ddns_cb;
|
||||
|
||||
/* space for the on * executable statements */
|
||||
struct on_star on_star;
|
||||
};
|
||||
|
||||
struct ia_xx {
|
||||
@ -2079,7 +2090,8 @@ int evaluate_data_expression (struct data_string *,
|
||||
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 *,
|
||||
@ -2944,14 +2956,16 @@ int execute_statements (struct binding_value **result,
|
||||
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);
|
||||
|
@ -3,7 +3,7 @@
|
||||
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
|
||||
*
|
||||
@ -160,28 +160,26 @@ void bootp (packet)
|
||||
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. */
|
||||
@ -340,10 +338,9 @@ void bootp (packet)
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
@ -3,7 +3,7 @@
|
||||
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
|
||||
*
|
||||
@ -69,10 +69,8 @@ void classification_setup ()
|
||||
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)
|
||||
|
@ -3248,19 +3248,19 @@ int parse_lease_declaration (struct lease **lp, struct parse *cfile)
|
||||
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;
|
||||
@ -3400,31 +3400,31 @@ int parse_lease_declaration (struct lease **lp, struct parse *cfile)
|
||||
|
||||
/* 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);
|
||||
@ -4146,9 +4146,11 @@ parse_ia_na_declaration(struct parse *cfile) {
|
||||
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.");
|
||||
@ -4409,6 +4411,41 @@ parse_ia_na_declaration(struct parse *cfile) {
|
||||
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, "
|
||||
@ -4446,6 +4483,30 @@ parse_ia_na_declaration(struct parse *cfile) {
|
||||
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,
|
||||
@ -4527,9 +4588,11 @@ parse_ia_ta_declaration(struct parse *cfile) {
|
||||
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.");
|
||||
@ -4790,6 +4853,41 @@ parse_ia_ta_declaration(struct parse *cfile) {
|
||||
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, "
|
||||
@ -4827,6 +4925,30 @@ parse_ia_ta_declaration(struct parse *cfile) {
|
||||
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,
|
||||
@ -4909,9 +5031,11 @@ parse_ia_pd_declaration(struct parse *cfile) {
|
||||
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.");
|
||||
@ -5172,6 +5296,41 @@ parse_ia_pd_declaration(struct parse *cfile) {
|
||||
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, "
|
||||
@ -5209,6 +5368,30 @@ parse_ia_pd_declaration(struct parse *cfile) {
|
||||
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,
|
||||
|
37
server/db.c
37
server/db.c
@ -3,7 +3,8 @@
|
||||
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
|
||||
@ -264,21 +265,22 @@ int write_lease (lease)
|
||||
} 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)
|
||||
@ -642,6 +644,29 @@ write_ia(const struct ia_xx *ia) {
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
/*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
@ -275,16 +275,20 @@ ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
|
||||
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;
|
||||
}
|
||||
|
140
server/dhcp.c
140
server/dhcp.c
@ -907,21 +907,18 @@ void dhcpdecline (packet, ms_nulltp)
|
||||
|
||||
/* 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. */
|
||||
@ -1082,20 +1079,19 @@ void dhcpinform (packet, ms_nulltp)
|
||||
|
||||
/* 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. */
|
||||
@ -1604,47 +1600,45 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
|
||||
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,
|
||||
@ -1829,7 +1823,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
|
||||
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;
|
||||
@ -1844,15 +1839,13 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
|
||||
/* 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. */
|
||||
@ -2485,15 +2478,13 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
|
||||
|
||||
/* 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
|
||||
@ -4593,13 +4584,13 @@ setup_server_source_address(struct in_addr *from,
|
||||
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 */
|
||||
@ -4608,7 +4599,8 @@ setup_server_source_address(struct in_addr *from,
|
||||
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
|
||||
|
@ -883,14 +883,9 @@ void postconf_initialization (int quiet)
|
||||
/* 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 &&
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@ -204,26 +204,16 @@ dhcpleasequery(struct packet *packet, int ms_nulltp) {
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1093,7 +1083,7 @@ dhcpv6_leasequery(struct data_string *reply_ret, struct packet *packet) {
|
||||
}
|
||||
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;
|
||||
|
||||
|
175
server/dhcpv6.c
175
server/dhcpv6.c
@ -81,6 +81,9 @@ struct reply_state {
|
||||
/* 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;
|
||||
@ -230,7 +233,8 @@ set_server_duid_from_option(void) {
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -820,7 +824,7 @@ start_reply(struct packet *packet,
|
||||
}
|
||||
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.
|
||||
@ -1405,16 +1409,18 @@ lease_to_client(struct data_string *reply_ret,
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1841,6 +1847,19 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
|
||||
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.
|
||||
@ -1878,6 +1897,20 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
|
||||
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);
|
||||
@ -1897,6 +1930,12 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
|
||||
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
|
||||
@ -2499,6 +2538,19 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
|
||||
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.
|
||||
@ -2832,10 +2884,38 @@ reply_process_is_addressed(struct reply_state *reply,
|
||||
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
|
||||
@ -2843,7 +2923,7 @@ reply_process_is_addressed(struct reply_state *reply,
|
||||
*/
|
||||
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,
|
||||
@ -2854,7 +2934,8 @@ reply_process_is_addressed(struct reply_state *reply,
|
||||
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)
|
||||
@ -2960,7 +3041,7 @@ reply_process_is_addressed(struct reply_state *reply,
|
||||
/* 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
|
||||
@ -2970,7 +3051,7 @@ reply_process_is_addressed(struct reply_state *reply,
|
||||
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)
|
||||
@ -3368,6 +3449,19 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
|
||||
/* 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. */
|
||||
@ -3388,6 +3482,20 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
|
||||
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);
|
||||
@ -3403,6 +3511,12 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
|
||||
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
|
||||
@ -3833,10 +3947,38 @@ reply_process_is_prefixed(struct reply_state *reply,
|
||||
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
|
||||
@ -3844,7 +3986,7 @@ reply_process_is_prefixed(struct reply_state *reply,
|
||||
*/
|
||||
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,
|
||||
@ -3855,7 +3997,8 @@ reply_process_is_prefixed(struct reply_state *reply,
|
||||
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)
|
||||
@ -3946,7 +4089,7 @@ reply_process_is_prefixed(struct reply_state *reply,
|
||||
/* 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
|
||||
@ -3956,7 +4099,7 @@ reply_process_is_prefixed(struct reply_state *reply,
|
||||
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)
|
||||
@ -4683,7 +4826,7 @@ iterate_over_ia_na(struct data_string *reply_ret,
|
||||
}
|
||||
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.
|
||||
@ -5197,7 +5340,7 @@ iterate_over_ia_pd(struct data_string *reply_ret,
|
||||
}
|
||||
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
|
||||
|
@ -628,10 +628,9 @@ ldap_start (void)
|
||||
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,
|
||||
|
131
server/mdb.c
131
server/mdb.c
@ -1191,28 +1191,29 @@ int supersede_lease (comp, lease, commit, propogate, pimmediate)
|
||||
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. */
|
||||
@ -1455,23 +1456,21 @@ void make_binding_state_transition (struct lease *lease)
|
||||
#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)
|
||||
@ -1521,22 +1520,20 @@ void make_binding_state_transition (struct lease *lease)
|
||||
*/
|
||||
(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. */
|
||||
@ -1656,17 +1653,17 @@ int lease_copy (struct lease **lp,
|
||||
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;
|
||||
@ -1691,31 +1688,31 @@ void release_lease (lease, packet)
|
||||
#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)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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
|
||||
@ -197,6 +197,20 @@ iasubopt_dereference(struct iasubopt **iasubopt, const char *file, int line) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1309,6 +1323,38 @@ move_lease_to_inactive(struct ipv6_pool *pool, struct iasubopt *lease,
|
||||
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) {
|
||||
|
@ -408,71 +408,71 @@ isc_result_t dhcp_lease_destroy (omapi_object_t *h, const char *file, int line)
|
||||
{
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user