2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-01 06:45:27 +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 #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -777,3 +777,69 @@ int option_state_dereference (ptr, name)
dfree (options, name); dfree (options, name);
return 1; 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 #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -384,8 +384,12 @@ static enum dhcp_token intern (atom, dfv)
return BOOLEAN; return BOOLEAN;
break; break;
case 'c': case 'c':
if (!strcasecmp (atom + 1, "ommit"))
return COMMIT;
if (!strcasecmp (atom + 1, "ode")) if (!strcasecmp (atom + 1, "ode"))
return CODE; return CODE;
if (!strcasecmp (atom + 1, "onfig-option"))
return CONFIG_OPTION;
if (!strcasecmp (atom + 1, "heck")) if (!strcasecmp (atom + 1, "heck"))
return CHECK; return CHECK;
if (!strcasecmp (atom + 1, "lass")) if (!strcasecmp (atom + 1, "lass"))
@@ -436,6 +440,8 @@ static enum dhcp_token intern (atom, dfv)
} }
break; break;
case 'e': case 'e':
if (!strcasecmp (atom + 1, "xpiry"))
return EXPIRY;
if (isascii (atom [1]) && tolower (atom [1]) == 'x') { if (isascii (atom [1]) && tolower (atom [1]) == 'x') {
if (!strcasecmp (atom + 2, "tract-int")) if (!strcasecmp (atom + 2, "tract-int"))
return EXTRACT_INT; return EXTRACT_INT;
@@ -477,6 +483,8 @@ static enum dhcp_token intern (atom, dfv)
case 'h': case 'h':
if (!strcasecmp (atom + 1, "ost")) if (!strcasecmp (atom + 1, "ost"))
return HOST; return HOST;
if (!strcasecmp (atom + 1, "ost-decl-name"))
return HOST_DECL_NAME;
if (!strcasecmp (atom + 1, "ardware")) if (!strcasecmp (atom + 1, "ardware"))
return HARDWARE; return HARDWARE;
if (!strcasecmp (atom + 1, "ostname")) if (!strcasecmp (atom + 1, "ostname"))
@@ -553,6 +561,8 @@ static enum dhcp_token intern (atom, dfv)
case 'o': case 'o':
if (!strcasecmp (atom + 1, "r")) if (!strcasecmp (atom + 1, "r"))
return OR; return OR;
if (!strcasecmp (atom + 1, "n"))
return ON;
if (!strcasecmp (atom + 1, "ption")) if (!strcasecmp (atom + 1, "ption"))
return OPTION; return OPTION;
if (!strcasecmp (atom + 1, "ne-lease-per-client")) if (!strcasecmp (atom + 1, "ne-lease-per-client"))
@@ -583,6 +593,8 @@ static enum dhcp_token intern (atom, dfv)
return PORT; return PORT;
if (!strcasecmp (atom + 1, "otential-conflict")) if (!strcasecmp (atom + 1, "otential-conflict"))
return POTENTIAL_CONFLICT; return POTENTIAL_CONFLICT;
if (!strcasecmp (atom + 1, "ick-first-value"))
return PICK_FIRST_VALUE;
break; break;
case 'r': case 'r':
if (!strcasecmp (atom + 1, "ange")) if (!strcasecmp (atom + 1, "ange"))
@@ -607,6 +619,8 @@ static enum dhcp_token intern (atom, dfv)
return REJECT; return REJECT;
if (!strcasecmp (atom + 1, "everse")) if (!strcasecmp (atom + 1, "everse"))
return REVERSE; return REVERSE;
if (!strcasecmp (atom + 1, "elease"))
return RELEASE;
break; break;
case 's': case 's':
if (!strcasecmp (atom + 1, "igned")) if (!strcasecmp (atom + 1, "igned"))

View File

@@ -22,7 +22,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -43,6 +43,46 @@ int execute_statements (packet, lease, in_options, out_options, statements)
for (r = statements; r; r = r -> next) { for (r = statements; r; r = r -> next) {
switch (r -> op) { 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: case if_statement:
status = evaluate_boolean_expression status = evaluate_boolean_expression
(&result, packet, (&result, packet,

View File

@@ -22,7 +22,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -1151,27 +1151,29 @@ int parse_cshl (data, cfile)
* APPEND option-parameter SEMI * 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; FILE *cfile;
int *lose; int *lose;
{ {
struct executable_statement *head, **next; struct executable_statement **next;
next = &head; next = statements;
while ((*next = parse_executable_statement (cfile, lose))) while (parse_executable_statement (next, cfile, lose))
next = &((*next) -> next); next = &((*next) -> next);
if (!*lose) if (!*lose)
return head; return 1;
return (struct executable_statement *)0; return 0;
} }
struct executable_statement *parse_executable_statement (cfile, lose) int parse_executable_statement (result, cfile, lose)
struct executable_statement **result;
FILE *cfile; FILE *cfile;
int *lose; int *lose;
{ {
enum dhcp_token token; enum dhcp_token token;
char *val; char *val;
struct executable_statement *stmt, base; struct executable_statement base;
struct class *cta; struct class *cta;
struct option *option; struct option *option;
struct option_cache *cache; struct option_cache *cache;
@@ -1180,8 +1182,8 @@ struct executable_statement *parse_executable_statement (cfile, lose)
switch (token) { switch (token) {
case IF: case IF:
next_token (&val, cfile); next_token (&val, cfile);
stmt = parse_if_statement (cfile, lose); return parse_if_statement (result, cfile, lose);
return stmt;
case TOKEN_ADD: case TOKEN_ADD:
token = next_token (&val, cfile); token = next_token (&val, cfile);
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."); parse_warn ("expecting class name.");
skip_to_semi (cfile); skip_to_semi (cfile);
*lose = 1; *lose = 1;
return (struct executable_statement *)0; return 0;
} }
cta = find_class (val); cta = find_class (val);
if (!cta) { if (!cta) {
parse_warn ("unknown class %s.", val); parse_warn ("unknown class %s.", val);
skip_to_semi (cfile); skip_to_semi (cfile);
*lose = 1; *lose = 1;
return (struct executable_statement *)0; return 0;
} }
if (!parse_semi (cfile)) { if (!parse_semi (cfile)) {
*lose = 1; *lose = 1;
return (struct executable_statement *)0; return 0;
} }
memset (&base, 0, sizeof base); if (!executable_statement_allocate
base.op = add_statement; (result, "parse_executable_statement"))
base.data.add = cta; log_fatal ("no memory for new statement.");
(*result) -> op = add_statement;
(*result) -> data.add = cta;
break; break;
case BREAK: case BREAK:
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (!parse_semi (cfile)) { if (!parse_semi (cfile)) {
*lose = 1; *lose = 1;
return (struct executable_statement *)0; return 0;
} }
memset (&base, 0, sizeof base); if (!executable_statement_allocate
base.op = break_statement; (result, "parse_executable_statement"))
log_fatal ("no memory for new statement.");
(*result) -> op = break_statement;
break; break;
case SEND: case SEND:
*lose = 1; *lose = 1;
parse_warn ("send not appropriate here."); parse_warn ("send not appropriate here.");
skip_to_semi (cfile); skip_to_semi (cfile);
return (struct executable_statement *)0; return 0;
case SUPERSEDE: case SUPERSEDE:
case OPTION: case OPTION:
@@ -1229,9 +1235,9 @@ struct executable_statement *parse_executable_statement (cfile, lose)
option = parse_option_name (cfile, 0); option = parse_option_name (cfile, 0);
if (!option) { if (!option) {
*lose = 1; *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); supersede_option_statement);
case ALLOW: case ALLOW:
@@ -1240,10 +1246,12 @@ struct executable_statement *parse_executable_statement (cfile, lose)
cache = (struct option_cache *)0; cache = (struct option_cache *)0;
if (!parse_allow_deny (&cache, cfile, if (!parse_allow_deny (&cache, cfile,
token == ALLOW ? 1 : 0)) token == ALLOW ? 1 : 0))
return (struct executable_statement *)0; return 0;
memset (&base, 0, sizeof base); if (!executable_statement_allocate
base.op = supersede_option_statement; (result, "parse_executable_statement"))
base.data.option = cache; log_fatal ("no memory for new statement.");
(*result) -> op = supersede_option_statement;
(*result) -> data.option = cache;
break; break;
case DEFAULT: case DEFAULT:
@@ -1251,9 +1259,9 @@ struct executable_statement *parse_executable_statement (cfile, lose)
option = parse_option_name (cfile, 0); option = parse_option_name (cfile, 0);
if (!option) { if (!option) {
*lose = 1; *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); default_option_statement);
case PREPEND: case PREPEND:
@@ -1261,9 +1269,9 @@ struct executable_statement *parse_executable_statement (cfile, lose)
option = parse_option_name (cfile, 0); option = parse_option_name (cfile, 0);
if (!option) { if (!option) {
*lose = 1; *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); prepend_option_statement);
case APPEND: case APPEND:
@@ -1271,23 +1279,96 @@ struct executable_statement *parse_executable_statement (cfile, lose)
option = parse_option_name (cfile, 0); option = parse_option_name (cfile, 0);
if (!option) { if (!option) {
*lose = 1; *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); append_option_statement);
case ON:
token = next_token (&val, cfile);
return parse_on_statement (result, cfile, lose);
default: default:
*lose = 0; *lose = 0;
return (struct executable_statement *)0; return 0;
} }
stmt = ((struct executable_statement *) return 1;
dmalloc (sizeof (struct executable_statement), }
"parse_executable_statement"));
if (!stmt) /*
* 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."); 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 * ELSIF if-statement
*/ */
struct executable_statement *parse_if_statement (cfile, lose) int parse_if_statement (result, cfile, lose)
struct executable_statement **result;
FILE *cfile; FILE *cfile;
int *lose; int *lose;
{ {
enum dhcp_token token; enum dhcp_token token;
char *val; char *val;
struct executable_statement *stmt;
struct expression *if_condition;
struct executable_statement *true, *false;
if_condition = (struct expression *)0; if (!executable_statement_allocate (result, "parse_if_statement"))
if (!parse_boolean_expression (&if_condition, cfile, lose)) { log_fatal ("no memory for if statement.");
(*result) -> op = if_statement;
if (!parse_boolean_expression (&(*result) -> data.ie.expr,
cfile, lose)) {
if (!*lose) if (!*lose)
parse_warn ("boolean expression expected."); parse_warn ("boolean expression expected.");
return (struct executable_statement *)0; executable_statement_dereference (result,
"parse_if_statement");
return 0;
} }
#if defined (DEBUG_EXPRESSION_PARSE) #if defined (DEBUG_EXPRESSION_PARSE)
print_expression ("if condition", if_condition); print_expression ("if condition", if_condition);
@@ -1324,22 +1410,30 @@ struct executable_statement *parse_if_statement (cfile, lose)
parse_warn ("left brace expected."); parse_warn ("left brace expected.");
skip_to_semi (cfile); skip_to_semi (cfile);
*lose = 1; *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); 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) { if (token != RBRACE) {
parse_warn ("right brace expected."); parse_warn ("right brace expected.");
skip_to_semi (cfile); skip_to_semi (cfile);
*lose = 1; *lose = 1;
return (struct executable_statement *)0; executable_statement_dereference
(result, "parse_if_statement");
return 0;
} }
token = peek_token (&val, cfile); token = peek_token (&val, cfile);
if (token == ELSE) { if (token == ELSE) {
@@ -1347,46 +1441,53 @@ struct executable_statement *parse_if_statement (cfile, lose)
token = peek_token (&val, cfile); token = peek_token (&val, cfile);
if (token == IF) { if (token == IF) {
token = next_token (&val, cfile); token = next_token (&val, cfile);
false = parse_if_statement (cfile, lose); if (!parse_if_statement (&(*result) -> data.ie.false,
if (*lose) cfile, lose)) {
return (struct executable_statement *)0; if (*lose) {
return 0;
executable_statement_dereference
(result, "parse_if_statement");
}
}
} else if (token != LBRACE) { } else if (token != LBRACE) {
parse_warn ("left brace or if expected."); parse_warn ("left brace or if expected.");
skip_to_semi (cfile); skip_to_semi (cfile);
*lose = 1; *lose = 1;
return (struct executable_statement *)0; executable_statement_dereference
(result, "parse_if_statement");
return 0;
} else { } else {
token = next_token (&val, cfile); token = next_token (&val, cfile);
false = parse_executable_statements (cfile, lose); if (!parse_if_statement (&(*result) -> data.ie.false,
if (*lose) cfile, lose)) {
return (struct executable_statement *)0; executable_statement_dereference
(result, "parse_if_statement");
return 0;
}
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (token != RBRACE) { if (token != RBRACE) {
parse_warn ("right brace expected."); parse_warn ("right brace expected.");
skip_to_semi (cfile); skip_to_semi (cfile);
*lose = 1; *lose = 1;
return (struct executable_statement *)0; executable_statement_dereference
(result, "parse_if_statement");
return 0;
} }
} }
} else if (token == ELSIF) { } else if (token == ELSIF) {
token = next_token (&val, cfile); token = next_token (&val, cfile);
false = parse_if_statement (cfile, lose); if (!parse_if_statement (&(*result) -> data.ie.false,
if (*lose) cfile, lose)) {
return (struct executable_statement *)0; if (*lose) {
return 0;
executable_statement_dereference
(result, "parse_if_statement");
}
}
} else } else
false = (struct executable_statement *)0; (*result) -> data.ie.false = (struct executable_statement *)0;
stmt = ((struct executable_statement *) return 1;
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;
} }
/* /*
@@ -1486,6 +1587,7 @@ int parse_non_binary (expr, cfile, lose, context)
char *val; char *val;
struct collection *col; struct collection *col;
struct option *option; struct option *option;
struct expression *nexp;
token = peek_token (&val, cfile); token = peek_token (&val, cfile);
@@ -1746,11 +1848,49 @@ int parse_non_binary (expr, cfile, lose, context)
goto norparen; goto norparen;
break; 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); 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")) if (!expression_allocate (expr, "parse_expression: OPTION"))
log_fatal ("can't allocate expression"); 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); (*expr) -> data.option = parse_option_name (cfile, 0);
if (!(*expr) -> data.option) { if (!(*expr) -> data.option) {
*lose = 1; *lose = 1;
@@ -1775,6 +1915,14 @@ int parse_non_binary (expr, cfile, lose, context)
(*expr) -> op = expr_leased_address; (*expr) -> op = expr_leased_address;
break; 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: case PACKET:
token = next_token (&val, cfile); token = next_token (&val, cfile);
if (!expression_allocate (expr, "parse_expression: PACKET")) 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 would be painful to come up with BNF for it. However, it always
starts as above and ends in a SEMI. */ starts as above and ends in a SEMI. */
struct executable_statement *parse_option_statement (cfile, lookups, int parse_option_statement (result, cfile, lookups, option, op)
option, op) struct executable_statement **result;
FILE *cfile; FILE *cfile;
int lookups; int lookups;
struct option *option; struct option *option;
@@ -2159,7 +2307,7 @@ struct executable_statement *parse_option_statement (cfile, lookups,
parse_warn ("expecting a data expression."); parse_warn ("expecting a data expression.");
skip_to_semi (cfile); skip_to_semi (cfile);
} }
return (struct executable_statement *)0; return 0;
} }
/* We got a valid expression, so use it. */ /* We got a valid expression, so use it. */
@@ -2182,7 +2330,7 @@ struct executable_statement *parse_option_statement (cfile, lookups,
tmp, uniform, lookups)) { tmp, uniform, lookups)) {
expression_dereference expression_dereference
(&tmp, "parse_option_statement"); (&tmp, "parse_option_statement");
return (struct executable_statement *)0; return 0;
} }
if (tmp) if (tmp)
expression_dereference expression_dereference
@@ -2200,15 +2348,14 @@ struct executable_statement *parse_option_statement (cfile, lookups,
done: done:
if (!parse_semi (cfile)) if (!parse_semi (cfile))
return (struct executable_statement *)0; return 0;
stmt = ((struct executable_statement *) if (!executable_statement_allocate (result, "parse_option_statement"))
dmalloc (sizeof *stmt, "parse_option_statement")); log_fatal ("no memory for option statement.");
memset (stmt, 0, sizeof *stmt); (*result) -> op = op;
stmt -> op = op; if (expr && !option_cache (&(*result) -> data.option,
if (expr && !option_cache (&stmt -> data.option,
(struct data_string *)0, expr, option)) (struct data_string *)0, expr, option))
log_fatal ("no memory for option cache"); log_fatal ("no memory for option cache");
return stmt; return 1;
} }
int parse_option_token (rv, cfile, fmt, expr, uniform, lookups) int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)

View File

@@ -22,7 +22,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -538,6 +538,9 @@ int evaluate_boolean_expression (result, packet, options, lease, expr)
case expr_encode_int32: case expr_encode_int32:
case expr_binary_to_ascii: case expr_binary_to_ascii:
case expr_reverse: case expr_reverse:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
case expr_leased_address: case expr_leased_address:
log_error ("Data opcode in evaluate_boolean_expression: %d", log_error ("Data opcode in evaluate_boolean_expression: %d",
expr -> op); expr -> op);
@@ -651,6 +654,7 @@ int evaluate_data_expression (result, packet, options, lease, expr)
/* Extract an option. */ /* Extract an option. */
case expr_option: case expr_option:
case expr_config_option:
if (options) if (options)
s0 = ((*expr -> data.option -> universe -> get_func) s0 = ((*expr -> data.option -> universe -> get_func)
(result, expr -> data.option -> universe, (result, expr -> data.option -> universe,
@@ -1098,7 +1102,53 @@ int evaluate_data_expression (result, packet, options, lease, expr)
#endif #endif
return 1; 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_check:
case expr_equal: case expr_equal:
@@ -1160,6 +1210,9 @@ int evaluate_numeric_expression (result, packet, options, lease, expr)
case expr_encode_int32: case expr_encode_int32:
case expr_binary_to_ascii: case expr_binary_to_ascii:
case expr_reverse: case expr_reverse:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
case expr_leased_address: case expr_leased_address:
log_error ("Data opcode in evaluate_numeric_expression: %d", log_error ("Data opcode in evaluate_numeric_expression: %d",
expr -> op); expr -> op);
@@ -1411,6 +1464,15 @@ void expression_dereference (eptr, name)
name); name);
break; 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: case expr_reverse:
if (expr -> data.reverse.width) if (expr -> data.reverse.width)
expression_dereference (&expr -> data.reverse.width, expression_dereference (&expr -> data.reverse.width,
@@ -1547,6 +1609,9 @@ static int op_val (op)
case expr_known: case expr_known:
case expr_binary_to_ascii: case expr_binary_to_ascii:
case expr_reverse: case expr_reverse:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
case expr_leased_address: case expr_leased_address:
return 100; return 100;
@@ -1599,6 +1664,9 @@ enum expression_context op_context (op)
case expr_known: case expr_known:
case expr_binary_to_ascii: case expr_binary_to_ascii:
case expr_reverse: case expr_reverse:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
case expr_leased_address: case expr_leased_address:
return context_any; return context_any;

View File

@@ -186,6 +186,10 @@ struct lease {
struct class *billing_class; struct class *billing_class;
struct hardware hardware_addr; struct hardware hardware_addr;
struct executable_statement *on_expiry;
struct executable_statement *on_commit;
struct executable_statement *on_release;
int flags; int flags;
# define STATIC_LEASE 1 # define STATIC_LEASE 1
# define BOOTP_LEASE 2 # define BOOTP_LEASE 2
@@ -902,11 +906,12 @@ struct option *parse_option_name PROTO ((FILE *, int));
void parse_option_space_decl PROTO ((FILE *)); void parse_option_space_decl PROTO ((FILE *));
int parse_option_code_definition PROTO ((FILE *, struct option *)); int parse_option_code_definition PROTO ((FILE *, struct option *));
int parse_cshl PROTO ((struct data_string *, FILE *)); int parse_cshl PROTO ((struct data_string *, FILE *));
struct executable_statement *parse_executable_statement PROTO ((FILE *, int parse_executable_statement PROTO ((struct executable_statement **,
int *)); FILE *, int *));
struct executable_statement *parse_executable_statements PROTO ((FILE *, int parse_executable_statements PROTO ((struct executable_statement **,
int *)); FILE *, int *));
struct executable_statement *parse_if_statement PROTO ((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_boolean_expression PROTO ((struct expression **, FILE *, int *));
int parse_data_expression PROTO ((struct expression **, FILE *, int *)); int parse_data_expression PROTO ((struct expression **, FILE *, int *));
int parse_numeric_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 *, int parse_expression PROTO ((struct expression **, FILE *, int *,
enum expression_context, enum expression_context,
struct expression **, enum expr_op)); struct expression **, enum expr_op));
struct executable_statement *parse_option_statement PROTO ((FILE *, int, int parse_option_statement PROTO ((struct executable_statement **, FILE *, int,
struct option *, struct option *, enum statement_op));
enum statement_op)
);
int parse_option_token PROTO ((struct expression **, FILE *, char *, int parse_option_token PROTO ((struct expression **, FILE *, char *,
struct expression *, int, int)); struct expression *, int, int));
int parse_allow_deny PROTO ((struct option_cache **, FILE *, 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 **, int option_state_reference PROTO ((struct option_state **,
struct option_state *, char *)); struct option_state *, char *));
int option_state_dereference PROTO ((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 */ /* print.c */
char *print_hw_addr PROTO ((int, int, unsigned char *)); char *print_hw_addr PROTO ((int, int, unsigned char *));

View File

@@ -184,6 +184,13 @@ enum dhcp_token {
REVERSE = 402, REVERSE = 402,
LEASED_ADDRESS = 403, LEASED_ADDRESS = 403,
BINARY_TO_ASCII = 404, 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 && \ #define is_identifier(x) ((x) >= FIRST_TOKEN && \

View File

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

View File

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

View File

@@ -22,7 +22,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -426,10 +426,10 @@ int parse_statement (cfile, group, type, host_decl, declaration)
} }
finish_option: finish_option:
et = parse_option_statement et = (struct executable_statement *)0;
(cfile, 1, option, if (!parse_option_statement
supersede_option_statement); (&et, cfile, 1, option,
if (!et) supersede_option_statement))
return declaration; return declaration;
goto insert_statement; goto insert_statement;
} else } else
@@ -451,18 +451,16 @@ int parse_statement (cfile, group, type, host_decl, declaration)
(unsigned char *)val, 0)); (unsigned char *)val, 0));
if (option) { if (option) {
token = next_token (&val, cfile); token = next_token (&val, cfile);
et = parse_option_statement if (!parse_option_statement
(cfile, 1, option, (&et, cfile, 1, option,
supersede_option_statement); supersede_option_statement))
if (!et)
return declaration; return declaration;
} }
} }
if (!et) { if (!et) {
lose = 0; lose = 0;
et = parse_executable_statement (cfile, &lose); if (!parse_executable_statement (&et, cfile, &lose)) {
if (!et) {
if (!lose) { if (!lose) {
if (declaration) if (declaration)
parse_warn ("expecting a %s.", parse_warn ("expecting a %s.",
@@ -483,13 +481,41 @@ int parse_statement (cfile, group, type, host_decl, declaration)
} }
insert_statement: insert_statement:
if (group -> statements) { 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; for (ep = group -> statements; ep -> next;
ep = ep -> next) ep = ep -> next)
; if (ep -> refcnt > 1) /* XXX */
ep -> next = et; 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 } else
group -> statements = et; executable_statement_reference
(&group -> statements, et, "parse_statements");
return declaration; return declaration;
} }