Sync with HEAD.
[dragonfly.git] / contrib / dhcp-3.0 / common / tree.c
blobf44bffe5aa741ca08b3cc233cf4768fcc754250e
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.101.2.11 2004/11/24 17:39:16 dhankins 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;
252 struct expression *rv;
254 /* Allocate a node to enforce a limit on evaluation. */
255 if (!expression_allocate (new, MDL))
256 log_error ("no memory for limit expression");
257 (*new) -> op = expr_substring;
258 expression_reference (&(*new) -> data.substring.expr, expr, MDL);
260 /* Offset is a constant 0. */
261 if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) {
262 log_error ("no memory for limit offset expression");
263 expression_dereference (new, MDL);
264 return 0;
266 (*new) -> data.substring.offset -> op = expr_const_int;
267 (*new) -> data.substring.offset -> data.const_int = 0;
269 /* Length is a constant: the specified limit. */
270 if (!expression_allocate (&(*new) -> data.substring.len, MDL)) {
271 log_error ("no memory for limit length expression");
272 expression_dereference (new, MDL);
273 return 0;
275 (*new) -> data.substring.len -> op = expr_const_int;
276 (*new) -> data.substring.len -> data.const_int = limit;
278 return 1;
281 int option_cache (struct option_cache **oc, struct data_string *dp,
282 struct expression *expr, struct option *option,
283 const char *file, int line)
285 if (!option_cache_allocate (oc, file, line))
286 return 0;
287 if (dp)
288 data_string_copy (&(*oc) -> data, dp, file, line);
289 if (expr)
290 expression_reference (&(*oc) -> expression, expr, file, line);
291 (*oc) -> option = option;
292 return 1;
295 int make_let (result, name)
296 struct executable_statement **result;
297 const char *name;
299 if (!(executable_statement_allocate (result, MDL)))
300 return 0;
302 (*result) -> op = let_statement;
303 (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL);
304 if (!(*result) -> data.let.name) {
305 executable_statement_dereference (result, MDL);
306 return 0;
308 strcpy ((*result) -> data.let.name, name);
309 return 1;
312 static int do_host_lookup (result, dns)
313 struct data_string *result;
314 struct dns_host_entry *dns;
316 struct hostent *h;
317 unsigned i, count;
318 unsigned new_len;
320 #ifdef DEBUG_EVAL
321 log_debug ("time: now = %d dns = %d diff = %d",
322 cur_time, dns -> timeout, cur_time - dns -> timeout);
323 #endif
325 /* If the record hasn't timed out, just copy the data and return. */
326 if (cur_time <= dns -> timeout) {
327 #ifdef DEBUG_EVAL
328 log_debug ("easy copy: %d %s",
329 dns -> data.len,
330 (dns -> data.len > 4
331 ? inet_ntoa (*(struct in_addr *)(dns -> data.data))
332 : 0));
333 #endif
334 data_string_copy (result, &dns -> data, MDL);
335 return 1;
337 #ifdef DEBUG_EVAL
338 log_debug ("Looking up %s", dns -> hostname);
339 #endif
341 /* Otherwise, look it up... */
342 h = gethostbyname (dns -> hostname);
343 if (!h) {
344 #ifndef NO_H_ERRNO
345 switch (h_errno) {
346 case HOST_NOT_FOUND:
347 #endif
348 log_error ("%s: host unknown.", dns -> hostname);
349 #ifndef NO_H_ERRNO
350 break;
351 case TRY_AGAIN:
352 log_error ("%s: temporary name server failure",
353 dns -> hostname);
354 break;
355 case NO_RECOVERY:
356 log_error ("%s: name server failed", dns -> hostname);
357 break;
358 case NO_DATA:
359 log_error ("%s: no A record associated with address",
360 dns -> hostname);
362 #endif /* !NO_H_ERRNO */
364 /* Okay to try again after a minute. */
365 dns -> timeout = cur_time + 60;
366 data_string_forget (&dns -> data, MDL);
367 return 0;
370 #ifdef DEBUG_EVAL
371 log_debug ("Lookup succeeded; first address is %s",
372 inet_ntoa (h -> h_addr_list [0]));
373 #endif
375 /* Count the number of addresses we got... */
376 for (count = 0; h -> h_addr_list [count]; count++)
379 /* Dereference the old data, if any. */
380 data_string_forget (&dns -> data, MDL);
382 /* Do we need to allocate more memory? */
383 new_len = count * h -> h_length;
384 if (!buffer_allocate (&dns -> data.buffer, new_len, MDL))
386 log_error ("No memory for %s.", dns -> hostname);
387 return 0;
390 dns -> data.data = &dns -> data.buffer -> data [0];
391 dns -> data.len = new_len;
392 dns -> data.terminated = 0;
394 /* Addresses are conveniently stored one to the buffer, so we
395 have to copy them out one at a time... :'( */
396 for (i = 0; i < count; i++) {
397 memcpy (&dns -> data.buffer -> data [h -> h_length * i],
398 h -> h_addr_list [i], (unsigned)(h -> h_length));
400 #ifdef DEBUG_EVAL
401 log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
402 *(int *)(dns -> buffer), h -> h_addr_list [0]);
403 #endif
405 /* XXX Set the timeout for an hour from now.
406 XXX This should really use the time on the DNS reply. */
407 dns -> timeout = cur_time + 3600;
409 #ifdef DEBUG_EVAL
410 log_debug ("hard copy: %d %s", dns -> data.len,
411 (dns -> data.len > 4
412 ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));
413 #endif
414 data_string_copy (result, &dns -> data, MDL);
415 return 1;
418 int evaluate_expression (result, packet, lease, client_state,
419 in_options, cfg_options, scope, expr, file, line)
420 struct binding_value **result;
421 struct packet *packet;
422 struct lease *lease;
423 struct client_state *client_state;
424 struct option_state *in_options;
425 struct option_state *cfg_options;
426 struct binding_scope **scope;
427 struct expression *expr;
428 const char *file;
429 int line;
431 struct binding_value *bv;
432 int status;
433 struct binding *binding;
435 bv = (struct binding_value *)0;
437 if (expr -> op == expr_variable_reference) {
438 if (!scope || !*scope)
439 return 0;
441 binding = find_binding (*scope, expr -> data.variable);
443 if (binding && binding -> value) {
444 if (result)
445 binding_value_reference (result,
446 binding -> value,
447 file, line);
448 return 1;
449 } else
450 return 0;
451 } else if (expr -> op == expr_funcall) {
452 struct string_list *s;
453 struct expression *arg;
454 struct binding_scope *ns;
455 struct binding *nb;
457 if (!scope || !*scope) {
458 log_error ("%s: no such function.",
459 expr -> data.funcall.name);
460 return 0;
463 binding = find_binding (*scope, expr -> data.funcall.name);
465 if (!binding || !binding -> value) {
466 log_error ("%s: no such function.",
467 expr -> data.funcall.name);
468 return 0;
470 if (binding -> value -> type != binding_function) {
471 log_error ("%s: not a function.",
472 expr -> data.funcall.name);
473 return 0;
476 /* Create a new binding scope in which to define
477 the arguments to the function. */
478 ns = (struct binding_scope *)0;
479 if (!binding_scope_allocate (&ns, MDL)) {
480 log_error ("%s: can't allocate argument scope.",
481 expr -> data.funcall.name);
482 return 0;
485 arg = expr -> data.funcall.arglist;
486 s = binding -> value -> value.fundef -> args;
487 while (arg && s) {
488 nb = dmalloc (sizeof *nb, MDL);
489 if (!nb) {
490 blb:
491 binding_scope_dereference (&ns, MDL);
492 return 0;
493 } else {
494 memset (nb, 0, sizeof *nb);
495 nb -> name = dmalloc (strlen (s -> string) + 1,
496 MDL);
497 if (nb -> name)
498 strcpy (nb -> name, s -> string);
499 else {
500 dfree (nb, MDL);
501 nb = (struct binding *)0;
502 goto blb;
505 evaluate_expression (&nb -> value, packet, lease,
506 client_state,
507 in_options, cfg_options, scope,
508 arg -> data.arg.val, file, line);
509 nb -> next = ns -> bindings;
510 ns -> bindings = nb;
511 arg = arg -> data.arg.next;
512 s = s -> next;
514 if (arg) {
515 log_error ("%s: too many arguments.",
516 expr -> data.funcall.name);
517 binding_scope_dereference (&ns, MDL);
518 return 0;
520 if (s) {
521 log_error ("%s: too few arguments.",
522 expr -> data.funcall.name);
523 binding_scope_dereference (&ns, MDL);
524 return 0;
527 if (scope && *scope)
528 binding_scope_reference (&ns -> outer, *scope, MDL);
530 status = (execute_statements
531 (&bv, packet,
532 lease, client_state, in_options, cfg_options, &ns,
533 binding -> value -> value.fundef -> statements));
534 binding_scope_dereference (&ns, MDL);
536 if (!bv)
537 return 1;
538 } else if (is_boolean_expression (expr)) {
539 if (!binding_value_allocate (&bv, MDL))
540 return 0;
541 bv -> type = binding_boolean;
542 status = (evaluate_boolean_expression
543 (&bv -> value.boolean, packet, lease, client_state,
544 in_options, cfg_options, scope, expr));
545 } else if (is_numeric_expression (expr)) {
546 if (!binding_value_allocate (&bv, MDL))
547 return 0;
548 bv -> type = binding_numeric;
549 status = (evaluate_numeric_expression
550 (&bv -> value.intval, packet, lease, client_state,
551 in_options, cfg_options, scope, expr));
552 } else if (is_data_expression (expr)) {
553 if (!binding_value_allocate (&bv, MDL))
554 return 0;
555 bv -> type = binding_data;
556 status = (evaluate_data_expression
557 (&bv -> value.data, packet, lease, client_state,
558 in_options, cfg_options, scope, expr, MDL));
559 } else if (is_dns_expression (expr)) {
560 #if defined (NSUPDATE)
561 if (!binding_value_allocate (&bv, MDL))
562 return 0;
563 bv -> type = binding_dns;
564 status = (evaluate_dns_expression
565 (&bv -> value.dns, packet, lease, client_state,
566 in_options, cfg_options, scope, expr));
567 #endif
568 } else {
569 log_error ("%s: invalid expression type: %d",
570 "evaluate_expression", expr -> op);
571 return 0;
573 if (result && status)
574 binding_value_reference (result, bv, file, line);
575 binding_value_dereference (&bv, MDL);
577 return status;
580 int binding_value_dereference (struct binding_value **v,
581 const char *file, int line)
583 struct binding_value *bv = *v;
585 *v = (struct binding_value *)0;
587 /* Decrement the reference count. If it's nonzero, we're
588 done. */
589 --(bv -> refcnt);
590 rc_register (file, line, v, bv, bv -> refcnt, 1, RC_MISC);
591 if (bv -> refcnt > 0)
592 return 1;
593 if (bv -> refcnt < 0) {
594 log_error ("%s(%d): negative refcnt!", file, line);
595 #if defined (DEBUG_RC_HISTORY)
596 dump_rc_history (bv);
597 #endif
598 #if defined (POINTER_DEBUG)
599 abort ();
600 #else
601 return 0;
602 #endif
605 switch (bv -> type) {
606 case binding_boolean:
607 case binding_numeric:
608 break;
609 case binding_data:
610 if (bv -> value.data.buffer)
611 data_string_forget (&bv -> value.data, file, line);
612 break;
613 case binding_dns:
614 #if defined (NSUPDATE)
615 if (bv -> value.dns) {
616 if (bv -> value.dns -> r_data) {
617 dfree (bv -> value.dns -> r_data_ephem, MDL);
618 bv -> value.dns -> r_data = (unsigned char *)0;
619 bv -> value.dns -> r_data_ephem =
620 (unsigned char *)0;
622 minires_freeupdrec (bv -> value.dns);
624 break;
625 #endif
626 default:
627 log_error ("%s(%d): invalid binding type: %d",
628 file, line, bv -> type);
629 return 0;
631 dfree (bv, file, line);
632 return 1;
635 #if defined (NSUPDATE)
636 int evaluate_dns_expression (result, packet, lease, client_state, in_options,
637 cfg_options, scope, expr)
638 ns_updrec **result;
639 struct packet *packet;
640 struct lease *lease;
641 struct client_state *client_state;
642 struct option_state *in_options;
643 struct option_state *cfg_options;
644 struct binding_scope **scope;
645 struct expression *expr;
647 ns_updrec *foo;
648 unsigned long ttl = 0;
649 char *tname;
650 struct data_string name, data;
651 int r0, r1, r2, r3;
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, right;
907 struct data_string rrtype, rrname, rrdata;
908 unsigned long ttl;
909 int srrtype, srrname, srrdata, sttl;
910 int bleft, bright;
911 int sleft, sright;
912 struct binding *binding;
913 struct binding_value *bv, *obv;
915 switch (expr -> op) {
916 case expr_check:
917 *result = check_collection (packet, lease,
918 expr -> data.check);
919 #if defined (DEBUG_EXPRESSIONS)
920 log_debug ("bool: check (%s) returns %s",
921 expr -> data.check -> name,
922 *result ? "true" : "false");
923 #endif
924 return 1;
926 case expr_equal:
927 case expr_not_equal:
928 bv = obv = (struct binding_value *)0;
929 sleft = evaluate_expression (&bv, packet, lease, client_state,
930 in_options, cfg_options, scope,
931 expr -> data.equal [0], MDL);
932 sright = evaluate_expression (&obv, packet, lease,
933 client_state, in_options,
934 cfg_options, scope,
935 expr -> data.equal [1], MDL);
936 if (sleft && sright) {
937 if (bv -> type != obv -> type)
938 *result = expr -> op == expr_not_equal;
939 else {
940 switch (obv -> type) {
941 case binding_boolean:
942 if (bv -> value.boolean == obv -> value.boolean)
943 *result = expr -> op == expr_equal;
944 else
945 *result = expr -> op == expr_not_equal;
946 break;
948 case binding_data:
949 if ((bv -> value.data.len ==
950 obv -> value.data.len) &&
951 !memcmp (bv -> value.data.data,
952 obv -> value.data.data,
953 obv -> value.data.len))
954 *result = expr -> op == expr_equal;
955 else
956 *result = expr -> op == expr_not_equal;
957 break;
959 case binding_numeric:
960 if (bv -> value.intval == obv -> value.intval)
961 *result = expr -> op == expr_equal;
962 else
963 *result = expr -> op == expr_not_equal;
964 break;
966 case binding_dns:
967 #if defined (NSUPDATE)
968 /* XXX This should be a comparison for equal
969 XXX values, not for identity. */
970 if (bv -> value.dns == obv -> value.dns)
971 *result = expr -> op == expr_equal;
972 else
973 *result = expr -> op == expr_not_equal;
974 #else
975 *result = expr -> op == expr_not_equal;
976 #endif
977 break;
979 case binding_function:
980 if (bv -> value.fundef == obv -> value.fundef)
981 *result = expr -> op == expr_equal;
982 else
983 *result = expr -> op == expr_not_equal;
984 break;
985 default:
986 *result = expr -> op == expr_not_equal;
987 break;
990 } else if (!sleft && !sright)
991 *result = expr -> op == expr_equal;
992 else
993 *result = expr -> op == expr_not_equal;
995 #if defined (DEBUG_EXPRESSIONS)
996 log_debug ("bool: %sequal = %s",
997 expr -> op == expr_not_equal ? "not" : "",
998 (*result ? "true" : "false"));
999 #endif
1000 if (sleft)
1001 binding_value_dereference (&bv, MDL);
1002 if (sright)
1003 binding_value_dereference (&obv, MDL);
1004 return 1;
1006 case expr_and:
1007 sleft = evaluate_boolean_expression (&bleft, packet, lease,
1008 client_state,
1009 in_options, cfg_options,
1010 scope,
1011 expr -> data.and [0]);
1012 if (sleft && bleft)
1013 sright = evaluate_boolean_expression
1014 (&bright, packet, lease, client_state,
1015 in_options, cfg_options,
1016 scope, expr -> data.and [1]);
1017 else
1018 sright = bright = 0;
1020 #if defined (DEBUG_EXPRESSIONS)
1021 log_debug ("bool: and (%s, %s) = %s",
1022 sleft ? (bleft ? "true" : "false") : "NULL",
1023 sright ? (bright ? "true" : "false") : "NULL",
1024 ((sleft && sright)
1025 ? (bleft && bright ? "true" : "false") : "NULL"));
1026 #endif
1027 if (sleft && sright) {
1028 *result = bleft && bright;
1029 return 1;
1031 return 0;
1033 case expr_or:
1034 bleft = bright = 0;
1035 sleft = evaluate_boolean_expression (&bleft, packet, lease,
1036 client_state,
1037 in_options, cfg_options,
1038 scope,
1039 expr -> data.or [0]);
1040 if (!sleft || !bleft)
1041 sright = evaluate_boolean_expression
1042 (&bright, packet, lease, client_state,
1043 in_options, cfg_options,
1044 scope, expr -> data.or [1]);
1045 else
1046 sright = 0;
1047 #if defined (DEBUG_EXPRESSIONS)
1048 log_debug ("bool: or (%s, %s) = %s",
1049 sleft ? (bleft ? "true" : "false") : "NULL",
1050 sright ? (bright ? "true" : "false") : "NULL",
1051 ((sleft || sright)
1052 ? (bleft || bright ? "true" : "false") : "NULL"));
1053 #endif
1054 if (sleft || sright) {
1055 *result = bleft || bright;
1056 return 1;
1058 return 0;
1060 case expr_not:
1061 sleft = evaluate_boolean_expression (&bleft, packet, lease,
1062 client_state,
1063 in_options, cfg_options,
1064 scope,
1065 expr -> data.not);
1066 #if defined (DEBUG_EXPRESSIONS)
1067 log_debug ("bool: not (%s) = %s",
1068 sleft ? (bleft ? "true" : "false") : "NULL",
1069 ((sleft && sright)
1070 ? (!bleft ? "true" : "false") : "NULL"));
1072 #endif
1073 if (sleft) {
1074 *result = !bleft;
1075 return 1;
1077 return 0;
1079 case expr_exists:
1080 memset (&left, 0, sizeof left);
1081 if (!in_options ||
1082 !get_option (&left, expr -> data.exists -> universe,
1083 packet, lease, client_state,
1084 in_options, cfg_options, in_options,
1085 scope, expr -> data.exists -> code, MDL))
1086 *result = 0;
1087 else {
1088 *result = 1;
1089 data_string_forget (&left, MDL);
1091 #if defined (DEBUG_EXPRESSIONS)
1092 log_debug ("bool: exists %s.%s = %s",
1093 expr -> data.option -> universe -> name,
1094 expr -> data.option -> name,
1095 *result ? "true" : "false");
1096 #endif
1097 return 1;
1099 case expr_known:
1100 if (!packet) {
1101 #if defined (DEBUG_EXPRESSIONS)
1102 log_debug ("bool: known = NULL");
1103 #endif
1104 return 0;
1106 #if defined (DEBUG_EXPRESSIONS)
1107 log_debug ("bool: known = %s",
1108 packet -> known ? "true" : "false");
1109 #endif
1110 *result = packet -> known;
1111 return 1;
1113 case expr_static:
1114 if (!lease || !(lease -> flags & STATIC_LEASE)) {
1115 #if defined (DEBUG_EXPRESSIONS)
1116 log_debug ("bool: static = false (%s %s %s %d)",
1117 lease ? "y" : "n",
1118 (lease && (lease -> flags & STATIC_LEASE)
1119 ? "y" : "n"),
1120 piaddr (lease -> ip_addr),
1121 lease ? lease -> flags : 0);
1122 #endif
1123 *result = 0;
1124 return 1;
1126 #if defined (DEBUG_EXPRESSIONS)
1127 log_debug ("bool: static = true");
1128 #endif
1129 *result = 1;
1130 return 1;
1132 case expr_variable_exists:
1133 if (scope && *scope) {
1134 binding = find_binding (*scope, expr -> data.variable);
1136 if (binding) {
1137 if (binding -> value)
1138 *result = 1;
1139 else
1140 *result = 0;
1141 } else
1142 *result = 0;
1143 } else
1144 *result = 0;
1145 #if defined (DEBUG_EXPRESSIONS)
1146 log_debug ("boolean: %s? = %s", expr -> data.variable,
1147 *result ? "true" : "false");
1148 #endif
1149 return 1;
1151 case expr_variable_reference:
1152 if (scope && *scope) {
1153 binding = find_binding (*scope, expr -> data.variable);
1155 if (binding && binding -> value) {
1156 if (binding -> value -> type ==
1157 binding_boolean) {
1158 *result = binding -> value -> value.boolean;
1159 sleft = 1;
1160 } else {
1161 log_error ("binding type %d in %s.",
1162 binding -> value -> type,
1163 "evaluate_boolean_expression");
1164 sleft = 0;
1166 } else
1167 sleft = 0;
1168 } else
1169 sleft = 0;
1170 #if defined (DEBUG_EXPRESSIONS)
1171 log_debug ("boolean: %s = %s", expr -> data.variable,
1172 sleft ? (*result ? "true" : "false") : "NULL");
1173 #endif
1174 return sleft;
1176 case expr_funcall:
1177 bv = (struct binding_value *)0;
1178 sleft = evaluate_expression (&bv, packet, lease, client_state,
1179 in_options, cfg_options,
1180 scope, expr, MDL);
1181 if (sleft) {
1182 if (bv -> type != binding_boolean)
1183 log_error ("%s() returned type %d in %s.",
1184 expr -> data.funcall.name,
1185 bv -> type,
1186 "evaluate_boolean_expression");
1187 else
1188 *result = bv -> value.boolean;
1189 binding_value_dereference (&bv, MDL);
1191 #if defined (DEBUG_EXPRESSIONS)
1192 log_debug ("boolean: %s() = %s", expr -> data.funcall.name,
1193 sleft ? (*result ? "true" : "false") : "NULL");
1194 #endif
1195 break;
1197 case expr_none:
1198 case expr_match:
1199 case expr_substring:
1200 case expr_suffix:
1201 case expr_option:
1202 case expr_hardware:
1203 case expr_const_data:
1204 case expr_packet:
1205 case expr_concat:
1206 case expr_encapsulate:
1207 case expr_host_lookup:
1208 case expr_encode_int8:
1209 case expr_encode_int16:
1210 case expr_encode_int32:
1211 case expr_binary_to_ascii:
1212 case expr_reverse:
1213 case expr_pick_first_value:
1214 case expr_host_decl_name:
1215 case expr_config_option:
1216 case expr_leased_address:
1217 case expr_null:
1218 case expr_filename:
1219 case expr_sname:
1220 log_error ("Data opcode in evaluate_boolean_expression: %d",
1221 expr -> op);
1222 return 0;
1224 case expr_extract_int8:
1225 case expr_extract_int16:
1226 case expr_extract_int32:
1227 case expr_const_int:
1228 case expr_lease_time:
1229 case expr_dns_transaction:
1230 case expr_add:
1231 case expr_subtract:
1232 case expr_multiply:
1233 case expr_divide:
1234 case expr_remainder:
1235 case expr_binary_and:
1236 case expr_binary_or:
1237 case expr_binary_xor:
1238 case expr_client_state:
1239 log_error ("Numeric opcode in evaluate_boolean_expression: %d",
1240 expr -> op);
1241 return 0;
1243 case expr_ns_add:
1244 case expr_ns_delete:
1245 case expr_ns_exists:
1246 case expr_ns_not_exists:
1247 log_error ("dns opcode in evaluate_boolean_expression: %d",
1248 expr -> op);
1249 return 0;
1251 case expr_function:
1252 log_error ("function definition in evaluate_boolean_expr");
1253 return 0;
1255 case expr_arg:
1256 break;
1259 log_error ("Bogus opcode in evaluate_boolean_expression: %d",
1260 expr -> op);
1261 return 0;
1264 int evaluate_data_expression (result, packet, lease, client_state,
1265 in_options, cfg_options, scope, expr, file, line)
1266 struct data_string *result;
1267 struct packet *packet;
1268 struct lease *lease;
1269 struct client_state *client_state;
1270 struct option_state *in_options;
1271 struct option_state *cfg_options;
1272 struct binding_scope **scope;
1273 struct expression *expr;
1274 const char *file;
1275 int line;
1277 struct data_string data, other;
1278 unsigned long offset, len, i;
1279 int s0, s1, s2, s3;
1280 int status;
1281 struct binding *binding;
1282 char *s;
1283 struct binding_value *bv;
1285 switch (expr -> op) {
1286 /* Extract N bytes starting at byte M of a data string. */
1287 case expr_substring:
1288 memset (&data, 0, sizeof data);
1289 s0 = evaluate_data_expression (&data, packet, lease,
1290 client_state,
1291 in_options, cfg_options, scope,
1292 expr -> data.substring.expr,
1293 MDL);
1295 /* Evaluate the offset and length. */
1296 s1 = evaluate_numeric_expression
1297 (&offset, packet, lease, client_state, in_options,
1298 cfg_options, scope, expr -> data.substring.offset);
1299 s2 = evaluate_numeric_expression (&len, packet, lease,
1300 client_state,
1301 in_options, cfg_options,
1302 scope,
1303 expr -> data.substring.len);
1305 if (s0 && s1 && s2) {
1306 /* If the offset is after end of the string,
1307 return an empty string. Otherwise, do the
1308 adjustments and return what's left. */
1309 if (data.len > offset) {
1310 data_string_copy (result, &data, file, line);
1311 result -> len -= offset;
1312 if (result -> len > len) {
1313 result -> len = len;
1314 result -> terminated = 0;
1316 result -> data += offset;
1318 s3 = 1;
1319 } else
1320 s3 = 0;
1322 #if defined (DEBUG_EXPRESSIONS)
1323 log_debug ("data: substring (%s, %s, %s) = %s",
1324 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1325 s1 ? print_dec_1 (offset) : "NULL",
1326 s2 ? print_dec_2 (len) : "NULL",
1327 (s3 ? print_hex_2 (result -> len, result -> data, 30)
1328 : "NULL"));
1329 #endif
1330 if (s0)
1331 data_string_forget (&data, MDL);
1332 if (s3)
1333 return 1;
1334 return 0;
1337 /* Extract the last N bytes of a data string. */
1338 case expr_suffix:
1339 memset (&data, 0, sizeof data);
1340 s0 = evaluate_data_expression (&data, packet, lease,
1341 client_state,
1342 in_options, cfg_options, scope,
1343 expr -> data.suffix.expr, MDL);
1344 /* Evaluate the length. */
1345 s1 = evaluate_numeric_expression (&len, packet, lease,
1346 client_state,
1347 in_options, cfg_options,
1348 scope,
1349 expr -> data.suffix.len);
1350 if (s0 && s1) {
1351 data_string_copy (result, &data, file, line);
1353 /* If we are returning the last N bytes of a
1354 string whose length is <= N, just return
1355 the string - otherwise, compute a new
1356 starting address and decrease the
1357 length. */
1358 if (data.len > len) {
1359 result -> data += data.len - len;
1360 result -> len = len;
1362 data_string_forget (&data, MDL);
1365 #if defined (DEBUG_EXPRESSIONS)
1366 log_debug ("data: suffix (%s, %s) = %s",
1367 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1368 s1 ? print_dec_1 (len) : "NULL",
1369 ((s0 && s1)
1370 ? print_hex_2 (result -> len, result -> data, 30)
1371 : "NULL"));
1372 #endif
1373 return s0 && s1;
1375 /* Extract an option. */
1376 case expr_option:
1377 if (in_options)
1378 s0 = get_option (result,
1379 expr -> data.option -> universe,
1380 packet, lease, client_state,
1381 in_options, cfg_options, in_options,
1382 scope, expr -> data.option -> code,
1383 file, line);
1384 else
1385 s0 = 0;
1387 #if defined (DEBUG_EXPRESSIONS)
1388 log_debug ("data: option %s.%s = %s",
1389 expr -> data.option -> universe -> name,
1390 expr -> data.option -> name,
1391 s0 ? print_hex_1 (result -> len, result -> data, 60)
1392 : "NULL");
1393 #endif
1394 return s0;
1396 case expr_config_option:
1397 if (cfg_options)
1398 s0 = get_option (result,
1399 expr -> data.option -> universe,
1400 packet, lease, client_state,
1401 in_options, cfg_options, cfg_options,
1402 scope, expr -> data.option -> code,
1403 file, line);
1404 else
1405 s0 = 0;
1407 #if defined (DEBUG_EXPRESSIONS)
1408 log_debug ("data: config-option %s.%s = %s",
1409 expr -> data.option -> universe -> name,
1410 expr -> data.option -> name,
1411 s0 ? print_hex_1 (result -> len, result -> data, 60)
1412 : "NULL");
1413 #endif
1414 return s0;
1416 /* Combine the hardware type and address. */
1417 case expr_hardware:
1418 /* On the client, hardware is our hardware. */
1419 if (client_state) {
1420 memset (result, 0, sizeof *result);
1421 result -> data =
1422 client_state -> interface -> hw_address.hbuf;
1423 result -> len =
1424 client_state -> interface -> hw_address.hlen;
1425 #if defined (DEBUG_EXPRESSIONS)
1426 log_debug ("data: hardware = %s",
1427 print_hex_1 (result -> len,
1428 result -> data, 60));
1429 #endif
1430 return 1;
1433 /* The server cares about the client's hardware address,
1434 so only in the case where we are examining a packet can
1435 we return anything. */
1436 if (!packet || !packet -> raw) {
1437 log_error ("data: hardware: raw packet not available");
1438 return 0;
1440 if (packet -> raw -> hlen > sizeof packet -> raw -> chaddr) {
1441 log_error ("data: hardware: invalid hlen (%d)\n",
1442 packet -> raw -> hlen);
1443 return 0;
1445 result -> len = packet -> raw -> hlen + 1;
1446 if (buffer_allocate (&result -> buffer, result -> len,
1447 file, line)) {
1448 result -> data = &result -> buffer -> data [0];
1449 result -> buffer -> data [0] = packet -> raw -> htype;
1450 memcpy (&result -> buffer -> data [1],
1451 packet -> raw -> chaddr,
1452 packet -> raw -> hlen);
1453 result -> terminated = 0;
1454 } else {
1455 log_error ("data: hardware: no memory for buffer.");
1456 return 0;
1458 #if defined (DEBUG_EXPRESSIONS)
1459 log_debug ("data: hardware = %s",
1460 print_hex_1 (result -> len, result -> data, 60));
1461 #endif
1462 return 1;
1464 /* Extract part of the raw packet. */
1465 case expr_packet:
1466 if (!packet || !packet -> raw) {
1467 log_error ("data: packet: raw packet not available");
1468 return 0;
1471 s0 = evaluate_numeric_expression (&offset, packet, lease,
1472 client_state,
1473 in_options, cfg_options,
1474 scope,
1475 expr -> data.packet.offset);
1476 s1 = evaluate_numeric_expression (&len,
1477 packet, lease, client_state,
1478 in_options, cfg_options,
1479 scope,
1480 expr -> data.packet.len);
1481 if (s0 && s1 && offset < packet -> packet_length) {
1482 if (offset + len > packet -> packet_length)
1483 result -> len =
1484 packet -> packet_length - offset;
1485 else
1486 result -> len = len;
1487 if (buffer_allocate (&result -> buffer,
1488 result -> len, file, line)) {
1489 result -> data = &result -> buffer -> data [0];
1490 memcpy (result -> buffer -> data,
1491 (((unsigned char *)(packet -> raw))
1492 + offset), result -> len);
1493 result -> terminated = 0;
1494 } else {
1495 log_error ("data: packet: no buffer memory.");
1496 return 0;
1498 s2 = 1;
1499 } else
1500 s2 = 0;
1501 #if defined (DEBUG_EXPRESSIONS)
1502 log_debug ("data: packet (%ld, %ld) = %s",
1503 offset, len,
1504 s2 ? print_hex_1 (result -> len,
1505 result -> data, 60) : NULL);
1506 #endif
1507 return s2;
1509 /* The encapsulation of all defined options in an
1510 option space... */
1511 case expr_encapsulate:
1512 if (cfg_options)
1513 s0 = option_space_encapsulate
1514 (result, packet, lease, client_state,
1515 in_options, cfg_options, scope,
1516 &expr -> data.encapsulate);
1517 else
1518 s0 = 0;
1520 #if defined (DEBUG_EXPRESSIONS)
1521 log_debug ("data: encapsulate (%s) = %s",
1522 expr -> data.encapsulate.data,
1523 s0 ? print_hex_1 (result -> len,
1524 result -> data, 60) : "NULL");
1525 #endif
1526 return s0;
1528 /* Some constant data... */
1529 case expr_const_data:
1530 #if defined (DEBUG_EXPRESSIONS)
1531 log_debug ("data: const = %s",
1532 print_hex_1 (expr -> data.const_data.len,
1533 expr -> data.const_data.data, 60));
1534 #endif
1535 data_string_copy (result,
1536 &expr -> data.const_data, file, line);
1537 return 1;
1539 /* Hostname lookup... */
1540 case expr_host_lookup:
1541 s0 = do_host_lookup (result, expr -> data.host_lookup);
1542 #if defined (DEBUG_EXPRESSIONS)
1543 log_debug ("data: DNS lookup (%s) = %s",
1544 expr -> data.host_lookup -> hostname,
1546 ? print_dotted_quads (result -> len, result -> data)
1547 : "NULL"));
1548 #endif
1549 return s0;
1551 /* Concatenation... */
1552 case expr_concat:
1553 memset (&data, 0, sizeof data);
1554 s0 = evaluate_data_expression (&data, packet, lease,
1555 client_state,
1556 in_options, cfg_options, scope,
1557 expr -> data.concat [0], MDL);
1558 memset (&other, 0, sizeof other);
1559 s1 = evaluate_data_expression (&other, packet, lease,
1560 client_state,
1561 in_options, cfg_options, scope,
1562 expr -> data.concat [1], MDL);
1564 if (s0 && s1) {
1565 result -> len = data.len + other.len;
1566 if (!buffer_allocate (&result -> buffer,
1567 (result -> len + other.terminated),
1568 file, line)) {
1569 log_error ("data: concat: no memory");
1570 result -> len = 0;
1571 data_string_forget (&data, MDL);
1572 data_string_forget (&other, MDL);
1573 return 0;
1575 result -> data = &result -> buffer -> data [0];
1576 memcpy (result -> buffer -> data, data.data, data.len);
1577 memcpy (&result -> buffer -> data [data.len],
1578 other.data, other.len + other.terminated);
1581 if (s0)
1582 data_string_forget (&data, MDL);
1583 if (s1)
1584 data_string_forget (&other, MDL);
1585 #if defined (DEBUG_EXPRESSIONS)
1586 log_debug ("data: concat (%s, %s) = %s",
1587 s0 ? print_hex_1 (data.len, data.data, 20) : "NULL",
1588 s1 ? print_hex_2 (other.len, other.data, 20) : "NULL",
1589 ((s0 && s1)
1590 ? print_hex_3 (result -> len, result -> data, 30)
1591 : "NULL"));
1592 #endif
1593 return s0 && s1;
1595 case expr_encode_int8:
1596 s0 = evaluate_numeric_expression (&len, packet, lease,
1597 client_state,
1598 in_options, cfg_options,
1599 scope,
1600 expr -> data.encode_int);
1601 if (s0) {
1602 result -> len = 1;
1603 if (!buffer_allocate (&result -> buffer,
1604 1, file, line)) {
1605 log_error ("data: encode_int8: no memory");
1606 result -> len = 0;
1607 s0 = 0;
1608 } else {
1609 result -> data = &result -> buffer -> data [0];
1610 result -> buffer -> data [0] = len;
1612 } else
1613 result -> len = 0;
1615 #if defined (DEBUG_EXPRESSIONS)
1616 if (!s0)
1617 log_debug ("data: encode_int8 (NULL) = NULL");
1618 else
1619 log_debug ("data: encode_int8 (%ld) = %s", len,
1620 print_hex_2 (result -> len,
1621 result -> data, 20));
1622 #endif
1623 return s0;
1626 case expr_encode_int16:
1627 s0 = evaluate_numeric_expression (&len, packet, lease,
1628 client_state,
1629 in_options, cfg_options,
1630 scope,
1631 expr -> data.encode_int);
1632 if (s0) {
1633 result -> len = 2;
1634 if (!buffer_allocate (&result -> buffer, 2,
1635 file, line)) {
1636 log_error ("data: encode_int16: no memory");
1637 result -> len = 0;
1638 s0 = 0;
1639 } else {
1640 result -> data = &result -> buffer -> data [0];
1641 putUShort (result -> buffer -> data, len);
1643 } else
1644 result -> len = 0;
1646 #if defined (DEBUG_EXPRESSIONS)
1647 if (!s0)
1648 log_debug ("data: encode_int16 (NULL) = NULL");
1649 else
1650 log_debug ("data: encode_int16 (%ld) = %s", len,
1651 print_hex_2 (result -> len,
1652 result -> data, 20));
1653 #endif
1654 return s0;
1656 case expr_encode_int32:
1657 s0 = evaluate_numeric_expression (&len, packet, lease,
1658 client_state,
1659 in_options, cfg_options,
1660 scope,
1661 expr -> data.encode_int);
1662 if (s0) {
1663 result -> len = 4;
1664 if (!buffer_allocate (&result -> buffer, 4,
1665 file, line)) {
1666 log_error ("data: encode_int32: no memory");
1667 result -> len = 0;
1668 s0 = 0;
1669 } else {
1670 result -> data = &result -> buffer -> data [0];
1671 putULong (result -> buffer -> data, len);
1673 } else
1674 result -> len = 0;
1676 #if defined (DEBUG_EXPRESSIONS)
1677 if (!s0)
1678 log_debug ("data: encode_int32 (NULL) = NULL");
1679 else
1680 log_debug ("data: encode_int32 (%ld) = %s", len,
1681 print_hex_2 (result -> len,
1682 result -> data, 20));
1683 #endif
1684 return s0;
1686 case expr_binary_to_ascii:
1687 /* Evaluate the base (offset) and width (len): */
1688 s0 = evaluate_numeric_expression
1689 (&offset, packet, lease, client_state, in_options,
1690 cfg_options, scope, expr -> data.b2a.base);
1691 s1 = evaluate_numeric_expression (&len, packet, lease,
1692 client_state,
1693 in_options, cfg_options,
1694 scope,
1695 expr -> data.b2a.width);
1697 /* Evaluate the seperator string. */
1698 memset (&data, 0, sizeof data);
1699 s2 = evaluate_data_expression (&data, packet, lease,
1700 client_state,
1701 in_options, cfg_options, scope,
1702 expr -> data.b2a.seperator,
1703 MDL);
1705 /* Evaluate the data to be converted. */
1706 memset (&other, 0, sizeof other);
1707 s3 = evaluate_data_expression (&other, packet, lease,
1708 client_state,
1709 in_options, cfg_options, scope,
1710 expr -> data.b2a.buffer, MDL);
1712 if (s0 && s1 && s2 && s3) {
1713 unsigned buflen, i;
1715 if (len != 8 && len != 16 && len != 32) {
1716 log_info ("binary_to_ascii: %s %ld!",
1717 "invalid width", len);
1718 status = 0;
1719 goto b2a_out;
1721 len /= 8;
1723 /* The buffer must be a multiple of the number's
1724 width. */
1725 if (other.len % len) {
1726 log_info ("binary-to-ascii: %s %d %s %ld!",
1727 "length of buffer", other.len,
1728 "not a multiple of width", len);
1729 status = 0;
1730 goto b2a_out;
1733 /* Count the width of the output. */
1734 buflen = 0;
1735 for (i = 0; i < other.len; i += len) {
1736 if (len == 1) {
1737 if (offset == 8) {
1738 if (other.data [i] < 8)
1739 buflen++;
1740 else if (other.data [i] < 64)
1741 buflen += 2;
1742 else
1743 buflen += 3;
1744 } else if (offset == 10) {
1745 if (other.data [i] < 10)
1746 buflen++;
1747 else if (other.data [i] < 100)
1748 buflen += 2;
1749 else
1750 buflen += 3;
1751 } else if (offset == 16) {
1752 if (other.data [i] < 16)
1753 buflen++;
1754 else
1755 buflen += 2;
1756 } else
1757 buflen += (converted_length
1758 (&other.data [i],
1759 offset, 1));
1760 } else
1761 buflen += (converted_length
1762 (&other.data [i],
1763 offset, len));
1764 if (i + len != other.len)
1765 buflen += data.len;
1768 if (!buffer_allocate (&result -> buffer,
1769 buflen + 1, file, line)) {
1770 log_error ("data: binary-to-ascii: no memory");
1771 status = 0;
1772 goto b2a_out;
1774 result -> data = &result -> buffer -> data [0];
1775 result -> len = buflen;
1776 result -> terminated = 1;
1778 buflen = 0;
1779 for (i = 0; i < other.len; i += len) {
1780 buflen += (binary_to_ascii
1781 (&result -> buffer -> data [buflen],
1782 &other.data [i], offset, len));
1783 if (i + len != other.len) {
1784 memcpy (&result ->
1785 buffer -> data [buflen],
1786 data.data, data.len);
1787 buflen += data.len;
1790 /* NUL terminate. */
1791 result -> buffer -> data [buflen] = 0;
1792 status = 1;
1793 } else
1794 status = 0;
1796 b2a_out:
1797 #if defined (DEBUG_EXPRESSIONS)
1798 log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
1799 s0 ? print_dec_1 (offset) : "NULL",
1800 s1 ? print_dec_2 (len) : "NULL",
1801 s2 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1802 s3 ? print_hex_2 (other.len, other.data, 30) : "NULL",
1803 (status ? print_hex_3 (result -> len, result -> data, 30)
1804 : "NULL"));
1805 #endif
1806 if (s2)
1807 data_string_forget (&data, MDL);
1808 if (s3)
1809 data_string_forget (&other, MDL);
1810 if (status)
1811 return 1;
1812 return 0;
1814 case expr_reverse:
1815 /* Evaluate the width (len): */
1816 s0 = evaluate_numeric_expression
1817 (&len, packet, lease, client_state, in_options,
1818 cfg_options, scope, expr -> data.reverse.width);
1820 /* Evaluate the data. */
1821 memset (&data, 0, sizeof data);
1822 s1 = evaluate_data_expression (&data, packet, lease,
1823 client_state,
1824 in_options, cfg_options, scope,
1825 expr -> data.reverse.buffer,
1826 MDL);
1828 if (s0 && s1) {
1829 char *upper;
1830 int i;
1832 /* The buffer must be a multiple of the number's
1833 width. */
1834 if (data.len % len) {
1835 log_info ("reverse: %s %d %s %ld!",
1836 "length of buffer", data.len,
1837 "not a multiple of width", len);
1838 status = 0;
1839 goto reverse_out;
1842 /* XXX reverse in place? I don't think we can. */
1843 if (!buffer_allocate (&result -> buffer,
1844 data.len, file, line)) {
1845 log_error ("data: reverse: no memory");
1846 status = 0;
1847 goto reverse_out;
1849 result -> data = &result -> buffer -> data [0];
1850 result -> len = data.len;
1851 result -> terminated = 0;
1853 for (i = 0; i < data.len; i += len) {
1854 memcpy (&result -> buffer -> data [i],
1855 &data.data [data.len - i - len], len);
1857 status = 1;
1858 } else
1859 status = 0;
1861 reverse_out:
1862 #if defined (DEBUG_EXPRESSIONS)
1863 log_debug ("data: reverse (%s, %s) = %s",
1864 s0 ? print_dec_1 (len) : "NULL",
1865 s1 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1866 (status ? print_hex_3 (result -> len, result -> data, 30)
1867 : "NULL"));
1868 #endif
1869 if (s0)
1870 data_string_forget (&data, MDL);
1871 if (status)
1872 return 1;
1873 return 0;
1875 case expr_leased_address:
1876 if (!lease) {
1877 log_error ("data: leased_address: not available");
1878 return 0;
1880 result -> len = lease -> ip_addr.len;
1881 if (buffer_allocate (&result -> buffer, result -> len,
1882 file, line)) {
1883 result -> data = &result -> buffer -> data [0];
1884 memcpy (&result -> buffer -> data [0],
1885 lease -> ip_addr.iabuf, lease -> ip_addr.len);
1886 result -> terminated = 0;
1887 } else {
1888 log_error ("data: leased-address: no memory.");
1889 return 0;
1891 #if defined (DEBUG_EXPRESSIONS)
1892 log_debug ("data: leased-address = %s",
1893 print_hex_1 (result -> len, result -> data, 60));
1894 #endif
1895 return 1;
1897 case expr_pick_first_value:
1898 memset (&data, 0, sizeof data);
1899 if ((evaluate_data_expression
1900 (result, packet,
1901 lease, client_state, in_options, cfg_options,
1902 scope, expr -> data.pick_first_value.car, MDL))) {
1903 #if defined (DEBUG_EXPRESSIONS)
1904 log_debug ("data: pick_first_value (%s, xxx)",
1905 print_hex_1 (result -> len,
1906 result -> data, 40));
1907 #endif
1908 return 1;
1911 if (expr -> data.pick_first_value.cdr &&
1912 (evaluate_data_expression
1913 (result, packet,
1914 lease, client_state, in_options, cfg_options,
1915 scope, expr -> data.pick_first_value.cdr, MDL))) {
1916 #if defined (DEBUG_EXPRESSIONS)
1917 log_debug ("data: pick_first_value (NULL, %s)",
1918 print_hex_1 (result -> len,
1919 result -> data, 40));
1920 #endif
1921 return 1;
1924 #if defined (DEBUG_EXPRESSIONS)
1925 log_debug ("data: pick_first_value (NULL, NULL) = NULL");
1926 #endif
1927 return 0;
1929 case expr_host_decl_name:
1930 if (!lease || !lease -> host) {
1931 log_error ("data: host_decl_name: not available");
1932 return 0;
1934 result -> len = strlen (lease -> host -> name);
1935 if (buffer_allocate (&result -> buffer,
1936 result -> len + 1, file, line)) {
1937 result -> data = &result -> buffer -> data [0];
1938 strcpy ((char *)&result -> buffer -> data [0],
1939 lease -> host -> name);
1940 result -> terminated = 1;
1941 } else {
1942 log_error ("data: host-decl-name: no memory.");
1943 return 0;
1945 #if defined (DEBUG_EXPRESSIONS)
1946 log_debug ("data: host-decl-name = %s", lease -> host -> name);
1947 #endif
1948 return 1;
1950 case expr_null:
1951 #if defined (DEBUG_EXPRESSIONS)
1952 log_debug ("data: null = NULL");
1953 #endif
1954 return 0;
1956 case expr_variable_reference:
1957 if (scope && *scope) {
1958 binding = find_binding (*scope, expr -> data.variable);
1960 if (binding && binding -> value) {
1961 if (binding -> value -> type == binding_data) {
1962 data_string_copy (result,
1963 &binding -> value -> value.data,
1964 file, line);
1965 s0 = 1;
1966 } else if (binding -> value -> type != binding_data) {
1967 log_error ("binding type %d in %s.",
1968 binding -> value -> type,
1969 "evaluate_data_expression");
1970 s0 = 0;
1971 } else
1972 s0 = 0;
1973 } else
1974 s0 = 0;
1975 } else
1976 s0 = 0;
1977 #if defined (DEBUG_EXPRESSIONS)
1978 log_debug ("data: %s = %s", expr -> data.variable,
1979 s0 ? print_hex_1 (result -> len,
1980 result -> data, 50) : "NULL");
1981 #endif
1982 return s0;
1984 case expr_funcall:
1985 bv = (struct binding_value *)0;
1986 s0 = evaluate_expression (&bv, packet, lease, client_state,
1987 in_options, cfg_options,
1988 scope, expr, MDL);
1989 if (s0) {
1990 if (bv -> type != binding_data)
1991 log_error ("%s() returned type %d in %s.",
1992 expr -> data.funcall.name,
1993 bv -> type,
1994 "evaluate_data_expression");
1995 else
1996 data_string_copy (result, &bv -> value.data,
1997 file, line);
1998 binding_value_dereference (&bv, MDL);
2000 #if defined (DEBUG_EXPRESSIONS)
2001 log_debug ("data: %s = %s", expr -> data.funcall.name,
2002 s0 ? print_hex_1 (result -> len,
2003 result -> data, 50) : "NULL");
2004 #endif
2005 break;
2007 /* Extract the filename. */
2008 case expr_filename:
2009 if (packet && packet -> raw -> file [0]) {
2010 char *fn =
2011 memchr (packet -> raw -> file, 0,
2012 sizeof packet -> raw -> file);
2013 if (!fn)
2014 fn = ((char *)packet -> raw -> file +
2015 sizeof packet -> raw -> file);
2016 result -> len = fn - &(packet -> raw -> file [0]);
2017 if (buffer_allocate (&result -> buffer,
2018 result -> len + 1, file, line)) {
2019 result -> data = &result -> buffer -> data [0];
2020 memcpy (&result -> buffer -> data [0],
2021 packet -> raw -> file,
2022 result -> len);
2023 result -> buffer -> data [result -> len] = 0;
2024 result -> terminated = 1;
2025 s0 = 1;
2026 } else {
2027 log_error ("data: filename: no memory.");
2028 s0 = 0;
2030 } else
2031 s0 = 0;
2033 #if defined (DEBUG_EXPRESSIONS)
2034 log_info ("data: filename = \"%s\"",
2035 s0 ? (const char *)(result -> data) : "NULL");
2036 #endif
2037 return s0;
2039 /* Extract the server name. */
2040 case expr_sname:
2041 if (packet && packet -> raw -> sname [0]) {
2042 char *fn =
2043 memchr (packet -> raw -> sname, 0,
2044 sizeof packet -> raw -> sname);
2045 if (!fn)
2046 fn = ((char *)packet -> raw -> sname +
2047 sizeof packet -> raw -> sname);
2048 result -> len = fn - &packet -> raw -> sname [0];
2049 if (buffer_allocate (&result -> buffer,
2050 result -> len + 1, file, line)) {
2051 result -> data = &result -> buffer -> data [0];
2052 memcpy (&result -> buffer -> data [0],
2053 packet -> raw -> sname,
2054 result -> len);
2055 result -> buffer -> data [result -> len] = 0;
2056 result -> terminated = 1;
2057 s0 = 1;
2058 } else {
2059 log_error ("data: sname: no memory.");
2060 s0 = 0;
2062 } else
2063 s0 = 0;
2065 #if defined (DEBUG_EXPRESSIONS)
2066 log_info ("data: sname = \"%s\"",
2067 s0 ? (const char *)(result -> data) : "NULL");
2068 #endif
2069 return s0;
2071 case expr_check:
2072 case expr_equal:
2073 case expr_not_equal:
2074 case expr_and:
2075 case expr_or:
2076 case expr_not:
2077 case expr_match:
2078 case expr_static:
2079 case expr_known:
2080 case expr_none:
2081 case expr_exists:
2082 case expr_variable_exists:
2083 log_error ("Boolean opcode in evaluate_data_expression: %d",
2084 expr -> op);
2085 return 0;
2087 case expr_extract_int8:
2088 case expr_extract_int16:
2089 case expr_extract_int32:
2090 case expr_const_int:
2091 case expr_lease_time:
2092 case expr_dns_transaction:
2093 case expr_add:
2094 case expr_subtract:
2095 case expr_multiply:
2096 case expr_divide:
2097 case expr_remainder:
2098 case expr_binary_and:
2099 case expr_binary_or:
2100 case expr_binary_xor:
2101 case expr_client_state:
2102 log_error ("Numeric opcode in evaluate_data_expression: %d",
2103 expr -> op);
2104 return 0;
2106 case expr_ns_add:
2107 case expr_ns_delete:
2108 case expr_ns_exists:
2109 case expr_ns_not_exists:
2110 log_error ("dns update opcode in evaluate_data_expression: %d",
2111 expr -> op);
2112 return 0;
2114 case expr_function:
2115 log_error ("function definition in evaluate_data_expression");
2116 return 0;
2118 case expr_arg:
2119 break;
2122 log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op);
2123 return 0;
2126 int evaluate_numeric_expression (result, packet, lease, client_state,
2127 in_options, cfg_options, scope, expr)
2128 unsigned long *result;
2129 struct packet *packet;
2130 struct lease *lease;
2131 struct client_state *client_state;
2132 struct option_state *in_options;
2133 struct option_state *cfg_options;
2134 struct binding_scope **scope;
2135 struct expression *expr;
2137 struct data_string data;
2138 int status, sleft, sright;
2139 #if defined (NSUPDATE)
2140 ns_updrec *nut;
2141 ns_updque uq;
2142 #endif
2143 struct expression *cur, *next;
2144 struct binding *binding;
2145 struct binding_value *bv;
2146 unsigned long ileft, iright;
2148 switch (expr -> op) {
2149 case expr_check:
2150 case expr_equal:
2151 case expr_not_equal:
2152 case expr_and:
2153 case expr_or:
2154 case expr_not:
2155 case expr_match:
2156 case expr_static:
2157 case expr_known:
2158 case expr_none:
2159 case expr_exists:
2160 case expr_variable_exists:
2161 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
2162 expr -> op);
2163 return 0;
2165 case expr_substring:
2166 case expr_suffix:
2167 case expr_option:
2168 case expr_hardware:
2169 case expr_const_data:
2170 case expr_packet:
2171 case expr_concat:
2172 case expr_encapsulate:
2173 case expr_host_lookup:
2174 case expr_encode_int8:
2175 case expr_encode_int16:
2176 case expr_encode_int32:
2177 case expr_binary_to_ascii:
2178 case expr_reverse:
2179 case expr_filename:
2180 case expr_sname:
2181 case expr_pick_first_value:
2182 case expr_host_decl_name:
2183 case expr_config_option:
2184 case expr_leased_address:
2185 case expr_null:
2186 log_error ("Data opcode in evaluate_numeric_expression: %d",
2187 expr -> op);
2188 return 0;
2190 case expr_extract_int8:
2191 memset (&data, 0, sizeof data);
2192 status = evaluate_data_expression
2193 (&data, packet, lease, client_state, in_options,
2194 cfg_options, scope, expr -> data.extract_int, MDL);
2195 if (status)
2196 *result = data.data [0];
2197 #if defined (DEBUG_EXPRESSIONS)
2198 log_debug ("num: extract_int8 (%s) = %s",
2199 status ? print_hex_1 (data.len, data.data, 60) : "NULL",
2200 status ? print_dec_1 (*result) : "NULL" );
2201 #endif
2202 if (status) data_string_forget (&data, MDL);
2203 return status;
2205 case expr_extract_int16:
2206 memset (&data, 0, sizeof data);
2207 status = (evaluate_data_expression
2208 (&data, packet, lease, client_state, in_options,
2209 cfg_options, scope, expr -> data.extract_int, MDL));
2210 if (status && data.len >= 2)
2211 *result = getUShort (data.data);
2212 #if defined (DEBUG_EXPRESSIONS)
2213 log_debug ("num: extract_int16 (%s) = %ld",
2214 ((status && data.len >= 2) ?
2215 print_hex_1 (data.len, data.data, 60) : "NULL"),
2216 *result);
2217 #endif
2218 if (status) data_string_forget (&data, MDL);
2219 return (status && data.len >= 2);
2221 case expr_extract_int32:
2222 memset (&data, 0, sizeof data);
2223 status = (evaluate_data_expression
2224 (&data, packet, lease, client_state, in_options,
2225 cfg_options, scope, expr -> data.extract_int, MDL));
2226 if (status && data.len >= 4)
2227 *result = getULong (data.data);
2228 #if defined (DEBUG_EXPRESSIONS)
2229 log_debug ("num: extract_int32 (%s) = %ld",
2230 ((status && data.len >= 4) ?
2231 print_hex_1 (data.len, data.data, 60) : "NULL"),
2232 *result);
2233 #endif
2234 if (status) data_string_forget (&data, MDL);
2235 return (status && data.len >= 4);
2237 case expr_const_int:
2238 *result = expr -> data.const_int;
2239 #if defined (DEBUG_EXPRESSIONS)
2240 log_debug ("number: CONSTANT = %ld", *result);
2241 #endif
2242 return 1;
2244 case expr_lease_time:
2245 if (!lease) {
2246 log_error ("data: leased_lease: not available");
2247 return 0;
2249 if (lease -> ends < cur_time) {
2250 log_error ("%s %lu when it is now %lu",
2251 "data: lease_time: lease ends at",
2252 (long)(lease -> ends), (long)cur_time);
2253 return 0;
2255 *result = lease -> ends - cur_time;
2256 #if defined (DEBUG_EXPRESSIONS)
2257 log_debug ("number: lease-time = (%lu - %lu) = %ld",
2258 lease -> ends,
2259 cur_time, *result);
2260 #endif
2261 return 1;
2263 case expr_dns_transaction:
2264 #if !defined (NSUPDATE)
2265 return 0;
2266 #else
2267 if (!resolver_inited) {
2268 minires_ninit (&resolver_state);
2269 resolver_inited = 1;
2270 resolver_state.retrans = 1;
2271 resolver_state.retry = 1;
2273 ISC_LIST_INIT (uq);
2274 cur = expr;
2275 do {
2276 next = cur -> data.dns_transaction.cdr;
2277 nut = 0;
2278 status = (evaluate_dns_expression
2279 (&nut, packet,
2280 lease, client_state, in_options, cfg_options,
2281 scope, cur -> data.dns_transaction.car));
2282 if (!status)
2283 goto dns_bad;
2284 ISC_LIST_APPEND (uq, nut, r_link);
2285 cur = next;
2286 } while (next);
2288 /* Do the update and record the error code, if there was
2289 an error; otherwise set it to NOERROR. */
2290 *result = minires_nupdate (&resolver_state,
2291 ISC_LIST_HEAD (uq));
2292 status = 1;
2294 print_dns_status ((int)*result, &uq);
2296 dns_bad:
2297 while (!ISC_LIST_EMPTY (uq)) {
2298 ns_updrec *tmp = ISC_LIST_HEAD (uq);
2299 ISC_LIST_UNLINK (uq, tmp, r_link);
2300 if (tmp -> r_data_ephem) {
2301 dfree (tmp -> r_data_ephem, MDL);
2302 tmp -> r_data = (unsigned char *)0;
2303 tmp -> r_data_ephem = (unsigned char *)0;
2305 minires_freeupdrec (tmp);
2307 return status;
2308 #endif /* NSUPDATE */
2310 case expr_variable_reference:
2311 if (scope && *scope) {
2312 binding = find_binding (*scope, expr -> data.variable);
2314 if (binding && binding -> value) {
2315 if (binding -> value -> type == binding_numeric) {
2316 *result = binding -> value -> value.intval;
2317 status = 1;
2318 } else {
2319 log_error ("binding type %d in %s.",
2320 binding -> value -> type,
2321 "evaluate_numeric_expression");
2322 status = 0;
2324 } else
2325 status = 0;
2326 } else
2327 status = 0;
2328 #if defined (DEBUG_EXPRESSIONS)
2329 if (status)
2330 log_debug ("numeric: %s = %ld",
2331 expr -> data.variable, *result);
2332 else
2333 log_debug ("numeric: %s = NULL",
2334 expr -> data.variable);
2335 #endif
2336 return status;
2338 case expr_funcall:
2339 bv = (struct binding_value *)0;
2340 status = evaluate_expression (&bv, packet, lease,
2341 client_state,
2342 in_options, cfg_options,
2343 scope, expr, MDL);
2344 if (status) {
2345 if (bv -> type != binding_numeric)
2346 log_error ("%s() returned type %d in %s.",
2347 expr -> data.funcall.name,
2348 bv -> type,
2349 "evaluate_numeric_expression");
2350 else
2351 *result = bv -> value.intval;
2352 binding_value_dereference (&bv, MDL);
2354 #if defined (DEBUG_EXPRESSIONS)
2355 log_debug ("data: %s = %ld", expr -> data.funcall.name,
2356 status ? *result : 0);
2357 #endif
2358 break;
2360 case expr_add:
2361 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2362 client_state,
2363 in_options, cfg_options,
2364 scope,
2365 expr -> data.and [0]);
2366 sright = evaluate_numeric_expression (&iright, packet, lease,
2367 client_state,
2368 in_options, cfg_options,
2369 scope,
2370 expr -> data.and [1]);
2372 #if defined (DEBUG_EXPRESSIONS)
2373 if (sleft && sright)
2374 log_debug ("num: %ld + %ld = %ld",
2375 ileft, iright, ileft + iright);
2376 else if (sleft)
2377 log_debug ("num: %ld + NULL = NULL", ileft);
2378 else
2379 log_debug ("num: NULL + %ld = NULL", iright);
2380 #endif
2381 if (sleft && sright) {
2382 *result = ileft + iright;
2383 return 1;
2385 return 0;
2387 case expr_subtract:
2388 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2389 client_state,
2390 in_options, cfg_options,
2391 scope,
2392 expr -> data.and [0]);
2393 sright = evaluate_numeric_expression (&iright, packet, lease,
2394 client_state,
2395 in_options, cfg_options,
2396 scope,
2397 expr -> data.and [1]);
2399 #if defined (DEBUG_EXPRESSIONS)
2400 if (sleft && sright)
2401 log_debug ("num: %ld - %ld = %ld",
2402 ileft, iright, ileft - iright);
2403 else if (sleft)
2404 log_debug ("num: %ld - NULL = NULL", ileft);
2405 else
2406 log_debug ("num: NULL - %ld = NULL", iright);
2407 #endif
2408 if (sleft && sright) {
2409 *result = ileft - iright;
2410 return 1;
2412 return 0;
2414 case expr_multiply:
2415 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2416 client_state,
2417 in_options, cfg_options,
2418 scope,
2419 expr -> data.and [0]);
2420 sright = evaluate_numeric_expression (&iright, packet, lease,
2421 client_state,
2422 in_options, cfg_options,
2423 scope,
2424 expr -> data.and [1]);
2426 #if defined (DEBUG_EXPRESSIONS)
2427 if (sleft && sright)
2428 log_debug ("num: %ld * %ld = %ld",
2429 ileft, iright, ileft * iright);
2430 else if (sleft)
2431 log_debug ("num: %ld * NULL = NULL", ileft);
2432 else
2433 log_debug ("num: NULL * %ld = NULL", iright);
2434 #endif
2435 if (sleft && sright) {
2436 *result = ileft * iright;
2437 return 1;
2439 return 0;
2441 case expr_divide:
2442 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2443 client_state,
2444 in_options, cfg_options,
2445 scope,
2446 expr -> data.and [0]);
2447 sright = evaluate_numeric_expression (&iright, packet, lease,
2448 client_state,
2449 in_options, cfg_options,
2450 scope,
2451 expr -> data.and [1]);
2453 #if defined (DEBUG_EXPRESSIONS)
2454 if (sleft && sright) {
2455 if (iright != 0)
2456 log_debug ("num: %ld / %ld = %ld",
2457 ileft, iright, ileft / iright);
2458 else
2459 log_debug ("num: %ld / %ld = NULL",
2460 ileft, iright);
2461 } else if (sleft)
2462 log_debug ("num: %ld / NULL = NULL", ileft);
2463 else
2464 log_debug ("num: NULL / %ld = NULL", iright);
2465 #endif
2466 if (sleft && sright && iright) {
2467 *result = ileft / iright;
2468 return 1;
2470 return 0;
2472 case expr_remainder:
2473 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2474 client_state,
2475 in_options, cfg_options,
2476 scope,
2477 expr -> data.and [0]);
2478 sright = evaluate_numeric_expression (&iright, packet, lease,
2479 client_state,
2480 in_options, cfg_options,
2481 scope,
2482 expr -> data.and [1]);
2484 #if defined (DEBUG_EXPRESSIONS)
2485 if (sleft && sright) {
2486 if (iright != 0)
2487 log_debug ("num: %ld %% %ld = %ld",
2488 ileft, iright, ileft % iright);
2489 else
2490 log_debug ("num: %ld %% %ld = NULL",
2491 ileft, iright);
2492 } else if (sleft)
2493 log_debug ("num: %ld %% NULL = NULL", ileft);
2494 else
2495 log_debug ("num: NULL %% %ld = NULL", iright);
2496 #endif
2497 if (sleft && sright && iright) {
2498 *result = ileft % iright;
2499 return 1;
2501 return 0;
2503 case expr_binary_and:
2504 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2505 client_state,
2506 in_options, cfg_options,
2507 scope,
2508 expr -> data.and [0]);
2509 sright = evaluate_numeric_expression (&iright, packet, lease,
2510 client_state,
2511 in_options, cfg_options,
2512 scope,
2513 expr -> data.and [1]);
2515 #if defined (DEBUG_EXPRESSIONS)
2516 if (sleft && sright)
2517 log_debug ("num: %ld | %ld = %ld",
2518 ileft, iright, ileft & iright);
2519 else if (sleft)
2520 log_debug ("num: %ld & NULL = NULL", ileft);
2521 else
2522 log_debug ("num: NULL & %ld = NULL", iright);
2523 #endif
2524 if (sleft && sright) {
2525 *result = ileft & iright;
2526 return 1;
2528 return 0;
2530 case expr_binary_or:
2531 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2532 client_state,
2533 in_options, cfg_options,
2534 scope,
2535 expr -> data.and [0]);
2536 sright = evaluate_numeric_expression (&iright, packet, lease,
2537 client_state,
2538 in_options, cfg_options,
2539 scope,
2540 expr -> data.and [1]);
2542 #if defined (DEBUG_EXPRESSIONS)
2543 if (sleft && sright)
2544 log_debug ("num: %ld | %ld = %ld",
2545 ileft, iright, ileft | iright);
2546 else if (sleft)
2547 log_debug ("num: %ld | NULL = NULL", ileft);
2548 else
2549 log_debug ("num: NULL | %ld = NULL", iright);
2550 #endif
2551 if (sleft && sright) {
2552 *result = ileft | iright;
2553 return 1;
2555 return 0;
2557 case expr_binary_xor:
2558 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2559 client_state,
2560 in_options, cfg_options,
2561 scope,
2562 expr -> data.and [0]);
2563 sright = evaluate_numeric_expression (&iright, packet, lease,
2564 client_state,
2565 in_options, cfg_options,
2566 scope,
2567 expr -> data.and [1]);
2569 #if defined (DEBUG_EXPRESSIONS)
2570 if (sleft && sright)
2571 log_debug ("num: %ld ^ %ld = %ld",
2572 ileft, iright, ileft ^ iright);
2573 else if (sleft)
2574 log_debug ("num: %ld ^ NULL = NULL", ileft);
2575 else
2576 log_debug ("num: NULL ^ %ld = NULL", iright);
2577 #endif
2578 if (sleft && sright) {
2579 *result = ileft ^ iright;
2580 return 1;
2582 return 0;
2584 case expr_client_state:
2585 if (client_state) {
2586 #if defined (DEBUG_EXPRESSIONS)
2587 log_debug ("num: client-state = %d",
2588 client_state -> state);
2589 #endif
2590 *result = client_state -> state;
2591 return 1;
2592 } else {
2593 #if defined (DEBUG_EXPRESSIONS)
2594 log_debug ("num: client-state = NULL");
2595 #endif
2596 return 0;
2599 case expr_ns_add:
2600 case expr_ns_delete:
2601 case expr_ns_exists:
2602 case expr_ns_not_exists:
2603 log_error ("dns opcode in evaluate_numeric_expression: %d",
2604 expr -> op);
2605 return 0;
2607 case expr_function:
2608 log_error ("function definition in evaluate_numeric_expr");
2609 return 0;
2611 case expr_arg:
2612 break;
2615 log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op);
2616 return 0;
2619 /* Return data hanging off of an option cache structure, or if there
2620 isn't any, evaluate the expression hanging off of it and return the
2621 result of that evaluation. There should never be both an expression
2622 and a valid data_string. */
2624 int evaluate_option_cache (result, packet, lease, client_state,
2625 in_options, cfg_options, scope, oc, file, line)
2626 struct data_string *result;
2627 struct packet *packet;
2628 struct lease *lease;
2629 struct client_state *client_state;
2630 struct option_state *in_options;
2631 struct option_state *cfg_options;
2632 struct binding_scope **scope;
2633 struct option_cache *oc;
2634 const char *file;
2635 int line;
2637 if (oc -> data.len) {
2638 data_string_copy (result, &oc -> data, file, line);
2639 return 1;
2641 if (!oc -> expression)
2642 return 0;
2643 return evaluate_data_expression (result, packet, lease, client_state,
2644 in_options, cfg_options, scope,
2645 oc -> expression, file, line);
2648 /* Evaluate an option cache and extract a boolean from the result,
2649 returning the boolean. Return false if there is no data. */
2651 int evaluate_boolean_option_cache (ignorep, packet,
2652 lease, client_state, in_options,
2653 cfg_options, scope, oc, file, line)
2654 int *ignorep;
2655 struct packet *packet;
2656 struct lease *lease;
2657 struct client_state *client_state;
2658 struct option_state *in_options;
2659 struct option_state *cfg_options;
2660 struct binding_scope **scope;
2661 struct option_cache *oc;
2662 const char *file;
2663 int line;
2665 struct data_string ds;
2666 int result;
2668 /* So that we can be called with option_lookup as an argument. */
2669 if (!oc || !in_options)
2670 return 0;
2672 memset (&ds, 0, sizeof ds);
2673 if (!evaluate_option_cache (&ds, packet,
2674 lease, client_state, in_options,
2675 cfg_options, scope, oc, file, line))
2676 return 0;
2678 if (ds.len) {
2679 result = ds.data [0];
2680 if (result == 2) {
2681 result = 0;
2682 *ignorep = 1;
2683 } else
2684 *ignorep = 0;
2685 } else
2686 result = 0;
2687 data_string_forget (&ds, MDL);
2688 return result;
2692 /* Evaluate a boolean expression and return the result of the evaluation,
2693 or FALSE if it failed. */
2695 int evaluate_boolean_expression_result (ignorep, packet, lease, client_state,
2696 in_options, cfg_options, scope, expr)
2697 int *ignorep;
2698 struct packet *packet;
2699 struct lease *lease;
2700 struct client_state *client_state;
2701 struct option_state *in_options;
2702 struct option_state *cfg_options;
2703 struct binding_scope **scope;
2704 struct expression *expr;
2706 int result;
2708 /* So that we can be called with option_lookup as an argument. */
2709 if (!expr)
2710 return 0;
2712 if (!evaluate_boolean_expression (&result, packet, lease, client_state,
2713 in_options, cfg_options,
2714 scope, expr))
2715 return 0;
2717 if (result == 2) {
2718 *ignorep = 1;
2719 result = 0;
2720 } else
2721 *ignorep = 0;
2722 return result;
2726 /* Dereference an expression node, and if the reference count goes to zero,
2727 dereference any data it refers to, and then free it. */
2728 void expression_dereference (eptr, file, line)
2729 struct expression **eptr;
2730 const char *file;
2731 int line;
2733 struct expression *expr = *eptr;
2735 /* Zero the pointer. */
2736 *eptr = (struct expression *)0;
2738 /* Decrement the reference count. If it's nonzero, we're
2739 done. */
2740 --(expr -> refcnt);
2741 rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC);
2742 if (expr -> refcnt > 0)
2743 return;
2744 if (expr -> refcnt < 0) {
2745 log_error ("%s(%d): negative refcnt!", file, line);
2746 #if defined (DEBUG_RC_HISTORY)
2747 dump_rc_history (expr);
2748 #endif
2749 #if defined (POINTER_DEBUG)
2750 abort ();
2751 #else
2752 return;
2753 #endif
2756 /* Dereference subexpressions. */
2757 switch (expr -> op) {
2758 /* All the binary operators can be handled the same way. */
2759 case expr_equal:
2760 case expr_not_equal:
2761 case expr_concat:
2762 case expr_and:
2763 case expr_or:
2764 case expr_add:
2765 case expr_subtract:
2766 case expr_multiply:
2767 case expr_divide:
2768 case expr_remainder:
2769 case expr_binary_and:
2770 case expr_binary_or:
2771 case expr_binary_xor:
2772 case expr_client_state:
2773 if (expr -> data.equal [0])
2774 expression_dereference (&expr -> data.equal [0],
2775 file, line);
2776 if (expr -> data.equal [1])
2777 expression_dereference (&expr -> data.equal [1],
2778 file, line);
2779 break;
2781 case expr_substring:
2782 if (expr -> data.substring.expr)
2783 expression_dereference (&expr -> data.substring.expr,
2784 file, line);
2785 if (expr -> data.substring.offset)
2786 expression_dereference (&expr -> data.substring.offset,
2787 file, line);
2788 if (expr -> data.substring.len)
2789 expression_dereference (&expr -> data.substring.len,
2790 file, line);
2791 break;
2793 case expr_suffix:
2794 if (expr -> data.suffix.expr)
2795 expression_dereference (&expr -> data.suffix.expr,
2796 file, line);
2797 if (expr -> data.suffix.len)
2798 expression_dereference (&expr -> data.suffix.len,
2799 file, line);
2800 break;
2802 case expr_not:
2803 if (expr -> data.not)
2804 expression_dereference (&expr -> data.not, file, line);
2805 break;
2807 case expr_packet:
2808 if (expr -> data.packet.offset)
2809 expression_dereference (&expr -> data.packet.offset,
2810 file, line);
2811 if (expr -> data.packet.len)
2812 expression_dereference (&expr -> data.packet.len,
2813 file, line);
2814 break;
2816 case expr_extract_int8:
2817 case expr_extract_int16:
2818 case expr_extract_int32:
2819 if (expr -> data.extract_int)
2820 expression_dereference (&expr -> data.extract_int,
2821 file, line);
2822 break;
2824 case expr_encode_int8:
2825 case expr_encode_int16:
2826 case expr_encode_int32:
2827 if (expr -> data.encode_int)
2828 expression_dereference (&expr -> data.encode_int,
2829 file, line);
2830 break;
2832 case expr_encapsulate:
2833 case expr_const_data:
2834 data_string_forget (&expr -> data.const_data, file, line);
2835 break;
2837 case expr_host_lookup:
2838 if (expr -> data.host_lookup)
2839 dns_host_entry_dereference (&expr -> data.host_lookup,
2840 file, line);
2841 break;
2843 case expr_binary_to_ascii:
2844 if (expr -> data.b2a.base)
2845 expression_dereference (&expr -> data.b2a.base,
2846 file, line);
2847 if (expr -> data.b2a.width)
2848 expression_dereference (&expr -> data.b2a.width,
2849 file, line);
2850 if (expr -> data.b2a.seperator)
2851 expression_dereference (&expr -> data.b2a.seperator,
2852 file, line);
2853 if (expr -> data.b2a.buffer)
2854 expression_dereference (&expr -> data.b2a.buffer,
2855 file, line);
2856 break;
2858 case expr_pick_first_value:
2859 if (expr -> data.pick_first_value.car)
2860 expression_dereference (&expr -> data.pick_first_value.car,
2861 file, line);
2862 if (expr -> data.pick_first_value.cdr)
2863 expression_dereference (&expr -> data.pick_first_value.cdr,
2864 file, line);
2865 break;
2867 case expr_reverse:
2868 if (expr -> data.reverse.width)
2869 expression_dereference (&expr -> data.reverse.width,
2870 file, line);
2871 if (expr -> data.reverse.buffer)
2872 expression_dereference
2873 (&expr -> data.reverse.buffer, file, line);
2874 break;
2876 case expr_dns_transaction:
2877 if (expr -> data.dns_transaction.car)
2878 expression_dereference (&expr -> data.dns_transaction.car,
2879 file, line);
2880 if (expr -> data.dns_transaction.cdr)
2881 expression_dereference (&expr -> data.dns_transaction.cdr,
2882 file, line);
2883 break;
2885 case expr_ns_add:
2886 if (expr -> data.ns_add.rrname)
2887 expression_dereference (&expr -> data.ns_add.rrname,
2888 file, line);
2889 if (expr -> data.ns_add.rrdata)
2890 expression_dereference (&expr -> data.ns_add.rrdata,
2891 file, line);
2892 if (expr -> data.ns_add.ttl)
2893 expression_dereference (&expr -> data.ns_add.ttl,
2894 file, line);
2895 break;
2897 case expr_ns_delete:
2898 case expr_ns_exists:
2899 case expr_ns_not_exists:
2900 if (expr -> data.ns_delete.rrname)
2901 expression_dereference (&expr -> data.ns_delete.rrname,
2902 file, line);
2903 if (expr -> data.ns_delete.rrdata)
2904 expression_dereference (&expr -> data.ns_delete.rrdata,
2905 file, line);
2906 break;
2908 case expr_variable_reference:
2909 case expr_variable_exists:
2910 if (expr -> data.variable)
2911 dfree (expr -> data.variable, file, line);
2912 break;
2914 case expr_funcall:
2915 if (expr -> data.funcall.name)
2916 dfree (expr -> data.funcall.name, file, line);
2917 if (expr -> data.funcall.arglist)
2918 expression_dereference (&expr -> data.funcall.arglist,
2919 file, line);
2920 break;
2922 case expr_arg:
2923 if (expr -> data.arg.val)
2924 expression_dereference (&expr -> data.arg.val,
2925 file, line);
2926 if (expr -> data.arg.next)
2927 expression_dereference (&expr -> data.arg.next,
2928 file, line);
2929 break;
2931 case expr_function:
2932 fundef_dereference (&expr -> data.func, file, line);
2933 break;
2935 /* No subexpressions. */
2936 case expr_leased_address:
2937 case expr_lease_time:
2938 case expr_filename:
2939 case expr_sname:
2940 case expr_const_int:
2941 case expr_check:
2942 case expr_option:
2943 case expr_hardware:
2944 case expr_exists:
2945 case expr_known:
2946 case expr_null:
2947 break;
2949 default:
2950 break;
2952 free_expression (expr, MDL);
2955 int is_dns_expression (expr)
2956 struct expression *expr;
2958 return (expr -> op == expr_ns_add ||
2959 expr -> op == expr_ns_delete ||
2960 expr -> op == expr_ns_exists ||
2961 expr -> op == expr_ns_not_exists);
2964 int is_boolean_expression (expr)
2965 struct expression *expr;
2967 return (expr -> op == expr_check ||
2968 expr -> op == expr_exists ||
2969 expr -> op == expr_variable_exists ||
2970 expr -> op == expr_equal ||
2971 expr -> op == expr_not_equal ||
2972 expr -> op == expr_and ||
2973 expr -> op == expr_or ||
2974 expr -> op == expr_not ||
2975 expr -> op == expr_known ||
2976 expr -> op == expr_static);
2979 int is_data_expression (expr)
2980 struct expression *expr;
2982 return (expr -> op == expr_substring ||
2983 expr -> op == expr_suffix ||
2984 expr -> op == expr_option ||
2985 expr -> op == expr_hardware ||
2986 expr -> op == expr_const_data ||
2987 expr -> op == expr_packet ||
2988 expr -> op == expr_concat ||
2989 expr -> op == expr_encapsulate ||
2990 expr -> op == expr_encode_int8 ||
2991 expr -> op == expr_encode_int16 ||
2992 expr -> op == expr_encode_int32 ||
2993 expr -> op == expr_host_lookup ||
2994 expr -> op == expr_binary_to_ascii ||
2995 expr -> op == expr_filename ||
2996 expr -> op == expr_sname ||
2997 expr -> op == expr_reverse ||
2998 expr -> op == expr_pick_first_value ||
2999 expr -> op == expr_host_decl_name ||
3000 expr -> op == expr_leased_address ||
3001 expr -> op == expr_config_option ||
3002 expr -> op == expr_null);
3005 int is_numeric_expression (expr)
3006 struct expression *expr;
3008 return (expr -> op == expr_extract_int8 ||
3009 expr -> op == expr_extract_int16 ||
3010 expr -> op == expr_extract_int32 ||
3011 expr -> op == expr_const_int ||
3012 expr -> op == expr_lease_time ||
3013 expr -> op == expr_dns_transaction ||
3014 expr -> op == expr_add ||
3015 expr -> op == expr_subtract ||
3016 expr -> op == expr_multiply ||
3017 expr -> op == expr_divide ||
3018 expr -> op == expr_remainder ||
3019 expr -> op == expr_binary_and ||
3020 expr -> op == expr_binary_or ||
3021 expr -> op == expr_binary_xor ||
3022 expr -> op == expr_client_state);
3025 int is_compound_expression (expr)
3026 struct expression *expr;
3028 return (expr -> op == expr_ns_add ||
3029 expr -> op == expr_ns_delete ||
3030 expr -> op == expr_ns_exists ||
3031 expr -> op == expr_ns_not_exists ||
3032 expr -> op == expr_substring ||
3033 expr -> op == expr_suffix ||
3034 expr -> op == expr_option ||
3035 expr -> op == expr_concat ||
3036 expr -> op == expr_encode_int8 ||
3037 expr -> op == expr_encode_int16 ||
3038 expr -> op == expr_encode_int32 ||
3039 expr -> op == expr_binary_to_ascii ||
3040 expr -> op == expr_reverse ||
3041 expr -> op == expr_pick_first_value ||
3042 expr -> op == expr_config_option ||
3043 expr -> op == expr_extract_int8 ||
3044 expr -> op == expr_extract_int16 ||
3045 expr -> op == expr_extract_int32 ||
3046 expr -> op == expr_dns_transaction);
3049 static int op_val PROTO ((enum expr_op));
3051 static int op_val (op)
3052 enum expr_op op;
3054 switch (op) {
3055 case expr_none:
3056 case expr_match:
3057 case expr_static:
3058 case expr_check:
3059 case expr_substring:
3060 case expr_suffix:
3061 case expr_concat:
3062 case expr_encapsulate:
3063 case expr_host_lookup:
3064 case expr_not:
3065 case expr_option:
3066 case expr_hardware:
3067 case expr_packet:
3068 case expr_const_data:
3069 case expr_extract_int8:
3070 case expr_extract_int16:
3071 case expr_extract_int32:
3072 case expr_encode_int8:
3073 case expr_encode_int16:
3074 case expr_encode_int32:
3075 case expr_const_int:
3076 case expr_exists:
3077 case expr_variable_exists:
3078 case expr_known:
3079 case expr_binary_to_ascii:
3080 case expr_reverse:
3081 case expr_filename:
3082 case expr_sname:
3083 case expr_pick_first_value:
3084 case expr_host_decl_name:
3085 case expr_config_option:
3086 case expr_leased_address:
3087 case expr_lease_time:
3088 case expr_dns_transaction:
3089 case expr_null:
3090 case expr_variable_reference:
3091 case expr_ns_add:
3092 case expr_ns_delete:
3093 case expr_ns_exists:
3094 case expr_ns_not_exists:
3095 case expr_arg:
3096 case expr_funcall:
3097 case expr_function:
3098 /* XXXDPN: Need to assign sane precedences to these. */
3099 case expr_binary_and:
3100 case expr_binary_or:
3101 case expr_binary_xor:
3102 case expr_client_state:
3103 return 100;
3105 case expr_equal:
3106 case expr_not_equal:
3107 return 4;
3109 case expr_or:
3110 case expr_and:
3111 return 3;
3113 case expr_add:
3114 case expr_subtract:
3115 return 2;
3117 case expr_multiply:
3118 case expr_divide:
3119 case expr_remainder:
3120 return 1;
3122 return 100;
3125 int op_precedence (op1, op2)
3126 enum expr_op op1, op2;
3128 int ov1, ov2;
3130 return op_val (op1) - op_val (op2);
3133 enum expression_context expression_context (struct expression *expr)
3135 if (is_data_expression (expr))
3136 return context_data;
3137 if (is_numeric_expression (expr))
3138 return context_numeric;
3139 if (is_boolean_expression (expr))
3140 return context_boolean;
3141 if (is_dns_expression (expr))
3142 return context_dns;
3143 return context_any;
3146 enum expression_context op_context (op)
3147 enum expr_op op;
3149 switch (op) {
3150 /* XXX Why aren't these specific? */
3151 case expr_none:
3152 case expr_match:
3153 case expr_static:
3154 case expr_check:
3155 case expr_substring:
3156 case expr_suffix:
3157 case expr_concat:
3158 case expr_encapsulate:
3159 case expr_host_lookup:
3160 case expr_not:
3161 case expr_option:
3162 case expr_hardware:
3163 case expr_packet:
3164 case expr_const_data:
3165 case expr_extract_int8:
3166 case expr_extract_int16:
3167 case expr_extract_int32:
3168 case expr_encode_int8:
3169 case expr_encode_int16:
3170 case expr_encode_int32:
3171 case expr_const_int:
3172 case expr_exists:
3173 case expr_variable_exists:
3174 case expr_known:
3175 case expr_binary_to_ascii:
3176 case expr_reverse:
3177 case expr_filename:
3178 case expr_sname:
3179 case expr_pick_first_value:
3180 case expr_host_decl_name:
3181 case expr_config_option:
3182 case expr_leased_address:
3183 case expr_lease_time:
3184 case expr_null:
3185 case expr_variable_reference:
3186 case expr_ns_add:
3187 case expr_ns_delete:
3188 case expr_ns_exists:
3189 case expr_ns_not_exists:
3190 case expr_dns_transaction:
3191 case expr_arg:
3192 case expr_funcall:
3193 case expr_function:
3194 return context_any;
3196 case expr_equal:
3197 case expr_not_equal:
3198 return context_data;
3200 case expr_and:
3201 return context_boolean;
3203 case expr_or:
3204 return context_boolean;
3206 case expr_add:
3207 case expr_subtract:
3208 case expr_multiply:
3209 case expr_divide:
3210 case expr_remainder:
3211 case expr_binary_and:
3212 case expr_binary_or:
3213 case expr_binary_xor:
3214 case expr_client_state:
3215 return context_numeric;
3217 return context_any;
3220 int write_expression (file, expr, col, indent, firstp)
3221 FILE *file;
3222 struct expression *expr;
3223 int col;
3224 int indent;
3225 int firstp;
3227 struct expression *e;
3228 const char *s;
3229 char obuf [65];
3230 int scol;
3231 int width;
3233 /* If this promises to be a fat expression, start a new line. */
3234 if (!firstp && is_compound_expression (expr)) {
3235 indent_spaces (file, indent);
3236 col = indent;
3239 switch (expr -> op) {
3240 case expr_none:
3241 col = token_print_indent (file, col, indent, "", "", "null");
3242 break;
3244 case expr_check:
3245 col = token_print_indent (file, col, indent, "", "", "check");
3246 col = token_print_indent_concat (file, col, indent,
3247 " ", "", "\"",
3248 expr -> data.check -> name,
3249 "\"", (char *)0);
3250 break;
3252 case expr_not_equal:
3253 s = "!=";
3254 goto binary;
3256 case expr_equal:
3257 s = "=";
3258 binary:
3259 col = write_expression (file, expr -> data.equal [0],
3260 col, indent, 1);
3261 col = token_print_indent (file, col, indent, " ", " ", s);
3262 col = write_expression (file, expr -> data.equal [1],
3263 col, indent + 2, 0);
3264 break;
3266 case expr_substring:
3267 col = token_print_indent (file, col, indent, "", "",
3268 "substring");
3269 col = token_print_indent (file, col, indent, " ", "", "(");
3270 scol = col;
3271 col = write_expression (file, expr -> data.substring.expr,
3272 col, scol, 1);
3273 col = token_print_indent (file, col, indent, "", " ", ",");
3274 col = write_expression (file, expr -> data.substring.offset,
3275 col, indent, 0);
3276 col = token_print_indent (file, col, scol, "", " ", ",");
3277 col = write_expression (file, expr -> data.substring.len,
3278 col, scol, 0);
3279 col = token_print_indent (file, col, indent, "", "", ")");
3280 break;
3282 case expr_suffix:
3283 col = token_print_indent (file, col, indent, "", "", "suffix");
3284 col = token_print_indent (file, col, indent, " ", "", "(");
3285 scol = col;
3286 col = write_expression (file, expr -> data.suffix.expr,
3287 col, scol, 1);
3288 col = token_print_indent (file, col, scol, "", " ", ",");
3289 col = write_expression (file, expr -> data.suffix.len,
3290 col, scol, 0);
3291 col = token_print_indent (file, col, indent, "", "", ")");
3292 break;
3294 case expr_concat:
3295 e = expr;
3296 col = token_print_indent (file, col, indent, "", "",
3297 "concat");
3298 col = token_print_indent (file, col, indent, " ", "", "(");
3299 scol = col;
3300 firstp = 1;
3301 concat_again:
3302 col = write_expression (file, e -> data.concat [0],
3303 col, scol, firstp);
3304 firstp = 0;
3305 if (!e -> data.concat [1])
3306 goto no_concat_cdr;
3307 col = token_print_indent (file, col, scol, "", " ", ",");
3308 if (e -> data.concat [1] -> op == expr_concat) {
3309 e = e -> data.concat [1];
3310 goto concat_again;
3312 col = write_expression (file, e -> data.concat [1],
3313 col, scol, 0);
3314 no_concat_cdr:
3315 col = token_print_indent (file, col, indent, "", "", ")");
3316 break;
3318 case expr_host_lookup:
3319 col = token_print_indent (file, col, indent, "", "",
3320 "gethostbyname");
3321 col = token_print_indent (file, col, indent, " ", "", "(");
3322 col = token_print_indent_concat
3323 (file, col, indent, "", "",
3324 "\"", expr -> data.host_lookup -> hostname, "\"",
3325 (char *)0);
3326 col = token_print_indent (file, col, indent, "", "", ")");
3327 break;
3329 case expr_add:
3330 s = "+";
3331 goto binary;
3333 case expr_subtract:
3334 s = "-";
3335 goto binary;
3337 case expr_multiply:
3338 s = "*";
3339 goto binary;
3341 case expr_divide:
3342 s = "/";
3343 goto binary;
3345 case expr_remainder:
3346 s = "%";
3347 goto binary;
3349 case expr_binary_and:
3350 s = "&";
3351 goto binary;
3353 case expr_binary_or:
3354 s = "|";
3355 goto binary;
3357 case expr_binary_xor:
3358 s = "^";
3359 goto binary;
3361 case expr_and:
3362 s = "and";
3363 goto binary;
3365 case expr_or:
3366 s = "or";
3367 goto binary;
3369 case expr_not:
3370 col = token_print_indent (file, col, indent, "", " ", "not");
3371 col = write_expression (file,
3372 expr -> data.not, col, indent + 2, 1);
3373 break;
3375 case expr_option:
3376 s = "option";
3378 print_option_name:
3379 col = token_print_indent (file, col, indent, "", "", s);
3381 if (expr -> data.option -> universe != &dhcp_universe) {
3382 col = token_print_indent (file, col, indent,
3383 " ", "",
3384 (expr -> data.option ->
3385 universe -> name));
3386 col = token_print_indent (file, col, indent, "", "",
3387 ".");
3388 col = token_print_indent (file, col, indent, "", "",
3389 expr -> data.option -> name);
3390 } else {
3391 col = token_print_indent (file, col, indent, " ", "",
3392 expr -> data.option -> name);
3394 break;
3396 case expr_hardware:
3397 col = token_print_indent (file, col, indent, "", "",
3398 "hardware");
3399 break;
3401 case expr_packet:
3402 col = token_print_indent (file, col, indent, "", "",
3403 "packet");
3404 col = token_print_indent (file, col, indent, " ", "", "(");
3405 scol = col;
3406 col = write_expression (file, expr -> data.packet.offset,
3407 col, indent, 1);
3408 col = token_print_indent (file, col, scol, "", " ", ",");
3409 col = write_expression (file, expr -> data.packet.len,
3410 col, scol, 0);
3411 col = token_print_indent (file, col, indent, "", "", ")");
3412 break;
3414 case expr_const_data:
3415 col = token_indent_data_string (file, col, indent, "", "",
3416 &expr -> data.const_data);
3417 break;
3419 case expr_extract_int8:
3420 width = 8;
3421 extract_int:
3422 col = token_print_indent (file, col, indent, "", "",
3423 "extract-int");
3424 col = token_print_indent (file, col, indent, " ", "", "(");
3425 scol = col;
3426 col = write_expression (file, expr -> data.extract_int,
3427 col, indent, 1);
3428 col = token_print_indent (file, col, scol, "", " ", ",");
3429 sprintf (obuf, "%d", width);
3430 col = token_print_indent (file, col, scol, " ", "", obuf);
3431 col = token_print_indent (file, col, indent, "", "", ")");
3432 break;
3434 case expr_extract_int16:
3435 width = 16;
3436 goto extract_int;
3438 case expr_extract_int32:
3439 width = 32;
3440 goto extract_int;
3442 case expr_encode_int8:
3443 width = 8;
3444 encode_int:
3445 col = token_print_indent (file, col, indent, "", "",
3446 "encode-int");
3447 col = token_print_indent (file, col, indent, " ", "", "(");
3448 scol = col;
3449 col = write_expression (file, expr -> data.extract_int,
3450 col, indent, 1);
3451 col = token_print_indent (file, col, scol, "", " ", ",");
3452 sprintf (obuf, "%d", width);
3453 col = token_print_indent (file, col, scol, " ", "", obuf);
3454 col = token_print_indent (file, col, indent, "", "",
3455 ")");
3456 break;
3458 case expr_encode_int16:
3459 width = 16;
3460 goto encode_int;
3462 case expr_encode_int32:
3463 width = 32;
3464 goto encode_int;
3466 case expr_const_int:
3467 sprintf (obuf, "%lu", expr -> data.const_int);
3468 col = token_print_indent (file, col, indent, "", "", obuf);
3469 break;
3471 case expr_exists:
3472 s = "exists";
3473 goto print_option_name;
3475 case expr_encapsulate:
3476 col = token_print_indent (file, col, indent, "", "",
3477 "encapsulate");
3478 col = token_indent_data_string (file, col, indent, " ", "",
3479 &expr -> data.encapsulate);
3480 break;
3482 case expr_known:
3483 col = token_print_indent (file, col, indent, "", "", "known");
3484 break;
3486 case expr_reverse:
3487 col = token_print_indent (file, col, indent, "", "",
3488 "reverse");
3489 col = token_print_indent (file, col, indent, " ", "", "(");
3490 scol = col;
3491 col = write_expression (file, expr -> data.reverse.width,
3492 col, scol, 1);
3493 col = token_print_indent (file, col, scol, "", " ", ",");
3494 col = write_expression (file, expr -> data.reverse.buffer,
3495 col, scol, 0);
3496 col = token_print_indent (file, col, indent, "", "",
3497 ")");
3498 break;
3500 case expr_leased_address:
3501 col = token_print_indent (file, col, indent, "", "",
3502 "leased-address");
3503 break;
3505 case expr_client_state:
3506 col = token_print_indent (file, col, indent, "", "",
3507 "client-state");
3508 break;
3510 case expr_binary_to_ascii:
3511 col = token_print_indent (file, col, indent, "", "",
3512 "binary-to-ascii");
3513 col = token_print_indent (file, col, indent, " ", "",
3514 "(");
3515 scol = col;
3516 col = write_expression (file, expr -> data.b2a.base,
3517 col, scol, 1);
3518 col = token_print_indent (file, col, scol, "", " ",
3519 ",");
3520 col = write_expression (file, expr -> data.b2a.width,
3521 col, scol, 0);
3522 col = token_print_indent (file, col, scol, "", " ",
3523 ",");
3524 col = write_expression (file, expr -> data.b2a.seperator,
3525 col, scol, 0);
3526 col = token_print_indent (file, col, scol, "", " ",
3527 ",");
3528 col = write_expression (file, expr -> data.b2a.buffer,
3529 col, scol, 0);
3530 col = token_print_indent (file, col, indent, "", "",
3531 ")");
3532 break;
3534 case expr_config_option:
3535 s = "config-option";
3536 goto print_option_name;
3538 case expr_host_decl_name:
3539 col = token_print_indent (file, col, indent, "", "",
3540 "host-decl-name");
3541 break;
3543 case expr_pick_first_value:
3544 e = expr;
3545 col = token_print_indent (file, col, indent, "", "",
3546 "concat");
3547 col = token_print_indent (file, col, indent, " ", "",
3548 "(");
3549 scol = col;
3550 firstp = 1;
3551 pick_again:
3552 col = write_expression (file,
3553 e -> data.pick_first_value.car,
3554 col, scol, firstp);
3555 firstp = 0;
3556 /* We're being very lisp-like right now - instead of
3557 representing this expression as (first middle . last) we're
3558 representing it as (first middle last), which means that the
3559 tail cdr is always nil. Apologies to non-wisp-lizards - may
3560 this obscure way of describing the problem motivate you to
3561 learn more about the one true computing language. */
3562 if (!e -> data.pick_first_value.cdr)
3563 goto no_pick_cdr;
3564 col = token_print_indent (file, col, scol, "", " ",
3565 ",");
3566 if (e -> data.pick_first_value.cdr -> op ==
3567 expr_pick_first_value) {
3568 e = e -> data.pick_first_value.cdr;
3569 goto pick_again;
3571 col = write_expression (file,
3572 e -> data.pick_first_value.cdr,
3573 col, scol, 0);
3574 no_pick_cdr:
3575 col = token_print_indent (file, col, indent, "", "",
3576 ")");
3577 break;
3579 case expr_lease_time:
3580 col = token_print_indent (file, col, indent, "", "",
3581 "lease-time");
3582 break;
3584 case expr_dns_transaction:
3585 col = token_print_indent (file, col, indent, "", "",
3586 "ns-update");
3587 col = token_print_indent (file, col, indent, " ", "",
3588 "(");
3589 scol = 0;
3590 for (e = expr;
3591 e && e -> op == expr_dns_transaction;
3592 e = e -> data.dns_transaction.cdr) {
3593 if (!scol) {
3594 scol = col;
3595 firstp = 1;
3596 } else
3597 firstp = 0;
3598 col = write_expression (file,
3599 e -> data.dns_transaction.car,
3600 col, scol, firstp);
3601 if (e -> data.dns_transaction.cdr)
3602 col = token_print_indent (file, col, scol,
3603 "", " ", ",");
3605 if (e)
3606 col = write_expression (file, e, col, scol, 0);
3607 col = token_print_indent (file, col, indent, "", "", ")");
3608 break;
3610 case expr_ns_add:
3611 col = token_print_indent (file, col, indent, "", "",
3612 "update");
3613 col = token_print_indent (file, col, indent, " ", "",
3614 "(");
3615 scol = col;
3616 sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
3617 col = token_print_indent (file, col, scol, "", "", obuf);
3618 col = token_print_indent (file, col, scol, "", " ",
3619 ",");
3620 sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
3621 col = token_print_indent (file, col, scol, "", "", obuf);
3622 col = token_print_indent (file, col, scol, "", " ",
3623 ",");
3624 col = write_expression (file, expr -> data.ns_add.rrname,
3625 col, scol, 0);
3626 col = token_print_indent (file, col, scol, "", " ",
3627 ",");
3628 col = write_expression (file, expr -> data.ns_add.rrdata,
3629 col, scol, 0);
3630 col = token_print_indent (file, col, scol, "", " ",
3631 ",");
3632 col = write_expression (file, expr -> data.ns_add.ttl,
3633 col, scol, 0);
3634 col = token_print_indent (file, col, indent, "", "",
3635 ")");
3636 break;
3638 case expr_ns_delete:
3639 col = token_print_indent (file, col, indent, "", "",
3640 "delete");
3641 col = token_print_indent (file, col, indent, " ", "",
3642 "(");
3643 finish_ns_small:
3644 scol = col;
3645 sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
3646 col = token_print_indent (file, col, scol, "", "", obuf);
3647 col = token_print_indent (file, col, scol, "", " ",
3648 ",");
3649 sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
3650 col = token_print_indent (file, col, scol, "", "", obuf);
3651 col = token_print_indent (file, col, scol, "", " ",
3652 ",");
3653 col = write_expression (file, expr -> data.ns_add.rrname,
3654 col, scol, 0);
3655 col = token_print_indent (file, col, scol, "", " ",
3656 ",");
3657 col = write_expression (file, expr -> data.ns_add.rrdata,
3658 col, scol, 0);
3659 col = token_print_indent (file, col, indent, "", "",
3660 ")");
3661 break;
3663 case expr_ns_exists:
3664 col = token_print_indent (file, col, indent, "", "",
3665 "exists");
3666 col = token_print_indent (file, col, indent, " ", "",
3667 "(");
3668 goto finish_ns_small;
3670 case expr_ns_not_exists:
3671 col = token_print_indent (file, col, indent, "", "",
3672 "not exists");
3673 col = token_print_indent (file, col, indent, " ", "",
3674 "(");
3675 goto finish_ns_small;
3677 case expr_static:
3678 col = token_print_indent (file, col, indent, "", "",
3679 "static");
3680 break;
3682 case expr_null:
3683 col = token_print_indent (file, col, indent, "", "", "null");
3684 break;
3686 case expr_variable_reference:
3687 col = token_print_indent (file, indent, indent, "", "",
3688 expr -> data.variable);
3689 break;
3691 case expr_variable_exists:
3692 col = token_print_indent (file, indent, indent, "", "",
3693 "defined");
3694 col = token_print_indent (file, col, indent, " ", "", "(");
3695 col = token_print_indent (file, col, indent, "", "",
3696 expr -> data.variable);
3697 col = token_print_indent (file, col, indent, "", "", ")");
3698 break;
3700 default:
3701 log_fatal ("invalid expression type in print_expression: %d",
3702 expr -> op);
3704 return col;
3707 struct binding *find_binding (struct binding_scope *scope, const char *name)
3709 struct binding *bp;
3710 struct binding_scope *s;
3712 for (s = scope; s; s = s -> outer) {
3713 for (bp = s -> bindings; bp; bp = bp -> next) {
3714 if (!strcasecmp (name, bp -> name)) {
3715 return bp;
3719 return (struct binding *)0;
3722 int free_bindings (struct binding_scope *scope, const char *file, int line)
3724 struct binding *bp, *next;
3726 for (bp = scope -> bindings; bp; bp = next) {
3727 next = bp -> next;
3728 if (bp -> name)
3729 dfree (bp -> name, file, line);
3730 if (bp -> value)
3731 binding_value_dereference (&bp -> value, file, line);
3732 dfree (bp, file, line);
3734 scope -> bindings = (struct binding *)0;
3735 return 1;
3738 int binding_scope_dereference (ptr, file, line)
3739 struct binding_scope **ptr;
3740 const char *file;
3741 int line;
3743 int i;
3744 struct binding_scope *binding_scope;
3746 if (!ptr || !*ptr) {
3747 log_error ("%s(%d): null pointer", file, line);
3748 #if defined (POINTER_DEBUG)
3749 abort ();
3750 #else
3751 return 0;
3752 #endif
3755 binding_scope = *ptr;
3756 *ptr = (struct binding_scope *)0;
3757 --binding_scope -> refcnt;
3758 rc_register (file, line, ptr,
3759 binding_scope, binding_scope -> refcnt, 1, RC_MISC);
3760 if (binding_scope -> refcnt > 0)
3761 return 1;
3763 if (binding_scope -> refcnt < 0) {
3764 log_error ("%s(%d): negative refcnt!", file, line);
3765 #if defined (DEBUG_RC_HISTORY)
3766 dump_rc_history (binding_scope);
3767 #endif
3768 #if defined (POINTER_DEBUG)
3769 abort ();
3770 #else
3771 return 0;
3772 #endif
3775 free_bindings (binding_scope, file, line);
3776 if (binding_scope -> outer)
3777 binding_scope_dereference (&binding_scope -> outer, MDL);
3778 dfree (binding_scope, file, line);
3779 return 1;
3782 int fundef_dereference (ptr, file, line)
3783 struct fundef **ptr;
3784 const char *file;
3785 int line;
3787 struct fundef *bp = *ptr;
3788 struct string_list *sp, *next;
3790 if (!ptr) {
3791 log_error ("%s(%d): null pointer", file, line);
3792 #if defined (POINTER_DEBUG)
3793 abort ();
3794 #else
3795 return 0;
3796 #endif
3799 if (!bp) {
3800 log_error ("%s(%d): null pointer", file, line);
3801 #if defined (POINTER_DEBUG)
3802 abort ();
3803 #else
3804 return 0;
3805 #endif
3808 bp -> refcnt--;
3809 rc_register (file, line, ptr, bp, bp -> refcnt, 1, RC_MISC);
3810 if (bp -> refcnt < 0) {
3811 log_error ("%s(%d): negative refcnt!", file, line);
3812 #if defined (DEBUG_RC_HISTORY)
3813 dump_rc_history (bp);
3814 #endif
3815 #if defined (POINTER_DEBUG)
3816 abort ();
3817 #else
3818 return 0;
3819 #endif
3821 if (!bp -> refcnt) {
3822 for (sp = bp -> args; sp; sp = next) {
3823 next = sp -> next;
3824 dfree (sp, file, line);
3826 if (bp -> statements)
3827 executable_statement_dereference (&bp -> statements,
3828 file, line);
3829 dfree (bp, file, line);
3831 *ptr = (struct fundef *)0;
3832 return 1;
3835 #if defined (NOTYET) /* Post 3.0 final. */
3836 int data_subexpression_length (int *rv,
3837 struct expression *expr)
3839 int crhs, clhs, llhs, lrhs;
3840 switch (expr -> op) {
3841 case expr_substring:
3842 if (expr -> data.substring.len &&
3843 expr -> data.substring.len -> op == expr_const_int) {
3844 (*rv =
3845 (int)expr -> data.substring.len -> data.const_int);
3846 return 1;
3848 return 0;
3850 case expr_packet:
3851 case expr_suffix:
3852 if (expr -> data.suffix.len &&
3853 expr -> data.suffix.len -> op == expr_const_int) {
3854 (*rv =
3855 (int)expr -> data.suffix.len -> data.const_int);
3856 return 1;
3858 return 0;
3860 case expr_concat:
3861 clhs = data_subexpression_length (&llhs,
3862 expr -> data.concat [0]);
3863 crhs = data_subexpression_length (&lrhs,
3864 expr -> data.concat [1]);
3865 if (crhs == 0 || clhs == 0)
3866 return 0;
3867 *rv = llhs + lrhs;
3868 return 1;
3869 break;
3871 case expr_hardware:
3872 return 0;
3874 case expr_const_data:
3875 *rv = expr -> data.const_data.len;
3876 return 2;
3878 case expr_reverse:
3879 return data_subexpression_length (rv,
3880 expr -> data.reverse.buffer);
3882 case expr_leased_address:
3883 case expr_lease_time:
3884 *rv = 4;
3885 return 2;
3887 case expr_pick_first_value:
3888 clhs = data_subexpression_length (&llhs,
3889 expr -> data.concat [0]);
3890 crhs = data_subexpression_length (&lrhs,
3891 expr -> data.concat [1]);
3892 if (crhs == 0 || clhs == 0)
3893 return 0;
3894 if (llhs > lrhs)
3895 *rv = llhs;
3896 else
3897 *rv = lrhs;
3898 return 1;
3900 case expr_binary_to_ascii:
3901 case expr_config_option:
3902 case expr_host_decl_name:
3903 case expr_encapsulate:
3904 case expr_filename:
3905 case expr_sname:
3906 case expr_host_lookup:
3907 case expr_option:
3908 case expr_none:
3909 case expr_match:
3910 case expr_check:
3911 case expr_equal:
3912 case expr_and:
3913 case expr_or:
3914 case expr_not:
3915 case expr_extract_int8:
3916 case expr_extract_int16:
3917 case expr_extract_int32:
3918 case expr_encode_int8:
3919 case expr_encode_int16:
3920 case expr_encode_int32:
3921 case expr_const_int:
3922 case expr_exists:
3923 case expr_known:
3924 case expr_dns_transaction:
3925 case expr_static:
3926 case expr_ns_add:
3927 case expr_ns_delete:
3928 case expr_ns_exists:
3929 case expr_ns_not_exists:
3930 case expr_not_equal:
3931 case expr_null:
3932 case expr_variable_exists:
3933 case expr_variable_reference:
3934 case expr_arg:
3935 case expr_funcall:
3936 case expr_function:
3937 case expr_add:
3938 case expr_subtract:
3939 case expr_multiply:
3940 case expr_divide:
3941 case expr_remainder:
3942 case expr_binary_and:
3943 case expr_binary_or:
3944 case expr_binary_xor:
3945 case expr_client_state:
3946 return 0;
3948 return 0;
3951 int expr_valid_for_context (struct expression *expr,
3952 enum expression_context context)
3954 /* We don't know at parse time what type of value a function may
3955 return, so we can't flag an error on it. */
3956 if (expr -> op == expr_funcall ||
3957 expr -> op == expr_variable_reference)
3958 return 1;
3960 switch (context) {
3961 case context_any:
3962 return 1;
3964 case context_boolean:
3965 if (is_boolean_expression (expr))
3966 return 1;
3967 return 0;
3969 case context_data:
3970 if (is_data_expression (expr))
3971 return 1;
3972 return 0;
3974 case context_numeric:
3975 if (is_numeric_expression (expr))
3976 return 1;
3977 return 0;
3979 case context_dns:
3980 if (is_dns_expression (expr)) {
3981 return 1;
3983 return 0;
3985 case context_data_or_numeric:
3986 if (is_numeric_expression (expr) ||
3987 is_data_expression (expr)) {
3988 return 1;
3990 return 0;
3992 case context_function:
3993 if (expr -> op == expr_function)
3994 return 1;
3995 return 0;
3997 return 0;
3999 #endif /* NOTYET */
4001 struct binding *create_binding (struct binding_scope **scope, const char *name)
4003 struct binding *binding;
4005 if (!*scope) {
4006 if (!binding_scope_allocate (scope, MDL))
4007 return (struct binding *)0;
4010 binding = find_binding (*scope, name);
4011 if (!binding) {
4012 binding = dmalloc (sizeof *binding, MDL);
4013 if (!binding)
4014 return (struct binding *)0;
4016 memset (binding, 0, sizeof *binding);
4017 binding -> name = dmalloc (strlen (name) + 1, MDL);
4018 if (!binding -> name) {
4019 dfree (binding, MDL);
4020 return (struct binding *)0;
4022 strcpy (binding -> name, name);
4024 binding -> next = (*scope) -> bindings;
4025 (*scope) -> bindings = binding;
4028 return binding;
4032 int bind_ds_value (struct binding_scope **scope,
4033 const char *name,
4034 struct data_string *value)
4036 struct binding *binding;
4038 binding = create_binding (scope, name);
4039 if (!binding)
4040 return 0;
4042 if (binding -> value)
4043 binding_value_dereference (&binding -> value, MDL);
4045 if (!binding_value_allocate (&binding -> value, MDL))
4046 return 0;
4048 data_string_copy (&binding -> value -> value.data, value, MDL);
4049 binding -> value -> type = binding_data;
4051 return 1;
4055 int find_bound_string (struct data_string *value,
4056 struct binding_scope *scope,
4057 const char *name)
4059 struct binding *binding;
4061 binding = find_binding (scope, name);
4062 if (!binding ||
4063 !binding -> value ||
4064 binding -> value -> type != binding_data)
4065 return 0;
4067 if (binding -> value -> value.data.terminated) {
4068 data_string_copy (value, &binding -> value -> value.data, MDL);
4069 } else {
4070 buffer_allocate (&value -> buffer,
4071 binding -> value -> value.data.len,
4072 MDL);
4073 if (!value -> buffer)
4074 return 0;
4076 memcpy (value -> buffer -> data,
4077 binding -> value -> value.data.data,
4078 binding -> value -> value.data.len);
4079 value -> data = value -> buffer -> data;
4080 value -> len = binding -> value -> value.data.len;
4083 return 1;
4086 int unset (struct binding_scope *scope, const char *name)
4088 struct binding *binding;
4090 binding = find_binding (scope, name);
4091 if (binding) {
4092 if (binding -> value)
4093 binding_value_dereference
4094 (&binding -> value, MDL);
4095 return 1;
4097 return 0;
4100 /* vim: set tabstop=8: */