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