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