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