3 Routines for manipulating parse trees... */
6 * Copyright (c) 1996-1999 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
13 * http://www.isc.org/isc-license-1.0.html.
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
24 static char copyright
[] =
25 "$Id: tree.c,v 1.23 1999/03/16 05:50:37 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
30 static int do_host_lookup
PROTO ((struct data_string
*,
31 struct dns_host_entry
*));
37 pair foo
= (pair
)dmalloc (sizeof *foo
, "cons");
39 log_fatal ("no memory for cons.");
45 int make_const_option_cache (oc
, buffer
, data
, len
, option
, name
)
46 struct option_cache
**oc
;
47 struct buffer
**buffer
;
50 struct option
*option
;
59 bp
= (struct buffer
*)0;
60 if (!buffer_allocate (&bp
, len
, name
)) {
61 log_error ("%s: can't allocate buffer.", name
);
66 if (!option_cache_allocate (oc
, name
)) {
67 log_error ("%s: can't allocate option cache.");
68 buffer_dereference (&bp
, name
);
72 (*oc
) -> data
.len
= len
;
73 (*oc
) -> data
.data
= &bp
-> data
[0];
74 (*oc
) -> data
.terminated
= 0;
76 memcpy ((*oc
) -> data
.data
, data
, len
);
77 (*oc
) -> option
= option
;
81 int make_host_lookup (expr
, name
)
82 struct expression
**expr
;
85 if (!expression_allocate (expr
, "make_host_lookup")) {
86 log_error ("No memory for host lookup tree node.");
89 (*expr
) -> op
= expr_host_lookup
;
90 if (!enter_dns_host (&((*expr
) -> data
.host_lookup
), name
)) {
91 expression_dereference (expr
, "make_host_lookup");
97 int enter_dns_host (dh
, name
)
98 struct dns_host_entry
**dh
;
101 /* XXX This should really keep a hash table of hostnames
102 XXX and just add a new reference to a hostname that
103 XXX already exists, if possible, rather than creating
104 XXX a new structure. */
105 if (!dns_host_entry_allocate (dh
, name
, "enter_dns_host")) {
106 log_error ("Can't allocate space for new host.");
112 int make_const_data (expr
, data
, len
, terminated
, allocate
)
113 struct expression
**expr
;
119 struct expression
*nt
;
121 if (!expression_allocate (expr
, "make_host_lookup")) {
122 log_error ("No memory for make_const_data tree node.");
129 if (!buffer_allocate (&nt
-> data
.const_data
.buffer
,
131 "make_const_data")) {
132 log_error ("Can't allocate const_data buffer.");
133 expression_dereference (expr
,
137 nt
-> data
.const_data
.data
=
138 &nt
-> data
.const_data
.buffer
-> data
[0];
139 memcpy (nt
-> data
.const_data
.data
,
140 data
, len
+ terminated
);
142 nt
-> data
.const_data
.data
= data
;
143 nt
-> data
.const_data
.terminated
= terminated
;
145 nt
-> data
.const_data
.data
= 0;
147 nt
-> op
= expr_const_data
;
148 nt
-> data
.const_data
.len
= len
;
152 int make_concat (expr
, left
, right
)
153 struct expression
**expr
;
154 struct expression
*left
, *right
;
156 /* If we're concatenating a null tree to a non-null tree, just
157 return the non-null tree; if both trees are null, return
162 expression_reference (expr
, right
, "make_concat");
166 expression_reference (expr
, left
, "make_concat");
170 /* Otherwise, allocate a new node to concatenate the two. */
171 if (!expression_allocate (expr
, "make_concat")) {
172 log_error ("No memory for concatenation expression node.");
176 (*expr
) -> op
= expr_concat
;
177 expression_reference (&(*expr
) -> data
.concat
[0],
178 left
, "make_concat");
179 expression_reference (&(*expr
) -> data
.concat
[1],
180 right
, "make_concat");
184 int make_substring (new, expr
, offset
, length
)
185 struct expression
**new;
186 struct expression
*expr
;
187 struct expression
*offset
;
188 struct expression
*length
;
190 /* Allocate an expression node to compute the substring. */
191 if (!expression_allocate (new, "make_substring")) {
192 log_error ("no memory for substring expression.");
195 (*new) -> op
= expr_substring
;
196 expression_reference (&(*new) -> data
.substring
.expr
,
197 expr
, "make_concat");
198 expression_reference (&(*new) -> data
.substring
.offset
,
199 offset
, "make_concat");
200 expression_reference (&(*new) -> data
.substring
.len
,
201 length
, "make_concat");
205 int make_limit (new, expr
, limit
)
206 struct expression
**new;
207 struct expression
*expr
;
210 struct expression
*rv
;
212 /* Allocate a node to enforce a limit on evaluation. */
213 if (!expression_allocate (new, "make_limit"))
214 log_error ("no memory for limit expression");
215 (*new) -> op
= expr_substring
;
216 expression_reference (&(*new) -> data
.substring
.expr
,
219 /* Offset is a constant 0. */
220 if (!expression_allocate (&(*new) -> data
.substring
.offset
,
222 log_error ("no memory for limit offset expression");
223 expression_dereference (new, "make_limit");
226 (*new) -> data
.substring
.offset
-> op
= expr_const_int
;
227 (*new) -> data
.substring
.offset
-> data
.const_int
= 0;
229 /* Length is a constant: the specified limit. */
230 if (!expression_allocate (&(*new) -> data
.substring
.len
,
232 log_error ("no memory for limit length expression");
233 expression_dereference (new, "make_limit");
236 (*new) -> data
.substring
.len
-> op
= expr_const_int
;
237 (*new) -> data
.substring
.len
-> data
.const_int
= limit
;
242 int option_cache (oc
, dp
, expr
, option
)
243 struct option_cache
**oc
;
244 struct data_string
*dp
;
245 struct expression
*expr
;
246 struct option
*option
;
248 if (!option_cache_allocate (oc
, "option_cache"))
251 data_string_copy (&(*oc
) -> data
, dp
, "option_cache");
253 expression_reference (&(*oc
) -> expression
,
254 expr
, "option_cache");
255 (*oc
) -> option
= option
;
259 int do_host_lookup (result
, dns
)
260 struct data_string
*result
;
261 struct dns_host_entry
*dns
;
268 log_debug ("time: now = %d dns = %d %d diff = %d",
269 cur_time
, dns
-> timeout
, cur_time
- dns
-> timeout
);
272 /* If the record hasn't timed out, just copy the data and return. */
273 if (cur_time
<= dns
-> timeout
) {
275 log_debug ("easy copy: %d %s",
278 ? inet_ntoa (*(struct in_addr
*)(dns
-> data
.data
))
281 data_string_copy (result
, &dns
-> data
, "do_host_lookup");
285 log_debug ("Looking up %s", dns
-> hostname
);
288 /* Otherwise, look it up... */
289 h
= gethostbyname (dns
-> hostname
);
295 log_error ("%s: host unknown.", dns
-> hostname
);
299 log_error ("%s: temporary name server failure",
303 log_error ("%s: name server failed", dns
-> hostname
);
306 log_error ("%s: no A record associated with address",
309 #endif /* !NO_H_ERRNO */
311 /* Okay to try again after a minute. */
312 dns
-> timeout
= cur_time
+ 60;
313 data_string_forget (&dns
-> data
, "do_host_lookup");
318 log_debug ("Lookup succeeded; first address is %s",
319 inet_ntoa (h
-> h_addr_list
[0]));
322 /* Count the number of addresses we got... */
323 for (count
= 0; h
-> h_addr_list
[count
]; count
++)
326 /* Dereference the old data, if any. */
327 data_string_forget (&dns
-> data
, "do_host_lookup");
329 /* Do we need to allocate more memory? */
330 new_len
= count
* h
-> h_length
;
331 if (!buffer_allocate (&dns
-> data
.buffer
, new_len
, "do_host_lookup"))
333 log_error ("No memory for %s.", dns
-> hostname
);
337 dns
-> data
.data
= &dns
-> data
.buffer
-> data
[0];
338 dns
-> data
.len
= new_len
;
339 dns
-> data
.terminated
= 0;
341 /* Addresses are conveniently stored one to the buffer, so we
342 have to copy them out one at a time... :'( */
343 for (i
= 0; i
< count
; i
++) {
344 memcpy (&dns
-> data
.data
[h
-> h_length
* i
],
345 h
-> h_addr_list
[i
], h
-> h_length
);
348 log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
349 *(int *)(dns
-> buffer
), h
-> h_addr_list
[0]);
352 /* XXX Set the timeout for an hour from now.
353 XXX This should really use the time on the DNS reply. */
354 dns
-> timeout
= cur_time
+ 3600;
357 log_debug ("hard copy: %d %s", dns
-> data
.len
,
359 ? inet_ntoa (*(struct in_addr
*)(dns
-> data
.data
)) : 0));
361 data_string_copy (result
, &dns
-> data
, "do_host_lookup");
365 int evaluate_boolean_expression (result
, packet
, options
, expr
)
367 struct packet
*packet
;
368 struct option_state
*options
;
369 struct expression
*expr
;
371 struct data_string left
, right
;
375 switch (expr
-> op
) {
377 *result
= check_collection (packet
, expr
-> data
.check
);
378 #if defined (DEBUG_EXPRESSIONS)
379 log_info ("bool: check (%s) returns %s",
380 expr
-> data
.check
-> name
, *result
? "true" : "false");
385 memset (&left
, 0, sizeof left
);
386 sleft
= evaluate_data_expression (&left
, packet
, options
,
387 expr
-> data
.equal
[0]);
388 memset (&right
, 0, sizeof right
);
389 sright
= evaluate_data_expression (&right
, packet
, options
,
390 expr
-> data
.equal
[1]);
391 if (sleft
&& sright
) {
392 if (left
.len
== right
.len
&&
393 !memcmp (left
.data
, right
.data
, left
.len
))
399 #if defined (DEBUG_EXPRESSIONS)
400 log_info ("bool: equal (%s, %s) = %s",
401 sleft
? print_hex_1 (left
.len
, left
.data
, 30) : "NULL",
402 sright
? print_hex_2 (right
.len
,
403 right
.data
, 30) : "NULL",
405 ? (*result
? "true" : "false")
409 data_string_forget (&left
,
410 "evaluate_boolean_expression");
412 data_string_forget (&right
,
413 "evaluate_boolean_expression");
414 return sleft
&& sright
;
417 sleft
= evaluate_boolean_expression (&bleft
, packet
, options
,
418 expr
-> data
.and [0]);
419 sright
= evaluate_boolean_expression (&bright
, packet
, options
,
420 expr
-> data
.and [1]);
422 #if defined (DEBUG_EXPRESSIONS)
423 log_info ("bool: and (%s, %s) = %s",
424 sleft
? (bleft
? "true" : "false") : "NULL",
425 sright
? (bright
? "true" : "false") : "NULL",
427 ? (bleft
&& bright
? "true" : "false") : "NULL"));
429 if (sleft
&& sright
) {
430 *result
= bleft
&& bright
;
436 sleft
= evaluate_boolean_expression (&bleft
, packet
, options
,
437 expr
-> data
.or [0]);
438 sright
= evaluate_boolean_expression (&bright
, packet
, options
,
439 expr
-> data
.or [1]);
440 #if defined (DEBUG_EXPRESSIONS)
441 log_info ("bool: or (%s, %s) = %s",
442 sleft
? (bleft
? "true" : "false") : "NULL",
443 sright
? (bright
? "true" : "false") : "NULL",
445 ? (bleft
|| bright
? "true" : "false") : "NULL"));
447 if (sleft
&& sright
) {
448 *result
= bleft
|| bright
;
454 sleft
= evaluate_boolean_expression (&bleft
, packet
, options
,
456 #if defined (DEBUG_EXPRESSIONS)
457 log_info ("bool: not (%s) = %s",
458 sleft
? (bleft
? "true" : "false") : "NULL",
460 ? (!bleft
? "true" : "false") : "NULL"));
470 memset (&left
, 0, sizeof left
);
471 if (!((*expr
-> data
.option
-> universe
-> lookup_func
)
472 (&left
, options
, expr
-> data
.exists
-> code
)))
476 data_string_forget (&left
,
477 "evaluate_boolean_expression");
479 #if defined (DEBUG_EXPRESSIONS)
480 log_info ("data: exists %s.%s = %s",
481 expr
-> data
.option
-> universe
-> name
,
482 expr
-> data
.option
-> name
, *result
? "true" : "false");
490 case expr_const_data
:
493 case expr_host_lookup
:
494 log_error ("Data opcode in evaluate_boolean_expression: %d",
498 case expr_extract_int8
:
499 case expr_extract_int16
:
500 case expr_extract_int32
:
502 log_error ("Numeric opcode in evaluate_boolean_expression: %d",
507 log_error ("Bogus opcode in evaluate_boolean_expression: %d", expr
-> op
);
511 int evaluate_data_expression (result
, packet
, options
, expr
)
512 struct data_string
*result
;
513 struct packet
*packet
;
514 struct option_state
*options
;
515 struct expression
*expr
;
517 struct data_string data
, other
;
518 unsigned long offset
, len
;
521 switch (expr
-> op
) {
522 /* Extract N bytes starting at byte M of a data string. */
524 memset (&data
, 0, sizeof data
);
525 s0
= evaluate_data_expression (&data
, packet
, options
,
526 expr
-> data
.substring
.expr
);
528 /* Evaluate the offset and length. */
529 s1
= evaluate_numeric_expression
531 packet
, options
, expr
-> data
.substring
.offset
);
532 s2
= evaluate_numeric_expression (&len
, packet
, options
,
533 expr
-> data
.substring
.len
);
535 if (s0
&& s1
&& s2
) {
536 /* If the offset is after end of the string,
537 return an empty string. Otherwise, do the
538 adjustments and return what's left. */
539 if (data
.len
> offset
) {
540 data_string_copy (result
, &data
,
541 "evaluate_data_expression");
542 result
-> len
-= offset
;
543 if (result
-> len
> len
) {
545 result
-> terminated
= 0;
547 result
-> data
+= offset
;
553 #if defined (DEBUG_EXPRESSIONS)
554 log_info ("data: substring (%s, %s, %s) = %s",
555 s0
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
556 s1
? print_dec_1 (offset
) : "NULL",
557 s2
? print_dec_2 (len
) : "NULL",
558 (s3
? print_hex_2 (result
-> len
, result
-> data
, 30)
563 data_string_forget (&data
, "evaluate_data_expression");
567 /* Extract the last N bytes of a data string. */
569 memset (&data
, 0, sizeof data
);
570 s0
= evaluate_data_expression (&data
, packet
, options
,
571 expr
-> data
.suffix
.expr
);
572 /* Evaluate the length. */
573 s1
= evaluate_numeric_expression (&len
, packet
, options
,
574 expr
-> data
.substring
.len
);
576 data_string_copy (result
, &data
,
577 "evaluate_data_expression");
579 /* If we are returning the last N bytes of a
580 string whose length is <= N, just return
581 the string - otherwise, compute a new
582 starting address and decrease the
584 if (data
.len
> len
) {
585 result
-> data
+= data
.len
- len
;
590 #if defined (DEBUG_EXPRESSIONS)
591 log_info ("data: suffix (%s, %d) = %s",
592 s0
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
593 s1
? print_dec_1 (len
) : "NULL",
595 ? print_hex_2 (result
-> len
, result
-> data
, 30)
600 /* Extract an option. */
602 s0
= ((*expr
-> data
.option
-> universe
-> lookup_func
)
603 (result
, &packet
-> options
,
604 expr
-> data
.option
-> code
));
605 #if defined (DEBUG_EXPRESSIONS)
606 log_info ("data: option %s.%s = %s",
607 expr
-> data
.option
-> universe
-> name
,
608 expr
-> data
.option
-> name
,
609 s0
? print_hex_1 (result
-> len
, result
-> data
, 60)
614 /* Combine the hardware type and address. */
616 if (!packet
|| !packet
-> raw
) {
617 log_error ("data: hardware: raw packet not available");
620 if (packet
-> raw
-> hlen
> sizeof packet
-> raw
-> chaddr
) {
621 log_error ("data: hardware: invalid hlen (%d)\n",
622 packet
-> raw
-> hlen
);
625 result
-> len
= packet
-> raw
-> hlen
+ 1;
626 if (buffer_allocate (&result
-> buffer
, result
-> len
,
627 "evaluate_data_expression")) {
628 result
-> data
= &result
-> buffer
-> data
[0];
629 result
-> data
[0] = packet
-> raw
-> htype
;
630 memcpy (&result
-> data
[1], packet
-> raw
-> chaddr
,
631 packet
-> raw
-> hlen
);
632 result
-> terminated
= 0;
634 log_error ("data: hardware: no memory for buffer.");
637 #if defined (DEBUG_EXPRESSIONS)
638 log_info ("data: hardware = %s",
639 print_hex_1 (result
-> len
, result
-> data
, 60));
643 /* Extract part of the raw packet. */
645 if (!packet
|| !packet
-> raw
) {
646 log_error ("data: packet: raw packet not available");
650 s0
= evaluate_numeric_expression (&len
, packet
, options
,
651 expr
-> data
.packet
.len
);
652 s1
= evaluate_numeric_expression (&offset
, packet
, options
,
653 expr
-> data
.packet
.len
);
654 if (s0
&& s1
&& offset
< packet
-> packet_length
) {
655 if (offset
+ len
> packet
-> packet_length
)
657 packet
-> packet_length
- offset
;
660 if (buffer_allocate (&result
-> buffer
, result
-> len
,
661 "evaluate_data_expression")) {
662 result
-> data
= &result
-> buffer
-> data
[0];
663 memcpy (result
-> data
,
664 (((unsigned char *)(packet
-> raw
))
665 + offset
), result
-> len
);
666 result
-> terminated
= 0;
668 log_error ("data: packet: no memory for buffer.");
674 #if defined (DEBUG_EXPRESSIONS)
675 log_info ("data: packet (%d, %d) = %s",
677 s2
? print_hex_1 (result
-> len
,
678 result
-> data
, 60) : NULL
);
682 /* Some constant data... */
683 case expr_const_data
:
684 #if defined (DEBUG_EXPRESSIONS)
685 log_info ("data: const = %s",
686 print_hex_1 (expr
-> data
.const_data
.len
,
687 expr
-> data
.const_data
.data
, 60));
689 data_string_copy (result
,
690 &expr
-> data
.const_data
,
691 "evaluate_data_expression");
694 /* Hostname lookup... */
695 case expr_host_lookup
:
696 s0
= do_host_lookup (result
, expr
-> data
.host_lookup
);
697 #if defined (DEBUG_EXPRESSIONS)
698 log_info ("data: DNS lookup (%s) = %s",
699 expr
-> data
.host_lookup
-> hostname
,
701 ? print_dotted_quads (result
-> len
, result
-> data
)
706 /* Concatenation... */
708 memset (&data
, 0, sizeof data
);
709 s0
= evaluate_data_expression (&data
, packet
, options
,
710 expr
-> data
.concat
[0]);
711 memset (&other
, 0, sizeof other
);
712 s1
= evaluate_data_expression (&other
, packet
, options
,
713 expr
-> data
.concat
[1]);
716 result
-> len
= data
.len
+ other
.len
;
717 if (!buffer_allocate (&result
-> buffer
,
721 log_error ("data: concat: no memory");
723 data_string_forget (&data
, "expr_concat");
724 data_string_forget (&other
, "expr_concat");
727 result
-> data
= &result
-> buffer
-> data
[0];
728 memcpy (result
-> data
, data
.data
, data
.len
);
729 memcpy (&result
-> data
[data
.len
],
730 other
.data
, other
.len
+ other
.terminated
);
732 data_string_copy (result
, &data
, "expr_concat");
734 data_string_copy (result
, &other
, "expr_concat");
735 #if defined (DEBUG_EXPRESSIONS)
736 log_info ("data: concat (%s, %s) = %s",
737 s0
? print_hex_1 (data
.len
, data
.data
, 20) : "NULL",
738 s1
? print_hex_2 (other
.len
, other
.data
, 20) : "NULL",
740 ? print_hex_3 (result
-> len
, result
-> data
, 30)
751 log_error ("Boolean opcode in evaluate_data_expression: %d",
755 case expr_extract_int8
:
756 case expr_extract_int16
:
757 case expr_extract_int32
:
759 log_error ("Numeric opcode in evaluate_data_expression: %d",
764 log_error ("Bogus opcode in evaluate_data_expression: %d", expr
-> op
);
768 int evaluate_numeric_expression (result
, packet
, options
, expr
)
769 unsigned long *result
;
770 struct packet
*packet
;
771 struct option_state
*options
;
772 struct expression
*expr
;
774 struct data_string data
;
777 switch (expr
-> op
) {
784 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
792 case expr_const_data
:
795 case expr_host_lookup
:
796 log_error ("Data opcode in evaluate_numeric_expression: %d",
800 case expr_extract_int8
:
801 memset (&data
, 0, sizeof data
);
802 status
= evaluate_data_expression
804 options
, expr
-> data
.extract_int
);
806 *result
= data
.data
[0];
807 #if defined (DEBUG_EXPRESSIONS)
808 log_info ("num: extract_int8 (%s) = %s",
809 status
? print_hex_1 (data
.len
, data
.data
, 60) : "NULL",
810 status
? print_dec_1 (*result
) : "NULL" );
813 data_string_forget (&data
, "expr_extract_int8");
816 case expr_extract_int16
:
817 memset (&data
, 0, sizeof data
);
818 status
= (evaluate_data_expression
819 (&data
, packet
, options
,
820 expr
-> data
.extract_int
));
821 if (status
&& data
.len
>= 2)
822 *result
= getUShort (data
.data
);
823 #if defined (DEBUG_EXPRESSIONS)
824 log_info ("num: extract_int16 (%s) = %ld",
825 ((status
&& data
.len
>= 2) ?
826 print_hex_1 (data
.len
, data
.data
, 60) : "NULL"),
830 data_string_forget (&data
, "expr_extract_int16");
831 return (status
&& data
.len
>= 2);
833 case expr_extract_int32
:
834 memset (&data
, 0, sizeof data
);
835 status
= (evaluate_data_expression
836 (&data
, packet
, options
,
837 expr
-> data
.extract_int
));
838 if (status
&& data
.len
>= 4)
839 *result
= getULong (data
.data
);
840 #if defined (DEBUG_EXPRESSIONS)
841 log_info ("num: extract_int32 (%s) = %ld",
842 ((status
&& data
.len
>= 4) ?
843 print_hex_1 (data
.len
, data
.data
, 60) : "NULL"),
847 data_string_forget (&data
, "expr_extract_int32");
848 return (status
&& data
.len
>= 4);
851 *result
= expr
-> data
.const_int
;
855 log_error ("Bogus opcode in evaluate_numeric_expression: %d", expr
-> op
);
859 /* Return data hanging off of an option cache structure, or if there
860 isn't any, evaluate the expression hanging off of it and return the
861 result of that evaluation. There should never be both an expression
862 and a valid data_string. */
864 int evaluate_option_cache (result
, packet
, options
, oc
)
865 struct data_string
*result
;
866 struct packet
*packet
;
867 struct option_state
*options
;
868 struct option_cache
*oc
;
870 if (oc
-> data
.len
) {
871 data_string_copy (result
,
872 &oc
-> data
, "evaluate_option_cache");
875 if (!oc
-> expression
)
877 return evaluate_data_expression (result
,
878 packet
, options
, oc
-> expression
);
881 /* Evaluate an option cache and extract a boolean from the result,
882 returning the boolean. Return false if there is no data. */
884 int evaluate_boolean_option_cache (packet
, options
, oc
)
885 struct packet
*packet
;
886 struct option_state
*options
;
887 struct option_cache
*oc
;
889 struct data_string ds
;
892 /* So that we can be called with option_lookup as an argument. */
896 memset (&ds
, 0, sizeof ds
);
897 if (!evaluate_option_cache (&ds
, packet
, options
, oc
))
900 if (ds
.len
&& ds
.data
[0])
904 data_string_forget (&ds
, "evaluate_boolean_option_cache");
909 /* Evaluate a boolean expression and return the result of the evaluation,
910 or FALSE if it failed. */
912 int evaluate_boolean_expression_result (packet
, options
, expr
)
913 struct packet
*packet
;
914 struct option_state
*options
;
915 struct expression
*expr
;
919 /* So that we can be called with option_lookup as an argument. */
923 if (!evaluate_boolean_expression (&result
, packet
, options
, expr
))
930 /* Dereference an expression node, and if the reference count goes to zero,
931 dereference any data it refers to, and then free it. */
932 void expression_dereference (eptr
, name
)
933 struct expression
**eptr
;
936 struct expression
*expr
= *eptr
;
938 /* Zero the pointer. */
939 *eptr
= (struct expression
*)0;
941 /* Decrement the reference count. If it's nonzero, we're
943 if (--(expr
-> refcnt
) > 0)
945 if (expr
-> refcnt
< 0) {
946 log_error ("expression_dereference: negative refcnt!");
950 /* Dereference subexpressions. */
951 switch (expr
-> op
) {
952 /* All the binary operators can be handled the same way. */
957 if (expr
-> data
.equal
[0])
958 expression_dereference (&expr
-> data
.equal
[0], name
);
959 if (expr
-> data
.equal
[1])
960 expression_dereference (&expr
-> data
.equal
[1], name
);
964 if (expr
-> data
.substring
.expr
)
965 expression_dereference (&expr
-> data
.substring
.expr
,
967 if (expr
-> data
.substring
.offset
)
968 expression_dereference (&expr
-> data
.substring
.offset
,
970 if (expr
-> data
.substring
.len
)
971 expression_dereference (&expr
-> data
.substring
.len
,
976 if (expr
-> data
.suffix
.expr
)
977 expression_dereference (&expr
-> data
.suffix
.expr
,
979 if (expr
-> data
.suffix
.len
)
980 expression_dereference (&expr
-> data
.suffix
.len
,
985 if (expr
-> data
.not)
986 expression_dereference (&expr
-> data
.not, name
);
990 if (expr
-> data
.packet
.offset
)
991 expression_dereference (&expr
-> data
.packet
.offset
,
993 if (expr
-> data
.packet
.len
)
994 expression_dereference (&expr
-> data
.packet
.len
,
998 case expr_extract_int8
:
999 case expr_extract_int16
:
1000 case expr_extract_int32
:
1001 if (expr
-> data
.extract_int
)
1002 expression_dereference (&expr
-> data
.extract_int
,
1006 case expr_const_data
:
1007 data_string_forget (&expr
-> data
.const_data
, name
);
1010 case expr_host_lookup
:
1011 if (expr
-> data
.host_lookup
)
1012 dns_host_entry_dereference (&expr
-> data
.host_lookup
,
1016 /* No subexpressions. */
1017 case expr_const_int
:
1028 free_expression (expr
, "expression_dereference");
1032 /* Free all of the state in an option state buffer. The buffer itself is
1033 not freed, since these buffers are always contained in other structures. */
1035 void option_state_dereference (state
)
1036 struct option_state
*state
;
1039 struct agent_options
*a
, *na
;
1040 struct option_tag
*ot
, *not;
1043 /* Having done the cons_options(), we can release the tree_cache
1045 for (i
= 0; i
< OPTION_HASH_SIZE
; i
++) {
1046 for (cp
= state
-> dhcp_hash
[i
]; cp
; cp
= next
) {
1048 option_cache_dereference
1049 ((struct option_cache
**)&cp
-> car
,
1050 "option_state_dereference");
1051 free_pair (cp
, "option_state_dereference");
1053 for (cp
= state
-> server_hash
[i
]; cp
; cp
= next
) {
1055 option_cache_dereference
1056 ((struct option_cache
**)&cp
-> car
,
1057 "option_state_dereference");
1061 /* We can also release the agent options, if any... */
1062 for (a
= state
-> agent_options
; a
; a
= na
) {
1064 for (ot
= a
-> first
; ot
; ot
= not) {
1071 /* Make a copy of the data in data_string, upping the buffer reference
1072 count if there's a buffer. */
1074 void data_string_copy (dest
, src
, name
)
1075 struct data_string
*dest
;
1076 struct data_string
*src
;
1080 buffer_reference (&dest
-> buffer
, src
-> buffer
, name
);
1081 dest
-> data
= src
-> data
;
1082 dest
-> terminated
= src
-> terminated
;
1083 dest
-> len
= src
-> len
;
1086 /* Release the reference count to a data string's buffer (if any) and
1087 zero out the other information, yielding the null data string. */
1089 void data_string_forget (data
, name
)
1090 struct data_string
*data
;
1094 buffer_dereference (&data
-> buffer
, name
);
1095 memset (data
, 0, sizeof *data
);
1098 /* Make a copy of the data in data_string, upping the buffer reference
1099 count if there's a buffer. */
1101 void data_string_truncate (dp
, len
)
1102 struct data_string
*dp
;
1105 if (len
< dp
-> len
) {
1106 dp
-> terminated
= 0;
1111 int is_boolean_expression (expr
)
1112 struct expression
*expr
;
1114 return (expr
-> op
== expr_check
||
1115 expr
-> op
== expr_equal
||
1116 expr
-> op
== expr_and
||
1117 expr
-> op
== expr_or
||
1118 expr
-> op
== expr_not
);
1121 int is_data_expression (expr
)
1122 struct expression
*expr
;
1124 return (expr
-> op
== expr_substring
||
1125 expr
-> op
== expr_suffix
||
1126 expr
-> op
== expr_option
||
1127 expr
-> op
== expr_hardware
||
1128 expr
-> op
== expr_const_data
||
1129 expr
-> op
== expr_packet
||
1130 expr
-> op
== expr_concat
||
1131 expr
-> op
== expr_host_lookup
);
1134 int is_numeric_expression (expr
)
1135 struct expression
*expr
;
1137 return (expr
-> op
== expr_extract_int8
||
1138 expr
-> op
== expr_extract_int16
||
1139 expr
-> op
== expr_extract_int32
||
1140 expr
-> op
== expr_const_int
);
1143 static int op_val
PROTO ((enum expr_op
));
1145 static int op_val (op
)
1152 case expr_substring
:
1155 case expr_host_lookup
:
1160 case expr_const_data
:
1161 case expr_extract_int8
:
1162 case expr_extract_int16
:
1163 case expr_extract_int32
:
1164 case expr_const_int
:
1180 int op_precedence (op1
, op2
)
1181 enum expr_op op1
, op2
;
1185 return op_val (op1
) - op_val (op2
);
1188 enum expression_context
op_context (op
)
1195 case expr_substring
:
1198 case expr_host_lookup
:
1203 case expr_const_data
:
1204 case expr_extract_int8
:
1205 case expr_extract_int16
:
1206 case expr_extract_int32
:
1207 case expr_const_int
:
1212 return context_data
;
1215 return context_boolean
;
1218 return context_boolean
;