Commit fdac15d9 authored by Ted Lemon's avatar Ted Lemon

- Pull up 3.0 changes.

- Support malloc debug.
- Parse ganged events, let, unset, parenthesized if statements, eval.
- Part of backwards compatibility for BCTEL (doesn't work yet)
parent dbf6124a
......@@ -22,7 +22,7 @@
#ifndef lint
static char copyright[] =
"$Id: parse.c,v 1.58 2000/01/08 01:36:39 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
"$Id: parse.c,v 1.59 2000/01/25 01:13:21 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
......@@ -112,7 +112,7 @@ char *parse_string (cfile)
skip_to_semi (cfile);
return (char *)0;
}
s = (char *)malloc (strlen (val) + 1);
s = (char *)dmalloc (strlen (val) + 1, MDL);
if (!s)
log_fatal ("no memory for string %s.", val);
strcpy (s, val);
......@@ -147,7 +147,7 @@ char *parse_host_name (cfile)
token = next_token (&val, cfile);
/* Store this identifier... */
if (!(s = (char *)malloc (strlen (val) + 1)))
if (!(s = (char *)dmalloc (strlen (val) + 1, MDL)))
log_fatal ("can't allocate temp space for hostname.");
strcpy (s, val);
c = cons ((caddr_t)s, c);
......@@ -160,7 +160,7 @@ char *parse_host_name (cfile)
} while (token == DOT);
/* Assemble the hostname together into a string. */
if (!(s = (char *)malloc (len)))
if (!(s = (char *)dmalloc (len, MDL)))
log_fatal ("can't allocate space for hostname.");
t = s + len;
*--t = 0;
......@@ -170,8 +170,8 @@ char *parse_host_name (cfile)
t -= l;
memcpy (t, (char *)(c -> car), l);
/* Free up temp space. */
free (c -> car);
free (c);
dfree (c -> car, MDL);
dfree (c, MDL);
c = cdr;
if (t != s)
*--t = '.';
......@@ -291,7 +291,7 @@ void parse_hardware_param (cfile, hardware)
if (!t)
return;
if (hlen + 1 > sizeof hardware -> hbuf) {
free (t);
dfree (t, MDL);
parse_warn (cfile, "hardware address too long");
} else {
hardware -> hlen = hlen + 1;
......@@ -299,7 +299,7 @@ void parse_hardware_param (cfile, hardware)
if (hlen + 1 < sizeof hardware -> hbuf)
memset (&hardware -> hbuf [hlen + 1], 0,
(sizeof hardware -> hbuf) - hlen - 1);
free (t);
dfree (t, MDL);
}
token = next_token (&val, cfile);
......@@ -354,7 +354,7 @@ unsigned char *parse_numeric_aggregate (cfile, buf,
pair c = (pair)0;
if (!bufp && *max) {
bufp = (unsigned char *)malloc (*max * size / 8);
bufp = (unsigned char *)dmalloc (*max * size / 8, MDL);
if (!bufp)
log_fatal ("no space for numeric aggregate");
s = 0;
......@@ -396,7 +396,7 @@ unsigned char *parse_numeric_aggregate (cfile, buf,
convert_num (cfile, s, val, base, size);
s += size / 8;
} else {
t = (unsigned char *)malloc (strlen (val) + 1);
t = (unsigned char *)dmalloc (strlen (val) + 1, MDL);
if (!t)
log_fatal ("no temp space for number.");
strcpy ((char *)t, val);
......@@ -406,7 +406,7 @@ unsigned char *parse_numeric_aggregate (cfile, buf,
/* If we had to cons up a list, convert it now. */
if (c) {
bufp = (unsigned char *)malloc (count * size / 8);
bufp = (unsigned char *)dmalloc (count * size / 8, MDL);
if (!bufp)
log_fatal ("no space for numeric aggregate.");
s = bufp + count - size / 8;
......@@ -417,8 +417,8 @@ unsigned char *parse_numeric_aggregate (cfile, buf,
convert_num (cfile, s, (char *)(c -> car), base, size);
s -= size / 8;
/* Free up temp space. */
free (c -> car);
free (c);
dfree (c -> car, MDL);
dfree (c, MDL);
c = cdr;
}
return bufp;
......@@ -749,7 +749,7 @@ struct option *parse_option_name (cfile, allocate, known)
skip_to_semi (cfile);
return (struct option *)0;
}
uname = malloc (strlen (val) + 1);
uname = dmalloc (strlen (val) + 1, MDL);
if (!uname)
log_fatal ("no memory for uname information.");
strcpy (uname, val);
......@@ -803,9 +803,8 @@ struct option *parse_option_name (cfile, allocate, known)
option -> name = val;
else {
char *s;
free (uname);
s = dmalloc (strlen (val) + 1,
"parse_option_name");
dfree (uname, MDL);
s = dmalloc (strlen (val) + 1, MDL);
if (!s)
log_fatal ("no memory for option %s.%s",
universe -> name, val);
......@@ -826,7 +825,7 @@ struct option *parse_option_name (cfile, allocate, known)
}
/* Free the initial identifier token. */
free (uname);
dfree (uname, MDL);
return option;
}
......@@ -853,7 +852,7 @@ void parse_option_space_decl (cfile)
log_fatal ("No memory for new option space.");
/* Set up the server option universe... */
s = dmalloc (strlen (val) + 1, "parse_option_space_decl");
s = dmalloc (strlen (val) + 1, MDL);
if (!s)
log_fatal ("No memory for new option space name.");
strcpy (s, val);
......@@ -872,13 +871,12 @@ void parse_option_space_decl (cfile)
nu -> store_length = putUChar;
nu -> index = universe_count++;
if (nu -> index >= universe_max) {
ua = dmalloc (universe_max * 2 * sizeof *ua,
"parse_option_space_decl");
ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
if (!ua)
log_fatal ("No memory to expand option space array.");
memcpy (ua, universes, universe_max * sizeof *ua);
universe_max *= 2;
dfree (universes, "parse_option_space_decl");
dfree (universes, MDL);
universes = ua;
}
universes [nu -> index] = nu;
......@@ -1084,7 +1082,7 @@ int parse_option_code_definition (cfile, option)
skip_to_semi (cfile);
return 0;
}
s = dmalloc (tokix + arrayp + 1, "parse_option_code_definition");
s = dmalloc (tokix + arrayp + 1, MDL);
if (!s)
log_fatal ("no memory for option format.");
memcpy (s, tokbuf, tokix);
......@@ -1128,15 +1126,14 @@ int parse_cshl (data, cfile)
skip_to_semi (cfile);
for (; sl; sl = next) {
next = sl -> next;
dfree (sl, "parse_cshl");
dfree (sl, MDL);
}
return 0;
}
if (ilen == sizeof ibuf) {
next = (struct option_tag *)
dmalloc (ilen - 1 +
sizeof (struct option_tag),
"parse_cshl");
sizeof (struct option_tag), MDL);
if (!next)
log_fatal ("no memory for string list.");
memcpy (next -> data, ibuf, ilen);
......@@ -1164,7 +1161,7 @@ int parse_cshl (data, cfile)
next = sl -> next;
memcpy (rvp, sl -> data, sizeof ibuf);
rvp += sizeof ibuf;
dfree (sl, "parse_cshl");
dfree (sl, MDL);
sl = next;
}
......@@ -1375,7 +1372,6 @@ int parse_executable_statement (result, cfile, lose, case_context)
case TOKEN_SET:
token = next_token (&val, cfile);
token = next_token (&val, cfile);
token = next_token (&val, cfile);
if (token != NAME && token != NUMBER_OR_NAME) {
......@@ -1391,9 +1387,8 @@ int parse_executable_statement (result, cfile, lose, case_context)
(result,
"parse_executable_statement"))
log_fatal ("no memory for set statement.");
(*result) -> op = default_statement;
(*result) -> data.set.name = dmalloc (strlen (val) + 1,
"parse_executable_stmt");
(*result) -> op = set_statement;
(*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL);
if (!(*result)->data.set.name)
log_fatal ("can't allocate variable name");
strcpy ((*result) -> data.set.name, val);
......@@ -1419,6 +1414,56 @@ int parse_executable_statement (result, cfile, lose, case_context)
parse_semi (cfile);
break;
case UNSET:
token = next_token (&val, cfile);
token = next_token (&val, cfile);
if (token != NAME && token != NUMBER_OR_NAME) {
parse_warn (cfile,
"%s can't be a variable name", val);
badunset:
skip_to_semi (cfile);
*lose = 1;
return 0;
}
if (!executable_statement_allocate
(result,
"parse_executable_statement"))
log_fatal ("no memory for set statement.");
(*result) -> op = unset_statement;
(*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
if (!(*result)->data.unset)
log_fatal ("can't allocate variable name");
strcpy ((*result) -> data.unset, val);
parse_semi (cfile);
break;
case EVAL:
token = next_token (&val, cfile);
if (!executable_statement_allocate
(result,
"parse_executable_statement"))
log_fatal ("no memory for eval statement.");
(*result) -> op = eval_statement;
if (!parse_expression (&(*result) -> data.eval,
cfile, lose, context_data, /* XXX */
(struct expression **)0, expr_none)) {
if (!*lose)
parse_warn (cfile,
"expecting data expression.");
else
*lose = 1;
skip_to_semi (cfile);
executable_statement_dereference
(result, "parse_executable_statement");
return 0;
}
parse_semi (cfile);
break;
default:
*lose = 0;
return 0;
......@@ -1455,11 +1500,11 @@ int parse_on_statement (result, cfile, lose)
break;
case COMMIT:
(*result) -> data.on.evtypes = ON_COMMIT;
(*result) -> data.on.evtypes |= ON_COMMIT;
break;
case RELEASE:
(*result) -> data.on.evtypes = ON_RELEASE;
(*result) -> data.on.evtypes |= ON_RELEASE;
break;
default:
......@@ -1468,7 +1513,7 @@ int parse_on_statement (result, cfile, lose)
*lose = 1;
executable_statement_dereference
(result, "parse_on_statement");
break;
return 0;
}
token = next_token (&val, cfile);
} while (token == OR);
......@@ -1641,12 +1686,21 @@ int parse_if_statement (result, cfile, lose)
{
enum dhcp_token token;
const char *val;
int parenp;
if (!executable_statement_allocate (result, "parse_if_statement"))
log_fatal ("no memory for if statement.");
(*result) -> op = if_statement;
token = peek_token (&val, cfile);
if (token == LPAREN) {
parenp = 1;
next_token (&val, cfile);
} else
parenp = 0;
if (!parse_boolean_expression (&(*result) -> data.ie.expr,
cfile, lose)) {
if (!*lose)
......@@ -1659,6 +1713,16 @@ int parse_if_statement (result, cfile, lose)
#if defined (DEBUG_EXPRESSION_PARSE)
print_expression ("if condition", if_condition);
#endif
if (parenp) {
token = next_token (&val, cfile);
if (token != RPAREN) {
parse_warn (cfile, "expecting right paren.");
*lose = 1;
executable_statement_dereference
(result, "parse_if_statement");
return 0;
}
}
token = next_token (&val, cfile);
if (token != LBRACE) {
parse_warn (cfile, "left brace expected.");
......@@ -1884,6 +1948,8 @@ int parse_non_binary (expr, cfile, lose, context)
int known;
enum expr_op opcode;
const char *s;
struct executable_statement *stmt;
int i;
token = peek_token (&val, cfile);
......@@ -2176,7 +2242,7 @@ int parse_non_binary (expr, cfile, lose, context)
goto norparen;
break;
case PICK_FIRST_VALUE:
case PICK:
/* pick (a, b, c) actually produces an internal representation
that looks like pick (a, pick (b, pick (c, nil))). */
token = next_token (&val, cfile);
......@@ -2220,70 +2286,75 @@ int parse_non_binary (expr, cfile, lose, context)
parse_warn (cfile,
"Please rebuild dhcpd with --with-nsupdate.");
#endif
token = next_token (&val, cfile);
if (token == DNS_UPDATE)
opcode = expr_ns_add;
else
opcode = expr_ns_delete;
token = next_token (&val, cfile);
if (!expression_allocate (expr,
"parse_expression: DNS_UPDATE"))
log_fatal ("can't allocate expression");
(*expr) -> op = expr_dns_transaction;
token = next_token (&val, cfile);
if (token != LPAREN)
goto nolparen;
nexp = (struct expression *)0;
if (!expression_allocate (&nexp,
"parse_expression: DNS_UPDATE1"))
log_fatal ("can't allocate expression");
nexp -> op = opcode;
(*expr) -> data.dns_transaction.car = nexp;
token = next_token (&val, cfile);
if (token != STRING) {
parse_warn (cfile,
"parse_expression: expecting string.");
badnsupdate:
expression_dereference
(expr, "parse_expression");
skip_to_semi (cfile);
*lose = 1;
return 0;
}
if (!strcasecmp (val, "a"))
nexp -> data.ns_add.rrtype = T_A;
i = T_A;
else if (!strcasecmp (val, "ptr"))
nexp -> data.ns_add.rrtype = T_PTR;
i = T_PTR;
else if (!strcasecmp (val, "mx"))
nexp -> data.ns_add.rrtype = T_MX;
i = T_MX;
else if (!strcasecmp (val, "cname"))
nexp -> data.ns_add.rrtype = T_CNAME;
i = T_CNAME;
else if (!strcasecmp (val, "TXT"))
nexp -> data.ns_add.rrtype = T_TXT;
i = T_TXT;
else {
parse_warn (cfile, "unexpected rrtype: %s", val);
goto badnsupdate;
}
nexp -> data.ns_add.rrclass = C_IN;
if (!expression_allocate (expr,
"parse_expression: DNS_UPDATE"))
log_fatal ("can't allocate expression");
#if 0
(*expr) -> op = expr_funcall;
(*expr) -> data.funcall.context = context_boolean;
(*expr) -> data.funcall.name =
if (!make_let (&(*expr) -> data.funcall.statements, "rrtype"))
log_fatal ("can't allocate rrtype let.");
stmt = (*expr) -> data.funcall.statements;
if (!make_const_int (stmt -> data.let.value, i))
log_fatal ("can't allocate rrtype value.");
token = next_token (&val, cfile);
if (token != COMMA)
goto nocomma;
if (!(parse_data_expression
(&nexp -> data.ns_add.rrname, cfile, lose)))
if (!make_let (&stmt -> data.let.statements, "rrname"))
log_fatal ("can't allocate rrname let.");
stmt = stmt -> data.let.statements;
if (!(parse_data_expression (&stmt -> data.let.expr,
cfile, lose)))
goto nodata;
token = next_token (&val, cfile);
if (token != COMMA)
goto nocomma;
if (!(parse_data_expression
(&nexp -> data.ns_add.rrdata, cfile, lose)))
if (!make_let (&stmt -> data.let.statements, "rrdata"))
log_fatal ("can't allocate rrname let.");
stmt = stmt -> data.let.statements;
if (!(parse_data_expression (&stmt -> data.let.expr,
cfile, lose)))
goto nodata;
if (opcode == expr_ns_add) {
......@@ -2291,14 +2362,18 @@ int parse_non_binary (expr, cfile, lose, context)
if (token != COMMA)
goto nocomma;
if (!make_let (&stmt -> data.let.statements, "ttl"))
log_fatal ("can't allocate rrname let.");
stmt = stmt -> data.let.statements;
if (!(parse_numeric_expression
(&nexp -> data.ns_add.ttl, cfile, lose))) {
(&stmt -> data.let.expr, cfile, lose))) {
parse_warn (cfile,
"expecting data expression.");
"expecting numeric expression.");
goto badnsupdate;
}
}
#endif
token = next_token (&val, cfile);
if (token != RPAREN)
goto norparen;
......@@ -2354,7 +2429,12 @@ int parse_non_binary (expr, cfile, lose, context)
/* NOT EXISTS is special cased above... */
not_exists:
token = next_token (&val, cfile);
token = peek_token (&val, cfile);
if (token != EXISTS) {
parse_warn (cfile, "expecting DNS prerequisite.");
*lose = 1;
return 0;
}
opcode = expr_ns_not_exists;
goto nsupdatecode;
case TOKEN_ADD:
......@@ -2498,6 +2578,22 @@ int parse_non_binary (expr, cfile, lose, context)
(*expr) -> op = expr_leased_address;
break;
case FILENAME:
token = next_token (&val, cfile);
if (!expression_allocate (expr,
"parse_expression: FILENAME"))
log_fatal ("can't allocate expression");
(*expr) -> op = expr_filename;
break;
case SERVER_NAME:
token = next_token (&val, cfile);
if (!expression_allocate (expr,
"parse_expression: SERVER_NAME"))
log_fatal ("can't allocate expression");
(*expr) -> op = expr_sname;
break;
case LEASE_TIME:
token = next_token (&val, cfile);
if (!expression_allocate (expr,
......@@ -2552,7 +2648,7 @@ int parse_non_binary (expr, cfile, lose, context)
log_fatal ("can't allocate expression");
(*expr) -> op = expr_variable_reference;
(*expr) -> data.variable =
dmalloc (strlen (s) + 1, "parse_expression");
dmalloc (strlen (s) + 1, MDL);
if (!(*expr) -> data.variable)
log_fatal ("can't allocate variable name.");
strcpy ((*expr) -> data.variable, s);
......@@ -2832,8 +2928,7 @@ int parse_non_binary (expr, cfile, lose, context)
if (!expression_allocate (expr, "parse_expression"))
log_fatal ("can't allocate expression");
(*expr) -> op = expr_variable_exists;
(*expr) -> data.variable = dmalloc (strlen (val) + 1,
"parse_expression");
(*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
if (!(*expr)->data.variable)
log_fatal ("can't allocate variable name");
strcpy ((*expr) -> data.variable, val);
......@@ -2851,8 +2946,7 @@ int parse_non_binary (expr, cfile, lose, context)
if (!expression_allocate (expr, "parse_expression"))
log_fatal ("can't allocate expression");
(*expr) -> op = expr_variable_reference;
(*expr) -> data.variable = dmalloc (strlen (val) + 1,
"parse_expression");
(*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
if (!(*expr)->data.variable)
log_fatal ("can't allocate variable name");
strcpy ((*expr) -> data.variable, val);
......@@ -3131,6 +3225,7 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
int len;
unsigned char *ob;
struct iaddr addr;
int num;
switch (*fmt) {
case 'U':
......@@ -3194,9 +3289,19 @@ int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
}
break;
case 'T': /* Lease interval. */
token = next_token (&val, cfile);
if (token != INFINITE)
goto check_number;
putLong (buf, -1);
if (!make_const_data (&t, buf, 4, 0, 1))
return 0;
break;
case 'L': /* Unsigned 32-bit integer... */
case 'l': /* Signed 32-bit integer... */
token = next_token (&val, cfile);
check_number:
if (token != NUMBER) {
need_number:
parse_warn (cfile, "expecting number.");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment