2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-01 14:55:30 +00:00

- Regularize expression evaluation calls so that they are all passed a pointer

to the incoming packet, if any, the current lease, if any, the parsed
  incoming options, and the in-scope configuration file options.
- Incoming packets are now reference counted, so that the callee can save
  them for later expression evaluation (e.g., in dhcp_reply).
This commit is contained in:
Ted Lemon
1999-07-31 18:03:55 +00:00
parent 8cdb80a772
commit 4038ec529e
2 changed files with 227 additions and 160 deletions

View File

@@ -22,7 +22,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: options.c,v 1.44 1999/07/06 16:53:30 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n"; "$Id: options.c,v 1.45 1999/07/31 18:03:54 mellon Exp $ Copyright (c) 1995, 1996 The Internet Software Consortium. All rights reserved.\n";
#endif /* not lint */ #endif /* not lint */
#define DHCP_OPTION_DATA #define DHCP_OPTION_DATA
@@ -233,13 +233,14 @@ int parse_agent_information_option (packet, len, data)
three seperate buffers if needed. This allows us to cons up a set three seperate buffers if needed. This allows us to cons up a set
of vendor options using the same routine. */ of vendor options using the same routine. */
int cons_options (inpacket, outpacket, lease, int cons_options (inpacket, outpacket, lease, mms, in_options, cfg_options,
mms, options, overload, terminate, bootpp, prl) overload, terminate, bootpp, prl)
struct packet *inpacket; struct packet *inpacket;
struct dhcp_packet *outpacket; struct dhcp_packet *outpacket;
struct lease *lease; struct lease *lease;
int mms; int mms;
struct option_state *options; struct option_state *in_options;
struct option_state *cfg_options;
int overload; /* Overload flags that may be set. */ int overload; /* Overload flags that may be set. */
int terminate; int terminate;
int bootpp; int bootpp;
@@ -267,8 +268,8 @@ int cons_options (inpacket, outpacket, lease,
if (!mms && inpacket && if (!mms && inpacket &&
(op = lookup_option (&dhcp_universe, inpacket -> options, (op = lookup_option (&dhcp_universe, inpacket -> options,
DHO_DHCP_MAX_MESSAGE_SIZE))) { DHO_DHCP_MAX_MESSAGE_SIZE))) {
evaluate_option_cache (&ds, inpacket, evaluate_option_cache (&ds, inpacket, lease,
inpacket -> options, lease, op); in_options, cfg_options, op);
if (ds.len >= sizeof (u_int16_t)) if (ds.len >= sizeof (u_int16_t))
mms = getUShort (ds.data); mms = getUShort (ds.data);
data_string_forget (&ds, "cons_options"); data_string_forget (&ds, "cons_options");
@@ -329,13 +330,13 @@ int cons_options (inpacket, outpacket, lease,
space, and the first for loop is skipped, because space, and the first for loop is skipped, because
it's slightly more general to do it this way, it's slightly more general to do it this way,
taking the 1Q99 DHCP futures work into account. */ taking the 1Q99 DHCP futures work into account. */
if (options -> site_code_min) { if (cfg_options -> site_code_min) {
for (i = 0; i < OPTION_HASH_SIZE; i++) { for (i = 0; i < OPTION_HASH_SIZE; i++) {
hash = options -> universes [dhcp_universe.index]; hash = cfg_options -> universes [dhcp_universe.index];
for (pp = hash [i]; pp; pp = pp -> cdr) { for (pp = hash [i]; pp; pp = pp -> cdr) {
op = (struct option_cache *)(pp -> car); op = (struct option_cache *)(pp -> car);
if (op -> option -> code < if (op -> option -> code <
options -> site_code_min && cfg_options -> site_code_min &&
priority_len < PRIORITY_COUNT) priority_len < PRIORITY_COUNT)
priority_list [priority_len++] = priority_list [priority_len++] =
op -> option -> code; op -> option -> code;
@@ -347,11 +348,12 @@ int cons_options (inpacket, outpacket, lease,
is no site option space, we'll be cycling through the is no site option space, we'll be cycling through the
dhcp option space. */ dhcp option space. */
for (i = 0; i < OPTION_HASH_SIZE; i++) { for (i = 0; i < OPTION_HASH_SIZE; i++) {
hash = options -> universes [options -> site_universe]; hash = (cfg_options -> universes
[cfg_options -> site_universe]);
for (pp = hash [i]; pp; pp = pp -> cdr) { for (pp = hash [i]; pp; pp = pp -> cdr) {
op = (struct option_cache *)(pp -> car); op = (struct option_cache *)(pp -> car);
if (op -> option -> code >= if (op -> option -> code >=
options -> site_code_min && cfg_options -> site_code_min &&
priority_len < PRIORITY_COUNT) priority_len < PRIORITY_COUNT)
priority_list [priority_len++] = priority_list [priority_len++] =
op -> option -> code; op -> option -> code;
@@ -364,8 +366,9 @@ int cons_options (inpacket, outpacket, lease,
(main_buffer_size - 7 + (main_buffer_size - 7 +
((overload & 1) ? DHCP_FILE_LEN : 0) + ((overload & 1) ? DHCP_FILE_LEN : 0) +
((overload & 2) ? DHCP_SNAME_LEN : 0)), ((overload & 2) ? DHCP_SNAME_LEN : 0)),
inpacket,
lease, lease,
options, in_options, cfg_options,
priority_list, priority_len, priority_list, priority_len,
main_buffer_size, main_buffer_size,
(main_buffer_size + (main_buffer_size +
@@ -437,8 +440,8 @@ int cons_options (inpacket, outpacket, lease,
/* We tack any agent options onto the end of the packet after /* We tack any agent options onto the end of the packet after
we've put it together. */ we've put it together. */
if (options -> universe_count > agent_universe.index && if (cfg_options -> universe_count > agent_universe.index &&
options -> universes [agent_universe.index]) { cfg_options -> universes [agent_universe.index]) {
int len = 0; int len = 0;
struct agent_options *a; struct agent_options *a;
struct option_tag *o; struct option_tag *o;
@@ -446,7 +449,7 @@ int cons_options (inpacket, outpacket, lease,
/* Cycle through the options, appending them to the /* Cycle through the options, appending them to the
buffer. */ buffer. */
for (a = ((struct agent_options *) for (a = ((struct agent_options *)
options -> universes [agent_universe.index]); cfg_options -> universes [agent_universe.index]);
a; a = a -> next) { a; a = a -> next) {
if (agentix + a -> length + 3 + DHCP_FIXED_LEN <= if (agentix + a -> length + 3 + DHCP_FIXED_LEN <=
dhcp_max_agent_option_packet_length) { dhcp_max_agent_option_packet_length) {
@@ -474,12 +477,15 @@ int cons_options (inpacket, outpacket, lease,
/* Store all the requested options into the requested buffer. */ /* Store all the requested options into the requested buffer. */
int store_options (buffer, buflen, lease, options, priority_list, priority_len, int store_options (buffer, buflen, packet, lease,
first_cutoff, second_cutoff, terminate) in_options, cfg_options, priority_list,
priority_len, first_cutoff, second_cutoff, terminate)
unsigned char *buffer; unsigned char *buffer;
int buflen; int buflen;
struct packet *packet;
struct lease *lease; struct lease *lease;
struct option_state *options; struct option_state *in_options;
struct option_state *cfg_options;
int *priority_list; int *priority_list;
int priority_len; int priority_len;
int first_cutoff, second_cutoff; int first_cutoff, second_cutoff;
@@ -524,12 +530,12 @@ int store_options (buffer, buflen, lease, options, priority_list, priority_len,
/* Look up the option in the site option space if the code /* Look up the option in the site option space if the code
is above the cutoff, otherwise in the DHCP option space. */ is above the cutoff, otherwise in the DHCP option space. */
if (code >= options -> site_code_min) if (code >= cfg_options -> site_code_min)
oc = lookup_option oc = lookup_option
(universes [options -> site_universe], (universes [cfg_options -> site_universe],
options, code); cfg_options, code);
else else
oc = lookup_option (&dhcp_universe, options, code); oc = lookup_option (&dhcp_universe, cfg_options, code);
/* If no data is available for this option, skip it. */ /* If no data is available for this option, skip it. */
if (!oc) { if (!oc) {
@@ -537,8 +543,8 @@ int store_options (buffer, buflen, lease, options, priority_list, priority_len,
} }
/* Find the value of the option... */ /* Find the value of the option... */
evaluate_option_cache (&od, (struct packet *)0, evaluate_option_cache (&od, packet, lease,
options, lease, oc); in_options, cfg_options, oc);
if (!od.len) { if (!od.len) {
continue; continue;
} }
@@ -784,63 +790,14 @@ char *pretty_print_option (code, data, len, emit_commas, emit_quotes)
return optbuf; return optbuf;
} }
void do_packet (interface, packet, len, from_port, from, hfrom) int hashed_option_get (result, universe, packet, lease,
struct interface_info *interface; in_options, cfg_options, options, code)
struct dhcp_packet *packet;
int len;
unsigned int from_port;
struct iaddr from;
struct hardware *hfrom;
{
struct packet tp;
int i;
struct option_cache *op;
memset (&tp, 0, sizeof tp);
tp.raw = packet;
tp.packet_length = len;
tp.client_port = from_port;
tp.client_addr = from;
tp.interface = interface;
tp.haddr = hfrom;
if (packet -> hlen > sizeof packet -> chaddr) {
log_info ("Discarding packet with bogus hlen.");
return;
}
if (!parse_options (&tp)) {
if (tp.options)
option_state_dereference (&tp.options, "do_packet");
return;
}
if (tp.options_valid &&
(op = lookup_option (&dhcp_universe, tp.options,
DHO_DHCP_MESSAGE_TYPE))) {
struct data_string dp;
memset (&dp, 0, sizeof dp);
evaluate_option_cache (&dp, &tp, tp.options,
(struct lease *)0, op);
if (dp.len > 0)
tp.packet_type = dp.data [0];
else
tp.packet_type = 0;
data_string_forget (&dp, "do_packet");
}
if (tp.packet_type)
dhcp (&tp);
else
bootp (&tp);
option_state_dereference (&tp.options, "do_packet");
}
int hashed_option_get (result, universe, packet, lease, options, code)
struct data_string *result; struct data_string *result;
struct universe *universe; struct universe *universe;
struct packet *packet; struct packet *packet;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct option_state *options; struct option_state *options;
int code; int code;
{ {
@@ -851,17 +808,20 @@ int hashed_option_get (result, universe, packet, lease, options, code)
oc = ((*universe -> lookup_func) (universe, options, code)); oc = ((*universe -> lookup_func) (universe, options, code));
if (!oc) if (!oc)
return 0; return 0;
if (!evaluate_option_cache (result, packet, if (!evaluate_option_cache (result, packet, lease,
options, lease, oc)) in_options, cfg_options, oc))
return 0; return 0;
return 1; return 1;
} }
int agent_option_get (result, universe, packet, lease, options, code) int agent_option_get (result, universe, packet, lease,
in_options, cfg_options, options, code)
struct data_string *result; struct data_string *result;
struct universe *universe; struct universe *universe;
struct packet *packet; struct packet *packet;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct option_state *options; struct option_state *options;
int code; int code;
{ {
@@ -1224,10 +1184,13 @@ int agent_option_state_dereference (universe, state)
return 1; return 1;
} }
int store_option (result, universe, lease, oc) int store_option (result, universe, packet, lease, in_options, cfg_options, oc)
struct data_string *result; struct data_string *result;
struct universe *universe; struct universe *universe;
struct packet *packet;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct option_cache *oc; struct option_cache *oc;
{ {
struct data_string d1, d2; struct data_string d1, d2;
@@ -1235,8 +1198,8 @@ int store_option (result, universe, lease, oc)
memset (&d1, 0, sizeof d1); memset (&d1, 0, sizeof d1);
memset (&d2, 0, sizeof d2); memset (&d2, 0, sizeof d2);
if (evaluate_option_cache (&d2, (struct packet *)0, if (evaluate_option_cache (&d2, packet, lease,
(struct option_state *)0, lease, oc)) { in_options, cfg_options, oc)) {
if (!buffer_allocate (&d1.buffer, if (!buffer_allocate (&d1.buffer,
(result -> len + (result -> len +
universe -> length_size + universe -> length_size +
@@ -1266,10 +1229,13 @@ int store_option (result, universe, lease, oc)
return 0; return 0;
} }
int option_space_encapsulate (result, options, lease, name) int option_space_encapsulate (result, packet, lease,
in_options, cfg_options, name)
struct data_string *result; struct data_string *result;
struct option_state *options; struct packet *packet;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct data_string *name; struct data_string *name;
{ {
struct universe *u; struct universe *u;
@@ -1282,33 +1248,38 @@ int option_space_encapsulate (result, options, lease, name)
} }
if (u -> encapsulate) if (u -> encapsulate)
return (*u -> encapsulate) (result, options, lease, u); return (*u -> encapsulate) (result, packet, lease,
in_options, cfg_options, u);
log_error ("encapsulation requested for %s with no support.", log_error ("encapsulation requested for %s with no support.",
name -> data); name -> data);
return 0; return 0;
} }
int hashed_option_space_encapsulate (result, options, lease, universe) int hashed_option_space_encapsulate (result, packet, lease,
in_options, cfg_options, universe)
struct data_string *result; struct data_string *result;
struct option_state *options; struct packet *packet;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct universe *universe; struct universe *universe;
{ {
pair p, *hash; pair p, *hash;
int status; int status;
int i; int i;
if (universe -> index >= options -> universe_count) if (universe -> index >= cfg_options -> universe_count)
return 0; return 0;
hash = options -> universes [universe -> index]; hash = cfg_options -> universes [universe -> index];
if (!hash) if (!hash)
return 0; return 0;
status = 0; status = 0;
for (i = 0; i < OPTION_HASH_SIZE; i++) { for (i = 0; i < OPTION_HASH_SIZE; i++) {
for (p = hash [i]; p; p = p -> cdr) { for (p = hash [i]; p; p = p -> cdr) {
if (store_option (result, universe, lease, if (store_option (result, universe, packet, lease,
in_options, cfg_options,
(struct option_cache *)p -> car)) (struct option_cache *)p -> car))
status = 1; status = 1;
} }
@@ -1316,3 +1287,65 @@ int hashed_option_space_encapsulate (result, options, lease, universe)
return status; return status;
} }
void do_packet (interface, packet, len, from_port, from, hfrom)
struct interface_info *interface;
struct dhcp_packet *packet;
int len;
unsigned int from_port;
struct iaddr from;
struct hardware *hfrom;
{
int i;
struct option_cache *op;
struct packet *decoded_packet;
decoded_packet = (struct packet *)0;
if (!packet_allocate (&decoded_packet, "do_packet")) {
log_error ("do_packet: no memory for incoming packet!");
return;
}
decoded_packet -> raw = packet;
decoded_packet -> packet_length = len;
decoded_packet -> client_port = from_port;
decoded_packet -> client_addr = from;
decoded_packet -> interface = interface;
decoded_packet -> haddr = hfrom;
if (packet -> hlen > sizeof packet -> chaddr) {
packet_dereference (&decoded_packet, "do_packet");
log_info ("Discarding packet with bogus hlen.");
return;
}
if (!parse_options (decoded_packet)) {
if (decoded_packet -> options)
option_state_dereference (&decoded_packet -> options,
"do_packet");
packet_dereference (&decoded_packet, "do_packet");
return;
}
if (decoded_packet -> options_valid &&
(op = lookup_option (&dhcp_universe, decoded_packet -> options,
DHO_DHCP_MESSAGE_TYPE))) {
struct data_string dp;
memset (&dp, 0, sizeof dp);
evaluate_option_cache (&dp, decoded_packet, (struct lease *)0,
decoded_packet -> options,
(struct option_state *)0, op);
if (dp.len > 0)
decoded_packet -> packet_type = dp.data [0];
else
decoded_packet -> packet_type = 0;
data_string_forget (&dp, "do_packet");
}
if (decoded_packet -> packet_type)
dhcp (decoded_packet);
else
bootp (decoded_packet);
/* If the caller kept the packet, they'll have upped the refcnt. */
packet_dereference (&decoded_packet, "do_packet");
}

View File

@@ -22,7 +22,7 @@
#ifndef lint #ifndef lint
static char copyright[] = static char copyright[] =
"$Id: tree.c,v 1.42 1999/07/21 20:58:17 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n"; "$Id: tree.c,v 1.43 1999/07/31 18:03:55 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"
@@ -378,11 +378,13 @@ static int do_host_lookup (result, dns)
return 1; return 1;
} }
int evaluate_boolean_expression (result, packet, options, lease, expr) int evaluate_boolean_expression (result, packet, lease, in_options,
cfg_options, expr)
int *result; int *result;
struct packet *packet; struct packet *packet;
struct option_state *options;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct expression *expr; struct expression *expr;
{ {
struct data_string left, right; struct data_string left, right;
@@ -404,12 +406,12 @@ int evaluate_boolean_expression (result, packet, options, lease, expr)
case expr_equal: case expr_equal:
memset (&left, 0, sizeof left); memset (&left, 0, sizeof left);
sleft = evaluate_data_expression (&left, packet, options, sleft = evaluate_data_expression (&left, packet, lease,
lease, in_options, cfg_options,
expr -> data.equal [0]); expr -> data.equal [0]);
memset (&right, 0, sizeof right); memset (&right, 0, sizeof right);
sright = evaluate_data_expression (&right, packet, options, sright = evaluate_data_expression (&right, packet, lease,
lease, in_options, cfg_options,
expr -> data.equal [1]); expr -> data.equal [1]);
if (sleft && sright) { if (sleft && sright) {
if (left.len == right.len && if (left.len == right.len &&
@@ -437,11 +439,11 @@ int evaluate_boolean_expression (result, packet, options, lease, expr)
return sleft && sright; return sleft && sright;
case expr_and: case expr_and:
sleft = evaluate_boolean_expression (&bleft, packet, options, sleft = evaluate_boolean_expression (&bleft, packet, lease,
lease, in_options, cfg_options,
expr -> data.and [0]); expr -> data.and [0]);
sright = evaluate_boolean_expression (&bright, packet, options, sright = evaluate_boolean_expression (&bright, packet, lease,
lease, in_options, cfg_options,
expr -> data.and [1]); expr -> data.and [1]);
#if defined (DEBUG_EXPRESSIONS) #if defined (DEBUG_EXPRESSIONS)
@@ -458,11 +460,11 @@ int evaluate_boolean_expression (result, packet, options, lease, expr)
return 0; return 0;
case expr_or: case expr_or:
sleft = evaluate_boolean_expression (&bleft, packet, options, sleft = evaluate_boolean_expression (&bleft, packet, lease,
lease, in_options, cfg_options,
expr -> data.or [0]); expr -> data.or [0]);
sright = evaluate_boolean_expression (&bright, packet, options, sright = evaluate_boolean_expression (&bright, packet, lease,
lease, in_options, cfg_options,
expr -> data.or [1]); expr -> data.or [1]);
#if defined (DEBUG_EXPRESSIONS) #if defined (DEBUG_EXPRESSIONS)
log_debug ("bool: or (%s, %s) = %s", log_debug ("bool: or (%s, %s) = %s",
@@ -478,8 +480,8 @@ int evaluate_boolean_expression (result, packet, options, lease, expr)
return 0; return 0;
case expr_not: case expr_not:
sleft = evaluate_boolean_expression (&bleft, packet, options, sleft = evaluate_boolean_expression (&bleft, packet, lease,
lease, in_options, cfg_options,
expr -> data.not); expr -> data.not);
#if defined (DEBUG_EXPRESSIONS) #if defined (DEBUG_EXPRESSIONS)
log_debug ("bool: not (%s) = %s", log_debug ("bool: not (%s) = %s",
@@ -496,10 +498,11 @@ int evaluate_boolean_expression (result, packet, options, lease, expr)
case expr_exists: case expr_exists:
memset (&left, 0, sizeof left); memset (&left, 0, sizeof left);
if (!options || if (!in_options ||
!((*expr -> data.option -> universe -> get_func) !((*expr -> data.option -> universe -> get_func)
(&left, expr -> data.exists -> universe, (&left, expr -> data.exists -> universe,
packet, lease, options, expr -> data.exists -> code))) packet, lease, in_options, cfg_options, in_options,
expr -> data.exists -> code)))
*result = 0; *result = 0;
else { else {
*result = 1; *result = 1;
@@ -535,15 +538,19 @@ int evaluate_boolean_expression (result, packet, options, lease, expr)
if (packet -> packet_type != DHCPREQUEST) if (packet -> packet_type != DHCPREQUEST)
return 0; return 0;
memset (&rrtype, 0, sizeof expr1); memset (&rrtype, 0, sizeof expr1);
s0 = evaluate_data_expression (&rrtype, packet, options, lease, s0 = evaluate_data_expression (&rrtype, packet, lease,
in_options, cfg_options,
expr -> data.dns_update.type); expr -> data.dns_update.type);
memset (&expr1, 0, sizeof expr1); memset (&expr1, 0, sizeof expr1);
s1 = evaluate_data_expression (&expr1, packet, options, lease, s1 = evaluate_data_expression (&expr1, packet, lease,
in_options, cfg_options,
expr -> data.dns_update.expr1); expr -> data.dns_update.expr1);
memset (&expr2, 0, sizeof expr2); memset (&expr2, 0, sizeof expr2);
s2 = evaluate_data_expression (&expr2, packet, options, lease, s2 = evaluate_data_expression (&expr2, packet, lease,
in_options, cfg_options,
expr -> data.dns_update.expr2); expr -> data.dns_update.expr2);
s3 = evaluate_numeric_expression (&ttl, packet, options, lease, s3 = evaluate_numeric_expression (&ttl, packet, lease,
in_options, cfg_options,
expr -> data.dns_update.ttl); expr -> data.dns_update.ttl);
*result = 0; /* assume failure */ *result = 0; /* assume failure */
@@ -609,11 +616,13 @@ log_info("calling updatePTR(%s, %s, %d, lease)", expr1.data , expr2.data, ttl);
return 0; return 0;
} }
int evaluate_data_expression (result, packet, options, lease, expr) int evaluate_data_expression (result, packet, lease,
in_options, cfg_options, expr)
struct data_string *result; struct data_string *result;
struct packet *packet; struct packet *packet;
struct option_state *options;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct expression *expr; struct expression *expr;
{ {
struct data_string data, other; struct data_string data, other;
@@ -625,15 +634,16 @@ int evaluate_data_expression (result, packet, options, lease, expr)
/* Extract N bytes starting at byte M of a data string. */ /* Extract N bytes starting at byte M of a data string. */
case expr_substring: case expr_substring:
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
s0 = evaluate_data_expression (&data, packet, options, s0 = evaluate_data_expression (&data, packet, lease,
lease, in_options, cfg_options,
expr -> data.substring.expr); expr -> data.substring.expr);
/* Evaluate the offset and length. */ /* Evaluate the offset and length. */
s1 = evaluate_numeric_expression s1 = evaluate_numeric_expression
(&offset, packet, options, lease, (&offset, packet, lease, in_options, cfg_options,
expr -> data.substring.offset); expr -> data.substring.offset);
s2 = evaluate_numeric_expression (&len, packet, options, lease, s2 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
expr -> data.substring.len); expr -> data.substring.len);
if (s0 && s1 && s2) { if (s0 && s1 && s2) {
@@ -671,10 +681,12 @@ int evaluate_data_expression (result, packet, options, lease, expr)
/* Extract the last N bytes of a data string. */ /* Extract the last N bytes of a data string. */
case expr_suffix: case expr_suffix:
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
s0 = evaluate_data_expression (&data, packet, options, lease, s0 = evaluate_data_expression (&data, packet, lease,
in_options, cfg_options,
expr -> data.suffix.expr); expr -> data.suffix.expr);
/* Evaluate the length. */ /* Evaluate the length. */
s1 = evaluate_numeric_expression (&len, packet, options, lease, s1 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
expr -> data.substring.len); expr -> data.substring.len);
if (s0 && s1) { if (s0 && s1) {
data_string_copy (result, &data, data_string_copy (result, &data,
@@ -703,10 +715,11 @@ int evaluate_data_expression (result, packet, options, lease, expr)
/* Extract an option. */ /* Extract an option. */
case expr_option: case expr_option:
if (options) if (in_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,
packet, lease, options, packet, lease,
in_options, cfg_options, in_options,
expr -> data.option -> code)); expr -> data.option -> code));
else else
s0 = 0; s0 = 0;
@@ -721,10 +734,11 @@ int evaluate_data_expression (result, packet, options, lease, expr)
return s0; return s0;
case expr_config_option: case expr_config_option:
if (lease -> state && lease -> state -> options) if (cfg_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,
packet, lease, lease -> state -> options, packet, lease,
in_options, cfg_options, cfg_options,
expr -> data.option -> code)); expr -> data.option -> code));
else else
s0 = 0; s0 = 0;
@@ -774,10 +788,12 @@ int evaluate_data_expression (result, packet, options, lease, expr)
return 0; return 0;
} }
s0 = evaluate_numeric_expression (&len, packet, options, lease, s0 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
expr -> data.packet.len); expr -> data.packet.len);
s1 = evaluate_numeric_expression (&offset, s1 = evaluate_numeric_expression (&offset,
packet, options, lease, packet, lease,
in_options, cfg_options,
expr -> data.packet.len); expr -> data.packet.len);
if (s0 && s1 && offset < packet -> packet_length) { if (s0 && s1 && offset < packet -> packet_length) {
if (offset + len > packet -> packet_length) if (offset + len > packet -> packet_length)
@@ -810,9 +826,10 @@ int evaluate_data_expression (result, packet, options, lease, expr)
/* The encapsulation of all defined options in an /* The encapsulation of all defined options in an
option space... */ option space... */
case expr_encapsulate: case expr_encapsulate:
if (options) if (cfg_options)
s0 = option_space_encapsulate s0 = option_space_encapsulate
(result, options, lease, (result, packet, lease,
in_options, cfg_options,
&expr -> data.encapsulate); &expr -> data.encapsulate);
else else
s0 = 0; s0 = 0;
@@ -852,10 +869,12 @@ int evaluate_data_expression (result, packet, options, lease, expr)
/* Concatenation... */ /* Concatenation... */
case expr_concat: case expr_concat:
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
s0 = evaluate_data_expression (&data, packet, options, lease, s0 = evaluate_data_expression (&data, packet, lease,
in_options, cfg_options,
expr -> data.concat [0]); expr -> data.concat [0]);
memset (&other, 0, sizeof other); memset (&other, 0, sizeof other);
s1 = evaluate_data_expression (&other, packet, options, lease, s1 = evaluate_data_expression (&other, packet, lease,
in_options, cfg_options,
expr -> data.concat [1]); expr -> data.concat [1]);
if (s0 && s1) { if (s0 && s1) {
@@ -889,7 +908,8 @@ int evaluate_data_expression (result, packet, options, lease, expr)
return s0 || s1; return s0 || s1;
case expr_encode_int8: case expr_encode_int8:
s0 = evaluate_numeric_expression (&len, packet, options, lease, s0 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
expr -> data.packet.len); expr -> data.packet.len);
if (s0) { if (s0) {
result -> len = 1; result -> len = 1;
@@ -917,7 +937,8 @@ int evaluate_data_expression (result, packet, options, lease, expr)
case expr_encode_int16: case expr_encode_int16:
s0 = evaluate_numeric_expression (&len, packet, options, lease, s0 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
expr -> data.packet.len); expr -> data.packet.len);
if (s0) { if (s0) {
result -> len = 2; result -> len = 2;
@@ -944,7 +965,8 @@ int evaluate_data_expression (result, packet, options, lease, expr)
return s0; return s0;
case expr_encode_int32: case expr_encode_int32:
s0 = evaluate_numeric_expression (&len, packet, options, lease, s0 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
expr -> data.packet.len); expr -> data.packet.len);
if (s0) { if (s0) {
result -> len = 4; result -> len = 4;
@@ -973,19 +995,22 @@ int evaluate_data_expression (result, packet, options, lease, expr)
case expr_binary_to_ascii: case expr_binary_to_ascii:
/* Evaluate the base (offset) and width (len): */ /* Evaluate the base (offset) and width (len): */
s0 = evaluate_numeric_expression s0 = evaluate_numeric_expression
(&offset, packet, options, lease, (&offset, packet, lease, in_options, cfg_options,
expr -> data.b2a.base); expr -> data.b2a.base);
s1 = evaluate_numeric_expression (&len, packet, options, lease, s1 = evaluate_numeric_expression (&len, packet, lease,
in_options, cfg_options,
expr -> data.b2a.width); expr -> data.b2a.width);
/* Evaluate the seperator string. */ /* Evaluate the seperator string. */
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
s2 = evaluate_data_expression (&data, packet, options, lease, s2 = evaluate_data_expression (&data, packet, lease,
in_options, cfg_options,
expr -> data.b2a.seperator); expr -> data.b2a.seperator);
/* Evaluate the data to be converted. */ /* Evaluate the data to be converted. */
memset (&other, 0, sizeof other); memset (&other, 0, sizeof other);
s3 = evaluate_data_expression (&other, packet, options, lease, s3 = evaluate_data_expression (&other, packet, lease,
in_options, cfg_options,
expr -> data.b2a.buffer); expr -> data.b2a.buffer);
if (s0 && s1 && s2 && s3) { if (s0 && s1 && s2 && s3) {
@@ -1091,12 +1116,13 @@ int evaluate_data_expression (result, packet, options, lease, expr)
case expr_reverse: case expr_reverse:
/* Evaluate the width (len): */ /* Evaluate the width (len): */
s0 = evaluate_numeric_expression s0 = evaluate_numeric_expression
(&len, packet, options, lease, (&len, packet, lease, in_options, cfg_options,
expr -> data.reverse.width); expr -> data.reverse.width);
/* Evaluate the data. */ /* Evaluate the data. */
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
s1 = evaluate_data_expression (&data, packet, options, lease, s1 = evaluate_data_expression (&data, packet, lease,
in_options, cfg_options,
expr -> data.reverse.buffer); expr -> data.reverse.buffer);
if (s0 && s1) { if (s0 && s1) {
@@ -1171,7 +1197,7 @@ int evaluate_data_expression (result, packet, options, lease, expr)
case expr_pick_first_value: case expr_pick_first_value:
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
if ((evaluate_data_expression if ((evaluate_data_expression
(result, packet, options, lease, (result, packet, lease, in_options, cfg_options,
expr -> data.pick_first_value.car))) { expr -> data.pick_first_value.car))) {
#if defined (DEBUG_EXPRESSIONS) #if defined (DEBUG_EXPRESSIONS)
log_debug ("data: pick_first_value (%s, ???)", log_debug ("data: pick_first_value (%s, ???)",
@@ -1181,7 +1207,7 @@ int evaluate_data_expression (result, packet, options, lease, expr)
return 1; return 1;
} }
if ((evaluate_data_expression if ((evaluate_data_expression
(result, packet, options, lease, (result, packet, lease, in_options, cfg_options,
expr -> data.pick_first_value.cdr))) { expr -> data.pick_first_value.cdr))) {
#if defined (DEBUG_EXPRESSIONS) #if defined (DEBUG_EXPRESSIONS)
log_debug ("data: pick_first_value (NULL, %s)", log_debug ("data: pick_first_value (NULL, %s)",
@@ -1241,11 +1267,13 @@ int evaluate_data_expression (result, packet, options, lease, expr)
return 0; return 0;
} }
int evaluate_numeric_expression (result, packet, options, lease, expr) int evaluate_numeric_expression (result, packet, lease,
in_options, cfg_options, expr)
unsigned long *result; unsigned long *result;
struct packet *packet; struct packet *packet;
struct option_state *options;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct expression *expr; struct expression *expr;
{ {
struct data_string data; struct data_string data;
@@ -1288,8 +1316,8 @@ int evaluate_numeric_expression (result, packet, options, lease, expr)
case expr_extract_int8: case expr_extract_int8:
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
status = evaluate_data_expression status = evaluate_data_expression
(&data, packet, (&data, packet, lease, in_options, cfg_options,
options, lease, expr -> data.extract_int); expr -> data.extract_int);
if (status) if (status)
*result = data.data [0]; *result = data.data [0];
#if defined (DEBUG_EXPRESSIONS) #if defined (DEBUG_EXPRESSIONS)
@@ -1304,7 +1332,7 @@ int evaluate_numeric_expression (result, packet, options, lease, expr)
case expr_extract_int16: case expr_extract_int16:
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
status = (evaluate_data_expression status = (evaluate_data_expression
(&data, packet, options, lease, (&data, packet, lease, in_options, cfg_options,
expr -> data.extract_int)); expr -> data.extract_int));
if (status && data.len >= 2) if (status && data.len >= 2)
*result = getUShort (data.data); *result = getUShort (data.data);
@@ -1321,7 +1349,7 @@ int evaluate_numeric_expression (result, packet, options, lease, expr)
case expr_extract_int32: case expr_extract_int32:
memset (&data, 0, sizeof data); memset (&data, 0, sizeof data);
status = (evaluate_data_expression status = (evaluate_data_expression
(&data, packet, options, lease, (&data, packet, lease, in_options, cfg_options,
expr -> data.extract_int)); expr -> data.extract_int));
if (status && data.len >= 4) if (status && data.len >= 4)
*result = getULong (data.data); *result = getULong (data.data);
@@ -1371,11 +1399,12 @@ int evaluate_numeric_expression (result, packet, options, lease, expr)
result of that evaluation. There should never be both an expression result of that evaluation. There should never be both an expression
and a valid data_string. */ and a valid data_string. */
int evaluate_option_cache (result, packet, options, lease, oc) int evaluate_option_cache (result, packet, lease, in_options, cfg_options, oc)
struct data_string *result; struct data_string *result;
struct packet *packet; struct packet *packet;
struct option_state *options;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct option_cache *oc; struct option_cache *oc;
{ {
if (oc -> data.len) { if (oc -> data.len) {
@@ -1385,28 +1414,31 @@ int evaluate_option_cache (result, packet, options, lease, oc)
} }
if (!oc -> expression) if (!oc -> expression)
return 0; return 0;
return evaluate_data_expression (result, packet, options, lease, return evaluate_data_expression (result, packet, lease, in_options,
cfg_options,
oc -> expression); oc -> expression);
} }
/* Evaluate an option cache and extract a boolean from the result, /* Evaluate an option cache and extract a boolean from the result,
returning the boolean. Return false if there is no data. */ returning the boolean. Return false if there is no data. */
int evaluate_boolean_option_cache (packet, options, lease, oc) int evaluate_boolean_option_cache (packet, lease, in_options, cfg_options, oc)
struct packet *packet; struct packet *packet;
struct option_state *options;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct option_cache *oc; struct option_cache *oc;
{ {
struct data_string ds; struct data_string ds;
int result; int result;
/* So that we can be called with option_lookup as an argument. */ /* So that we can be called with option_lookup as an argument. */
if (!oc || !options) if (!oc || !in_options)
return 0; return 0;
memset (&ds, 0, sizeof ds); memset (&ds, 0, sizeof ds);
if (!evaluate_option_cache (&ds, packet, options, lease, oc)) if (!evaluate_option_cache (&ds, packet, lease,
in_options, cfg_options, oc))
return 0; return 0;
if (ds.len && ds.data [0]) if (ds.len && ds.data [0])
@@ -1421,10 +1453,12 @@ int evaluate_boolean_option_cache (packet, options, lease, oc)
/* Evaluate a boolean expression and return the result of the evaluation, /* Evaluate a boolean expression and return the result of the evaluation,
or FALSE if it failed. */ or FALSE if it failed. */
int evaluate_boolean_expression_result (packet, options, lease, expr) int evaluate_boolean_expression_result (packet, lease,
in_options, cfg_options, expr)
struct packet *packet; struct packet *packet;
struct option_state *options;
struct lease *lease; struct lease *lease;
struct option_state *in_options;
struct option_state *cfg_options;
struct expression *expr; struct expression *expr;
{ {
int result; int result;
@@ -1433,8 +1467,8 @@ int evaluate_boolean_expression_result (packet, options, lease, expr)
if (!expr) if (!expr)
return 0; return 0;
if (!evaluate_boolean_expression (&result, if (!evaluate_boolean_expression (&result, packet, lease,
packet, options, lease, expr)) in_options, cfg_options, expr))
return 0; return 0;
return result; return result;