Routines for manipulating parse trees... */
/*
- * Copyright (c) 1996-1999 Internet Software Consortium.
+ * Copyright (c) 1996-2000 Internet Software Consortium.
* Use is subject to license terms which appear in the file named
* ISC-LICENSE that should have accompanied this file when you
* received it. If a file named ISC-LICENSE did not accompany this
#ifndef lint
static char copyright[] =
-"$Id: tree.c,v 1.67 2000/01/08 01:38:52 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
+"$Id: tree.c,v 1.68 2000/01/25 01:16:14 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */
#include "dhcpd.h"
caddr_t car;
pair cdr;
{
- pair foo = (pair)dmalloc (sizeof *foo, "cons");
+ pair foo = (pair)dmalloc (sizeof *foo, MDL);
if (!foo)
log_fatal ("no memory for cons.");
foo -> car = car;
struct expression **expr;
const char *name;
{
- if (!expression_allocate (expr, "make_host_lookup")) {
+ if (!expression_allocate (expr, MDL)) {
log_error ("No memory for host lookup tree node.");
return 0;
}
(*expr) -> op = expr_host_lookup;
if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) {
- expression_dereference (expr, "make_host_lookup");
+ expression_dereference (expr, MDL);
return 0;
}
return 1;
XXX and just add a new reference to a hostname that
XXX already exists, if possible, rather than creating
XXX a new structure. */
- if (!dns_host_entry_allocate (dh, name, "enter_dns_host")) {
+ if (!dns_host_entry_allocate (dh, name, MDL)) {
log_error ("Can't allocate space for new host.");
return 0;
}
{
struct expression *nt;
- if (!expression_allocate (expr, "make_host_lookup")) {
+ if (!expression_allocate (expr, MDL)) {
log_error ("No memory for make_const_data tree node.");
return 0;
}
if (len) {
if (allocate) {
if (!buffer_allocate (&nt -> data.const_data.buffer,
- len + terminated,
- "make_const_data")) {
+ len + terminated, MDL)) {
log_error ("Can't allocate const_data buffer");
- expression_dereference (expr,
- "make_const_data");
+ expression_dereference (expr, MDL);
return 0;
}
nt -> data.const_data.data =
return 1;
}
+int make_const_int (expr, val)
+ struct expression **expr;
+ unsigned long val;
+{
+ if (!expression_allocate (expr, MDL)) {
+ log_error ("No memory for make_const_data tree node.");
+ return 0;
+ }
+
+ (*expr) -> op = expr_const_int;
+ (*expr) -> data.const_int = val;
+ return 1;
+}
+
int make_concat (expr, left, right)
struct expression **expr;
struct expression *left, *right;
if (!left) {
if (!right)
return 0;
- expression_reference (expr, right, "make_concat");
+ expression_reference (expr, right, MDL);
return 1;
}
if (!right) {
- expression_reference (expr, left, "make_concat");
+ expression_reference (expr, left, MDL);
return 1;
}
/* Otherwise, allocate a new node to concatenate the two. */
- if (!expression_allocate (expr, "make_concat")) {
+ if (!expression_allocate (expr, MDL)) {
log_error ("No memory for concatenation expression node.");
return 0;
}
(*expr) -> op = expr_concat;
- expression_reference (&(*expr) -> data.concat [0],
- left, "make_concat");
- expression_reference (&(*expr) -> data.concat [1],
- right, "make_concat");
+ expression_reference (&(*expr) -> data.concat [0], left, MDL);
+ expression_reference (&(*expr) -> data.concat [1], right, MDL);
return 1;
}
struct data_string *name;
{
/* Allocate a new node to store the encapsulation. */
- if (!expression_allocate (expr, "make_encapsulation")) {
+ if (!expression_allocate (expr, MDL)) {
log_error ("No memory for encapsulation expression node.");
return 0;
}
(*expr) -> op = expr_encapsulate;
- data_string_copy (&(*expr) -> data.encapsulate,
- name, "make_concat");
+ data_string_copy (&(*expr) -> data.encapsulate, name, MDL);
return 1;
}
struct expression *length;
{
/* Allocate an expression node to compute the substring. */
- if (!expression_allocate (new, "make_substring")) {
+ if (!expression_allocate (new, MDL)) {
log_error ("no memory for substring expression.");
return 0;
}
(*new) -> op = expr_substring;
- expression_reference (&(*new) -> data.substring.expr,
- expr, "make_concat");
- expression_reference (&(*new) -> data.substring.offset,
- offset, "make_concat");
- expression_reference (&(*new) -> data.substring.len,
- length, "make_concat");
+ expression_reference (&(*new) -> data.substring.expr, expr, MDL);
+ expression_reference (&(*new) -> data.substring.offset, offset, MDL);
+ expression_reference (&(*new) -> data.substring.len, length, MDL);
return 1;
}
struct expression *rv;
/* Allocate a node to enforce a limit on evaluation. */
- if (!expression_allocate (new, "make_limit"))
+ if (!expression_allocate (new, MDL))
log_error ("no memory for limit expression");
(*new) -> op = expr_substring;
- expression_reference (&(*new) -> data.substring.expr,
- expr, "make_limit");
+ expression_reference (&(*new) -> data.substring.expr, expr, MDL);
/* Offset is a constant 0. */
- if (!expression_allocate (&(*new) -> data.substring.offset,
- "make_limit")) {
+ if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) {
log_error ("no memory for limit offset expression");
- expression_dereference (new, "make_limit");
+ expression_dereference (new, MDL);
return 0;
}
(*new) -> data.substring.offset -> op = expr_const_int;
(*new) -> data.substring.offset -> data.const_int = 0;
/* Length is a constant: the specified limit. */
- if (!expression_allocate (&(*new) -> data.substring.len,
- "make_limit")) {
+ if (!expression_allocate (&(*new) -> data.substring.len, MDL)) {
log_error ("no memory for limit length expression");
- expression_dereference (new, "make_limit");
+ expression_dereference (new, MDL);
return 0;
}
(*new) -> data.substring.len -> op = expr_const_int;
struct expression *expr;
struct option *option;
{
- if (!option_cache_allocate (oc, "option_cache"))
+ if (!option_cache_allocate (oc, MDL))
return 0;
if (dp)
- data_string_copy (&(*oc) -> data, dp, "option_cache");
+ data_string_copy (&(*oc) -> data, dp, MDL);
if (expr)
- expression_reference (&(*oc) -> expression,
- expr, "option_cache");
+ expression_reference (&(*oc) -> expression, expr, MDL);
(*oc) -> option = option;
return 1;
}
+int make_let (result, name)
+ struct executable_statement **result;
+ const char *name;
+{
+ if (!(executable_statement_allocate (result, MDL)))
+ return 0;
+
+ (*result) -> op = let_statement;
+ (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL);
+ if (!(*result) -> data.let.name) {
+ executable_statement_dereference (result, MDL);
+ return 0;
+ }
+ strcpy ((*result) -> data.let.name, name);
+ return 1;
+}
+
static int do_host_lookup (result, dns)
struct data_string *result;
struct dns_host_entry *dns;
unsigned new_len;
#ifdef DEBUG_EVAL
- log_debug ("time: now = %d dns = %d %d diff = %d",
+ log_debug ("time: now = %d dns = %d diff = %d",
cur_time, dns -> timeout, cur_time - dns -> timeout);
#endif
? inet_ntoa (*(struct in_addr *)(dns -> data.data))
: 0));
#endif
- data_string_copy (result, &dns -> data, "do_host_lookup");
+ data_string_copy (result, &dns -> data, MDL);
return 1;
}
#ifdef DEBUG_EVAL
/* Okay to try again after a minute. */
dns -> timeout = cur_time + 60;
- data_string_forget (&dns -> data, "do_host_lookup");
+ data_string_forget (&dns -> data, MDL);
return 0;
}
;
/* Dereference the old data, if any. */
- data_string_forget (&dns -> data, "do_host_lookup");
+ data_string_forget (&dns -> data, MDL);
/* Do we need to allocate more memory? */
new_len = count * h -> h_length;
- if (!buffer_allocate (&dns -> data.buffer, new_len, "do_host_lookup"))
+ if (!buffer_allocate (&dns -> data.buffer, new_len, MDL))
{
log_error ("No memory for %s.", dns -> hostname);
return 0;
(dns -> data.len > 4
? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));
#endif
- data_string_copy (result, &dns -> data, "do_host_lookup");
+ data_string_copy (result, &dns -> data, MDL);
return 1;
}
int evaluate_dns_expression (result, packet, lease, in_options,
- cfg_options, expr)
+ cfg_options, scope, expr)
ns_updrec **result;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct expression *expr;
{
ns_updrec *foo;
case expr_ns_add:
r0 = evaluate_numeric_expression (&ttl, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.ns_add.ttl);
goto nsfinish;
nsfinish:
memset (&name, 0, sizeof name);
r1 = evaluate_data_expression (&name, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
expr -> data.ns_add.rrname);
if (r1) {
/* The result of the evaluation may or may not
be NUL-terminated, but we need it
terminated for sure, so we have to allocate
a buffer and terminate it. */
- tname = malloc (name.len + 1);
+ tname = dmalloc (name.len + 1, MDL);
if (!tname) {
r2 = 0;
r1 = 0;
- data_string_forget (&name,
- "evaluate_dns_expression");
+ data_string_forget (&name, MDL);
} else {
memcpy (tname, name.data, name.len);
tname [name.len] = 0;
memset (&data, 0, sizeof data);
r2 = evaluate_data_expression
(&data, packet, lease, in_options,
- cfg_options,
+ cfg_options, scope,
expr -> data.ns_add.rrdata);
}
} else
if (!*result) {
ngood:
if (r2) {
- data_string_forget (&data,
- "evaluate_dns_expression");
+ data_string_forget (&data, MDL);
r2 = 0;
}
} else {
it. This should be fixed when the new
resolver is merged. */
if (data.len == 4) {
- (*result) -> r_data = malloc (16);
+ (*result) -> r_data = dmalloc (16, MDL);
if (!(*result) -> r_data)
goto dpngood;
sprintf ((*result) -> r_data,
strlen ((*result) -> r_data);
} else {
(*result) -> r_size = data.len;
- (*result) -> r_data = malloc (data.len);
+ (*result) -> r_data = dmalloc (data.len,
+ MDL);
if (!(*result) -> r_data) {
dpngood: /* double plus ungood. */
res_freeupdrec (*result);
}
}
if (r1) {
- data_string_forget (&name, "evaluate_dns_expression");
- free (tname);
+ data_string_forget (&name, MDL);
+ dfree (tname, MDL);
}
if (r2)
- data_string_forget (&data, "evaluate_dns_expression");
+ data_string_forget (&data, MDL);
/* One flaw in the thinking here: an IP address and an
ASCII string both look like data expressions, but
for A records, we want an ASCII string, not a
binary IP address. Do I need to turn binary IP
addresses into a seperate type? */
- return r0 && r1 && r2 && *result;
+ return (r0 && r1 &&
+ (r2 || expr -> op != expr_ns_add) && *result);
#else
case expr_ns_add:
case expr_encode_int32:
case expr_binary_to_ascii:
case expr_reverse:
+ case expr_filename:
+ case expr_sname:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
}
int evaluate_boolean_expression (result, packet, lease, in_options,
- cfg_options, expr)
+ cfg_options, scope, expr)
int *result;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct expression *expr;
{
struct data_string left, right;
memset (&left, 0, sizeof left);
sleft = evaluate_data_expression (&left, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.equal [0]);
memset (&right, 0, sizeof right);
sright = evaluate_data_expression (&right, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.equal [1]);
if (sleft && sright) {
if (left.len == right.len &&
: "NULL"));
#endif
if (sleft)
- data_string_forget (&left,
- "evaluate_boolean_expression");
+ data_string_forget (&left, MDL);
if (sright)
- data_string_forget (&right,
- "evaluate_boolean_expression");
+ data_string_forget (&right, MDL);
return sleft && sright;
case expr_and:
sleft = evaluate_boolean_expression (&bleft, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.and [0]);
sright = evaluate_boolean_expression (&bright, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.and [1]);
#if defined (DEBUG_EXPRESSIONS)
case expr_or:
sleft = evaluate_boolean_expression (&bleft, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.or [0]);
sright = evaluate_boolean_expression (&bright, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.or [1]);
#if defined (DEBUG_EXPRESSIONS)
log_debug ("bool: or (%s, %s) = %s",
case expr_not:
sleft = evaluate_boolean_expression (&bleft, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.not);
#if defined (DEBUG_EXPRESSIONS)
log_debug ("bool: not (%s) = %s",
!((*expr -> data.option -> universe -> get_func)
(&left, expr -> data.exists -> universe,
packet, lease, in_options, cfg_options, in_options,
- expr -> data.exists -> code)))
+ scope, expr -> data.exists -> code)))
*result = 0;
else {
*result = 1;
- data_string_forget (&left,
- "evaluate_boolean_expression");
+ data_string_forget (&left, MDL);
}
#if defined (DEBUG_EXPRESSIONS)
log_debug ("bool: exists %s.%s = %s",
- expr -> data.option -> universe -> name,
- expr -> data.option -> name, *result ? "true" : "false");
+ expr -> data.option -> universe -> name,
+ expr -> data.option -> name,
+ *result ? "true" : MDL);
#endif
return 1;
return 1;
case expr_variable_exists:
- for (binding = lease -> bindings; binding;
- binding = binding -> next) {
- if (!(strcasecmp
- (lease -> bindings -> name,
- expr -> data.variable)))
- break;
- }
+ binding = find_binding (scope, expr -> data.variable);
+
if (binding) {
if (binding -> value.data)
*result = 1;
}
int evaluate_data_expression (result, packet, lease,
- in_options, cfg_options, expr)
+ in_options, cfg_options, scope, expr)
struct data_string *result;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct expression *expr;
{
struct data_string data, other;
case expr_substring:
memset (&data, 0, sizeof data);
s0 = evaluate_data_expression (&data, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
expr -> data.substring.expr);
/* Evaluate the offset and length. */
s1 = evaluate_numeric_expression
(&offset, packet, lease, in_options, cfg_options,
- expr -> data.substring.offset);
+ scope, expr -> data.substring.offset);
s2 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.substring.len);
if (s0 && s1 && s2) {
return an empty string. Otherwise, do the
adjustments and return what's left. */
if (data.len > offset) {
- data_string_copy (result, &data,
- "evaluate_data_expression");
+ data_string_copy (result, &data, MDL);
result -> len -= offset;
if (result -> len > len) {
result -> len = len;
(s3 ? print_hex_2 (result -> len, result -> data, 30)
: "NULL"));
#endif
+ if (s0)
+ data_string_forget (&data, MDL);
if (s3)
return 1;
- data_string_forget (&data, "evaluate_data_expression");
return 0;
case expr_suffix:
memset (&data, 0, sizeof data);
s0 = evaluate_data_expression (&data, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
expr -> data.suffix.expr);
/* Evaluate the length. */
s1 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.substring.len);
if (s0 && s1) {
- data_string_copy (result, &data,
- "evaluate_data_expression");
+ data_string_copy (result, &data, MDL);
/* If we are returning the last N bytes of a
string whose length is <= N, just return
(result, expr -> data.option -> universe,
packet, lease,
in_options, cfg_options, in_options,
- expr -> data.option -> code));
+ scope, expr -> data.option -> code));
else
s0 = 0;
(result, expr -> data.option -> universe,
packet, lease,
in_options, cfg_options, cfg_options,
- expr -> data.option -> code));
+ scope, expr -> data.option -> code));
else
s0 = 0;
return 0;
}
result -> len = packet -> raw -> hlen + 1;
- if (buffer_allocate (&result -> buffer, result -> len,
- "evaluate_data_expression")) {
+ if (buffer_allocate (&result -> buffer, result -> len, MDL)) {
result -> data = &result -> buffer -> data [0];
result -> buffer -> data [0] = packet -> raw -> htype;
memcpy (&result -> buffer -> data [1],
s0 = evaluate_numeric_expression (&offset, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.packet.offset);
s1 = evaluate_numeric_expression (&len,
packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.packet.len);
if (s0 && s1 && offset < packet -> packet_length) {
if (offset + len > packet -> packet_length)
packet -> packet_length - offset;
else
result -> len = len;
- if (buffer_allocate (&result -> buffer, result -> len,
- "evaluate_data_expression")) {
+ if (buffer_allocate (&result -> buffer,
+ result -> len, MDL)) {
result -> data = &result -> buffer -> data [0];
memcpy (result -> buffer -> data,
(((unsigned char *)(packet -> raw))
if (cfg_options)
s0 = option_space_encapsulate
(result, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
&expr -> data.encapsulate);
else
s0 = 0;
log_debug ("data: encapsulate (%s) = %s",
expr -> data.encapsulate.data,
s0 ? print_hex_1 (result -> len,
- result -> data, 60) : "null");
+ result -> data, 60) : "NULL");
#endif
return s0;
expr -> data.const_data.data, 60));
#endif
data_string_copy (result,
- &expr -> data.const_data,
- "evaluate_data_expression");
+ &expr -> data.const_data, MDL);
return 1;
/* Hostname lookup... */
case expr_concat:
memset (&data, 0, sizeof data);
s0 = evaluate_data_expression (&data, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
expr -> data.concat [0]);
memset (&other, 0, sizeof other);
s1 = evaluate_data_expression (&other, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
expr -> data.concat [1]);
if (s0 && s1) {
result -> len = data.len + other.len;
if (!buffer_allocate (&result -> buffer,
(result -> len +
- other.terminated),
- "expr_concat")) {
+ other.terminated), MDL)) {
log_error ("data: concat: no memory");
result -> len = 0;
- data_string_forget (&data, "expr_concat");
- data_string_forget (&other, "expr_concat");
+ data_string_forget (&data, MDL);
+ data_string_forget (&other, MDL);
return 0;
}
result -> data = &result -> buffer -> data [0];
memcpy (&result -> buffer -> data [data.len],
other.data, other.len + other.terminated);
} else if (s0)
- data_string_forget (&data, "expr_concat");
+ data_string_forget (&data, MDL);
else if (s1)
- data_string_forget (&other, "expr_concat");
+ data_string_forget (&other, MDL);
#if defined (DEBUG_EXPRESSIONS)
log_debug ("data: concat (%s, %s) = %s",
s0 ? print_hex_1 (data.len, data.data, 20) : "NULL",
case expr_encode_int8:
s0 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.packet.len);
if (s0) {
result -> len = 1;
- if (!buffer_allocate (&result -> buffer, 1,
- "expr_encode_int8")) {
+ if (!buffer_allocate (&result -> buffer, 1, MDL)) {
log_error ("data: encode_int8: no memory");
result -> len = 0;
s0 = 0;
case expr_encode_int16:
s0 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.packet.len);
if (s0) {
result -> len = 2;
- if (!buffer_allocate (&result -> buffer, 2,
- "expr_encode_int16")) {
+ if (!buffer_allocate (&result -> buffer, 2, MDL)) {
log_error ("data: encode_int16: no memory");
result -> len = 0;
s0 = 0;
case expr_encode_int32:
s0 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.packet.len);
if (s0) {
result -> len = 4;
- if (!buffer_allocate (&result -> buffer, 4,
- "expr_encode_int32")) {
+ if (!buffer_allocate (&result -> buffer, 4, MDL)) {
log_error ("data: encode_int32: no memory");
result -> len = 0;
s0 = 0;
/* Evaluate the base (offset) and width (len): */
s0 = evaluate_numeric_expression
(&offset, packet, lease, in_options, cfg_options,
- expr -> data.b2a.base);
+ scope, expr -> data.b2a.base);
s1 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
+ scope,
expr -> data.b2a.width);
/* Evaluate the seperator string. */
memset (&data, 0, sizeof data);
s2 = evaluate_data_expression (&data, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
expr -> data.b2a.seperator);
/* Evaluate the data to be converted. */
memset (&other, 0, sizeof other);
s3 = evaluate_data_expression (&other, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
expr -> data.b2a.buffer);
if (s0 && s1 && s2 && s3) {
buflen += data.len;
}
- if (!buffer_allocate (&result -> buffer, buflen + 1,
- "binary-to-ascii")) {
+ if (!buffer_allocate (&result -> buffer,
+ buflen + 1, MDL)) {
log_error ("data: binary-to-ascii: no memory");
status = 0;
goto b2a_out;
: "NULL"));
#endif
if (s2)
- data_string_forget (&data, "binary-to-ascii");
+ data_string_forget (&data, MDL);
if (s3)
- data_string_forget (&other, "binary-to-ascii");
+ data_string_forget (&other, MDL);
if (status)
return 1;
return 0;
/* Evaluate the width (len): */
s0 = evaluate_numeric_expression
(&len, packet, lease, in_options, cfg_options,
- expr -> data.reverse.width);
+ scope, expr -> data.reverse.width);
/* Evaluate the data. */
memset (&data, 0, sizeof data);
s1 = evaluate_data_expression (&data, packet, lease,
- in_options, cfg_options,
+ in_options, cfg_options, scope,
expr -> data.reverse.buffer);
if (s0 && s1) {
}
/* XXX reverse in place? I don't think we can. */
- if (!buffer_allocate (&result -> buffer, data.len,
- "reverse")) {
+ if (!buffer_allocate (&result -> buffer,
+ data.len, MDL)) {
log_error ("data: reverse: no memory");
status = 0;
goto reverse_out;
: "NULL"));
#endif
if (s0)
- data_string_forget (&data, "evaluate_data_expression");
+ data_string_forget (&data, MDL);
if (status)
return 1;
return 0;
return 0;
}
result -> len = lease -> ip_addr.len;
- if (buffer_allocate (&result -> buffer, result -> len,
- "leased-address")) {
+ if (buffer_allocate (&result -> buffer, result -> len, MDL)) {
result -> data = &result -> buffer -> data [0];
memcpy (&result -> buffer -> data [0],
lease -> ip_addr.iabuf, lease -> ip_addr.len);
case expr_pick_first_value:
memset (&data, 0, sizeof data);
if ((evaluate_data_expression
- (result, packet, lease, in_options, cfg_options,
+ (result, packet, lease, in_options, cfg_options, scope,
expr -> data.pick_first_value.car))) {
#if defined (DEBUG_EXPRESSIONS)
log_debug ("data: pick_first_value (%s, ???)",
if (expr -> data.pick_first_value.cdr &&
(evaluate_data_expression
- (result, packet, lease, in_options, cfg_options,
+ (result, packet, lease, in_options, cfg_options, scope,
expr -> data.pick_first_value.cdr))) {
#if defined (DEBUG_EXPRESSIONS)
log_debug ("data: pick_first_value (NULL, %s)",
return 0;
}
result -> len = strlen (lease -> host -> name);
- if (buffer_allocate (&result -> buffer, result -> len + 1,
- "host-decl-name")) {
+ if (buffer_allocate (&result -> buffer,
+ result -> len + 1, MDL)) {
result -> data = &result -> buffer -> data [0];
strcpy ((char *)&result -> buffer -> data [0],
lease -> host -> name);
return 0;
case expr_variable_reference:
- for (binding = lease -> bindings; binding;
- binding = binding -> next) {
- if (!(strcasecmp (lease -> bindings -> name,
- expr -> data.variable)))
- break;
- }
+ binding = find_binding (scope, expr -> data.variable);
+
if (binding) {
if (binding -> value.data) {
- data_string_copy (result, &binding -> value,
- "variable-reference");
+ data_string_copy (result,
+ &binding -> value, MDL);
s0 = 1;
} else
s0 = 0;
#endif
return s0;
+ /* Extract the filename. */
+ case expr_filename:
+ if (packet && packet -> raw -> file [0]) {
+ char *fn =
+ memchr (packet -> raw -> file, 0,
+ sizeof packet -> raw -> file);
+ if (!fn)
+ fn = ((char *)packet -> raw -> file +
+ sizeof packet -> raw -> file);
+ result -> len = fn - &(packet -> raw -> file [0]);
+ if (buffer_allocate (&result -> buffer,
+ result -> len + 1, MDL)) {
+ result -> data = &result -> buffer -> data [0];
+ memcpy (&result -> buffer -> data [0],
+ packet -> raw -> file,
+ result -> len);
+ result -> buffer -> data [result -> len] = 0;
+ result -> terminated = 1;
+ s0 = 1;
+ } else {
+ log_error ("data: filename: no memory.");
+ s0 = 0;
+ }
+ } else
+ s0 = 0;
+
+#if defined (DEBUG_EXPRESSIONS)
+ log_info ("data: filename = \"%s\"",
+ s0 ? result -> data : "NULL");
+#endif
+ return s0;
+
+ /* Extract the server name. */
+ case expr_sname:
+ if (packet && packet -> raw -> sname [0]) {
+ char *fn =
+ memchr (packet -> raw -> sname, 0,
+ sizeof packet -> raw -> sname);
+ if (!fn)
+ fn = ((char *)packet -> raw -> sname +
+ sizeof packet -> raw -> sname);
+ result -> len = fn - &packet -> raw -> sname [0];
+ if (buffer_allocate (&result -> buffer,
+ result -> len + 1, MDL)) {
+ result -> data = &result -> buffer -> data [0];
+ memcpy (&result -> buffer -> data [0],
+ packet -> raw -> sname,
+ result -> len);
+ result -> buffer -> data [result -> len] = 0;
+ result -> terminated = 1;
+ s0 = 1;
+ } else {
+ log_error ("data: sname: no memory.");
+ s0 = 0;
+ }
+ } else
+ s0 = 0;
+
+#if defined (DEBUG_EXPRESSIONS)
+ log_info ("data: sname = \"%s\"",
+ s0 ? result -> data : "NULL");
+#endif
+ return s0;
+
case expr_check:
case expr_equal:
case expr_not_equal:
}
int evaluate_numeric_expression (result, packet, lease,
- in_options, cfg_options, expr)
+ in_options, cfg_options, scope, expr)
unsigned long *result;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct expression *expr;
{
struct data_string data;
case expr_encode_int32:
case expr_binary_to_ascii:
case expr_reverse:
+ case expr_filename:
+ case expr_sname:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
memset (&data, 0, sizeof data);
status = evaluate_data_expression
(&data, packet, lease, in_options, cfg_options,
- expr -> data.extract_int);
+ scope, expr -> data.extract_int);
if (status)
*result = data.data [0];
#if defined (DEBUG_EXPRESSIONS)
status ? print_hex_1 (data.len, data.data, 60) : "NULL",
status ? print_dec_1 (*result) : "NULL" );
#endif
- if (status)
- data_string_forget (&data, "expr_extract_int8");
+ if (status) data_string_forget (&data, MDL);
return status;
case expr_extract_int16:
memset (&data, 0, sizeof data);
status = (evaluate_data_expression
(&data, packet, lease, in_options, cfg_options,
- expr -> data.extract_int));
+ scope, expr -> data.extract_int));
if (status && data.len >= 2)
*result = getUShort (data.data);
#if defined (DEBUG_EXPRESSIONS)
print_hex_1 (data.len, data.data, 60) : "NULL"),
*result);
#endif
- if (status)
- data_string_forget (&data, "expr_extract_int16");
+ if (status) data_string_forget (&data, MDL);
return (status && data.len >= 2);
case expr_extract_int32:
memset (&data, 0, sizeof data);
status = (evaluate_data_expression
(&data, packet, lease, in_options, cfg_options,
- expr -> data.extract_int));
+ scope, expr -> data.extract_int));
if (status && data.len >= 4)
*result = getULong (data.data);
#if defined (DEBUG_EXPRESSIONS)
print_hex_1 (data.len, data.data, 60) : "NULL"),
*result);
#endif
- if (status)
- data_string_forget (&data, "expr_extract_int32");
+ if (status) data_string_forget (&data, MDL);
return (status && data.len >= 4);
case expr_const_int:
nut = 0;
status = (evaluate_dns_expression
(&nut, packet, lease, in_options, cfg_options,
- cur -> data.dns_transaction.car));
+ scope, cur -> data.dns_transaction.car));
if (!status)
goto dns_bad;
APPEND (uq, nut, r_link);
if (res_nupdate (&res, HEAD (uq), NULL))
*result = NOERROR;
else
- *result = res.res_h_errno;
+ /* The resolver doesn't return any actual error
+ codes - just 1 for success, zero for failure! */
+ /* *result = res.res_h_errno; */
+ *result = SERVFAIL;
status = 1;
print_dns_status ((int)*result, &uq);
while (!EMPTY (uq)) {
ns_updrec *tmp = HEAD (uq);
UNLINK (uq, tmp, r_link);
- if (tmp -> r_data)
- dfree (tmp -> r_data,
- "evaluate_numeric_expression");
+ if (tmp -> r_data) {
+ dfree (tmp -> r_data, MDL);
+ tmp -> r_data = (char *)0;
+ }
+ if (tmp -> r_dname) {
+ dfree (tmp -> r_dname, MDL);
+ tmp -> r_dname = (char *)0;
+ }
res_freeupdrec (tmp);
}
return status;
result of that evaluation. There should never be both an expression
and a valid data_string. */
-int evaluate_option_cache (result, packet, lease, in_options, cfg_options, oc)
+int evaluate_option_cache (result, packet, lease,
+ in_options, cfg_options, scope, oc, file, line)
struct data_string *result;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct option_cache *oc;
+ const char *file;
+ int line;
{
if (oc -> data.len) {
- data_string_copy (result,
- &oc -> data, "evaluate_option_cache");
+ data_string_copy (result, &oc -> data, file, line);
return 1;
}
if (!oc -> expression)
return 0;
- return evaluate_data_expression (result, packet, lease, in_options,
- cfg_options,
+ return evaluate_data_expression (result, packet, lease,
+ in_options, cfg_options, scope,
oc -> expression);
}
/* Evaluate an option cache and extract a boolean from the result,
returning the boolean. Return false if there is no data. */
-int evaluate_boolean_option_cache (ignorep,
- packet, lease, in_options, cfg_options, oc)
+int evaluate_boolean_option_cache (ignorep, packet, lease, in_options,
+ cfg_options, scope, oc, file, line)
int *ignorep;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct option_cache *oc;
+ const char *file;
+ int line;
{
struct data_string ds;
int result;
memset (&ds, 0, sizeof ds);
if (!evaluate_option_cache (&ds, packet, lease,
- in_options, cfg_options, oc))
+ in_options, cfg_options, scope, oc))
return 0;
if (ds.len) {
} else
*ignorep = 0;
} else
- result = 0;
- data_string_forget (&ds, "evaluate_boolean_option_cache");
+ result = 0; data_string_forget (&ds, MDL);
return result;
}
/* Evaluate a boolean expression and return the result of the evaluation,
or FALSE if it failed. */
-int evaluate_boolean_expression_result (ignorep, packet, lease,
- in_options, cfg_options, expr)
+int evaluate_boolean_expression_result (ignorep, packet, lease, in_options,
+ cfg_options, scope, expr, file, line)
int *ignorep;
struct packet *packet;
struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
+ struct binding_scope *scope;
struct expression *expr;
+ const char *file;
+ int line;
{
int result;
return 0;
if (!evaluate_boolean_expression (&result, packet, lease,
- in_options, cfg_options, expr))
+ in_options, cfg_options,
+ scope, expr, file, line))
return 0;
if (result == 2) {
/* Decrement the reference count. If it's nonzero, we're
done. */
- if (--(expr -> refcnt) > 0)
+ --(expr -> refcnt);
+ rc_register (file, line, expr, expr -> refcnt);
+ if (expr -> refcnt > 0)
return;
if (expr -> refcnt < 0) {
log_error ("expression_dereference: negative refcnt!");
+#if defined (DEBUG_RC_HISTORY)
+ dump_rc_history ();
+#endif
#if defined (POINTER_DEBUG)
abort ();
#else
/* No subexpressions. */
case expr_leased_address:
case expr_lease_time:
+ case expr_filename:
+ case expr_sname:
case expr_const_int:
case expr_check:
case expr_option:
default:
break;
}
-
- free_expression (expr, "expression_dereference");
-}
-
-/* Make a copy of the data in data_string, upping the buffer reference
- count if there's a buffer. */
-
-void data_string_copy (dest, src, name)
- struct data_string *dest;
- struct data_string *src;
- const char *name;
-{
- if (src -> buffer)
- buffer_reference (&dest -> buffer, src -> buffer, name);
- dest -> data = src -> data;
- dest -> terminated = src -> terminated;
- dest -> len = src -> len;
-}
-
-/* Release the reference count to a data string's buffer (if any) and
- zero out the other information, yielding the null data string. */
-
-void data_string_forget (data, name)
- struct data_string *data;
- const char *name;
-{
- if (data -> buffer)
- buffer_dereference (&data -> buffer, name);
- memset (data, 0, sizeof *data);
-}
-
-/* Make a copy of the data in data_string, upping the buffer reference
- count if there's a buffer. */
-
-void data_string_truncate (dp, len)
- struct data_string *dp;
- int len;
-{
- if (len < dp -> len) {
- dp -> terminated = 0;
- dp -> len = len;
- }
+ free_expression (expr, MDL);
}
int is_dns_expression (expr)
expr -> op == expr_encode_int32 ||
expr -> op == expr_host_lookup ||
expr -> op == expr_binary_to_ascii ||
+ expr -> op == expr_filename ||
+ expr -> op == expr_sname ||
expr -> op == expr_reverse ||
expr -> op == expr_pick_first_value ||
expr -> op == expr_host_decl_name ||
case expr_known:
case expr_binary_to_ascii:
case expr_reverse:
+ case expr_filename:
+ case expr_sname:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
case expr_known:
case expr_binary_to_ascii:
case expr_reverse:
+ case expr_filename:
+ case expr_sname:
case expr_pick_first_value:
case expr_host_decl_name:
case expr_config_option:
}
return col;
}
+
+struct binding *find_binding (struct binding_scope *scope, const char *name)
+{
+ struct binding *bp;
+ struct binding_scope *s;
+
+ for (s = scope; s; s = s -> outer) {
+ for (bp = s -> bindings; bp; bp = bp -> next) {
+ if (!strcasecmp (name, bp -> name)) {
+ return bp;
+ }
+ }
+ }
+ return (struct binding *)0;
+}
+
+int free_bindings (struct binding_scope *scope, const char *name)
+{
+ struct binding *bp, *next;
+
+ for (bp = scope -> bindings; bp; bp = next) {
+ next = bp -> next;
+ if (bp -> name)
+ dfree (bp -> name, name);
+ if (bp -> value.data)
+ data_string_forget (&bp -> value, name);
+ dfree (bp, name);
+ }
+ scope -> bindings = (struct binding *)0;
+ return 1;
+}
+
+int binding_scope_dereference (ptr, name)
+ struct binding_scope **ptr;
+ const char *name;
+{
+ struct binding_scope *bp;
+
+ if (!ptr || !*ptr) {
+ log_error ("Null pointer in binding_scope_dereference: %s",
+ name);
+#if defined (POINTER_DEBUG)
+ abort ();
+#else
+ return 0;
+#endif
+ }
+
+ if ((*ptr) -> bindings)
+ free_bindings (*ptr, name);
+ dfree ((*ptr), name);
+ *ptr = (struct binding_scope *)0;
+ return 1;
+}
+
/* vim: set tabstop=8: */