ISC DHCP  4.3.1
A reference DHCPv4 and DHCPv6 implementation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tree.c
Go to the documentation of this file.
1 /* tree.c
2 
3  Routines for manipulating parse trees... */
4 
5 /*
6  * Copyright (c) 2011-2014 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 2004-2007,2009 by Internet Systems Consortium, Inc. ("ISC")
8  * Copyright (c) 1995-2003 by Internet Software Consortium
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Internet Systems Consortium, Inc.
23  * 950 Charter Street
24  * Redwood City, CA 94063
25  * <info@isc.org>
26  * https://www.isc.org/
27  *
28  */
29 
30 #include "dhcpd.h"
31 #include <omapip/omapip_p.h>
32 #include <ctype.h>
33 #include <sys/wait.h>
34 
35 #ifdef HAVE_REGEX_H
36 # include <regex.h>
37 #endif
38 
40 
41 static int do_host_lookup (struct data_string *, struct dns_host_entry *);
42 
43 #define DS_SPRINTF_SIZE 128
44 
45 /*
46  * If we are using a data_string structure to hold a NUL-terminated
47  * ASCII string, this function can be used to append a printf-formatted
48  * string to the end of it. The data_string structure will be resized to
49  * be big enough to hold the new string.
50  *
51  * If the append works, then 1 is returned.
52  *
53  * If it is not possible to allocate a buffer big enough to hold the
54  * new value, then the old data_string is unchanged, and 0 is returned.
55  */
56 int
57 data_string_sprintfa(struct data_string *ds, const char *fmt, ...) {
58  va_list args;
59  int cur_strlen;
60  int max;
61  int vsnprintf_ret;
62  int new_len;
63  struct buffer *tmp_buffer;
64 
65  /*
66  * If the data_string is empty, then initialize it.
67  */
68  if (ds->data == NULL) {
69  /* INSIST(ds.buffer == NULL); */
71  return 0;
72  }
73  ds->data = ds->buffer->data;
74  ds->len = DS_SPRINTF_SIZE;
75  *((char *)ds->data) = '\0';
76  }
77 
78  /*
79  * Get the length of the string, and figure out how much space
80  * is left.
81  */
82  cur_strlen = strlen((char *)ds->data);
83  max = ds->len - cur_strlen;
84 
85  /*
86  * Use vsnprintf(), which won't write past our space, but will
87  * tell us how much space it wants.
88  */
89  va_start(args, fmt);
90  vsnprintf_ret = vsnprintf((char *)ds->data+cur_strlen, max, fmt, args);
91  va_end(args);
92  /* INSIST(vsnprintf_ret >= 0); */
93 
94  /*
95  * If our buffer is not big enough, we need a new buffer.
96  */
97  if (vsnprintf_ret >= max) {
98  /*
99  * Figure out a size big enough.
100  */
101  new_len = ds->len * 2;
102  while (new_len <= cur_strlen + vsnprintf_ret) {
103  new_len *= 2;
104  }
105 
106  /*
107  * Create a new buffer and fill it.
108  */
109  tmp_buffer = NULL;
110  if (!buffer_allocate(&tmp_buffer, new_len, MDL)) {
111  /*
112  * If we can't create a big enough buffer,
113  * we should remove any truncated output that we had.
114  */
115  *((char *)ds->data+cur_strlen) = '\0';
116  va_end(args);
117  return 0;
118  }
119  memcpy(tmp_buffer->data, ds->data, cur_strlen);
120 
121  /* Rerun the vsprintf. */
122  va_start(args, fmt);
123  vsprintf((char *)tmp_buffer->data + cur_strlen, fmt, args);
124  va_end(args);
125 
126  /*
127  * Replace our old buffer with the new buffer.
128  */
130  buffer_reference(&ds->buffer, tmp_buffer, MDL);
131  buffer_dereference(&tmp_buffer, MDL);
132  ds->data = ds->buffer->data;
133  ds->len = new_len;
134  }
135  return 1;
136 }
137 
138 pair cons (car, cdr)
139  caddr_t car;
140  pair cdr;
141 {
142  pair foo = (pair)dmalloc (sizeof *foo, MDL);
143  if (!foo)
144  log_fatal ("no memory for cons.");
145  foo -> car = car;
146  foo -> cdr = cdr;
147  return foo;
148 }
149 
151  struct option_cache **oc;
152  struct buffer **buffer;
153  u_int8_t *data;
154  unsigned len;
155  struct option *option;
156  const char *file;
157  int line;
158 {
159  struct buffer *bp;
160 
161  if (buffer) {
162  bp = *buffer;
163  *buffer = 0;
164  } else {
165  bp = (struct buffer *)0;
166  if (!buffer_allocate (&bp, len, file, line)) {
167  log_error ("%s(%d): can't allocate buffer.",
168  file, line);
169  return 0;
170  }
171  }
172 
173  if (!option_cache_allocate (oc, file, line)) {
174  log_error ("%s(%d): can't allocate option cache.", file, line);
175  buffer_dereference (&bp, file, line);
176  return 0;
177  }
178 
179  (*oc) -> data.len = len;
180  (*oc) -> data.buffer = bp;
181  (*oc) -> data.data = &bp -> data [0];
182  (*oc) -> data.terminated = 0;
183  if (data)
184  memcpy (&bp -> data [0], data, len);
185  option_reference(&((*oc)->option), option, MDL);
186  return 1;
187 }
188 
189 int make_host_lookup (expr, name)
190  struct expression **expr;
191  const char *name;
192 {
193  if (!expression_allocate (expr, MDL)) {
194  log_error ("No memory for host lookup tree node.");
195  return 0;
196  }
197  (*expr) -> op = expr_host_lookup;
198  if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) {
199  expression_dereference (expr, MDL);
200  return 0;
201  }
202  return 1;
203 }
204 
205 int enter_dns_host (dh, name)
206  struct dns_host_entry **dh;
207  const char *name;
208 {
209  /* XXX This should really keep a hash table of hostnames
210  XXX and just add a new reference to a hostname that
211  XXX already exists, if possible, rather than creating
212  XXX a new structure. */
213  if (!dns_host_entry_allocate (dh, name, MDL)) {
214  log_error ("Can't allocate space for new host.");
215  return 0;
216  }
217  return 1;
218 }
219 
220 int make_const_data (struct expression **expr, const unsigned char *data,
221  unsigned len, int terminated, int allocate,
222  const char *file, int line)
223 {
224  struct expression *nt;
225 
226  if (!expression_allocate (expr, file, line)) {
227  log_error ("No memory for make_const_data tree node.");
228  return 0;
229  }
230  nt = *expr;
231 
232  if (len) {
233  if (allocate) {
234  if (!buffer_allocate (&nt -> data.const_data.buffer,
235  len + terminated, file, line)) {
236  log_error ("Can't allocate const_data buffer");
237  expression_dereference (expr, file, line);
238  return 0;
239  }
240  nt -> data.const_data.data =
241  &nt -> data.const_data.buffer -> data [0];
242  memcpy (nt -> data.const_data.buffer -> data,
243  data, len + terminated);
244  } else
245  nt -> data.const_data.data = data;
246  nt -> data.const_data.terminated = terminated;
247  } else
248  nt -> data.const_data.data = 0;
249 
250  nt -> op = expr_const_data;
251  nt -> data.const_data.len = len;
252  return 1;
253 }
254 
255 int make_const_int (expr, val)
256  struct expression **expr;
257  unsigned long val;
258 {
259  if (!expression_allocate (expr, MDL)) {
260  log_error ("No memory for make_const_int tree node.");
261  return 0;
262  }
263 
264  (*expr) -> op = expr_const_int;
265  (*expr) -> data.const_int = val;
266  return 1;
267 }
268 
269 int make_concat (expr, left, right)
270  struct expression **expr;
271  struct expression *left, *right;
272 {
273  /* If we're concatenating a null tree to a non-null tree, just
274  return the non-null tree; if both trees are null, return
275  a null tree. */
276  if (!left) {
277  if (!right)
278  return 0;
279  expression_reference (expr, right, MDL);
280  return 1;
281  }
282  if (!right) {
283  expression_reference (expr, left, MDL);
284  return 1;
285  }
286 
287  /* Otherwise, allocate a new node to concatenate the two. */
288  if (!expression_allocate (expr, MDL)) {
289  log_error ("No memory for concatenation expression node.");
290  return 0;
291  }
292 
293  (*expr) -> op = expr_concat;
294  expression_reference (&(*expr) -> data.concat [0], left, MDL);
295  expression_reference (&(*expr) -> data.concat [1], right, MDL);
296  return 1;
297 }
298 
299 int make_encapsulation (expr, name)
300  struct expression **expr;
301  struct data_string *name;
302 {
303  /* Allocate a new node to store the encapsulation. */
304  if (!expression_allocate (expr, MDL)) {
305  log_error ("No memory for encapsulation expression node.");
306  return 0;
307  }
308 
309  (*expr) -> op = expr_encapsulate;
310  data_string_copy (&(*expr) -> data.encapsulate, name, MDL);
311  return 1;
312 }
313 
314 int make_substring (new, expr, offset, length)
315  struct expression **new;
316  struct expression *expr;
317  struct expression *offset;
318  struct expression *length;
319 {
320  /* Allocate an expression node to compute the substring. */
321  if (!expression_allocate (new, MDL)) {
322  log_error ("no memory for substring expression.");
323  return 0;
324  }
325  (*new) -> op = expr_substring;
326  expression_reference (&(*new) -> data.substring.expr, expr, MDL);
327  expression_reference (&(*new) -> data.substring.offset, offset, MDL);
328  expression_reference (&(*new) -> data.substring.len, length, MDL);
329  return 1;
330 }
331 
332 int make_limit (new, expr, limit)
333  struct expression **new;
334  struct expression *expr;
335  int limit;
336 {
337  /* Allocate a node to enforce a limit on evaluation. */
338  if (!expression_allocate (new, MDL))
339  log_error ("no memory for limit expression");
340  (*new) -> op = expr_substring;
341  expression_reference (&(*new) -> data.substring.expr, expr, MDL);
342 
343  /* Offset is a constant 0. */
344  if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) {
345  log_error ("no memory for limit offset expression");
347  return 0;
348  }
349  (*new) -> data.substring.offset -> op = expr_const_int;
350  (*new) -> data.substring.offset -> data.const_int = 0;
351 
352  /* Length is a constant: the specified limit. */
353  if (!expression_allocate (&(*new) -> data.substring.len, MDL)) {
354  log_error ("no memory for limit length expression");
356  return 0;
357  }
358  (*new) -> data.substring.len -> op = expr_const_int;
359  (*new) -> data.substring.len -> data.const_int = limit;
360 
361  return 1;
362 }
363 
364 int option_cache (struct option_cache **oc, struct data_string *dp,
365  struct expression *expr, struct option *option,
366  const char *file, int line)
367 {
368  if (!option_cache_allocate (oc, file, line))
369  return 0;
370  if (dp)
371  data_string_copy (&(*oc) -> data, dp, file, line);
372  if (expr)
373  expression_reference (&(*oc) -> expression, expr, file, line);
374  option_reference(&(*oc)->option, option, MDL);
375  return 1;
376 }
377 
378 int make_let (result, name)
379  struct executable_statement **result;
380  const char *name;
381 {
382  if (!(executable_statement_allocate (result, MDL)))
383  return 0;
384 
385  (*result) -> op = let_statement;
386  (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL);
387  if (!(*result) -> data.let.name) {
389  return 0;
390  }
391  strcpy ((*result) -> data.let.name, name);
392  return 1;
393 }
394 
395 static int do_host_lookup (result, dns)
396  struct data_string *result;
397  struct dns_host_entry *dns;
398 {
399  struct hostent *h;
400  unsigned i, count;
401  unsigned new_len;
402 
403 #ifdef DEBUG_EVAL
404  log_debug ("time: now = %d dns = %d diff = %d",
405  cur_time, dns -> timeout, cur_time - dns -> timeout);
406 #endif
407 
408  /* If the record hasn't timed out, just copy the data and return. */
409  if (cur_time <= dns -> timeout) {
410 #ifdef DEBUG_EVAL
411  log_debug ("easy copy: %d %s",
412  dns -> data.len,
413  (dns -> data.len > 4
414  ? inet_ntoa (*(struct in_addr *)(dns -> data.data))
415  : 0));
416 #endif
417  data_string_copy (result, &dns -> data, MDL);
418  return 1;
419  }
420 #ifdef DEBUG_EVAL
421  log_debug ("Looking up %s", dns -> hostname);
422 #endif
423 
424  /* Otherwise, look it up... */
425  h = gethostbyname (dns -> hostname);
426  if (!h) {
427 #ifndef NO_H_ERRNO
428  switch (h_errno) {
429  case HOST_NOT_FOUND:
430 #endif
431  log_error ("%s: host unknown.", dns -> hostname);
432 #ifndef NO_H_ERRNO
433  break;
434  case TRY_AGAIN:
435  log_error ("%s: temporary name server failure",
436  dns -> hostname);
437  break;
438  case NO_RECOVERY:
439  log_error ("%s: name server failed", dns -> hostname);
440  break;
441  case NO_DATA:
442  log_error ("%s: no A record associated with address",
443  dns -> hostname);
444  }
445 #endif /* !NO_H_ERRNO */
446 
447  /* Okay to try again after a minute. */
448  dns -> timeout = cur_time + 60;
449  data_string_forget (&dns -> data, MDL);
450  return 0;
451  }
452 
453 #ifdef DEBUG_EVAL
454  log_debug ("Lookup succeeded; first address is %s",
455  inet_ntoa (h -> h_addr_list [0]));
456 #endif
457 
458  /* Count the number of addresses we got... */
459  for (count = 0; h -> h_addr_list [count]; count++)
460  ;
461 
462  /* Dereference the old data, if any. */
463  data_string_forget (&dns -> data, MDL);
464 
465  /* Do we need to allocate more memory? */
466  new_len = count * h -> h_length;
467  if (!buffer_allocate (&dns -> data.buffer, new_len, MDL))
468  {
469  log_error ("No memory for %s.", dns -> hostname);
470  return 0;
471  }
472 
473  dns -> data.data = &dns -> data.buffer -> data [0];
474  dns -> data.len = new_len;
475  dns -> data.terminated = 0;
476 
477  /* Addresses are conveniently stored one to the buffer, so we
478  have to copy them out one at a time... :'( */
479  for (i = 0; i < count; i++) {
480  memcpy (&dns -> data.buffer -> data [h -> h_length * i],
481  h -> h_addr_list [i], (unsigned)(h -> h_length));
482  }
483 #ifdef DEBUG_EVAL
484  log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
485  *(int *)(dns -> buffer), h -> h_addr_list [0]);
486 #endif
487 
488  /* XXX Set the timeout for an hour from now.
489  XXX This should really use the time on the DNS reply. */
490  dns -> timeout = cur_time + 3600;
491 
492 #ifdef DEBUG_EVAL
493  log_debug ("hard copy: %d %s", dns -> data.len,
494  (dns -> data.len > 4
495  ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));
496 #endif
497  data_string_copy (result, &dns -> data, MDL);
498  return 1;
499 }
500 
502  in_options, cfg_options, scope, expr, file, line)
503  struct binding_value **result;
504  struct packet *packet;
505  struct lease *lease;
506  struct client_state *client_state;
507  struct option_state *in_options;
508  struct option_state *cfg_options;
509  struct binding_scope **scope;
510  struct expression *expr;
511  const char *file;
512  int line;
513 {
514  struct binding_value *bv;
515  int status;
516  struct binding *binding;
517 
518  bv = (struct binding_value *)0;
519 
520  if (expr -> op == expr_variable_reference) {
521  if (!scope || !*scope)
522  return 0;
523 
524  binding = find_binding (*scope, expr -> data.variable);
525 
526  if (binding && binding -> value) {
527  if (result)
528  binding_value_reference (result,
529  binding -> value,
530  file, line);
531  return 1;
532  } else
533  return 0;
534  } else if (expr -> op == expr_funcall) {
535  struct string_list *s;
536  struct expression *arg;
537  struct binding_scope *ns;
538  struct binding *nb;
539 
540  if (!scope || !*scope) {
541  log_error ("%s: no such function.",
542  expr -> data.funcall.name);
543  return 0;
544  }
545 
546  binding = find_binding (*scope, expr -> data.funcall.name);
547 
548  if (!binding || !binding -> value) {
549  log_error ("%s: no such function.",
550  expr -> data.funcall.name);
551  return 0;
552  }
553  if (binding -> value -> type != binding_function) {
554  log_error ("%s: not a function.",
555  expr -> data.funcall.name);
556  return 0;
557  }
558 
559  /* Create a new binding scope in which to define
560  the arguments to the function. */
561  ns = (struct binding_scope *)0;
562  if (!binding_scope_allocate (&ns, MDL)) {
563  log_error ("%s: can't allocate argument scope.",
564  expr -> data.funcall.name);
565  return 0;
566  }
567 
568  arg = expr -> data.funcall.arglist;
569  s = binding -> value -> value.fundef -> args;
570  while (arg && s) {
571  nb = dmalloc (sizeof *nb, MDL);
572  if (!nb) {
573  blb:
575  return 0;
576  } else {
577  memset (nb, 0, sizeof *nb);
578  nb -> name = dmalloc (strlen (s -> string) + 1,
579  MDL);
580  if (nb -> name)
581  strcpy (nb -> name, s -> string);
582  else {
583  dfree (nb, MDL);
584  goto blb;
585  }
586  }
587  evaluate_expression (&nb -> value, packet, lease,
588  client_state,
589  in_options, cfg_options, scope,
590  arg -> data.arg.val, file, line);
591  nb -> next = ns -> bindings;
592  ns -> bindings = nb;
593  arg = arg -> data.arg.next;
594  s = s -> next;
595  }
596  if (arg) {
597  log_error ("%s: too many arguments.",
598  expr -> data.funcall.name);
600  return 0;
601  }
602  if (s) {
603  log_error ("%s: too few arguments.",
604  expr -> data.funcall.name);
606  return 0;
607  }
608 
609  if (scope && *scope)
610  binding_scope_reference (&ns -> outer, *scope, MDL);
611 
612  status = (execute_statements
613  (&bv, packet,
614  lease, client_state, in_options, cfg_options, &ns,
615  binding->value->value.fundef->statements, NULL));
617 
618  if (!bv)
619  return 1;
620  } else if (is_boolean_expression (expr)) {
621  if (!binding_value_allocate (&bv, MDL))
622  return 0;
623  bv -> type = binding_boolean;
625  (&bv -> value.boolean, packet, lease, client_state,
626  in_options, cfg_options, scope, expr));
627  } else if (is_numeric_expression (expr)) {
628  if (!binding_value_allocate (&bv, MDL))
629  return 0;
630  bv -> type = binding_numeric;
632  (&bv -> value.intval, packet, lease, client_state,
633  in_options, cfg_options, scope, expr));
634  } else if (is_data_expression (expr)) {
635  if (!binding_value_allocate (&bv, MDL))
636  return 0;
637  bv -> type = binding_data;
638  status = (evaluate_data_expression
639  (&bv -> value.data, packet, lease, client_state,
640  in_options, cfg_options, scope, expr, MDL));
641  } else {
642  log_error ("%s: invalid expression type: %d",
643  "evaluate_expression", expr -> op);
644  return 0;
645  }
646  if (result && status)
647  binding_value_reference (result, bv, file, line);
649 
650  return status;
651 }
652 
654  const char *file, int line)
655 {
656  struct binding_value *bv = *v;
657 
658  *v = (struct binding_value *)0;
659 
660  /* Decrement the reference count. If it's nonzero, we're
661  done. */
662  --(bv -> refcnt);
663  rc_register (file, line, v, bv, bv -> refcnt, 1, RC_MISC);
664  if (bv -> refcnt > 0)
665  return 1;
666  if (bv -> refcnt < 0) {
667  log_error ("%s(%d): negative refcnt!", file, line);
668 #if defined (DEBUG_RC_HISTORY)
669  dump_rc_history (bv);
670 #endif
671 #if defined (POINTER_DEBUG)
672  abort ();
673 #else
674  return 0;
675 #endif
676  }
677 
678  switch (bv -> type) {
679  case binding_boolean:
680  case binding_numeric:
681  break;
682  case binding_data:
683  if (bv -> value.data.buffer)
684  data_string_forget (&bv -> value.data, file, line);
685  break;
686  default:
687  log_error ("%s(%d): invalid binding type: %d",
688  file, line, bv -> type);
689  return 0;
690  }
691  free_binding_value(bv, file, line);
692  return 1;
693 }
694 
696  in_options, cfg_options, scope, expr)
697  int *result;
698  struct packet *packet;
699  struct lease *lease;
700  struct client_state *client_state;
701  struct option_state *in_options;
702  struct option_state *cfg_options;
703  struct binding_scope **scope;
704  struct expression *expr;
705 {
706  struct data_string left, right;
707  int bleft, bright;
708  int sleft, sright;
709  struct binding *binding;
710  struct binding_value *bv, *obv;
711 #ifdef HAVE_REGEX_H
712  int regflags = REG_EXTENDED | REG_NOSUB;
713  regex_t re;
714 #endif
715 
716  switch (expr -> op) {
717  case expr_check:
718  *result = check_collection (packet, lease,
719  expr -> data.check);
720 #if defined (DEBUG_EXPRESSIONS)
721  log_debug ("bool: check (%s) returns %s",
722  expr -> data.check -> name,
723  *result ? "true" : "false");
724 #endif
725  return 1;
726 
727  case expr_equal:
728  case expr_not_equal:
729  bv = obv = (struct binding_value *)0;
730  sleft = evaluate_expression (&bv, packet, lease, client_state,
731  in_options, cfg_options, scope,
732  expr -> data.equal [0], MDL);
733  sright = evaluate_expression (&obv, packet, lease,
734  client_state, in_options,
735  cfg_options, scope,
736  expr -> data.equal [1], MDL);
737  if (sleft && sright) {
738  if (bv -> type != obv -> type)
739  *result = expr -> op == expr_not_equal;
740  else {
741  switch (obv -> type) {
742  case binding_boolean:
743  if (bv -> value.boolean == obv -> value.boolean)
744  *result = expr -> op == expr_equal;
745  else
746  *result = expr -> op == expr_not_equal;
747  break;
748 
749  case binding_data:
750  if ((bv -> value.data.len ==
751  obv -> value.data.len) &&
752  !memcmp (bv -> value.data.data,
753  obv -> value.data.data,
754  obv -> value.data.len))
755  *result = expr -> op == expr_equal;
756  else
757  *result = expr -> op == expr_not_equal;
758  break;
759 
760  case binding_numeric:
761  if (bv -> value.intval == obv -> value.intval)
762  *result = expr -> op == expr_equal;
763  else
764  *result = expr -> op == expr_not_equal;
765  break;
766 
767  case binding_function:
768  if (bv -> value.fundef == obv -> value.fundef)
769  *result = expr -> op == expr_equal;
770  else
771  *result = expr -> op == expr_not_equal;
772  break;
773  default:
774  *result = expr -> op == expr_not_equal;
775  break;
776  }
777  }
778  } else if (!sleft && !sright)
779  *result = expr -> op == expr_equal;
780  else
781  *result = expr -> op == expr_not_equal;
782 
783 #if defined (DEBUG_EXPRESSIONS)
784  log_debug ("bool: %sequal = %s",
785  expr -> op == expr_not_equal ? "not" : "",
786  (*result ? "true" : "false"));
787 #endif
788  if (sleft)
790  if (sright)
792  return 1;
793 
794  case expr_iregex_match:
795 #ifdef HAVE_REGEX_H
796  regflags |= REG_ICASE;
797 #endif
798  /* FALL THROUGH */
799  case expr_regex_match:
800 #ifdef HAVE_REGEX_H
801  memset(&left, 0, sizeof left);
802  bleft = evaluate_data_expression(&left, packet, lease,
803  client_state,
804  in_options, cfg_options,
805  scope,
806  expr->data.equal[0], MDL);
807  memset(&right, 0, sizeof right);
808  bright = evaluate_data_expression(&right, packet, lease,
809  client_state,
810  in_options, cfg_options,
811  scope,
812  expr->data.equal[1], MDL);
813 
814  *result = 0;
815  memset(&re, 0, sizeof(re));
816  if (bleft && bright &&
817  (left.data != NULL) && (right.data != NULL) &&
818  (regcomp(&re, (char *)right.data, regflags) == 0) &&
819  (regexec(&re, (char *)left.data, (size_t)0, NULL, 0) == 0))
820  *result = 1;
821 
822 #if defined (DEBUG_EXPRESSIONS)
823  log_debug("bool: %s ~= %s yields %s",
824  bleft ? print_hex_1(left.len, left.data, 20)
825  : "NULL",
826  bright ? print_hex_2 (right.len, right.data, 20)
827  : "NULL",
828  *result ? "true" : "false");
829 #endif
830 
831  if (bleft)
832  data_string_forget(&left, MDL);
833  if (bright)
834  data_string_forget(&right, MDL);
835 
836  regfree(&re);
837 
838  /*
839  * If we have bleft and bright then we have a good
840  * syntax, otherwise not.
841  *
842  * XXX: we don't warn on invalid regular expression
843  * syntax, should we?
844  */
845  return bleft && bright;
846 #else
847  /* It shouldn't be possible to configure a regex operator
848  * when there's no support.
849  */
850  log_fatal("Impossible condition at %s:%d.", MDL);
851  break;
852 #endif
853 
854  case expr_and:
855  sleft = evaluate_boolean_expression (&bleft, packet, lease,
856  client_state,
857  in_options, cfg_options,
858  scope,
859  expr -> data.and [0]);
860  if (sleft && bleft)
862  (&bright, packet, lease, client_state,
863  in_options, cfg_options,
864  scope, expr -> data.and [1]);
865  else
866  sright = bright = 0;
867 
868 #if defined (DEBUG_EXPRESSIONS)
869  log_debug ("bool: and (%s, %s) = %s",
870  sleft ? (bleft ? "true" : "false") : "NULL",
871  sright ? (bright ? "true" : "false") : "NULL",
872  ((sleft && sright)
873  ? (bleft && bright ? "true" : "false") : "NULL"));
874 #endif
875  if (sleft && sright) {
876  *result = bleft && bright;
877  return 1;
878  }
879  return 0;
880 
881  case expr_or:
882  bleft = bright = 0;
883  sleft = evaluate_boolean_expression (&bleft, packet, lease,
884  client_state,
885  in_options, cfg_options,
886  scope,
887  expr -> data.or [0]);
888  if (!sleft || !bleft)
890  (&bright, packet, lease, client_state,
891  in_options, cfg_options,
892  scope, expr -> data.or [1]);
893  else
894  sright = 0;
895 #if defined (DEBUG_EXPRESSIONS)
896  log_debug ("bool: or (%s, %s) = %s",
897  sleft ? (bleft ? "true" : "false") : "NULL",
898  sright ? (bright ? "true" : "false") : "NULL",
899  ((sleft || sright)
900  ? (bleft || bright ? "true" : "false") : "NULL"));
901 #endif
902  if (sleft || sright) {
903  *result = bleft || bright;
904  return 1;
905  }
906  return 0;
907 
908  case expr_not:
909  sleft = evaluate_boolean_expression(&bleft, packet, lease,
910  client_state,
911  in_options, cfg_options,
912  scope,
913  expr->data.not);
914 #if defined (DEBUG_EXPRESSIONS)
915  log_debug("bool: not (%s) = %s",
916  sleft ? (bleft ? "true" : "false") : "NULL",
917  sleft ? (!bleft ? "true" : "false") : "NULL");
918 #endif
919  if (sleft) {
920  *result = !bleft;
921  return 1;
922  }
923  return 0;
924 
925  case expr_exists:
926  memset (&left, 0, sizeof left);
927  if (!in_options ||
928  !get_option (&left, expr -> data.exists -> universe,
929  packet, lease, client_state,
930  in_options, cfg_options, in_options,
931  scope, expr -> data.exists -> code, MDL))
932  *result = 0;
933  else {
934  *result = 1;
935  data_string_forget (&left, MDL);
936  }
937 #if defined (DEBUG_EXPRESSIONS)
938  log_debug ("bool: exists %s.%s = %s",
939  expr -> data.option -> universe -> name,
940  expr -> data.option -> name,
941  *result ? "true" : "false");
942 #endif
943  return 1;
944 
945  case expr_known:
946  if (!packet) {
947 #if defined (DEBUG_EXPRESSIONS)
948  log_debug ("bool: known = NULL");
949 #endif
950  return 0;
951  }
952 #if defined (DEBUG_EXPRESSIONS)
953  log_debug ("bool: known = %s",
954  packet -> known ? "true" : "false");
955 #endif
956  *result = packet -> known;
957  return 1;
958 
959  case expr_static:
960  if (!lease || !(lease -> flags & STATIC_LEASE)) {
961 #if defined (DEBUG_EXPRESSIONS)
962  log_debug ("bool: static = false (%s %s %s %d)",
963  lease ? "y" : "n",
964  (lease && (lease -> flags & STATIC_LEASE)
965  ? "y" : "n"),
966  piaddr (lease -> ip_addr),
967  lease ? lease -> flags : 0);
968 #endif
969  *result = 0;
970  return 1;
971  }
972 #if defined (DEBUG_EXPRESSIONS)
973  log_debug ("bool: static = true");
974 #endif
975  *result = 1;
976  return 1;
977 
979  if (scope && *scope) {
980  binding = find_binding (*scope, expr -> data.variable);
981 
982  if (binding) {
983  if (binding -> value)
984  *result = 1;
985  else
986  *result = 0;
987  } else
988  *result = 0;
989  } else
990  *result = 0;
991 #if defined (DEBUG_EXPRESSIONS)
992  log_debug ("boolean: %s? = %s", expr -> data.variable,
993  *result ? "true" : "false");
994 #endif
995  return 1;
996 
998  if (scope && *scope) {
999  binding = find_binding (*scope, expr -> data.variable);
1000 
1001  if (binding && binding -> value) {
1002  if (binding -> value -> type ==
1003  binding_boolean) {
1004  *result = binding -> value -> value.boolean;
1005  sleft = 1;
1006  } else {
1007  log_error ("binding type %d in %s.",
1008  binding -> value -> type,
1009  "evaluate_boolean_expression");
1010  sleft = 0;
1011  }
1012  } else
1013  sleft = 0;
1014  } else
1015  sleft = 0;
1016 #if defined (DEBUG_EXPRESSIONS)
1017  log_debug ("boolean: %s = %s", expr -> data.variable,
1018  sleft ? (*result ? "true" : "false") : "NULL");
1019 #endif
1020  return sleft;
1021 
1022  case expr_funcall:
1023  bv = (struct binding_value *)0;
1024  sleft = evaluate_expression (&bv, packet, lease, client_state,
1025  in_options, cfg_options,
1026  scope, expr, MDL);
1027  if (sleft) {
1028  if (bv -> type != binding_boolean)
1029  log_error ("%s() returned type %d in %s.",
1030  expr -> data.funcall.name,
1031  bv -> type,
1032  "evaluate_boolean_expression");
1033  else
1034  *result = bv -> value.boolean;
1036  }
1037 #if defined (DEBUG_EXPRESSIONS)
1038  log_debug ("boolean: %s() = %s", expr -> data.funcall.name,
1039  sleft ? (*result ? "true" : "false") : "NULL");
1040 #endif
1041  break;
1042 
1043  case expr_none:
1044  case expr_match:
1045  case expr_substring:
1046  case expr_suffix:
1047  case expr_lcase:
1048  case expr_ucase:
1049  case expr_option:
1050  case expr_hardware:
1051  case expr_const_data:
1052  case expr_packet:
1053  case expr_concat:
1054  case expr_encapsulate:
1055  case expr_host_lookup:
1056  case expr_encode_int8:
1057  case expr_encode_int16:
1058  case expr_encode_int32:
1059  case expr_binary_to_ascii:
1060  case expr_reverse:
1061  case expr_pick_first_value:
1062  case expr_host_decl_name:
1063  case expr_config_option:
1064  case expr_leased_address:
1065  case expr_null:
1066  case expr_filename:
1067  case expr_sname:
1068  case expr_gethostname:
1069  case expr_v6relay:
1070  log_error ("Data opcode in evaluate_boolean_expression: %d",
1071  expr -> op);
1072  return 0;
1073 
1074  case expr_extract_int8:
1075  case expr_extract_int16:
1076  case expr_extract_int32:
1077  case expr_const_int:
1078  case expr_lease_time:
1079  case expr_dns_transaction:
1080  case expr_add:
1081  case expr_subtract:
1082  case expr_multiply:
1083  case expr_divide:
1084  case expr_remainder:
1085  case expr_binary_and:
1086  case expr_binary_or:
1087  case expr_binary_xor:
1088  case expr_client_state:
1089  log_error ("Numeric opcode in evaluate_boolean_expression: %d",
1090  expr -> op);
1091  return 0;
1092 
1093  case expr_ns_add:
1094  case expr_ns_delete:
1095  case expr_ns_exists:
1096  case expr_ns_not_exists:
1097  log_error ("dns opcode in evaluate_boolean_expression: %d",
1098  expr -> op);
1099  return 0;
1100 
1101  case expr_function:
1102  log_error ("function definition in evaluate_boolean_expr");
1103  return 0;
1104 
1105  case expr_arg:
1106  break;
1107  }
1108 
1109  log_error ("Bogus opcode in evaluate_boolean_expression: %d",
1110  expr -> op);
1111  return 0;
1112 }
1113 
1115  in_options, cfg_options, scope, expr, file, line)
1116  struct data_string *result;
1117  struct packet *packet;
1118  struct lease *lease;
1119  struct client_state *client_state;
1120  struct option_state *in_options;
1121  struct option_state *cfg_options;
1122  struct binding_scope **scope;
1123  struct expression *expr;
1124  const char *file;
1125  int line;
1126 {
1127  struct data_string data, other;
1128  unsigned long offset, len, i;
1129  int s0, s1, s2, s3;
1130  int status;
1131  struct binding *binding;
1132  unsigned char *s;
1133  struct binding_value *bv;
1134  struct packet *relay_packet;
1135  struct option_state *relay_options;
1136 
1137  switch (expr -> op) {
1138  /* Extract N bytes starting at byte M of a data string. */
1139  case expr_substring:
1140  memset (&data, 0, sizeof data);
1141  s0 = evaluate_data_expression (&data, packet, lease,
1142  client_state,
1143  in_options, cfg_options, scope,
1144  expr -> data.substring.expr,
1145  MDL);
1146 
1147  /* Evaluate the offset and length. */
1149  (&offset, packet, lease, client_state, in_options,
1150  cfg_options, scope, expr -> data.substring.offset);
1151  s2 = evaluate_numeric_expression (&len, packet, lease,
1152  client_state,
1153  in_options, cfg_options,
1154  scope,
1155  expr -> data.substring.len);
1156 
1157  if (s0 && s1 && s2) {
1158  /* If the offset is after end of the string,
1159  return an empty string. Otherwise, do the
1160  adjustments and return what's left. */
1161  if (data.len > offset) {
1162  data_string_copy (result, &data, file, line);
1163  result -> len -= offset;
1164  if (result -> len > len) {
1165  result -> len = len;
1166  result -> terminated = 0;
1167  }
1168  result -> data += offset;
1169  }
1170  s3 = 1;
1171  } else
1172  s3 = 0;
1173 
1174 #if defined (DEBUG_EXPRESSIONS)
1175  log_debug ("data: substring (%s, %s, %s) = %s",
1176  s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1177  s1 ? print_dec_1 (offset) : "NULL",
1178  s2 ? print_dec_2 (len) : "NULL",
1179  (s3 ? print_hex_2 (result -> len, result -> data, 30)
1180  : "NULL"));
1181 #endif
1182  if (s0)
1183  data_string_forget (&data, MDL);
1184  if (s3)
1185  return 1;
1186  return 0;
1187 
1188  /* Extract the last N bytes of a data string. */
1189  case expr_suffix:
1190  memset (&data, 0, sizeof data);
1191  s0 = evaluate_data_expression (&data, packet, lease,
1192  client_state,
1193  in_options, cfg_options, scope,
1194  expr -> data.suffix.expr, MDL);
1195  /* Evaluate the length. */
1196  s1 = evaluate_numeric_expression (&len, packet, lease,
1197  client_state,
1198  in_options, cfg_options,
1199  scope,
1200  expr -> data.suffix.len);
1201  if (s0 && s1) {
1202  data_string_copy (result, &data, file, line);
1203 
1204  /* If we are returning the last N bytes of a
1205  string whose length is <= N, just return
1206  the string - otherwise, compute a new
1207  starting address and decrease the
1208  length. */
1209  if (data.len > len) {
1210  result -> data += data.len - len;
1211  result -> len = len;
1212  }
1213 
1214  data_string_forget (&data, MDL);
1215  }
1216 
1217 #if defined (DEBUG_EXPRESSIONS)
1218  log_debug ("data: suffix (%s, %s) = %s",
1219  s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1220  s1 ? print_dec_1 (len) : "NULL",
1221  ((s0 && s1)
1222  ? print_hex_2 (result -> len, result -> data, 30)
1223  : "NULL"));
1224 #endif
1225 
1226  return s0 && s1;
1227 
1228  /* Convert string to lowercase. */
1229  case expr_lcase:
1230  memset(&data, 0, sizeof data);
1231  s0 = evaluate_data_expression(&data, packet, lease,
1232  client_state,
1233  in_options, cfg_options, scope,
1234  expr->data.lcase, MDL);
1235  s1 = 0;
1236  if (s0) {
1237  result->len = data.len;
1238  if (buffer_allocate(&result->buffer,
1239  result->len + data.terminated,
1240  MDL)) {
1241  result->data = &result->buffer->data[0];
1242  memcpy(result->buffer->data, data.data,
1243  data.len + data.terminated);
1244  result->terminated = data.terminated;
1245  s = (unsigned char *)result->data;
1246  for (i = 0; i < result->len; i++, s++)
1247  *s = tolower(*s);
1248  s1 = 1;
1249  } else {
1250  log_error("data: lcase: no buffer memory.");
1251  }
1252  }
1253 
1254 #if defined (DEBUG_EXPRESSIONS)
1255  log_debug("data: lcase (%s) = %s",
1256  s0 ? print_hex_1(data.len, data.data, 30) : "NULL",
1257  s1 ? print_hex_2(result->len, result->data, 30)
1258  : "NULL");
1259 #endif
1260  if (s0)
1261  data_string_forget(&data, MDL);
1262  return s1;
1263 
1264  /* Convert string to uppercase. */
1265  case expr_ucase:
1266  memset(&data, 0, sizeof data);
1267  s0 = evaluate_data_expression(&data, packet, lease,
1268  client_state,
1269  in_options, cfg_options, scope,
1270  expr->data.lcase, MDL);
1271  s1 = 0;
1272  if (s0) {
1273  result->len = data.len;
1274  if (buffer_allocate(&result->buffer,
1275  result->len + data.terminated,
1276  file, line)) {
1277  result->data = &result->buffer->data[0];
1278  memcpy(result->buffer->data, data.data,
1279  data.len + data.terminated);
1280  result->terminated = data.terminated;
1281  s = (unsigned char *)result->data;
1282  for (i = 0; i < result->len; i++, s++)
1283  *s = toupper(*s);
1284  s1 = 1;
1285  } else {
1286  log_error("data: lcase: no buffer memory.");
1287  }
1288  }
1289 
1290 #if defined (DEBUG_EXPRESSIONS)
1291  log_debug("data: ucase (%s) = %s",
1292  s0 ? print_hex_1(data.len, data.data, 30) : "NULL",
1293  s1 ? print_hex_2(result->len, result->data, 30)
1294  : "NULL");
1295 #endif
1296  if (s0)
1297  data_string_forget(&data, MDL);
1298 
1299  return s1;
1300 
1301  /* Extract an option. */
1302  case expr_option:
1303  if (in_options)
1304  s0 = get_option (result,
1305  expr -> data.option -> universe,
1306  packet, lease, client_state,
1307  in_options, cfg_options, in_options,
1308  scope, expr -> data.option -> code,
1309  file, line);
1310  else
1311  s0 = 0;
1312 
1313 #if defined (DEBUG_EXPRESSIONS)
1314  log_debug ("data: option %s.%s = %s",
1315  expr -> data.option -> universe -> name,
1316  expr -> data.option -> name,
1317  s0 ? print_hex_1 (result -> len, result -> data, 60)
1318  : "NULL");
1319 #endif
1320  return s0;
1321 
1322  case expr_config_option:
1323  if (cfg_options)
1324  s0 = get_option (result,
1325  expr -> data.option -> universe,
1326  packet, lease, client_state,
1327  in_options, cfg_options, cfg_options,
1328  scope, expr -> data.option -> code,
1329  file, line);
1330  else
1331  s0 = 0;
1332 
1333 #if defined (DEBUG_EXPRESSIONS)
1334  log_debug ("data: config-option %s.%s = %s",
1335  expr -> data.option -> universe -> name,
1336  expr -> data.option -> name,
1337  s0 ? print_hex_1 (result -> len, result -> data, 60)
1338  : "NULL");
1339 #endif
1340  return s0;
1341 
1342  /* Combine the hardware type and address. */
1343  case expr_hardware:
1344  /* On the client, hardware is our hardware. */
1345  if (client_state) {
1346  memset(result, 0, sizeof(*result));
1347  result->data = client_state->interface->hw_address.hbuf;
1348  result->len = client_state->interface->hw_address.hlen;
1349 #if defined (DEBUG_EXPRESSIONS)
1350  log_debug("data: hardware = %s",
1351  print_hex_1(result->len, result->data, 60));
1352 #endif
1353  return (1);
1354  }
1355 
1356  /* The server cares about the client's hardware address,
1357  so only in the case where we are examining a packet or have
1358  a lease with a hardware address can we return anything. */
1359 
1360  if (packet != NULL && packet->raw != NULL) {
1361  if (packet->raw->hlen > sizeof(packet->raw->chaddr)) {
1362  log_error("data: hardware: invalid hlen (%d)\n",
1363  packet->raw->hlen);
1364  return (0);
1365  }
1366  result->len = packet->raw->hlen + 1;
1367  if (buffer_allocate(&result->buffer, result->len, MDL)){
1368  result->data = &result->buffer->data[0];
1369  result->buffer->data[0] = packet->raw->htype;
1370  memcpy(&result->buffer->data[1],
1371  packet->raw->chaddr, packet->raw->hlen);
1372  result->terminated = 0;
1373  } else {
1374  log_error("data: hardware: "
1375  "no memory for buffer.");
1376  return (0);
1377  }
1378  } else if (lease != NULL) {
1379  result->len = lease->hardware_addr.hlen;
1380  if (buffer_allocate(&result->buffer, result->len, MDL)){
1381  result->data = &result->buffer->data[0];
1382  memcpy(result->buffer->data,
1383  lease->hardware_addr.hbuf, result->len);
1384  result->terminated = 0;
1385  } else {
1386  log_error("data: hardware: "
1387  "no memory for buffer.");
1388  return (0);
1389  }
1390  } else {
1391  log_error("data: hardware: no raw packet or lease "
1392  "is available");
1393  return (0);
1394  }
1395 
1396 #if defined (DEBUG_EXPRESSIONS)
1397  log_debug("data: hardware = %s",
1398  print_hex_1(result->len, result->data, 60));
1399 #endif
1400  return (1);
1401 
1402  /* Extract part of the raw packet. */
1403  case expr_packet:
1404  if (!packet || !packet -> raw) {
1405  log_error ("data: packet: raw packet not available");
1406  return 0;
1407  }
1408 
1409  s0 = evaluate_numeric_expression (&offset, packet, lease,
1410  client_state,
1411  in_options, cfg_options,
1412  scope,
1413  expr -> data.packet.offset);
1414  s1 = evaluate_numeric_expression (&len,
1415  packet, lease, client_state,
1416  in_options, cfg_options,
1417  scope,
1418  expr -> data.packet.len);
1419  if (s0 && s1 && offset < packet -> packet_length) {
1420  if (offset + len > packet -> packet_length)
1421  result -> len =
1422  packet -> packet_length - offset;
1423  else
1424  result -> len = len;
1425  if (buffer_allocate (&result -> buffer,
1426  result -> len, file, line)) {
1427  result -> data = &result -> buffer -> data [0];
1428  memcpy (result -> buffer -> data,
1429  (((unsigned char *)(packet -> raw))
1430  + offset), result -> len);
1431  result -> terminated = 0;
1432  } else {
1433  log_error ("data: packet: no buffer memory.");
1434  return 0;
1435  }
1436  s2 = 1;
1437  } else
1438  s2 = 0;
1439 #if defined (DEBUG_EXPRESSIONS)
1440  log_debug ("data: packet (%ld, %ld) = %s",
1441  offset, len,
1442  s2 ? print_hex_1 (result -> len,
1443  result -> data, 60) : NULL);
1444 #endif
1445  return s2;
1446 
1447  /* The encapsulation of all defined options in an
1448  option space... */
1449  case expr_encapsulate:
1450  if (cfg_options)
1452  (result, packet, lease, client_state,
1453  in_options, cfg_options, scope,
1454  &expr -> data.encapsulate);
1455  else
1456  s0 = 0;
1457 
1458 #if defined (DEBUG_EXPRESSIONS)
1459  log_debug ("data: encapsulate (%s) = %s",
1460  expr -> data.encapsulate.data,
1461  s0 ? print_hex_1 (result -> len,
1462  result -> data, 60) : "NULL");
1463 #endif
1464  return s0;
1465 
1466  /* Some constant data... */
1467  case expr_const_data:
1468 #if defined (DEBUG_EXPRESSIONS)
1469  log_debug ("data: const = %s",
1470  print_hex_1 (expr -> data.const_data.len,
1471  expr -> data.const_data.data, 60));
1472 #endif
1473  data_string_copy (result,
1474  &expr -> data.const_data, file, line);
1475  return 1;
1476 
1477  /* Hostname lookup... */
1478  case expr_host_lookup:
1479  s0 = do_host_lookup (result, expr -> data.host_lookup);
1480 #if defined (DEBUG_EXPRESSIONS)
1481  log_debug ("data: DNS lookup (%s) = %s",
1482  expr -> data.host_lookup -> hostname,
1483  (s0
1484  ? print_dotted_quads (result -> len, result -> data)
1485  : "NULL"));
1486 #endif
1487  return s0;
1488 
1489  /* Concatenation... */
1490  case expr_concat:
1491  memset (&data, 0, sizeof data);
1492  s0 = evaluate_data_expression (&data, packet, lease,
1493  client_state,
1494  in_options, cfg_options, scope,
1495  expr -> data.concat [0], MDL);
1496  memset (&other, 0, sizeof other);
1497  s1 = evaluate_data_expression (&other, packet, lease,
1498  client_state,
1499  in_options, cfg_options, scope,
1500  expr -> data.concat [1], MDL);
1501 
1502  if (s0 && s1) {
1503  result -> len = data.len + other.len;
1504  if (!buffer_allocate (&result -> buffer,
1505  (result -> len + other.terminated),
1506  file, line)) {
1507  log_error ("data: concat: no memory");
1508  result -> len = 0;
1509  data_string_forget (&data, MDL);
1510  data_string_forget (&other, MDL);
1511  return 0;
1512  }
1513  result -> data = &result -> buffer -> data [0];
1514  memcpy (result -> buffer -> data, data.data, data.len);
1515  memcpy (&result -> buffer -> data [data.len],
1516  other.data, other.len + other.terminated);
1517  }
1518 
1519  if (s0)
1520  data_string_forget (&data, MDL);
1521  if (s1)
1522  data_string_forget (&other, MDL);
1523 #if defined (DEBUG_EXPRESSIONS)
1524  log_debug ("data: concat (%s, %s) = %s",
1525  s0 ? print_hex_1 (data.len, data.data, 20) : "NULL",
1526  s1 ? print_hex_2 (other.len, other.data, 20) : "NULL",
1527  ((s0 && s1)
1528  ? print_hex_3 (result -> len, result -> data, 30)
1529  : "NULL"));
1530 #endif
1531  return s0 && s1;
1532 
1533  case expr_encode_int8:
1534  s0 = evaluate_numeric_expression (&len, packet, lease,
1535  client_state,
1536  in_options, cfg_options,
1537  scope,
1538  expr -> data.encode_int);
1539  if (s0) {
1540  result -> len = 1;
1541  if (!buffer_allocate (&result -> buffer,
1542  1, file, line)) {
1543  log_error ("data: encode_int8: no memory");
1544  result -> len = 0;
1545  s0 = 0;
1546  } else {
1547  result -> data = &result -> buffer -> data [0];
1548  result -> buffer -> data [0] = len;
1549  }
1550  } else
1551  result -> len = 0;
1552 
1553 #if defined (DEBUG_EXPRESSIONS)
1554  if (!s0)
1555  log_debug ("data: encode_int8 (NULL) = NULL");
1556  else
1557  log_debug ("data: encode_int8 (%ld) = %s", len,
1558  print_hex_2 (result -> len,
1559  result -> data, 20));
1560 #endif
1561  return s0;
1562 
1563 
1564  case expr_encode_int16:
1565  s0 = evaluate_numeric_expression (&len, packet, lease,
1566  client_state,
1567  in_options, cfg_options,
1568  scope,
1569  expr -> data.encode_int);
1570  if (s0) {
1571  result -> len = 2;
1572  if (!buffer_allocate (&result -> buffer, 2,
1573  file, line)) {
1574  log_error ("data: encode_int16: no memory");
1575  result -> len = 0;
1576  s0 = 0;
1577  } else {
1578  result -> data = &result -> buffer -> data [0];
1579  putUShort (result -> buffer -> data, len);
1580  }
1581  } else
1582  result -> len = 0;
1583 
1584 #if defined (DEBUG_EXPRESSIONS)
1585  if (!s0)
1586  log_debug ("data: encode_int16 (NULL) = NULL");
1587  else
1588  log_debug ("data: encode_int16 (%ld) = %s", len,
1589  print_hex_2 (result -> len,
1590  result -> data, 20));
1591 #endif
1592  return s0;
1593 
1594  case expr_encode_int32:
1595  s0 = evaluate_numeric_expression (&len, packet, lease,
1596  client_state,
1597  in_options, cfg_options,
1598  scope,
1599  expr -> data.encode_int);
1600  if (s0) {
1601  result -> len = 4;
1602  if (!buffer_allocate (&result -> buffer, 4,
1603  file, line)) {
1604  log_error ("data: encode_int32: no memory");
1605  result -> len = 0;
1606  s0 = 0;
1607  } else {
1608  result -> data = &result -> buffer -> data [0];
1609  putULong (result -> buffer -> data, len);
1610  }
1611  } else
1612  result -> len = 0;
1613 
1614 #if defined (DEBUG_EXPRESSIONS)
1615  if (!s0)
1616  log_debug ("data: encode_int32 (NULL) = NULL");
1617  else
1618  log_debug ("data: encode_int32 (%ld) = %s", len,
1619  print_hex_2 (result -> len,
1620  result -> data, 20));
1621 #endif
1622  return s0;
1623 
1624  case expr_binary_to_ascii:
1625  /* Evaluate the base (offset) and width (len): */
1627  (&offset, packet, lease, client_state, in_options,
1628  cfg_options, scope, expr -> data.b2a.base);
1629  s1 = evaluate_numeric_expression (&len, packet, lease,
1630  client_state,
1631  in_options, cfg_options,
1632  scope,
1633  expr -> data.b2a.width);
1634 
1635  /* Evaluate the separator string. */
1636  memset (&data, 0, sizeof data);
1637  s2 = evaluate_data_expression (&data, packet, lease,
1638  client_state,
1639  in_options, cfg_options, scope,
1640  expr -> data.b2a.separator,
1641  MDL);
1642 
1643  /* Evaluate the data to be converted. */
1644  memset (&other, 0, sizeof other);
1645  s3 = evaluate_data_expression (&other, packet, lease,
1646  client_state,
1647  in_options, cfg_options, scope,
1648  expr -> data.b2a.buffer, MDL);
1649 
1650  if (s0 && s1 && s2 && s3) {
1651  unsigned buflen, i;
1652 
1653  if (len != 8 && len != 16 && len != 32) {
1654  log_info ("binary_to_ascii: %s %ld!",
1655  "invalid width", len);
1656  status = 0;
1657  goto b2a_out;
1658  }
1659  len /= 8;
1660 
1661  /* The buffer must be a multiple of the number's
1662  width. */
1663  if (other.len % len) {
1664  log_info ("binary-to-ascii: %s %d %s %ld!",
1665  "length of buffer", other.len,
1666  "not a multiple of width", len);
1667  status = 0;
1668  goto b2a_out;
1669  }
1670 
1671  /* Count the width of the output. */
1672  buflen = 0;
1673  for (i = 0; i < other.len; i += len) {
1674  if (len == 1) {
1675  if (offset == 8) {
1676  if (other.data [i] < 8)
1677  buflen++;
1678  else if (other.data [i] < 64)
1679  buflen += 2;
1680  else
1681  buflen += 3;
1682  } else if (offset == 10) {
1683  if (other.data [i] < 10)
1684  buflen++;
1685  else if (other.data [i] < 100)
1686  buflen += 2;
1687  else
1688  buflen += 3;
1689  } else if (offset == 16) {
1690  if (other.data [i] < 16)
1691  buflen++;
1692  else
1693  buflen += 2;
1694  } else
1695  buflen += (converted_length
1696  (&other.data [i],
1697  offset, 1));
1698  } else
1699  buflen += (converted_length
1700  (&other.data [i],
1701  offset, len));
1702  if (i + len != other.len)
1703  buflen += data.len;
1704  }
1705 
1706  if (!buffer_allocate (&result -> buffer,
1707  buflen + 1, file, line)) {
1708  log_error ("data: binary-to-ascii: no memory");
1709  status = 0;
1710  goto b2a_out;
1711  }
1712  result -> data = &result -> buffer -> data [0];
1713  result -> len = buflen;
1714  result -> terminated = 1;
1715 
1716  buflen = 0;
1717  for (i = 0; i < other.len; i += len) {
1718  buflen += (binary_to_ascii
1719  (&result -> buffer -> data [buflen],
1720  &other.data [i], offset, len));
1721  if (i + len != other.len) {
1722  memcpy (&result ->
1723  buffer -> data [buflen],
1724  data.data, data.len);
1725  buflen += data.len;
1726  }
1727  }
1728  /* NUL terminate. */
1729  result -> buffer -> data [buflen] = 0;
1730  status = 1;
1731  } else
1732  status = 0;
1733 
1734  b2a_out:
1735 #if defined (DEBUG_EXPRESSIONS)
1736  log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
1737  s0 ? print_dec_1 (offset) : "NULL",
1738  s1 ? print_dec_2 (len) : "NULL",
1739  s2 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1740  s3 ? print_hex_2 (other.len, other.data, 30) : "NULL",
1741  (status ? print_hex_3 (result -> len, result -> data, 30)
1742  : "NULL"));
1743 #endif
1744  if (s2)
1745  data_string_forget (&data, MDL);
1746  if (s3)
1747  data_string_forget (&other, MDL);
1748  if (status)
1749  return 1;
1750  return 0;
1751 
1752  case expr_reverse:
1753  /* Evaluate the width (len): */
1755  (&len, packet, lease, client_state, in_options,
1756  cfg_options, scope, expr -> data.reverse.width);
1757 
1758  /* Evaluate the data. */
1759  memset (&data, 0, sizeof data);
1760  s1 = evaluate_data_expression (&data, packet, lease,
1761  client_state,
1762  in_options, cfg_options, scope,
1763  expr -> data.reverse.buffer,
1764  MDL);
1765 
1766  if (s0 && s1) {
1767  int i;
1768 
1769  /* The buffer must be a multiple of the number's
1770  width. */
1771  if (data.len % len) {
1772  log_info ("reverse: %s %d %s %ld!",
1773  "length of buffer", data.len,
1774  "not a multiple of width", len);
1775  status = 0;
1776  goto reverse_out;
1777  }
1778 
1779  /* XXX reverse in place? I don't think we can. */
1780  if (!buffer_allocate (&result -> buffer,
1781  data.len, file, line)) {
1782  log_error ("data: reverse: no memory");
1783  status = 0;
1784  goto reverse_out;
1785  }
1786  result -> data = &result -> buffer -> data [0];
1787  result -> len = data.len;
1788  result -> terminated = 0;
1789 
1790  for (i = 0; i < data.len; i += len) {
1791  memcpy (&result -> buffer -> data [i],
1792  &data.data [data.len - i - len], len);
1793  }
1794  status = 1;
1795  } else
1796  status = 0;
1797 
1798  reverse_out:
1799 #if defined (DEBUG_EXPRESSIONS)
1800  log_debug ("data: reverse (%s, %s) = %s",
1801  s0 ? print_dec_1 (len) : "NULL",
1802  s1 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1803  (status ? print_hex_3 (result -> len, result -> data, 30)
1804  : "NULL"));
1805 #endif
1806  if (s0)
1807  data_string_forget (&data, MDL);
1808  if (status)
1809  return 1;
1810  return 0;
1811 
1812  case expr_leased_address:
1813  if (!lease) {
1814  log_debug("data: \"leased-address\" configuration "
1815  "directive: there is no lease associated "
1816  "with this client.");
1817  return 0;
1818  }
1819  result -> len = lease -> ip_addr.len;
1820  if (buffer_allocate (&result -> buffer, result -> len,
1821  file, line)) {
1822  result -> data = &result -> buffer -> data [0];
1823  memcpy (&result -> buffer -> data [0],
1824  lease -> ip_addr.iabuf, lease -> ip_addr.len);
1825  result -> terminated = 0;
1826  } else {
1827  log_error ("data: leased-address: no memory.");
1828  return 0;
1829  }
1830 #if defined (DEBUG_EXPRESSIONS)
1831  log_debug ("data: leased-address = %s",
1832  print_hex_1 (result -> len, result -> data, 60));
1833 #endif
1834  return 1;
1835 
1836  case expr_pick_first_value:
1837  memset (&data, 0, sizeof data);
1839  (result, packet,
1840  lease, client_state, in_options, cfg_options,
1841  scope, expr -> data.pick_first_value.car, MDL))) {
1842 #if defined (DEBUG_EXPRESSIONS)
1843  log_debug ("data: pick_first_value (%s, xxx)",
1844  print_hex_1 (result -> len,
1845  result -> data, 40));
1846 #endif
1847  return 1;
1848  }
1849 
1850  if (expr -> data.pick_first_value.cdr &&
1852  (result, packet,
1853  lease, client_state, in_options, cfg_options,
1854  scope, expr -> data.pick_first_value.cdr, MDL))) {
1855 #if defined (DEBUG_EXPRESSIONS)
1856  log_debug ("data: pick_first_value (NULL, %s)",
1857  print_hex_1 (result -> len,
1858  result -> data, 40));
1859 #endif
1860  return 1;
1861  }
1862 
1863 #if defined (DEBUG_EXPRESSIONS)
1864  log_debug ("data: pick_first_value (NULL, NULL) = NULL");
1865 #endif
1866  return 0;
1867 
1868  case expr_host_decl_name:
1869  if (!lease || !lease -> host) {
1870  log_error ("data: host_decl_name: not available");
1871  return 0;
1872  }
1873  result -> len = strlen (lease -> host -> name);
1874  if (buffer_allocate (&result -> buffer,
1875  result -> len + 1, file, line)) {
1876  result -> data = &result -> buffer -> data [0];
1877  strcpy ((char *)&result -> buffer -> data [0],
1878  lease -> host -> name);
1879  result -> terminated = 1;
1880  } else {
1881  log_error ("data: host-decl-name: no memory.");
1882  return 0;
1883  }
1884 #if defined (DEBUG_EXPRESSIONS)
1885  log_debug ("data: host-decl-name = %s", lease -> host -> name);
1886 #endif
1887  return 1;
1888 
1889  case expr_null:
1890 #if defined (DEBUG_EXPRESSIONS)
1891  log_debug ("data: null = NULL");
1892 #endif
1893  return 0;
1894 
1896  if (scope && *scope) {
1897  binding = find_binding (*scope, expr -> data.variable);
1898 
1899  if (binding && binding -> value) {
1900  if (binding -> value -> type == binding_data) {
1901  data_string_copy (result,
1902  &binding -> value -> value.data,
1903  file, line);
1904  s0 = 1;
1905  } else if (binding -> value -> type != binding_data) {
1906  log_error ("binding type %d in %s.",
1907  binding -> value -> type,
1908  "evaluate_data_expression");
1909  s0 = 0;
1910  } else
1911  s0 = 0;
1912  } else
1913  s0 = 0;
1914  } else
1915  s0 = 0;
1916 #if defined (DEBUG_EXPRESSIONS)
1917  log_debug ("data: %s = %s", expr -> data.variable,
1918  s0 ? print_hex_1 (result -> len,
1919  result -> data, 50) : "NULL");
1920 #endif
1921  return s0;
1922 
1923  case expr_funcall:
1924  bv = (struct binding_value *)0;
1925  s0 = evaluate_expression (&bv, packet, lease, client_state,
1926  in_options, cfg_options,
1927  scope, expr, MDL);
1928  if (s0) {
1929  if (bv -> type != binding_data)
1930  log_error ("%s() returned type %d in %s.",
1931  expr -> data.funcall.name,
1932  bv -> type,
1933  "evaluate_data_expression");
1934  else
1935  data_string_copy (result, &bv -> value.data,
1936  file, line);
1938  }
1939 #if defined (DEBUG_EXPRESSIONS)
1940  log_debug ("data: %s = %s", expr -> data.funcall.name,
1941  s0 ? print_hex_1 (result -> len,
1942  result -> data, 50) : "NULL");
1943 #endif
1944  break;
1945 
1946  /* Extract the filename. */
1947  case expr_filename:
1948  if (packet && packet -> raw -> file [0]) {
1949  char *fn =
1950  memchr (packet -> raw -> file, 0,
1951  sizeof packet -> raw -> file);
1952  if (!fn)
1953  fn = ((char *)packet -> raw -> file +
1954  sizeof packet -> raw -> file);
1955  result -> len = fn - &(packet -> raw -> file [0]);
1956  if (buffer_allocate (&result -> buffer,
1957  result -> len + 1, file, line)) {
1958  result -> data = &result -> buffer -> data [0];
1959  memcpy (&result -> buffer -> data [0],
1960  packet -> raw -> file,
1961  result -> len);
1962  result -> buffer -> data [result -> len] = 0;
1963  result -> terminated = 1;
1964  s0 = 1;
1965  } else {
1966  log_error ("data: filename: no memory.");
1967  s0 = 0;
1968  }
1969  } else
1970  s0 = 0;
1971 
1972 #if defined (DEBUG_EXPRESSIONS)
1973  log_info ("data: filename = \"%s\"",
1974  s0 ? (const char *)(result -> data) : "NULL");
1975 #endif
1976  return s0;
1977 
1978  /* Extract the server name. */
1979  case expr_sname:
1980  if (packet && packet -> raw -> sname [0]) {
1981  char *fn =
1982  memchr (packet -> raw -> sname, 0,
1983  sizeof packet -> raw -> sname);
1984  if (!fn)
1985  fn = ((char *)packet -> raw -> sname +
1986  sizeof packet -> raw -> sname);
1987  result -> len = fn - &packet -> raw -> sname [0];
1988  if (buffer_allocate (&result -> buffer,
1989  result -> len + 1, file, line)) {
1990  result -> data = &result -> buffer -> data [0];
1991  memcpy (&result -> buffer -> data [0],
1992  packet -> raw -> sname,
1993  result -> len);
1994  result -> buffer -> data [result -> len] = 0;
1995  result -> terminated = 1;
1996  s0 = 1;
1997  } else {
1998  log_error ("data: sname: no memory.");
1999  s0 = 0;
2000  }
2001  } else
2002  s0 = 0;
2003 
2004 #if defined (DEBUG_EXPRESSIONS)
2005  log_info ("data: sname = \"%s\"",
2006  s0 ? (const char *)(result -> data) : "NULL");
2007 #endif
2008  return s0;
2009 
2010  /* Provide the system's local hostname as a return value. */
2011  case expr_gethostname:
2012  /*
2013  * Allocate a buffer to return.
2014  *
2015  * The largest valid hostname is maybe 64 octets at a single
2016  * label, or 255 octets if you think a hostname is allowed
2017  * to contain labels (plus termination).
2018  */
2019  memset(result, 0, sizeof(*result));
2020  if (!buffer_allocate(&result->buffer, 255, file, line)) {
2021  log_error("data: gethostname(): no memory for buffer");
2022  return 0;
2023  }
2024  result->data = result->buffer->data;
2025 
2026  /*
2027  * On successful completion, gethostname() resturns 0. It may
2028  * not null-terminate the string if there was insufficient
2029  * space.
2030  */
2031  if (!gethostname((char *)result->buffer->data, 255)) {
2032  if (result->buffer->data[255] == '\0')
2033  result->len =
2034  strlen((char *)result->buffer->data);
2035  else
2036  result->len = 255;
2037  return 1;
2038  }
2039 
2040  data_string_forget(result, MDL);
2041  return 0;
2042 
2043  /* Find an option within a v6relay context
2044  *
2045  * The numeric expression in relay indicates which relay
2046  * to try and use as the context. The relays are numbered
2047  * 1 to 32 with 1 being the one closest to the client and
2048  * 32 closest to the server. A value of greater than 33
2049  * indicates using the one closest to the server whatever
2050  * the count. A value of 0 indicates not using the relay
2051  * options, this is included for completeness and consistency
2052  * with the host-identier code.
2053  *
2054  * The data expression in roption is evaluated in that
2055  * context and the result returned.
2056  */
2057  case expr_v6relay:
2058  len = 0;
2059  s1 = 0;
2060  memset (&data, 0, sizeof data);
2061 
2062  /* Evaluate the relay count */
2063  s0 = evaluate_numeric_expression(&len, packet, lease,
2064  client_state,
2065  in_options, cfg_options,
2066  scope,
2067  expr->data.v6relay.relay);
2068 
2069  /* no number or an obviously invalid number */
2070  if ((s0 == 0) ||
2071  ((len > 0) &&
2072  ((packet == NULL) ||
2073  (packet->dhcpv6_container_packet == NULL)))) {
2074 #if defined (DEBUG_EXPRESSIONS)
2075  log_debug("data: v6relay(%d) = NULL", len);
2076 #endif
2077  return (0);
2078  }
2079 
2080  /* Find the correct packet for the requested relay */
2081  i = len;
2082  relay_packet = packet;
2083  relay_options = in_options;
2084  while ((i != 0) &&
2085  (relay_packet->dhcpv6_container_packet != NULL)) {
2086  relay_packet = relay_packet->dhcpv6_container_packet;
2087  relay_options = relay_packet->options;
2088  i--;
2089  }
2090  /* We wanted a specific relay but were unable to find it */
2091  if ((len <= MAX_V6RELAY_HOPS) && (i != 0)) {
2092 #if defined (DEBUG_EXPRESSIONS)
2093  log_debug("data: v6relay(%d) = NULL", len);
2094 #endif
2095  return (0);
2096  }
2097 
2098  s1 = evaluate_data_expression(&data, relay_packet, lease,
2099  client_state, relay_options,
2100  cfg_options, scope,
2101  expr->data.v6relay.roption,
2102  MDL);
2103 
2104  if (s1) {
2105  data_string_copy(result, &data, file, line);
2106  data_string_forget(&data, MDL);
2107  }
2108 
2109 #if defined (DEBUG_EXPRESSIONS)
2110  log_debug("data: v6relay(%d) = %s", len,
2111  s1 ? print_hex_3(result->len, result->data, 30)
2112  : "NULL");
2113 #endif
2114  return (s1);
2115 
2116  case expr_check:
2117  case expr_equal:
2118  case expr_not_equal:
2119  case expr_regex_match:
2120  case expr_iregex_match:
2121  case expr_and:
2122  case expr_or:
2123  case expr_not:
2124  case expr_match:
2125  case expr_static:
2126  case expr_known:
2127  case expr_none:
2128  case expr_exists:
2129  case expr_variable_exists:
2130  log_error ("Boolean opcode in evaluate_data_expression: %d",
2131  expr -> op);
2132  return 0;
2133 
2134  case expr_extract_int8:
2135  case expr_extract_int16:
2136  case expr_extract_int32:
2137  case expr_const_int:
2138  case expr_lease_time:
2139  case expr_dns_transaction:
2140  case expr_add:
2141  case expr_subtract:
2142  case expr_multiply:
2143  case expr_divide:
2144  case expr_remainder:
2145  case expr_binary_and:
2146  case expr_binary_or:
2147  case expr_binary_xor:
2148  case expr_client_state:
2149  log_error ("Numeric opcode in evaluate_data_expression: %d",
2150  expr -> op);
2151  return 0;
2152 
2153  case expr_ns_add:
2154  case expr_ns_delete:
2155  case expr_ns_exists:
2156  case expr_ns_not_exists:
2157  log_error ("dns opcode in evaluate_boolean_expression: %d",
2158  expr -> op);
2159  return 0;
2160 
2161  case expr_function:
2162  log_error ("function definition in evaluate_data_expression");
2163  return 0;
2164 
2165  case expr_arg:
2166  break;
2167  }
2168 
2169  log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op);
2170  return 0;
2171 }
2172 
2174  in_options, cfg_options, scope, expr)
2175  unsigned long *result;
2176  struct packet *packet;
2177  struct lease *lease;
2178  struct client_state *client_state;
2179  struct option_state *in_options;
2180  struct option_state *cfg_options;
2181  struct binding_scope **scope;
2182  struct expression *expr;
2183 {
2184  struct data_string data;
2185  int status, sleft, sright;
2186 
2187  struct binding *binding;
2188  struct binding_value *bv;
2189  unsigned long ileft, iright;
2190  int rc = 0;
2191 
2192  switch (expr -> op) {
2193  case expr_check:
2194  case expr_equal:
2195  case expr_not_equal:
2196  case expr_regex_match:
2197  case expr_iregex_match:
2198  case expr_and:
2199  case expr_or:
2200  case expr_not:
2201  case expr_match:
2202  case expr_static:
2203  case expr_known:
2204  case expr_none:
2205  case expr_exists:
2206  case expr_variable_exists:
2207  log_error ("Boolean opcode in evaluate_numeric_expression: %d",
2208  expr -> op);
2209  return 0;
2210 
2211  case expr_substring:
2212  case expr_suffix:
2213  case expr_lcase:
2214  case expr_ucase:
2215  case expr_option:
2216  case expr_hardware:
2217  case expr_const_data:
2218  case expr_packet:
2219  case expr_concat:
2220  case expr_encapsulate:
2221  case expr_host_lookup:
2222  case expr_encode_int8:
2223  case expr_encode_int16:
2224  case expr_encode_int32:
2225  case expr_binary_to_ascii:
2226  case expr_reverse:
2227  case expr_filename:
2228  case expr_sname:
2229  case expr_pick_first_value:
2230  case expr_host_decl_name:
2231  case expr_config_option:
2232  case expr_leased_address:
2233  case expr_null:
2234  case expr_gethostname:
2235  case expr_v6relay:
2236  log_error ("Data opcode in evaluate_numeric_expression: %d",
2237  expr -> op);
2238  return 0;
2239 
2240  case expr_extract_int8:
2241  memset (&data, 0, sizeof data);
2242  status = evaluate_data_expression
2243  (&data, packet, lease, client_state, in_options,
2244  cfg_options, scope, expr -> data.extract_int, MDL);
2245  if (status)
2246  *result = data.data [0];
2247 #if defined (DEBUG_EXPRESSIONS)
2248  log_debug ("num: extract_int8 (%s) = %s",
2249  status ? print_hex_1 (data.len, data.data, 60) : "NULL",
2250  status ? print_dec_1 (*result) : "NULL" );
2251 #endif
2252  if (status) data_string_forget (&data, MDL);
2253  return status;
2254 
2255  case expr_extract_int16:
2256  memset(&data, 0, sizeof(data));
2257  status = (evaluate_data_expression
2258  (&data, packet, lease, client_state, in_options,
2259  cfg_options, scope, expr->data.extract_int, MDL));
2260  if (status && data.len >= 2) {
2261  *result = getUShort(data.data);
2262  rc = 1;
2263  }
2264 #if defined (DEBUG_EXPRESSIONS)
2265  if (rc == 1) {
2266  log_debug("num: extract_int16 (%s) = %ld",
2267  print_hex_1(data.len, data.data, 60),
2268  *result);
2269  } else {
2270  log_debug("num: extract_int16 (NULL) = NULL");
2271  }
2272 #endif
2273  if (status)
2274  data_string_forget(&data, MDL);
2275 
2276  return (rc);
2277 
2278  case expr_extract_int32:
2279  memset (&data, 0, sizeof data);
2280  status = (evaluate_data_expression
2281  (&data, packet, lease, client_state, in_options,
2282  cfg_options, scope, expr -> data.extract_int, MDL));
2283  if (status && data.len >= 4) {
2284  *result = getULong (data.data);
2285  rc = 1;
2286  }
2287 #if defined (DEBUG_EXPRESSIONS)
2288  if (rc == 1) {
2289  log_debug ("num: extract_int32 (%s) = %ld",
2290  print_hex_1 (data.len, data.data, 60),
2291  *result);
2292  } else {
2293  log_debug ("num: extract_int32 (NULL) = NULL");
2294  }
2295 #endif
2296  if (status) data_string_forget (&data, MDL);
2297  return (rc);
2298 
2299  case expr_const_int:
2300  *result = expr -> data.const_int;
2301 #if defined (DEBUG_EXPRESSIONS)
2302  log_debug ("number: CONSTANT = %ld", *result);
2303 #endif
2304  return 1;
2305 
2306  case expr_lease_time:
2307  if (!lease) {
2308  log_error("data: leased_lease: not available");
2309  return (0);
2310  }
2311  if (lease->ends < cur_time) {
2312  log_error("%s %lu when it is now %lu",
2313  "data: lease_time: lease ends at",
2314  (long)(lease->ends), (long)cur_time);
2315  return (0);
2316  }
2317  *result = lease->ends - cur_time;
2318 #if defined (DEBUG_EXPRESSIONS)
2319  log_debug("number: lease-time = (%lu - %lu) = %ld",
2320  (long unsigned)lease->ends,
2321  (long unsigned)cur_time, *result);
2322 #endif
2323  return (1);
2324 
2326  if (scope && *scope) {
2327  binding = find_binding (*scope, expr -> data.variable);
2328 
2329  if (binding && binding -> value) {
2330  if (binding -> value -> type == binding_numeric) {
2331  *result = binding -> value -> value.intval;
2332  status = 1;
2333  } else {
2334  log_error ("binding type %d in %s.",
2335  binding -> value -> type,
2336  "evaluate_numeric_expression");
2337  status = 0;
2338  }
2339  } else
2340  status = 0;
2341  } else
2342  status = 0;
2343 #if defined (DEBUG_EXPRESSIONS)
2344  if (status)
2345  log_debug ("numeric: %s = %ld",
2346  expr -> data.variable, *result);
2347  else
2348  log_debug ("numeric: %s = NULL",
2349  expr -> data.variable);
2350 #endif
2351  return status;
2352 
2353  case expr_funcall:
2354  bv = (struct binding_value *)0;
2355  status = evaluate_expression (&bv, packet, lease,
2356  client_state,
2357  in_options, cfg_options,
2358  scope, expr, MDL);
2359  if (status) {
2360  if (bv -> type != binding_numeric)
2361  log_error ("%s() returned type %d in %s.",
2362  expr -> data.funcall.name,
2363  bv -> type,
2364  "evaluate_numeric_expression");
2365  else
2366  *result = bv -> value.intval;
2368  }
2369 #if defined (DEBUG_EXPRESSIONS)
2370  log_debug ("data: %s = %ld", expr -> data.funcall.name,
2371  status ? *result : 0);
2372 #endif
2373  break;
2374 
2375  case expr_add:
2376  sleft = evaluate_numeric_expression (&ileft, packet, lease,
2377  client_state,
2378  in_options, cfg_options,
2379  scope,
2380  expr -> data.and [0]);
2381  sright = evaluate_numeric_expression (&iright, packet, lease,
2382  client_state,
2383  in_options, cfg_options,
2384  scope,
2385  expr -> data.and [1]);
2386 
2387 #if defined (DEBUG_EXPRESSIONS)
2388  if (sleft && sright)
2389  log_debug ("num: %ld + %ld = %ld",
2390  ileft, iright, ileft + iright);
2391  else if (sleft)
2392  log_debug ("num: %ld + NULL = NULL", ileft);
2393  else
2394  log_debug ("num: NULL + %ld = NULL", iright);
2395 #endif
2396  if (sleft && sright) {
2397  *result = ileft + iright;
2398  return 1;
2399  }
2400  return 0;
2401 
2402  case expr_subtract:
2403  sleft = evaluate_numeric_expression (&ileft, packet, lease,
2404  client_state,
2405  in_options, cfg_options,
2406  scope,
2407  expr -> data.and [0]);
2408  sright = evaluate_numeric_expression (&iright, packet, lease,
2409  client_state,
2410  in_options, cfg_options,
2411  scope,
2412  expr -> data.and [1]);
2413 
2414 #if defined (DEBUG_EXPRESSIONS)
2415  if (sleft && sright)
2416  log_debug ("num: %ld - %ld = %ld",
2417  ileft, iright, ileft - iright);
2418  else if (sleft)
2419  log_debug ("num: %ld - NULL = NULL", ileft);
2420  else
2421  log_debug ("num: NULL - %ld = NULL", iright);
2422 #endif
2423  if (sleft && sright) {
2424  *result = ileft - iright;
2425  return 1;
2426  }
2427  return 0;
2428 
2429  case expr_multiply:
2430  sleft = evaluate_numeric_expression (&ileft, packet, lease,
2431  client_state,
2432  in_options, cfg_options,
2433  scope,
2434  expr -> data.and [0]);
2435  sright = evaluate_numeric_expression (&iright, packet, lease,
2436  client_state,
2437  in_options, cfg_options,
2438  scope,
2439  expr -> data.and [1]);
2440 
2441 #if defined (DEBUG_EXPRESSIONS)
2442  if (sleft && sright)
2443  log_debug ("num: %ld * %ld = %ld",
2444  ileft, iright, ileft * iright);
2445  else if (sleft)
2446  log_debug ("num: %ld * NULL = NULL", ileft);
2447  else
2448  log_debug ("num: NULL * %ld = NULL", iright);
2449 #endif
2450  if (sleft && sright) {
2451  *result = ileft * iright;
2452  return 1;
2453  }
2454  return 0;
2455 
2456  case expr_divide:
2457  sleft = evaluate_numeric_expression (&ileft, packet, lease,
2458  client_state,
2459  in_options, cfg_options,
2460  scope,
2461  expr -> data.and [0]);
2462  sright = evaluate_numeric_expression (&iright, packet, lease,
2463  client_state,
2464  in_options, cfg_options,
2465  scope,
2466  expr -> data.and [1]);
2467 
2468 #if defined (DEBUG_EXPRESSIONS)
2469  if (sleft && sright) {
2470  if (iright != 0)
2471  log_debug ("num: %ld / %ld = %ld",
2472  ileft, iright, ileft / iright);
2473  else
2474  log_debug ("num: %ld / %ld = NULL",
2475  ileft, iright);
2476  } else if (sleft)
2477  log_debug ("num: %ld / NULL = NULL", ileft);
2478  else
2479  log_debug ("num: NULL / %ld = NULL", iright);
2480 #endif
2481  if (sleft && sright && iright) {
2482  *result = ileft / iright;
2483  return 1;
2484  }
2485  return 0;
2486 
2487  case expr_remainder:
2488  sleft = evaluate_numeric_expression (&ileft, packet, lease,
2489  client_state,
2490  in_options, cfg_options,
2491  scope,
2492  expr -> data.and [0]);
2493  sright = evaluate_numeric_expression (&iright, packet, lease,
2494  client_state,
2495  in_options, cfg_options,
2496  scope,
2497  expr -> data.and [1]);
2498 
2499 #if defined (DEBUG_EXPRESSIONS)
2500  if (sleft && sright) {
2501  if (iright != 0)
2502  log_debug ("num: %ld %% %ld = %ld",
2503  ileft, iright, ileft % iright);
2504  else
2505  log_debug ("num: %ld %% %ld = NULL",
2506  ileft, iright);
2507  } else if (sleft)
2508  log_debug ("num: %ld %% NULL = NULL", ileft);
2509  else
2510  log_debug ("num: NULL %% %ld = NULL", iright);
2511 #endif
2512  if (sleft && sright && iright) {
2513  *result = ileft % iright;
2514  return 1;
2515  }
2516  return 0;
2517 
2518  case expr_binary_and:
2519  sleft = evaluate_numeric_expression (&ileft, packet, lease,
2520  client_state,
2521  in_options, cfg_options,
2522  scope,
2523  expr -> data.and [0]);
2524  sright = evaluate_numeric_expression (&iright, packet, lease,
2525  client_state,
2526  in_options, cfg_options,
2527  scope,
2528  expr -> data.and [1]);
2529 
2530 #if defined (DEBUG_EXPRESSIONS)
2531  if (sleft && sright)
2532  log_debug ("num: %ld | %ld = %ld",
2533  ileft, iright, ileft & iright);
2534  else if (sleft)
2535  log_debug ("num: %ld & NULL = NULL", ileft);
2536  else
2537  log_debug ("num: NULL & %ld = NULL", iright);
2538 #endif
2539  if (sleft && sright) {
2540  *result = ileft & iright;
2541  return 1;
2542  }
2543  return 0;
2544 
2545  case expr_binary_or:
2546  sleft = evaluate_numeric_expression (&ileft, packet, lease,
2547  client_state,
2548  in_options, cfg_options,
2549  scope,
2550  expr -> data.and [0]);
2551  sright = evaluate_numeric_expression (&iright, packet, lease,
2552  client_state,
2553  in_options, cfg_options,
2554  scope,
2555  expr -> data.and [1]);
2556 
2557 #if defined (DEBUG_EXPRESSIONS)
2558  if (sleft && sright)
2559  log_debug ("num: %ld | %ld = %ld",
2560  ileft, iright, ileft | iright);
2561  else if (sleft)
2562  log_debug ("num: %ld | NULL = NULL", ileft);
2563  else
2564  log_debug ("num: NULL | %ld = NULL", iright);
2565 #endif
2566  if (sleft && sright) {
2567  *result = ileft | iright;
2568  return 1;
2569  }
2570  return 0;
2571 
2572  case expr_binary_xor:
2573  sleft = evaluate_numeric_expression (&ileft, packet, lease,
2574  client_state,
2575  in_options, cfg_options,
2576  scope,
2577  expr -> data.and [0]);
2578  sright = evaluate_numeric_expression (&iright, packet, lease,
2579  client_state,
2580  in_options, cfg_options,
2581  scope,
2582  expr -> data.and [1]);
2583 
2584 #if defined (DEBUG_EXPRESSIONS)
2585  if (sleft && sright)
2586  log_debug ("num: %ld ^ %ld = %ld",
2587  ileft, iright, ileft ^ iright);
2588  else if (sleft)
2589  log_debug ("num: %ld ^ NULL = NULL", ileft);
2590  else
2591  log_debug ("num: NULL ^ %ld = NULL", iright);
2592 #endif
2593  if (sleft && sright) {
2594  *result = ileft ^ iright;
2595  return 1;
2596  }
2597  return 0;
2598 
2599  case expr_client_state:
2600  if (client_state) {
2601 #if defined (DEBUG_EXPRESSIONS)
2602  log_debug ("num: client-state = %d",
2603  client_state -> state);
2604 #endif
2605  *result = client_state -> state;
2606  return 1;
2607  } else {
2608 #if defined (DEBUG_EXPRESSIONS)
2609  log_debug ("num: client-state = NULL");
2610 #endif
2611  return 0;
2612  }
2613 
2614  case expr_function:
2615  log_error ("function definition in evaluate_numeric_expr");
2616  return 0;
2617 
2618  case expr_arg:
2619  break;
2620 
2621  default:
2622  log_fatal("Impossible case at %s:%d. Undefined operator "
2623  "%d.", MDL, expr->op);
2624  break;
2625  }
2626 
2627  log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op);
2628  return 0;
2629 }
2630 
2631 /*
2632  * Return data hanging off of an option cache structure, or if there
2633  * isn't any, evaluate the expression hanging off of it and return the
2634  * result of that evaluation. There should never be both an expression
2635  * and a valid data_string.
2636  *
2637  * returns 0 if there wasn't an expression or it couldn't be evaluated
2638  * returns non-zero if there was an expression or string that was evaluated
2639  * When it returns zero the arguements, in particualr resutl, should not
2640  * be modified
2641  */
2642 
2644  in_options, cfg_options, scope, oc, file, line)
2645  struct data_string *result;
2646  struct packet *packet;
2647  struct lease *lease;
2648  struct client_state *client_state;
2649  struct option_state *in_options;
2650  struct option_state *cfg_options;
2651  struct binding_scope **scope;
2652  struct option_cache *oc;
2653  const char *file;
2654  int line;
2655 {
2656  if (oc->data.data != NULL) {
2657  data_string_copy (result, &oc -> data, file, line);
2658  return 1;
2659  }
2660  if (!oc -> expression)
2661  return 0;
2662  return evaluate_data_expression (result, packet, lease, client_state,
2663  in_options, cfg_options, scope,
2664  oc -> expression, file, line);
2665 }
2666 
2667 /* Evaluate an option cache and extract a boolean from the result,
2668  returning the boolean. Return false if there is no data. */
2669 
2671  lease, client_state, in_options,
2672  cfg_options, scope, oc, file, line)
2673  int *ignorep;
2674  struct packet *packet;
2675  struct lease *lease;
2676  struct client_state *client_state;
2677  struct option_state *in_options;
2678  struct option_state *cfg_options;
2679  struct binding_scope **scope;
2680  struct option_cache *oc;
2681  const char *file;
2682  int line;
2683 {
2684  struct data_string ds;
2685  int result;
2686 
2687  /* So that we can be called with option_lookup as an argument. */
2688  if (!oc || !in_options)
2689  return 0;
2690 
2691  memset (&ds, 0, sizeof ds);
2692  if (!evaluate_option_cache (&ds, packet,
2693  lease, client_state, in_options,
2694  cfg_options, scope, oc, file, line))
2695  return 0;
2696 
2697  /* The boolean option cache is actually a trinary value. Zero is
2698  * off, one is on, and 2 is 'ignore'.
2699  */
2700  if (ds.len) {
2701  result = ds.data [0];
2702  if (result == 2) {
2703  result = 0;
2704  if (ignorep != NULL)
2705  *ignorep = 1;
2706  } else if (ignorep != NULL)
2707  *ignorep = 0;
2708  } else
2709  result = 0;
2710  data_string_forget (&ds, MDL);
2711  return result;
2712 }
2713 
2714 
2715 /* Evaluate a boolean expression and return the result of the evaluation,
2716  or FALSE if it failed. */
2717 
2719  in_options, cfg_options, scope, expr)
2720  int *ignorep;
2721  struct packet *packet;
2722  struct lease *lease;
2723  struct client_state *client_state;
2724  struct option_state *in_options;
2725  struct option_state *cfg_options;
2726  struct binding_scope **scope;
2727  struct expression *expr;
2728 {
2729  int result;
2730 
2731  /* So that we can be called with option_lookup as an argument. */
2732  if (!expr)
2733  return 0;
2734 
2735  if (!evaluate_boolean_expression (&result, packet, lease, client_state,
2736  in_options, cfg_options,
2737  scope, expr))
2738  return 0;
2739 
2740  if (result == 2) {
2741  *ignorep = 1;
2742  result = 0;
2743  } else
2744  *ignorep = 0;
2745  return result;
2746 }
2747 
2748 
2749 /* Dereference an expression node, and if the reference count goes to zero,
2750  dereference any data it refers to, and then free it. */
2752  struct expression **eptr;
2753  const char *file;
2754  int line;
2755 {
2756  struct expression *expr = *eptr;
2757 
2758  /* Zero the pointer. */
2759  *eptr = (struct expression *)0;
2760 
2761  /* Decrement the reference count. If it's nonzero, we're
2762  done. */
2763  --(expr -> refcnt);
2764  rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC);
2765  if (expr -> refcnt > 0)
2766  return;
2767  if (expr -> refcnt < 0) {
2768  log_error ("%s(%d): negative refcnt!", file, line);
2769 #if defined (DEBUG_RC_HISTORY)
2770  dump_rc_history (expr);
2771 #endif
2772 #if defined (POINTER_DEBUG)
2773  abort ();
2774 #else
2775  return;
2776 #endif
2777  }
2778 
2779  /* Dereference subexpressions. */
2780  switch (expr -> op) {
2781  /* All the binary operators can be handled the same way. */
2782  case expr_equal:
2783  case expr_not_equal:
2784  case expr_regex_match:
2785  case expr_iregex_match:
2786  case expr_concat:
2787  case expr_and:
2788  case expr_or:
2789  case expr_add:
2790  case expr_subtract:
2791  case expr_multiply:
2792  case expr_divide:
2793  case expr_remainder:
2794  case expr_binary_and:
2795  case expr_binary_or:
2796  case expr_binary_xor:
2797  case expr_client_state:
2798  if (expr -> data.equal [0])
2799  expression_dereference (&expr -> data.equal [0],
2800  file, line);
2801  if (expr -> data.equal [1])
2802  expression_dereference (&expr -> data.equal [1],
2803  file, line);
2804  break;
2805 
2806  case expr_substring:
2807  if (expr -> data.substring.expr)
2809  file, line);
2810  if (expr -> data.substring.offset)
2812  file, line);
2813  if (expr -> data.substring.len)
2815  file, line);
2816  break;
2817 
2818  case expr_suffix:
2819  if (expr -> data.suffix.expr)
2821  file, line);
2822  if (expr -> data.suffix.len)
2824  file, line);
2825  break;
2826 
2827  case expr_lcase:
2828  if (expr->data.lcase)
2830  break;
2831 
2832  case expr_ucase:
2833  if (expr->data.ucase)
2835  break;
2836 
2837  case expr_not:
2838  if (expr -> data.not)
2839  expression_dereference (&expr -> data.not, file, line);
2840  break;
2841 
2842  case expr_packet:
2843  if (expr -> data.packet.offset)
2845  file, line);
2846  if (expr -> data.packet.len)
2848  file, line);
2849  break;
2850 
2851  case expr_extract_int8:
2852  case expr_extract_int16:
2853  case expr_extract_int32:
2854  if (expr -> data.extract_int)
2856  file, line);
2857  break;
2858 
2859  case expr_encode_int8:
2860  case expr_encode_int16:
2861  case expr_encode_int32:
2862  if (expr -> data.encode_int)
2864  file, line);
2865  break;
2866 
2867  case expr_encapsulate:
2868  case expr_const_data:
2869  data_string_forget (&expr -> data.const_data, file, line);
2870  break;
2871 
2872  case expr_host_lookup:
2873  if (expr -> data.host_lookup)
2875  file, line);
2876  break;
2877 
2878  case expr_binary_to_ascii:
2879  if (expr -> data.b2a.base)
2880  expression_dereference (&expr -> data.b2a.base,
2881  file, line);
2882  if (expr -> data.b2a.width)
2884  file, line);
2885  if (expr -> data.b2a.separator)
2887  file, line);
2888  if (expr -> data.b2a.buffer)
2890  file, line);
2891  break;
2892 
2893  case expr_pick_first_value:
2894  if (expr -> data.pick_first_value.car)
2896  file, line);
2897  if (expr -> data.pick_first_value.cdr)
2899  file, line);
2900  break;
2901 
2902  case expr_reverse:
2903  if (expr -> data.reverse.width)
2905  file, line);
2906  if (expr -> data.reverse.buffer)
2908  (&expr -> data.reverse.buffer, file, line);
2909  break;
2910 
2912  case expr_variable_exists:
2913  if (expr -> data.variable)
2914  dfree (expr -> data.variable, file, line);
2915  break;
2916 
2917  case expr_funcall:
2918  if (expr -> data.funcall.name)
2919  dfree (expr -> data.funcall.name, file, line);
2920  if (expr -> data.funcall.arglist)
2922  file, line);
2923  break;
2924 
2925  case expr_arg:
2926  if (expr -> data.arg.val)
2927  expression_dereference (&expr -> data.arg.val,
2928  file, line);
2929  if (expr -> data.arg.next)
2930  expression_dereference (&expr -> data.arg.next,
2931  file, line);
2932  break;
2933 
2934  case expr_function:
2935  fundef_dereference (&expr -> data.func, file, line);
2936  break;
2937 
2938  case expr_v6relay:
2939  if (expr->data.v6relay.relay)
2941  file, line);
2942 
2943  if (expr->data.v6relay.roption)
2945  file, line);
2946  break;
2947 
2948  /* No subexpressions. */
2949  case expr_leased_address:
2950  case expr_lease_time:
2951  case expr_filename:
2952  case expr_sname:
2953  case expr_const_int:
2954  case expr_check:
2955  case expr_option:
2956  case expr_hardware:
2957  case expr_exists:
2958  case expr_known:
2959  case expr_null:
2960  case expr_gethostname:
2961  break;
2962 
2963  default:
2964  break;
2965  }
2966  free_expression (expr, MDL);
2967 }
2968 
2970  struct expression *expr;
2971 {
2972  return (expr -> op == expr_check ||
2973  expr -> op == expr_exists ||
2974  expr -> op == expr_variable_exists ||
2975  expr -> op == expr_equal ||
2976  expr -> op == expr_not_equal ||
2977  expr->op == expr_regex_match ||
2978  expr->op == expr_iregex_match ||
2979  expr -> op == expr_and ||
2980  expr -> op == expr_or ||
2981  expr -> op == expr_not ||
2982  expr -> op == expr_known ||
2983  expr -> op == expr_static);
2984 }
2985 
2987  struct expression *expr;
2988 {
2989  return (expr->op == expr_substring ||
2990  expr->op == expr_suffix ||
2991  expr->op == expr_lcase ||
2992  expr->op == expr_ucase ||
2993  expr->op == expr_option ||
2994  expr->op == expr_hardware ||
2995  expr->op == expr_const_data ||
2996  expr->op == expr_packet ||
2997  expr->op == expr_concat ||
2998  expr->op == expr_encapsulate ||
2999  expr->op == expr_encode_int8 ||
3000  expr->op == expr_encode_int16 ||
3001  expr->op == expr_encode_int32 ||
3002  expr->op == expr_host_lookup ||
3003  expr->op == expr_binary_to_ascii ||
3004  expr->op == expr_filename ||
3005  expr->op == expr_sname ||
3006  expr->op == expr_reverse ||
3007  expr->op == expr_pick_first_value ||
3008  expr->op == expr_host_decl_name ||
3009  expr->op == expr_leased_address ||
3010  expr->op == expr_config_option ||
3011  expr->op == expr_null ||
3012  expr->op == expr_gethostname ||
3013  expr->op == expr_v6relay);
3014 }
3015 
3017  struct expression *expr;
3018 {
3019  return (expr -> op == expr_extract_int8 ||
3020  expr -> op == expr_extract_int16 ||
3021  expr -> op == expr_extract_int32 ||
3022  expr -> op == expr_const_int ||
3023  expr -> op == expr_lease_time ||
3024  expr -> op == expr_add ||
3025  expr -> op == expr_subtract ||
3026  expr -> op == expr_multiply ||
3027  expr -> op == expr_divide ||
3028  expr -> op == expr_remainder ||
3029  expr -> op == expr_binary_and ||
3030  expr -> op == expr_binary_or ||
3031  expr -> op == expr_binary_xor ||
3032  expr -> op == expr_client_state);
3033 }
3034 
3036  struct expression *expr;
3037 {
3038  return (expr -> op == expr_substring ||
3039  expr -> op == expr_suffix ||
3040  expr -> op == expr_option ||
3041  expr -> op == expr_concat ||
3042  expr -> op == expr_encode_int8 ||
3043  expr -> op == expr_encode_int16 ||
3044  expr -> op == expr_encode_int32 ||
3045  expr -> op == expr_binary_to_ascii ||
3046  expr -> op == expr_reverse ||
3047  expr -> op == expr_pick_first_value ||
3048  expr -> op == expr_config_option ||
3049  expr -> op == expr_extract_int8 ||
3050  expr -> op == expr_extract_int16 ||
3051  expr -> op == expr_extract_int32 ||
3052  expr -> op == expr_v6relay);
3053 }
3054 
3055 static int op_val (enum expr_op);
3056 
3057 static int op_val (op)
3058  enum expr_op op;
3059 {
3060  switch (op) {
3061  case expr_none:
3062  case expr_match:
3063  case expr_static:
3064  case expr_check:
3065  case expr_substring:
3066  case expr_suffix:
3067  case expr_lcase:
3068  case expr_ucase:
3069  case expr_concat:
3070  case expr_encapsulate:
3071  case expr_host_lookup:
3072  case expr_not:
3073  case expr_option:
3074  case expr_hardware:
3075  case expr_packet:
3076  case expr_const_data:
3077  case expr_extract_int8:
3078  case expr_extract_int16:
3079  case expr_extract_int32:
3080  case expr_encode_int8:
3081  case expr_encode_int16:
3082  case expr_encode_int32:
3083  case expr_const_int:
3084  case expr_exists:
3085  case expr_variable_exists:
3086  case expr_known:
3087  case expr_binary_to_ascii:
3088  case expr_reverse:
3089  case expr_filename:
3090  case expr_sname:
3091  case expr_pick_first_value:
3092  case expr_host_decl_name:
3093  case expr_config_option:
3094  case expr_leased_address:
3095  case expr_lease_time:
3096  case expr_dns_transaction:
3097  case expr_null:
3099  case expr_ns_add:
3100  case expr_ns_delete:
3101  case expr_ns_exists:
3102  case expr_ns_not_exists:
3103  case expr_arg:
3104  case expr_funcall:
3105  case expr_function:
3106  /* XXXDPN: Need to assign sane precedences to these. */
3107  case expr_binary_and:
3108  case expr_binary_or:
3109  case expr_binary_xor:
3110  case expr_client_state:
3111  case expr_gethostname:
3112  case expr_v6relay:
3113  return 100;
3114 
3115  case expr_equal:
3116  case expr_not_equal:
3117  case expr_regex_match:
3118  case expr_iregex_match:
3119  return 4;
3120 
3121  case expr_or:
3122  case expr_and:
3123  return 3;
3124 
3125  case expr_add:
3126  case expr_subtract:
3127  return 2;
3128 
3129  case expr_multiply:
3130  case expr_divide:
3131  case expr_remainder:
3132  return 1;
3133  }
3134  return 100;
3135 }
3136 
3137 int op_precedence (op1, op2)
3138  enum expr_op op1, op2;
3139 {
3140  return op_val (op1) - op_val (op2);
3141 }
3142 
3144 {
3145  if (is_data_expression (expr))
3146  return context_data;
3147  if (is_numeric_expression (expr))
3148  return context_numeric;
3149  if (is_boolean_expression (expr))
3150  return context_boolean;
3151  return context_any;
3152 }
3153 
3155  enum expr_op op;
3156 {
3157  switch (op) {
3158 /* XXX Why aren't these specific? */
3159  case expr_none:
3160  case expr_match:
3161  case expr_static:
3162  case expr_check:
3163  case expr_substring:
3164  case expr_suffix:
3165  case expr_lcase:
3166  case expr_ucase:
3167  case expr_concat:
3168  case expr_encapsulate:
3169  case expr_host_lookup:
3170  case expr_not:
3171  case expr_option:
3172  case expr_hardware:
3173  case expr_packet:
3174  case expr_const_data:
3175  case expr_extract_int8:
3176  case expr_extract_int16:
3177  case expr_extract_int32:
3178  case expr_encode_int8:
3179  case expr_encode_int16:
3180  case expr_encode_int32:
3181  case expr_const_int:
3182  case expr_exists:
3183  case expr_variable_exists:
3184  case expr_known:
3185  case expr_binary_to_ascii:
3186  case expr_reverse:
3187  case expr_filename:
3188  case expr_sname:
3189  case expr_pick_first_value:
3190  case expr_host_decl_name:
3191  case expr_config_option:
3192  case expr_leased_address:
3193  case expr_lease_time:
3194  case expr_null:
3196  case expr_ns_add:
3197  case expr_ns_delete:
3198  case expr_ns_exists:
3199  case expr_ns_not_exists:
3200  case expr_dns_transaction:
3201  case expr_arg:
3202  case expr_funcall:
3203  case expr_function:
3204  case expr_gethostname:
3205  case expr_v6relay:
3206  return context_any;
3207 
3208  case expr_equal:
3209  case expr_not_equal:
3210  case expr_regex_match:
3211  case expr_iregex_match:
3212  return context_data;
3213 
3214  case expr_and:
3215  return context_boolean;
3216 
3217  case expr_or:
3218  return context_boolean;
3219 
3220  case expr_add:
3221  case expr_subtract:
3222  case expr_multiply:
3223  case expr_divide:
3224  case expr_remainder:
3225  case expr_binary_and:
3226  case expr_binary_or:
3227  case expr_binary_xor:
3228  case expr_client_state:
3229  return context_numeric;
3230  }
3231  return context_any;
3232 }
3233 
3234 int write_expression (file, expr, col, indent, firstp)
3235  FILE *file;
3236  struct expression *expr;
3237  int col;
3238  int indent;
3239  int firstp;
3240 {
3241  struct expression *e;
3242  const char *s;
3243  char obuf [65];
3244  int scol;
3245  int width;
3246 
3247  /* If this promises to be a fat expression, start a new line. */
3248  if (!firstp && is_compound_expression (expr)) {
3249  indent_spaces (file, indent);
3250  col = indent;
3251  }
3252 
3253  switch (expr -> op) {
3254  case expr_none:
3255  col = token_print_indent (file, col, indent, "", "", "null");
3256  break;
3257 
3258  case expr_check:
3259  col = token_print_indent (file, col, indent, "", "", "check");
3260  col = token_print_indent_concat (file, col, indent,
3261  " ", "", "\"",
3262  expr -> data.check -> name,
3263  "\"", (char *)0);
3264  break;
3265 
3266  case expr_regex_match:
3267  s = "~=";
3268  goto binary;
3269 
3270  case expr_iregex_match:
3271  s = "~~";
3272  goto binary;
3273 
3274  case expr_not_equal:
3275  s = "!=";
3276  goto binary;
3277 
3278  case expr_equal:
3279  s = "=";
3280  binary:
3281  col = write_expression (file, expr -> data.equal [0],
3282  col, indent, 1);
3283  col = token_print_indent (file, col, indent, " ", " ", s);
3284  col = write_expression (file, expr -> data.equal [1],
3285  col, indent + 2, 0);
3286  break;
3287 
3288  case expr_substring:
3289  col = token_print_indent (file, col, indent, "", "",
3290  "substring");
3291  col = token_print_indent (file, col, indent, " ", "", "(");
3292  scol = col;
3293  col = write_expression (file, expr -> data.substring.expr,
3294  col, scol, 1);
3295  col = token_print_indent (file, col, indent, "", " ", ",");
3296  col = write_expression (file, expr -> data.substring.offset,
3297  col, indent, 0);
3298  col = token_print_indent (file, col, scol, "", " ", ",");
3299  col = write_expression (file, expr -> data.substring.len,
3300  col, scol, 0);
3301  col = token_print_indent (file, col, indent, "", "", ")");
3302  break;
3303 
3304  case expr_suffix:
3305  col = token_print_indent (file, col, indent, "", "", "suffix");
3306  col = token_print_indent (file, col, indent, " ", "", "(");
3307  scol = col;
3308  col = write_expression (file, expr -> data.suffix.expr,
3309  col, scol, 1);
3310  col = token_print_indent (file, col, scol, "", " ", ",");
3311  col = write_expression (file, expr -> data.suffix.len,
3312  col, scol, 0);
3313  col = token_print_indent (file, col, indent, "", "", ")");
3314  break;
3315 
3316  case expr_lcase:
3317  col = token_print_indent(file, col, indent, "", "", "lcase");
3318  col = token_print_indent(file, col, indent, " ", "", "(");
3319  scol = col;
3320  col = write_expression(file, expr->data.lcase, col, scol, 1);
3321  col = token_print_indent(file, col, indent, "", "", ")");
3322  break;
3323 
3324  case expr_ucase:
3325  col = token_print_indent(file, col, indent, "", "", "ucase");
3326  col = token_print_indent(file, col, indent, " ", "", "(");
3327  scol = col;
3328  col = write_expression(file, expr->data.ucase, col, scol, 1);
3329  col = token_print_indent(file, col, indent, "", "", ")");
3330  break;
3331 
3332  case expr_concat:
3333  e = expr;
3334  col = token_print_indent (file, col, indent, "", "",
3335  "concat");
3336  col = token_print_indent (file, col, indent, " ", "", "(");
3337  scol = col;
3338  firstp = 1;
3339  concat_again:
3340  col = write_expression (file, e -> data.concat [0],
3341  col, scol, firstp);
3342  firstp = 0;
3343  if (!e -> data.concat [1])
3344  goto no_concat_cdr;
3345  col = token_print_indent (file, col, scol, "", " ", ",");
3346  if (e -> data.concat [1] -> op == expr_concat) {
3347  e = e -> data.concat [1];
3348  goto concat_again;
3349  }
3350  col = write_expression (file, e -> data.concat [1],
3351  col, scol, 0);
3352  no_concat_cdr:
3353  col = token_print_indent (file, col, indent, "", "", ")");
3354  break;
3355 
3356  case expr_host_lookup:
3357  col = token_print_indent (file, col, indent, "", "",
3358  "gethostbyname");
3359  col = token_print_indent (file, col, indent, " ", "", "(");
3361  (file, col, indent, "", "",
3362  "\"", expr -> data.host_lookup -> hostname, "\"",
3363  (char *)0);
3364  col = token_print_indent (file, col, indent, "", "", ")");
3365  break;
3366 
3367  case expr_add:
3368  s = "+";
3369  goto binary;
3370 
3371  case expr_subtract:
3372  s = "-";
3373  goto binary;
3374 
3375  case expr_multiply:
3376  s = "*";
3377  goto binary;
3378 
3379  case expr_divide:
3380  s = "/";
3381  goto binary;
3382 
3383  case expr_remainder:
3384  s = "%";
3385  goto binary;
3386 
3387  case expr_binary_and:
3388  s = "&";
3389  goto binary;
3390 
3391  case expr_binary_or:
3392  s = "|";
3393  goto binary;
3394 
3395  case expr_binary_xor:
3396  s = "^";
3397  goto binary;
3398 
3399  case expr_and:
3400  s = "and";
3401  goto binary;
3402 
3403  case expr_or:
3404  s = "or";
3405  goto binary;
3406 
3407  case expr_not:
3408  col = token_print_indent (file, col, indent, "", " ", "not");
3409  col = write_expression (file,
3410  expr -> data.not, col, indent + 2, 1);
3411  break;
3412 
3413  case expr_option:
3414  s = "option";
3415 
3416  print_option_name:
3417  col = token_print_indent (file, col, indent, "", "", s);
3418 
3419  if (expr -> data.option -> universe != &dhcp_universe) {
3420  col = token_print_indent (file, col, indent,
3421  " ", "",
3422  (expr -> data.option ->
3423  universe -> name));
3424  col = token_print_indent (file, col, indent, "", "",
3425  ".");
3426  col = token_print_indent (file, col, indent, "", "",
3427  expr -> data.option -> name);
3428  } else {
3429  col = token_print_indent (file, col, indent, " ", "",
3430  expr -> data.option -> name);
3431  }
3432  break;
3433 
3434  case expr_hardware:
3435  col = token_print_indent (file, col, indent, "", "",
3436  "hardware");
3437  break;
3438 
3439  case expr_packet:
3440  col = token_print_indent (file, col, indent, "", "",
3441  "packet");
3442  col = token_print_indent (file, col, indent, " ", "", "(");
3443  scol = col;
3444  col = write_expression (file, expr -> data.packet.offset,
3445  col, indent, 1);
3446  col = token_print_indent (file, col, scol, "", " ", ",");
3447  col = write_expression (file, expr -> data.packet.len,
3448  col, scol, 0);
3449  col = token_print_indent (file, col, indent, "", "", ")");
3450  break;
3451 
3452  case expr_const_data:
3453  col = token_indent_data_string (file, col, indent, "", "",
3454  &expr -> data.const_data);
3455  break;
3456 
3457  case expr_extract_int8:
3458  width = 8;
3459  extract_int:
3460  col = token_print_indent (file, col, indent, "", "",
3461  "extract-int");
3462  col = token_print_indent (file, col, indent, " ", "", "(");
3463  scol = col;
3464  col = write_expression (file, expr -> data.extract_int,
3465  col, indent, 1);
3466  col = token_print_indent (file, col, scol, "", " ", ",");
3467  sprintf (obuf, "%d", width);
3468  col = token_print_indent (file, col, scol, " ", "", obuf);
3469  col = token_print_indent (file, col, indent, "", "", ")");
3470  break;
3471 
3472  case expr_extract_int16:
3473  width = 16;
3474  goto extract_int;
3475 
3476  case expr_extract_int32:
3477  width = 32;
3478  goto extract_int;
3479 
3480  case expr_encode_int8:
3481  width = 8;
3482  encode_int:
3483  col = token_print_indent (file, col, indent, "", "",
3484  "encode-int");
3485  col = token_print_indent (file, col, indent, " ", "", "(");
3486  scol = col;
3487  col = write_expression (file, expr -> data.extract_int,
3488  col, indent, 1);
3489  col = token_print_indent (file, col, scol, "", " ", ",");
3490  sprintf (obuf, "%d", width);
3491  col = token_print_indent (file, col, scol, " ", "", obuf);
3492  col = token_print_indent (file, col, indent, "", "",
3493  ")");
3494  break;
3495 
3496  case expr_encode_int16:
3497  width = 16;
3498  goto encode_int;
3499 
3500  case expr_encode_int32:
3501  width = 32;
3502  goto encode_int;
3503 
3504  case expr_const_int:
3505  sprintf (obuf, "%lu", expr -> data.const_int);
3506  col = token_print_indent (file, col, indent, "", "", obuf);
3507  break;
3508 
3509  case expr_exists:
3510  s = "exists";
3511  goto print_option_name;
3512 
3513  case expr_encapsulate:
3514  col = token_print_indent (file, col, indent, "", "",
3515  "encapsulate");
3516  col = token_indent_data_string (file, col, indent, " ", "",
3517  &expr -> data.encapsulate);
3518  break;
3519 
3520  case expr_known:
3521  col = token_print_indent (file, col, indent, "", "", "known");
3522  break;
3523 
3524  case expr_reverse:
3525  col = token_print_indent (file, col, indent, "", "",
3526  "reverse");
3527  col = token_print_indent (file, col, indent, " ", "", "(");
3528  scol = col;
3529  col = write_expression (file, expr -> data.reverse.width,
3530  col, scol, 1);
3531  col = token_print_indent (file, col, scol, "", " ", ",");
3532  col = write_expression (file, expr -> data.reverse.buffer,
3533  col, scol, 0);
3534  col = token_print_indent (file, col, indent, "", "",
3535  ")");
3536  break;
3537 
3538  case expr_leased_address:
3539  col = token_print_indent (file, col, indent, "", "",
3540  "leased-address");
3541  break;
3542 
3543  case expr_client_state:
3544  col = token_print_indent (file, col, indent, "", "",
3545  "client-state");
3546  break;
3547 
3548  case expr_binary_to_ascii:
3549  col = token_print_indent (file, col, indent, "", "",
3550  "binary-to-ascii");
3551  col = token_print_indent (file, col, indent, " ", "",
3552  "(");
3553  scol = col;
3554  col = write_expression (file, expr -> data.b2a.base,
3555  col, scol, 1);
3556  col = token_print_indent (file, col, scol, "", " ",
3557  ",");
3558  col = write_expression (file, expr -> data.b2a.width,
3559  col, scol, 0);
3560  col = token_print_indent (file, col, scol, "", " ",
3561  ",");
3562  col = write_expression (file, expr -> data.b2a.separator,
3563  col, scol, 0);
3564  col = token_print_indent (file, col, scol, "", " ",
3565  ",");
3566  col = write_expression (file, expr -> data.b2a.buffer,
3567  col, scol, 0);
3568  col = token_print_indent (file, col, indent, "", "",
3569  ")");
3570  break;
3571 
3572  case expr_config_option:
3573  s = "config-option";
3574  goto print_option_name;
3575 
3576  case expr_host_decl_name:
3577  col = token_print_indent (file, col, indent, "", "",
3578  "host-decl-name");
3579  break;
3580 
3581  case expr_pick_first_value:
3582  e = expr;
3583  col = token_print_indent (file, col, indent, "", "",
3584  "concat");
3585  col = token_print_indent (file, col, indent, " ", "",
3586  "(");
3587  scol = col;
3588  firstp = 1;
3589  pick_again:
3590  col = write_expression (file,
3591  e -> data.pick_first_value.car,
3592  col, scol, firstp);
3593  firstp = 0;
3594  /* We're being very lisp-like right now - instead of
3595  representing this expression as (first middle . last) we're
3596  representing it as (first middle last), which means that the
3597  tail cdr is always nil. Apologies to non-wisp-lizards - may
3598  this obscure way of describing the problem motivate you to
3599  learn more about the one true computing language. */
3600  if (!e -> data.pick_first_value.cdr)
3601  goto no_pick_cdr;
3602  col = token_print_indent (file, col, scol, "", " ",
3603  ",");
3604  if (e -> data.pick_first_value.cdr -> op ==
3606  e = e -> data.pick_first_value.cdr;
3607  goto pick_again;
3608  }
3609  col = write_expression (file,
3610  e -> data.pick_first_value.cdr,
3611  col, scol, 0);
3612  no_pick_cdr:
3613  col = token_print_indent (file, col, indent, "", "",
3614  ")");
3615  break;
3616 
3617  case expr_lease_time:
3618  col = token_print_indent (file, col, indent, "", "",
3619  "lease-time");
3620  break;
3621 
3622  case expr_static:
3623  col = token_print_indent (file, col, indent, "", "",
3624  "static");
3625  break;
3626 
3627  case expr_null:
3628  col = token_print_indent (file, col, indent, "", "", "null");
3629  break;
3630 
3632  col = token_print_indent (file, indent, indent, "", "",
3633  expr -> data.variable);
3634  break;
3635 
3636  case expr_variable_exists:
3637  col = token_print_indent (file, indent, indent, "", "",
3638  "defined");
3639  col = token_print_indent (file, col, indent, " ", "", "(");
3640  col = token_print_indent (file, col, indent, "", "",
3641  expr -> data.variable);
3642  col = token_print_indent (file, col, indent, "", "", ")");
3643  break;
3644 
3645  case expr_gethostname:
3646  col = token_print_indent(file, col, indent, "", "",
3647  "gethostname()");
3648  break;
3649 
3650  case expr_funcall:
3651  col = token_print_indent(file, indent, indent, "", "",
3652  expr->data.funcall.name);
3653  col = token_print_indent(file, col, indent, " ", "", "(");
3654 
3655  firstp = 1;
3656  e = expr->data.funcall.arglist;
3657  while (e != NULL) {
3658  if (!firstp)
3659  col = token_print_indent(file, col, indent,
3660  "", " ", ",");
3661 
3662  col = write_expression(file, e->data.arg.val, col,
3663  indent, firstp);
3664  firstp = 0;
3665  e = e->data.arg.next;
3666  }
3667 
3668  col = token_print_indent(file, col, indent, "", "", ")");
3669  break;
3670 
3671  case expr_v6relay:
3672  col = token_print_indent(file, col, indent, "", "",
3673  "v6relay");
3674  col = token_print_indent(file, col, indent, " ", "", "(");
3675  scol = col;
3676  col = write_expression(file, expr->data.v6relay.relay,
3677  col, scol, 1);
3678  col = token_print_indent (file, col, scol, "", " ", ",");
3679  col = write_expression(file, expr->data.v6relay.roption,
3680  col, scol, 0);
3681  col = token_print_indent(file, col, indent, "", "", ")");
3682  break;
3683 
3684  default:
3685  log_fatal ("invalid expression type in print_expression: %d",
3686  expr -> op);
3687  }
3688  return col;
3689 }
3690 
3691 struct binding *find_binding (struct binding_scope *scope, const char *name)
3692 {
3693  struct binding *bp;
3694  struct binding_scope *s;
3695 
3696  for (s = scope; s; s = s -> outer) {
3697  for (bp = s -> bindings; bp; bp = bp -> next) {
3698  if (!strcasecmp (name, bp -> name)) {
3699  return bp;
3700  }
3701  }
3702  }
3703  return (struct binding *)0;
3704 }
3705 
3706 int free_bindings (struct binding_scope *scope, const char *file, int line)
3707 {
3708  struct binding *bp, *next;
3709 
3710  for (bp = scope -> bindings; bp; bp = next) {
3711  next = bp -> next;
3712  if (bp -> name)
3713  dfree (bp -> name, file, line);
3714  if (bp -> value)
3715  binding_value_dereference (&bp -> value, file, line);
3716  dfree (bp, file, line);
3717  }
3718  scope -> bindings = (struct binding *)0;
3719  return 1;
3720 }
3721 
3723  struct binding_scope **ptr;
3724  const char *file;
3725  int line;
3726 {
3727  struct binding_scope *binding_scope;
3728 
3729  if (!ptr || !*ptr) {
3730  log_error ("%s(%d): null pointer", file, line);
3731 #if defined (POINTER_DEBUG)
3732  abort ();
3733 #else
3734  return 0;
3735 #endif
3736  }
3737 
3738  binding_scope = *ptr;
3739  *ptr = (struct binding_scope *)0;
3740  --binding_scope -> refcnt;
3741  rc_register (file, line, ptr,
3742  binding_scope, binding_scope -> refcnt, 1, RC_MISC);
3743  if (binding_scope -> refcnt > 0)
3744  return 1;
3745 
3746  if (binding_scope -> refcnt < 0) {
3747  log_error ("%s(%d): negative refcnt!", file, line);
3748 #if defined (DEBUG_RC_HISTORY)
3749  dump_rc_history (binding_scope);
3750 #endif
3751 #if defined (POINTER_DEBUG)
3752  abort ();
3753 #else
3754  return 0;
3755 #endif
3756  }
3757 
3758  free_bindings (binding_scope, file, line);
3759  if (binding_scope -> outer)
3760  binding_scope_dereference (&binding_scope -> outer, MDL);
3761  dfree (binding_scope, file, line);
3762  return 1;
3763 }
3764 
3766  struct fundef **ptr;
3767  const char *file;
3768  int line;
3769 {
3770  struct fundef *bp;
3771  struct string_list *sp, *next;
3772 
3773  if ((ptr == NULL) || (*ptr == NULL)) {
3774  log_error ("%s(%d): null pointer", file, line);
3775 #if defined (POINTER_DEBUG)
3776  abort ();
3777 #else
3778  return 0;
3779 #endif
3780  }
3781 
3782  bp = *ptr;
3783  bp -> refcnt--;
3784  rc_register (file, line, ptr, bp, bp -> refcnt, 1, RC_MISC);
3785  if (bp -> refcnt < 0) {
3786  log_error ("%s(%d): negative refcnt!", file, line);
3787 #if defined (DEBUG_RC_HISTORY)
3788  dump_rc_history (bp);
3789 #endif
3790 #if defined (POINTER_DEBUG)
3791  abort ();
3792 #else
3793  return 0;
3794 #endif
3795  }
3796  if (!bp -> refcnt) {
3797  for (sp = bp -> args; sp; sp = next) {
3798  next = sp -> next;
3799  dfree (sp, file, line);
3800  }
3801  if (bp -> statements)
3802  executable_statement_dereference (&bp -> statements,
3803  file, line);
3804  dfree (bp, file, line);
3805  }
3806  *ptr = (struct fundef *)0;
3807  return 1;
3808 }
3809 
3810 #if defined (NOTYET) /* Post 3.0 final. */
3811 int data_subexpression_length (int *rv,
3812  struct expression *expr)
3813 {
3814  int crhs, clhs, llhs, lrhs;
3815  switch (expr -> op) {
3816  case expr_substring:
3817  if (expr -> data.substring.len &&
3818  expr -> data.substring.len -> op == expr_const_int) {
3819  (*rv =
3820  (int)expr -> data.substring.len -> data.const_int);
3821  return 1;
3822  }
3823  return 0;
3824 
3825  case expr_packet:
3826  case expr_suffix:
3827  if (expr -> data.suffix.len &&
3828  expr -> data.suffix.len -> op == expr_const_int) {
3829  (*rv =
3830  (int)expr -> data.suffix.len -> data.const_int);
3831  return 1;
3832  }
3833  return 0;
3834 
3835  case expr_lcase:
3836  return data_subexpression_length(rv, expr->data.lcase);
3837 
3838  case expr_ucase:
3839  return data_subexpression_length(rv, expr->data.ucase);
3840 
3841  case expr_concat:
3842  clhs = data_subexpression_length (&llhs,
3843  expr -> data.concat [0]);
3844  crhs = data_subexpression_length (&lrhs,
3845  expr -> data.concat [1]);
3846  if (crhs == 0 || clhs == 0)
3847  return 0;
3848  *rv = llhs + lrhs;
3849  return 1;
3850  break;
3851 
3852  case expr_hardware:
3853  return 0;
3854 
3855  case expr_const_data:
3856  *rv = expr -> data.const_data.len;
3857  return 2;
3858 
3859  case expr_reverse:
3860  return data_subexpression_length (rv,
3861  expr -> data.reverse.buffer);
3862 
3863  case expr_leased_address:
3864  case expr_lease_time:
3865  *rv = 4;
3866  return 2;
3867 
3868  case expr_pick_first_value:
3869  clhs = data_subexpression_length (&llhs,
3870  expr -> data.concat [0]);
3871  crhs = data_subexpression_length (&lrhs,
3872  expr -> data.concat [1]);
3873  if (crhs == 0 || clhs == 0)
3874  return 0;
3875  if (llhs > lrhs)
3876  *rv = llhs;
3877  else
3878  *rv = lrhs;
3879  return 1;
3880 
3881  case expr_v6relay:
3882  clhs = data_subexpression_length (&llhs,
3883  expr -> data.v6relay.relay);
3884  crhs = data_subexpression_length (&lrhs,
3885  expr -> data.v6relay.roption);
3886  if (crhs == 0 || clhs == 0)
3887  return 0;
3888  *rv = llhs + lrhs;
3889  return 1;
3890  break;
3891 
3892  case expr_binary_to_ascii:
3893  case expr_config_option:
3894  case expr_host_decl_name:
3895  case expr_encapsulate:
3896  case expr_filename:
3897  case expr_sname:
3898  case expr_host_lookup:
3899  case expr_option:
3900  case expr_none:
3901  case expr_match:
3902  case expr_check:
3903  case expr_equal:
3904  case expr_regex_match:
3905  case expr_iregex_match:
3906  case expr_and:
3907  case expr_or:
3908  case expr_not:
3909  case expr_extract_int8:
3910  case expr_extract_int16:
3911  case expr_extract_int32:
3912  case expr_encode_int8:
3913  case expr_encode_int16:
3914  case expr_encode_int32:
3915  case expr_const_int:
3916  case expr_exists:
3917  case expr_known:
3918  case expr_static:
3919  case expr_not_equal:
3920  case expr_null:
3921  case expr_variable_exists:
3923  case expr_arg:
3924  case expr_funcall:
3925  case expr_function:
3926  case expr_add:
3927  case expr_subtract:
3928  case expr_multiply:
3929  case expr_divide:
3930  case expr_remainder:
3931  case expr_binary_and:
3932  case expr_binary_or:
3933  case expr_binary_xor:
3934  case expr_client_state:
3935  case expr_gethostname:
3936  return 0;
3937  }
3938  return 0;
3939 }
3940 
3941 int expr_valid_for_context (struct expression *expr,
3942  enum expression_context context)
3943 {
3944  /* We don't know at parse time what type of value a function may
3945  return, so we can't flag an error on it. */
3946  if (expr -> op == expr_funcall ||
3947  expr -> op == expr_variable_reference)
3948  return 1;
3949 
3950  switch (context) {
3951  case context_any:
3952  return 1;
3953 
3954  case context_boolean:
3955  if (is_boolean_expression (expr))
3956  return 1;
3957  return 0;
3958 
3959  case context_data:
3960  if (is_data_expression (expr))
3961  return 1;
3962  return 0;
3963 
3964  case context_numeric:
3965  if (is_numeric_expression (expr))
3966  return 1;
3967  return 0;
3968 
3970  if (is_numeric_expression (expr) ||
3971  is_data_expression (expr)) {
3972  return 1;
3973  }
3974  return 0;
3975 
3976  case context_function:
3977  if (expr -> op == expr_function)
3978  return 1;
3979  return 0;
3980  }
3981  return 0;
3982 }
3983 #endif /* NOTYET */
3984 
3985 struct binding *create_binding (struct binding_scope **scope, const char *name)
3986 {
3987  struct binding *binding;
3988 
3989  if (!*scope) {
3990  if (!binding_scope_allocate (scope, MDL))
3991  return (struct binding *)0;
3992  }
3993 
3994  binding = find_binding (*scope, name);
3995  if (!binding) {
3996  binding = dmalloc (sizeof *binding, MDL);
3997  if (!binding)
3998  return (struct binding *)0;
3999 
4000  memset (binding, 0, sizeof *binding);
4001  binding -> name = dmalloc (strlen (name) + 1, MDL);
4002  if (!binding -> name) {
4003  dfree (binding, MDL);
4004  return (struct binding *)0;
4005  }
4006  strcpy (binding -> name, name);
4007 
4008  binding -> next = (*scope) -> bindings;
4009  (*scope) -> bindings = binding;
4010  }
4011 
4012  return binding;
4013 }
4014 
4015 
4016 int bind_ds_value (struct binding_scope **scope,
4017  const char *name,
4018  struct data_string *value)
4019 {
4020  struct binding *binding;
4021 
4022  binding = create_binding (scope, name);
4023  if (!binding)
4024  return 0;
4025 
4026  if (binding -> value)
4027  binding_value_dereference (&binding -> value, MDL);
4028 
4029  if (!binding_value_allocate (&binding -> value, MDL))
4030  return 0;
4031 
4032  data_string_copy (&binding -> value -> value.data, value, MDL);
4033  binding -> value -> type = binding_data;
4034 
4035  return 1;
4036 }
4037 
4038 
4040  struct binding_scope *scope,
4041  const char *name)
4042 {
4043  struct binding *binding;
4044 
4045  binding = find_binding (scope, name);
4046  if (!binding ||
4047  !binding -> value ||
4048  binding -> value -> type != binding_data)
4049  return 0;
4050 
4051  if (binding -> value -> value.data.terminated) {
4052  data_string_copy (value, &binding -> value -> value.data, MDL);
4053  } else {
4054  if (buffer_allocate (&value->buffer,
4055  binding->value->value.data.len,
4056  MDL) == 0) {
4057  return 0;
4058  }
4059 
4060  memcpy (value -> buffer -> data,
4061  binding -> value -> value.data.data,
4062  binding -> value -> value.data.len);
4063  value -> data = value -> buffer -> data;
4064  value -> len = binding -> value -> value.data.len;
4065  }
4066 
4067  return 1;
4068 }
4069 
4070 int unset (struct binding_scope *scope, const char *name)
4071 {
4072  struct binding *binding;
4073 
4074  binding = find_binding (scope, name);
4075  if (binding) {
4076  if (binding -> value)
4078  (&binding -> value, MDL);
4079  return 1;
4080  }
4081  return 0;
4082 }
4083 
4084 /* vim: set tabstop=8: */
enum expr_op op
Definition: tree.h:199
#define rc_register(file, line, reference, addr, refcnt, d, f)
Definition: alloc.h:88
int executable_statement_allocate(struct executable_statement **ptr, const char *file, int line)
Definition: alloc.c:959
Definition: tree.h:31
const char int line
Definition: dhcpd.h:3557
struct binding_scope * global_scope
Definition: tree.c:39
Definition: tree.h:142
int binding_value_dereference(struct binding_value **v, const char *file, int line)
Definition: tree.c:653
Definition: dhcpd.h:507
unsigned len
Definition: tree.h:80
int executable_statement_dereference(struct executable_statement **ptr, const char *file, int line)
Definition: execute.c:615
Definition: tree.h:94
int free_bindings(struct binding_scope *scope, const char *file, int line)
Definition: tree.c:3706
struct expression * val
Definition: tree.h:269
const char * piaddr(const struct iaddr addr)
Definition: inet.c:581
u_int8_t hlen
Definition: dhcpd.h:440
int make_const_option_cache(struct option_cache **oc, struct buffer **buffer, u_int8_t *data, unsigned len, struct option *option, const char *file, int line)
Definition: tree.c:150
struct expression::expr_union::@25 arg
struct expression * equal[2]
Definition: tree.h:206
struct binding_scope * outer
Definition: tree.h:126
struct data_string encapsulate
Definition: tree.h:235
void * dmalloc(unsigned, const char *, int)
Definition: alloc.c:56
struct expression::expr_union::@21 pick_first_value
int expression_allocate(struct expression **cptr, const char *file, int line)
Definition: alloc.c:427
int data_string_sprintfa(struct data_string *ds, const char *fmt,...)
Definition: tree.c:57
int execute_statements(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct executable_statement *statements, struct on_star *on_star)
Definition: execute.c:35
int refcnt
Definition: tree.h:125
struct iaddr ip_addr(struct iaddr subnet, struct iaddr mask, u_int32_t host_address)
Definition: inet.c:65
int binding_value_reference(struct binding_value **ptr, struct binding_value *src, const char *file, int line)
Definition: alloc.c:521
#define MDL
Definition: omapip.h:568
unsigned char iabuf[16]
Definition: inet.h:33
#define print_hex_1(len, data, limit)
Definition: dhcpd.h:2424
int refcnt
Definition: tree.h:198
u_int8_t hlen
Definition: dhcp.h:51
struct executable_statement * statements
Definition: tree.h:97
enum expression_context expression_context(struct expression *expr)
Definition: tree.c:3143
unsigned long const_int
Definition: tree.h:231
struct expression * lcase
Definition: tree.h:220
struct data_string data
Definition: tree.h:110
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
struct binding * next
Definition: tree.h:119
struct expression * arglist
Definition: tree.h:274
struct expression::expr_union::@16 substring
int is_numeric_expression(struct expression *expr)
Definition: tree.c:3016
int option_reference(struct option **dest, struct option *src, const char *file, int line)
Definition: tables.c:934
int find_bound_string(struct data_string *value, struct binding_scope *scope, const char *name)
Definition: tree.c:4039
struct universe dhcp_universe
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1276
struct expression * concat[2]
Definition: tree.h:232
Definition: tree.h:141
int evaluate_numeric_expression(unsigned long *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct expression *expr)
Definition: tree.c:2173
enum binding_value::@15 type
int log_error(const char *,...) __attribute__((__format__(__printf__
int is_compound_expression(struct expression *expr)
Definition: tree.c:3035
struct expression * offset
Definition: tree.h:203
int binding_scope_dereference(struct binding_scope **ptr, const char *file, int line)
Definition: tree.c:3722
enum expression_context op_context(enum expr_op op)
Definition: tree.c:3154
Definition: tree.h:177
int evaluate_expression(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct expression *expr, const char *file, int line)
Definition: tree.c:501
struct fundef * func
Definition: tree.h:276
unsigned len
Definition: inet.h:32
struct _pair * pair
int option_space_encapsulate(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct data_string *name)
Definition: options.c:2961
struct expression * not
Definition: tree.h:209
int terminated
Definition: tree.h:81
int make_substring(struct expression **new, struct expression *expr, struct expression *offset, struct expression *length)
Definition: tree.c:314
struct option_state * options
Definition: dhcpd.h:407
Definition: tree.h:301
struct expression::expr_union::@17 suffix
int is_boolean_expression(struct expression *expr)
Definition: tree.c:2969
void expression_dereference(struct expression **eptr, const char *file, int line)
Definition: tree.c:2751
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int evaluate_boolean_expression_result(int *ignorep, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct expression *expr)
Definition: tree.c:2718
int binding_value_allocate(struct binding_value **cptr, const char *file, int line)
Definition: alloc.c:501
int buffer_reference(struct buffer **ptr, struct buffer *bp, const char *file, int line)
Definition: alloc.c:699
int option_cache_allocate(struct option_cache **cptr, const char *file, int line)
Definition: alloc.c:631
struct fundef * fundef
Definition: tree.h:113
struct dhcp_packet * raw
Definition: dhcpd.h:370
union expression::expr_union data
struct hardware hardware_addr
Definition: dhcpd.h:529
int unset(struct binding_scope *scope, const char *name)
Definition: tree.c:4070
struct expression * encode_int
Definition: tree.h:230
int make_host_lookup(struct expression **expr, const char *name)
Definition: tree.c:189
u_int8_t htype
Definition: dhcp.h:50
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition: tree.c:2643
Definition: tree.h:345
unsigned char chaddr[16]
Definition: dhcp.h:60
char * name
Definition: tree.h:120
#define MAX_V6RELAY_HOPS
Definition: dhcp6.h:197
struct expression::expr_union::@20 reverse
struct expression * width
Definition: tree.h:238
struct expression * roption
Definition: tree.h:279
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
Definition: alloc.c:680
int binding_scope_allocate(struct binding_scope **ptr, const char *file, int line)
Definition: alloc.c:1195
void putULong(unsigned char *, u_int32_t)
Definition: convert.c:70
int binary_to_ascii(unsigned char *, const unsigned char *, unsigned int, unsigned int)
Definition: convert.c:150
Definition: dhcpd.h:369
struct expression * next
Definition: tree.h:270
struct expression * expr
Definition: tree.h:202
#define cur_time
Definition: dhcpd.h:1946
int make_concat(struct expression **expr, struct expression *left, struct expression *right)
Definition: tree.c:269
u_int32_t getUShort(const unsigned char *)
void dfree(void *, const char *, int)
Definition: alloc.c:131
struct expression * buffer
Definition: tree.h:240
int make_let(struct executable_statement **result, const char *name)
Definition: tree.c:378
struct hardware hw_address
Definition: dhcpd.h:1250
struct expression * base
Definition: tree.h:237
#define print_hex_3(len, data, limit)
Definition: dhcpd.h:2426
int int log_info(const char *,...) __attribute__((__format__(__printf__
struct expression * relay
Definition: tree.h:278
int fundef_dereference(struct fundef **ptr, const char *file, int line)
Definition: tree.c:3765
struct expression::expr_union::@19 b2a
int evaluate_data_expression(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct expression *expr, const char *file, int line)
Definition: tree.c:1114
int option_cache(struct option_cache **oc, struct data_string *dp, struct expression *expr, struct option *option, const char *file, int line)
Definition: tree.c:364
struct expression * extract_int
Definition: tree.h:229
Definition: tree.h:287
struct option * option
Definition: tree.h:222
u_int32_t getULong(const unsigned char *)
Definition: tree.h:143
int get_option(struct data_string *result, struct universe *universe, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct option_state *options, struct binding_scope **scope, unsigned code, const char *file, int line)
Definition: options.c:2147
int check_collection(struct packet *packet, struct lease *lease, struct collection *collection)
Definition: dhclient.c:1257
union binding_value::value value
struct data_string const_data
Definition: tree.h:228
struct binding * bindings
Definition: tree.h:127
expr_op
Definition: tree.h:132
void indent(int)
int binding_scope_reference(struct binding_scope **ptr, struct binding_scope *bp, const char *file, int line)
Definition: alloc.c:1228
struct expression * len
Definition: tree.h:204
int evaluate_boolean_option_cache(int *ignorep, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition: tree.c:2670
#define print_hex_2(len, data, limit)
Definition: dhcpd.h:2425
int make_const_data(struct expression **expr, const unsigned char *data, unsigned len, int terminated, int allocate, const char *file, int line)
Definition: tree.c:220
int enter_dns_host(struct dns_host_entry **dh, const char *name)
Definition: tree.c:205
struct data_string data
Definition: tree.h:290
struct string_list * next
Definition: dhcpd.h:312
const char int
Definition: omapip.h:443
int is_data_expression(struct expression *expr)
Definition: tree.c:2986
struct binding_value * value
Definition: tree.h:121
int make_limit(struct expression **new, struct expression *expr, int limit)
Definition: tree.c:332
struct binding * create_binding(struct binding_scope **scope, const char *name)
Definition: tree.c:3985
struct expression * ucase
Definition: tree.h:221
void free_expression(struct expression *expr, const char *file, int line)
Definition: alloc.c:475
unsigned char data[1]
Definition: tree.h:63
Definition: tree.h:61
struct collection * check
Definition: tree.h:215
int make_encapsulation(struct expression **expr, struct data_string *name)
Definition: tree.c:299
int expression_reference(struct expression **ptr, struct expression *src, const char *file, int line)
Definition: alloc.c:447
int refcnt
Definition: tree.h:101
#define STATIC_LEASE
Definition: dhcpd.h:532
int dns_host_entry_allocate(struct dns_host_entry **ptr, const char *hostname, const char *file, int line)
Definition: alloc.c:769
int converted_length(const unsigned char *, unsigned int, unsigned int)
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
Definition: dhcpd.h:441
expression_context
Definition: tree.h:84
int evaluate_boolean_expression(int *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct expression *expr)
Definition: tree.c:695
int op_precedence(enum expr_op op1, enum expr_op op2)
Definition: tree.c:3137
struct data_string data
Definition: dhcpd.h:354
Definition: tree.h:118
struct expression * cdr
Definition: tree.h:248
int dns_host_entry_dereference(struct dns_host_entry **ptr, const char *file, int line)
Definition: alloc.c:814
int make_const_int(struct expression **expr, unsigned long val)
Definition: tree.c:255
struct expression::expr_union::@27 v6relay
struct dns_host_entry * host_lookup
Definition: tree.h:233
pair cons(caddr_t car, pair cdr)
Definition: tree.c:138
int write_expression(FILE *file, struct expression *expr, int col, int indent, int firstp)
Definition: tree.c:3234
struct binding * find_binding(struct binding_scope *scope, const char *name)
Definition: tree.c:3691
const char * file
Definition: dhcpd.h:3557
void putUShort(unsigned char *, u_int32_t)
Definition: convert.c:86
struct expression * car
Definition: tree.h:247
unsigned long intval
Definition: tree.h:111
const unsigned char * data
Definition: tree.h:79
struct interface_info * interface
Definition: dhcpd.h:1165
int bind_ds_value(struct binding_scope **scope, const char *name, struct data_string *value)
Definition: tree.c:4016
TIME ends
Definition: dhcpd.h:513
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
Definition: alloc.c:1260
void free_binding_value(struct binding_value *bv, const char *file, int line)
Definition: alloc.c:549
struct expression::expr_union::@26 funcall
int data_subexpression_length(int *, struct expression *)
#define DS_SPRINTF_SIZE
Definition: tree.c:43
#define RC_MISC
Definition: alloc.h:56
int expr_valid_for_context(struct expression *, enum expression_context)
struct expression::expr_union::@18 packet
struct buffer * buffer
Definition: tree.h:78
struct expression * separator
Definition: tree.h:239
int buffer_dereference(struct buffer **ptr, const char *file, int line)
Definition: alloc.c:727
struct packet * dhcpv6_container_packet
Definition: dhcpd.h:386
Definition: tree.h:180