2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-31 22:35:25 +00:00

Massive rototill to support some new DDNS features.

This commit is contained in:
Ted Lemon
1999-07-16 21:34:14 +00:00
parent 343729b9b1
commit 79a65726f0
10 changed files with 515 additions and 121 deletions

View File

@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: alloc.c,v 1.30 1999/05/27 12:38:05 mellon Exp $ Copyright (c) 1995, 1996, 1998 The Internet Software Consortium. All rights reserved.\n";
"$Id: alloc.c,v 1.31 1999/07/16 21:33:57 mellon Exp $ Copyright (c) 1995, 1996, 1998 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -777,3 +777,69 @@ int option_state_dereference (ptr, name)
dfree (options, name);
return 1;
}
int executable_statement_allocate (ptr, name)
struct executable_statement **ptr;
char *name;
{
struct executable_statement *bp;
bp = dmalloc (sizeof *bp, name);
if (!bp)
return 0;
memset (bp, 0, sizeof *bp);
bp -> refcnt = 0;
return executable_statement_reference (ptr, bp, name);
}
int executable_statement_reference (ptr, bp, name)
struct executable_statement **ptr;
struct executable_statement *bp;
char *name;
{
if (!ptr) {
log_error ("Null ptr in executable_statement_reference: %s",
name);
#if defined (POINTER_DEBUG)
abort ();
#else
return 0;
#endif
}
if (*ptr) {
log_error ("Nonnull ptr in executable_statement_reference: %s",
name);
#if defined (POINTER_DEBUG)
abort ();
#else
*ptr = (struct executable_statement *)0;
#endif
}
*ptr = bp;
bp -> refcnt++;
return 1;
}
int executable_statement_dereference (ptr, name)
struct executable_statement **ptr;
char *name;
{
struct executable_statement *bp;
if (!ptr || !*ptr) {
log_error ("Null ptr in executable_statement_dereference: %s",
name);
#if defined (POINTER_DEBUG)
abort ();
#else
return 0;
#endif
}
(*ptr) -> refcnt--;
if (!(*ptr) -> refcnt)
dfree ((*ptr), name);
*ptr = (struct executable_statement *)0;
return 1;
}

View File

@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: conflex.c,v 1.48 1999/07/06 20:41:22 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
"$Id: conflex.c,v 1.49 1999/07/16 21:33:58 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -384,8 +384,12 @@ static enum dhcp_token intern (atom, dfv)
return BOOLEAN;
break;
case 'c':
if (!strcasecmp (atom + 1, "ommit"))
return COMMIT;
if (!strcasecmp (atom + 1, "ode"))
return CODE;
if (!strcasecmp (atom + 1, "onfig-option"))
return CONFIG_OPTION;
if (!strcasecmp (atom + 1, "heck"))
return CHECK;
if (!strcasecmp (atom + 1, "lass"))
@@ -436,6 +440,8 @@ static enum dhcp_token intern (atom, dfv)
}
break;
case 'e':
if (!strcasecmp (atom + 1, "xpiry"))
return EXPIRY;
if (isascii (atom [1]) && tolower (atom [1]) == 'x') {
if (!strcasecmp (atom + 2, "tract-int"))
return EXTRACT_INT;
@@ -477,6 +483,8 @@ static enum dhcp_token intern (atom, dfv)
case 'h':
if (!strcasecmp (atom + 1, "ost"))
return HOST;
if (!strcasecmp (atom + 1, "ost-decl-name"))
return HOST_DECL_NAME;
if (!strcasecmp (atom + 1, "ardware"))
return HARDWARE;
if (!strcasecmp (atom + 1, "ostname"))
@@ -553,6 +561,8 @@ static enum dhcp_token intern (atom, dfv)
case 'o':
if (!strcasecmp (atom + 1, "r"))
return OR;
if (!strcasecmp (atom + 1, "n"))
return ON;
if (!strcasecmp (atom + 1, "ption"))
return OPTION;
if (!strcasecmp (atom + 1, "ne-lease-per-client"))
@@ -583,6 +593,8 @@ static enum dhcp_token intern (atom, dfv)
return PORT;
if (!strcasecmp (atom + 1, "otential-conflict"))
return POTENTIAL_CONFLICT;
if (!strcasecmp (atom + 1, "ick-first-value"))
return PICK_FIRST_VALUE;
break;
case 'r':
if (!strcasecmp (atom + 1, "ange"))
@@ -607,6 +619,8 @@ static enum dhcp_token intern (atom, dfv)
return REJECT;
if (!strcasecmp (atom + 1, "everse"))
return REVERSE;
if (!strcasecmp (atom + 1, "elease"))
return RELEASE;
break;
case 's':
if (!strcasecmp (atom + 1, "igned"))

View File

@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: execute.c,v 1.10 1999/07/02 20:57:24 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
"$Id: execute.c,v 1.11 1999/07/16 21:33:58 mellon Exp $ Copyright (c) 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -43,6 +43,46 @@ int execute_statements (packet, lease, in_options, out_options, statements)
for (r = statements; r; r = r -> next) {
switch (r -> op) {
case statements_statement:
log_info ("exec: statements");
if (!execute_statements (packet, lease,
in_options, out_options,
r -> data.statements.car))
return 0;
if (!execute_statements (packet, lease,
in_options, out_options,
r -> data.statements.cdr))
return 0;
break;
case on_statement:
if (lease) {
struct executable_statement **d;
switch (r -> data.on.evtype) {
case expiry:
d = &lease -> on_expiry;
break;
case commit:
d = &lease -> on_commit;
break;
case release:
d = &lease -> on_release;
break;
default:
log_fatal ("unknown event type %d %s",
r -> data.on.evtype,
"in on statement.");
break;
}
if (*d)
executable_statement_dereference
(d, "execute_statements");
executable_statement_reference
(d, r -> data.on.statements,
"execute_statements");
}
break;
case if_statement:
status = evaluate_boolean_expression
(&result, packet,

View File

@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: parse.c,v 1.28 1999/07/06 20:41:22 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
"$Id: parse.c,v 1.29 1999/07/16 21:33:59 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -1151,27 +1151,29 @@ int parse_cshl (data, cfile)
* APPEND option-parameter SEMI
*/
struct executable_statement *parse_executable_statements (cfile, lose)
int parse_executable_statements (statements, cfile, lose)
struct executable_statement **statements;
FILE *cfile;
int *lose;
{
struct executable_statement *head, **next;
struct executable_statement **next;
next = &head;
while ((*next = parse_executable_statement (cfile, lose)))
next = statements;
while (parse_executable_statement (next, cfile, lose))
next = &((*next) -> next);
if (!*lose)
return head;
return (struct executable_statement *)0;
return 1;
return 0;
}
struct executable_statement *parse_executable_statement (cfile, lose)
int parse_executable_statement (result, cfile, lose)
struct executable_statement **result;
FILE *cfile;
int *lose;
{
enum dhcp_token token;
char *val;
struct executable_statement *stmt, base;
struct executable_statement base;
struct class *cta;
struct option *option;
struct option_cache *cache;
@@ -1180,8 +1182,8 @@ struct executable_statement *parse_executable_statement (cfile, lose)
switch (token) {
case IF:
next_token (&val, cfile);
stmt = parse_if_statement (cfile, lose);
return stmt;
return parse_if_statement (result, cfile, lose);
case TOKEN_ADD:
token = next_token (&val, cfile);
token = next_token (&val, cfile);
@@ -1189,39 +1191,43 @@ struct executable_statement *parse_executable_statement (cfile, lose)
parse_warn ("expecting class name.");
skip_to_semi (cfile);
*lose = 1;
return (struct executable_statement *)0;
return 0;
}
cta = find_class (val);
if (!cta) {
parse_warn ("unknown class %s.", val);
skip_to_semi (cfile);
*lose = 1;
return (struct executable_statement *)0;
return 0;
}
if (!parse_semi (cfile)) {
*lose = 1;
return (struct executable_statement *)0;
return 0;
}
memset (&base, 0, sizeof base);
base.op = add_statement;
base.data.add = cta;
if (!executable_statement_allocate
(result, "parse_executable_statement"))
log_fatal ("no memory for new statement.");
(*result) -> op = add_statement;
(*result) -> data.add = cta;
break;
case BREAK:
token = next_token (&val, cfile);
if (!parse_semi (cfile)) {
*lose = 1;
return (struct executable_statement *)0;
return 0;
}
memset (&base, 0, sizeof base);
base.op = break_statement;
if (!executable_statement_allocate
(result, "parse_executable_statement"))
log_fatal ("no memory for new statement.");
(*result) -> op = break_statement;
break;
case SEND:
*lose = 1;
parse_warn ("send not appropriate here.");
skip_to_semi (cfile);
return (struct executable_statement *)0;
return 0;
case SUPERSEDE:
case OPTION:
@@ -1229,9 +1235,9 @@ struct executable_statement *parse_executable_statement (cfile, lose)
option = parse_option_name (cfile, 0);
if (!option) {
*lose = 1;
return (struct executable_statement *)0;
return 0;
}
return parse_option_statement (cfile, 1, option,
return parse_option_statement (result, cfile, 1, option,
supersede_option_statement);
case ALLOW:
@@ -1240,10 +1246,12 @@ struct executable_statement *parse_executable_statement (cfile, lose)
cache = (struct option_cache *)0;
if (!parse_allow_deny (&cache, cfile,
token == ALLOW ? 1 : 0))
return (struct executable_statement *)0;
memset (&base, 0, sizeof base);
base.op = supersede_option_statement;
base.data.option = cache;
return 0;
if (!executable_statement_allocate
(result, "parse_executable_statement"))
log_fatal ("no memory for new statement.");
(*result) -> op = supersede_option_statement;
(*result) -> data.option = cache;
break;
case DEFAULT:
@@ -1251,9 +1259,9 @@ struct executable_statement *parse_executable_statement (cfile, lose)
option = parse_option_name (cfile, 0);
if (!option) {
*lose = 1;
return (struct executable_statement *)0;
return 0;
}
return parse_option_statement (cfile, 1, option,
return parse_option_statement (result, cfile, 1, option,
default_option_statement);
case PREPEND:
@@ -1261,9 +1269,9 @@ struct executable_statement *parse_executable_statement (cfile, lose)
option = parse_option_name (cfile, 0);
if (!option) {
*lose = 1;
return (struct executable_statement *)0;
return 0;
}
return parse_option_statement (cfile, 1, option,
return parse_option_statement (result, cfile, 1, option,
prepend_option_statement);
case APPEND:
@@ -1271,23 +1279,96 @@ struct executable_statement *parse_executable_statement (cfile, lose)
option = parse_option_name (cfile, 0);
if (!option) {
*lose = 1;
return (struct executable_statement *)0;
return 0;
}
return parse_option_statement (cfile, 1, option,
return parse_option_statement (result, cfile, 1, option,
append_option_statement);
case ON:
token = next_token (&val, cfile);
return parse_on_statement (result, cfile, lose);
default:
*lose = 0;
return (struct executable_statement *)0;
return 0;
}
stmt = ((struct executable_statement *)
dmalloc (sizeof (struct executable_statement),
"parse_executable_statement"));
if (!stmt)
return 1;
}
/*
* on-statement :== event-type LBRACE executable-statements RBRACE
*
* event-type :== EXPIRY | COMMIT | RELEASE
*/
int parse_on_statement (result, cfile, lose)
struct executable_statement **result;
FILE *cfile;
int *lose;
{
enum dhcp_token token;
char *val;
if (!executable_statement_allocate (result,
"parse_executable_statement"))
log_fatal ("no memory for new statement.");
*stmt = base;
return stmt;
token = next_token (&val, cfile);
switch (token) {
case EXPIRY:
(*result) -> data.on.evtype = expiry;
break;
case COMMIT:
(*result) -> data.on.evtype = expiry;
break;
case RELEASE:
(*result) -> data.on.evtype = expiry;
break;
default:
parse_warn ("expecting a lease event type");
skip_to_semi (cfile);
*lose = 1;
executable_statement_dereference
(result, "parse_on_statement");
break;
}
token = next_token (&val, cfile);
if (token != LBRACE) {
parse_warn ("left brace expected.");
skip_to_semi (cfile);
*lose = 1;
executable_statement_dereference (result,
"parse_on_statement");
return 0;
}
if (!parse_executable_statements (&(*result) -> data.on.statements,
cfile, lose)) {
if (*lose) {
/* Try to even things up. */
do {
token = next_token (&val, cfile);
} while (token != EOF && token != RBRACE);
executable_statement_dereference
(result, "parse_on_statement");
return 0;
}
}
token = next_token (&val, cfile);
if (token != RBRACE) {
parse_warn ("right brace expected.");
skip_to_semi (cfile);
*lose = 1;
executable_statement_dereference
(result, "parse_on_statement");
return 0;
}
return 1;
}
/*
@@ -1300,21 +1381,26 @@ struct executable_statement *parse_executable_statement (cfile, lose)
* ELSIF if-statement
*/
struct executable_statement *parse_if_statement (cfile, lose)
int parse_if_statement (result, cfile, lose)
struct executable_statement **result;
FILE *cfile;
int *lose;
{
enum dhcp_token token;
char *val;
struct executable_statement *stmt;
struct expression *if_condition;
struct executable_statement *true, *false;
if_condition = (struct expression *)0;
if (!parse_boolean_expression (&if_condition, cfile, lose)) {
if (!executable_statement_allocate (result, "parse_if_statement"))
log_fatal ("no memory for if statement.");
(*result) -> op = if_statement;
if (!parse_boolean_expression (&(*result) -> data.ie.expr,
cfile, lose)) {
if (!*lose)
parse_warn ("boolean expression expected.");
return (struct executable_statement *)0;
executable_statement_dereference (result,
"parse_if_statement");
return 0;
}
#if defined (DEBUG_EXPRESSION_PARSE)
print_expression ("if condition", if_condition);
@@ -1324,22 +1410,30 @@ struct executable_statement *parse_if_statement (cfile, lose)
parse_warn ("left brace expected.");
skip_to_semi (cfile);
*lose = 1;
return (struct executable_statement *)0;
executable_statement_dereference (result,
"parse_if_statement");
return 0;
}
if (!parse_executable_statements (&(*result) -> data.ie.true,
cfile, lose)) {
if (*lose) {
/* Try to even things up. */
do {
token = next_token (&val, cfile);
} while (token != EOF && token != RBRACE);
executable_statement_dereference
(result, "parse_if_statement");
return 0;
}
}
true = parse_executable_statements (cfile, lose);
token = next_token (&val, cfile);
if (*lose) {
/* Try to even things up. */
do {
token = next_token (&val, cfile);
} while (token != EOF && token != RBRACE);
return (struct executable_statement *)0;
}
if (token != RBRACE) {
parse_warn ("right brace expected.");
skip_to_semi (cfile);
*lose = 1;
return (struct executable_statement *)0;
executable_statement_dereference
(result, "parse_if_statement");
return 0;
}
token = peek_token (&val, cfile);
if (token == ELSE) {
@@ -1347,46 +1441,53 @@ struct executable_statement *parse_if_statement (cfile, lose)
token = peek_token (&val, cfile);
if (token == IF) {
token = next_token (&val, cfile);
false = parse_if_statement (cfile, lose);
if (*lose)
return (struct executable_statement *)0;
if (!parse_if_statement (&(*result) -> data.ie.false,
cfile, lose)) {
if (*lose) {
return 0;
executable_statement_dereference
(result, "parse_if_statement");
}
}
} else if (token != LBRACE) {
parse_warn ("left brace or if expected.");
skip_to_semi (cfile);
*lose = 1;
return (struct executable_statement *)0;
executable_statement_dereference
(result, "parse_if_statement");
return 0;
} else {
token = next_token (&val, cfile);
false = parse_executable_statements (cfile, lose);
if (*lose)
return (struct executable_statement *)0;
if (!parse_if_statement (&(*result) -> data.ie.false,
cfile, lose)) {
executable_statement_dereference
(result, "parse_if_statement");
return 0;
}
token = next_token (&val, cfile);
if (token != RBRACE) {
parse_warn ("right brace expected.");
skip_to_semi (cfile);
*lose = 1;
return (struct executable_statement *)0;
executable_statement_dereference
(result, "parse_if_statement");
return 0;
}
}
} else if (token == ELSIF) {
token = next_token (&val, cfile);
false = parse_if_statement (cfile, lose);
if (*lose)
return (struct executable_statement *)0;
if (!parse_if_statement (&(*result) -> data.ie.false,
cfile, lose)) {
if (*lose) {
return 0;
executable_statement_dereference
(result, "parse_if_statement");
}
}
} else
false = (struct executable_statement *)0;
(*result) -> data.ie.false = (struct executable_statement *)0;
stmt = ((struct executable_statement *)
dmalloc (sizeof (struct executable_statement),
"parse_if_statement"));
if (!stmt)
log_fatal ("no memory for if statement.");
memset (stmt, 0, sizeof *stmt);
stmt -> op = if_statement;
stmt -> data.ie.expr = if_condition;
stmt -> data.ie.true = true;
stmt -> data.ie.false = false;
return stmt;
return 1;
}
/*
@@ -1486,6 +1587,7 @@ int parse_non_binary (expr, cfile, lose, context)
char *val;
struct collection *col;
struct option *option;
struct expression *nexp;
token = peek_token (&val, cfile);
@@ -1746,11 +1848,49 @@ int parse_non_binary (expr, cfile, lose, context)
goto norparen;
break;
case OPTION:
case PICK_FIRST_VALUE:
/* pick (a, b, c) actually produces an internal representation
that looks like pick (a, pick (b, pick (c, nil))). */
token = next_token (&val, cfile);
if (!(expression_allocate
(expr, "parse_expression: PICK_FIRST_VALUE")))
log_fatal ("can't allocate expression");
(*expr) -> op = expr_reverse;
token = next_token (&val, cfile);
if (token != LPAREN)
goto nolparen;
nexp = *expr;
do {
struct expression *tmp = (struct expression *)0;
if (!(parse_data_expression
(&nexp -> data.pick_first_value.car,
cfile, lose)))
goto nodata;
token = next_token (&val, cfile);
if (token == COMMA) {
if (!(expression_allocate
(&nexp -> data.pick_first_value.cdr,
"parse_expression: PICK_FIRST_VALUE")))
log_fatal ("can't allocate expr");
nexp = nexp -> data.pick_first_value.cdr;
}
} while (token == COMMA);
if (token != RPAREN)
goto norparen;
break;
case OPTION:
case CONFIG_OPTION:
if (!expression_allocate (expr, "parse_expression: OPTION"))
log_fatal ("can't allocate expression");
(*expr) -> op = expr_option;
(*expr) -> op = token == (OPTION
? expr_option
: expr_config_option);
token = next_token (&val, cfile);
(*expr) -> data.option = parse_option_name (cfile, 0);
if (!(*expr) -> data.option) {
*lose = 1;
@@ -1775,6 +1915,14 @@ int parse_non_binary (expr, cfile, lose, context)
(*expr) -> op = expr_leased_address;
break;
case HOST_DECL_NAME:
token = next_token (&val, cfile);
if (!expression_allocate (expr,
"parse_expression: HOST_DECL_NAME"))
log_fatal ("can't allocate expression");
(*expr) -> op = expr_host_decl_name;
break;
case PACKET:
token = next_token (&val, cfile);
if (!expression_allocate (expr, "parse_expression: PACKET"))
@@ -2123,8 +2271,8 @@ int parse_expression (expr, cfile, lose, context, plhs, binop)
would be painful to come up with BNF for it. However, it always
starts as above and ends in a SEMI. */
struct executable_statement *parse_option_statement (cfile, lookups,
option, op)
int parse_option_statement (result, cfile, lookups, option, op)
struct executable_statement **result;
FILE *cfile;
int lookups;
struct option *option;
@@ -2159,7 +2307,7 @@ struct executable_statement *parse_option_statement (cfile, lookups,
parse_warn ("expecting a data expression.");
skip_to_semi (cfile);
}
return (struct executable_statement *)0;
return 0;
}
/* We got a valid expression, so use it. */
@@ -2182,7 +2330,7 @@ struct executable_statement *parse_option_statement (cfile, lookups,
tmp, uniform, lookups)) {
expression_dereference
(&tmp, "parse_option_statement");
return (struct executable_statement *)0;
return 0;
}
if (tmp)
expression_dereference
@@ -2200,15 +2348,14 @@ struct executable_statement *parse_option_statement (cfile, lookups,
done:
if (!parse_semi (cfile))
return (struct executable_statement *)0;
stmt = ((struct executable_statement *)
dmalloc (sizeof *stmt, "parse_option_statement"));
memset (stmt, 0, sizeof *stmt);
stmt -> op = op;
if (expr && !option_cache (&stmt -> data.option,
return 0;
if (!executable_statement_allocate (result, "parse_option_statement"))
log_fatal ("no memory for option statement.");
(*result) -> op = op;
if (expr && !option_cache (&(*result) -> data.option,
(struct data_string *)0, expr, option))
log_fatal ("no memory for option cache");
return stmt;
return 1;
}
int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)

View File

@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: tree.c,v 1.32 1999/07/13 18:00:12 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
"$Id: tree.c,v 1.33 1999/07/16 21:33:59 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -538,6 +538,9 @@ int evaluate_boolean_expression (result, packet, options, lease, expr)
case expr_encode_int32:
case expr_binary_to_ascii:
case expr_reverse:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
case expr_leased_address:
log_error ("Data opcode in evaluate_boolean_expression: %d",
expr -> op);
@@ -651,6 +654,7 @@ int evaluate_data_expression (result, packet, options, lease, expr)
/* Extract an option. */
case expr_option:
case expr_config_option:
if (options)
s0 = ((*expr -> data.option -> universe -> get_func)
(result, expr -> data.option -> universe,
@@ -1098,7 +1102,53 @@ int evaluate_data_expression (result, packet, options, lease, expr)
#endif
return 1;
case expr_pick_first_value:
memset (&data, 0, sizeof data);
if ((evaluate_data_expression
(result, packet, options, lease,
expr -> data.pick_first_value.car))) {
#if defined (DEBUG_EXPRESSIONS)
log_info ("data: pick_first_value (%s, ???)",
print_hex_1 (result -> len,
result -> data, 40));
#endif
return 1;
}
if ((evaluate_data_expression
(result, packet, options, lease,
expr -> data.pick_first_value.cdr))) {
#if defined (DEBUG_EXPRESSIONS)
log_info ("data: pick_first_value (NULL, %s)",
print_hex_1 (result -> len,
result -> data, 40));
#endif
return 1;
}
#if defined (DEBUG_EXPRESSIONS)
log_info ("data: pick_first_value (NULL, NULL) = NULL");
#endif
return 0;
case expr_host_decl_name:
if (!lease || !lease -> host) {
log_error ("data: host_decl_name: not available");
return 0;
}
result -> len = strlen (lease -> host -> name) + 1;
if (buffer_allocate (&result -> buffer, result -> len,
"host-decl-name")) {
result -> data = &result -> buffer -> data [0];
strcpy (&result -> data [0], lease -> host -> name);
result -> terminated = 1;
} else {
log_error ("data: host-decl-name: no memory.");
return 0;
}
#if defined (DEBUG_EXPRESSIONS)
log_info ("data: host-decl-name = %s", lease -> host -> name);
#endif
return 1;
case expr_check:
case expr_equal:
@@ -1160,6 +1210,9 @@ int evaluate_numeric_expression (result, packet, options, lease, expr)
case expr_encode_int32:
case expr_binary_to_ascii:
case expr_reverse:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
case expr_leased_address:
log_error ("Data opcode in evaluate_numeric_expression: %d",
expr -> op);
@@ -1411,6 +1464,15 @@ void expression_dereference (eptr, name)
name);
break;
case expr_pick_first_value:
if (expr -> data.pick_first_value.car)
expression_dereference
(&expr -> data.pick_first_value.car, name);
if (expr -> data.pick_first_value.cdr)
expression_dereference
(&expr -> data.pick_first_value.cdr, name);
break;
case expr_reverse:
if (expr -> data.reverse.width)
expression_dereference (&expr -> data.reverse.width,
@@ -1547,6 +1609,9 @@ static int op_val (op)
case expr_known:
case expr_binary_to_ascii:
case expr_reverse:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
case expr_leased_address:
return 100;
@@ -1599,6 +1664,9 @@ enum expression_context op_context (op)
case expr_known:
case expr_binary_to_ascii:
case expr_reverse:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
case expr_leased_address:
return context_any;

View File

@@ -186,6 +186,10 @@ struct lease {
struct class *billing_class;
struct hardware hardware_addr;
struct executable_statement *on_expiry;
struct executable_statement *on_commit;
struct executable_statement *on_release;
int flags;
# define STATIC_LEASE 1
# define BOOTP_LEASE 2
@@ -902,11 +906,12 @@ struct option *parse_option_name PROTO ((FILE *, int));
void parse_option_space_decl PROTO ((FILE *));
int parse_option_code_definition PROTO ((FILE *, struct option *));
int parse_cshl PROTO ((struct data_string *, FILE *));
struct executable_statement *parse_executable_statement PROTO ((FILE *,
int *));
struct executable_statement *parse_executable_statements PROTO ((FILE *,
int *));
struct executable_statement *parse_if_statement PROTO ((FILE *, int *));
int parse_executable_statement PROTO ((struct executable_statement **,
FILE *, int *));
int parse_executable_statements PROTO ((struct executable_statement **,
FILE *, int *));
int parse_on_statement PROTO ((struct executable_statement **, FILE *, int *));
int parse_if_statement PROTO ((struct executable_statement **, FILE *, int *));
int parse_boolean_expression PROTO ((struct expression **, FILE *, int *));
int parse_data_expression PROTO ((struct expression **, FILE *, int *));
int parse_numeric_expression PROTO ((struct expression **, FILE *, int *));
@@ -915,10 +920,8 @@ int parse_non_binary PROTO ((struct expression **, FILE *, int *,
int parse_expression PROTO ((struct expression **, FILE *, int *,
enum expression_context,
struct expression **, enum expr_op));
struct executable_statement *parse_option_statement PROTO ((FILE *, int,
struct option *,
enum statement_op)
);
int parse_option_statement PROTO ((struct executable_statement **, FILE *, int,
struct option *, enum statement_op));
int parse_option_token PROTO ((struct expression **, FILE *, char *,
struct expression *, int, int));
int parse_allow_deny PROTO ((struct option_cache **, FILE *, int));
@@ -1095,6 +1098,13 @@ int option_state_allocate PROTO ((struct option_state **, char *));
int option_state_reference PROTO ((struct option_state **,
struct option_state *, char *));
int option_state_dereference PROTO ((struct option_state **, char *));
int executable_statement_allocate PROTO ((struct executable_statement **,
char *));
int executable_statement_reference PROTO ((struct executable_statement **,
struct executable_statement *,
char *));
int executable_statement_dereference PROTO ((struct executable_statement **,
char *));
/* print.c */
char *print_hw_addr PROTO ((int, int, unsigned char *));

View File

@@ -184,6 +184,13 @@ enum dhcp_token {
REVERSE = 402,
LEASED_ADDRESS = 403,
BINARY_TO_ASCII = 404,
PICK_FIRST_VALUE = 405,
CONFIG_OPTION = 406,
HOST_DECL_NAME = 407,
ON = 408,
EXPIRY = 409,
RELEASE = 410,
COMMIT = 411,
};
#define is_identifier(x) ((x) >= FIRST_TOKEN && \

View File

@@ -21,6 +21,7 @@
*/
struct executable_statement {
int refcnt;
struct executable_statement *next;
enum statement_op {
if_statement,
@@ -32,6 +33,8 @@ struct executable_statement {
append_option_statement,
prepend_option_statement,
send_option_statement,
statements_statement,
on_statement,
} op;
union {
struct {
@@ -44,6 +47,11 @@ struct executable_statement {
struct option_cache *supersede;
struct option_cache *prepend;
struct option_cache *append;
struct executable_statement *statements;
struct {
enum { expiry, commit, release } evtype;
struct executable_statement *statements;
} on;
} data;
};

View File

@@ -86,6 +86,9 @@ enum expr_op {
expr_reverse,
expr_leased_address,
expr_binary_to_ascii,
expr_config_option,
expr_host_decl_name,
expr_pick_first_value,
};
struct expression {
@@ -107,6 +110,7 @@ struct expression {
struct expression *len;
} suffix;
struct option *option;
struct option *config_option;
struct {
struct expression *offset;
struct expression *len;
@@ -129,6 +133,10 @@ struct expression {
struct expression *width;
struct expression *buffer;
} reverse;
struct {
struct expression *car;
struct expression *cdr;
} pick_first_value;
} data;
int flags;
# define EXPR_EPHEMERAL 1

View File

@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: confpars.c,v 1.74 1999/07/12 22:44:16 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
"$Id: confpars.c,v 1.75 1999/07/16 21:34:14 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
@@ -426,10 +426,10 @@ int parse_statement (cfile, group, type, host_decl, declaration)
}
finish_option:
et = parse_option_statement
(cfile, 1, option,
supersede_option_statement);
if (!et)
et = (struct executable_statement *)0;
if (!parse_option_statement
(&et, cfile, 1, option,
supersede_option_statement))
return declaration;
goto insert_statement;
} else
@@ -451,18 +451,16 @@ int parse_statement (cfile, group, type, host_decl, declaration)
(unsigned char *)val, 0));
if (option) {
token = next_token (&val, cfile);
et = parse_option_statement
(cfile, 1, option,
supersede_option_statement);
if (!et)
if (!parse_option_statement
(&et, cfile, 1, option,
supersede_option_statement))
return declaration;
}
}
if (!et) {
lose = 0;
et = parse_executable_statement (cfile, &lose);
if (!et) {
if (!parse_executable_statement (&et, cfile, &lose)) {
if (!lose) {
if (declaration)
parse_warn ("expecting a %s.",
@@ -483,13 +481,41 @@ int parse_statement (cfile, group, type, host_decl, declaration)
}
insert_statement:
if (group -> statements) {
int multi = 0;
/* If this set of statements is only referenced
by this group, just add the current statement
to the end of the chain. */
for (ep = group -> statements; ep -> next;
ep = ep -> next)
;
ep -> next = et;
if (ep -> refcnt > 1) /* XXX */
multi = 1;
if (!multi) {
executable_statement_reference
(&ep -> next, et, "parse_statement");
return declaration;
}
/* Otherwise, make a parent chain, and put the
current group statements first and the new
statement in the next pointer. */
ep = (struct executable_statement *)0;
if (!executable_statement_allocate
(&ep, "parse_statement"))
log_fatal ("No memory for statements.");
ep -> op = statements_statement;
executable_statement_reference
(&ep -> data.statements,
group -> statements, "parse_statement");
executable_statement_reference
(&ep -> next, et, "parse_statement");
executable_statement_dereference
(&group -> statements, "parse_statement");
executable_statement_reference
(&group -> statements, ep, "parse_statements");
} else
group -> statements = et;
executable_statement_reference
(&group -> statements, et, "parse_statements");
return declaration;
}