3 Routines for manipulating parse trees... */
6 * Copyright (c) 2004-2007,2009 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.
23 * Redwood City, CA 94063
25 * https://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 * ``https://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''.
36 #include <omapip/omapip_p.h>
44 struct binding_scope
*global_scope
;
46 static int do_host_lookup
PROTO ((struct data_string
*,
47 struct dns_host_entry
*));
49 #define DS_SPRINTF_SIZE 128
52 * If we are using a data_string structure to hold a NUL-terminated
53 * ASCII string, this function can be used to append a printf-formatted
54 * string to the end of it. The data_string structure will be resized to
55 * be big enough to hold the new string.
57 * If the append works, then 1 is returned.
59 * If it is not possible to allocate a buffer big enough to hold the
60 * new value, then the old data_string is unchanged, and 0 is returned.
63 data_string_sprintfa(struct data_string
*ds
, const char *fmt
, ...) {
69 struct buffer
*tmp_buffer
;
72 * If the data_string is empty, then initialize it.
74 if (ds
->data
== NULL
) {
75 /* INSIST(ds.buffer == NULL); */
76 if (!buffer_allocate(&ds
->buffer
, DS_SPRINTF_SIZE
, MDL
)) {
79 ds
->data
= ds
->buffer
->data
;
80 ds
->len
= DS_SPRINTF_SIZE
;
81 *((char *)ds
->data
) = '\0';
85 * Get the length of the string, and figure out how much space
88 cur_strlen
= strlen((char *)ds
->data
);
89 max
= ds
->len
- cur_strlen
;
92 * Use vsnprintf(), which won't write past our space, but will
93 * tell us how much space it wants.
96 vsnprintf_ret
= vsnprintf((char *)ds
->data
+cur_strlen
, max
, fmt
, args
);
98 /* INSIST(vsnprintf_ret >= 0); */
101 * If our buffer is not big enough, we need a new buffer.
103 if (vsnprintf_ret
>= max
) {
105 * Figure out a size big enough.
107 new_len
= ds
->len
* 2;
108 while (new_len
<= cur_strlen
+ vsnprintf_ret
) {
113 * Create a new buffer and fill it.
116 if (!buffer_allocate(&tmp_buffer
, new_len
, MDL
)) {
118 * If we can't create a big enough buffer,
119 * we should remove any truncated output that we had.
121 *((char *)ds
->data
+cur_strlen
) = '\0';
125 memcpy(tmp_buffer
->data
, ds
->data
, cur_strlen
);
127 /* Rerun the vsprintf. */
129 vsprintf((char *)tmp_buffer
->data
+ cur_strlen
, fmt
, args
);
133 * Replace our old buffer with the new buffer.
135 buffer_dereference(&ds
->buffer
, MDL
);
136 buffer_reference(&ds
->buffer
, tmp_buffer
, MDL
);
137 buffer_dereference(&tmp_buffer
, MDL
);
138 ds
->data
= ds
->buffer
->data
;
148 pair foo
= (pair
)dmalloc (sizeof *foo
, MDL
);
150 log_fatal ("no memory for cons.");
156 int make_const_option_cache (oc
, buffer
, data
, len
, option
, file
, line
)
157 struct option_cache
**oc
;
158 struct buffer
**buffer
;
161 struct option
*option
;
171 bp
= (struct buffer
*)0;
172 if (!buffer_allocate (&bp
, len
, file
, line
)) {
173 log_error ("%s(%d): can't allocate buffer.",
179 if (!option_cache_allocate (oc
, file
, line
)) {
180 log_error ("%s(%d): can't allocate option cache.", file
, line
);
181 buffer_dereference (&bp
, file
, line
);
185 (*oc
) -> data
.len
= len
;
186 (*oc
) -> data
.buffer
= bp
;
187 (*oc
) -> data
.data
= &bp
-> data
[0];
188 (*oc
) -> data
.terminated
= 0;
190 memcpy (&bp
-> data
[0], data
, len
);
191 option_reference(&((*oc
)->option
), option
, MDL
);
195 int make_host_lookup (expr
, name
)
196 struct expression
**expr
;
199 if (!expression_allocate (expr
, MDL
)) {
200 log_error ("No memory for host lookup tree node.");
203 (*expr
) -> op
= expr_host_lookup
;
204 if (!enter_dns_host (&((*expr
) -> data
.host_lookup
), name
)) {
205 expression_dereference (expr
, MDL
);
211 int enter_dns_host (dh
, name
)
212 struct dns_host_entry
**dh
;
215 /* XXX This should really keep a hash table of hostnames
216 XXX and just add a new reference to a hostname that
217 XXX already exists, if possible, rather than creating
218 XXX a new structure. */
219 if (!dns_host_entry_allocate (dh
, name
, MDL
)) {
220 log_error ("Can't allocate space for new host.");
226 int make_const_data (struct expression
**expr
, const unsigned char *data
,
227 unsigned len
, int terminated
, int allocate
,
228 const char *file
, int line
)
230 struct expression
*nt
;
232 if (!expression_allocate (expr
, file
, line
)) {
233 log_error ("No memory for make_const_data tree node.");
240 if (!buffer_allocate (&nt
-> data
.const_data
.buffer
,
241 len
+ terminated
, file
, line
)) {
242 log_error ("Can't allocate const_data buffer");
243 expression_dereference (expr
, file
, line
);
246 nt
-> data
.const_data
.data
=
247 &nt
-> data
.const_data
.buffer
-> data
[0];
248 memcpy (nt
-> data
.const_data
.buffer
-> data
,
249 data
, len
+ terminated
);
251 nt
-> data
.const_data
.data
= data
;
252 nt
-> data
.const_data
.terminated
= terminated
;
254 nt
-> data
.const_data
.data
= 0;
256 nt
-> op
= expr_const_data
;
257 nt
-> data
.const_data
.len
= len
;
261 int make_const_int (expr
, val
)
262 struct expression
**expr
;
265 if (!expression_allocate (expr
, MDL
)) {
266 log_error ("No memory for make_const_int tree node.");
270 (*expr
) -> op
= expr_const_int
;
271 (*expr
) -> data
.const_int
= val
;
275 int make_concat (expr
, left
, right
)
276 struct expression
**expr
;
277 struct expression
*left
, *right
;
279 /* If we're concatenating a null tree to a non-null tree, just
280 return the non-null tree; if both trees are null, return
285 expression_reference (expr
, right
, MDL
);
289 expression_reference (expr
, left
, MDL
);
293 /* Otherwise, allocate a new node to concatenate the two. */
294 if (!expression_allocate (expr
, MDL
)) {
295 log_error ("No memory for concatenation expression node.");
299 (*expr
) -> op
= expr_concat
;
300 expression_reference (&(*expr
) -> data
.concat
[0], left
, MDL
);
301 expression_reference (&(*expr
) -> data
.concat
[1], right
, MDL
);
305 int make_encapsulation (expr
, name
)
306 struct expression
**expr
;
307 struct data_string
*name
;
309 /* Allocate a new node to store the encapsulation. */
310 if (!expression_allocate (expr
, MDL
)) {
311 log_error ("No memory for encapsulation expression node.");
315 (*expr
) -> op
= expr_encapsulate
;
316 data_string_copy (&(*expr
) -> data
.encapsulate
, name
, MDL
);
320 int make_substring (new, expr
, offset
, length
)
321 struct expression
**new;
322 struct expression
*expr
;
323 struct expression
*offset
;
324 struct expression
*length
;
326 /* Allocate an expression node to compute the substring. */
327 if (!expression_allocate (new, MDL
)) {
328 log_error ("no memory for substring expression.");
331 (*new) -> op
= expr_substring
;
332 expression_reference (&(*new) -> data
.substring
.expr
, expr
, MDL
);
333 expression_reference (&(*new) -> data
.substring
.offset
, offset
, MDL
);
334 expression_reference (&(*new) -> data
.substring
.len
, length
, MDL
);
338 int make_limit (new, expr
, limit
)
339 struct expression
**new;
340 struct expression
*expr
;
343 /* Allocate a node to enforce a limit on evaluation. */
344 if (!expression_allocate (new, MDL
))
345 log_error ("no memory for limit expression");
346 (*new) -> op
= expr_substring
;
347 expression_reference (&(*new) -> data
.substring
.expr
, expr
, MDL
);
349 /* Offset is a constant 0. */
350 if (!expression_allocate (&(*new) -> data
.substring
.offset
, MDL
)) {
351 log_error ("no memory for limit offset expression");
352 expression_dereference (new, MDL
);
355 (*new) -> data
.substring
.offset
-> op
= expr_const_int
;
356 (*new) -> data
.substring
.offset
-> data
.const_int
= 0;
358 /* Length is a constant: the specified limit. */
359 if (!expression_allocate (&(*new) -> data
.substring
.len
, MDL
)) {
360 log_error ("no memory for limit length expression");
361 expression_dereference (new, MDL
);
364 (*new) -> data
.substring
.len
-> op
= expr_const_int
;
365 (*new) -> data
.substring
.len
-> data
.const_int
= limit
;
370 int option_cache (struct option_cache
**oc
, struct data_string
*dp
,
371 struct expression
*expr
, struct option
*option
,
372 const char *file
, int line
)
374 if (!option_cache_allocate (oc
, file
, line
))
377 data_string_copy (&(*oc
) -> data
, dp
, file
, line
);
379 expression_reference (&(*oc
) -> expression
, expr
, file
, line
);
380 option_reference(&(*oc
)->option
, option
, MDL
);
384 int make_let (result
, name
)
385 struct executable_statement
**result
;
388 if (!(executable_statement_allocate (result
, MDL
)))
391 (*result
) -> op
= let_statement
;
392 (*result
) -> data
.let
.name
= dmalloc (strlen (name
) + 1, MDL
);
393 if (!(*result
) -> data
.let
.name
) {
394 executable_statement_dereference (result
, MDL
);
397 strcpy ((*result
) -> data
.let
.name
, name
);
401 static int do_host_lookup (result
, dns
)
402 struct data_string
*result
;
403 struct dns_host_entry
*dns
;
410 log_debug ("time: now = %d dns = %d diff = %d",
411 cur_time
, dns
-> timeout
, cur_time
- dns
-> timeout
);
414 /* If the record hasn't timed out, just copy the data and return. */
415 if (cur_time
<= dns
-> timeout
) {
417 log_debug ("easy copy: %d %s",
420 ? inet_ntoa (*(struct in_addr
*)(dns
-> data
.data
))
423 data_string_copy (result
, &dns
-> data
, MDL
);
427 log_debug ("Looking up %s", dns
-> hostname
);
430 /* Otherwise, look it up... */
431 h
= gethostbyname (dns
-> hostname
);
437 log_error ("%s: host unknown.", dns
-> hostname
);
441 log_error ("%s: temporary name server failure",
445 log_error ("%s: name server failed", dns
-> hostname
);
448 log_error ("%s: no A record associated with address",
451 #endif /* !NO_H_ERRNO */
453 /* Okay to try again after a minute. */
454 dns
-> timeout
= cur_time
+ 60;
455 data_string_forget (&dns
-> data
, MDL
);
460 log_debug ("Lookup succeeded; first address is %s",
461 inet_ntoa (h
-> h_addr_list
[0]));
464 /* Count the number of addresses we got... */
465 for (count
= 0; h
-> h_addr_list
[count
]; count
++)
468 /* Dereference the old data, if any. */
469 data_string_forget (&dns
-> data
, MDL
);
471 /* Do we need to allocate more memory? */
472 new_len
= count
* h
-> h_length
;
473 if (!buffer_allocate (&dns
-> data
.buffer
, new_len
, MDL
))
475 log_error ("No memory for %s.", dns
-> hostname
);
479 dns
-> data
.data
= &dns
-> data
.buffer
-> data
[0];
480 dns
-> data
.len
= new_len
;
481 dns
-> data
.terminated
= 0;
483 /* Addresses are conveniently stored one to the buffer, so we
484 have to copy them out one at a time... :'( */
485 for (i
= 0; i
< count
; i
++) {
486 memcpy (&dns
-> data
.buffer
-> data
[h
-> h_length
* i
],
487 h
-> h_addr_list
[i
], (unsigned)(h
-> h_length
));
490 log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
491 *(int *)(dns
-> buffer
), h
-> h_addr_list
[0]);
494 /* XXX Set the timeout for an hour from now.
495 XXX This should really use the time on the DNS reply. */
496 dns
-> timeout
= cur_time
+ 3600;
499 log_debug ("hard copy: %d %s", dns
-> data
.len
,
501 ? inet_ntoa (*(struct in_addr
*)(dns
-> data
.data
)) : 0));
503 data_string_copy (result
, &dns
-> data
, MDL
);
507 int evaluate_expression (result
, packet
, lease
, client_state
,
508 in_options
, cfg_options
, scope
, expr
, file
, line
)
509 struct binding_value
**result
;
510 struct packet
*packet
;
512 struct client_state
*client_state
;
513 struct option_state
*in_options
;
514 struct option_state
*cfg_options
;
515 struct binding_scope
**scope
;
516 struct expression
*expr
;
520 struct binding_value
*bv
;
522 struct binding
*binding
;
524 bv
= (struct binding_value
*)0;
526 if (expr
-> op
== expr_variable_reference
) {
527 if (!scope
|| !*scope
)
530 binding
= find_binding (*scope
, expr
-> data
.variable
);
532 if (binding
&& binding
-> value
) {
534 binding_value_reference (result
,
540 } else if (expr
-> op
== expr_funcall
) {
541 struct string_list
*s
;
542 struct expression
*arg
;
543 struct binding_scope
*ns
;
546 if (!scope
|| !*scope
) {
547 log_error ("%s: no such function.",
548 expr
-> data
.funcall
.name
);
552 binding
= find_binding (*scope
, expr
-> data
.funcall
.name
);
554 if (!binding
|| !binding
-> value
) {
555 log_error ("%s: no such function.",
556 expr
-> data
.funcall
.name
);
559 if (binding
-> value
-> type
!= binding_function
) {
560 log_error ("%s: not a function.",
561 expr
-> data
.funcall
.name
);
565 /* Create a new binding scope in which to define
566 the arguments to the function. */
567 ns
= (struct binding_scope
*)0;
568 if (!binding_scope_allocate (&ns
, MDL
)) {
569 log_error ("%s: can't allocate argument scope.",
570 expr
-> data
.funcall
.name
);
574 arg
= expr
-> data
.funcall
.arglist
;
575 s
= binding
-> value
-> value
.fundef
-> args
;
577 nb
= dmalloc (sizeof *nb
, MDL
);
580 binding_scope_dereference (&ns
, MDL
);
583 memset (nb
, 0, sizeof *nb
);
584 nb
-> name
= dmalloc (strlen (s
-> string
) + 1,
587 strcpy (nb
-> name
, s
-> string
);
590 nb
= (struct binding
*)0;
594 evaluate_expression (&nb
-> value
, packet
, lease
,
596 in_options
, cfg_options
, scope
,
597 arg
-> data
.arg
.val
, file
, line
);
598 nb
-> next
= ns
-> bindings
;
600 arg
= arg
-> data
.arg
.next
;
604 log_error ("%s: too many arguments.",
605 expr
-> data
.funcall
.name
);
606 binding_scope_dereference (&ns
, MDL
);
610 log_error ("%s: too few arguments.",
611 expr
-> data
.funcall
.name
);
612 binding_scope_dereference (&ns
, MDL
);
617 binding_scope_reference (&ns
-> outer
, *scope
, MDL
);
619 status
= (execute_statements
621 lease
, client_state
, in_options
, cfg_options
, &ns
,
622 binding
-> value
-> value
.fundef
-> statements
));
623 binding_scope_dereference (&ns
, MDL
);
627 } else if (is_boolean_expression (expr
)) {
628 if (!binding_value_allocate (&bv
, MDL
))
630 bv
-> type
= binding_boolean
;
631 status
= (evaluate_boolean_expression
632 (&bv
-> value
.boolean
, packet
, lease
, client_state
,
633 in_options
, cfg_options
, scope
, expr
));
634 } else if (is_numeric_expression (expr
)) {
635 if (!binding_value_allocate (&bv
, MDL
))
637 bv
-> type
= binding_numeric
;
638 status
= (evaluate_numeric_expression
639 (&bv
-> value
.intval
, packet
, lease
, client_state
,
640 in_options
, cfg_options
, scope
, expr
));
641 } else if (is_data_expression (expr
)) {
642 if (!binding_value_allocate (&bv
, MDL
))
644 bv
-> type
= binding_data
;
645 status
= (evaluate_data_expression
646 (&bv
-> value
.data
, packet
, lease
, client_state
,
647 in_options
, cfg_options
, scope
, expr
, MDL
));
648 #if defined (NSUPDATE_OLD)
649 } else if (is_dns_expression (expr
)) {
650 if (!binding_value_allocate (&bv
, MDL
))
652 bv
-> type
= binding_dns
;
653 status
= (evaluate_dns_expression
654 (&bv
-> value
.dns
, packet
, lease
, client_state
,
655 in_options
, cfg_options
, scope
, expr
));
658 log_error ("%s: invalid expression type: %d",
659 "evaluate_expression", expr
-> op
);
662 if (result
&& status
)
663 binding_value_reference (result
, bv
, file
, line
);
664 binding_value_dereference (&bv
, MDL
);
669 int binding_value_dereference (struct binding_value
**v
,
670 const char *file
, int line
)
672 struct binding_value
*bv
= *v
;
674 *v
= (struct binding_value
*)0;
676 /* Decrement the reference count. If it's nonzero, we're
679 rc_register (file
, line
, v
, bv
, bv
-> refcnt
, 1, RC_MISC
);
680 if (bv
-> refcnt
> 0)
682 if (bv
-> refcnt
< 0) {
683 log_error ("%s(%d): negative refcnt!", file
, line
);
684 #if defined (DEBUG_RC_HISTORY)
685 dump_rc_history (bv
);
687 #if defined (POINTER_DEBUG)
694 switch (bv
-> type
) {
695 case binding_boolean
:
696 case binding_numeric
:
699 if (bv
-> value
.data
.buffer
)
700 data_string_forget (&bv
-> value
.data
, file
, line
);
703 #if defined (NSUPDATE_OLD)
704 if (bv
-> value
.dns
) {
705 if (bv
-> value
.dns
-> r_data
) {
706 dfree (bv
-> value
.dns
-> r_data_ephem
, MDL
);
707 bv
-> value
.dns
-> r_data
= (unsigned char *)0;
708 bv
-> value
.dns
-> r_data_ephem
=
711 minires_freeupdrec (bv
-> value
.dns
);
716 log_error ("%s(%d): invalid binding type: %d",
717 file
, line
, bv
-> type
);
720 free_binding_value(bv
, file
, line
);
724 #if defined (NSUPDATE_OLD)
725 int evaluate_dns_expression (result
, packet
, lease
, client_state
, in_options
,
726 cfg_options
, scope
, expr
)
728 struct packet
*packet
;
730 struct client_state
*client_state
;
731 struct option_state
*in_options
;
732 struct option_state
*cfg_options
;
733 struct binding_scope
**scope
;
734 struct expression
*expr
;
736 unsigned long ttl
= 0;
738 struct data_string name
, data
;
741 if (!result
|| *result
) {
742 log_error ("evaluate_dns_expression called with non-null %s",
744 #if defined (POINTER_DEBUG)
751 switch (expr
-> op
) {
752 #if defined (NSUPDATE)
754 r0
= evaluate_numeric_expression (&ttl
, packet
, lease
,
756 in_options
, cfg_options
,
758 expr
-> data
.ns_add
.ttl
);
765 case expr_ns_not_exists
:
768 memset (&name
, 0, sizeof name
);
769 r1
= evaluate_data_expression (&name
, packet
, lease
,
771 in_options
, cfg_options
, scope
,
772 expr
-> data
.ns_add
.rrname
,
775 /* The result of the evaluation may or may not
776 be NUL-terminated, but we need it
777 terminated for sure, so we have to allocate
778 a buffer and terminate it. */
779 tname
= dmalloc (name
.len
+ 1, MDL
);
783 data_string_forget (&name
, MDL
);
785 memcpy (tname
, name
.data
, name
.len
);
786 tname
[name
.len
] = 0;
787 memset (&data
, 0, sizeof data
);
788 r2
= evaluate_data_expression
789 (&data
, packet
, lease
, client_state
,
790 in_options
, cfg_options
, scope
,
791 expr
-> data
.ns_add
.rrdata
, MDL
);
797 if (r0
&& r1
&& (r2
|| expr
-> op
!= expr_ns_add
)) {
798 *result
= minires_mkupdrec (((expr
-> op
== expr_ns_add
||
799 expr
-> op
== expr_ns_delete
)
800 ? S_UPDATE
: S_PREREQ
),
802 expr
-> data
.ns_add
.rrclass
,
803 expr
-> data
.ns_add
.rrtype
,
808 data_string_forget (&data
, MDL
);
813 /* As a special case, if we get exactly
814 four bytes of data, it's an IP address
815 represented as a 32-bit quantity, which
816 is actually what we *should* be getting
817 here. Because res_mkupdrec is currently
818 broken and expects a dotted quad, convert
819 it. This should be fixed when the new
820 resolver is merged. */
822 (*result
) -> r_data_ephem
=
824 if (!(*result
) -> r_data_ephem
)
826 (*result
) -> r_data
=
827 (*result
) -> r_data_ephem
;
828 /*%Audit% 16 bytes max. %2004.06.17,Safe%*/
829 sprintf ((char *)(*result
) -> r_data_ephem
,
831 data
.data
[0] & 0xff,
832 data
.data
[1] & 0xff,
833 data
.data
[2] & 0xff,
834 data
.data
[3] & 0xff);
835 (*result
) -> r_size
=
836 strlen ((const char *)
837 (*result
) -> r_data
);
839 (*result
) -> r_size
= data
.len
;
840 (*result
) -> r_data_ephem
=
841 dmalloc (data
.len
, MDL
);
842 if (!(*result
) -> r_data_ephem
) {
843 dpngood
: /* double plus ungood. */
844 minires_freeupdrec (*result
);
848 (*result
) -> r_data
=
849 (*result
) -> r_data_ephem
;
850 memcpy ((*result
) -> r_data_ephem
,
851 data
.data
, data
.len
);
854 (*result
) -> r_data
= 0;
855 (*result
) -> r_size
= 0;
857 switch (expr
-> op
) {
859 (*result
) -> r_opcode
= ADD
;
862 (*result
) -> r_opcode
= DELETE
;
865 (*result
) -> r_opcode
= YXRRSET
;
867 case expr_ns_not_exists
:
868 (*result
) -> r_opcode
= NXRRSET
;
871 /* Can't happen, but satisfy gcc. */
878 data_string_forget (&name
, MDL
);
882 data_string_forget (&data
, MDL
);
883 /* One flaw in the thinking here: an IP address and an
884 ASCII string both look like data expressions, but
885 for A records, we want an ASCII string, not a
886 binary IP address. Do I need to turn binary IP
887 addresses into a separate type? */
889 (r2
|| expr
-> op
!= expr_ns_add
) && *result
);
895 case expr_ns_not_exists
:
899 log_error ("%s: dns values for functions not supported.",
900 expr
-> data
.funcall
.name
);
903 case expr_variable_reference
:
904 log_error ("%s: dns values for variables not supported.",
905 expr
-> data
.variable
);
911 case expr_regex_match
:
912 case expr_iregex_match
:
920 case expr_variable_exists
:
921 log_error ("Boolean opcode in evaluate_dns_expression: %d",
932 case expr_const_data
:
935 case expr_encapsulate
:
936 case expr_host_lookup
:
937 case expr_encode_int8
:
938 case expr_encode_int16
:
939 case expr_encode_int32
:
940 case expr_binary_to_ascii
:
944 case expr_pick_first_value
:
945 case expr_host_decl_name
:
946 case expr_config_option
:
947 case expr_leased_address
:
949 case expr_gethostname
:
950 log_error ("Data opcode in evaluate_dns_expression: %d",
954 case expr_extract_int8
:
955 case expr_extract_int16
:
956 case expr_extract_int32
:
958 case expr_lease_time
:
959 case expr_dns_transaction
:
965 case expr_binary_and
:
967 case expr_binary_xor
:
968 case expr_client_state
:
969 log_error ("Numeric opcode in evaluate_dns_expression: %d",
974 log_error ("Function opcode in evaluate_dns_expression: %d",
982 log_error ("Bogus opcode in evaluate_dns_expression: %d",
986 #endif /* defined (NSUPDATE_OLD) */
988 int evaluate_boolean_expression (result
, packet
, lease
, client_state
,
989 in_options
, cfg_options
, scope
, expr
)
991 struct packet
*packet
;
993 struct client_state
*client_state
;
994 struct option_state
*in_options
;
995 struct option_state
*cfg_options
;
996 struct binding_scope
**scope
;
997 struct expression
*expr
;
999 struct data_string left
, right
;
1002 struct binding
*binding
;
1003 struct binding_value
*bv
, *obv
;
1005 int regflags
= REG_EXTENDED
| REG_NOSUB
;
1009 switch (expr
-> op
) {
1011 *result
= check_collection (packet
, lease
,
1012 expr
-> data
.check
);
1013 #if defined (DEBUG_EXPRESSIONS)
1014 log_debug ("bool: check (%s) returns %s",
1015 expr
-> data
.check
-> name
,
1016 *result
? "true" : "false");
1021 case expr_not_equal
:
1022 bv
= obv
= (struct binding_value
*)0;
1023 sleft
= evaluate_expression (&bv
, packet
, lease
, client_state
,
1024 in_options
, cfg_options
, scope
,
1025 expr
-> data
.equal
[0], MDL
);
1026 sright
= evaluate_expression (&obv
, packet
, lease
,
1027 client_state
, in_options
,
1029 expr
-> data
.equal
[1], MDL
);
1030 if (sleft
&& sright
) {
1031 if (bv
-> type
!= obv
-> type
)
1032 *result
= expr
-> op
== expr_not_equal
;
1034 switch (obv
-> type
) {
1035 case binding_boolean
:
1036 if (bv
-> value
.boolean
== obv
-> value
.boolean
)
1037 *result
= expr
-> op
== expr_equal
;
1039 *result
= expr
-> op
== expr_not_equal
;
1043 if ((bv
-> value
.data
.len
==
1044 obv
-> value
.data
.len
) &&
1045 !memcmp (bv
-> value
.data
.data
,
1046 obv
-> value
.data
.data
,
1047 obv
-> value
.data
.len
))
1048 *result
= expr
-> op
== expr_equal
;
1050 *result
= expr
-> op
== expr_not_equal
;
1053 case binding_numeric
:
1054 if (bv
-> value
.intval
== obv
-> value
.intval
)
1055 *result
= expr
-> op
== expr_equal
;
1057 *result
= expr
-> op
== expr_not_equal
;
1059 #if defined (NSUPDATE_OLD)
1061 #if defined (NSUPDATE)
1062 /* XXX This should be a comparison for equal
1063 XXX values, not for identity. */
1064 if (bv
-> value
.dns
== obv
-> value
.dns
)
1065 *result
= expr
-> op
== expr_equal
;
1067 *result
= expr
-> op
== expr_not_equal
;
1069 *result
= expr
-> op
== expr_not_equal
;
1072 #endif /* NSUPDATE_OLD */
1073 case binding_function
:
1074 if (bv
-> value
.fundef
== obv
-> value
.fundef
)
1075 *result
= expr
-> op
== expr_equal
;
1077 *result
= expr
-> op
== expr_not_equal
;
1080 *result
= expr
-> op
== expr_not_equal
;
1084 } else if (!sleft
&& !sright
)
1085 *result
= expr
-> op
== expr_equal
;
1087 *result
= expr
-> op
== expr_not_equal
;
1089 #if defined (DEBUG_EXPRESSIONS)
1090 log_debug ("bool: %sequal = %s",
1091 expr
-> op
== expr_not_equal
? "not" : "",
1092 (*result
? "true" : "false"));
1095 binding_value_dereference (&bv
, MDL
);
1097 binding_value_dereference (&obv
, MDL
);
1100 case expr_iregex_match
:
1102 regflags
|= REG_ICASE
;
1105 case expr_regex_match
:
1107 memset(&left
, 0, sizeof left
);
1108 bleft
= evaluate_data_expression(&left
, packet
, lease
,
1110 in_options
, cfg_options
,
1112 expr
->data
.equal
[0], MDL
);
1113 memset(&right
, 0, sizeof right
);
1114 bright
= evaluate_data_expression(&right
, packet
, lease
,
1116 in_options
, cfg_options
,
1118 expr
->data
.equal
[1], MDL
);
1121 memset(&re
, 0, sizeof(re
));
1122 if (bleft
&& bright
&&
1123 (regcomp(&re
, (char *)right
.data
, regflags
) == 0) &&
1124 (regexec(&re
, (char *)left
.data
, (size_t)0, NULL
, 0) == 0))
1127 #if defined (DEBUG_EXPRESSIONS)
1128 log_debug("bool: %s ~= %s yields %s",
1129 bleft
? print_hex_1(left
.len
, left
.data
, 20)
1131 bright
? print_hex_2 (right
.len
, right
.data
, 20)
1133 *result
? "true" : "false");
1137 data_string_forget(&left
, MDL
);
1139 data_string_forget(&right
, MDL
);
1144 * If we have bleft and bright then we have a good
1145 * syntax, otherwise not.
1147 * XXX: we don't warn on invalid regular expression
1148 * syntax, should we?
1150 return bleft
&& bright
;
1152 /* It shouldn't be possible to configure a regex operator
1153 * when there's no support.
1155 log_fatal("Impossible condition at %s:%d.", MDL
);
1160 sleft
= evaluate_boolean_expression (&bleft
, packet
, lease
,
1162 in_options
, cfg_options
,
1164 expr
-> data
.and [0]);
1166 sright
= evaluate_boolean_expression
1167 (&bright
, packet
, lease
, client_state
,
1168 in_options
, cfg_options
,
1169 scope
, expr
-> data
.and [1]);
1171 sright
= bright
= 0;
1173 #if defined (DEBUG_EXPRESSIONS)
1174 log_debug ("bool: and (%s, %s) = %s",
1175 sleft
? (bleft
? "true" : "false") : "NULL",
1176 sright
? (bright
? "true" : "false") : "NULL",
1178 ? (bleft
&& bright
? "true" : "false") : "NULL"));
1180 if (sleft
&& sright
) {
1181 *result
= bleft
&& bright
;
1188 sleft
= evaluate_boolean_expression (&bleft
, packet
, lease
,
1190 in_options
, cfg_options
,
1192 expr
-> data
.or [0]);
1193 if (!sleft
|| !bleft
)
1194 sright
= evaluate_boolean_expression
1195 (&bright
, packet
, lease
, client_state
,
1196 in_options
, cfg_options
,
1197 scope
, expr
-> data
.or [1]);
1200 #if defined (DEBUG_EXPRESSIONS)
1201 log_debug ("bool: or (%s, %s) = %s",
1202 sleft
? (bleft
? "true" : "false") : "NULL",
1203 sright
? (bright
? "true" : "false") : "NULL",
1205 ? (bleft
|| bright
? "true" : "false") : "NULL"));
1207 if (sleft
|| sright
) {
1208 *result
= bleft
|| bright
;
1214 sleft
= evaluate_boolean_expression (&bleft
, packet
, lease
,
1216 in_options
, cfg_options
,
1219 #if defined (DEBUG_EXPRESSIONS)
1220 log_debug ("bool: not (%s) = %s",
1221 sleft
? (bleft
? "true" : "false") : "NULL",
1223 ? (!bleft
? "true" : "false") : "NULL"));
1233 memset (&left
, 0, sizeof left
);
1235 !get_option (&left
, expr
-> data
.exists
-> universe
,
1236 packet
, lease
, client_state
,
1237 in_options
, cfg_options
, in_options
,
1238 scope
, expr
-> data
.exists
-> code
, MDL
))
1242 data_string_forget (&left
, MDL
);
1244 #if defined (DEBUG_EXPRESSIONS)
1245 log_debug ("bool: exists %s.%s = %s",
1246 expr
-> data
.option
-> universe
-> name
,
1247 expr
-> data
.option
-> name
,
1248 *result
? "true" : "false");
1254 #if defined (DEBUG_EXPRESSIONS)
1255 log_debug ("bool: known = NULL");
1259 #if defined (DEBUG_EXPRESSIONS)
1260 log_debug ("bool: known = %s",
1261 packet
-> known
? "true" : "false");
1263 *result
= packet
-> known
;
1267 if (!lease
|| !(lease
-> flags
& STATIC_LEASE
)) {
1268 #if defined (DEBUG_EXPRESSIONS)
1269 log_debug ("bool: static = false (%s %s %s %d)",
1271 (lease
&& (lease
-> flags
& STATIC_LEASE
)
1273 piaddr (lease
-> ip_addr
),
1274 lease
? lease
-> flags
: 0);
1279 #if defined (DEBUG_EXPRESSIONS)
1280 log_debug ("bool: static = true");
1285 case expr_variable_exists
:
1286 if (scope
&& *scope
) {
1287 binding
= find_binding (*scope
, expr
-> data
.variable
);
1290 if (binding
-> value
)
1298 #if defined (DEBUG_EXPRESSIONS)
1299 log_debug ("boolean: %s? = %s", expr
-> data
.variable
,
1300 *result
? "true" : "false");
1304 case expr_variable_reference
:
1305 if (scope
&& *scope
) {
1306 binding
= find_binding (*scope
, expr
-> data
.variable
);
1308 if (binding
&& binding
-> value
) {
1309 if (binding
-> value
-> type
==
1311 *result
= binding
-> value
-> value
.boolean
;
1314 log_error ("binding type %d in %s.",
1315 binding
-> value
-> type
,
1316 "evaluate_boolean_expression");
1323 #if defined (DEBUG_EXPRESSIONS)
1324 log_debug ("boolean: %s = %s", expr
-> data
.variable
,
1325 sleft
? (*result
? "true" : "false") : "NULL");
1330 bv
= (struct binding_value
*)0;
1331 sleft
= evaluate_expression (&bv
, packet
, lease
, client_state
,
1332 in_options
, cfg_options
,
1335 if (bv
-> type
!= binding_boolean
)
1336 log_error ("%s() returned type %d in %s.",
1337 expr
-> data
.funcall
.name
,
1339 "evaluate_boolean_expression");
1341 *result
= bv
-> value
.boolean
;
1342 binding_value_dereference (&bv
, MDL
);
1344 #if defined (DEBUG_EXPRESSIONS)
1345 log_debug ("boolean: %s() = %s", expr
-> data
.funcall
.name
,
1346 sleft
? (*result
? "true" : "false") : "NULL");
1352 case expr_substring
:
1358 case expr_const_data
:
1361 case expr_encapsulate
:
1362 case expr_host_lookup
:
1363 case expr_encode_int8
:
1364 case expr_encode_int16
:
1365 case expr_encode_int32
:
1366 case expr_binary_to_ascii
:
1368 case expr_pick_first_value
:
1369 case expr_host_decl_name
:
1370 case expr_config_option
:
1371 case expr_leased_address
:
1375 case expr_gethostname
:
1376 log_error ("Data opcode in evaluate_boolean_expression: %d",
1380 case expr_extract_int8
:
1381 case expr_extract_int16
:
1382 case expr_extract_int32
:
1383 case expr_const_int
:
1384 case expr_lease_time
:
1385 case expr_dns_transaction
:
1390 case expr_remainder
:
1391 case expr_binary_and
:
1392 case expr_binary_or
:
1393 case expr_binary_xor
:
1394 case expr_client_state
:
1395 log_error ("Numeric opcode in evaluate_boolean_expression: %d",
1400 case expr_ns_delete
:
1401 case expr_ns_exists
:
1402 case expr_ns_not_exists
:
1403 log_error ("dns opcode in evaluate_boolean_expression: %d",
1408 log_error ("function definition in evaluate_boolean_expr");
1415 log_error ("Bogus opcode in evaluate_boolean_expression: %d",
1420 int evaluate_data_expression (result
, packet
, lease
, client_state
,
1421 in_options
, cfg_options
, scope
, expr
, file
, line
)
1422 struct data_string
*result
;
1423 struct packet
*packet
;
1424 struct lease
*lease
;
1425 struct client_state
*client_state
;
1426 struct option_state
*in_options
;
1427 struct option_state
*cfg_options
;
1428 struct binding_scope
**scope
;
1429 struct expression
*expr
;
1433 struct data_string data
, other
;
1434 unsigned long offset
, len
, i
;
1437 struct binding
*binding
;
1439 struct binding_value
*bv
;
1441 switch (expr
-> op
) {
1442 /* Extract N bytes starting at byte M of a data string. */
1443 case expr_substring
:
1444 memset (&data
, 0, sizeof data
);
1445 s0
= evaluate_data_expression (&data
, packet
, lease
,
1447 in_options
, cfg_options
, scope
,
1448 expr
-> data
.substring
.expr
,
1451 /* Evaluate the offset and length. */
1452 s1
= evaluate_numeric_expression
1453 (&offset
, packet
, lease
, client_state
, in_options
,
1454 cfg_options
, scope
, expr
-> data
.substring
.offset
);
1455 s2
= evaluate_numeric_expression (&len
, packet
, lease
,
1457 in_options
, cfg_options
,
1459 expr
-> data
.substring
.len
);
1461 if (s0
&& s1
&& s2
) {
1462 /* If the offset is after end of the string,
1463 return an empty string. Otherwise, do the
1464 adjustments and return what's left. */
1465 if (data
.len
> offset
) {
1466 data_string_copy (result
, &data
, file
, line
);
1467 result
-> len
-= offset
;
1468 if (result
-> len
> len
) {
1469 result
-> len
= len
;
1470 result
-> terminated
= 0;
1472 result
-> data
+= offset
;
1478 #if defined (DEBUG_EXPRESSIONS)
1479 log_debug ("data: substring (%s, %s, %s) = %s",
1480 s0
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
1481 s1
? print_dec_1 (offset
) : "NULL",
1482 s2
? print_dec_2 (len
) : "NULL",
1483 (s3
? print_hex_2 (result
-> len
, result
-> data
, 30)
1487 data_string_forget (&data
, MDL
);
1492 /* Extract the last N bytes of a data string. */
1494 memset (&data
, 0, sizeof data
);
1495 s0
= evaluate_data_expression (&data
, packet
, lease
,
1497 in_options
, cfg_options
, scope
,
1498 expr
-> data
.suffix
.expr
, MDL
);
1499 /* Evaluate the length. */
1500 s1
= evaluate_numeric_expression (&len
, packet
, lease
,
1502 in_options
, cfg_options
,
1504 expr
-> data
.suffix
.len
);
1506 data_string_copy (result
, &data
, file
, line
);
1508 /* If we are returning the last N bytes of a
1509 string whose length is <= N, just return
1510 the string - otherwise, compute a new
1511 starting address and decrease the
1513 if (data
.len
> len
) {
1514 result
-> data
+= data
.len
- len
;
1515 result
-> len
= len
;
1517 data_string_forget (&data
, MDL
);
1520 #if defined (DEBUG_EXPRESSIONS)
1521 log_debug ("data: suffix (%s, %s) = %s",
1522 s0
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
1523 s1
? print_dec_1 (len
) : "NULL",
1525 ? print_hex_2 (result
-> len
, result
-> data
, 30)
1530 /* Convert string to lowercase. */
1532 memset(&data
, 0, sizeof data
);
1533 s0
= evaluate_data_expression(&data
, packet
, lease
,
1535 in_options
, cfg_options
, scope
,
1536 expr
->data
.lcase
, MDL
);
1539 result
->len
= data
.len
;
1540 if (buffer_allocate(&result
->buffer
,
1541 result
->len
+ data
.terminated
,
1543 result
->data
= &result
->buffer
->data
[0];
1544 memcpy(result
->buffer
->data
, data
.data
,
1545 data
.len
+ data
.terminated
);
1546 result
->terminated
= data
.terminated
;
1547 s
= (unsigned char *)result
->data
;
1548 for (i
= 0; i
< result
->len
; i
++, s
++)
1552 log_error("data: lcase: no buffer memory.");
1556 #if defined (DEBUG_EXPRESSIONS)
1557 log_debug("data: lcase (%s) = %s",
1558 s0
? print_hex_1(data
.len
, data
.data
, 30) : "NULL",
1559 s1
? print_hex_2(result
->len
, result
->data
, 30)
1563 data_string_forget(&data
, MDL
);
1566 /* Convert string to uppercase. */
1568 memset(&data
, 0, sizeof data
);
1569 s0
= evaluate_data_expression(&data
, packet
, lease
,
1571 in_options
, cfg_options
, scope
,
1572 expr
->data
.lcase
, MDL
);
1575 result
->len
= data
.len
;
1576 if (buffer_allocate(&result
->buffer
,
1577 result
->len
+ data
.terminated
,
1579 result
->data
= &result
->buffer
->data
[0];
1580 memcpy(result
->buffer
->data
, data
.data
,
1581 data
.len
+ data
.terminated
);
1582 result
->terminated
= data
.terminated
;
1583 s
= (unsigned char *)result
->data
;
1584 for (i
= 0; i
< result
->len
; i
++, s
++)
1588 log_error("data: lcase: no buffer memory.");
1592 #if defined (DEBUG_EXPRESSIONS)
1593 log_debug("data: ucase (%s) = %s",
1594 s0
? print_hex_1(data
.len
, data
.data
, 30) : "NULL",
1595 s1
? print_hex_2(result
->len
, result
->data
, 30)
1599 data_string_forget(&data
, MDL
);
1602 /* Extract an option. */
1605 s0
= get_option (result
,
1606 expr
-> data
.option
-> universe
,
1607 packet
, lease
, client_state
,
1608 in_options
, cfg_options
, in_options
,
1609 scope
, expr
-> data
.option
-> code
,
1614 #if defined (DEBUG_EXPRESSIONS)
1615 log_debug ("data: option %s.%s = %s",
1616 expr
-> data
.option
-> universe
-> name
,
1617 expr
-> data
.option
-> name
,
1618 s0
? print_hex_1 (result
-> len
, result
-> data
, 60)
1623 case expr_config_option
:
1625 s0
= get_option (result
,
1626 expr
-> data
.option
-> universe
,
1627 packet
, lease
, client_state
,
1628 in_options
, cfg_options
, cfg_options
,
1629 scope
, expr
-> data
.option
-> code
,
1634 #if defined (DEBUG_EXPRESSIONS)
1635 log_debug ("data: config-option %s.%s = %s",
1636 expr
-> data
.option
-> universe
-> name
,
1637 expr
-> data
.option
-> name
,
1638 s0
? print_hex_1 (result
-> len
, result
-> data
, 60)
1643 /* Combine the hardware type and address. */
1645 /* On the client, hardware is our hardware. */
1647 memset (result
, 0, sizeof *result
);
1649 client_state
-> interface
-> hw_address
.hbuf
;
1651 client_state
-> interface
-> hw_address
.hlen
;
1652 #if defined (DEBUG_EXPRESSIONS)
1653 log_debug ("data: hardware = %s",
1654 print_hex_1 (result
-> len
,
1655 result
-> data
, 60));
1660 /* The server cares about the client's hardware address,
1661 so only in the case where we are examining a packet can
1662 we return anything. */
1663 if (!packet
|| !packet
-> raw
) {
1664 log_error ("data: hardware: raw packet not available");
1667 if (packet
-> raw
-> hlen
> sizeof packet
-> raw
-> chaddr
) {
1668 log_error ("data: hardware: invalid hlen (%d)\n",
1669 packet
-> raw
-> hlen
);
1672 result
-> len
= packet
-> raw
-> hlen
+ 1;
1673 if (buffer_allocate (&result
-> buffer
, result
-> len
,
1675 result
-> data
= &result
-> buffer
-> data
[0];
1676 result
-> buffer
-> data
[0] = packet
-> raw
-> htype
;
1677 memcpy (&result
-> buffer
-> data
[1],
1678 packet
-> raw
-> chaddr
,
1679 packet
-> raw
-> hlen
);
1680 result
-> terminated
= 0;
1682 log_error ("data: hardware: no memory for buffer.");
1685 #if defined (DEBUG_EXPRESSIONS)
1686 log_debug ("data: hardware = %s",
1687 print_hex_1 (result
-> len
, result
-> data
, 60));
1691 /* Extract part of the raw packet. */
1693 if (!packet
|| !packet
-> raw
) {
1694 log_error ("data: packet: raw packet not available");
1698 s0
= evaluate_numeric_expression (&offset
, packet
, lease
,
1700 in_options
, cfg_options
,
1702 expr
-> data
.packet
.offset
);
1703 s1
= evaluate_numeric_expression (&len
,
1704 packet
, lease
, client_state
,
1705 in_options
, cfg_options
,
1707 expr
-> data
.packet
.len
);
1708 if (s0
&& s1
&& offset
< packet
-> packet_length
) {
1709 if (offset
+ len
> packet
-> packet_length
)
1711 packet
-> packet_length
- offset
;
1713 result
-> len
= len
;
1714 if (buffer_allocate (&result
-> buffer
,
1715 result
-> len
, file
, line
)) {
1716 result
-> data
= &result
-> buffer
-> data
[0];
1717 memcpy (result
-> buffer
-> data
,
1718 (((unsigned char *)(packet
-> raw
))
1719 + offset
), result
-> len
);
1720 result
-> terminated
= 0;
1722 log_error ("data: packet: no buffer memory.");
1728 #if defined (DEBUG_EXPRESSIONS)
1729 log_debug ("data: packet (%ld, %ld) = %s",
1731 s2
? print_hex_1 (result
-> len
,
1732 result
-> data
, 60) : NULL
);
1736 /* The encapsulation of all defined options in an
1738 case expr_encapsulate
:
1740 s0
= option_space_encapsulate
1741 (result
, packet
, lease
, client_state
,
1742 in_options
, cfg_options
, scope
,
1743 &expr
-> data
.encapsulate
);
1747 #if defined (DEBUG_EXPRESSIONS)
1748 log_debug ("data: encapsulate (%s) = %s",
1749 expr
-> data
.encapsulate
.data
,
1750 s0
? print_hex_1 (result
-> len
,
1751 result
-> data
, 60) : "NULL");
1755 /* Some constant data... */
1756 case expr_const_data
:
1757 #if defined (DEBUG_EXPRESSIONS)
1758 log_debug ("data: const = %s",
1759 print_hex_1 (expr
-> data
.const_data
.len
,
1760 expr
-> data
.const_data
.data
, 60));
1762 data_string_copy (result
,
1763 &expr
-> data
.const_data
, file
, line
);
1766 /* Hostname lookup... */
1767 case expr_host_lookup
:
1768 s0
= do_host_lookup (result
, expr
-> data
.host_lookup
);
1769 #if defined (DEBUG_EXPRESSIONS)
1770 log_debug ("data: DNS lookup (%s) = %s",
1771 expr
-> data
.host_lookup
-> hostname
,
1773 ? print_dotted_quads (result
-> len
, result
-> data
)
1778 /* Concatenation... */
1780 memset (&data
, 0, sizeof data
);
1781 s0
= evaluate_data_expression (&data
, packet
, lease
,
1783 in_options
, cfg_options
, scope
,
1784 expr
-> data
.concat
[0], MDL
);
1785 memset (&other
, 0, sizeof other
);
1786 s1
= evaluate_data_expression (&other
, packet
, lease
,
1788 in_options
, cfg_options
, scope
,
1789 expr
-> data
.concat
[1], MDL
);
1792 result
-> len
= data
.len
+ other
.len
;
1793 if (!buffer_allocate (&result
-> buffer
,
1794 (result
-> len
+ other
.terminated
),
1796 log_error ("data: concat: no memory");
1798 data_string_forget (&data
, MDL
);
1799 data_string_forget (&other
, MDL
);
1802 result
-> data
= &result
-> buffer
-> data
[0];
1803 memcpy (result
-> buffer
-> data
, data
.data
, data
.len
);
1804 memcpy (&result
-> buffer
-> data
[data
.len
],
1805 other
.data
, other
.len
+ other
.terminated
);
1809 data_string_forget (&data
, MDL
);
1811 data_string_forget (&other
, MDL
);
1812 #if defined (DEBUG_EXPRESSIONS)
1813 log_debug ("data: concat (%s, %s) = %s",
1814 s0
? print_hex_1 (data
.len
, data
.data
, 20) : "NULL",
1815 s1
? print_hex_2 (other
.len
, other
.data
, 20) : "NULL",
1817 ? print_hex_3 (result
-> len
, result
-> data
, 30)
1822 case expr_encode_int8
:
1823 s0
= evaluate_numeric_expression (&len
, packet
, lease
,
1825 in_options
, cfg_options
,
1827 expr
-> data
.encode_int
);
1830 if (!buffer_allocate (&result
-> buffer
,
1832 log_error ("data: encode_int8: no memory");
1836 result
-> data
= &result
-> buffer
-> data
[0];
1837 result
-> buffer
-> data
[0] = len
;
1842 #if defined (DEBUG_EXPRESSIONS)
1844 log_debug ("data: encode_int8 (NULL) = NULL");
1846 log_debug ("data: encode_int8 (%ld) = %s", len
,
1847 print_hex_2 (result
-> len
,
1848 result
-> data
, 20));
1853 case expr_encode_int16
:
1854 s0
= evaluate_numeric_expression (&len
, packet
, lease
,
1856 in_options
, cfg_options
,
1858 expr
-> data
.encode_int
);
1861 if (!buffer_allocate (&result
-> buffer
, 2,
1863 log_error ("data: encode_int16: no memory");
1867 result
-> data
= &result
-> buffer
-> data
[0];
1868 putUShort (result
-> buffer
-> data
, len
);
1873 #if defined (DEBUG_EXPRESSIONS)
1875 log_debug ("data: encode_int16 (NULL) = NULL");
1877 log_debug ("data: encode_int16 (%ld) = %s", len
,
1878 print_hex_2 (result
-> len
,
1879 result
-> data
, 20));
1883 case expr_encode_int32
:
1884 s0
= evaluate_numeric_expression (&len
, packet
, lease
,
1886 in_options
, cfg_options
,
1888 expr
-> data
.encode_int
);
1891 if (!buffer_allocate (&result
-> buffer
, 4,
1893 log_error ("data: encode_int32: no memory");
1897 result
-> data
= &result
-> buffer
-> data
[0];
1898 putULong (result
-> buffer
-> data
, len
);
1903 #if defined (DEBUG_EXPRESSIONS)
1905 log_debug ("data: encode_int32 (NULL) = NULL");
1907 log_debug ("data: encode_int32 (%ld) = %s", len
,
1908 print_hex_2 (result
-> len
,
1909 result
-> data
, 20));
1913 case expr_binary_to_ascii
:
1914 /* Evaluate the base (offset) and width (len): */
1915 s0
= evaluate_numeric_expression
1916 (&offset
, packet
, lease
, client_state
, in_options
,
1917 cfg_options
, scope
, expr
-> data
.b2a
.base
);
1918 s1
= evaluate_numeric_expression (&len
, packet
, lease
,
1920 in_options
, cfg_options
,
1922 expr
-> data
.b2a
.width
);
1924 /* Evaluate the separator string. */
1925 memset (&data
, 0, sizeof data
);
1926 s2
= evaluate_data_expression (&data
, packet
, lease
,
1928 in_options
, cfg_options
, scope
,
1929 expr
-> data
.b2a
.separator
,
1932 /* Evaluate the data to be converted. */
1933 memset (&other
, 0, sizeof other
);
1934 s3
= evaluate_data_expression (&other
, packet
, lease
,
1936 in_options
, cfg_options
, scope
,
1937 expr
-> data
.b2a
.buffer
, MDL
);
1939 if (s0
&& s1
&& s2
&& s3
) {
1942 if (len
!= 8 && len
!= 16 && len
!= 32) {
1943 log_info ("binary_to_ascii: %s %ld!",
1944 "invalid width", len
);
1950 /* The buffer must be a multiple of the number's
1952 if (other
.len
% len
) {
1953 log_info ("binary-to-ascii: %s %d %s %ld!",
1954 "length of buffer", other
.len
,
1955 "not a multiple of width", len
);
1960 /* Count the width of the output. */
1962 for (i
= 0; i
< other
.len
; i
+= len
) {
1965 if (other
.data
[i
] < 8)
1967 else if (other
.data
[i
] < 64)
1971 } else if (offset
== 10) {
1972 if (other
.data
[i
] < 10)
1974 else if (other
.data
[i
] < 100)
1978 } else if (offset
== 16) {
1979 if (other
.data
[i
] < 16)
1984 buflen
+= (converted_length
1988 buflen
+= (converted_length
1991 if (i
+ len
!= other
.len
)
1995 if (!buffer_allocate (&result
-> buffer
,
1996 buflen
+ 1, file
, line
)) {
1997 log_error ("data: binary-to-ascii: no memory");
2001 result
-> data
= &result
-> buffer
-> data
[0];
2002 result
-> len
= buflen
;
2003 result
-> terminated
= 1;
2006 for (i
= 0; i
< other
.len
; i
+= len
) {
2007 buflen
+= (binary_to_ascii
2008 (&result
-> buffer
-> data
[buflen
],
2009 &other
.data
[i
], offset
, len
));
2010 if (i
+ len
!= other
.len
) {
2012 buffer
-> data
[buflen
],
2013 data
.data
, data
.len
);
2017 /* NUL terminate. */
2018 result
-> buffer
-> data
[buflen
] = 0;
2024 #if defined (DEBUG_EXPRESSIONS)
2025 log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
2026 s0
? print_dec_1 (offset
) : "NULL",
2027 s1
? print_dec_2 (len
) : "NULL",
2028 s2
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
2029 s3
? print_hex_2 (other
.len
, other
.data
, 30) : "NULL",
2030 (status
? print_hex_3 (result
-> len
, result
-> data
, 30)
2034 data_string_forget (&data
, MDL
);
2036 data_string_forget (&other
, MDL
);
2042 /* Evaluate the width (len): */
2043 s0
= evaluate_numeric_expression
2044 (&len
, packet
, lease
, client_state
, in_options
,
2045 cfg_options
, scope
, expr
-> data
.reverse
.width
);
2047 /* Evaluate the data. */
2048 memset (&data
, 0, sizeof data
);
2049 s1
= evaluate_data_expression (&data
, packet
, lease
,
2051 in_options
, cfg_options
, scope
,
2052 expr
-> data
.reverse
.buffer
,
2058 /* The buffer must be a multiple of the number's
2060 if (data
.len
% len
) {
2061 log_info ("reverse: %s %d %s %ld!",
2062 "length of buffer", data
.len
,
2063 "not a multiple of width", len
);
2068 /* XXX reverse in place? I don't think we can. */
2069 if (!buffer_allocate (&result
-> buffer
,
2070 data
.len
, file
, line
)) {
2071 log_error ("data: reverse: no memory");
2075 result
-> data
= &result
-> buffer
-> data
[0];
2076 result
-> len
= data
.len
;
2077 result
-> terminated
= 0;
2079 for (i
= 0; i
< data
.len
; i
+= len
) {
2080 memcpy (&result
-> buffer
-> data
[i
],
2081 &data
.data
[data
.len
- i
- len
], len
);
2088 #if defined (DEBUG_EXPRESSIONS)
2089 log_debug ("data: reverse (%s, %s) = %s",
2090 s0
? print_dec_1 (len
) : "NULL",
2091 s1
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
2092 (status
? print_hex_3 (result
-> len
, result
-> data
, 30)
2096 data_string_forget (&data
, MDL
);
2101 case expr_leased_address
:
2103 log_debug("data: \"leased-address\" configuration "
2104 "directive: there is no lease associated "
2105 "with this client.");
2108 result
-> len
= lease
-> ip_addr
.len
;
2109 if (buffer_allocate (&result
-> buffer
, result
-> len
,
2111 result
-> data
= &result
-> buffer
-> data
[0];
2112 memcpy (&result
-> buffer
-> data
[0],
2113 lease
-> ip_addr
.iabuf
, lease
-> ip_addr
.len
);
2114 result
-> terminated
= 0;
2116 log_error ("data: leased-address: no memory.");
2119 #if defined (DEBUG_EXPRESSIONS)
2120 log_debug ("data: leased-address = %s",
2121 print_hex_1 (result
-> len
, result
-> data
, 60));
2125 case expr_pick_first_value
:
2126 memset (&data
, 0, sizeof data
);
2127 if ((evaluate_data_expression
2129 lease
, client_state
, in_options
, cfg_options
,
2130 scope
, expr
-> data
.pick_first_value
.car
, MDL
))) {
2131 #if defined (DEBUG_EXPRESSIONS)
2132 log_debug ("data: pick_first_value (%s, xxx)",
2133 print_hex_1 (result
-> len
,
2134 result
-> data
, 40));
2139 if (expr
-> data
.pick_first_value
.cdr
&&
2140 (evaluate_data_expression
2142 lease
, client_state
, in_options
, cfg_options
,
2143 scope
, expr
-> data
.pick_first_value
.cdr
, MDL
))) {
2144 #if defined (DEBUG_EXPRESSIONS)
2145 log_debug ("data: pick_first_value (NULL, %s)",
2146 print_hex_1 (result
-> len
,
2147 result
-> data
, 40));
2152 #if defined (DEBUG_EXPRESSIONS)
2153 log_debug ("data: pick_first_value (NULL, NULL) = NULL");
2157 case expr_host_decl_name
:
2158 if (!lease
|| !lease
-> host
) {
2159 log_error ("data: host_decl_name: not available");
2162 result
-> len
= strlen (lease
-> host
-> name
);
2163 if (buffer_allocate (&result
-> buffer
,
2164 result
-> len
+ 1, file
, line
)) {
2165 result
-> data
= &result
-> buffer
-> data
[0];
2166 strcpy ((char *)&result
-> buffer
-> data
[0],
2167 lease
-> host
-> name
);
2168 result
-> terminated
= 1;
2170 log_error ("data: host-decl-name: no memory.");
2173 #if defined (DEBUG_EXPRESSIONS)
2174 log_debug ("data: host-decl-name = %s", lease
-> host
-> name
);
2179 #if defined (DEBUG_EXPRESSIONS)
2180 log_debug ("data: null = NULL");
2184 case expr_variable_reference
:
2185 if (scope
&& *scope
) {
2186 binding
= find_binding (*scope
, expr
-> data
.variable
);
2188 if (binding
&& binding
-> value
) {
2189 if (binding
-> value
-> type
== binding_data
) {
2190 data_string_copy (result
,
2191 &binding
-> value
-> value
.data
,
2194 } else if (binding
-> value
-> type
!= binding_data
) {
2195 log_error ("binding type %d in %s.",
2196 binding
-> value
-> type
,
2197 "evaluate_data_expression");
2205 #if defined (DEBUG_EXPRESSIONS)
2206 log_debug ("data: %s = %s", expr
-> data
.variable
,
2207 s0
? print_hex_1 (result
-> len
,
2208 result
-> data
, 50) : "NULL");
2213 bv
= (struct binding_value
*)0;
2214 s0
= evaluate_expression (&bv
, packet
, lease
, client_state
,
2215 in_options
, cfg_options
,
2218 if (bv
-> type
!= binding_data
)
2219 log_error ("%s() returned type %d in %s.",
2220 expr
-> data
.funcall
.name
,
2222 "evaluate_data_expression");
2224 data_string_copy (result
, &bv
-> value
.data
,
2226 binding_value_dereference (&bv
, MDL
);
2228 #if defined (DEBUG_EXPRESSIONS)
2229 log_debug ("data: %s = %s", expr
-> data
.funcall
.name
,
2230 s0
? print_hex_1 (result
-> len
,
2231 result
-> data
, 50) : "NULL");
2235 /* Extract the filename. */
2237 if (packet
&& packet
-> raw
-> file
[0]) {
2239 memchr (packet
-> raw
-> file
, 0,
2240 sizeof packet
-> raw
-> file
);
2242 fn
= ((char *)packet
-> raw
-> file
+
2243 sizeof packet
-> raw
-> file
);
2244 result
-> len
= fn
- &(packet
-> raw
-> file
[0]);
2245 if (buffer_allocate (&result
-> buffer
,
2246 result
-> len
+ 1, file
, line
)) {
2247 result
-> data
= &result
-> buffer
-> data
[0];
2248 memcpy (&result
-> buffer
-> data
[0],
2249 packet
-> raw
-> file
,
2251 result
-> buffer
-> data
[result
-> len
] = 0;
2252 result
-> terminated
= 1;
2255 log_error ("data: filename: no memory.");
2261 #if defined (DEBUG_EXPRESSIONS)
2262 log_info ("data: filename = \"%s\"",
2263 s0
? (const char *)(result
-> data
) : "NULL");
2267 /* Extract the server name. */
2269 if (packet
&& packet
-> raw
-> sname
[0]) {
2271 memchr (packet
-> raw
-> sname
, 0,
2272 sizeof packet
-> raw
-> sname
);
2274 fn
= ((char *)packet
-> raw
-> sname
+
2275 sizeof packet
-> raw
-> sname
);
2276 result
-> len
= fn
- &packet
-> raw
-> sname
[0];
2277 if (buffer_allocate (&result
-> buffer
,
2278 result
-> len
+ 1, file
, line
)) {
2279 result
-> data
= &result
-> buffer
-> data
[0];
2280 memcpy (&result
-> buffer
-> data
[0],
2281 packet
-> raw
-> sname
,
2283 result
-> buffer
-> data
[result
-> len
] = 0;
2284 result
-> terminated
= 1;
2287 log_error ("data: sname: no memory.");
2293 #if defined (DEBUG_EXPRESSIONS)
2294 log_info ("data: sname = \"%s\"",
2295 s0
? (const char *)(result
-> data
) : "NULL");
2299 /* Provide the system's local hostname as a return value. */
2300 case expr_gethostname
:
2302 * Allocate a buffer to return.
2304 * The largest valid hostname is maybe 64 octets at a single
2305 * label, or 255 octets if you think a hostname is allowed
2306 * to contain labels (plus termination).
2308 memset(result
, 0, sizeof(*result
));
2309 if (!buffer_allocate(&result
->buffer
, 255, file
, line
)) {
2310 log_error("data: gethostname(): no memory for buffer");
2313 result
->data
= result
->buffer
->data
;
2316 * On successful completion, gethostname() resturns 0. It may
2317 * not null-terminate the string if there was insufficient
2320 if (!gethostname((char *)result
->buffer
->data
, 255)) {
2321 if (result
->buffer
->data
[255] == '\0')
2323 strlen((char *)result
->buffer
->data
);
2329 data_string_forget(result
, MDL
);
2334 case expr_not_equal
:
2335 case expr_regex_match
:
2336 case expr_iregex_match
:
2345 case expr_variable_exists
:
2346 log_error ("Boolean opcode in evaluate_data_expression: %d",
2350 case expr_extract_int8
:
2351 case expr_extract_int16
:
2352 case expr_extract_int32
:
2353 case expr_const_int
:
2354 case expr_lease_time
:
2355 case expr_dns_transaction
:
2360 case expr_remainder
:
2361 case expr_binary_and
:
2362 case expr_binary_or
:
2363 case expr_binary_xor
:
2364 case expr_client_state
:
2365 log_error ("Numeric opcode in evaluate_data_expression: %d",
2370 case expr_ns_delete
:
2371 case expr_ns_exists
:
2372 case expr_ns_not_exists
:
2373 log_error ("dns update opcode in evaluate_data_expression: %d",
2378 log_error ("function definition in evaluate_data_expression");
2385 log_error ("Bogus opcode in evaluate_data_expression: %d", expr
-> op
);
2389 int evaluate_numeric_expression (result
, packet
, lease
, client_state
,
2390 in_options
, cfg_options
, scope
, expr
)
2391 unsigned long *result
;
2392 struct packet
*packet
;
2393 struct lease
*lease
;
2394 struct client_state
*client_state
;
2395 struct option_state
*in_options
;
2396 struct option_state
*cfg_options
;
2397 struct binding_scope
**scope
;
2398 struct expression
*expr
;
2400 struct data_string data
;
2401 int status
, sleft
, sright
;
2402 #if defined (NSUPDATE_OLD)
2405 struct expression
*cur
, *next
;
2408 struct binding
*binding
;
2409 struct binding_value
*bv
;
2410 unsigned long ileft
, iright
;
2412 switch (expr
-> op
) {
2415 case expr_not_equal
:
2416 case expr_regex_match
:
2417 case expr_iregex_match
:
2426 case expr_variable_exists
:
2427 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
2431 case expr_substring
:
2437 case expr_const_data
:
2440 case expr_encapsulate
:
2441 case expr_host_lookup
:
2442 case expr_encode_int8
:
2443 case expr_encode_int16
:
2444 case expr_encode_int32
:
2445 case expr_binary_to_ascii
:
2449 case expr_pick_first_value
:
2450 case expr_host_decl_name
:
2451 case expr_config_option
:
2452 case expr_leased_address
:
2454 case expr_gethostname
:
2455 log_error ("Data opcode in evaluate_numeric_expression: %d",
2459 case expr_extract_int8
:
2460 memset (&data
, 0, sizeof data
);
2461 status
= evaluate_data_expression
2462 (&data
, packet
, lease
, client_state
, in_options
,
2463 cfg_options
, scope
, expr
-> data
.extract_int
, MDL
);
2465 *result
= data
.data
[0];
2466 #if defined (DEBUG_EXPRESSIONS)
2467 log_debug ("num: extract_int8 (%s) = %s",
2468 status
? print_hex_1 (data
.len
, data
.data
, 60) : "NULL",
2469 status
? print_dec_1 (*result
) : "NULL" );
2471 if (status
) data_string_forget (&data
, MDL
);
2474 case expr_extract_int16
:
2475 memset (&data
, 0, sizeof data
);
2476 status
= (evaluate_data_expression
2477 (&data
, packet
, lease
, client_state
, in_options
,
2478 cfg_options
, scope
, expr
-> data
.extract_int
, MDL
));
2479 if (status
&& data
.len
>= 2)
2480 *result
= getUShort (data
.data
);
2481 #if defined (DEBUG_EXPRESSIONS)
2482 log_debug ("num: extract_int16 (%s) = %ld",
2483 ((status
&& data
.len
>= 2) ?
2484 print_hex_1 (data
.len
, data
.data
, 60) : "NULL"),
2487 if (status
) data_string_forget (&data
, MDL
);
2488 return (status
&& data
.len
>= 2);
2490 case expr_extract_int32
:
2491 memset (&data
, 0, sizeof data
);
2492 status
= (evaluate_data_expression
2493 (&data
, packet
, lease
, client_state
, in_options
,
2494 cfg_options
, scope
, expr
-> data
.extract_int
, MDL
));
2495 if (status
&& data
.len
>= 4)
2496 *result
= getULong (data
.data
);
2497 #if defined (DEBUG_EXPRESSIONS)
2498 log_debug ("num: extract_int32 (%s) = %ld",
2499 ((status
&& data
.len
>= 4) ?
2500 print_hex_1 (data
.len
, data
.data
, 60) : "NULL"),
2503 if (status
) data_string_forget (&data
, MDL
);
2504 return (status
&& data
.len
>= 4);
2506 case expr_const_int
:
2507 *result
= expr
-> data
.const_int
;
2508 #if defined (DEBUG_EXPRESSIONS)
2509 log_debug ("number: CONSTANT = %ld", *result
);
2513 case expr_lease_time
:
2515 log_error ("data: leased_lease: not available");
2518 if (lease
-> ends
< cur_time
) {
2519 log_error ("%s %lu when it is now %lu",
2520 "data: lease_time: lease ends at",
2521 (long)(lease
-> ends
), (long)cur_time
);
2524 *result
= lease
-> ends
- cur_time
;
2525 #if defined (DEBUG_EXPRESSIONS)
2526 log_debug ("number: lease-time = (%lu - %lu) = %ld",
2532 case expr_dns_transaction
:
2533 #if !defined (NSUPDATE_OLD)
2536 if (!resolver_inited
) {
2537 minires_ninit (&resolver_state
);
2538 resolver_inited
= 1;
2539 resolver_state
.retrans
= 1;
2540 resolver_state
.retry
= 1;
2545 next
= cur
-> data
.dns_transaction
.cdr
;
2547 status
= (evaluate_dns_expression
2549 lease
, client_state
, in_options
, cfg_options
,
2550 scope
, cur
-> data
.dns_transaction
.car
));
2553 ISC_LIST_APPEND (uq
, nut
, r_link
);
2557 /* Do the update and record the error code, if there was
2558 an error; otherwise set it to NOERROR. */
2559 *result
= minires_nupdate (&resolver_state
,
2560 ISC_LIST_HEAD (uq
));
2563 print_dns_status ((int)*result
, &uq
);
2566 while (!ISC_LIST_EMPTY (uq
)) {
2567 ns_updrec
*tmp
= ISC_LIST_HEAD (uq
);
2568 ISC_LIST_UNLINK (uq
, tmp
, r_link
);
2569 if (tmp
-> r_data_ephem
) {
2570 dfree (tmp
-> r_data_ephem
, MDL
);
2571 tmp
-> r_data
= (unsigned char *)0;
2572 tmp
-> r_data_ephem
= (unsigned char *)0;
2574 minires_freeupdrec (tmp
);
2577 #endif /* NSUPDATE_OLD */
2579 case expr_variable_reference
:
2580 if (scope
&& *scope
) {
2581 binding
= find_binding (*scope
, expr
-> data
.variable
);
2583 if (binding
&& binding
-> value
) {
2584 if (binding
-> value
-> type
== binding_numeric
) {
2585 *result
= binding
-> value
-> value
.intval
;
2588 log_error ("binding type %d in %s.",
2589 binding
-> value
-> type
,
2590 "evaluate_numeric_expression");
2597 #if defined (DEBUG_EXPRESSIONS)
2599 log_debug ("numeric: %s = %ld",
2600 expr
-> data
.variable
, *result
);
2602 log_debug ("numeric: %s = NULL",
2603 expr
-> data
.variable
);
2608 bv
= (struct binding_value
*)0;
2609 status
= evaluate_expression (&bv
, packet
, lease
,
2611 in_options
, cfg_options
,
2614 if (bv
-> type
!= binding_numeric
)
2615 log_error ("%s() returned type %d in %s.",
2616 expr
-> data
.funcall
.name
,
2618 "evaluate_numeric_expression");
2620 *result
= bv
-> value
.intval
;
2621 binding_value_dereference (&bv
, MDL
);
2623 #if defined (DEBUG_EXPRESSIONS)
2624 log_debug ("data: %s = %ld", expr
-> data
.funcall
.name
,
2625 status
? *result
: 0);
2630 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2632 in_options
, cfg_options
,
2634 expr
-> data
.and [0]);
2635 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2637 in_options
, cfg_options
,
2639 expr
-> data
.and [1]);
2641 #if defined (DEBUG_EXPRESSIONS)
2642 if (sleft
&& sright
)
2643 log_debug ("num: %ld + %ld = %ld",
2644 ileft
, iright
, ileft
+ iright
);
2646 log_debug ("num: %ld + NULL = NULL", ileft
);
2648 log_debug ("num: NULL + %ld = NULL", iright
);
2650 if (sleft
&& sright
) {
2651 *result
= ileft
+ iright
;
2657 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2659 in_options
, cfg_options
,
2661 expr
-> data
.and [0]);
2662 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2664 in_options
, cfg_options
,
2666 expr
-> data
.and [1]);
2668 #if defined (DEBUG_EXPRESSIONS)
2669 if (sleft
&& sright
)
2670 log_debug ("num: %ld - %ld = %ld",
2671 ileft
, iright
, ileft
- iright
);
2673 log_debug ("num: %ld - NULL = NULL", ileft
);
2675 log_debug ("num: NULL - %ld = NULL", iright
);
2677 if (sleft
&& sright
) {
2678 *result
= ileft
- iright
;
2684 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2686 in_options
, cfg_options
,
2688 expr
-> data
.and [0]);
2689 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2691 in_options
, cfg_options
,
2693 expr
-> data
.and [1]);
2695 #if defined (DEBUG_EXPRESSIONS)
2696 if (sleft
&& sright
)
2697 log_debug ("num: %ld * %ld = %ld",
2698 ileft
, iright
, ileft
* iright
);
2700 log_debug ("num: %ld * NULL = NULL", ileft
);
2702 log_debug ("num: NULL * %ld = NULL", iright
);
2704 if (sleft
&& sright
) {
2705 *result
= ileft
* iright
;
2711 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2713 in_options
, cfg_options
,
2715 expr
-> data
.and [0]);
2716 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2718 in_options
, cfg_options
,
2720 expr
-> data
.and [1]);
2722 #if defined (DEBUG_EXPRESSIONS)
2723 if (sleft
&& sright
) {
2725 log_debug ("num: %ld / %ld = %ld",
2726 ileft
, iright
, ileft
/ iright
);
2728 log_debug ("num: %ld / %ld = NULL",
2731 log_debug ("num: %ld / NULL = NULL", ileft
);
2733 log_debug ("num: NULL / %ld = NULL", iright
);
2735 if (sleft
&& sright
&& iright
) {
2736 *result
= ileft
/ iright
;
2741 case expr_remainder
:
2742 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2744 in_options
, cfg_options
,
2746 expr
-> data
.and [0]);
2747 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2749 in_options
, cfg_options
,
2751 expr
-> data
.and [1]);
2753 #if defined (DEBUG_EXPRESSIONS)
2754 if (sleft
&& sright
) {
2756 log_debug ("num: %ld %% %ld = %ld",
2757 ileft
, iright
, ileft
% iright
);
2759 log_debug ("num: %ld %% %ld = NULL",
2762 log_debug ("num: %ld %% NULL = NULL", ileft
);
2764 log_debug ("num: NULL %% %ld = NULL", iright
);
2766 if (sleft
&& sright
&& iright
) {
2767 *result
= ileft
% iright
;
2772 case expr_binary_and
:
2773 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2775 in_options
, cfg_options
,
2777 expr
-> data
.and [0]);
2778 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2780 in_options
, cfg_options
,
2782 expr
-> data
.and [1]);
2784 #if defined (DEBUG_EXPRESSIONS)
2785 if (sleft
&& sright
)
2786 log_debug ("num: %ld | %ld = %ld",
2787 ileft
, iright
, ileft
& iright
);
2789 log_debug ("num: %ld & NULL = NULL", ileft
);
2791 log_debug ("num: NULL & %ld = NULL", iright
);
2793 if (sleft
&& sright
) {
2794 *result
= ileft
& iright
;
2799 case expr_binary_or
:
2800 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2802 in_options
, cfg_options
,
2804 expr
-> data
.and [0]);
2805 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2807 in_options
, cfg_options
,
2809 expr
-> data
.and [1]);
2811 #if defined (DEBUG_EXPRESSIONS)
2812 if (sleft
&& sright
)
2813 log_debug ("num: %ld | %ld = %ld",
2814 ileft
, iright
, ileft
| iright
);
2816 log_debug ("num: %ld | NULL = NULL", ileft
);
2818 log_debug ("num: NULL | %ld = NULL", iright
);
2820 if (sleft
&& sright
) {
2821 *result
= ileft
| iright
;
2826 case expr_binary_xor
:
2827 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2829 in_options
, cfg_options
,
2831 expr
-> data
.and [0]);
2832 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2834 in_options
, cfg_options
,
2836 expr
-> data
.and [1]);
2838 #if defined (DEBUG_EXPRESSIONS)
2839 if (sleft
&& sright
)
2840 log_debug ("num: %ld ^ %ld = %ld",
2841 ileft
, iright
, ileft
^ iright
);
2843 log_debug ("num: %ld ^ NULL = NULL", ileft
);
2845 log_debug ("num: NULL ^ %ld = NULL", iright
);
2847 if (sleft
&& sright
) {
2848 *result
= ileft
^ iright
;
2853 case expr_client_state
:
2855 #if defined (DEBUG_EXPRESSIONS)
2856 log_debug ("num: client-state = %d",
2857 client_state
-> state
);
2859 *result
= client_state
-> state
;
2862 #if defined (DEBUG_EXPRESSIONS)
2863 log_debug ("num: client-state = NULL");
2869 case expr_ns_delete
:
2870 case expr_ns_exists
:
2871 case expr_ns_not_exists
:
2872 log_error ("dns opcode in evaluate_numeric_expression: %d",
2877 log_error ("function definition in evaluate_numeric_expr");
2884 log_fatal("Impossible case at %s:%d. Undefined operator "
2885 "%d.", MDL
, expr
->op
);
2889 log_error ("evaluate_numeric_expression: bogus opcode %d", expr
-> op
);
2893 /* Return data hanging off of an option cache structure, or if there
2894 isn't any, evaluate the expression hanging off of it and return the
2895 result of that evaluation. There should never be both an expression
2896 and a valid data_string. */
2898 int evaluate_option_cache (result
, packet
, lease
, client_state
,
2899 in_options
, cfg_options
, scope
, oc
, file
, line
)
2900 struct data_string
*result
;
2901 struct packet
*packet
;
2902 struct lease
*lease
;
2903 struct client_state
*client_state
;
2904 struct option_state
*in_options
;
2905 struct option_state
*cfg_options
;
2906 struct binding_scope
**scope
;
2907 struct option_cache
*oc
;
2911 if (oc
->data
.data
!= NULL
) {
2912 data_string_copy (result
, &oc
-> data
, file
, line
);
2915 if (!oc
-> expression
)
2917 return evaluate_data_expression (result
, packet
, lease
, client_state
,
2918 in_options
, cfg_options
, scope
,
2919 oc
-> expression
, file
, line
);
2922 /* Evaluate an option cache and extract a boolean from the result,
2923 returning the boolean. Return false if there is no data. */
2925 int evaluate_boolean_option_cache (ignorep
, packet
,
2926 lease
, client_state
, in_options
,
2927 cfg_options
, scope
, oc
, file
, line
)
2929 struct packet
*packet
;
2930 struct lease
*lease
;
2931 struct client_state
*client_state
;
2932 struct option_state
*in_options
;
2933 struct option_state
*cfg_options
;
2934 struct binding_scope
**scope
;
2935 struct option_cache
*oc
;
2939 struct data_string ds
;
2942 /* So that we can be called with option_lookup as an argument. */
2943 if (!oc
|| !in_options
)
2946 memset (&ds
, 0, sizeof ds
);
2947 if (!evaluate_option_cache (&ds
, packet
,
2948 lease
, client_state
, in_options
,
2949 cfg_options
, scope
, oc
, file
, line
))
2952 /* The boolean option cache is actually a trinary value. Zero is
2953 * off, one is on, and 2 is 'ignore'.
2956 result
= ds
.data
[0];
2959 if (ignorep
!= NULL
)
2961 } else if (ignorep
!= NULL
)
2965 data_string_forget (&ds
, MDL
);
2970 /* Evaluate a boolean expression and return the result of the evaluation,
2971 or FALSE if it failed. */
2973 int evaluate_boolean_expression_result (ignorep
, packet
, lease
, client_state
,
2974 in_options
, cfg_options
, scope
, expr
)
2976 struct packet
*packet
;
2977 struct lease
*lease
;
2978 struct client_state
*client_state
;
2979 struct option_state
*in_options
;
2980 struct option_state
*cfg_options
;
2981 struct binding_scope
**scope
;
2982 struct expression
*expr
;
2986 /* So that we can be called with option_lookup as an argument. */
2990 if (!evaluate_boolean_expression (&result
, packet
, lease
, client_state
,
2991 in_options
, cfg_options
,
3004 /* Dereference an expression node, and if the reference count goes to zero,
3005 dereference any data it refers to, and then free it. */
3006 void expression_dereference (eptr
, file
, line
)
3007 struct expression
**eptr
;
3011 struct expression
*expr
= *eptr
;
3013 /* Zero the pointer. */
3014 *eptr
= (struct expression
*)0;
3016 /* Decrement the reference count. If it's nonzero, we're
3019 rc_register (file
, line
, eptr
, expr
, expr
-> refcnt
, 1, RC_MISC
);
3020 if (expr
-> refcnt
> 0)
3022 if (expr
-> refcnt
< 0) {
3023 log_error ("%s(%d): negative refcnt!", file
, line
);
3024 #if defined (DEBUG_RC_HISTORY)
3025 dump_rc_history (expr
);
3027 #if defined (POINTER_DEBUG)
3034 /* Dereference subexpressions. */
3035 switch (expr
-> op
) {
3036 /* All the binary operators can be handled the same way. */
3038 case expr_not_equal
:
3039 case expr_regex_match
:
3040 case expr_iregex_match
:
3048 case expr_remainder
:
3049 case expr_binary_and
:
3050 case expr_binary_or
:
3051 case expr_binary_xor
:
3052 case expr_client_state
:
3053 if (expr
-> data
.equal
[0])
3054 expression_dereference (&expr
-> data
.equal
[0],
3056 if (expr
-> data
.equal
[1])
3057 expression_dereference (&expr
-> data
.equal
[1],
3061 case expr_substring
:
3062 if (expr
-> data
.substring
.expr
)
3063 expression_dereference (&expr
-> data
.substring
.expr
,
3065 if (expr
-> data
.substring
.offset
)
3066 expression_dereference (&expr
-> data
.substring
.offset
,
3068 if (expr
-> data
.substring
.len
)
3069 expression_dereference (&expr
-> data
.substring
.len
,
3074 if (expr
-> data
.suffix
.expr
)
3075 expression_dereference (&expr
-> data
.suffix
.expr
,
3077 if (expr
-> data
.suffix
.len
)
3078 expression_dereference (&expr
-> data
.suffix
.len
,
3083 if (expr
->data
.lcase
)
3084 expression_dereference(&expr
->data
.lcase
, MDL
);
3088 if (expr
->data
.ucase
)
3089 expression_dereference(&expr
->data
.ucase
, MDL
);
3093 if (expr
-> data
.not)
3094 expression_dereference (&expr
-> data
.not, file
, line
);
3098 if (expr
-> data
.packet
.offset
)
3099 expression_dereference (&expr
-> data
.packet
.offset
,
3101 if (expr
-> data
.packet
.len
)
3102 expression_dereference (&expr
-> data
.packet
.len
,
3106 case expr_extract_int8
:
3107 case expr_extract_int16
:
3108 case expr_extract_int32
:
3109 if (expr
-> data
.extract_int
)
3110 expression_dereference (&expr
-> data
.extract_int
,
3114 case expr_encode_int8
:
3115 case expr_encode_int16
:
3116 case expr_encode_int32
:
3117 if (expr
-> data
.encode_int
)
3118 expression_dereference (&expr
-> data
.encode_int
,
3122 case expr_encapsulate
:
3123 case expr_const_data
:
3124 data_string_forget (&expr
-> data
.const_data
, file
, line
);
3127 case expr_host_lookup
:
3128 if (expr
-> data
.host_lookup
)
3129 dns_host_entry_dereference (&expr
-> data
.host_lookup
,
3133 case expr_binary_to_ascii
:
3134 if (expr
-> data
.b2a
.base
)
3135 expression_dereference (&expr
-> data
.b2a
.base
,
3137 if (expr
-> data
.b2a
.width
)
3138 expression_dereference (&expr
-> data
.b2a
.width
,
3140 if (expr
-> data
.b2a
.separator
)
3141 expression_dereference (&expr
-> data
.b2a
.separator
,
3143 if (expr
-> data
.b2a
.buffer
)
3144 expression_dereference (&expr
-> data
.b2a
.buffer
,
3148 case expr_pick_first_value
:
3149 if (expr
-> data
.pick_first_value
.car
)
3150 expression_dereference (&expr
-> data
.pick_first_value
.car
,
3152 if (expr
-> data
.pick_first_value
.cdr
)
3153 expression_dereference (&expr
-> data
.pick_first_value
.cdr
,
3158 if (expr
-> data
.reverse
.width
)
3159 expression_dereference (&expr
-> data
.reverse
.width
,
3161 if (expr
-> data
.reverse
.buffer
)
3162 expression_dereference
3163 (&expr
-> data
.reverse
.buffer
, file
, line
);
3166 case expr_dns_transaction
:
3167 if (expr
-> data
.dns_transaction
.car
)
3168 expression_dereference (&expr
-> data
.dns_transaction
.car
,
3170 if (expr
-> data
.dns_transaction
.cdr
)
3171 expression_dereference (&expr
-> data
.dns_transaction
.cdr
,
3176 if (expr
-> data
.ns_add
.rrname
)
3177 expression_dereference (&expr
-> data
.ns_add
.rrname
,
3179 if (expr
-> data
.ns_add
.rrdata
)
3180 expression_dereference (&expr
-> data
.ns_add
.rrdata
,
3182 if (expr
-> data
.ns_add
.ttl
)
3183 expression_dereference (&expr
-> data
.ns_add
.ttl
,
3187 case expr_ns_delete
:
3188 case expr_ns_exists
:
3189 case expr_ns_not_exists
:
3190 if (expr
-> data
.ns_delete
.rrname
)
3191 expression_dereference (&expr
-> data
.ns_delete
.rrname
,
3193 if (expr
-> data
.ns_delete
.rrdata
)
3194 expression_dereference (&expr
-> data
.ns_delete
.rrdata
,
3198 case expr_variable_reference
:
3199 case expr_variable_exists
:
3200 if (expr
-> data
.variable
)
3201 dfree (expr
-> data
.variable
, file
, line
);
3205 if (expr
-> data
.funcall
.name
)
3206 dfree (expr
-> data
.funcall
.name
, file
, line
);
3207 if (expr
-> data
.funcall
.arglist
)
3208 expression_dereference (&expr
-> data
.funcall
.arglist
,
3213 if (expr
-> data
.arg
.val
)
3214 expression_dereference (&expr
-> data
.arg
.val
,
3216 if (expr
-> data
.arg
.next
)
3217 expression_dereference (&expr
-> data
.arg
.next
,
3222 fundef_dereference (&expr
-> data
.func
, file
, line
);
3225 /* No subexpressions. */
3226 case expr_leased_address
:
3227 case expr_lease_time
:
3230 case expr_const_int
:
3237 case expr_gethostname
:
3243 free_expression (expr
, MDL
);
3246 int is_dns_expression (expr
)
3247 struct expression
*expr
;
3249 return (expr
-> op
== expr_ns_add
||
3250 expr
-> op
== expr_ns_delete
||
3251 expr
-> op
== expr_ns_exists
||
3252 expr
-> op
== expr_ns_not_exists
);
3255 int is_boolean_expression (expr
)
3256 struct expression
*expr
;
3258 return (expr
-> op
== expr_check
||
3259 expr
-> op
== expr_exists
||
3260 expr
-> op
== expr_variable_exists
||
3261 expr
-> op
== expr_equal
||
3262 expr
-> op
== expr_not_equal
||
3263 expr
->op
== expr_regex_match
||
3264 expr
->op
== expr_iregex_match
||
3265 expr
-> op
== expr_and
||
3266 expr
-> op
== expr_or
||
3267 expr
-> op
== expr_not
||
3268 expr
-> op
== expr_known
||
3269 expr
-> op
== expr_static
);
3272 int is_data_expression (expr
)
3273 struct expression
*expr
;
3275 return (expr
->op
== expr_substring
||
3276 expr
->op
== expr_suffix
||
3277 expr
->op
== expr_lcase
||
3278 expr
->op
== expr_ucase
||
3279 expr
->op
== expr_option
||
3280 expr
->op
== expr_hardware
||
3281 expr
->op
== expr_const_data
||
3282 expr
->op
== expr_packet
||
3283 expr
->op
== expr_concat
||
3284 expr
->op
== expr_encapsulate
||
3285 expr
->op
== expr_encode_int8
||
3286 expr
->op
== expr_encode_int16
||
3287 expr
->op
== expr_encode_int32
||
3288 expr
->op
== expr_host_lookup
||
3289 expr
->op
== expr_binary_to_ascii
||
3290 expr
->op
== expr_filename
||
3291 expr
->op
== expr_sname
||
3292 expr
->op
== expr_reverse
||
3293 expr
->op
== expr_pick_first_value
||
3294 expr
->op
== expr_host_decl_name
||
3295 expr
->op
== expr_leased_address
||
3296 expr
->op
== expr_config_option
||
3297 expr
->op
== expr_null
||
3298 expr
->op
== expr_gethostname
);
3301 int is_numeric_expression (expr
)
3302 struct expression
*expr
;
3304 return (expr
-> op
== expr_extract_int8
||
3305 expr
-> op
== expr_extract_int16
||
3306 expr
-> op
== expr_extract_int32
||
3307 expr
-> op
== expr_const_int
||
3308 expr
-> op
== expr_lease_time
||
3309 expr
-> op
== expr_dns_transaction
||
3310 expr
-> op
== expr_add
||
3311 expr
-> op
== expr_subtract
||
3312 expr
-> op
== expr_multiply
||
3313 expr
-> op
== expr_divide
||
3314 expr
-> op
== expr_remainder
||
3315 expr
-> op
== expr_binary_and
||
3316 expr
-> op
== expr_binary_or
||
3317 expr
-> op
== expr_binary_xor
||
3318 expr
-> op
== expr_client_state
);
3321 int is_compound_expression (expr
)
3322 struct expression
*expr
;
3324 return (expr
-> op
== expr_ns_add
||
3325 expr
-> op
== expr_ns_delete
||
3326 expr
-> op
== expr_ns_exists
||
3327 expr
-> op
== expr_ns_not_exists
||
3328 expr
-> op
== expr_substring
||
3329 expr
-> op
== expr_suffix
||
3330 expr
-> op
== expr_option
||
3331 expr
-> op
== expr_concat
||
3332 expr
-> op
== expr_encode_int8
||
3333 expr
-> op
== expr_encode_int16
||
3334 expr
-> op
== expr_encode_int32
||
3335 expr
-> op
== expr_binary_to_ascii
||
3336 expr
-> op
== expr_reverse
||
3337 expr
-> op
== expr_pick_first_value
||
3338 expr
-> op
== expr_config_option
||
3339 expr
-> op
== expr_extract_int8
||
3340 expr
-> op
== expr_extract_int16
||
3341 expr
-> op
== expr_extract_int32
||
3342 expr
-> op
== expr_dns_transaction
);
3345 static int op_val
PROTO ((enum expr_op
));
3347 static int op_val (op
)
3355 case expr_substring
:
3360 case expr_encapsulate
:
3361 case expr_host_lookup
:
3366 case expr_const_data
:
3367 case expr_extract_int8
:
3368 case expr_extract_int16
:
3369 case expr_extract_int32
:
3370 case expr_encode_int8
:
3371 case expr_encode_int16
:
3372 case expr_encode_int32
:
3373 case expr_const_int
:
3375 case expr_variable_exists
:
3377 case expr_binary_to_ascii
:
3381 case expr_pick_first_value
:
3382 case expr_host_decl_name
:
3383 case expr_config_option
:
3384 case expr_leased_address
:
3385 case expr_lease_time
:
3386 case expr_dns_transaction
:
3388 case expr_variable_reference
:
3390 case expr_ns_delete
:
3391 case expr_ns_exists
:
3392 case expr_ns_not_exists
:
3396 /* XXXDPN: Need to assign sane precedences to these. */
3397 case expr_binary_and
:
3398 case expr_binary_or
:
3399 case expr_binary_xor
:
3400 case expr_client_state
:
3401 case expr_gethostname
:
3405 case expr_not_equal
:
3406 case expr_regex_match
:
3407 case expr_iregex_match
:
3420 case expr_remainder
:
3426 int op_precedence (op1
, op2
)
3427 enum expr_op op1
, op2
;
3429 return op_val (op1
) - op_val (op2
);
3432 enum expression_context
expression_context (struct expression
*expr
)
3434 if (is_data_expression (expr
))
3435 return context_data
;
3436 if (is_numeric_expression (expr
))
3437 return context_numeric
;
3438 if (is_boolean_expression (expr
))
3439 return context_boolean
;
3440 if (is_dns_expression (expr
))
3445 enum expression_context
op_context (op
)
3449 /* XXX Why aren't these specific? */
3454 case expr_substring
:
3459 case expr_encapsulate
:
3460 case expr_host_lookup
:
3465 case expr_const_data
:
3466 case expr_extract_int8
:
3467 case expr_extract_int16
:
3468 case expr_extract_int32
:
3469 case expr_encode_int8
:
3470 case expr_encode_int16
:
3471 case expr_encode_int32
:
3472 case expr_const_int
:
3474 case expr_variable_exists
:
3476 case expr_binary_to_ascii
:
3480 case expr_pick_first_value
:
3481 case expr_host_decl_name
:
3482 case expr_config_option
:
3483 case expr_leased_address
:
3484 case expr_lease_time
:
3486 case expr_variable_reference
:
3488 case expr_ns_delete
:
3489 case expr_ns_exists
:
3490 case expr_ns_not_exists
:
3491 case expr_dns_transaction
:
3495 case expr_gethostname
:
3499 case expr_not_equal
:
3500 case expr_regex_match
:
3501 case expr_iregex_match
:
3502 return context_data
;
3505 return context_boolean
;
3508 return context_boolean
;
3514 case expr_remainder
:
3515 case expr_binary_and
:
3516 case expr_binary_or
:
3517 case expr_binary_xor
:
3518 case expr_client_state
:
3519 return context_numeric
;
3524 int write_expression (file
, expr
, col
, indent
, firstp
)
3526 struct expression
*expr
;
3531 struct expression
*e
;
3537 /* If this promises to be a fat expression, start a new line. */
3538 if (!firstp
&& is_compound_expression (expr
)) {
3539 indent_spaces (file
, indent
);
3543 switch (expr
-> op
) {
3545 col
= token_print_indent (file
, col
, indent
, "", "", "null");
3549 col
= token_print_indent (file
, col
, indent
, "", "", "check");
3550 col
= token_print_indent_concat (file
, col
, indent
,
3552 expr
-> data
.check
-> name
,
3556 case expr_regex_match
:
3560 case expr_iregex_match
:
3564 case expr_not_equal
:
3571 col
= write_expression (file
, expr
-> data
.equal
[0],
3573 col
= token_print_indent (file
, col
, indent
, " ", " ", s
);
3574 col
= write_expression (file
, expr
-> data
.equal
[1],
3575 col
, indent
+ 2, 0);
3578 case expr_substring
:
3579 col
= token_print_indent (file
, col
, indent
, "", "",
3581 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3583 col
= write_expression (file
, expr
-> data
.substring
.expr
,
3585 col
= token_print_indent (file
, col
, indent
, "", " ", ",");
3586 col
= write_expression (file
, expr
-> data
.substring
.offset
,
3588 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3589 col
= write_expression (file
, expr
-> data
.substring
.len
,
3591 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3595 col
= token_print_indent (file
, col
, indent
, "", "", "suffix");
3596 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3598 col
= write_expression (file
, expr
-> data
.suffix
.expr
,
3600 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3601 col
= write_expression (file
, expr
-> data
.suffix
.len
,
3603 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3606 col
= token_print_indent(file
, col
, indent
, "", "", "lcase");
3607 col
= token_print_indent(file
, col
, indent
, " ", "", "(");
3609 col
= write_expression(file
, expr
->data
.lcase
, col
, scol
, 1);
3610 col
= token_print_indent(file
, col
, indent
, "", "", ")");
3614 col
= token_print_indent(file
, col
, indent
, "", "", "ucase");
3615 col
= token_print_indent(file
, col
, indent
, " ", "", "(");
3617 col
= write_expression(file
, expr
->data
.ucase
, col
, scol
, 1);
3618 col
= token_print_indent(file
, col
, indent
, "", "", ")");
3623 col
= token_print_indent (file
, col
, indent
, "", "",
3625 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3629 col
= write_expression (file
, e
-> data
.concat
[0],
3632 if (!e
-> data
.concat
[1])
3634 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3635 if (e
-> data
.concat
[1] -> op
== expr_concat
) {
3636 e
= e
-> data
.concat
[1];
3639 col
= write_expression (file
, e
-> data
.concat
[1],
3642 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3645 case expr_host_lookup
:
3646 col
= token_print_indent (file
, col
, indent
, "", "",
3648 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3649 col
= token_print_indent_concat
3650 (file
, col
, indent
, "", "",
3651 "\"", expr
-> data
.host_lookup
-> hostname
, "\"",
3653 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3672 case expr_remainder
:
3676 case expr_binary_and
:
3680 case expr_binary_or
:
3684 case expr_binary_xor
:
3697 col
= token_print_indent (file
, col
, indent
, "", " ", "not");
3698 col
= write_expression (file
,
3699 expr
-> data
.not, col
, indent
+ 2, 1);
3706 col
= token_print_indent (file
, col
, indent
, "", "", s
);
3708 if (expr
-> data
.option
-> universe
!= &dhcp_universe
) {
3709 col
= token_print_indent (file
, col
, indent
,
3711 (expr
-> data
.option
->
3713 col
= token_print_indent (file
, col
, indent
, "", "",
3715 col
= token_print_indent (file
, col
, indent
, "", "",
3716 expr
-> data
.option
-> name
);
3718 col
= token_print_indent (file
, col
, indent
, " ", "",
3719 expr
-> data
.option
-> name
);
3724 col
= token_print_indent (file
, col
, indent
, "", "",
3729 col
= token_print_indent (file
, col
, indent
, "", "",
3731 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3733 col
= write_expression (file
, expr
-> data
.packet
.offset
,
3735 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3736 col
= write_expression (file
, expr
-> data
.packet
.len
,
3738 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3741 case expr_const_data
:
3742 col
= token_indent_data_string (file
, col
, indent
, "", "",
3743 &expr
-> data
.const_data
);
3746 case expr_extract_int8
:
3749 col
= token_print_indent (file
, col
, indent
, "", "",
3751 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3753 col
= write_expression (file
, expr
-> data
.extract_int
,
3755 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3756 sprintf (obuf
, "%d", width
);
3757 col
= token_print_indent (file
, col
, scol
, " ", "", obuf
);
3758 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3761 case expr_extract_int16
:
3765 case expr_extract_int32
:
3769 case expr_encode_int8
:
3772 col
= token_print_indent (file
, col
, indent
, "", "",
3774 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3776 col
= write_expression (file
, expr
-> data
.extract_int
,
3778 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3779 sprintf (obuf
, "%d", width
);
3780 col
= token_print_indent (file
, col
, scol
, " ", "", obuf
);
3781 col
= token_print_indent (file
, col
, indent
, "", "",
3785 case expr_encode_int16
:
3789 case expr_encode_int32
:
3793 case expr_const_int
:
3794 sprintf (obuf
, "%lu", expr
-> data
.const_int
);
3795 col
= token_print_indent (file
, col
, indent
, "", "", obuf
);
3800 goto print_option_name
;
3802 case expr_encapsulate
:
3803 col
= token_print_indent (file
, col
, indent
, "", "",
3805 col
= token_indent_data_string (file
, col
, indent
, " ", "",
3806 &expr
-> data
.encapsulate
);
3810 col
= token_print_indent (file
, col
, indent
, "", "", "known");
3814 col
= token_print_indent (file
, col
, indent
, "", "",
3816 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3818 col
= write_expression (file
, expr
-> data
.reverse
.width
,
3820 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3821 col
= write_expression (file
, expr
-> data
.reverse
.buffer
,
3823 col
= token_print_indent (file
, col
, indent
, "", "",
3827 case expr_leased_address
:
3828 col
= token_print_indent (file
, col
, indent
, "", "",
3832 case expr_client_state
:
3833 col
= token_print_indent (file
, col
, indent
, "", "",
3837 case expr_binary_to_ascii
:
3838 col
= token_print_indent (file
, col
, indent
, "", "",
3840 col
= token_print_indent (file
, col
, indent
, " ", "",
3843 col
= write_expression (file
, expr
-> data
.b2a
.base
,
3845 col
= token_print_indent (file
, col
, scol
, "", " ",
3847 col
= write_expression (file
, expr
-> data
.b2a
.width
,
3849 col
= token_print_indent (file
, col
, scol
, "", " ",
3851 col
= write_expression (file
, expr
-> data
.b2a
.separator
,
3853 col
= token_print_indent (file
, col
, scol
, "", " ",
3855 col
= write_expression (file
, expr
-> data
.b2a
.buffer
,
3857 col
= token_print_indent (file
, col
, indent
, "", "",
3861 case expr_config_option
:
3862 s
= "config-option";
3863 goto print_option_name
;
3865 case expr_host_decl_name
:
3866 col
= token_print_indent (file
, col
, indent
, "", "",
3870 case expr_pick_first_value
:
3872 col
= token_print_indent (file
, col
, indent
, "", "",
3874 col
= token_print_indent (file
, col
, indent
, " ", "",
3879 col
= write_expression (file
,
3880 e
-> data
.pick_first_value
.car
,
3883 /* We're being very lisp-like right now - instead of
3884 representing this expression as (first middle . last) we're
3885 representing it as (first middle last), which means that the
3886 tail cdr is always nil. Apologies to non-wisp-lizards - may
3887 this obscure way of describing the problem motivate you to
3888 learn more about the one true computing language. */
3889 if (!e
-> data
.pick_first_value
.cdr
)
3891 col
= token_print_indent (file
, col
, scol
, "", " ",
3893 if (e
-> data
.pick_first_value
.cdr
-> op
==
3894 expr_pick_first_value
) {
3895 e
= e
-> data
.pick_first_value
.cdr
;
3898 col
= write_expression (file
,
3899 e
-> data
.pick_first_value
.cdr
,
3902 col
= token_print_indent (file
, col
, indent
, "", "",
3906 case expr_lease_time
:
3907 col
= token_print_indent (file
, col
, indent
, "", "",
3911 case expr_dns_transaction
:
3912 col
= token_print_indent (file
, col
, indent
, "", "",
3914 col
= token_print_indent (file
, col
, indent
, " ", "",
3918 e
&& e
-> op
== expr_dns_transaction
;
3919 e
= e
-> data
.dns_transaction
.cdr
) {
3925 col
= write_expression (file
,
3926 e
-> data
.dns_transaction
.car
,
3928 if (e
-> data
.dns_transaction
.cdr
)
3929 col
= token_print_indent (file
, col
, scol
,
3933 col
= write_expression (file
, e
, col
, scol
, 0);
3934 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3938 col
= token_print_indent (file
, col
, indent
, "", "",
3940 col
= token_print_indent (file
, col
, indent
, " ", "",
3943 sprintf (obuf
, "%d", expr
-> data
.ns_add
.rrclass
);
3944 col
= token_print_indent (file
, col
, scol
, "", "", obuf
);
3945 col
= token_print_indent (file
, col
, scol
, "", " ",
3947 sprintf (obuf
, "%d", expr
-> data
.ns_add
.rrtype
);
3948 col
= token_print_indent (file
, col
, scol
, "", "", obuf
);
3949 col
= token_print_indent (file
, col
, scol
, "", " ",
3951 col
= write_expression (file
, expr
-> data
.ns_add
.rrname
,
3953 col
= token_print_indent (file
, col
, scol
, "", " ",
3955 col
= write_expression (file
, expr
-> data
.ns_add
.rrdata
,
3957 col
= token_print_indent (file
, col
, scol
, "", " ",
3959 col
= write_expression (file
, expr
-> data
.ns_add
.ttl
,
3961 col
= token_print_indent (file
, col
, indent
, "", "",
3965 case expr_ns_delete
:
3966 col
= token_print_indent (file
, col
, indent
, "", "",
3968 col
= token_print_indent (file
, col
, indent
, " ", "",
3972 sprintf (obuf
, "%d", expr
-> data
.ns_add
.rrclass
);
3973 col
= token_print_indent (file
, col
, scol
, "", "", obuf
);
3974 col
= token_print_indent (file
, col
, scol
, "", " ",
3976 sprintf (obuf
, "%d", expr
-> data
.ns_add
.rrtype
);
3977 col
= token_print_indent (file
, col
, scol
, "", "", obuf
);
3978 col
= token_print_indent (file
, col
, scol
, "", " ",
3980 col
= write_expression (file
, expr
-> data
.ns_add
.rrname
,
3982 col
= token_print_indent (file
, col
, scol
, "", " ",
3984 col
= write_expression (file
, expr
-> data
.ns_add
.rrdata
,
3986 col
= token_print_indent (file
, col
, indent
, "", "",
3990 case expr_ns_exists
:
3991 col
= token_print_indent (file
, col
, indent
, "", "",
3993 col
= token_print_indent (file
, col
, indent
, " ", "",
3995 goto finish_ns_small
;
3997 case expr_ns_not_exists
:
3998 col
= token_print_indent (file
, col
, indent
, "", "",
4000 col
= token_print_indent (file
, col
, indent
, " ", "",
4002 goto finish_ns_small
;
4005 col
= token_print_indent (file
, col
, indent
, "", "",
4010 col
= token_print_indent (file
, col
, indent
, "", "", "null");
4013 case expr_variable_reference
:
4014 col
= token_print_indent (file
, indent
, indent
, "", "",
4015 expr
-> data
.variable
);
4018 case expr_variable_exists
:
4019 col
= token_print_indent (file
, indent
, indent
, "", "",
4021 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
4022 col
= token_print_indent (file
, col
, indent
, "", "",
4023 expr
-> data
.variable
);
4024 col
= token_print_indent (file
, col
, indent
, "", "", ")");
4027 case expr_gethostname
:
4028 col
= token_print_indent(file
, col
, indent
, "", "",
4033 col
= token_print_indent(file
, indent
, indent
, "", "",
4034 expr
->data
.funcall
.name
);
4035 col
= token_print_indent(file
, col
, indent
, " ", "", "(");
4038 e
= expr
->data
.funcall
.arglist
;
4041 col
= token_print_indent(file
, col
, indent
,
4044 col
= write_expression(file
, e
->data
.arg
.val
, col
,
4047 e
= e
->data
.arg
.next
;
4050 col
= token_print_indent(file
, col
, indent
, "", "", ")");
4054 log_fatal ("invalid expression type in print_expression: %d",
4060 struct binding
*find_binding (struct binding_scope
*scope
, const char *name
)
4063 struct binding_scope
*s
;
4065 for (s
= scope
; s
; s
= s
-> outer
) {
4066 for (bp
= s
-> bindings
; bp
; bp
= bp
-> next
) {
4067 if (!strcasecmp (name
, bp
-> name
)) {
4072 return (struct binding
*)0;
4075 int free_bindings (struct binding_scope
*scope
, const char *file
, int line
)
4077 struct binding
*bp
, *next
;
4079 for (bp
= scope
-> bindings
; bp
; bp
= next
) {
4082 dfree (bp
-> name
, file
, line
);
4084 binding_value_dereference (&bp
-> value
, file
, line
);
4085 dfree (bp
, file
, line
);
4087 scope
-> bindings
= (struct binding
*)0;
4091 int binding_scope_dereference (ptr
, file
, line
)
4092 struct binding_scope
**ptr
;
4096 struct binding_scope
*binding_scope
;
4098 if (!ptr
|| !*ptr
) {
4099 log_error ("%s(%d): null pointer", file
, line
);
4100 #if defined (POINTER_DEBUG)
4107 binding_scope
= *ptr
;
4108 *ptr
= (struct binding_scope
*)0;
4109 --binding_scope
-> refcnt
;
4110 rc_register (file
, line
, ptr
,
4111 binding_scope
, binding_scope
-> refcnt
, 1, RC_MISC
);
4112 if (binding_scope
-> refcnt
> 0)
4115 if (binding_scope
-> refcnt
< 0) {
4116 log_error ("%s(%d): negative refcnt!", file
, line
);
4117 #if defined (DEBUG_RC_HISTORY)
4118 dump_rc_history (binding_scope
);
4120 #if defined (POINTER_DEBUG)
4127 free_bindings (binding_scope
, file
, line
);
4128 if (binding_scope
-> outer
)
4129 binding_scope_dereference (&binding_scope
-> outer
, MDL
);
4130 dfree (binding_scope
, file
, line
);
4134 int fundef_dereference (ptr
, file
, line
)
4135 struct fundef
**ptr
;
4139 struct fundef
*bp
= *ptr
;
4140 struct string_list
*sp
, *next
;
4143 log_error ("%s(%d): null pointer", file
, line
);
4144 #if defined (POINTER_DEBUG)
4152 log_error ("%s(%d): null pointer", file
, line
);
4153 #if defined (POINTER_DEBUG)
4161 rc_register (file
, line
, ptr
, bp
, bp
-> refcnt
, 1, RC_MISC
);
4162 if (bp
-> refcnt
< 0) {
4163 log_error ("%s(%d): negative refcnt!", file
, line
);
4164 #if defined (DEBUG_RC_HISTORY)
4165 dump_rc_history (bp
);
4167 #if defined (POINTER_DEBUG)
4173 if (!bp
-> refcnt
) {
4174 for (sp
= bp
-> args
; sp
; sp
= next
) {
4176 dfree (sp
, file
, line
);
4178 if (bp
-> statements
)
4179 executable_statement_dereference (&bp
-> statements
,
4181 dfree (bp
, file
, line
);
4183 *ptr
= (struct fundef
*)0;
4187 #if defined (NOTYET) /* Post 3.0 final. */
4188 int data_subexpression_length (int *rv
,
4189 struct expression
*expr
)
4191 int crhs
, clhs
, llhs
, lrhs
;
4192 switch (expr
-> op
) {
4193 case expr_substring
:
4194 if (expr
-> data
.substring
.len
&&
4195 expr
-> data
.substring
.len
-> op
== expr_const_int
) {
4197 (int)expr
-> data
.substring
.len
-> data
.const_int
);
4204 if (expr
-> data
.suffix
.len
&&
4205 expr
-> data
.suffix
.len
-> op
== expr_const_int
) {
4207 (int)expr
-> data
.suffix
.len
-> data
.const_int
);
4213 return data_subexpression_length(rv
, expr
->data
.lcase
);
4216 return data_subexpression_length(rv
, expr
->data
.ucase
);
4219 clhs
= data_subexpression_length (&llhs
,
4220 expr
-> data
.concat
[0]);
4221 crhs
= data_subexpression_length (&lrhs
,
4222 expr
-> data
.concat
[1]);
4223 if (crhs
== 0 || clhs
== 0)
4232 case expr_const_data
:
4233 *rv
= expr
-> data
.const_data
.len
;
4237 return data_subexpression_length (rv
,
4238 expr
-> data
.reverse
.buffer
);
4240 case expr_leased_address
:
4241 case expr_lease_time
:
4245 case expr_pick_first_value
:
4246 clhs
= data_subexpression_length (&llhs
,
4247 expr
-> data
.concat
[0]);
4248 crhs
= data_subexpression_length (&lrhs
,
4249 expr
-> data
.concat
[1]);
4250 if (crhs
== 0 || clhs
== 0)
4258 case expr_binary_to_ascii
:
4259 case expr_config_option
:
4260 case expr_host_decl_name
:
4261 case expr_encapsulate
:
4264 case expr_host_lookup
:
4270 case expr_regex_match
:
4271 case expr_iregex_match
:
4275 case expr_extract_int8
:
4276 case expr_extract_int16
:
4277 case expr_extract_int32
:
4278 case expr_encode_int8
:
4279 case expr_encode_int16
:
4280 case expr_encode_int32
:
4281 case expr_const_int
:
4284 case expr_dns_transaction
:
4287 case expr_ns_delete
:
4288 case expr_ns_exists
:
4289 case expr_ns_not_exists
:
4290 case expr_not_equal
:
4292 case expr_variable_exists
:
4293 case expr_variable_reference
:
4301 case expr_remainder
:
4302 case expr_binary_and
:
4303 case expr_binary_or
:
4304 case expr_binary_xor
:
4305 case expr_client_state
:
4306 case expr_gethostname
:
4312 int expr_valid_for_context (struct expression
*expr
,
4313 enum expression_context context
)
4315 /* We don't know at parse time what type of value a function may
4316 return, so we can't flag an error on it. */
4317 if (expr
-> op
== expr_funcall
||
4318 expr
-> op
== expr_variable_reference
)
4325 case context_boolean
:
4326 if (is_boolean_expression (expr
))
4331 if (is_data_expression (expr
))
4335 case context_numeric
:
4336 if (is_numeric_expression (expr
))
4341 if (is_dns_expression (expr
)) {
4346 case context_data_or_numeric
:
4347 if (is_numeric_expression (expr
) ||
4348 is_data_expression (expr
)) {
4353 case context_function
:
4354 if (expr
-> op
== expr_function
)
4362 struct binding
*create_binding (struct binding_scope
**scope
, const char *name
)
4364 struct binding
*binding
;
4367 if (!binding_scope_allocate (scope
, MDL
))
4368 return (struct binding
*)0;
4371 binding
= find_binding (*scope
, name
);
4373 binding
= dmalloc (sizeof *binding
, MDL
);
4375 return (struct binding
*)0;
4377 memset (binding
, 0, sizeof *binding
);
4378 binding
-> name
= dmalloc (strlen (name
) + 1, MDL
);
4379 if (!binding
-> name
) {
4380 dfree (binding
, MDL
);
4381 return (struct binding
*)0;
4383 strcpy (binding
-> name
, name
);
4385 binding
-> next
= (*scope
) -> bindings
;
4386 (*scope
) -> bindings
= binding
;
4393 int bind_ds_value (struct binding_scope
**scope
,
4395 struct data_string
*value
)
4397 struct binding
*binding
;
4399 binding
= create_binding (scope
, name
);
4403 if (binding
-> value
)
4404 binding_value_dereference (&binding
-> value
, MDL
);
4406 if (!binding_value_allocate (&binding
-> value
, MDL
))
4409 data_string_copy (&binding
-> value
-> value
.data
, value
, MDL
);
4410 binding
-> value
-> type
= binding_data
;
4416 int find_bound_string (struct data_string
*value
,
4417 struct binding_scope
*scope
,
4420 struct binding
*binding
;
4422 binding
= find_binding (scope
, name
);
4424 !binding
-> value
||
4425 binding
-> value
-> type
!= binding_data
)
4428 if (binding
-> value
-> value
.data
.terminated
) {
4429 data_string_copy (value
, &binding
-> value
-> value
.data
, MDL
);
4431 buffer_allocate (&value
-> buffer
,
4432 binding
-> value
-> value
.data
.len
,
4434 if (!value
-> buffer
)
4437 memcpy (value
-> buffer
-> data
,
4438 binding
-> value
-> value
.data
.data
,
4439 binding
-> value
-> value
.data
.len
);
4440 value
-> data
= value
-> buffer
-> data
;
4441 value
-> len
= binding
-> value
-> value
.data
.len
;
4447 int unset (struct binding_scope
*scope
, const char *name
)
4449 struct binding
*binding
;
4451 binding
= find_binding (scope
, name
);
4453 if (binding
-> value
)
4454 binding_value_dereference
4455 (&binding
-> value
, MDL
);
4461 /* vim: set tabstop=8: */