Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / network / stacks / AROSTCP / dhcp / common / tree.c
blob794f56fc7fe58dc2c266cae30f65c9638e46f2fc
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 #if 0
36 static char copyright[] =
37 "$Id$ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
38 #endif
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;
652 // int r3;
654 if (!result || *result) {
655 log_error ("evaluate_dns_expression called with non-null %s",
656 "result pointer");
657 #if defined (POINTER_DEBUG)
658 abort ();
659 #else
660 return 0;
661 #endif
664 switch (expr -> op) {
665 #if defined (NSUPDATE)
666 case expr_ns_add:
667 r0 = evaluate_numeric_expression (&ttl, packet, lease,
668 client_state,
669 in_options, cfg_options,
670 scope,
671 expr -> data.ns_add.ttl);
672 goto nsfinish;
674 case expr_ns_exists:
675 ttl = 1;
677 case expr_ns_delete:
678 case expr_ns_not_exists:
679 r0 = 1;
680 nsfinish:
681 memset (&name, 0, sizeof name);
682 r1 = evaluate_data_expression (&name, packet, lease,
683 client_state,
684 in_options, cfg_options, scope,
685 expr -> data.ns_add.rrname,
686 MDL);
687 if (r1) {
688 /* The result of the evaluation may or may not
689 be NUL-terminated, but we need it
690 terminated for sure, so we have to allocate
691 a buffer and terminate it. */
692 tname = dmalloc (name.len + 1, MDL);
693 if (!tname) {
694 r2 = 0;
695 r1 = 0;
696 data_string_forget (&name, MDL);
697 } else {
698 memcpy (tname, name.data, name.len);
699 tname [name.len] = 0;
700 memset (&data, 0, sizeof data);
701 r2 = evaluate_data_expression
702 (&data, packet, lease, client_state,
703 in_options, cfg_options, scope,
704 expr -> data.ns_add.rrdata, MDL);
706 } else {
707 r2 = 0;
708 tname = NULL;
710 if (r0 && r1 && (r2 || expr -> op != expr_ns_add)) {
711 *result = minires_mkupdrec (((expr -> op == expr_ns_add ||
712 expr -> op == expr_ns_delete)
713 ? S_UPDATE : S_PREREQ),
714 tname,
715 expr -> data.ns_add.rrclass,
716 expr -> data.ns_add.rrtype,
717 ttl);
718 if (!*result) {
719 ngood:
720 if (r2) {
721 data_string_forget (&data, MDL);
722 r2 = 0;
724 } else {
725 if (data.len) {
726 /* As a special case, if we get exactly
727 four bytes of data, it's an IP address
728 represented as a 32-bit quantity, which
729 is actually what we *should* be getting
730 here. Because res_mkupdrec is currently
731 broken and expects a dotted quad, convert
732 it. This should be fixed when the new
733 resolver is merged. */
734 if (data.len == 4) {
735 (*result) -> r_data_ephem =
736 dmalloc (16, MDL);
737 if (!(*result) -> r_data_ephem)
738 goto dpngood;
739 (*result) -> r_data =
740 (*result) -> r_data_ephem;
741 /*%Audit% 16 bytes max. %2004.06.17,Safe%*/
742 sprintf ((char *)(*result) -> r_data_ephem,
743 "%u.%u.%u.%u",
744 data.data [0] & 0xff,
745 data.data [1] & 0xff,
746 data.data [2] & 0xff,
747 data.data [3] & 0xff);
748 (*result) -> r_size =
749 strlen ((const char *)
750 (*result) -> r_data);
751 } else {
752 (*result) -> r_size = data.len;
753 (*result) -> r_data_ephem =
754 dmalloc (data.len, MDL);
755 if (!(*result) -> r_data_ephem) {
756 dpngood: /* double plus ungood. */
757 minires_freeupdrec (*result);
758 *result = 0;
759 goto ngood;
761 (*result) -> r_data =
762 (*result) -> r_data_ephem;
763 memcpy ((*result) -> r_data_ephem,
764 data.data, data.len);
766 } else {
767 (*result) -> r_data = 0;
768 (*result) -> r_size = 0;
770 switch (expr -> op) {
771 case expr_ns_add:
772 (*result) -> r_opcode = ADD;
773 break;
774 case expr_ns_delete:
775 (*result) -> r_opcode = DELETE;
776 break;
777 case expr_ns_exists:
778 (*result) -> r_opcode = YXRRSET;
779 break;
780 case expr_ns_not_exists:
781 (*result) -> r_opcode = NXRRSET;
782 break;
784 /* Can't happen, but satisfy gcc. */
785 default:
786 break;
790 if (r1) {
791 data_string_forget (&name, MDL);
792 dfree (tname, MDL);
794 if (r2)
795 data_string_forget (&data, MDL);
796 /* One flaw in the thinking here: an IP address and an
797 ASCII string both look like data expressions, but
798 for A records, we want an ASCII string, not a
799 binary IP address. Do I need to turn binary IP
800 addresses into a seperate type? */
801 return (r0 && r1 &&
802 (r2 || expr -> op != expr_ns_add) && *result);
804 #else
805 case expr_ns_add:
806 case expr_ns_delete:
807 case expr_ns_exists:
808 case expr_ns_not_exists:
809 return 0;
810 #endif
811 case expr_funcall:
812 log_error ("%s: dns values for functions not supported.",
813 expr -> data.funcall.name);
814 break;
816 case expr_variable_reference:
817 log_error ("%s: dns values for variables not supported.",
818 expr -> data.variable);
819 break;
821 case expr_check:
822 case expr_equal:
823 case expr_not_equal:
824 case expr_and:
825 case expr_or:
826 case expr_not:
827 case expr_match:
828 case expr_static:
829 case expr_known:
830 case expr_exists:
831 case expr_variable_exists:
832 log_error ("Boolean opcode in evaluate_dns_expression: %d",
833 expr -> op);
834 return 0;
836 case expr_none:
837 case expr_substring:
838 case expr_suffix:
839 case expr_option:
840 case expr_hardware:
841 case expr_const_data:
842 case expr_packet:
843 case expr_concat:
844 case expr_encapsulate:
845 case expr_host_lookup:
846 case expr_encode_int8:
847 case expr_encode_int16:
848 case expr_encode_int32:
849 case expr_binary_to_ascii:
850 case expr_reverse:
851 case expr_filename:
852 case expr_sname:
853 case expr_pick_first_value:
854 case expr_host_decl_name:
855 case expr_config_option:
856 case expr_leased_address:
857 case expr_null:
858 log_error ("Data opcode in evaluate_dns_expression: %d",
859 expr -> op);
860 return 0;
862 case expr_extract_int8:
863 case expr_extract_int16:
864 case expr_extract_int32:
865 case expr_const_int:
866 case expr_lease_time:
867 case expr_dns_transaction:
868 case expr_add:
869 case expr_subtract:
870 case expr_multiply:
871 case expr_divide:
872 case expr_remainder:
873 case expr_binary_and:
874 case expr_binary_or:
875 case expr_binary_xor:
876 case expr_client_state:
877 log_error ("Numeric opcode in evaluate_dns_expression: %d",
878 expr -> op);
879 return 0;
881 case expr_function:
882 log_error ("Function opcode in evaluate_dns_expression: %d",
883 expr -> op);
884 return 0;
886 case expr_arg:
887 break;
890 log_error ("Bogus opcode in evaluate_dns_expression: %d",
891 expr -> op);
892 return 0;
894 #endif /* defined (NSUPDATE) */
896 int evaluate_boolean_expression (result, packet, lease, client_state,
897 in_options, cfg_options, scope, expr)
898 int *result;
899 struct packet *packet;
900 struct lease *lease;
901 struct client_state *client_state;
902 struct option_state *in_options;
903 struct option_state *cfg_options;
904 struct binding_scope **scope;
905 struct expression *expr;
907 struct data_string left;
908 // struct data_string right;
909 // struct data_string rrtype, rrname, rrdata;
910 // unsigned long ttl;
911 // int srrtype, srrname, srrdata;
912 // int sttl;
913 int bleft, bright;
914 int sleft, sright;
915 struct binding *binding;
916 struct binding_value *bv, *obv;
918 switch (expr -> op) {
919 case expr_check:
920 *result = check_collection (packet, lease,
921 expr -> data.check);
922 #if defined (DEBUG_EXPRESSIONS)
923 log_debug ("bool: check (%s) returns %s",
924 expr -> data.check -> name,
925 *result ? "true" : "false");
926 #endif
927 return 1;
929 case expr_equal:
930 case expr_not_equal:
931 bv = obv = (struct binding_value *)0;
932 sleft = evaluate_expression (&bv, packet, lease, client_state,
933 in_options, cfg_options, scope,
934 expr -> data.equal [0], MDL);
935 sright = evaluate_expression (&obv, packet, lease,
936 client_state, in_options,
937 cfg_options, scope,
938 expr -> data.equal [1], MDL);
939 if (sleft && sright) {
940 if (bv -> type != obv -> type)
941 *result = expr -> op == expr_not_equal;
942 else {
943 switch (obv -> type) {
944 case binding_boolean:
945 if (bv -> value.boolean == obv -> value.boolean)
946 *result = expr -> op == expr_equal;
947 else
948 *result = expr -> op == expr_not_equal;
949 break;
951 case binding_data:
952 if ((bv -> value.data.len ==
953 obv -> value.data.len) &&
954 !memcmp (bv -> value.data.data,
955 obv -> value.data.data,
956 obv -> value.data.len))
957 *result = expr -> op == expr_equal;
958 else
959 *result = expr -> op == expr_not_equal;
960 break;
962 case binding_numeric:
963 if (bv -> value.intval == obv -> value.intval)
964 *result = expr -> op == expr_equal;
965 else
966 *result = expr -> op == expr_not_equal;
967 break;
969 case binding_dns:
970 #if defined (NSUPDATE)
971 /* XXX This should be a comparison for equal
972 XXX values, not for identity. */
973 if (bv -> value.dns == obv -> value.dns)
974 *result = expr -> op == expr_equal;
975 else
976 *result = expr -> op == expr_not_equal;
977 #else
978 *result = expr -> op == expr_not_equal;
979 #endif
980 break;
982 case binding_function:
983 if (bv -> value.fundef == obv -> value.fundef)
984 *result = expr -> op == expr_equal;
985 else
986 *result = expr -> op == expr_not_equal;
987 break;
988 default:
989 *result = expr -> op == expr_not_equal;
990 break;
993 } else if (!sleft && !sright)
994 *result = expr -> op == expr_equal;
995 else
996 *result = expr -> op == expr_not_equal;
998 #if defined (DEBUG_EXPRESSIONS)
999 log_debug ("bool: %sequal = %s",
1000 expr -> op == expr_not_equal ? "not" : "",
1001 (*result ? "true" : "false"));
1002 #endif
1003 if (sleft)
1004 binding_value_dereference (&bv, MDL);
1005 if (sright)
1006 binding_value_dereference (&obv, MDL);
1007 return 1;
1009 case expr_and:
1010 sleft = evaluate_boolean_expression (&bleft, packet, lease,
1011 client_state,
1012 in_options, cfg_options,
1013 scope,
1014 expr -> data.and [0]);
1015 if (sleft && bleft)
1016 sright = evaluate_boolean_expression
1017 (&bright, packet, lease, client_state,
1018 in_options, cfg_options,
1019 scope, expr -> data.and [1]);
1020 else
1021 sright = bright = 0;
1023 #if defined (DEBUG_EXPRESSIONS)
1024 log_debug ("bool: and (%s, %s) = %s",
1025 sleft ? (bleft ? "true" : "false") : "NULL",
1026 sright ? (bright ? "true" : "false") : "NULL",
1027 ((sleft && sright)
1028 ? (bleft && bright ? "true" : "false") : "NULL"));
1029 #endif
1030 if (sleft && sright) {
1031 *result = bleft && bright;
1032 return 1;
1034 return 0;
1036 case expr_or:
1037 bleft = bright = 0;
1038 sleft = evaluate_boolean_expression (&bleft, packet, lease,
1039 client_state,
1040 in_options, cfg_options,
1041 scope,
1042 expr -> data.or [0]);
1043 if (!sleft || !bleft)
1044 sright = evaluate_boolean_expression
1045 (&bright, packet, lease, client_state,
1046 in_options, cfg_options,
1047 scope, expr -> data.or [1]);
1048 else
1049 sright = 0;
1050 #if defined (DEBUG_EXPRESSIONS)
1051 log_debug ("bool: or (%s, %s) = %s",
1052 sleft ? (bleft ? "true" : "false") : "NULL",
1053 sright ? (bright ? "true" : "false") : "NULL",
1054 ((sleft || sright)
1055 ? (bleft || bright ? "true" : "false") : "NULL"));
1056 #endif
1057 if (sleft || sright) {
1058 *result = bleft || bright;
1059 return 1;
1061 return 0;
1063 case expr_not:
1064 sleft = evaluate_boolean_expression (&bleft, packet, lease,
1065 client_state,
1066 in_options, cfg_options,
1067 scope,
1068 expr -> data.not);
1069 #if defined (DEBUG_EXPRESSIONS)
1070 log_debug ("bool: not (%s) = %s",
1071 sleft ? (bleft ? "true" : "false") : "NULL",
1072 ((sleft && sright)
1073 ? (!bleft ? "true" : "false") : "NULL"));
1075 #endif
1076 if (sleft) {
1077 *result = !bleft;
1078 return 1;
1080 return 0;
1082 case expr_exists:
1083 memset (&left, 0, sizeof left);
1084 if (!in_options ||
1085 !get_option (&left, expr -> data.exists -> universe,
1086 packet, lease, client_state,
1087 in_options, cfg_options, in_options,
1088 scope, expr -> data.exists -> code, MDL))
1089 *result = 0;
1090 else {
1091 *result = 1;
1092 data_string_forget (&left, MDL);
1094 #if defined (DEBUG_EXPRESSIONS)
1095 log_debug ("bool: exists %s.%s = %s",
1096 expr -> data.option -> universe -> name,
1097 expr -> data.option -> name,
1098 *result ? "true" : "false");
1099 #endif
1100 return 1;
1102 case expr_known:
1103 if (!packet) {
1104 #if defined (DEBUG_EXPRESSIONS)
1105 log_debug ("bool: known = NULL");
1106 #endif
1107 return 0;
1109 #if defined (DEBUG_EXPRESSIONS)
1110 log_debug ("bool: known = %s",
1111 packet -> known ? "true" : "false");
1112 #endif
1113 *result = packet -> known;
1114 return 1;
1116 case expr_static:
1117 if (!lease || !(lease -> flags & STATIC_LEASE)) {
1118 #if defined (DEBUG_EXPRESSIONS)
1119 log_debug ("bool: static = false (%s %s %s %d)",
1120 lease ? "y" : "n",
1121 (lease && (lease -> flags & STATIC_LEASE)
1122 ? "y" : "n"),
1123 piaddr (lease -> ip_addr),
1124 lease ? lease -> flags : 0);
1125 #endif
1126 *result = 0;
1127 return 1;
1129 #if defined (DEBUG_EXPRESSIONS)
1130 log_debug ("bool: static = true");
1131 #endif
1132 *result = 1;
1133 return 1;
1135 case expr_variable_exists:
1136 if (scope && *scope) {
1137 binding = find_binding (*scope, expr -> data.variable);
1139 if (binding) {
1140 if (binding -> value)
1141 *result = 1;
1142 else
1143 *result = 0;
1144 } else
1145 *result = 0;
1146 } else
1147 *result = 0;
1148 #if defined (DEBUG_EXPRESSIONS)
1149 log_debug ("boolean: %s? = %s", expr -> data.variable,
1150 *result ? "true" : "false");
1151 #endif
1152 return 1;
1154 case expr_variable_reference:
1155 if (scope && *scope) {
1156 binding = find_binding (*scope, expr -> data.variable);
1158 if (binding && binding -> value) {
1159 if (binding -> value -> type ==
1160 binding_boolean) {
1161 *result = binding -> value -> value.boolean;
1162 sleft = 1;
1163 } else {
1164 log_error ("binding type %d in %s.",
1165 binding -> value -> type,
1166 "evaluate_boolean_expression");
1167 sleft = 0;
1169 } else
1170 sleft = 0;
1171 } else
1172 sleft = 0;
1173 #if defined (DEBUG_EXPRESSIONS)
1174 log_debug ("boolean: %s = %s", expr -> data.variable,
1175 sleft ? (*result ? "true" : "false") : "NULL");
1176 #endif
1177 return sleft;
1179 case expr_funcall:
1180 bv = (struct binding_value *)0;
1181 sleft = evaluate_expression (&bv, packet, lease, client_state,
1182 in_options, cfg_options,
1183 scope, expr, MDL);
1184 if (sleft) {
1185 if (bv -> type != binding_boolean)
1186 log_error ("%s() returned type %d in %s.",
1187 expr -> data.funcall.name,
1188 bv -> type,
1189 "evaluate_boolean_expression");
1190 else
1191 *result = bv -> value.boolean;
1192 binding_value_dereference (&bv, MDL);
1194 #if defined (DEBUG_EXPRESSIONS)
1195 log_debug ("boolean: %s() = %s", expr -> data.funcall.name,
1196 sleft ? (*result ? "true" : "false") : "NULL");
1197 #endif
1198 break;
1200 case expr_none:
1201 case expr_match:
1202 case expr_substring:
1203 case expr_suffix:
1204 case expr_option:
1205 case expr_hardware:
1206 case expr_const_data:
1207 case expr_packet:
1208 case expr_concat:
1209 case expr_encapsulate:
1210 case expr_host_lookup:
1211 case expr_encode_int8:
1212 case expr_encode_int16:
1213 case expr_encode_int32:
1214 case expr_binary_to_ascii:
1215 case expr_reverse:
1216 case expr_pick_first_value:
1217 case expr_host_decl_name:
1218 case expr_config_option:
1219 case expr_leased_address:
1220 case expr_null:
1221 case expr_filename:
1222 case expr_sname:
1223 log_error ("Data opcode in evaluate_boolean_expression: %d",
1224 expr -> op);
1225 return 0;
1227 case expr_extract_int8:
1228 case expr_extract_int16:
1229 case expr_extract_int32:
1230 case expr_const_int:
1231 case expr_lease_time:
1232 case expr_dns_transaction:
1233 case expr_add:
1234 case expr_subtract:
1235 case expr_multiply:
1236 case expr_divide:
1237 case expr_remainder:
1238 case expr_binary_and:
1239 case expr_binary_or:
1240 case expr_binary_xor:
1241 case expr_client_state:
1242 log_error ("Numeric opcode in evaluate_boolean_expression: %d",
1243 expr -> op);
1244 return 0;
1246 case expr_ns_add:
1247 case expr_ns_delete:
1248 case expr_ns_exists:
1249 case expr_ns_not_exists:
1250 log_error ("dns opcode in evaluate_boolean_expression: %d",
1251 expr -> op);
1252 return 0;
1254 case expr_function:
1255 log_error ("function definition in evaluate_boolean_expr");
1256 return 0;
1258 case expr_arg:
1259 break;
1262 log_error ("Bogus opcode in evaluate_boolean_expression: %d",
1263 expr -> op);
1264 return 0;
1267 int evaluate_data_expression (result, packet, lease, client_state,
1268 in_options, cfg_options, scope, expr, file, line)
1269 struct data_string *result;
1270 struct packet *packet;
1271 struct lease *lease;
1272 struct client_state *client_state;
1273 struct option_state *in_options;
1274 struct option_state *cfg_options;
1275 struct binding_scope **scope;
1276 struct expression *expr;
1277 const char *file;
1278 int line;
1280 struct data_string data, other;
1281 unsigned long offset, len;
1282 // unsigned long i;
1283 int s0, s1, s2, s3;
1284 int status;
1285 struct binding *binding;
1286 // char *s;
1287 struct binding_value *bv;
1289 switch (expr -> op) {
1290 /* Extract N bytes starting at byte M of a data string. */
1291 case expr_substring:
1292 memset (&data, 0, sizeof data);
1293 s0 = evaluate_data_expression (&data, packet, lease,
1294 client_state,
1295 in_options, cfg_options, scope,
1296 expr -> data.substring.expr,
1297 MDL);
1299 /* Evaluate the offset and length. */
1300 s1 = evaluate_numeric_expression
1301 (&offset, packet, lease, client_state, in_options,
1302 cfg_options, scope, expr -> data.substring.offset);
1303 s2 = evaluate_numeric_expression (&len, packet, lease,
1304 client_state,
1305 in_options, cfg_options,
1306 scope,
1307 expr -> data.substring.len);
1309 if (s0 && s1 && s2) {
1310 /* If the offset is after end of the string,
1311 return an empty string. Otherwise, do the
1312 adjustments and return what's left. */
1313 if (data.len > offset) {
1314 data_string_copy (result, &data, file, line);
1315 result -> len -= offset;
1316 if (result -> len > len) {
1317 result -> len = len;
1318 result -> terminated = 0;
1320 result -> data += offset;
1322 s3 = 1;
1323 } else
1324 s3 = 0;
1326 #if defined (DEBUG_EXPRESSIONS)
1327 log_debug ("data: substring (%s, %s, %s) = %s",
1328 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1329 s1 ? print_dec_1 (offset) : "NULL",
1330 s2 ? print_dec_2 (len) : "NULL",
1331 (s3 ? print_hex_2 (result -> len, result -> data, 30)
1332 : "NULL"));
1333 #endif
1334 if (s0)
1335 data_string_forget (&data, MDL);
1336 if (s3)
1337 return 1;
1338 return 0;
1341 /* Extract the last N bytes of a data string. */
1342 case expr_suffix:
1343 memset (&data, 0, sizeof data);
1344 s0 = evaluate_data_expression (&data, packet, lease,
1345 client_state,
1346 in_options, cfg_options, scope,
1347 expr -> data.suffix.expr, MDL);
1348 /* Evaluate the length. */
1349 s1 = evaluate_numeric_expression (&len, packet, lease,
1350 client_state,
1351 in_options, cfg_options,
1352 scope,
1353 expr -> data.suffix.len);
1354 if (s0 && s1) {
1355 data_string_copy (result, &data, file, line);
1357 /* If we are returning the last N bytes of a
1358 string whose length is <= N, just return
1359 the string - otherwise, compute a new
1360 starting address and decrease the
1361 length. */
1362 if (data.len > len) {
1363 result -> data += data.len - len;
1364 result -> len = len;
1366 data_string_forget (&data, MDL);
1369 #if defined (DEBUG_EXPRESSIONS)
1370 log_debug ("data: suffix (%s, %s) = %s",
1371 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1372 s1 ? print_dec_1 (len) : "NULL",
1373 ((s0 && s1)
1374 ? print_hex_2 (result -> len, result -> data, 30)
1375 : "NULL"));
1376 #endif
1377 return s0 && s1;
1379 /* Extract an option. */
1380 case expr_option:
1381 if (in_options)
1382 s0 = get_option (result,
1383 expr -> data.option -> universe,
1384 packet, lease, client_state,
1385 in_options, cfg_options, in_options,
1386 scope, expr -> data.option -> code,
1387 file, line);
1388 else
1389 s0 = 0;
1391 #if defined (DEBUG_EXPRESSIONS)
1392 log_debug ("data: option %s.%s = %s",
1393 expr -> data.option -> universe -> name,
1394 expr -> data.option -> name,
1395 s0 ? print_hex_1 (result -> len, result -> data, 60)
1396 : "NULL");
1397 #endif
1398 return s0;
1400 case expr_config_option:
1401 if (cfg_options)
1402 s0 = get_option (result,
1403 expr -> data.option -> universe,
1404 packet, lease, client_state,
1405 in_options, cfg_options, cfg_options,
1406 scope, expr -> data.option -> code,
1407 file, line);
1408 else
1409 s0 = 0;
1411 #if defined (DEBUG_EXPRESSIONS)
1412 log_debug ("data: config-option %s.%s = %s",
1413 expr -> data.option -> universe -> name,
1414 expr -> data.option -> name,
1415 s0 ? print_hex_1 (result -> len, result -> data, 60)
1416 : "NULL");
1417 #endif
1418 return s0;
1420 /* Combine the hardware type and address. */
1421 case expr_hardware:
1422 /* On the client, hardware is our hardware. */
1423 if (client_state) {
1424 memset (result, 0, sizeof *result);
1425 result -> data =
1426 client_state -> interface -> hw_address.hbuf;
1427 result -> len =
1428 client_state -> interface -> hw_address.hlen;
1429 #if defined (DEBUG_EXPRESSIONS)
1430 log_debug ("data: hardware = %s",
1431 print_hex_1 (result -> len,
1432 result -> data, 60));
1433 #endif
1434 return 1;
1437 /* The server cares about the client's hardware address,
1438 so only in the case where we are examining a packet can
1439 we return anything. */
1440 if (!packet || !packet -> raw) {
1441 log_error ("data: hardware: raw packet not available");
1442 return 0;
1444 if (packet -> raw -> hlen > sizeof packet -> raw -> chaddr) {
1445 log_error ("data: hardware: invalid hlen (%d)\n",
1446 packet -> raw -> hlen);
1447 return 0;
1449 result -> len = packet -> raw -> hlen + 1;
1450 if (buffer_allocate (&result -> buffer, result -> len,
1451 file, line)) {
1452 result -> data = &result -> buffer -> data [0];
1453 result -> buffer -> data [0] = packet -> raw -> htype;
1454 memcpy (&result -> buffer -> data [1],
1455 packet -> raw -> chaddr,
1456 packet -> raw -> hlen);
1457 result -> terminated = 0;
1458 } else {
1459 log_error ("data: hardware: no memory for buffer.");
1460 return 0;
1462 #if defined (DEBUG_EXPRESSIONS)
1463 log_debug ("data: hardware = %s",
1464 print_hex_1 (result -> len, result -> data, 60));
1465 #endif
1466 return 1;
1468 /* Extract part of the raw packet. */
1469 case expr_packet:
1470 if (!packet || !packet -> raw) {
1471 log_error ("data: packet: raw packet not available");
1472 return 0;
1475 s0 = evaluate_numeric_expression (&offset, packet, lease,
1476 client_state,
1477 in_options, cfg_options,
1478 scope,
1479 expr -> data.packet.offset);
1480 s1 = evaluate_numeric_expression (&len,
1481 packet, lease, client_state,
1482 in_options, cfg_options,
1483 scope,
1484 expr -> data.packet.len);
1485 if (s0 && s1 && offset < packet -> packet_length) {
1486 if (offset + len > packet -> packet_length)
1487 result -> len =
1488 packet -> packet_length - offset;
1489 else
1490 result -> len = len;
1491 if (buffer_allocate (&result -> buffer,
1492 result -> len, file, line)) {
1493 result -> data = &result -> buffer -> data [0];
1494 memcpy (result -> buffer -> data,
1495 (((unsigned char *)(packet -> raw))
1496 + offset), result -> len);
1497 result -> terminated = 0;
1498 } else {
1499 log_error ("data: packet: no buffer memory.");
1500 return 0;
1502 s2 = 1;
1503 } else
1504 s2 = 0;
1505 #if defined (DEBUG_EXPRESSIONS)
1506 log_debug ("data: packet (%ld, %ld) = %s",
1507 offset, len,
1508 s2 ? print_hex_1 (result -> len,
1509 result -> data, 60) : NULL);
1510 #endif
1511 return s2;
1513 /* The encapsulation of all defined options in an
1514 option space... */
1515 case expr_encapsulate:
1516 if (cfg_options)
1517 s0 = option_space_encapsulate
1518 (result, packet, lease, client_state,
1519 in_options, cfg_options, scope,
1520 &expr -> data.encapsulate);
1521 else
1522 s0 = 0;
1524 #if defined (DEBUG_EXPRESSIONS)
1525 log_debug ("data: encapsulate (%s) = %s",
1526 expr -> data.encapsulate.data,
1527 s0 ? print_hex_1 (result -> len,
1528 result -> data, 60) : "NULL");
1529 #endif
1530 return s0;
1532 /* Some constant data... */
1533 case expr_const_data:
1534 #if defined (DEBUG_EXPRESSIONS)
1535 log_debug ("data: const = %s",
1536 print_hex_1 (expr -> data.const_data.len,
1537 expr -> data.const_data.data, 60));
1538 #endif
1539 data_string_copy (result,
1540 &expr -> data.const_data, file, line);
1541 return 1;
1543 /* Hostname lookup... */
1544 case expr_host_lookup:
1545 s0 = do_host_lookup (result, expr -> data.host_lookup);
1546 #if defined (DEBUG_EXPRESSIONS)
1547 log_debug ("data: DNS lookup (%s) = %s",
1548 expr -> data.host_lookup -> hostname,
1550 ? print_dotted_quads (result -> len, result -> data)
1551 : "NULL"));
1552 #endif
1553 return s0;
1555 /* Concatenation... */
1556 case expr_concat:
1557 memset (&data, 0, sizeof data);
1558 s0 = evaluate_data_expression (&data, packet, lease,
1559 client_state,
1560 in_options, cfg_options, scope,
1561 expr -> data.concat [0], MDL);
1562 memset (&other, 0, sizeof other);
1563 s1 = evaluate_data_expression (&other, packet, lease,
1564 client_state,
1565 in_options, cfg_options, scope,
1566 expr -> data.concat [1], MDL);
1568 if (s0 && s1) {
1569 result -> len = data.len + other.len;
1570 if (!buffer_allocate (&result -> buffer,
1571 (result -> len + other.terminated),
1572 file, line)) {
1573 log_error ("data: concat: no memory");
1574 result -> len = 0;
1575 data_string_forget (&data, MDL);
1576 data_string_forget (&other, MDL);
1577 return 0;
1579 result -> data = &result -> buffer -> data [0];
1580 memcpy (result -> buffer -> data, data.data, data.len);
1581 memcpy (&result -> buffer -> data [data.len],
1582 other.data, other.len + other.terminated);
1585 if (s0)
1586 data_string_forget (&data, MDL);
1587 if (s1)
1588 data_string_forget (&other, MDL);
1589 #if defined (DEBUG_EXPRESSIONS)
1590 log_debug ("data: concat (%s, %s) = %s",
1591 s0 ? print_hex_1 (data.len, data.data, 20) : "NULL",
1592 s1 ? print_hex_2 (other.len, other.data, 20) : "NULL",
1593 ((s0 && s1)
1594 ? print_hex_3 (result -> len, result -> data, 30)
1595 : "NULL"));
1596 #endif
1597 return s0 && s1;
1599 case expr_encode_int8:
1600 s0 = evaluate_numeric_expression (&len, packet, lease,
1601 client_state,
1602 in_options, cfg_options,
1603 scope,
1604 expr -> data.encode_int);
1605 if (s0) {
1606 result -> len = 1;
1607 if (!buffer_allocate (&result -> buffer,
1608 1, file, line)) {
1609 log_error ("data: encode_int8: no memory");
1610 result -> len = 0;
1611 s0 = 0;
1612 } else {
1613 result -> data = &result -> buffer -> data [0];
1614 result -> buffer -> data [0] = len;
1616 } else
1617 result -> len = 0;
1619 #if defined (DEBUG_EXPRESSIONS)
1620 if (!s0)
1621 log_debug ("data: encode_int8 (NULL) = NULL");
1622 else
1623 log_debug ("data: encode_int8 (%ld) = %s", len,
1624 print_hex_2 (result -> len,
1625 result -> data, 20));
1626 #endif
1627 return s0;
1630 case expr_encode_int16:
1631 s0 = evaluate_numeric_expression (&len, packet, lease,
1632 client_state,
1633 in_options, cfg_options,
1634 scope,
1635 expr -> data.encode_int);
1636 if (s0) {
1637 result -> len = 2;
1638 if (!buffer_allocate (&result -> buffer, 2,
1639 file, line)) {
1640 log_error ("data: encode_int16: no memory");
1641 result -> len = 0;
1642 s0 = 0;
1643 } else {
1644 result -> data = &result -> buffer -> data [0];
1645 putUShort (result -> buffer -> data, len);
1647 } else
1648 result -> len = 0;
1650 #if defined (DEBUG_EXPRESSIONS)
1651 if (!s0)
1652 log_debug ("data: encode_int16 (NULL) = NULL");
1653 else
1654 log_debug ("data: encode_int16 (%ld) = %s", len,
1655 print_hex_2 (result -> len,
1656 result -> data, 20));
1657 #endif
1658 return s0;
1660 case expr_encode_int32:
1661 s0 = evaluate_numeric_expression (&len, packet, lease,
1662 client_state,
1663 in_options, cfg_options,
1664 scope,
1665 expr -> data.encode_int);
1666 if (s0) {
1667 result -> len = 4;
1668 if (!buffer_allocate (&result -> buffer, 4,
1669 file, line)) {
1670 log_error ("data: encode_int32: no memory");
1671 result -> len = 0;
1672 s0 = 0;
1673 } else {
1674 result -> data = &result -> buffer -> data [0];
1675 putULong (result -> buffer -> data, len);
1677 } else
1678 result -> len = 0;
1680 #if defined (DEBUG_EXPRESSIONS)
1681 if (!s0)
1682 log_debug ("data: encode_int32 (NULL) = NULL");
1683 else
1684 log_debug ("data: encode_int32 (%ld) = %s", len,
1685 print_hex_2 (result -> len,
1686 result -> data, 20));
1687 #endif
1688 return s0;
1690 case expr_binary_to_ascii:
1691 /* Evaluate the base (offset) and width (len): */
1692 s0 = evaluate_numeric_expression
1693 (&offset, packet, lease, client_state, in_options,
1694 cfg_options, scope, expr -> data.b2a.base);
1695 s1 = evaluate_numeric_expression (&len, packet, lease,
1696 client_state,
1697 in_options, cfg_options,
1698 scope,
1699 expr -> data.b2a.width);
1701 /* Evaluate the seperator string. */
1702 memset (&data, 0, sizeof data);
1703 s2 = evaluate_data_expression (&data, packet, lease,
1704 client_state,
1705 in_options, cfg_options, scope,
1706 expr -> data.b2a.seperator,
1707 MDL);
1709 /* Evaluate the data to be converted. */
1710 memset (&other, 0, sizeof other);
1711 s3 = evaluate_data_expression (&other, packet, lease,
1712 client_state,
1713 in_options, cfg_options, scope,
1714 expr -> data.b2a.buffer, MDL);
1716 if (s0 && s1 && s2 && s3) {
1717 unsigned buflen, i;
1719 if (len != 8 && len != 16 && len != 32) {
1720 log_info ("binary_to_ascii: %s %ld!",
1721 "invalid width", len);
1722 status = 0;
1723 goto b2a_out;
1725 len /= 8;
1727 /* The buffer must be a multiple of the number's
1728 width. */
1729 if (other.len % len) {
1730 log_info ("binary-to-ascii: %s %d %s %ld!",
1731 "length of buffer", other.len,
1732 "not a multiple of width", len);
1733 status = 0;
1734 goto b2a_out;
1737 /* Count the width of the output. */
1738 buflen = 0;
1739 for (i = 0; i < other.len; i += len) {
1740 if (len == 1) {
1741 if (offset == 8) {
1742 if (other.data [i] < 8)
1743 buflen++;
1744 else if (other.data [i] < 64)
1745 buflen += 2;
1746 else
1747 buflen += 3;
1748 } else if (offset == 10) {
1749 if (other.data [i] < 10)
1750 buflen++;
1751 else if (other.data [i] < 100)
1752 buflen += 2;
1753 else
1754 buflen += 3;
1755 } else if (offset == 16) {
1756 if (other.data [i] < 16)
1757 buflen++;
1758 else
1759 buflen += 2;
1760 } else
1761 buflen += (converted_length
1762 (&other.data [i],
1763 offset, 1));
1764 } else
1765 buflen += (converted_length
1766 (&other.data [i],
1767 offset, len));
1768 if (i + len != other.len)
1769 buflen += data.len;
1772 if (!buffer_allocate (&result -> buffer,
1773 buflen + 1, file, line)) {
1774 log_error ("data: binary-to-ascii: no memory");
1775 status = 0;
1776 goto b2a_out;
1778 result -> data = &result -> buffer -> data [0];
1779 result -> len = buflen;
1780 result -> terminated = 1;
1782 buflen = 0;
1783 for (i = 0; i < other.len; i += len) {
1784 buflen += (binary_to_ascii
1785 (&result -> buffer -> data [buflen],
1786 &other.data [i], offset, len));
1787 if (i + len != other.len) {
1788 memcpy (&result ->
1789 buffer -> data [buflen],
1790 data.data, data.len);
1791 buflen += data.len;
1794 /* NUL terminate. */
1795 result -> buffer -> data [buflen] = 0;
1796 status = 1;
1797 } else
1798 status = 0;
1800 b2a_out:
1801 #if defined (DEBUG_EXPRESSIONS)
1802 log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
1803 s0 ? print_dec_1 (offset) : "NULL",
1804 s1 ? print_dec_2 (len) : "NULL",
1805 s2 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1806 s3 ? print_hex_2 (other.len, other.data, 30) : "NULL",
1807 (status ? print_hex_3 (result -> len, result -> data, 30)
1808 : "NULL"));
1809 #endif
1810 if (s2)
1811 data_string_forget (&data, MDL);
1812 if (s3)
1813 data_string_forget (&other, MDL);
1814 if (status)
1815 return 1;
1816 return 0;
1818 case expr_reverse:
1819 /* Evaluate the width (len): */
1820 s0 = evaluate_numeric_expression
1821 (&len, packet, lease, client_state, in_options,
1822 cfg_options, scope, expr -> data.reverse.width);
1824 /* Evaluate the data. */
1825 memset (&data, 0, sizeof data);
1826 s1 = evaluate_data_expression (&data, packet, lease,
1827 client_state,
1828 in_options, cfg_options, scope,
1829 expr -> data.reverse.buffer,
1830 MDL);
1832 if (s0 && s1) {
1833 // char *upper;
1834 int i;
1836 /* The buffer must be a multiple of the number's
1837 width. */
1838 if (data.len % len) {
1839 log_info ("reverse: %s %d %s %ld!",
1840 "length of buffer", data.len,
1841 "not a multiple of width", len);
1842 status = 0;
1843 goto reverse_out;
1846 /* XXX reverse in place? I don't think we can. */
1847 if (!buffer_allocate (&result -> buffer,
1848 data.len, file, line)) {
1849 log_error ("data: reverse: no memory");
1850 status = 0;
1851 goto reverse_out;
1853 result -> data = &result -> buffer -> data [0];
1854 result -> len = data.len;
1855 result -> terminated = 0;
1857 for (i = 0; i < data.len; i += len) {
1858 memcpy (&result -> buffer -> data [i],
1859 &data.data [data.len - i - len], len);
1861 status = 1;
1862 } else
1863 status = 0;
1865 reverse_out:
1866 #if defined (DEBUG_EXPRESSIONS)
1867 log_debug ("data: reverse (%s, %s) = %s",
1868 s0 ? print_dec_1 (len) : "NULL",
1869 s1 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1870 (status ? print_hex_3 (result -> len, result -> data, 30)
1871 : "NULL"));
1872 #endif
1873 if (s0)
1874 data_string_forget (&data, MDL);
1875 if (status)
1876 return 1;
1877 return 0;
1879 case expr_leased_address:
1880 if (!lease) {
1881 log_error ("data: leased_address: not available");
1882 return 0;
1884 result -> len = lease -> ip_addr.len;
1885 if (buffer_allocate (&result -> buffer, result -> len,
1886 file, line)) {
1887 result -> data = &result -> buffer -> data [0];
1888 memcpy (&result -> buffer -> data [0],
1889 lease -> ip_addr.iabuf, lease -> ip_addr.len);
1890 result -> terminated = 0;
1891 } else {
1892 log_error ("data: leased-address: no memory.");
1893 return 0;
1895 #if defined (DEBUG_EXPRESSIONS)
1896 log_debug ("data: leased-address = %s",
1897 print_hex_1 (result -> len, result -> data, 60));
1898 #endif
1899 return 1;
1901 case expr_pick_first_value:
1902 memset (&data, 0, sizeof data);
1903 if ((evaluate_data_expression
1904 (result, packet,
1905 lease, client_state, in_options, cfg_options,
1906 scope, expr -> data.pick_first_value.car, MDL))) {
1907 #if defined (DEBUG_EXPRESSIONS)
1908 log_debug ("data: pick_first_value (%s, xxx)",
1909 print_hex_1 (result -> len,
1910 result -> data, 40));
1911 #endif
1912 return 1;
1915 if (expr -> data.pick_first_value.cdr &&
1916 (evaluate_data_expression
1917 (result, packet,
1918 lease, client_state, in_options, cfg_options,
1919 scope, expr -> data.pick_first_value.cdr, MDL))) {
1920 #if defined (DEBUG_EXPRESSIONS)
1921 log_debug ("data: pick_first_value (NULL, %s)",
1922 print_hex_1 (result -> len,
1923 result -> data, 40));
1924 #endif
1925 return 1;
1928 #if defined (DEBUG_EXPRESSIONS)
1929 log_debug ("data: pick_first_value (NULL, NULL) = NULL");
1930 #endif
1931 return 0;
1933 case expr_host_decl_name:
1934 if (!lease || !lease -> host) {
1935 log_error ("data: host_decl_name: not available");
1936 return 0;
1938 result -> len = strlen (lease -> host -> name);
1939 if (buffer_allocate (&result -> buffer,
1940 result -> len + 1, file, line)) {
1941 result -> data = &result -> buffer -> data [0];
1942 strcpy ((char *)&result -> buffer -> data [0],
1943 lease -> host -> name);
1944 result -> terminated = 1;
1945 } else {
1946 log_error ("data: host-decl-name: no memory.");
1947 return 0;
1949 #if defined (DEBUG_EXPRESSIONS)
1950 log_debug ("data: host-decl-name = %s", lease -> host -> name);
1951 #endif
1952 return 1;
1954 case expr_null:
1955 #if defined (DEBUG_EXPRESSIONS)
1956 log_debug ("data: null = NULL");
1957 #endif
1958 return 0;
1960 case expr_variable_reference:
1961 if (scope && *scope) {
1962 binding = find_binding (*scope, expr -> data.variable);
1964 if (binding && binding -> value) {
1965 if (binding -> value -> type == binding_data) {
1966 data_string_copy (result,
1967 &binding -> value -> value.data,
1968 file, line);
1969 s0 = 1;
1970 } else if (binding -> value -> type != binding_data) {
1971 log_error ("binding type %d in %s.",
1972 binding -> value -> type,
1973 "evaluate_data_expression");
1974 s0 = 0;
1975 } else
1976 s0 = 0;
1977 } else
1978 s0 = 0;
1979 } else
1980 s0 = 0;
1981 #if defined (DEBUG_EXPRESSIONS)
1982 log_debug ("data: %s = %s", expr -> data.variable,
1983 s0 ? print_hex_1 (result -> len,
1984 result -> data, 50) : "NULL");
1985 #endif
1986 return s0;
1988 case expr_funcall:
1989 bv = (struct binding_value *)0;
1990 s0 = evaluate_expression (&bv, packet, lease, client_state,
1991 in_options, cfg_options,
1992 scope, expr, MDL);
1993 if (s0) {
1994 if (bv -> type != binding_data)
1995 log_error ("%s() returned type %d in %s.",
1996 expr -> data.funcall.name,
1997 bv -> type,
1998 "evaluate_data_expression");
1999 else
2000 data_string_copy (result, &bv -> value.data,
2001 file, line);
2002 binding_value_dereference (&bv, MDL);
2004 #if defined (DEBUG_EXPRESSIONS)
2005 log_debug ("data: %s = %s", expr -> data.funcall.name,
2006 s0 ? print_hex_1 (result -> len,
2007 result -> data, 50) : "NULL");
2008 #endif
2009 break;
2011 /* Extract the filename. */
2012 case expr_filename:
2013 if (packet && packet -> raw -> file [0]) {
2014 char *fn =
2015 memchr (packet -> raw -> file, 0,
2016 sizeof packet -> raw -> file);
2017 if (!fn)
2018 fn = ((char *)packet -> raw -> file +
2019 sizeof packet -> raw -> file);
2020 result -> len = fn - &(packet -> raw -> file [0]);
2021 if (buffer_allocate (&result -> buffer,
2022 result -> len + 1, file, line)) {
2023 result -> data = &result -> buffer -> data [0];
2024 memcpy (&result -> buffer -> data [0],
2025 packet -> raw -> file,
2026 result -> len);
2027 result -> buffer -> data [result -> len] = 0;
2028 result -> terminated = 1;
2029 s0 = 1;
2030 } else {
2031 log_error ("data: filename: no memory.");
2032 s0 = 0;
2034 } else
2035 s0 = 0;
2037 #if defined (DEBUG_EXPRESSIONS)
2038 log_info ("data: filename = \"%s\"",
2039 s0 ? (const char *)(result -> data) : "NULL");
2040 #endif
2041 return s0;
2043 /* Extract the server name. */
2044 case expr_sname:
2045 if (packet && packet -> raw -> sname [0]) {
2046 char *fn =
2047 memchr (packet -> raw -> sname, 0,
2048 sizeof packet -> raw -> sname);
2049 if (!fn)
2050 fn = ((char *)packet -> raw -> sname +
2051 sizeof packet -> raw -> sname);
2052 result -> len = fn - &packet -> raw -> sname [0];
2053 if (buffer_allocate (&result -> buffer,
2054 result -> len + 1, file, line)) {
2055 result -> data = &result -> buffer -> data [0];
2056 memcpy (&result -> buffer -> data [0],
2057 packet -> raw -> sname,
2058 result -> len);
2059 result -> buffer -> data [result -> len] = 0;
2060 result -> terminated = 1;
2061 s0 = 1;
2062 } else {
2063 log_error ("data: sname: no memory.");
2064 s0 = 0;
2066 } else
2067 s0 = 0;
2069 #if defined (DEBUG_EXPRESSIONS)
2070 log_info ("data: sname = \"%s\"",
2071 s0 ? (const char *)(result -> data) : "NULL");
2072 #endif
2073 return s0;
2075 case expr_check:
2076 case expr_equal:
2077 case expr_not_equal:
2078 case expr_and:
2079 case expr_or:
2080 case expr_not:
2081 case expr_match:
2082 case expr_static:
2083 case expr_known:
2084 case expr_none:
2085 case expr_exists:
2086 case expr_variable_exists:
2087 log_error ("Boolean opcode in evaluate_data_expression: %d",
2088 expr -> op);
2089 return 0;
2091 case expr_extract_int8:
2092 case expr_extract_int16:
2093 case expr_extract_int32:
2094 case expr_const_int:
2095 case expr_lease_time:
2096 case expr_dns_transaction:
2097 case expr_add:
2098 case expr_subtract:
2099 case expr_multiply:
2100 case expr_divide:
2101 case expr_remainder:
2102 case expr_binary_and:
2103 case expr_binary_or:
2104 case expr_binary_xor:
2105 case expr_client_state:
2106 log_error ("Numeric opcode in evaluate_data_expression: %d",
2107 expr -> op);
2108 return 0;
2110 case expr_ns_add:
2111 case expr_ns_delete:
2112 case expr_ns_exists:
2113 case expr_ns_not_exists:
2114 log_error ("dns update opcode in evaluate_data_expression: %d",
2115 expr -> op);
2116 return 0;
2118 case expr_function:
2119 log_error ("function definition in evaluate_data_expression");
2120 return 0;
2122 case expr_arg:
2123 break;
2126 log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op);
2127 return 0;
2130 int evaluate_numeric_expression (result, packet, lease, client_state,
2131 in_options, cfg_options, scope, expr)
2132 unsigned long *result;
2133 struct packet *packet;
2134 struct lease *lease;
2135 struct client_state *client_state;
2136 struct option_state *in_options;
2137 struct option_state *cfg_options;
2138 struct binding_scope **scope;
2139 struct expression *expr;
2141 struct data_string data;
2142 int status, sleft, sright;
2143 #if defined (NSUPDATE)
2144 ns_updrec *nut;
2145 ns_updque uq;
2146 #endif
2147 struct expression *cur, *next;
2148 struct binding *binding;
2149 struct binding_value *bv;
2150 unsigned long ileft, iright;
2152 switch (expr -> op) {
2153 case expr_check:
2154 case expr_equal:
2155 case expr_not_equal:
2156 case expr_and:
2157 case expr_or:
2158 case expr_not:
2159 case expr_match:
2160 case expr_static:
2161 case expr_known:
2162 case expr_none:
2163 case expr_exists:
2164 case expr_variable_exists:
2165 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
2166 expr -> op);
2167 return 0;
2169 case expr_substring:
2170 case expr_suffix:
2171 case expr_option:
2172 case expr_hardware:
2173 case expr_const_data:
2174 case expr_packet:
2175 case expr_concat:
2176 case expr_encapsulate:
2177 case expr_host_lookup:
2178 case expr_encode_int8:
2179 case expr_encode_int16:
2180 case expr_encode_int32:
2181 case expr_binary_to_ascii:
2182 case expr_reverse:
2183 case expr_filename:
2184 case expr_sname:
2185 case expr_pick_first_value:
2186 case expr_host_decl_name:
2187 case expr_config_option:
2188 case expr_leased_address:
2189 case expr_null:
2190 log_error ("Data opcode in evaluate_numeric_expression: %d",
2191 expr -> op);
2192 return 0;
2194 case expr_extract_int8:
2195 memset (&data, 0, sizeof data);
2196 status = evaluate_data_expression
2197 (&data, packet, lease, client_state, in_options,
2198 cfg_options, scope, expr -> data.extract_int, MDL);
2199 if (status)
2200 *result = data.data [0];
2201 #if defined (DEBUG_EXPRESSIONS)
2202 log_debug ("num: extract_int8 (%s) = %s",
2203 status ? print_hex_1 (data.len, data.data, 60) : "NULL",
2204 status ? print_dec_1 (*result) : "NULL" );
2205 #endif
2206 if (status) data_string_forget (&data, MDL);
2207 return status;
2209 case expr_extract_int16:
2210 memset (&data, 0, sizeof data);
2211 status = (evaluate_data_expression
2212 (&data, packet, lease, client_state, in_options,
2213 cfg_options, scope, expr -> data.extract_int, MDL));
2214 if (status && data.len >= 2)
2215 *result = getUShort (data.data);
2216 #if defined (DEBUG_EXPRESSIONS)
2217 log_debug ("num: extract_int16 (%s) = %ld",
2218 ((status && data.len >= 2) ?
2219 print_hex_1 (data.len, data.data, 60) : "NULL"),
2220 *result);
2221 #endif
2222 if (status) data_string_forget (&data, MDL);
2223 return (status && data.len >= 2);
2225 case expr_extract_int32:
2226 memset (&data, 0, sizeof data);
2227 status = (evaluate_data_expression
2228 (&data, packet, lease, client_state, in_options,
2229 cfg_options, scope, expr -> data.extract_int, MDL));
2230 if (status && data.len >= 4)
2231 *result = getULong (data.data);
2232 #if defined (DEBUG_EXPRESSIONS)
2233 log_debug ("num: extract_int32 (%s) = %ld",
2234 ((status && data.len >= 4) ?
2235 print_hex_1 (data.len, data.data, 60) : "NULL"),
2236 *result);
2237 #endif
2238 if (status) data_string_forget (&data, MDL);
2239 return (status && data.len >= 4);
2241 case expr_const_int:
2242 *result = expr -> data.const_int;
2243 #if defined (DEBUG_EXPRESSIONS)
2244 log_debug ("number: CONSTANT = %ld", *result);
2245 #endif
2246 return 1;
2248 case expr_lease_time:
2249 if (!lease) {
2250 log_error ("data: leased_lease: not available");
2251 return 0;
2253 if (lease -> ends < cur_time) {
2254 log_error ("%s %lu when it is now %lu",
2255 "data: lease_time: lease ends at",
2256 (long)(lease -> ends), (long)cur_time);
2257 return 0;
2259 *result = lease -> ends - cur_time;
2260 #if defined (DEBUG_EXPRESSIONS)
2261 log_debug ("number: lease-time = (%lu - %lu) = %ld",
2262 lease -> ends,
2263 cur_time, *result);
2264 #endif
2265 return 1;
2267 case expr_dns_transaction:
2268 #if !defined (NSUPDATE)
2269 return 0;
2270 #else
2271 if (!resolver_inited) {
2272 minires_ninit (&resolver_state);
2273 resolver_inited = 1;
2274 resolver_state.retrans = 1;
2275 resolver_state.retry = 1;
2277 ISC_LIST_INIT (uq);
2278 cur = expr;
2279 do {
2280 next = cur -> data.dns_transaction.cdr;
2281 nut = 0;
2282 status = (evaluate_dns_expression
2283 (&nut, packet,
2284 lease, client_state, in_options, cfg_options,
2285 scope, cur -> data.dns_transaction.car));
2286 if (!status)
2287 goto dns_bad;
2288 ISC_LIST_APPEND (uq, nut, r_link);
2289 cur = next;
2290 } while (next);
2292 /* Do the update and record the error code, if there was
2293 an error; otherwise set it to NOERROR. */
2294 *result = minires_nupdate (&resolver_state,
2295 ISC_LIST_HEAD (uq));
2296 status = 1;
2298 print_dns_status ((int)*result, &uq);
2300 dns_bad:
2301 while (!ISC_LIST_EMPTY (uq)) {
2302 ns_updrec *tmp = ISC_LIST_HEAD (uq);
2303 ISC_LIST_UNLINK (uq, tmp, r_link);
2304 if (tmp -> r_data_ephem) {
2305 dfree (tmp -> r_data_ephem, MDL);
2306 tmp -> r_data = (unsigned char *)0;
2307 tmp -> r_data_ephem = (unsigned char *)0;
2309 minires_freeupdrec (tmp);
2311 return status;
2312 #endif /* NSUPDATE */
2314 case expr_variable_reference:
2315 if (scope && *scope) {
2316 binding = find_binding (*scope, expr -> data.variable);
2318 if (binding && binding -> value) {
2319 if (binding -> value -> type == binding_numeric) {
2320 *result = binding -> value -> value.intval;
2321 status = 1;
2322 } else {
2323 log_error ("binding type %d in %s.",
2324 binding -> value -> type,
2325 "evaluate_numeric_expression");
2326 status = 0;
2328 } else
2329 status = 0;
2330 } else
2331 status = 0;
2332 #if defined (DEBUG_EXPRESSIONS)
2333 if (status)
2334 log_debug ("numeric: %s = %ld",
2335 expr -> data.variable, *result);
2336 else
2337 log_debug ("numeric: %s = NULL",
2338 expr -> data.variable);
2339 #endif
2340 return status;
2342 case expr_funcall:
2343 bv = (struct binding_value *)0;
2344 status = evaluate_expression (&bv, packet, lease,
2345 client_state,
2346 in_options, cfg_options,
2347 scope, expr, MDL);
2348 if (status) {
2349 if (bv -> type != binding_numeric)
2350 log_error ("%s() returned type %d in %s.",
2351 expr -> data.funcall.name,
2352 bv -> type,
2353 "evaluate_numeric_expression");
2354 else
2355 *result = bv -> value.intval;
2356 binding_value_dereference (&bv, MDL);
2358 #if defined (DEBUG_EXPRESSIONS)
2359 log_debug ("data: %s = %ld", expr -> data.funcall.name,
2360 status ? *result : 0);
2361 #endif
2362 break;
2364 case expr_add:
2365 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2366 client_state,
2367 in_options, cfg_options,
2368 scope,
2369 expr -> data.and [0]);
2370 sright = evaluate_numeric_expression (&iright, packet, lease,
2371 client_state,
2372 in_options, cfg_options,
2373 scope,
2374 expr -> data.and [1]);
2376 #if defined (DEBUG_EXPRESSIONS)
2377 if (sleft && sright)
2378 log_debug ("num: %ld + %ld = %ld",
2379 ileft, iright, ileft + iright);
2380 else if (sleft)
2381 log_debug ("num: %ld + NULL = NULL", ileft);
2382 else
2383 log_debug ("num: NULL + %ld = NULL", iright);
2384 #endif
2385 if (sleft && sright) {
2386 *result = ileft + iright;
2387 return 1;
2389 return 0;
2391 case expr_subtract:
2392 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2393 client_state,
2394 in_options, cfg_options,
2395 scope,
2396 expr -> data.and [0]);
2397 sright = evaluate_numeric_expression (&iright, packet, lease,
2398 client_state,
2399 in_options, cfg_options,
2400 scope,
2401 expr -> data.and [1]);
2403 #if defined (DEBUG_EXPRESSIONS)
2404 if (sleft && sright)
2405 log_debug ("num: %ld - %ld = %ld",
2406 ileft, iright, ileft - iright);
2407 else if (sleft)
2408 log_debug ("num: %ld - NULL = NULL", ileft);
2409 else
2410 log_debug ("num: NULL - %ld = NULL", iright);
2411 #endif
2412 if (sleft && sright) {
2413 *result = ileft - iright;
2414 return 1;
2416 return 0;
2418 case expr_multiply:
2419 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2420 client_state,
2421 in_options, cfg_options,
2422 scope,
2423 expr -> data.and [0]);
2424 sright = evaluate_numeric_expression (&iright, packet, lease,
2425 client_state,
2426 in_options, cfg_options,
2427 scope,
2428 expr -> data.and [1]);
2430 #if defined (DEBUG_EXPRESSIONS)
2431 if (sleft && sright)
2432 log_debug ("num: %ld * %ld = %ld",
2433 ileft, iright, ileft * iright);
2434 else if (sleft)
2435 log_debug ("num: %ld * NULL = NULL", ileft);
2436 else
2437 log_debug ("num: NULL * %ld = NULL", iright);
2438 #endif
2439 if (sleft && sright) {
2440 *result = ileft * iright;
2441 return 1;
2443 return 0;
2445 case expr_divide:
2446 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2447 client_state,
2448 in_options, cfg_options,
2449 scope,
2450 expr -> data.and [0]);
2451 sright = evaluate_numeric_expression (&iright, packet, lease,
2452 client_state,
2453 in_options, cfg_options,
2454 scope,
2455 expr -> data.and [1]);
2457 #if defined (DEBUG_EXPRESSIONS)
2458 if (sleft && sright) {
2459 if (iright != 0)
2460 log_debug ("num: %ld / %ld = %ld",
2461 ileft, iright, ileft / iright);
2462 else
2463 log_debug ("num: %ld / %ld = NULL",
2464 ileft, iright);
2465 } else if (sleft)
2466 log_debug ("num: %ld / NULL = NULL", ileft);
2467 else
2468 log_debug ("num: NULL / %ld = NULL", iright);
2469 #endif
2470 if (sleft && sright && iright) {
2471 *result = ileft / iright;
2472 return 1;
2474 return 0;
2476 case expr_remainder:
2477 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2478 client_state,
2479 in_options, cfg_options,
2480 scope,
2481 expr -> data.and [0]);
2482 sright = evaluate_numeric_expression (&iright, packet, lease,
2483 client_state,
2484 in_options, cfg_options,
2485 scope,
2486 expr -> data.and [1]);
2488 #if defined (DEBUG_EXPRESSIONS)
2489 if (sleft && sright) {
2490 if (iright != 0)
2491 log_debug ("num: %ld %% %ld = %ld",
2492 ileft, iright, ileft % iright);
2493 else
2494 log_debug ("num: %ld %% %ld = NULL",
2495 ileft, iright);
2496 } else if (sleft)
2497 log_debug ("num: %ld %% NULL = NULL", ileft);
2498 else
2499 log_debug ("num: NULL %% %ld = NULL", iright);
2500 #endif
2501 if (sleft && sright && iright) {
2502 *result = ileft % iright;
2503 return 1;
2505 return 0;
2507 case expr_binary_and:
2508 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2509 client_state,
2510 in_options, cfg_options,
2511 scope,
2512 expr -> data.and [0]);
2513 sright = evaluate_numeric_expression (&iright, packet, lease,
2514 client_state,
2515 in_options, cfg_options,
2516 scope,
2517 expr -> data.and [1]);
2519 #if defined (DEBUG_EXPRESSIONS)
2520 if (sleft && sright)
2521 log_debug ("num: %ld | %ld = %ld",
2522 ileft, iright, ileft & iright);
2523 else if (sleft)
2524 log_debug ("num: %ld & NULL = NULL", ileft);
2525 else
2526 log_debug ("num: NULL & %ld = NULL", iright);
2527 #endif
2528 if (sleft && sright) {
2529 *result = ileft & iright;
2530 return 1;
2532 return 0;
2534 case expr_binary_or:
2535 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2536 client_state,
2537 in_options, cfg_options,
2538 scope,
2539 expr -> data.and [0]);
2540 sright = evaluate_numeric_expression (&iright, packet, lease,
2541 client_state,
2542 in_options, cfg_options,
2543 scope,
2544 expr -> data.and [1]);
2546 #if defined (DEBUG_EXPRESSIONS)
2547 if (sleft && sright)
2548 log_debug ("num: %ld | %ld = %ld",
2549 ileft, iright, ileft | iright);
2550 else if (sleft)
2551 log_debug ("num: %ld | NULL = NULL", ileft);
2552 else
2553 log_debug ("num: NULL | %ld = NULL", iright);
2554 #endif
2555 if (sleft && sright) {
2556 *result = ileft | iright;
2557 return 1;
2559 return 0;
2561 case expr_binary_xor:
2562 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2563 client_state,
2564 in_options, cfg_options,
2565 scope,
2566 expr -> data.and [0]);
2567 sright = evaluate_numeric_expression (&iright, packet, lease,
2568 client_state,
2569 in_options, cfg_options,
2570 scope,
2571 expr -> data.and [1]);
2573 #if defined (DEBUG_EXPRESSIONS)
2574 if (sleft && sright)
2575 log_debug ("num: %ld ^ %ld = %ld",
2576 ileft, iright, ileft ^ iright);
2577 else if (sleft)
2578 log_debug ("num: %ld ^ NULL = NULL", ileft);
2579 else
2580 log_debug ("num: NULL ^ %ld = NULL", iright);
2581 #endif
2582 if (sleft && sright) {
2583 *result = ileft ^ iright;
2584 return 1;
2586 return 0;
2588 case expr_client_state:
2589 if (client_state) {
2590 #if defined (DEBUG_EXPRESSIONS)
2591 log_debug ("num: client-state = %d",
2592 client_state -> state);
2593 #endif
2594 *result = client_state -> state;
2595 return 1;
2596 } else {
2597 #if defined (DEBUG_EXPRESSIONS)
2598 log_debug ("num: client-state = NULL");
2599 #endif
2600 return 0;
2603 case expr_ns_add:
2604 case expr_ns_delete:
2605 case expr_ns_exists:
2606 case expr_ns_not_exists:
2607 log_error ("dns opcode in evaluate_numeric_expression: %d",
2608 expr -> op);
2609 return 0;
2611 case expr_function:
2612 log_error ("function definition in evaluate_numeric_expr");
2613 return 0;
2615 case expr_arg:
2616 break;
2619 log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op);
2620 return 0;
2623 /* Return data hanging off of an option cache structure, or if there
2624 isn't any, evaluate the expression hanging off of it and return the
2625 result of that evaluation. There should never be both an expression
2626 and a valid data_string. */
2628 int evaluate_option_cache (result, packet, lease, client_state,
2629 in_options, cfg_options, scope, oc, file, line)
2630 struct data_string *result;
2631 struct packet *packet;
2632 struct lease *lease;
2633 struct client_state *client_state;
2634 struct option_state *in_options;
2635 struct option_state *cfg_options;
2636 struct binding_scope **scope;
2637 struct option_cache *oc;
2638 const char *file;
2639 int line;
2641 if (oc -> data.len) {
2642 data_string_copy (result, &oc -> data, file, line);
2643 return 1;
2645 if (!oc -> expression)
2646 return 0;
2647 return evaluate_data_expression (result, packet, lease, client_state,
2648 in_options, cfg_options, scope,
2649 oc -> expression, file, line);
2652 /* Evaluate an option cache and extract a boolean from the result,
2653 returning the boolean. Return false if there is no data. */
2655 int evaluate_boolean_option_cache (ignorep, packet,
2656 lease, client_state, in_options,
2657 cfg_options, scope, oc, file, line)
2658 int *ignorep;
2659 struct packet *packet;
2660 struct lease *lease;
2661 struct client_state *client_state;
2662 struct option_state *in_options;
2663 struct option_state *cfg_options;
2664 struct binding_scope **scope;
2665 struct option_cache *oc;
2666 const char *file;
2667 int line;
2669 struct data_string ds;
2670 int result;
2672 /* So that we can be called with option_lookup as an argument. */
2673 if (!oc || !in_options)
2674 return 0;
2676 memset (&ds, 0, sizeof ds);
2677 if (!evaluate_option_cache (&ds, packet,
2678 lease, client_state, in_options,
2679 cfg_options, scope, oc, file, line))
2680 return 0;
2682 if (ds.len) {
2683 result = ds.data [0];
2684 if (result == 2) {
2685 result = 0;
2686 *ignorep = 1;
2687 } else
2688 *ignorep = 0;
2689 } else
2690 result = 0;
2691 data_string_forget (&ds, MDL);
2692 return result;
2696 /* Evaluate a boolean expression and return the result of the evaluation,
2697 or FALSE if it failed. */
2699 int evaluate_boolean_expression_result (ignorep, packet, lease, client_state,
2700 in_options, cfg_options, scope, expr)
2701 int *ignorep;
2702 struct packet *packet;
2703 struct lease *lease;
2704 struct client_state *client_state;
2705 struct option_state *in_options;
2706 struct option_state *cfg_options;
2707 struct binding_scope **scope;
2708 struct expression *expr;
2710 int result;
2712 /* So that we can be called with option_lookup as an argument. */
2713 if (!expr)
2714 return 0;
2716 if (!evaluate_boolean_expression (&result, packet, lease, client_state,
2717 in_options, cfg_options,
2718 scope, expr))
2719 return 0;
2721 if (result == 2) {
2722 *ignorep = 1;
2723 result = 0;
2724 } else
2725 *ignorep = 0;
2726 return result;
2730 /* Dereference an expression node, and if the reference count goes to zero,
2731 dereference any data it refers to, and then free it. */
2732 void expression_dereference (eptr, file, line)
2733 struct expression **eptr;
2734 const char *file;
2735 int line;
2737 struct expression *expr = *eptr;
2739 /* Zero the pointer. */
2740 *eptr = (struct expression *)0;
2742 /* Decrement the reference count. If it's nonzero, we're
2743 done. */
2744 --(expr -> refcnt);
2745 rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC);
2746 if (expr -> refcnt > 0)
2747 return;
2748 if (expr -> refcnt < 0) {
2749 log_error ("%s(%d): negative refcnt!", file, line);
2750 #if defined (DEBUG_RC_HISTORY)
2751 dump_rc_history (expr);
2752 #endif
2753 #if defined (POINTER_DEBUG)
2754 abort ();
2755 #else
2756 return;
2757 #endif
2760 /* Dereference subexpressions. */
2761 switch (expr -> op) {
2762 /* All the binary operators can be handled the same way. */
2763 case expr_equal:
2764 case expr_not_equal:
2765 case expr_concat:
2766 case expr_and:
2767 case expr_or:
2768 case expr_add:
2769 case expr_subtract:
2770 case expr_multiply:
2771 case expr_divide:
2772 case expr_remainder:
2773 case expr_binary_and:
2774 case expr_binary_or:
2775 case expr_binary_xor:
2776 case expr_client_state:
2777 if (expr -> data.equal [0])
2778 expression_dereference (&expr -> data.equal [0],
2779 file, line);
2780 if (expr -> data.equal [1])
2781 expression_dereference (&expr -> data.equal [1],
2782 file, line);
2783 break;
2785 case expr_substring:
2786 if (expr -> data.substring.expr)
2787 expression_dereference (&expr -> data.substring.expr,
2788 file, line);
2789 if (expr -> data.substring.offset)
2790 expression_dereference (&expr -> data.substring.offset,
2791 file, line);
2792 if (expr -> data.substring.len)
2793 expression_dereference (&expr -> data.substring.len,
2794 file, line);
2795 break;
2797 case expr_suffix:
2798 if (expr -> data.suffix.expr)
2799 expression_dereference (&expr -> data.suffix.expr,
2800 file, line);
2801 if (expr -> data.suffix.len)
2802 expression_dereference (&expr -> data.suffix.len,
2803 file, line);
2804 break;
2806 case expr_not:
2807 if (expr -> data.not)
2808 expression_dereference (&expr -> data.not, file, line);
2809 break;
2811 case expr_packet:
2812 if (expr -> data.packet.offset)
2813 expression_dereference (&expr -> data.packet.offset,
2814 file, line);
2815 if (expr -> data.packet.len)
2816 expression_dereference (&expr -> data.packet.len,
2817 file, line);
2818 break;
2820 case expr_extract_int8:
2821 case expr_extract_int16:
2822 case expr_extract_int32:
2823 if (expr -> data.extract_int)
2824 expression_dereference (&expr -> data.extract_int,
2825 file, line);
2826 break;
2828 case expr_encode_int8:
2829 case expr_encode_int16:
2830 case expr_encode_int32:
2831 if (expr -> data.encode_int)
2832 expression_dereference (&expr -> data.encode_int,
2833 file, line);
2834 break;
2836 case expr_encapsulate:
2837 case expr_const_data:
2838 data_string_forget (&expr -> data.const_data, file, line);
2839 break;
2841 case expr_host_lookup:
2842 if (expr -> data.host_lookup)
2843 dns_host_entry_dereference (&expr -> data.host_lookup,
2844 file, line);
2845 break;
2847 case expr_binary_to_ascii:
2848 if (expr -> data.b2a.base)
2849 expression_dereference (&expr -> data.b2a.base,
2850 file, line);
2851 if (expr -> data.b2a.width)
2852 expression_dereference (&expr -> data.b2a.width,
2853 file, line);
2854 if (expr -> data.b2a.seperator)
2855 expression_dereference (&expr -> data.b2a.seperator,
2856 file, line);
2857 if (expr -> data.b2a.buffer)
2858 expression_dereference (&expr -> data.b2a.buffer,
2859 file, line);
2860 break;
2862 case expr_pick_first_value:
2863 if (expr -> data.pick_first_value.car)
2864 expression_dereference (&expr -> data.pick_first_value.car,
2865 file, line);
2866 if (expr -> data.pick_first_value.cdr)
2867 expression_dereference (&expr -> data.pick_first_value.cdr,
2868 file, line);
2869 break;
2871 case expr_reverse:
2872 if (expr -> data.reverse.width)
2873 expression_dereference (&expr -> data.reverse.width,
2874 file, line);
2875 if (expr -> data.reverse.buffer)
2876 expression_dereference
2877 (&expr -> data.reverse.buffer, file, line);
2878 break;
2880 case expr_dns_transaction:
2881 if (expr -> data.dns_transaction.car)
2882 expression_dereference (&expr -> data.dns_transaction.car,
2883 file, line);
2884 if (expr -> data.dns_transaction.cdr)
2885 expression_dereference (&expr -> data.dns_transaction.cdr,
2886 file, line);
2887 break;
2889 case expr_ns_add:
2890 if (expr -> data.ns_add.rrname)
2891 expression_dereference (&expr -> data.ns_add.rrname,
2892 file, line);
2893 if (expr -> data.ns_add.rrdata)
2894 expression_dereference (&expr -> data.ns_add.rrdata,
2895 file, line);
2896 if (expr -> data.ns_add.ttl)
2897 expression_dereference (&expr -> data.ns_add.ttl,
2898 file, line);
2899 break;
2901 case expr_ns_delete:
2902 case expr_ns_exists:
2903 case expr_ns_not_exists:
2904 if (expr -> data.ns_delete.rrname)
2905 expression_dereference (&expr -> data.ns_delete.rrname,
2906 file, line);
2907 if (expr -> data.ns_delete.rrdata)
2908 expression_dereference (&expr -> data.ns_delete.rrdata,
2909 file, line);
2910 break;
2912 case expr_variable_reference:
2913 case expr_variable_exists:
2914 if (expr -> data.variable)
2915 dfree (expr -> data.variable, file, line);
2916 break;
2918 case expr_funcall:
2919 if (expr -> data.funcall.name)
2920 dfree (expr -> data.funcall.name, file, line);
2921 if (expr -> data.funcall.arglist)
2922 expression_dereference (&expr -> data.funcall.arglist,
2923 file, line);
2924 break;
2926 case expr_arg:
2927 if (expr -> data.arg.val)
2928 expression_dereference (&expr -> data.arg.val,
2929 file, line);
2930 if (expr -> data.arg.next)
2931 expression_dereference (&expr -> data.arg.next,
2932 file, line);
2933 break;
2935 case expr_function:
2936 fundef_dereference (&expr -> data.func, file, line);
2937 break;
2939 /* No subexpressions. */
2940 case expr_leased_address:
2941 case expr_lease_time:
2942 case expr_filename:
2943 case expr_sname:
2944 case expr_const_int:
2945 case expr_check:
2946 case expr_option:
2947 case expr_hardware:
2948 case expr_exists:
2949 case expr_known:
2950 case expr_null:
2951 break;
2953 default:
2954 break;
2956 free_expression (expr, MDL);
2959 int is_dns_expression (expr)
2960 struct expression *expr;
2962 return (expr -> op == expr_ns_add ||
2963 expr -> op == expr_ns_delete ||
2964 expr -> op == expr_ns_exists ||
2965 expr -> op == expr_ns_not_exists);
2968 int is_boolean_expression (expr)
2969 struct expression *expr;
2971 return (expr -> op == expr_check ||
2972 expr -> op == expr_exists ||
2973 expr -> op == expr_variable_exists ||
2974 expr -> op == expr_equal ||
2975 expr -> op == expr_not_equal ||
2976 expr -> op == expr_and ||
2977 expr -> op == expr_or ||
2978 expr -> op == expr_not ||
2979 expr -> op == expr_known ||
2980 expr -> op == expr_static);
2983 int is_data_expression (expr)
2984 struct expression *expr;
2986 return (expr -> op == expr_substring ||
2987 expr -> op == expr_suffix ||
2988 expr -> op == expr_option ||
2989 expr -> op == expr_hardware ||
2990 expr -> op == expr_const_data ||
2991 expr -> op == expr_packet ||
2992 expr -> op == expr_concat ||
2993 expr -> op == expr_encapsulate ||
2994 expr -> op == expr_encode_int8 ||
2995 expr -> op == expr_encode_int16 ||
2996 expr -> op == expr_encode_int32 ||
2997 expr -> op == expr_host_lookup ||
2998 expr -> op == expr_binary_to_ascii ||
2999 expr -> op == expr_filename ||
3000 expr -> op == expr_sname ||
3001 expr -> op == expr_reverse ||
3002 expr -> op == expr_pick_first_value ||
3003 expr -> op == expr_host_decl_name ||
3004 expr -> op == expr_leased_address ||
3005 expr -> op == expr_config_option ||
3006 expr -> op == expr_null);
3009 int is_numeric_expression (expr)
3010 struct expression *expr;
3012 return (expr -> op == expr_extract_int8 ||
3013 expr -> op == expr_extract_int16 ||
3014 expr -> op == expr_extract_int32 ||
3015 expr -> op == expr_const_int ||
3016 expr -> op == expr_lease_time ||
3017 expr -> op == expr_dns_transaction ||
3018 expr -> op == expr_add ||
3019 expr -> op == expr_subtract ||
3020 expr -> op == expr_multiply ||
3021 expr -> op == expr_divide ||
3022 expr -> op == expr_remainder ||
3023 expr -> op == expr_binary_and ||
3024 expr -> op == expr_binary_or ||
3025 expr -> op == expr_binary_xor ||
3026 expr -> op == expr_client_state);
3029 int is_compound_expression (expr)
3030 struct expression *expr;
3032 return (expr -> op == expr_ns_add ||
3033 expr -> op == expr_ns_delete ||
3034 expr -> op == expr_ns_exists ||
3035 expr -> op == expr_ns_not_exists ||
3036 expr -> op == expr_substring ||
3037 expr -> op == expr_suffix ||
3038 expr -> op == expr_option ||
3039 expr -> op == expr_concat ||
3040 expr -> op == expr_encode_int8 ||
3041 expr -> op == expr_encode_int16 ||
3042 expr -> op == expr_encode_int32 ||
3043 expr -> op == expr_binary_to_ascii ||
3044 expr -> op == expr_reverse ||
3045 expr -> op == expr_pick_first_value ||
3046 expr -> op == expr_config_option ||
3047 expr -> op == expr_extract_int8 ||
3048 expr -> op == expr_extract_int16 ||
3049 expr -> op == expr_extract_int32 ||
3050 expr -> op == expr_dns_transaction);
3053 static int op_val PROTO ((enum expr_op));
3055 static int op_val (op)
3056 enum expr_op op;
3058 switch (op) {
3059 case expr_none:
3060 case expr_match:
3061 case expr_static:
3062 case expr_check:
3063 case expr_substring:
3064 case expr_suffix:
3065 case expr_concat:
3066 case expr_encapsulate:
3067 case expr_host_lookup:
3068 case expr_not:
3069 case expr_option:
3070 case expr_hardware:
3071 case expr_packet:
3072 case expr_const_data:
3073 case expr_extract_int8:
3074 case expr_extract_int16:
3075 case expr_extract_int32:
3076 case expr_encode_int8:
3077 case expr_encode_int16:
3078 case expr_encode_int32:
3079 case expr_const_int:
3080 case expr_exists:
3081 case expr_variable_exists:
3082 case expr_known:
3083 case expr_binary_to_ascii:
3084 case expr_reverse:
3085 case expr_filename:
3086 case expr_sname:
3087 case expr_pick_first_value:
3088 case expr_host_decl_name:
3089 case expr_config_option:
3090 case expr_leased_address:
3091 case expr_lease_time:
3092 case expr_dns_transaction:
3093 case expr_null:
3094 case expr_variable_reference:
3095 case expr_ns_add:
3096 case expr_ns_delete:
3097 case expr_ns_exists:
3098 case expr_ns_not_exists:
3099 case expr_arg:
3100 case expr_funcall:
3101 case expr_function:
3102 /* XXXDPN: Need to assign sane precedences to these. */
3103 case expr_binary_and:
3104 case expr_binary_or:
3105 case expr_binary_xor:
3106 case expr_client_state:
3107 return 100;
3109 case expr_equal:
3110 case expr_not_equal:
3111 return 4;
3113 case expr_or:
3114 case expr_and:
3115 return 3;
3117 case expr_add:
3118 case expr_subtract:
3119 return 2;
3121 case expr_multiply:
3122 case expr_divide:
3123 case expr_remainder:
3124 return 1;
3126 return 100;
3129 int op_precedence (op1, op2)
3130 enum expr_op op1, op2;
3132 // int ov1, ov2;
3134 return op_val (op1) - op_val (op2);
3137 enum expression_context expression_context (struct expression *expr)
3139 if (is_data_expression (expr))
3140 return context_data;
3141 if (is_numeric_expression (expr))
3142 return context_numeric;
3143 if (is_boolean_expression (expr))
3144 return context_boolean;
3145 if (is_dns_expression (expr))
3146 return context_dns;
3147 return context_any;
3150 enum expression_context op_context (op)
3151 enum expr_op op;
3153 switch (op) {
3154 /* XXX Why aren't these specific? */
3155 case expr_none:
3156 case expr_match:
3157 case expr_static:
3158 case expr_check:
3159 case expr_substring:
3160 case expr_suffix:
3161 case expr_concat:
3162 case expr_encapsulate:
3163 case expr_host_lookup:
3164 case expr_not:
3165 case expr_option:
3166 case expr_hardware:
3167 case expr_packet:
3168 case expr_const_data:
3169 case expr_extract_int8:
3170 case expr_extract_int16:
3171 case expr_extract_int32:
3172 case expr_encode_int8:
3173 case expr_encode_int16:
3174 case expr_encode_int32:
3175 case expr_const_int:
3176 case expr_exists:
3177 case expr_variable_exists:
3178 case expr_known:
3179 case expr_binary_to_ascii:
3180 case expr_reverse:
3181 case expr_filename:
3182 case expr_sname:
3183 case expr_pick_first_value:
3184 case expr_host_decl_name:
3185 case expr_config_option:
3186 case expr_leased_address:
3187 case expr_lease_time:
3188 case expr_null:
3189 case expr_variable_reference:
3190 case expr_ns_add:
3191 case expr_ns_delete:
3192 case expr_ns_exists:
3193 case expr_ns_not_exists:
3194 case expr_dns_transaction:
3195 case expr_arg:
3196 case expr_funcall:
3197 case expr_function:
3198 return context_any;
3200 case expr_equal:
3201 case expr_not_equal:
3202 return context_data;
3204 case expr_and:
3205 return context_boolean;
3207 case expr_or:
3208 return context_boolean;
3210 case expr_add:
3211 case expr_subtract:
3212 case expr_multiply:
3213 case expr_divide:
3214 case expr_remainder:
3215 case expr_binary_and:
3216 case expr_binary_or:
3217 case expr_binary_xor:
3218 case expr_client_state:
3219 return context_numeric;
3221 return context_any;
3224 int write_expression (file, expr, col, indent, firstp)
3225 FILE *file;
3226 struct expression *expr;
3227 int col;
3228 int indent;
3229 int firstp;
3231 struct expression *e;
3232 const char *s;
3233 char obuf [65];
3234 int scol;
3235 int width;
3237 /* If this promises to be a fat expression, start a new line. */
3238 if (!firstp && is_compound_expression (expr)) {
3239 indent_spaces (file, indent);
3240 col = indent;
3243 switch (expr -> op) {
3244 case expr_none:
3245 col = token_print_indent (file, col, indent, "", "", "null");
3246 break;
3248 case expr_check:
3249 col = token_print_indent (file, col, indent, "", "", "check");
3250 col = token_print_indent_concat (file, col, indent,
3251 " ", "", "\"",
3252 expr -> data.check -> name,
3253 "\"", (char *)0);
3254 break;
3256 case expr_not_equal:
3257 s = "!=";
3258 goto binary;
3260 case expr_equal:
3261 s = "=";
3262 binary:
3263 col = write_expression (file, expr -> data.equal [0],
3264 col, indent, 1);
3265 col = token_print_indent (file, col, indent, " ", " ", s);
3266 col = write_expression (file, expr -> data.equal [1],
3267 col, indent + 2, 0);
3268 break;
3270 case expr_substring:
3271 col = token_print_indent (file, col, indent, "", "",
3272 "substring");
3273 col = token_print_indent (file, col, indent, " ", "", "(");
3274 scol = col;
3275 col = write_expression (file, expr -> data.substring.expr,
3276 col, scol, 1);
3277 col = token_print_indent (file, col, indent, "", " ", ",");
3278 col = write_expression (file, expr -> data.substring.offset,
3279 col, indent, 0);
3280 col = token_print_indent (file, col, scol, "", " ", ",");
3281 col = write_expression (file, expr -> data.substring.len,
3282 col, scol, 0);
3283 col = token_print_indent (file, col, indent, "", "", ")");
3284 break;
3286 case expr_suffix:
3287 col = token_print_indent (file, col, indent, "", "", "suffix");
3288 col = token_print_indent (file, col, indent, " ", "", "(");
3289 scol = col;
3290 col = write_expression (file, expr -> data.suffix.expr,
3291 col, scol, 1);
3292 col = token_print_indent (file, col, scol, "", " ", ",");
3293 col = write_expression (file, expr -> data.suffix.len,
3294 col, scol, 0);
3295 col = token_print_indent (file, col, indent, "", "", ")");
3296 break;
3298 case expr_concat:
3299 e = expr;
3300 col = token_print_indent (file, col, indent, "", "",
3301 "concat");
3302 col = token_print_indent (file, col, indent, " ", "", "(");
3303 scol = col;
3304 firstp = 1;
3305 concat_again:
3306 col = write_expression (file, e -> data.concat [0],
3307 col, scol, firstp);
3308 firstp = 0;
3309 if (!e -> data.concat [1])
3310 goto no_concat_cdr;
3311 col = token_print_indent (file, col, scol, "", " ", ",");
3312 if (e -> data.concat [1] -> op == expr_concat) {
3313 e = e -> data.concat [1];
3314 goto concat_again;
3316 col = write_expression (file, e -> data.concat [1],
3317 col, scol, 0);
3318 no_concat_cdr:
3319 col = token_print_indent (file, col, indent, "", "", ")");
3320 break;
3322 case expr_host_lookup:
3323 col = token_print_indent (file, col, indent, "", "",
3324 "gethostbyname");
3325 col = token_print_indent (file, col, indent, " ", "", "(");
3326 col = token_print_indent_concat
3327 (file, col, indent, "", "",
3328 "\"", expr -> data.host_lookup -> hostname, "\"",
3329 (char *)0);
3330 col = token_print_indent (file, col, indent, "", "", ")");
3331 break;
3333 case expr_add:
3334 s = "+";
3335 goto binary;
3337 case expr_subtract:
3338 s = "-";
3339 goto binary;
3341 case expr_multiply:
3342 s = "*";
3343 goto binary;
3345 case expr_divide:
3346 s = "/";
3347 goto binary;
3349 case expr_remainder:
3350 s = "%";
3351 goto binary;
3353 case expr_binary_and:
3354 s = "&";
3355 goto binary;
3357 case expr_binary_or:
3358 s = "|";
3359 goto binary;
3361 case expr_binary_xor:
3362 s = "^";
3363 goto binary;
3365 case expr_and:
3366 s = "and";
3367 goto binary;
3369 case expr_or:
3370 s = "or";
3371 goto binary;
3373 case expr_not:
3374 col = token_print_indent (file, col, indent, "", " ", "not");
3375 col = write_expression (file,
3376 expr -> data.not, col, indent + 2, 1);
3377 break;
3379 case expr_option:
3380 s = "option";
3382 print_option_name:
3383 col = token_print_indent (file, col, indent, "", "", s);
3385 if (expr -> data.option -> universe != &dhcp_universe) {
3386 col = token_print_indent (file, col, indent,
3387 " ", "",
3388 (expr -> data.option ->
3389 universe -> name));
3390 col = token_print_indent (file, col, indent, "", "",
3391 ".");
3392 col = token_print_indent (file, col, indent, "", "",
3393 expr -> data.option -> name);
3394 } else {
3395 col = token_print_indent (file, col, indent, " ", "",
3396 expr -> data.option -> name);
3398 break;
3400 case expr_hardware:
3401 col = token_print_indent (file, col, indent, "", "",
3402 "hardware");
3403 break;
3405 case expr_packet:
3406 col = token_print_indent (file, col, indent, "", "",
3407 "packet");
3408 col = token_print_indent (file, col, indent, " ", "", "(");
3409 scol = col;
3410 col = write_expression (file, expr -> data.packet.offset,
3411 col, indent, 1);
3412 col = token_print_indent (file, col, scol, "", " ", ",");
3413 col = write_expression (file, expr -> data.packet.len,
3414 col, scol, 0);
3415 col = token_print_indent (file, col, indent, "", "", ")");
3416 break;
3418 case expr_const_data:
3419 col = token_indent_data_string (file, col, indent, "", "",
3420 &expr -> data.const_data);
3421 break;
3423 case expr_extract_int8:
3424 width = 8;
3425 extract_int:
3426 col = token_print_indent (file, col, indent, "", "",
3427 "extract-int");
3428 col = token_print_indent (file, col, indent, " ", "", "(");
3429 scol = col;
3430 col = write_expression (file, expr -> data.extract_int,
3431 col, indent, 1);
3432 col = token_print_indent (file, col, scol, "", " ", ",");
3433 sprintf (obuf, "%d", width);
3434 col = token_print_indent (file, col, scol, " ", "", obuf);
3435 col = token_print_indent (file, col, indent, "", "", ")");
3436 break;
3438 case expr_extract_int16:
3439 width = 16;
3440 goto extract_int;
3442 case expr_extract_int32:
3443 width = 32;
3444 goto extract_int;
3446 case expr_encode_int8:
3447 width = 8;
3448 encode_int:
3449 col = token_print_indent (file, col, indent, "", "",
3450 "encode-int");
3451 col = token_print_indent (file, col, indent, " ", "", "(");
3452 scol = col;
3453 col = write_expression (file, expr -> data.extract_int,
3454 col, indent, 1);
3455 col = token_print_indent (file, col, scol, "", " ", ",");
3456 sprintf (obuf, "%d", width);
3457 col = token_print_indent (file, col, scol, " ", "", obuf);
3458 col = token_print_indent (file, col, indent, "", "",
3459 ")");
3460 break;
3462 case expr_encode_int16:
3463 width = 16;
3464 goto encode_int;
3466 case expr_encode_int32:
3467 width = 32;
3468 goto encode_int;
3470 case expr_const_int:
3471 sprintf (obuf, "%lu", expr -> data.const_int);
3472 col = token_print_indent (file, col, indent, "", "", obuf);
3473 break;
3475 case expr_exists:
3476 s = "exists";
3477 goto print_option_name;
3479 case expr_encapsulate:
3480 col = token_print_indent (file, col, indent, "", "",
3481 "encapsulate");
3482 col = token_indent_data_string (file, col, indent, " ", "",
3483 &expr -> data.encapsulate);
3484 break;
3486 case expr_known:
3487 col = token_print_indent (file, col, indent, "", "", "known");
3488 break;
3490 case expr_reverse:
3491 col = token_print_indent (file, col, indent, "", "",
3492 "reverse");
3493 col = token_print_indent (file, col, indent, " ", "", "(");
3494 scol = col;
3495 col = write_expression (file, expr -> data.reverse.width,
3496 col, scol, 1);
3497 col = token_print_indent (file, col, scol, "", " ", ",");
3498 col = write_expression (file, expr -> data.reverse.buffer,
3499 col, scol, 0);
3500 col = token_print_indent (file, col, indent, "", "",
3501 ")");
3502 break;
3504 case expr_leased_address:
3505 col = token_print_indent (file, col, indent, "", "",
3506 "leased-address");
3507 break;
3509 case expr_client_state:
3510 col = token_print_indent (file, col, indent, "", "",
3511 "client-state");
3512 break;
3514 case expr_binary_to_ascii:
3515 col = token_print_indent (file, col, indent, "", "",
3516 "binary-to-ascii");
3517 col = token_print_indent (file, col, indent, " ", "",
3518 "(");
3519 scol = col;
3520 col = write_expression (file, expr -> data.b2a.base,
3521 col, scol, 1);
3522 col = token_print_indent (file, col, scol, "", " ",
3523 ",");
3524 col = write_expression (file, expr -> data.b2a.width,
3525 col, scol, 0);
3526 col = token_print_indent (file, col, scol, "", " ",
3527 ",");
3528 col = write_expression (file, expr -> data.b2a.seperator,
3529 col, scol, 0);
3530 col = token_print_indent (file, col, scol, "", " ",
3531 ",");
3532 col = write_expression (file, expr -> data.b2a.buffer,
3533 col, scol, 0);
3534 col = token_print_indent (file, col, indent, "", "",
3535 ")");
3536 break;
3538 case expr_config_option:
3539 s = "config-option";
3540 goto print_option_name;
3542 case expr_host_decl_name:
3543 col = token_print_indent (file, col, indent, "", "",
3544 "host-decl-name");
3545 break;
3547 case expr_pick_first_value:
3548 e = expr;
3549 col = token_print_indent (file, col, indent, "", "",
3550 "concat");
3551 col = token_print_indent (file, col, indent, " ", "",
3552 "(");
3553 scol = col;
3554 firstp = 1;
3555 pick_again:
3556 col = write_expression (file,
3557 e -> data.pick_first_value.car,
3558 col, scol, firstp);
3559 firstp = 0;
3560 /* We're being very lisp-like right now - instead of
3561 representing this expression as (first middle . last) we're
3562 representing it as (first middle last), which means that the
3563 tail cdr is always nil. Apologies to non-wisp-lizards - may
3564 this obscure way of describing the problem motivate you to
3565 learn more about the one true computing language. */
3566 if (!e -> data.pick_first_value.cdr)
3567 goto no_pick_cdr;
3568 col = token_print_indent (file, col, scol, "", " ",
3569 ",");
3570 if (e -> data.pick_first_value.cdr -> op ==
3571 expr_pick_first_value) {
3572 e = e -> data.pick_first_value.cdr;
3573 goto pick_again;
3575 col = write_expression (file,
3576 e -> data.pick_first_value.cdr,
3577 col, scol, 0);
3578 no_pick_cdr:
3579 col = token_print_indent (file, col, indent, "", "",
3580 ")");
3581 break;
3583 case expr_lease_time:
3584 col = token_print_indent (file, col, indent, "", "",
3585 "lease-time");
3586 break;
3588 case expr_dns_transaction:
3589 col = token_print_indent (file, col, indent, "", "",
3590 "ns-update");
3591 col = token_print_indent (file, col, indent, " ", "",
3592 "(");
3593 scol = 0;
3594 for (e = expr;
3595 e && e -> op == expr_dns_transaction;
3596 e = e -> data.dns_transaction.cdr) {
3597 if (!scol) {
3598 scol = col;
3599 firstp = 1;
3600 } else
3601 firstp = 0;
3602 col = write_expression (file,
3603 e -> data.dns_transaction.car,
3604 col, scol, firstp);
3605 if (e -> data.dns_transaction.cdr)
3606 col = token_print_indent (file, col, scol,
3607 "", " ", ",");
3609 if (e)
3610 col = write_expression (file, e, col, scol, 0);
3611 col = token_print_indent (file, col, indent, "", "", ")");
3612 break;
3614 case expr_ns_add:
3615 col = token_print_indent (file, col, indent, "", "",
3616 "update");
3617 col = token_print_indent (file, col, indent, " ", "",
3618 "(");
3619 scol = col;
3620 sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
3621 col = token_print_indent (file, col, scol, "", "", obuf);
3622 col = token_print_indent (file, col, scol, "", " ",
3623 ",");
3624 sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
3625 col = token_print_indent (file, col, scol, "", "", obuf);
3626 col = token_print_indent (file, col, scol, "", " ",
3627 ",");
3628 col = write_expression (file, expr -> data.ns_add.rrname,
3629 col, scol, 0);
3630 col = token_print_indent (file, col, scol, "", " ",
3631 ",");
3632 col = write_expression (file, expr -> data.ns_add.rrdata,
3633 col, scol, 0);
3634 col = token_print_indent (file, col, scol, "", " ",
3635 ",");
3636 col = write_expression (file, expr -> data.ns_add.ttl,
3637 col, scol, 0);
3638 col = token_print_indent (file, col, indent, "", "",
3639 ")");
3640 break;
3642 case expr_ns_delete:
3643 col = token_print_indent (file, col, indent, "", "",
3644 "delete");
3645 col = token_print_indent (file, col, indent, " ", "",
3646 "(");
3647 finish_ns_small:
3648 scol = col;
3649 sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
3650 col = token_print_indent (file, col, scol, "", "", obuf);
3651 col = token_print_indent (file, col, scol, "", " ",
3652 ",");
3653 sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
3654 col = token_print_indent (file, col, scol, "", "", obuf);
3655 col = token_print_indent (file, col, scol, "", " ",
3656 ",");
3657 col = write_expression (file, expr -> data.ns_add.rrname,
3658 col, scol, 0);
3659 col = token_print_indent (file, col, scol, "", " ",
3660 ",");
3661 col = write_expression (file, expr -> data.ns_add.rrdata,
3662 col, scol, 0);
3663 col = token_print_indent (file, col, indent, "", "",
3664 ")");
3665 break;
3667 case expr_ns_exists:
3668 col = token_print_indent (file, col, indent, "", "",
3669 "exists");
3670 col = token_print_indent (file, col, indent, " ", "",
3671 "(");
3672 goto finish_ns_small;
3674 case expr_ns_not_exists:
3675 col = token_print_indent (file, col, indent, "", "",
3676 "not exists");
3677 col = token_print_indent (file, col, indent, " ", "",
3678 "(");
3679 goto finish_ns_small;
3681 case expr_static:
3682 col = token_print_indent (file, col, indent, "", "",
3683 "static");
3684 break;
3686 case expr_null:
3687 col = token_print_indent (file, col, indent, "", "", "null");
3688 break;
3690 case expr_variable_reference:
3691 col = token_print_indent (file, indent, indent, "", "",
3692 expr -> data.variable);
3693 break;
3695 case expr_variable_exists:
3696 col = token_print_indent (file, indent, indent, "", "",
3697 "defined");
3698 col = token_print_indent (file, col, indent, " ", "", "(");
3699 col = token_print_indent (file, col, indent, "", "",
3700 expr -> data.variable);
3701 col = token_print_indent (file, col, indent, "", "", ")");
3702 break;
3704 default:
3705 log_fatal ("invalid expression type in print_expression: %d",
3706 expr -> op);
3708 return col;
3711 struct binding *find_binding (struct binding_scope *scope, const char *name)
3713 struct binding *bp;
3714 struct binding_scope *s;
3716 for (s = scope; s; s = s -> outer) {
3717 for (bp = s -> bindings; bp; bp = bp -> next) {
3718 if (!strcasecmp (name, bp -> name)) {
3719 return bp;
3723 return (struct binding *)0;
3726 int free_bindings (struct binding_scope *scope, const char *file, int line)
3728 struct binding *bp, *next;
3730 for (bp = scope -> bindings; bp; bp = next) {
3731 next = bp -> next;
3732 if (bp -> name)
3733 dfree (bp -> name, file, line);
3734 if (bp -> value)
3735 binding_value_dereference (&bp -> value, file, line);
3736 dfree (bp, file, line);
3738 scope -> bindings = (struct binding *)0;
3739 return 1;
3742 int binding_scope_dereference (ptr, file, line)
3743 struct binding_scope **ptr;
3744 const char *file;
3745 int line;
3747 // int i;
3748 struct binding_scope *binding_scope;
3750 if (!ptr || !*ptr) {
3751 log_error ("%s(%d): null pointer", file, line);
3752 #if defined (POINTER_DEBUG)
3753 abort ();
3754 #else
3755 return 0;
3756 #endif
3759 binding_scope = *ptr;
3760 *ptr = (struct binding_scope *)0;
3761 --binding_scope -> refcnt;
3762 rc_register (file, line, ptr,
3763 binding_scope, binding_scope -> refcnt, 1, RC_MISC);
3764 if (binding_scope -> refcnt > 0)
3765 return 1;
3767 if (binding_scope -> refcnt < 0) {
3768 log_error ("%s(%d): negative refcnt!", file, line);
3769 #if defined (DEBUG_RC_HISTORY)
3770 dump_rc_history (binding_scope);
3771 #endif
3772 #if defined (POINTER_DEBUG)
3773 abort ();
3774 #else
3775 return 0;
3776 #endif
3779 free_bindings (binding_scope, file, line);
3780 if (binding_scope -> outer)
3781 binding_scope_dereference (&binding_scope -> outer, MDL);
3782 dfree (binding_scope, file, line);
3783 return 1;
3786 int fundef_dereference (ptr, file, line)
3787 struct fundef **ptr;
3788 const char *file;
3789 int line;
3791 struct fundef *bp = *ptr;
3792 struct string_list *sp, *next;
3794 if (!ptr) {
3795 log_error ("%s(%d): null pointer", file, line);
3796 #if defined (POINTER_DEBUG)
3797 abort ();
3798 #else
3799 return 0;
3800 #endif
3803 if (!bp) {
3804 log_error ("%s(%d): null pointer", file, line);
3805 #if defined (POINTER_DEBUG)
3806 abort ();
3807 #else
3808 return 0;
3809 #endif
3812 bp -> refcnt--;
3813 rc_register (file, line, ptr, bp, bp -> refcnt, 1, RC_MISC);
3814 if (bp -> refcnt < 0) {
3815 log_error ("%s(%d): negative refcnt!", file, line);
3816 #if defined (DEBUG_RC_HISTORY)
3817 dump_rc_history (bp);
3818 #endif
3819 #if defined (POINTER_DEBUG)
3820 abort ();
3821 #else
3822 return 0;
3823 #endif
3825 if (!bp -> refcnt) {
3826 for (sp = bp -> args; sp; sp = next) {
3827 next = sp -> next;
3828 dfree (sp, file, line);
3830 if (bp -> statements)
3831 executable_statement_dereference (&bp -> statements,
3832 file, line);
3833 dfree (bp, file, line);
3835 *ptr = (struct fundef *)0;
3836 return 1;
3839 #if defined (NOTYET) /* Post 3.0 final. */
3840 int data_subexpression_length (int *rv,
3841 struct expression *expr)
3843 int crhs, clhs, llhs, lrhs;
3844 switch (expr -> op) {
3845 case expr_substring:
3846 if (expr -> data.substring.len &&
3847 expr -> data.substring.len -> op == expr_const_int) {
3848 (*rv =
3849 (int)expr -> data.substring.len -> data.const_int);
3850 return 1;
3852 return 0;
3854 case expr_packet:
3855 case expr_suffix:
3856 if (expr -> data.suffix.len &&
3857 expr -> data.suffix.len -> op == expr_const_int) {
3858 (*rv =
3859 (int)expr -> data.suffix.len -> data.const_int);
3860 return 1;
3862 return 0;
3864 case expr_concat:
3865 clhs = data_subexpression_length (&llhs,
3866 expr -> data.concat [0]);
3867 crhs = data_subexpression_length (&lrhs,
3868 expr -> data.concat [1]);
3869 if (crhs == 0 || clhs == 0)
3870 return 0;
3871 *rv = llhs + lrhs;
3872 return 1;
3873 break;
3875 case expr_hardware:
3876 return 0;
3878 case expr_const_data:
3879 *rv = expr -> data.const_data.len;
3880 return 2;
3882 case expr_reverse:
3883 return data_subexpression_length (rv,
3884 expr -> data.reverse.buffer);
3886 case expr_leased_address:
3887 case expr_lease_time:
3888 *rv = 4;
3889 return 2;
3891 case expr_pick_first_value:
3892 clhs = data_subexpression_length (&llhs,
3893 expr -> data.concat [0]);
3894 crhs = data_subexpression_length (&lrhs,
3895 expr -> data.concat [1]);
3896 if (crhs == 0 || clhs == 0)
3897 return 0;
3898 if (llhs > lrhs)
3899 *rv = llhs;
3900 else
3901 *rv = lrhs;
3902 return 1;
3904 case expr_binary_to_ascii:
3905 case expr_config_option:
3906 case expr_host_decl_name:
3907 case expr_encapsulate:
3908 case expr_filename:
3909 case expr_sname:
3910 case expr_host_lookup:
3911 case expr_option:
3912 case expr_none:
3913 case expr_match:
3914 case expr_check:
3915 case expr_equal:
3916 case expr_and:
3917 case expr_or:
3918 case expr_not:
3919 case expr_extract_int8:
3920 case expr_extract_int16:
3921 case expr_extract_int32:
3922 case expr_encode_int8:
3923 case expr_encode_int16:
3924 case expr_encode_int32:
3925 case expr_const_int:
3926 case expr_exists:
3927 case expr_known:
3928 case expr_dns_transaction:
3929 case expr_static:
3930 case expr_ns_add:
3931 case expr_ns_delete:
3932 case expr_ns_exists:
3933 case expr_ns_not_exists:
3934 case expr_not_equal:
3935 case expr_null:
3936 case expr_variable_exists:
3937 case expr_variable_reference:
3938 case expr_arg:
3939 case expr_funcall:
3940 case expr_function:
3941 case expr_add:
3942 case expr_subtract:
3943 case expr_multiply:
3944 case expr_divide:
3945 case expr_remainder:
3946 case expr_binary_and:
3947 case expr_binary_or:
3948 case expr_binary_xor:
3949 case expr_client_state:
3950 return 0;
3952 return 0;
3955 int expr_valid_for_context (struct expression *expr,
3956 enum expression_context context)
3958 /* We don't know at parse time what type of value a function may
3959 return, so we can't flag an error on it. */
3960 if (expr -> op == expr_funcall ||
3961 expr -> op == expr_variable_reference)
3962 return 1;
3964 switch (context) {
3965 case context_any:
3966 return 1;
3968 case context_boolean:
3969 if (is_boolean_expression (expr))
3970 return 1;
3971 return 0;
3973 case context_data:
3974 if (is_data_expression (expr))
3975 return 1;
3976 return 0;
3978 case context_numeric:
3979 if (is_numeric_expression (expr))
3980 return 1;
3981 return 0;
3983 case context_dns:
3984 if (is_dns_expression (expr)) {
3985 return 1;
3987 return 0;
3989 case context_data_or_numeric:
3990 if (is_numeric_expression (expr) ||
3991 is_data_expression (expr)) {
3992 return 1;
3994 return 0;
3996 case context_function:
3997 if (expr -> op == expr_function)
3998 return 1;
3999 return 0;
4001 return 0;
4003 #endif /* NOTYET */
4005 struct binding *create_binding (struct binding_scope **scope, const char *name)
4007 struct binding *binding;
4009 if (!*scope) {
4010 if (!binding_scope_allocate (scope, MDL))
4011 return (struct binding *)0;
4014 binding = find_binding (*scope, name);
4015 if (!binding) {
4016 binding = dmalloc (sizeof *binding, MDL);
4017 if (!binding)
4018 return (struct binding *)0;
4020 memset (binding, 0, sizeof *binding);
4021 binding -> name = dmalloc (strlen (name) + 1, MDL);
4022 if (!binding -> name) {
4023 dfree (binding, MDL);
4024 return (struct binding *)0;
4026 strcpy (binding -> name, name);
4028 binding -> next = (*scope) -> bindings;
4029 (*scope) -> bindings = binding;
4032 return binding;
4036 int bind_ds_value (struct binding_scope **scope,
4037 const char *name,
4038 struct data_string *value)
4040 struct binding *binding;
4042 binding = create_binding (scope, name);
4043 if (!binding)
4044 return 0;
4046 if (binding -> value)
4047 binding_value_dereference (&binding -> value, MDL);
4049 if (!binding_value_allocate (&binding -> value, MDL))
4050 return 0;
4052 data_string_copy (&binding -> value -> value.data, value, MDL);
4053 binding -> value -> type = binding_data;
4055 return 1;
4059 int find_bound_string (struct data_string *value,
4060 struct binding_scope *scope,
4061 const char *name)
4063 struct binding *binding;
4065 binding = find_binding (scope, name);
4066 if (!binding ||
4067 !binding -> value ||
4068 binding -> value -> type != binding_data)
4069 return 0;
4071 if (binding -> value -> value.data.terminated) {
4072 data_string_copy (value, &binding -> value -> value.data, MDL);
4073 } else {
4074 buffer_allocate (&value -> buffer,
4075 binding -> value -> value.data.len,
4076 MDL);
4077 if (!value -> buffer)
4078 return 0;
4080 memcpy (value -> buffer -> data,
4081 binding -> value -> value.data.data,
4082 binding -> value -> value.data.len);
4083 value -> data = value -> buffer -> data;
4084 value -> len = binding -> value -> value.data.len;
4087 return 1;
4090 int unset (struct binding_scope *scope, const char *name)
4092 struct binding *binding;
4094 binding = find_binding (scope, name);
4095 if (binding) {
4096 if (binding -> value)
4097 binding_value_dereference
4098 (&binding -> value, MDL);
4099 return 1;
4101 return 0;
4104 /* vim: set tabstop=8: */