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:
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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"))
|
||||
|
@@ -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,
|
||||
|
333
common/parse.c
333
common/parse.c
@@ -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)
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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 *));
|
||||
|
@@ -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 && \
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user