3 Routines for manipulating parse trees... */
6 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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 * Newmarket, NH 03857 USA
25 * https://www.isc.org/
30 #include <omapip/omapip_p.h>
38 struct binding_scope
*global_scope
;
40 static int do_host_lookup (struct data_string
*, struct dns_host_entry
*);
42 #define DS_SPRINTF_SIZE 128
45 * If we are using a data_string structure to hold a NUL-terminated
46 * ASCII string, this function can be used to append a printf-formatted
47 * string to the end of it. The data_string structure will be resized to
48 * be big enough to hold the new string.
50 * If the append works, then 1 is returned.
52 * If it is not possible to allocate a buffer big enough to hold the
53 * new value, then the old data_string is unchanged, and 0 is returned.
56 data_string_sprintfa(struct data_string
*ds
, const char *fmt
, ...) {
62 struct buffer
*tmp_buffer
;
65 * If the data_string is empty, then initialize it.
67 if (ds
->data
== NULL
) {
68 /* INSIST(ds.buffer == NULL); */
69 if (!buffer_allocate(&ds
->buffer
, DS_SPRINTF_SIZE
, MDL
)) {
72 ds
->data
= ds
->buffer
->data
;
73 ds
->len
= DS_SPRINTF_SIZE
;
74 *((char *)ds
->data
) = '\0';
78 * Get the length of the string, and figure out how much space
81 cur_strlen
= strlen((char *)ds
->data
);
82 max
= ds
->len
- cur_strlen
;
85 * Use vsnprintf(), which won't write past our space, but will
86 * tell us how much space it wants.
89 vsnprintf_ret
= vsnprintf((char *)ds
->data
+cur_strlen
, max
, fmt
, args
);
91 /* INSIST(vsnprintf_ret >= 0); */
94 * If our buffer is not big enough, we need a new buffer.
96 if (vsnprintf_ret
>= max
) {
98 * Figure out a size big enough.
100 new_len
= ds
->len
* 2;
101 while (new_len
<= cur_strlen
+ vsnprintf_ret
) {
106 * Create a new buffer and fill it.
109 if (!buffer_allocate(&tmp_buffer
, new_len
, MDL
)) {
111 * If we can't create a big enough buffer,
112 * we should remove any truncated output that we had.
114 *((char *)ds
->data
+cur_strlen
) = '\0';
118 memcpy(tmp_buffer
->data
, ds
->data
, cur_strlen
);
120 /* Rerun the vsprintf. */
122 vsprintf((char *)tmp_buffer
->data
+ cur_strlen
, fmt
, args
);
126 * Replace our old buffer with the new buffer.
128 buffer_dereference(&ds
->buffer
, MDL
);
129 buffer_reference(&ds
->buffer
, tmp_buffer
, MDL
);
130 buffer_dereference(&tmp_buffer
, MDL
);
131 ds
->data
= ds
->buffer
->data
;
141 pair foo
= (pair
)dmalloc (sizeof *foo
, MDL
);
143 log_fatal ("no memory for cons.");
149 int make_const_option_cache (oc
, buffer
, data
, len
, option
, file
, line
)
150 struct option_cache
**oc
;
151 struct buffer
**buffer
;
154 struct option
*option
;
164 bp
= (struct buffer
*)0;
165 if (!buffer_allocate (&bp
, len
, file
, line
)) {
166 log_error ("%s(%d): can't allocate buffer.",
172 if (!option_cache_allocate (oc
, file
, line
)) {
173 log_error ("%s(%d): can't allocate option cache.", file
, line
);
174 buffer_dereference (&bp
, file
, line
);
178 (*oc
) -> data
.len
= len
;
179 (*oc
) -> data
.buffer
= bp
;
180 (*oc
) -> data
.data
= &bp
-> data
[0];
181 (*oc
) -> data
.terminated
= 0;
183 memcpy (&bp
-> data
[0], data
, len
);
184 option_reference(&((*oc
)->option
), option
, MDL
);
188 int make_host_lookup (expr
, name
)
189 struct expression
**expr
;
192 if (!expression_allocate (expr
, MDL
)) {
193 log_error ("No memory for host lookup tree node.");
196 (*expr
) -> op
= expr_host_lookup
;
197 if (!enter_dns_host (&((*expr
) -> data
.host_lookup
), name
)) {
198 expression_dereference (expr
, MDL
);
204 int enter_dns_host (dh
, name
)
205 struct dns_host_entry
**dh
;
208 /* XXX This should really keep a hash table of hostnames
209 XXX and just add a new reference to a hostname that
210 XXX already exists, if possible, rather than creating
211 XXX a new structure. */
212 if (!dns_host_entry_allocate (dh
, name
, MDL
)) {
213 log_error ("Can't allocate space for new host.");
219 int make_const_data (struct expression
**expr
, const unsigned char *data
,
220 unsigned len
, int terminated
, int allocate
,
221 const char *file
, int line
)
223 struct expression
*nt
;
225 if (!expression_allocate (expr
, file
, line
)) {
226 log_error ("No memory for make_const_data tree node.");
233 if (!buffer_allocate (&nt
-> data
.const_data
.buffer
,
234 len
+ terminated
, file
, line
)) {
235 log_error ("Can't allocate const_data buffer");
236 expression_dereference (expr
, file
, line
);
239 nt
-> data
.const_data
.data
=
240 &nt
-> data
.const_data
.buffer
-> data
[0];
241 memcpy (nt
-> data
.const_data
.buffer
-> data
,
242 data
, len
+ terminated
);
244 nt
-> data
.const_data
.data
= data
;
245 nt
-> data
.const_data
.terminated
= terminated
;
247 nt
-> data
.const_data
.data
= 0;
249 nt
-> op
= expr_const_data
;
250 nt
-> data
.const_data
.len
= len
;
254 int make_const_int (expr
, val
)
255 struct expression
**expr
;
258 if (!expression_allocate (expr
, MDL
)) {
259 log_error ("No memory for make_const_int tree node.");
263 (*expr
) -> op
= expr_const_int
;
264 (*expr
) -> data
.const_int
= val
;
268 int make_concat (expr
, left
, right
)
269 struct expression
**expr
;
270 struct expression
*left
, *right
;
272 /* If we're concatenating a null tree to a non-null tree, just
273 return the non-null tree; if both trees are null, return
278 expression_reference (expr
, right
, MDL
);
282 expression_reference (expr
, left
, MDL
);
286 /* Otherwise, allocate a new node to concatenate the two. */
287 if (!expression_allocate (expr
, MDL
)) {
288 log_error ("No memory for concatenation expression node.");
292 (*expr
) -> op
= expr_concat
;
293 expression_reference (&(*expr
) -> data
.concat
[0], left
, MDL
);
294 expression_reference (&(*expr
) -> data
.concat
[1], right
, MDL
);
298 int make_encapsulation (expr
, name
)
299 struct expression
**expr
;
300 struct data_string
*name
;
302 /* Allocate a new node to store the encapsulation. */
303 if (!expression_allocate (expr
, MDL
)) {
304 log_error ("No memory for encapsulation expression node.");
308 (*expr
) -> op
= expr_encapsulate
;
309 data_string_copy (&(*expr
) -> data
.encapsulate
, name
, MDL
);
313 int make_substring (new, expr
, offset
, length
)
314 struct expression
**new;
315 struct expression
*expr
;
316 struct expression
*offset
;
317 struct expression
*length
;
319 /* Allocate an expression node to compute the substring. */
320 if (!expression_allocate (new, MDL
)) {
321 log_error ("no memory for substring expression.");
324 (*new) -> op
= expr_substring
;
325 expression_reference (&(*new) -> data
.substring
.expr
, expr
, MDL
);
326 expression_reference (&(*new) -> data
.substring
.offset
, offset
, MDL
);
327 expression_reference (&(*new) -> data
.substring
.len
, length
, MDL
);
331 int make_limit (new, expr
, limit
)
332 struct expression
**new;
333 struct expression
*expr
;
336 /* Allocate a node to enforce a limit on evaluation. */
337 if (!expression_allocate (new, MDL
))
338 log_error ("no memory for limit expression");
339 (*new) -> op
= expr_substring
;
340 expression_reference (&(*new) -> data
.substring
.expr
, expr
, MDL
);
342 /* Offset is a constant 0. */
343 if (!expression_allocate (&(*new) -> data
.substring
.offset
, MDL
)) {
344 log_error ("no memory for limit offset expression");
345 expression_dereference (new, MDL
);
348 (*new) -> data
.substring
.offset
-> op
= expr_const_int
;
349 (*new) -> data
.substring
.offset
-> data
.const_int
= 0;
351 /* Length is a constant: the specified limit. */
352 if (!expression_allocate (&(*new) -> data
.substring
.len
, MDL
)) {
353 log_error ("no memory for limit length expression");
354 expression_dereference (new, MDL
);
357 (*new) -> data
.substring
.len
-> op
= expr_const_int
;
358 (*new) -> data
.substring
.len
-> data
.const_int
= limit
;
363 int option_cache (struct option_cache
**oc
, struct data_string
*dp
,
364 struct expression
*expr
, struct option
*option
,
365 const char *file
, int line
)
367 if (!option_cache_allocate (oc
, file
, line
))
370 data_string_copy (&(*oc
) -> data
, dp
, file
, line
);
372 expression_reference (&(*oc
) -> expression
, expr
, file
, line
);
373 option_reference(&(*oc
)->option
, option
, MDL
);
377 int make_let (result
, name
)
378 struct executable_statement
**result
;
381 if (!(executable_statement_allocate (result
, MDL
)))
384 (*result
) -> op
= let_statement
;
385 (*result
) -> data
.let
.name
= dmalloc (strlen (name
) + 1, MDL
);
386 if (!(*result
) -> data
.let
.name
) {
387 executable_statement_dereference (result
, MDL
);
390 strcpy ((*result
) -> data
.let
.name
, name
);
394 static int do_host_lookup (result
, dns
)
395 struct data_string
*result
;
396 struct dns_host_entry
*dns
;
403 log_debug ("time: now = %d dns = %d diff = %d",
404 cur_time
, dns
-> timeout
, cur_time
- dns
-> timeout
);
407 /* If the record hasn't timed out, just copy the data and return. */
408 if (cur_time
<= dns
-> timeout
) {
410 log_debug ("easy copy: %d %s",
413 ? inet_ntoa (*(struct in_addr
*)(dns
-> data
.data
))
416 data_string_copy (result
, &dns
-> data
, MDL
);
420 log_debug ("Looking up %s", dns
-> hostname
);
423 /* Otherwise, look it up... */
424 h
= gethostbyname (dns
-> hostname
);
430 log_error ("%s: host unknown.", dns
-> hostname
);
434 log_error ("%s: temporary name server failure",
438 log_error ("%s: name server failed", dns
-> hostname
);
441 log_error ("%s: no A record associated with address",
444 #endif /* !NO_H_ERRNO */
446 /* Okay to try again after a minute. */
447 dns
-> timeout
= cur_time
+ 60;
448 data_string_forget (&dns
-> data
, MDL
);
453 log_debug ("Lookup succeeded; first address is %s",
454 inet_ntoa (h
-> h_addr_list
[0]));
457 /* Count the number of addresses we got... */
458 for (count
= 0; h
-> h_addr_list
[count
]; count
++)
461 /* Dereference the old data, if any. */
462 data_string_forget (&dns
-> data
, MDL
);
464 /* Do we need to allocate more memory? */
465 new_len
= count
* h
-> h_length
;
466 if (!buffer_allocate (&dns
-> data
.buffer
, new_len
, MDL
))
468 log_error ("No memory for %s.", dns
-> hostname
);
472 dns
-> data
.data
= &dns
-> data
.buffer
-> data
[0];
473 dns
-> data
.len
= new_len
;
474 dns
-> data
.terminated
= 0;
476 /* Addresses are conveniently stored one to the buffer, so we
477 have to copy them out one at a time... :'( */
478 for (i
= 0; i
< count
; i
++) {
479 memcpy (&dns
-> data
.buffer
-> data
[h
-> h_length
* i
],
480 h
-> h_addr_list
[i
], (unsigned)(h
-> h_length
));
483 log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
484 *(int *)(dns
-> buffer
), h
-> h_addr_list
[0]);
487 /* XXX Set the timeout for an hour from now.
488 XXX This should really use the time on the DNS reply. */
489 dns
-> timeout
= cur_time
+ 3600;
492 log_debug ("hard copy: %d %s", dns
-> data
.len
,
494 ? inet_ntoa (*(struct in_addr
*)(dns
-> data
.data
)) : 0));
496 data_string_copy (result
, &dns
-> data
, MDL
);
500 int evaluate_expression (result
, packet
, lease
, client_state
,
501 in_options
, cfg_options
, scope
, expr
, file
, line
)
502 struct binding_value
**result
;
503 struct packet
*packet
;
505 struct client_state
*client_state
;
506 struct option_state
*in_options
;
507 struct option_state
*cfg_options
;
508 struct binding_scope
**scope
;
509 struct expression
*expr
;
513 struct binding_value
*bv
;
515 struct binding
*binding
;
517 bv
= (struct binding_value
*)0;
519 if (expr
-> op
== expr_variable_reference
) {
520 if (!scope
|| !*scope
)
523 binding
= find_binding (*scope
, expr
-> data
.variable
);
525 if (binding
&& binding
-> value
) {
527 binding_value_reference (result
,
533 } else if (expr
-> op
== expr_funcall
) {
534 struct string_list
*s
;
535 struct expression
*arg
;
536 struct binding_scope
*ns
;
539 if (!scope
|| !*scope
) {
540 log_error ("%s: no such function.",
541 expr
-> data
.funcall
.name
);
545 binding
= find_binding (*scope
, expr
-> data
.funcall
.name
);
547 if (!binding
|| !binding
-> value
) {
548 log_error ("%s: no such function.",
549 expr
-> data
.funcall
.name
);
552 if (binding
-> value
-> type
!= binding_function
) {
553 log_error ("%s: not a function.",
554 expr
-> data
.funcall
.name
);
558 /* Create a new binding scope in which to define
559 the arguments to the function. */
560 ns
= (struct binding_scope
*)0;
561 if (!binding_scope_allocate (&ns
, MDL
)) {
562 log_error ("%s: can't allocate argument scope.",
563 expr
-> data
.funcall
.name
);
567 arg
= expr
-> data
.funcall
.arglist
;
568 s
= binding
-> value
-> value
.fundef
-> args
;
570 nb
= dmalloc (sizeof *nb
, MDL
);
573 binding_scope_dereference (&ns
, MDL
);
576 memset (nb
, 0, sizeof *nb
);
577 nb
-> name
= dmalloc (strlen (s
-> string
) + 1,
580 strcpy (nb
-> name
, s
-> string
);
586 evaluate_expression (&nb
-> value
, packet
, lease
,
588 in_options
, cfg_options
, scope
,
589 arg
-> data
.arg
.val
, file
, line
);
590 nb
-> next
= ns
-> bindings
;
592 arg
= arg
-> data
.arg
.next
;
596 log_error ("%s: too many arguments.",
597 expr
-> data
.funcall
.name
);
598 binding_scope_dereference (&ns
, MDL
);
602 log_error ("%s: too few arguments.",
603 expr
-> data
.funcall
.name
);
604 binding_scope_dereference (&ns
, MDL
);
609 binding_scope_reference (&ns
-> outer
, *scope
, MDL
);
611 status
= (execute_statements
613 lease
, client_state
, in_options
, cfg_options
, &ns
,
614 binding
->value
->value
.fundef
->statements
, NULL
));
615 binding_scope_dereference (&ns
, MDL
);
619 } else if (is_boolean_expression (expr
)) {
620 if (!binding_value_allocate (&bv
, MDL
))
622 bv
-> type
= binding_boolean
;
623 status
= (evaluate_boolean_expression
624 (&bv
-> value
.boolean
, packet
, lease
, client_state
,
625 in_options
, cfg_options
, scope
, expr
));
626 } else if (is_numeric_expression (expr
)) {
627 if (!binding_value_allocate (&bv
, MDL
))
629 bv
-> type
= binding_numeric
;
630 status
= (evaluate_numeric_expression
631 (&bv
-> value
.intval
, packet
, lease
, client_state
,
632 in_options
, cfg_options
, scope
, expr
));
633 } else if (is_data_expression (expr
)) {
634 if (!binding_value_allocate (&bv
, MDL
))
636 bv
-> type
= binding_data
;
637 status
= (evaluate_data_expression
638 (&bv
-> value
.data
, packet
, lease
, client_state
,
639 in_options
, cfg_options
, scope
, expr
, MDL
));
641 log_error ("%s: invalid expression type: %d",
642 "evaluate_expression", expr
-> op
);
645 if (result
&& status
)
646 binding_value_reference (result
, bv
, file
, line
);
647 binding_value_dereference (&bv
, MDL
);
652 int binding_value_dereference (struct binding_value
**v
,
653 const char *file
, int line
)
655 struct binding_value
*bv
= *v
;
657 *v
= (struct binding_value
*)0;
659 /* Decrement the reference count. If it's nonzero, we're
662 rc_register (file
, line
, v
, bv
, bv
-> refcnt
, 1, RC_MISC
);
663 if (bv
-> refcnt
> 0)
665 if (bv
-> refcnt
< 0) {
666 log_error ("%s(%d): negative refcnt!", file
, line
);
667 #if defined (DEBUG_RC_HISTORY)
668 dump_rc_history (bv
);
670 #if defined (POINTER_DEBUG)
677 switch (bv
-> type
) {
678 case binding_boolean
:
679 case binding_numeric
:
682 if (bv
-> value
.data
.buffer
)
683 data_string_forget (&bv
-> value
.data
, file
, line
);
686 log_error ("%s(%d): invalid binding type: %d",
687 file
, line
, bv
-> type
);
690 free_binding_value(bv
, file
, line
);
694 int evaluate_boolean_expression (result
, packet
, lease
, client_state
,
695 in_options
, cfg_options
, scope
, expr
)
697 struct packet
*packet
;
699 struct client_state
*client_state
;
700 struct option_state
*in_options
;
701 struct option_state
*cfg_options
;
702 struct binding_scope
**scope
;
703 struct expression
*expr
;
705 struct data_string left
, right
;
708 struct binding
*binding
;
709 struct binding_value
*bv
, *obv
;
711 int regflags
= REG_EXTENDED
| REG_NOSUB
;
715 switch (expr
-> op
) {
717 *result
= check_collection (packet
, lease
,
719 #if defined (DEBUG_EXPRESSIONS)
720 log_debug ("bool: check (%s) returns %s",
721 expr
-> data
.check
-> name
,
722 *result
? "true" : "false");
728 bv
= obv
= (struct binding_value
*)0;
729 sleft
= evaluate_expression (&bv
, packet
, lease
, client_state
,
730 in_options
, cfg_options
, scope
,
731 expr
-> data
.equal
[0], MDL
);
732 sright
= evaluate_expression (&obv
, packet
, lease
,
733 client_state
, in_options
,
735 expr
-> data
.equal
[1], MDL
);
736 if (sleft
&& sright
) {
737 if (bv
-> type
!= obv
-> type
)
738 *result
= expr
-> op
== expr_not_equal
;
740 switch (obv
-> type
) {
741 case binding_boolean
:
742 if (bv
-> value
.boolean
== obv
-> value
.boolean
)
743 *result
= expr
-> op
== expr_equal
;
745 *result
= expr
-> op
== expr_not_equal
;
749 if ((bv
-> value
.data
.len
==
750 obv
-> value
.data
.len
) &&
751 !memcmp (bv
-> value
.data
.data
,
752 obv
-> value
.data
.data
,
753 obv
-> value
.data
.len
))
754 *result
= expr
-> op
== expr_equal
;
756 *result
= expr
-> op
== expr_not_equal
;
759 case binding_numeric
:
760 if (bv
-> value
.intval
== obv
-> value
.intval
)
761 *result
= expr
-> op
== expr_equal
;
763 *result
= expr
-> op
== expr_not_equal
;
766 case binding_function
:
767 if (bv
-> value
.fundef
== obv
-> value
.fundef
)
768 *result
= expr
-> op
== expr_equal
;
770 *result
= expr
-> op
== expr_not_equal
;
773 *result
= expr
-> op
== expr_not_equal
;
777 } else if (!sleft
&& !sright
)
778 *result
= expr
-> op
== expr_equal
;
780 *result
= expr
-> op
== expr_not_equal
;
782 #if defined (DEBUG_EXPRESSIONS)
783 log_debug ("bool: %sequal = %s",
784 expr
-> op
== expr_not_equal
? "not" : "",
785 (*result
? "true" : "false"));
788 binding_value_dereference (&bv
, MDL
);
790 binding_value_dereference (&obv
, MDL
);
793 case expr_iregex_match
:
795 regflags
|= REG_ICASE
;
798 case expr_regex_match
:
800 memset(&left
, 0, sizeof left
);
801 bleft
= evaluate_data_expression(&left
, packet
, lease
,
803 in_options
, cfg_options
,
805 expr
->data
.equal
[0], MDL
);
807 /* This is annoying, regexec requires the string being processed
808 * to be NULL terminated, but left may not be, so pass it into
809 * the termination function to ensure it's null terminated.
811 if (bleft
&& (data_string_terminate(&left
, MDL
) == 0)) {
812 /* failed to make a null terminated version, couldn't
813 * create a copy, probably a memory issue, an error
814 * message has already been logged */
818 memset(&right
, 0, sizeof right
);
819 bright
= evaluate_data_expression(&right
, packet
, lease
,
821 in_options
, cfg_options
,
823 expr
->data
.equal
[1], MDL
);
826 memset(&re
, 0, sizeof(re
));
827 if (bleft
&& bright
&&
828 (left
.data
!= NULL
) && (right
.data
!= NULL
) &&
829 (regcomp(&re
, (char *)right
.data
, regflags
) == 0) &&
830 (regexec(&re
, (char *)left
.data
, (size_t)0, NULL
, 0) == 0))
833 #if defined (DEBUG_EXPRESSIONS)
834 log_debug("bool: %s ~= %s yields %s",
835 bleft
? print_hex_1(left
.len
, left
.data
, 20)
837 bright
? print_hex_2 (right
.len
, right
.data
, 20)
839 *result
? "true" : "false");
843 data_string_forget(&left
, MDL
);
845 data_string_forget(&right
, MDL
);
850 * If we have bleft and bright then we have a good
851 * syntax, otherwise not.
853 * XXX: we don't warn on invalid regular expression
856 return bleft
&& bright
;
858 /* It shouldn't be possible to configure a regex operator
859 * when there's no support.
861 log_fatal("Impossible condition at %s:%d.", MDL
);
866 sleft
= evaluate_boolean_expression (&bleft
, packet
, lease
,
868 in_options
, cfg_options
,
870 expr
-> data
.and [0]);
872 sright
= evaluate_boolean_expression
873 (&bright
, packet
, lease
, client_state
,
874 in_options
, cfg_options
,
875 scope
, expr
-> data
.and [1]);
879 #if defined (DEBUG_EXPRESSIONS)
880 log_debug ("bool: and (%s, %s) = %s",
881 sleft
? (bleft
? "true" : "false") : "NULL",
882 sright
? (bright
? "true" : "false") : "NULL",
884 ? (bleft
&& bright
? "true" : "false") : "NULL"));
886 if (sleft
&& sright
) {
887 *result
= bleft
&& bright
;
894 sleft
= evaluate_boolean_expression (&bleft
, packet
, lease
,
896 in_options
, cfg_options
,
898 expr
-> data
.or [0]);
899 if (!sleft
|| !bleft
)
900 sright
= evaluate_boolean_expression
901 (&bright
, packet
, lease
, client_state
,
902 in_options
, cfg_options
,
903 scope
, expr
-> data
.or [1]);
906 #if defined (DEBUG_EXPRESSIONS)
907 log_debug ("bool: or (%s, %s) = %s",
908 sleft
? (bleft
? "true" : "false") : "NULL",
909 sright
? (bright
? "true" : "false") : "NULL",
911 ? (bleft
|| bright
? "true" : "false") : "NULL"));
913 if (sleft
|| sright
) {
914 *result
= bleft
|| bright
;
920 sleft
= evaluate_boolean_expression(&bleft
, packet
, lease
,
922 in_options
, cfg_options
,
925 #if defined (DEBUG_EXPRESSIONS)
926 log_debug("bool: not (%s) = %s",
927 sleft
? (bleft
? "true" : "false") : "NULL",
928 sleft
? (!bleft
? "true" : "false") : "NULL");
937 memset (&left
, 0, sizeof left
);
939 !get_option (&left
, expr
-> data
.exists
-> universe
,
940 packet
, lease
, client_state
,
941 in_options
, cfg_options
, in_options
,
942 scope
, expr
-> data
.exists
-> code
, MDL
))
946 data_string_forget (&left
, MDL
);
948 #if defined (DEBUG_EXPRESSIONS)
949 log_debug ("bool: exists %s.%s = %s",
950 expr
-> data
.option
-> universe
-> name
,
951 expr
-> data
.option
-> name
,
952 *result
? "true" : "false");
958 #if defined (DEBUG_EXPRESSIONS)
959 log_debug ("bool: known = NULL");
963 #if defined (DEBUG_EXPRESSIONS)
964 log_debug ("bool: known = %s",
965 packet
-> known
? "true" : "false");
967 *result
= packet
-> known
;
971 if (!lease
|| !(lease
-> flags
& STATIC_LEASE
)) {
972 #if defined (DEBUG_EXPRESSIONS)
973 log_debug ("bool: static = false (%s %s %s %d)",
975 (lease
&& (lease
-> flags
& STATIC_LEASE
)
977 piaddr (lease
-> ip_addr
),
978 lease
? lease
-> flags
: 0);
983 #if defined (DEBUG_EXPRESSIONS)
984 log_debug ("bool: static = true");
989 case expr_variable_exists
:
990 if (scope
&& *scope
) {
991 binding
= find_binding (*scope
, expr
-> data
.variable
);
994 if (binding
-> value
)
1002 #if defined (DEBUG_EXPRESSIONS)
1003 log_debug ("boolean: %s? = %s", expr
-> data
.variable
,
1004 *result
? "true" : "false");
1008 case expr_variable_reference
:
1009 if (scope
&& *scope
) {
1010 binding
= find_binding (*scope
, expr
-> data
.variable
);
1012 if (binding
&& binding
-> value
) {
1013 if (binding
-> value
-> type
==
1015 *result
= binding
-> value
-> value
.boolean
;
1018 log_error ("binding type %d in %s.",
1019 binding
-> value
-> type
,
1020 "evaluate_boolean_expression");
1027 #if defined (DEBUG_EXPRESSIONS)
1028 log_debug ("boolean: %s = %s", expr
-> data
.variable
,
1029 sleft
? (*result
? "true" : "false") : "NULL");
1034 bv
= (struct binding_value
*)0;
1035 sleft
= evaluate_expression (&bv
, packet
, lease
, client_state
,
1036 in_options
, cfg_options
,
1039 if (bv
-> type
!= binding_boolean
)
1040 log_error ("%s() returned type %d in %s.",
1041 expr
-> data
.funcall
.name
,
1043 "evaluate_boolean_expression");
1045 *result
= bv
-> value
.boolean
;
1046 binding_value_dereference (&bv
, MDL
);
1048 #if defined (DEBUG_EXPRESSIONS)
1049 log_debug ("boolean: %s() = %s", expr
-> data
.funcall
.name
,
1050 sleft
? (*result
? "true" : "false") : "NULL");
1056 case expr_substring
:
1062 case expr_const_data
:
1065 case expr_encapsulate
:
1066 case expr_host_lookup
:
1067 case expr_encode_int8
:
1068 case expr_encode_int16
:
1069 case expr_encode_int32
:
1070 case expr_binary_to_ascii
:
1072 case expr_pick_first_value
:
1073 case expr_host_decl_name
:
1074 case expr_config_option
:
1075 case expr_leased_address
:
1079 case expr_gethostname
:
1081 case expr_concat_dclist
:
1082 log_error ("Data opcode in evaluate_boolean_expression: %d",
1086 case expr_extract_int8
:
1087 case expr_extract_int16
:
1088 case expr_extract_int32
:
1089 case expr_const_int
:
1090 case expr_lease_time
:
1091 case expr_dns_transaction
:
1096 case expr_remainder
:
1097 case expr_binary_and
:
1098 case expr_binary_or
:
1099 case expr_binary_xor
:
1100 case expr_client_state
:
1101 log_error ("Numeric opcode in evaluate_boolean_expression: %d",
1106 case expr_ns_delete
:
1107 case expr_ns_exists
:
1108 case expr_ns_not_exists
:
1109 log_error ("dns opcode in evaluate_boolean_expression: %d",
1114 log_error ("function definition in evaluate_boolean_expr");
1121 log_error ("Bogus opcode in evaluate_boolean_expression: %d",
1126 int evaluate_data_expression (result
, packet
, lease
, client_state
,
1127 in_options
, cfg_options
, scope
, expr
, file
, line
)
1128 struct data_string
*result
;
1129 struct packet
*packet
;
1130 struct lease
*lease
;
1131 struct client_state
*client_state
;
1132 struct option_state
*in_options
;
1133 struct option_state
*cfg_options
;
1134 struct binding_scope
**scope
;
1135 struct expression
*expr
;
1139 struct data_string data
, other
;
1140 unsigned long offset
, len
, i
;
1143 struct binding
*binding
;
1145 struct binding_value
*bv
;
1146 struct packet
*relay_packet
;
1147 struct option_state
*relay_options
;
1149 switch (expr
-> op
) {
1150 /* Extract N bytes starting at byte M of a data string. */
1151 case expr_substring
:
1152 memset (&data
, 0, sizeof data
);
1153 s0
= evaluate_data_expression (&data
, packet
, lease
,
1155 in_options
, cfg_options
, scope
,
1156 expr
-> data
.substring
.expr
,
1159 /* Evaluate the offset and length. */
1160 s1
= evaluate_numeric_expression
1161 (&offset
, packet
, lease
, client_state
, in_options
,
1162 cfg_options
, scope
, expr
-> data
.substring
.offset
);
1163 s2
= evaluate_numeric_expression (&len
, packet
, lease
,
1165 in_options
, cfg_options
,
1167 expr
-> data
.substring
.len
);
1169 if (s0
&& s1
&& s2
) {
1170 /* If the offset is after end of the string,
1171 return an empty string. Otherwise, do the
1172 adjustments and return what's left. */
1173 if (data
.len
> offset
) {
1174 data_string_copy (result
, &data
, file
, line
);
1175 result
-> len
-= offset
;
1176 if (result
-> len
> len
) {
1177 result
-> len
= len
;
1178 result
-> terminated
= 0;
1180 result
-> data
+= offset
;
1186 #if defined (DEBUG_EXPRESSIONS)
1187 log_debug ("data: substring (%s, %s, %s) = %s",
1188 s0
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
1189 s1
? print_dec_1 (offset
) : "NULL",
1190 s2
? print_dec_2 (len
) : "NULL",
1191 (s3
? print_hex_2 (result
-> len
, result
-> data
, 30)
1195 data_string_forget (&data
, MDL
);
1200 /* Extract the last N bytes of a data string. */
1202 memset (&data
, 0, sizeof data
);
1203 s0
= evaluate_data_expression (&data
, packet
, lease
,
1205 in_options
, cfg_options
, scope
,
1206 expr
-> data
.suffix
.expr
, MDL
);
1207 /* Evaluate the length. */
1208 s1
= evaluate_numeric_expression (&len
, packet
, lease
,
1210 in_options
, cfg_options
,
1212 expr
-> data
.suffix
.len
);
1214 data_string_copy (result
, &data
, file
, line
);
1216 /* If we are returning the last N bytes of a
1217 string whose length is <= N, just return
1218 the string - otherwise, compute a new
1219 starting address and decrease the
1221 if (data
.len
> len
) {
1222 result
-> data
+= data
.len
- len
;
1223 result
-> len
= len
;
1226 data_string_forget (&data
, MDL
);
1229 #if defined (DEBUG_EXPRESSIONS)
1230 log_debug ("data: suffix (%s, %s) = %s",
1231 s0
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
1232 s1
? print_dec_1 (len
) : "NULL",
1234 ? print_hex_2 (result
-> len
, result
-> data
, 30)
1240 /* Convert string to lowercase. */
1242 memset(&data
, 0, sizeof data
);
1243 s0
= evaluate_data_expression(&data
, packet
, lease
,
1245 in_options
, cfg_options
, scope
,
1246 expr
->data
.lcase
, MDL
);
1249 result
->len
= data
.len
;
1250 if (buffer_allocate(&result
->buffer
,
1251 result
->len
+ data
.terminated
,
1253 result
->data
= &result
->buffer
->data
[0];
1254 memcpy(result
->buffer
->data
, data
.data
,
1255 data
.len
+ data
.terminated
);
1256 result
->terminated
= data
.terminated
;
1257 s
= (unsigned char *)result
->data
;
1258 for (i
= 0; i
< result
->len
; i
++, s
++)
1262 log_error("data: lcase: no buffer memory.");
1266 #if defined (DEBUG_EXPRESSIONS)
1267 log_debug("data: lcase (%s) = %s",
1268 s0
? print_hex_1(data
.len
, data
.data
, 30) : "NULL",
1269 s1
? print_hex_2(result
->len
, result
->data
, 30)
1273 data_string_forget(&data
, MDL
);
1276 /* Convert string to uppercase. */
1278 memset(&data
, 0, sizeof data
);
1279 s0
= evaluate_data_expression(&data
, packet
, lease
,
1281 in_options
, cfg_options
, scope
,
1282 expr
->data
.lcase
, MDL
);
1285 result
->len
= data
.len
;
1286 if (buffer_allocate(&result
->buffer
,
1287 result
->len
+ data
.terminated
,
1289 result
->data
= &result
->buffer
->data
[0];
1290 memcpy(result
->buffer
->data
, data
.data
,
1291 data
.len
+ data
.terminated
);
1292 result
->terminated
= data
.terminated
;
1293 s
= (unsigned char *)result
->data
;
1294 for (i
= 0; i
< result
->len
; i
++, s
++)
1298 log_error("data: lcase: no buffer memory.");
1302 #if defined (DEBUG_EXPRESSIONS)
1303 log_debug("data: ucase (%s) = %s",
1304 s0
? print_hex_1(data
.len
, data
.data
, 30) : "NULL",
1305 s1
? print_hex_2(result
->len
, result
->data
, 30)
1309 data_string_forget(&data
, MDL
);
1313 /* Extract an option. */
1316 s0
= get_option (result
,
1317 expr
-> data
.option
-> universe
,
1318 packet
, lease
, client_state
,
1319 in_options
, cfg_options
, in_options
,
1320 scope
, expr
-> data
.option
-> code
,
1325 #if defined (DEBUG_EXPRESSIONS)
1326 log_debug ("data: option %s.%s = %s",
1327 expr
-> data
.option
-> universe
-> name
,
1328 expr
-> data
.option
-> name
,
1329 s0
? print_hex_1 (result
-> len
, result
-> data
, 60)
1334 case expr_config_option
:
1336 s0
= get_option (result
,
1337 expr
-> data
.option
-> universe
,
1338 packet
, lease
, client_state
,
1339 in_options
, cfg_options
, cfg_options
,
1340 scope
, expr
-> data
.option
-> code
,
1345 #if defined (DEBUG_EXPRESSIONS)
1346 log_debug ("data: config-option %s.%s = %s",
1347 expr
-> data
.option
-> universe
-> name
,
1348 expr
-> data
.option
-> name
,
1349 s0
? print_hex_1 (result
-> len
, result
-> data
, 60)
1354 /* Combine the hardware type and address. */
1356 /* On the client, hardware is our hardware. */
1358 memset(result
, 0, sizeof(*result
));
1359 result
->data
= client_state
->interface
->hw_address
.hbuf
;
1360 result
->len
= client_state
->interface
->hw_address
.hlen
;
1361 #if defined (DEBUG_EXPRESSIONS)
1362 log_debug("data: hardware = %s",
1363 print_hex_1(result
->len
, result
->data
, 60));
1368 /* The server cares about the client's hardware address,
1369 so only in the case where we are examining a packet or have
1370 a lease with a hardware address can we return anything. */
1372 if (packet
!= NULL
&& packet
->raw
!= NULL
) {
1373 if (packet
->raw
->hlen
> sizeof(packet
->raw
->chaddr
)) {
1374 log_error("data: hardware: invalid hlen (%d)\n",
1378 result
->len
= packet
->raw
->hlen
+ 1;
1379 if (buffer_allocate(&result
->buffer
, result
->len
, MDL
)){
1380 result
->data
= &result
->buffer
->data
[0];
1381 result
->buffer
->data
[0] = packet
->raw
->htype
;
1382 memcpy(&result
->buffer
->data
[1],
1383 packet
->raw
->chaddr
, packet
->raw
->hlen
);
1384 result
->terminated
= 0;
1386 log_error("data: hardware: "
1387 "no memory for buffer.");
1390 } else if (lease
!= NULL
) {
1391 result
->len
= lease
->hardware_addr
.hlen
;
1392 if (buffer_allocate(&result
->buffer
, result
->len
, MDL
)){
1393 result
->data
= &result
->buffer
->data
[0];
1394 memcpy(result
->buffer
->data
,
1395 lease
->hardware_addr
.hbuf
, result
->len
);
1396 result
->terminated
= 0;
1398 log_error("data: hardware: "
1399 "no memory for buffer.");
1403 log_error("data: hardware: no raw packet or lease "
1408 #if defined (DEBUG_EXPRESSIONS)
1409 log_debug("data: hardware = %s",
1410 print_hex_1(result
->len
, result
->data
, 60));
1414 /* Extract part of the raw packet. */
1416 if (!packet
|| !packet
-> raw
) {
1417 log_error ("data: packet: raw packet not available");
1421 s0
= evaluate_numeric_expression (&offset
, packet
, lease
,
1423 in_options
, cfg_options
,
1425 expr
-> data
.packet
.offset
);
1426 s1
= evaluate_numeric_expression (&len
,
1427 packet
, lease
, client_state
,
1428 in_options
, cfg_options
,
1430 expr
-> data
.packet
.len
);
1431 if (s0
&& s1
&& offset
< packet
-> packet_length
) {
1432 if (offset
+ len
> packet
-> packet_length
)
1434 packet
-> packet_length
- offset
;
1436 result
-> len
= len
;
1437 if (buffer_allocate (&result
-> buffer
,
1438 result
-> len
, file
, line
)) {
1439 result
-> data
= &result
-> buffer
-> data
[0];
1440 memcpy (result
-> buffer
-> data
,
1441 (((unsigned char *)(packet
-> raw
))
1442 + offset
), result
-> len
);
1443 result
-> terminated
= 0;
1445 log_error ("data: packet: no buffer memory.");
1451 #if defined (DEBUG_EXPRESSIONS)
1452 log_debug ("data: packet (%ld, %ld) = %s",
1454 s2
? print_hex_1 (result
-> len
,
1455 result
-> data
, 60) : NULL
);
1459 /* The encapsulation of all defined options in an
1461 case expr_encapsulate
:
1463 s0
= option_space_encapsulate
1464 (result
, packet
, lease
, client_state
,
1465 in_options
, cfg_options
, scope
,
1466 &expr
-> data
.encapsulate
);
1470 #if defined (DEBUG_EXPRESSIONS)
1471 log_debug ("data: encapsulate (%s) = %s",
1472 expr
-> data
.encapsulate
.data
,
1473 s0
? print_hex_1 (result
-> len
,
1474 result
-> data
, 60) : "NULL");
1478 /* Some constant data... */
1479 case expr_const_data
:
1480 #if defined (DEBUG_EXPRESSIONS)
1481 log_debug ("data: const = %s",
1482 print_hex_1 (expr
-> data
.const_data
.len
,
1483 expr
-> data
.const_data
.data
, 60));
1485 data_string_copy (result
,
1486 &expr
-> data
.const_data
, file
, line
);
1489 /* Hostname lookup... */
1490 case expr_host_lookup
:
1491 s0
= do_host_lookup (result
, expr
-> data
.host_lookup
);
1492 #if defined (DEBUG_EXPRESSIONS)
1493 log_debug ("data: DNS lookup (%s) = %s",
1494 expr
-> data
.host_lookup
-> hostname
,
1496 ? print_dotted_quads (result
-> len
, result
-> data
)
1501 /* Concatenation... */
1503 memset (&data
, 0, sizeof data
);
1504 s0
= evaluate_data_expression (&data
, packet
, lease
,
1506 in_options
, cfg_options
, scope
,
1507 expr
-> data
.concat
[0], MDL
);
1508 memset (&other
, 0, sizeof other
);
1509 s1
= evaluate_data_expression (&other
, packet
, lease
,
1511 in_options
, cfg_options
, scope
,
1512 expr
-> data
.concat
[1], MDL
);
1515 result
-> len
= data
.len
+ other
.len
;
1516 if (!buffer_allocate (&result
-> buffer
,
1517 (result
-> len
+ other
.terminated
),
1519 log_error ("data: concat: no memory");
1521 data_string_forget (&data
, MDL
);
1522 data_string_forget (&other
, MDL
);
1525 result
-> data
= &result
-> buffer
-> data
[0];
1526 memcpy (result
-> buffer
-> data
, data
.data
, data
.len
);
1527 memcpy (&result
-> buffer
-> data
[data
.len
],
1528 other
.data
, other
.len
+ other
.terminated
);
1532 data_string_forget (&data
, MDL
);
1534 data_string_forget (&other
, MDL
);
1535 #if defined (DEBUG_EXPRESSIONS)
1536 log_debug ("data: concat (%s, %s) = %s",
1537 s0
? print_hex_1 (data
.len
, data
.data
, 20) : "NULL",
1538 s1
? print_hex_2 (other
.len
, other
.data
, 20) : "NULL",
1540 ? print_hex_3 (result
-> len
, result
-> data
, 30)
1545 case expr_encode_int8
:
1546 s0
= evaluate_numeric_expression (&len
, packet
, lease
,
1548 in_options
, cfg_options
,
1550 expr
-> data
.encode_int
);
1553 if (!buffer_allocate (&result
-> buffer
,
1555 log_error ("data: encode_int8: no memory");
1559 result
-> data
= &result
-> buffer
-> data
[0];
1560 result
-> buffer
-> data
[0] = len
;
1565 #if defined (DEBUG_EXPRESSIONS)
1567 log_debug ("data: encode_int8 (NULL) = NULL");
1569 log_debug ("data: encode_int8 (%ld) = %s", len
,
1570 print_hex_2 (result
-> len
,
1571 result
-> data
, 20));
1576 case expr_encode_int16
:
1577 s0
= evaluate_numeric_expression (&len
, packet
, lease
,
1579 in_options
, cfg_options
,
1581 expr
-> data
.encode_int
);
1584 if (!buffer_allocate (&result
-> buffer
, 2,
1586 log_error ("data: encode_int16: no memory");
1590 result
-> data
= &result
-> buffer
-> data
[0];
1591 putUShort (result
-> buffer
-> data
, len
);
1596 #if defined (DEBUG_EXPRESSIONS)
1598 log_debug ("data: encode_int16 (NULL) = NULL");
1600 log_debug ("data: encode_int16 (%ld) = %s", len
,
1601 print_hex_2 (result
-> len
,
1602 result
-> data
, 20));
1606 case expr_encode_int32
:
1607 s0
= evaluate_numeric_expression (&len
, packet
, lease
,
1609 in_options
, cfg_options
,
1611 expr
-> data
.encode_int
);
1614 if (!buffer_allocate (&result
-> buffer
, 4,
1616 log_error ("data: encode_int32: no memory");
1620 result
-> data
= &result
-> buffer
-> data
[0];
1621 putULong (result
-> buffer
-> data
, len
);
1626 #if defined (DEBUG_EXPRESSIONS)
1628 log_debug ("data: encode_int32 (NULL) = NULL");
1630 log_debug ("data: encode_int32 (%ld) = %s", len
,
1631 print_hex_2 (result
-> len
,
1632 result
-> data
, 20));
1636 case expr_binary_to_ascii
:
1637 /* Evaluate the base (offset) and width (len): */
1638 s0
= evaluate_numeric_expression
1639 (&offset
, packet
, lease
, client_state
, in_options
,
1640 cfg_options
, scope
, expr
-> data
.b2a
.base
);
1641 s1
= evaluate_numeric_expression (&len
, packet
, lease
,
1643 in_options
, cfg_options
,
1645 expr
-> data
.b2a
.width
);
1647 /* Evaluate the separator string. */
1648 memset (&data
, 0, sizeof data
);
1649 s2
= evaluate_data_expression (&data
, packet
, lease
,
1651 in_options
, cfg_options
, scope
,
1652 expr
-> data
.b2a
.separator
,
1655 /* Evaluate the data to be converted. */
1656 memset (&other
, 0, sizeof other
);
1657 s3
= evaluate_data_expression (&other
, packet
, lease
,
1659 in_options
, cfg_options
, scope
,
1660 expr
-> data
.b2a
.buffer
, MDL
);
1662 if (s0
&& s1
&& s2
&& s3
) {
1665 if (len
!= 8 && len
!= 16 && len
!= 32) {
1666 log_info ("binary_to_ascii: %s %ld!",
1667 "invalid width", len
);
1673 /* The buffer must be a multiple of the number's
1675 if (other
.len
% len
) {
1676 log_info ("binary-to-ascii: %s %d %s %ld!",
1677 "length of buffer", other
.len
,
1678 "not a multiple of width", len
);
1683 /* Count the width of the output. */
1685 for (i
= 0; i
< other
.len
; i
+= len
) {
1688 if (other
.data
[i
] < 8)
1690 else if (other
.data
[i
] < 64)
1694 } else if (offset
== 10) {
1695 if (other
.data
[i
] < 10)
1697 else if (other
.data
[i
] < 100)
1701 } else if (offset
== 16) {
1702 if (other
.data
[i
] < 16)
1707 buflen
+= (converted_length
1711 buflen
+= (converted_length
1714 if (i
+ len
!= other
.len
)
1718 if (!buffer_allocate (&result
-> buffer
,
1719 buflen
+ 1, file
, line
)) {
1720 log_error ("data: binary-to-ascii: no memory");
1724 result
-> data
= &result
-> buffer
-> data
[0];
1725 result
-> len
= buflen
;
1726 result
-> terminated
= 1;
1729 for (i
= 0; i
< other
.len
; i
+= len
) {
1730 buflen
+= (binary_to_ascii
1731 (&result
-> buffer
-> data
[buflen
],
1732 &other
.data
[i
], offset
, len
));
1733 if (i
+ len
!= other
.len
) {
1735 buffer
-> data
[buflen
],
1736 data
.data
, data
.len
);
1740 /* NUL terminate. */
1741 result
-> buffer
-> data
[buflen
] = 0;
1747 #if defined (DEBUG_EXPRESSIONS)
1748 log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
1749 s0
? print_dec_1 (offset
) : "NULL",
1750 s1
? print_dec_2 (len
) : "NULL",
1751 s2
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
1752 s3
? print_hex_2 (other
.len
, other
.data
, 30) : "NULL",
1753 (status
? print_hex_3 (result
-> len
, result
-> data
, 30)
1757 data_string_forget (&data
, MDL
);
1759 data_string_forget (&other
, MDL
);
1765 /* Evaluate the width (len): */
1766 s0
= evaluate_numeric_expression
1767 (&len
, packet
, lease
, client_state
, in_options
,
1768 cfg_options
, scope
, expr
-> data
.reverse
.width
);
1770 /* Evaluate the data. */
1771 memset (&data
, 0, sizeof data
);
1772 s1
= evaluate_data_expression (&data
, packet
, lease
,
1774 in_options
, cfg_options
, scope
,
1775 expr
-> data
.reverse
.buffer
,
1781 /* The buffer must be a multiple of the number's
1783 if (data
.len
% len
) {
1784 log_info ("reverse: %s %d %s %ld!",
1785 "length of buffer", data
.len
,
1786 "not a multiple of width", len
);
1791 /* XXX reverse in place? I don't think we can. */
1792 if (!buffer_allocate (&result
-> buffer
,
1793 data
.len
, file
, line
)) {
1794 log_error ("data: reverse: no memory");
1798 result
-> data
= &result
-> buffer
-> data
[0];
1799 result
-> len
= data
.len
;
1800 result
-> terminated
= 0;
1802 for (i
= 0; i
< data
.len
; i
+= len
) {
1803 memcpy (&result
-> buffer
-> data
[i
],
1804 &data
.data
[data
.len
- i
- len
], len
);
1811 #if defined (DEBUG_EXPRESSIONS)
1812 log_debug ("data: reverse (%s, %s) = %s",
1813 s0
? print_dec_1 (len
) : "NULL",
1814 s1
? print_hex_1 (data
.len
, data
.data
, 30) : "NULL",
1815 (status
? print_hex_3 (result
-> len
, result
-> data
, 30)
1819 data_string_forget (&data
, MDL
);
1824 case expr_leased_address
:
1826 log_debug("data: \"leased-address\" configuration "
1827 "directive: there is no lease associated "
1828 "with this client.");
1831 result
-> len
= lease
-> ip_addr
.len
;
1832 if (buffer_allocate (&result
-> buffer
, result
-> len
,
1834 result
-> data
= &result
-> buffer
-> data
[0];
1835 memcpy (&result
-> buffer
-> data
[0],
1836 lease
-> ip_addr
.iabuf
, lease
-> ip_addr
.len
);
1837 result
-> terminated
= 0;
1839 log_error ("data: leased-address: no memory.");
1842 #if defined (DEBUG_EXPRESSIONS)
1843 log_debug ("data: leased-address = %s",
1844 print_hex_1 (result
-> len
, result
-> data
, 60));
1848 case expr_pick_first_value
:
1849 memset (&data
, 0, sizeof data
);
1850 if ((evaluate_data_expression
1852 lease
, client_state
, in_options
, cfg_options
,
1853 scope
, expr
-> data
.pick_first_value
.car
, MDL
))) {
1854 #if defined (DEBUG_EXPRESSIONS)
1855 log_debug ("data: pick_first_value (%s, xxx)",
1856 print_hex_1 (result
-> len
,
1857 result
-> data
, 40));
1862 if (expr
-> data
.pick_first_value
.cdr
&&
1863 (evaluate_data_expression
1865 lease
, client_state
, in_options
, cfg_options
,
1866 scope
, expr
-> data
.pick_first_value
.cdr
, MDL
))) {
1867 #if defined (DEBUG_EXPRESSIONS)
1868 log_debug ("data: pick_first_value (NULL, %s)",
1869 print_hex_1 (result
-> len
,
1870 result
-> data
, 40));
1875 #if defined (DEBUG_EXPRESSIONS)
1876 log_debug ("data: pick_first_value (NULL, NULL) = NULL");
1880 case expr_host_decl_name
:
1881 if (!lease
|| !lease
-> host
) {
1882 log_error ("data: host_decl_name: not available");
1885 result
-> len
= strlen (lease
-> host
-> name
);
1886 if (buffer_allocate (&result
-> buffer
,
1887 result
-> len
+ 1, file
, line
)) {
1888 result
-> data
= &result
-> buffer
-> data
[0];
1889 strcpy ((char *)&result
-> buffer
-> data
[0],
1890 lease
-> host
-> name
);
1891 result
-> terminated
= 1;
1893 log_error ("data: host-decl-name: no memory.");
1896 #if defined (DEBUG_EXPRESSIONS)
1897 log_debug ("data: host-decl-name = %s", lease
-> host
-> name
);
1902 #if defined (DEBUG_EXPRESSIONS)
1903 log_debug ("data: null = NULL");
1907 case expr_variable_reference
:
1908 if (scope
&& *scope
) {
1909 binding
= find_binding (*scope
, expr
-> data
.variable
);
1911 if (binding
&& binding
-> value
) {
1912 if (binding
-> value
-> type
== binding_data
) {
1913 data_string_copy (result
,
1914 &binding
-> value
-> value
.data
,
1917 } else if (binding
-> value
-> type
!= binding_data
) {
1918 log_error ("binding type %d in %s.",
1919 binding
-> value
-> type
,
1920 "evaluate_data_expression");
1928 #if defined (DEBUG_EXPRESSIONS)
1929 log_debug ("data: %s = %s", expr
-> data
.variable
,
1930 s0
? print_hex_1 (result
-> len
,
1931 result
-> data
, 50) : "NULL");
1936 bv
= (struct binding_value
*)0;
1937 s0
= evaluate_expression (&bv
, packet
, lease
, client_state
,
1938 in_options
, cfg_options
,
1941 if (bv
-> type
!= binding_data
)
1942 log_error ("%s() returned type %d in %s.",
1943 expr
-> data
.funcall
.name
,
1945 "evaluate_data_expression");
1947 data_string_copy (result
, &bv
-> value
.data
,
1949 binding_value_dereference (&bv
, MDL
);
1951 #if defined (DEBUG_EXPRESSIONS)
1952 log_debug ("data: %s = %s", expr
-> data
.funcall
.name
,
1953 s0
? print_hex_1 (result
-> len
,
1954 result
-> data
, 50) : "NULL");
1958 /* Extract the filename. */
1960 if (packet
&& packet
-> raw
-> file
[0]) {
1962 memchr (packet
-> raw
-> file
, 0,
1963 sizeof packet
-> raw
-> file
);
1965 fn
= ((char *)packet
-> raw
-> file
+
1966 sizeof packet
-> raw
-> file
);
1967 result
-> len
= fn
- &(packet
-> raw
-> file
[0]);
1968 if (buffer_allocate (&result
-> buffer
,
1969 result
-> len
+ 1, file
, line
)) {
1970 result
-> data
= &result
-> buffer
-> data
[0];
1971 memcpy (&result
-> buffer
-> data
[0],
1972 packet
-> raw
-> file
,
1974 result
-> buffer
-> data
[result
-> len
] = 0;
1975 result
-> terminated
= 1;
1978 log_error ("data: filename: no memory.");
1984 #if defined (DEBUG_EXPRESSIONS)
1985 log_info ("data: filename = \"%s\"",
1986 s0
? (const char *)(result
-> data
) : "NULL");
1990 /* Extract the server name. */
1992 if (packet
&& packet
-> raw
-> sname
[0]) {
1994 memchr (packet
-> raw
-> sname
, 0,
1995 sizeof packet
-> raw
-> sname
);
1997 fn
= ((char *)packet
-> raw
-> sname
+
1998 sizeof packet
-> raw
-> sname
);
1999 result
-> len
= fn
- &packet
-> raw
-> sname
[0];
2000 if (buffer_allocate (&result
-> buffer
,
2001 result
-> len
+ 1, file
, line
)) {
2002 result
-> data
= &result
-> buffer
-> data
[0];
2003 memcpy (&result
-> buffer
-> data
[0],
2004 packet
-> raw
-> sname
,
2006 result
-> buffer
-> data
[result
-> len
] = 0;
2007 result
-> terminated
= 1;
2010 log_error ("data: sname: no memory.");
2016 #if defined (DEBUG_EXPRESSIONS)
2017 log_info ("data: sname = \"%s\"",
2018 s0
? (const char *)(result
-> data
) : "NULL");
2022 /* Provide the system's local hostname as a return value. */
2023 case expr_gethostname
:
2025 * Allocate a buffer to return.
2027 * The largest valid hostname is maybe 64 octets at a single
2028 * label, or 255 octets if you think a hostname is allowed
2029 * to contain labels (plus termination).
2031 memset(result
, 0, sizeof(*result
));
2032 if (!buffer_allocate(&result
->buffer
, 255, file
, line
)) {
2033 log_error("data: gethostname(): no memory for buffer");
2036 result
->data
= result
->buffer
->data
;
2039 * On successful completion, gethostname() resturns 0. It may
2040 * not null-terminate the string if there was insufficient
2043 if (!gethostname((char *)result
->buffer
->data
, 255)) {
2044 if (result
->buffer
->data
[255] == '\0')
2046 strlen((char *)result
->buffer
->data
);
2052 data_string_forget(result
, MDL
);
2055 /* Find an option within a v6relay context
2057 * The numeric expression in relay indicates which relay
2058 * to try and use as the context. The relays are numbered
2059 * 1 to 32 with 1 being the one closest to the client and
2060 * 32 closest to the server. A value of greater than 33
2061 * indicates using the one closest to the server whatever
2062 * the count. A value of 0 indicates not using the relay
2063 * options, this is included for completeness and consistency
2064 * with the host-identier code.
2066 * The data expression in roption is evaluated in that
2067 * context and the result returned.
2072 memset (&data
, 0, sizeof data
);
2074 /* Evaluate the relay count */
2075 s0
= evaluate_numeric_expression(&len
, packet
, lease
,
2077 in_options
, cfg_options
,
2079 expr
->data
.v6relay
.relay
);
2081 /* no number or an obviously invalid number */
2084 ((packet
== NULL
) ||
2085 (packet
->dhcpv6_container_packet
== NULL
)))) {
2086 #if defined (DEBUG_EXPRESSIONS)
2087 log_debug("data: v6relay(%lu) = NULL", len
);
2092 /* Find the correct packet for the requested relay */
2094 relay_packet
= packet
;
2095 relay_options
= in_options
;
2097 (relay_packet
->dhcpv6_container_packet
!= NULL
)) {
2098 relay_packet
= relay_packet
->dhcpv6_container_packet
;
2099 relay_options
= relay_packet
->options
;
2102 /* We wanted a specific relay but were unable to find it */
2103 if ((len
<= MAX_V6RELAY_HOPS
) && (i
!= 0)) {
2104 #if defined (DEBUG_EXPRESSIONS)
2105 log_debug("data: v6relay(%lu) = NULL", len
);
2110 s1
= evaluate_data_expression(&data
, relay_packet
, lease
,
2111 client_state
, relay_options
,
2113 expr
->data
.v6relay
.roption
,
2117 data_string_copy(result
, &data
, file
, line
);
2118 data_string_forget(&data
, MDL
);
2121 #if defined (DEBUG_EXPRESSIONS)
2122 log_debug("data: v6relay(%lu) = %s", len
,
2123 s1
? print_hex_3(result
->len
, result
->data
, 30)
2128 case expr_concat_dclist
: {
2129 /* Operands are compressed domain-name lists ("Dc" format)
2130 * Fetch both compressed lists then call concat_dclists which
2131 * combines them into a single compressed list. */
2132 memset(&data
, 0, sizeof data
);
2134 s0
= evaluate_data_expression(&data
, packet
, lease
,
2136 in_options
, cfg_options
, scope
,
2137 expr
->data
.concat
[0], MDL
);
2139 memset (&other
, 0, sizeof other
);
2140 s1
= evaluate_data_expression (&other
, packet
, lease
,
2142 in_options
, cfg_options
, scope
,
2143 expr
->data
.concat
[1], MDL
);
2146 outcome
= concat_dclists(result
, &data
, &other
);
2148 log_error ("data: concat_dclist failed");
2152 #if defined (DEBUG_EXPRESSIONS)
2153 log_debug ("data: concat_dclists (%s, %s) = %s",
2154 (s0
? print_hex_1(data
.len
, data
.data
, data
.len
)
2156 (s1
? print_hex_2(other
.len
, other
.data
, other
.len
)
2158 (((s0
&& s1
) && result
->len
> 0)
2159 ? print_hex_3 (result
->len
, result
->data
, result
->len
)
2163 data_string_forget (&data
, MDL
);
2166 data_string_forget (&other
, MDL
);
2169 } /* expr_concat_dclist */
2173 case expr_not_equal
:
2174 case expr_regex_match
:
2175 case expr_iregex_match
:
2184 case expr_variable_exists
:
2185 log_error ("Boolean opcode in evaluate_data_expression: %d",
2189 case expr_extract_int8
:
2190 case expr_extract_int16
:
2191 case expr_extract_int32
:
2192 case expr_const_int
:
2193 case expr_lease_time
:
2194 case expr_dns_transaction
:
2199 case expr_remainder
:
2200 case expr_binary_and
:
2201 case expr_binary_or
:
2202 case expr_binary_xor
:
2203 case expr_client_state
:
2204 log_error ("Numeric opcode in evaluate_data_expression: %d",
2209 case expr_ns_delete
:
2210 case expr_ns_exists
:
2211 case expr_ns_not_exists
:
2212 log_error ("dns opcode in evaluate_boolean_expression: %d",
2217 log_error ("function definition in evaluate_data_expression");
2225 log_error ("Bogus opcode in evaluate_data_expression: %d", expr
-> op
);
2229 int evaluate_numeric_expression (result
, packet
, lease
, client_state
,
2230 in_options
, cfg_options
, scope
, expr
)
2231 unsigned long *result
;
2232 struct packet
*packet
;
2233 struct lease
*lease
;
2234 struct client_state
*client_state
;
2235 struct option_state
*in_options
;
2236 struct option_state
*cfg_options
;
2237 struct binding_scope
**scope
;
2238 struct expression
*expr
;
2240 struct data_string data
;
2241 int status
, sleft
, sright
;
2243 struct binding
*binding
;
2244 struct binding_value
*bv
;
2245 unsigned long ileft
, iright
;
2248 switch (expr
-> op
) {
2251 case expr_not_equal
:
2252 case expr_regex_match
:
2253 case expr_iregex_match
:
2262 case expr_variable_exists
:
2263 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
2267 case expr_substring
:
2273 case expr_const_data
:
2276 case expr_encapsulate
:
2277 case expr_host_lookup
:
2278 case expr_encode_int8
:
2279 case expr_encode_int16
:
2280 case expr_encode_int32
:
2281 case expr_binary_to_ascii
:
2285 case expr_pick_first_value
:
2286 case expr_host_decl_name
:
2287 case expr_config_option
:
2288 case expr_leased_address
:
2290 case expr_gethostname
:
2292 log_error ("Data opcode in evaluate_numeric_expression: %d",
2296 case expr_extract_int8
:
2297 memset (&data
, 0, sizeof data
);
2298 status
= evaluate_data_expression
2299 (&data
, packet
, lease
, client_state
, in_options
,
2300 cfg_options
, scope
, expr
-> data
.extract_int
, MDL
);
2302 *result
= data
.data
[0];
2303 #if defined (DEBUG_EXPRESSIONS)
2304 log_debug ("num: extract_int8 (%s) = %s",
2305 status
? print_hex_1 (data
.len
, data
.data
, 60) : "NULL",
2306 status
? print_dec_1 (*result
) : "NULL" );
2308 if (status
) data_string_forget (&data
, MDL
);
2311 case expr_extract_int16
:
2312 memset(&data
, 0, sizeof(data
));
2313 status
= (evaluate_data_expression
2314 (&data
, packet
, lease
, client_state
, in_options
,
2315 cfg_options
, scope
, expr
->data
.extract_int
, MDL
));
2316 if (status
&& data
.len
>= 2) {
2317 *result
= getUShort(data
.data
);
2320 #if defined (DEBUG_EXPRESSIONS)
2322 log_debug("num: extract_int16 (%s) = %ld",
2323 print_hex_1(data
.len
, data
.data
, 60),
2326 log_debug("num: extract_int16 (NULL) = NULL");
2330 data_string_forget(&data
, MDL
);
2334 case expr_extract_int32
:
2335 memset (&data
, 0, sizeof data
);
2336 status
= (evaluate_data_expression
2337 (&data
, packet
, lease
, client_state
, in_options
,
2338 cfg_options
, scope
, expr
-> data
.extract_int
, MDL
));
2339 if (status
&& data
.len
>= 4) {
2340 *result
= getULong (data
.data
);
2343 #if defined (DEBUG_EXPRESSIONS)
2345 log_debug ("num: extract_int32 (%s) = %ld",
2346 print_hex_1 (data
.len
, data
.data
, 60),
2349 log_debug ("num: extract_int32 (NULL) = NULL");
2352 if (status
) data_string_forget (&data
, MDL
);
2355 case expr_const_int
:
2356 *result
= expr
-> data
.const_int
;
2357 #if defined (DEBUG_EXPRESSIONS)
2358 log_debug ("number: CONSTANT = %ld", *result
);
2362 case expr_lease_time
:
2364 log_error("data: leased_lease: not available");
2367 if (lease
->ends
< cur_time
) {
2368 log_error("%s %lu when it is now %lu",
2369 "data: lease_time: lease ends at",
2370 (long)(lease
->ends
), (long)cur_time
);
2373 *result
= lease
->ends
- cur_time
;
2374 #if defined (DEBUG_EXPRESSIONS)
2375 log_debug("number: lease-time = (%lu - %lu) = %ld",
2376 (long unsigned)lease
->ends
,
2377 (long unsigned)cur_time
, *result
);
2381 case expr_variable_reference
:
2382 if (scope
&& *scope
) {
2383 binding
= find_binding (*scope
, expr
-> data
.variable
);
2385 if (binding
&& binding
-> value
) {
2386 if (binding
-> value
-> type
== binding_numeric
) {
2387 *result
= binding
-> value
-> value
.intval
;
2390 log_error ("binding type %d in %s.",
2391 binding
-> value
-> type
,
2392 "evaluate_numeric_expression");
2399 #if defined (DEBUG_EXPRESSIONS)
2401 log_debug ("numeric: %s = %ld",
2402 expr
-> data
.variable
, *result
);
2404 log_debug ("numeric: %s = NULL",
2405 expr
-> data
.variable
);
2410 bv
= (struct binding_value
*)0;
2411 status
= evaluate_expression (&bv
, packet
, lease
,
2413 in_options
, cfg_options
,
2416 if (bv
-> type
!= binding_numeric
)
2417 log_error ("%s() returned type %d in %s.",
2418 expr
-> data
.funcall
.name
,
2420 "evaluate_numeric_expression");
2422 *result
= bv
-> value
.intval
;
2423 binding_value_dereference (&bv
, MDL
);
2425 #if defined (DEBUG_EXPRESSIONS)
2426 log_debug ("data: %s = %ld", expr
-> data
.funcall
.name
,
2427 status
? *result
: 0);
2432 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2434 in_options
, cfg_options
,
2436 expr
-> data
.and [0]);
2437 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2439 in_options
, cfg_options
,
2441 expr
-> data
.and [1]);
2443 #if defined (DEBUG_EXPRESSIONS)
2444 if (sleft
&& sright
)
2445 log_debug ("num: %ld + %ld = %ld",
2446 ileft
, iright
, ileft
+ iright
);
2448 log_debug ("num: %ld + NULL = NULL", ileft
);
2450 log_debug ("num: NULL + %ld = NULL", iright
);
2452 if (sleft
&& sright
) {
2453 *result
= ileft
+ iright
;
2459 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2461 in_options
, cfg_options
,
2463 expr
-> data
.and [0]);
2464 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2466 in_options
, cfg_options
,
2468 expr
-> data
.and [1]);
2470 #if defined (DEBUG_EXPRESSIONS)
2471 if (sleft
&& sright
)
2472 log_debug ("num: %ld - %ld = %ld",
2473 ileft
, iright
, ileft
- iright
);
2475 log_debug ("num: %ld - NULL = NULL", ileft
);
2477 log_debug ("num: NULL - %ld = NULL", iright
);
2479 if (sleft
&& sright
) {
2480 *result
= ileft
- iright
;
2486 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2488 in_options
, cfg_options
,
2490 expr
-> data
.and [0]);
2491 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2493 in_options
, cfg_options
,
2495 expr
-> data
.and [1]);
2497 #if defined (DEBUG_EXPRESSIONS)
2498 if (sleft
&& sright
)
2499 log_debug ("num: %ld * %ld = %ld",
2500 ileft
, iright
, ileft
* iright
);
2502 log_debug ("num: %ld * NULL = NULL", ileft
);
2504 log_debug ("num: NULL * %ld = NULL", iright
);
2506 if (sleft
&& sright
) {
2507 *result
= ileft
* iright
;
2513 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2515 in_options
, cfg_options
,
2517 expr
-> data
.and [0]);
2518 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2520 in_options
, cfg_options
,
2522 expr
-> data
.and [1]);
2524 #if defined (DEBUG_EXPRESSIONS)
2525 if (sleft
&& sright
) {
2527 log_debug ("num: %ld / %ld = %ld",
2528 ileft
, iright
, ileft
/ iright
);
2530 log_debug ("num: %ld / %ld = NULL",
2533 log_debug ("num: %ld / NULL = NULL", ileft
);
2535 log_debug ("num: NULL / %ld = NULL", iright
);
2537 if (sleft
&& sright
&& iright
) {
2538 *result
= ileft
/ iright
;
2543 case expr_remainder
:
2544 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2546 in_options
, cfg_options
,
2548 expr
-> data
.and [0]);
2549 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2551 in_options
, cfg_options
,
2553 expr
-> data
.and [1]);
2555 #if defined (DEBUG_EXPRESSIONS)
2556 if (sleft
&& sright
) {
2558 log_debug ("num: %ld %% %ld = %ld",
2559 ileft
, iright
, ileft
% iright
);
2561 log_debug ("num: %ld %% %ld = NULL",
2564 log_debug ("num: %ld %% NULL = NULL", ileft
);
2566 log_debug ("num: NULL %% %ld = NULL", iright
);
2568 if (sleft
&& sright
&& iright
) {
2569 *result
= ileft
% iright
;
2574 case expr_binary_and
:
2575 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2577 in_options
, cfg_options
,
2579 expr
-> data
.and [0]);
2580 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2582 in_options
, cfg_options
,
2584 expr
-> data
.and [1]);
2586 #if defined (DEBUG_EXPRESSIONS)
2587 if (sleft
&& sright
)
2588 log_debug ("num: %ld | %ld = %ld",
2589 ileft
, iright
, ileft
& iright
);
2591 log_debug ("num: %ld & NULL = NULL", ileft
);
2593 log_debug ("num: NULL & %ld = NULL", iright
);
2595 if (sleft
&& sright
) {
2596 *result
= ileft
& iright
;
2601 case expr_binary_or
:
2602 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2604 in_options
, cfg_options
,
2606 expr
-> data
.and [0]);
2607 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2609 in_options
, cfg_options
,
2611 expr
-> data
.and [1]);
2613 #if defined (DEBUG_EXPRESSIONS)
2614 if (sleft
&& sright
)
2615 log_debug ("num: %ld | %ld = %ld",
2616 ileft
, iright
, ileft
| iright
);
2618 log_debug ("num: %ld | NULL = NULL", ileft
);
2620 log_debug ("num: NULL | %ld = NULL", iright
);
2622 if (sleft
&& sright
) {
2623 *result
= ileft
| iright
;
2628 case expr_binary_xor
:
2629 sleft
= evaluate_numeric_expression (&ileft
, packet
, lease
,
2631 in_options
, cfg_options
,
2633 expr
-> data
.and [0]);
2634 sright
= evaluate_numeric_expression (&iright
, packet
, lease
,
2636 in_options
, cfg_options
,
2638 expr
-> data
.and [1]);
2640 #if defined (DEBUG_EXPRESSIONS)
2641 if (sleft
&& sright
)
2642 log_debug ("num: %ld ^ %ld = %ld",
2643 ileft
, iright
, ileft
^ iright
);
2645 log_debug ("num: %ld ^ NULL = NULL", ileft
);
2647 log_debug ("num: NULL ^ %ld = NULL", iright
);
2649 if (sleft
&& sright
) {
2650 *result
= ileft
^ iright
;
2655 case expr_client_state
:
2657 #if defined (DEBUG_EXPRESSIONS)
2658 log_debug ("num: client-state = %d",
2659 client_state
-> state
);
2661 *result
= client_state
-> state
;
2664 #if defined (DEBUG_EXPRESSIONS)
2665 log_debug ("num: client-state = NULL");
2671 log_error ("function definition in evaluate_numeric_expr");
2678 log_fatal("Impossible case at %s:%d. Undefined operator "
2679 "%d.", MDL
, expr
->op
);
2683 log_error ("evaluate_numeric_expression: bogus opcode %d", expr
-> op
);
2688 * Return data hanging off of an option cache structure, or if there
2689 * isn't any, evaluate the expression hanging off of it and return the
2690 * result of that evaluation. There should never be both an expression
2691 * and a valid data_string.
2693 * returns 0 if there wasn't an expression or it couldn't be evaluated
2694 * returns non-zero if there was an expression or string that was evaluated
2695 * When it returns zero the arguements, in particualr resutl, should not
2699 int evaluate_option_cache (result
, packet
, lease
, client_state
,
2700 in_options
, cfg_options
, scope
, oc
, file
, line
)
2701 struct data_string
*result
;
2702 struct packet
*packet
;
2703 struct lease
*lease
;
2704 struct client_state
*client_state
;
2705 struct option_state
*in_options
;
2706 struct option_state
*cfg_options
;
2707 struct binding_scope
**scope
;
2708 struct option_cache
*oc
;
2712 if (oc
->data
.data
!= NULL
) {
2713 data_string_copy (result
, &oc
-> data
, file
, line
);
2716 if (!oc
-> expression
)
2718 return evaluate_data_expression (result
, packet
, lease
, client_state
,
2719 in_options
, cfg_options
, scope
,
2720 oc
-> expression
, file
, line
);
2723 /* Evaluate an option cache and extract a boolean from the result.
2724 * The boolean option cache is actually a trinary value where:
2726 * 0 = return 0, ignore parameter 0 (also the case for no data)
2727 * 1 = return 1, ignore parameter 0
2728 * 2 = return 0, ignore parameter 1
2730 * This supports both classic boolean flags on/off as well as the
2731 * allow/deny/ignore keywords
2733 int evaluate_boolean_option_cache (ignorep
, packet
,
2734 lease
, client_state
, in_options
,
2735 cfg_options
, scope
, oc
, file
, line
)
2737 struct packet
*packet
;
2738 struct lease
*lease
;
2739 struct client_state
*client_state
;
2740 struct option_state
*in_options
;
2741 struct option_state
*cfg_options
;
2742 struct binding_scope
**scope
;
2743 struct option_cache
*oc
;
2751 /* Only attempt to evaluate if option_cache is not null. This permits
2752 * us to be called with option_lookup() as an argument. */
2753 if (oc
&& in_options
) {
2754 struct data_string ds
;
2756 memset(&ds
, 0, sizeof ds
);
2757 if (evaluate_option_cache(&ds
, packet
,
2758 lease
, client_state
, in_options
,
2759 cfg_options
, scope
, oc
, file
,
2761 /* We have a value for the option set result and
2762 * ignore parameter accordingly. */
2764 if (ds
.data
[0] == 1)
2766 else if ((ds
.data
[0] == 2) && (ignorep
!= NULL
))
2770 data_string_forget(&ds
, MDL
);
2777 /* Evaluate a boolean expression and return the result of the evaluation,
2778 or FALSE if it failed. */
2780 int evaluate_boolean_expression_result (ignorep
, packet
, lease
, client_state
,
2781 in_options
, cfg_options
, scope
, expr
)
2783 struct packet
*packet
;
2784 struct lease
*lease
;
2785 struct client_state
*client_state
;
2786 struct option_state
*in_options
;
2787 struct option_state
*cfg_options
;
2788 struct binding_scope
**scope
;
2789 struct expression
*expr
;
2793 /* So that we can be called with option_lookup as an argument. */
2797 if (!evaluate_boolean_expression (&result
, packet
, lease
, client_state
,
2798 in_options
, cfg_options
,
2811 /* Dereference an expression node, and if the reference count goes to zero,
2812 dereference any data it refers to, and then free it. */
2813 void expression_dereference (eptr
, file
, line
)
2814 struct expression
**eptr
;
2818 struct expression
*expr
= *eptr
;
2820 /* Zero the pointer. */
2821 *eptr
= (struct expression
*)0;
2823 /* Decrement the reference count. If it's nonzero, we're
2826 rc_register (file
, line
, eptr
, expr
, expr
-> refcnt
, 1, RC_MISC
);
2827 if (expr
-> refcnt
> 0)
2829 if (expr
-> refcnt
< 0) {
2830 log_error ("%s(%d): negative refcnt!", file
, line
);
2831 #if defined (DEBUG_RC_HISTORY)
2832 dump_rc_history (expr
);
2834 #if defined (POINTER_DEBUG)
2841 /* Dereference subexpressions. */
2842 switch (expr
-> op
) {
2843 /* All the binary operators can be handled the same way. */
2845 case expr_not_equal
:
2846 case expr_regex_match
:
2847 case expr_iregex_match
:
2855 case expr_remainder
:
2856 case expr_binary_and
:
2857 case expr_binary_or
:
2858 case expr_binary_xor
:
2859 case expr_client_state
:
2860 if (expr
-> data
.equal
[0])
2861 expression_dereference (&expr
-> data
.equal
[0],
2863 if (expr
-> data
.equal
[1])
2864 expression_dereference (&expr
-> data
.equal
[1],
2868 case expr_substring
:
2869 if (expr
-> data
.substring
.expr
)
2870 expression_dereference (&expr
-> data
.substring
.expr
,
2872 if (expr
-> data
.substring
.offset
)
2873 expression_dereference (&expr
-> data
.substring
.offset
,
2875 if (expr
-> data
.substring
.len
)
2876 expression_dereference (&expr
-> data
.substring
.len
,
2881 if (expr
-> data
.suffix
.expr
)
2882 expression_dereference (&expr
-> data
.suffix
.expr
,
2884 if (expr
-> data
.suffix
.len
)
2885 expression_dereference (&expr
-> data
.suffix
.len
,
2890 if (expr
->data
.lcase
)
2891 expression_dereference(&expr
->data
.lcase
, MDL
);
2895 if (expr
->data
.ucase
)
2896 expression_dereference(&expr
->data
.ucase
, MDL
);
2900 if (expr
-> data
.not)
2901 expression_dereference (&expr
-> data
.not, file
, line
);
2905 if (expr
-> data
.packet
.offset
)
2906 expression_dereference (&expr
-> data
.packet
.offset
,
2908 if (expr
-> data
.packet
.len
)
2909 expression_dereference (&expr
-> data
.packet
.len
,
2913 case expr_extract_int8
:
2914 case expr_extract_int16
:
2915 case expr_extract_int32
:
2916 if (expr
-> data
.extract_int
)
2917 expression_dereference (&expr
-> data
.extract_int
,
2921 case expr_encode_int8
:
2922 case expr_encode_int16
:
2923 case expr_encode_int32
:
2924 if (expr
-> data
.encode_int
)
2925 expression_dereference (&expr
-> data
.encode_int
,
2929 case expr_encapsulate
:
2930 case expr_const_data
:
2931 data_string_forget (&expr
-> data
.const_data
, file
, line
);
2934 case expr_host_lookup
:
2935 if (expr
-> data
.host_lookup
)
2936 dns_host_entry_dereference (&expr
-> data
.host_lookup
,
2940 case expr_binary_to_ascii
:
2941 if (expr
-> data
.b2a
.base
)
2942 expression_dereference (&expr
-> data
.b2a
.base
,
2944 if (expr
-> data
.b2a
.width
)
2945 expression_dereference (&expr
-> data
.b2a
.width
,
2947 if (expr
-> data
.b2a
.separator
)
2948 expression_dereference (&expr
-> data
.b2a
.separator
,
2950 if (expr
-> data
.b2a
.buffer
)
2951 expression_dereference (&expr
-> data
.b2a
.buffer
,
2955 case expr_pick_first_value
:
2956 if (expr
-> data
.pick_first_value
.car
)
2957 expression_dereference (&expr
-> data
.pick_first_value
.car
,
2959 if (expr
-> data
.pick_first_value
.cdr
)
2960 expression_dereference (&expr
-> data
.pick_first_value
.cdr
,
2965 if (expr
-> data
.reverse
.width
)
2966 expression_dereference (&expr
-> data
.reverse
.width
,
2968 if (expr
-> data
.reverse
.buffer
)
2969 expression_dereference
2970 (&expr
-> data
.reverse
.buffer
, file
, line
);
2973 case expr_variable_reference
:
2974 case expr_variable_exists
:
2975 if (expr
-> data
.variable
)
2976 dfree (expr
-> data
.variable
, file
, line
);
2980 if (expr
-> data
.funcall
.name
)
2981 dfree (expr
-> data
.funcall
.name
, file
, line
);
2982 if (expr
-> data
.funcall
.arglist
)
2983 expression_dereference (&expr
-> data
.funcall
.arglist
,
2988 if (expr
-> data
.arg
.val
)
2989 expression_dereference (&expr
-> data
.arg
.val
,
2991 if (expr
-> data
.arg
.next
)
2992 expression_dereference (&expr
-> data
.arg
.next
,
2997 fundef_dereference (&expr
-> data
.func
, file
, line
);
3001 if (expr
->data
.v6relay
.relay
)
3002 expression_dereference(&expr
->data
.v6relay
.relay
,
3005 if (expr
->data
.v6relay
.roption
)
3006 expression_dereference(&expr
->data
.v6relay
.roption
,
3010 /* No subexpressions. */
3011 case expr_leased_address
:
3012 case expr_lease_time
:
3015 case expr_const_int
:
3022 case expr_gethostname
:
3028 free_expression (expr
, MDL
);
3031 int is_boolean_expression (expr
)
3032 struct expression
*expr
;
3034 return (expr
-> op
== expr_check
||
3035 expr
-> op
== expr_exists
||
3036 expr
-> op
== expr_variable_exists
||
3037 expr
-> op
== expr_equal
||
3038 expr
-> op
== expr_not_equal
||
3039 expr
->op
== expr_regex_match
||
3040 expr
->op
== expr_iregex_match
||
3041 expr
-> op
== expr_and
||
3042 expr
-> op
== expr_or
||
3043 expr
-> op
== expr_not
||
3044 expr
-> op
== expr_known
||
3045 expr
-> op
== expr_static
);
3048 int is_data_expression (expr
)
3049 struct expression
*expr
;
3051 return (expr
->op
== expr_substring
||
3052 expr
->op
== expr_suffix
||
3053 expr
->op
== expr_lcase
||
3054 expr
->op
== expr_ucase
||
3055 expr
->op
== expr_option
||
3056 expr
->op
== expr_hardware
||
3057 expr
->op
== expr_const_data
||
3058 expr
->op
== expr_packet
||
3059 expr
->op
== expr_concat
||
3060 expr
->op
== expr_encapsulate
||
3061 expr
->op
== expr_encode_int8
||
3062 expr
->op
== expr_encode_int16
||
3063 expr
->op
== expr_encode_int32
||
3064 expr
->op
== expr_host_lookup
||
3065 expr
->op
== expr_binary_to_ascii
||
3066 expr
->op
== expr_filename
||
3067 expr
->op
== expr_sname
||
3068 expr
->op
== expr_reverse
||
3069 expr
->op
== expr_pick_first_value
||
3070 expr
->op
== expr_host_decl_name
||
3071 expr
->op
== expr_leased_address
||
3072 expr
->op
== expr_config_option
||
3073 expr
->op
== expr_null
||
3074 expr
->op
== expr_gethostname
||
3075 expr
->op
== expr_v6relay
);
3078 int is_numeric_expression (expr
)
3079 struct expression
*expr
;
3081 return (expr
-> op
== expr_extract_int8
||
3082 expr
-> op
== expr_extract_int16
||
3083 expr
-> op
== expr_extract_int32
||
3084 expr
-> op
== expr_const_int
||
3085 expr
-> op
== expr_lease_time
||
3086 expr
-> op
== expr_add
||
3087 expr
-> op
== expr_subtract
||
3088 expr
-> op
== expr_multiply
||
3089 expr
-> op
== expr_divide
||
3090 expr
-> op
== expr_remainder
||
3091 expr
-> op
== expr_binary_and
||
3092 expr
-> op
== expr_binary_or
||
3093 expr
-> op
== expr_binary_xor
||
3094 expr
-> op
== expr_client_state
);
3097 int is_compound_expression (expr
)
3098 struct expression
*expr
;
3100 return (expr
-> op
== expr_substring
||
3101 expr
-> op
== expr_suffix
||
3102 expr
-> op
== expr_option
||
3103 expr
-> op
== expr_concat
||
3104 expr
-> op
== expr_encode_int8
||
3105 expr
-> op
== expr_encode_int16
||
3106 expr
-> op
== expr_encode_int32
||
3107 expr
-> op
== expr_binary_to_ascii
||
3108 expr
-> op
== expr_reverse
||
3109 expr
-> op
== expr_pick_first_value
||
3110 expr
-> op
== expr_config_option
||
3111 expr
-> op
== expr_extract_int8
||
3112 expr
-> op
== expr_extract_int16
||
3113 expr
-> op
== expr_extract_int32
||
3114 expr
-> op
== expr_v6relay
);
3117 static int op_val (enum expr_op
);
3119 static int op_val (op
)
3127 case expr_substring
:
3132 case expr_encapsulate
:
3133 case expr_host_lookup
:
3138 case expr_const_data
:
3139 case expr_extract_int8
:
3140 case expr_extract_int16
:
3141 case expr_extract_int32
:
3142 case expr_encode_int8
:
3143 case expr_encode_int16
:
3144 case expr_encode_int32
:
3145 case expr_const_int
:
3147 case expr_variable_exists
:
3149 case expr_binary_to_ascii
:
3153 case expr_pick_first_value
:
3154 case expr_host_decl_name
:
3155 case expr_config_option
:
3156 case expr_leased_address
:
3157 case expr_lease_time
:
3158 case expr_dns_transaction
:
3160 case expr_variable_reference
:
3162 case expr_ns_delete
:
3163 case expr_ns_exists
:
3164 case expr_ns_not_exists
:
3168 /* XXXDPN: Need to assign sane precedences to these. */
3169 case expr_binary_and
:
3170 case expr_binary_or
:
3171 case expr_binary_xor
:
3172 case expr_client_state
:
3173 case expr_gethostname
:
3175 case expr_concat_dclist
:
3179 case expr_not_equal
:
3180 case expr_regex_match
:
3181 case expr_iregex_match
:
3194 case expr_remainder
:
3200 int op_precedence (op1
, op2
)
3201 enum expr_op op1
, op2
;
3203 return op_val (op1
) - op_val (op2
);
3206 enum expression_context
expression_context (struct expression
*expr
)
3208 if (is_data_expression (expr
))
3209 return context_data
;
3210 if (is_numeric_expression (expr
))
3211 return context_numeric
;
3212 if (is_boolean_expression (expr
))
3213 return context_boolean
;
3217 enum expression_context
op_context (op
)
3221 /* XXX Why aren't these specific? */
3226 case expr_substring
:
3231 case expr_encapsulate
:
3232 case expr_host_lookup
:
3237 case expr_const_data
:
3238 case expr_extract_int8
:
3239 case expr_extract_int16
:
3240 case expr_extract_int32
:
3241 case expr_encode_int8
:
3242 case expr_encode_int16
:
3243 case expr_encode_int32
:
3244 case expr_const_int
:
3246 case expr_variable_exists
:
3248 case expr_binary_to_ascii
:
3252 case expr_pick_first_value
:
3253 case expr_host_decl_name
:
3254 case expr_config_option
:
3255 case expr_leased_address
:
3256 case expr_lease_time
:
3258 case expr_variable_reference
:
3260 case expr_ns_delete
:
3261 case expr_ns_exists
:
3262 case expr_ns_not_exists
:
3263 case expr_dns_transaction
:
3267 case expr_gethostname
:
3269 case expr_concat_dclist
:
3273 case expr_not_equal
:
3274 case expr_regex_match
:
3275 case expr_iregex_match
:
3276 return context_data
;
3279 return context_boolean
;
3282 return context_boolean
;
3288 case expr_remainder
:
3289 case expr_binary_and
:
3290 case expr_binary_or
:
3291 case expr_binary_xor
:
3292 case expr_client_state
:
3293 return context_numeric
;
3298 int write_expression (file
, expr
, col
, indent
, firstp
)
3300 struct expression
*expr
;
3305 struct expression
*e
;
3311 /* If this promises to be a fat expression, start a new line. */
3312 if (!firstp
&& is_compound_expression (expr
)) {
3313 indent_spaces (file
, indent
);
3317 switch (expr
-> op
) {
3319 col
= token_print_indent (file
, col
, indent
, "", "", "null");
3323 col
= token_print_indent (file
, col
, indent
, "", "", "check");
3324 col
= token_print_indent_concat (file
, col
, indent
,
3326 expr
-> data
.check
-> name
,
3330 case expr_regex_match
:
3334 case expr_iregex_match
:
3338 case expr_not_equal
:
3345 col
= write_expression (file
, expr
-> data
.equal
[0],
3347 col
= token_print_indent (file
, col
, indent
, " ", " ", s
);
3348 col
= write_expression (file
, expr
-> data
.equal
[1],
3349 col
, indent
+ 2, 0);
3352 case expr_substring
:
3353 col
= token_print_indent (file
, col
, indent
, "", "",
3355 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3357 col
= write_expression (file
, expr
-> data
.substring
.expr
,
3359 col
= token_print_indent (file
, col
, indent
, "", " ", ",");
3360 col
= write_expression (file
, expr
-> data
.substring
.offset
,
3362 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3363 col
= write_expression (file
, expr
-> data
.substring
.len
,
3365 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3369 col
= token_print_indent (file
, col
, indent
, "", "", "suffix");
3370 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3372 col
= write_expression (file
, expr
-> data
.suffix
.expr
,
3374 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3375 col
= write_expression (file
, expr
-> data
.suffix
.len
,
3377 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3381 col
= token_print_indent(file
, col
, indent
, "", "", "lcase");
3382 col
= token_print_indent(file
, col
, indent
, " ", "", "(");
3384 col
= write_expression(file
, expr
->data
.lcase
, col
, scol
, 1);
3385 col
= token_print_indent(file
, col
, indent
, "", "", ")");
3389 col
= token_print_indent(file
, col
, indent
, "", "", "ucase");
3390 col
= token_print_indent(file
, col
, indent
, " ", "", "(");
3392 col
= write_expression(file
, expr
->data
.ucase
, col
, scol
, 1);
3393 col
= token_print_indent(file
, col
, indent
, "", "", ")");
3398 col
= token_print_indent (file
, col
, indent
, "", "",
3400 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3404 col
= write_expression (file
, e
-> data
.concat
[0],
3407 if (!e
-> data
.concat
[1])
3409 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3410 if (e
-> data
.concat
[1] -> op
== expr_concat
) {
3411 e
= e
-> data
.concat
[1];
3414 col
= write_expression (file
, e
-> data
.concat
[1],
3417 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3420 case expr_host_lookup
:
3421 col
= token_print_indent (file
, col
, indent
, "", "",
3423 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3424 col
= token_print_indent_concat
3425 (file
, col
, indent
, "", "",
3426 "\"", expr
-> data
.host_lookup
-> hostname
, "\"",
3428 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3447 case expr_remainder
:
3451 case expr_binary_and
:
3455 case expr_binary_or
:
3459 case expr_binary_xor
:
3472 col
= token_print_indent (file
, col
, indent
, "", " ", "not");
3473 col
= write_expression (file
,
3474 expr
-> data
.not, col
, indent
+ 2, 1);
3481 col
= token_print_indent (file
, col
, indent
, "", "", s
);
3483 if (expr
-> data
.option
-> universe
!= &dhcp_universe
) {
3484 col
= token_print_indent (file
, col
, indent
,
3486 (expr
-> data
.option
->
3488 col
= token_print_indent (file
, col
, indent
, "", "",
3490 col
= token_print_indent (file
, col
, indent
, "", "",
3491 expr
-> data
.option
-> name
);
3493 col
= token_print_indent (file
, col
, indent
, " ", "",
3494 expr
-> data
.option
-> name
);
3499 col
= token_print_indent (file
, col
, indent
, "", "",
3504 col
= token_print_indent (file
, col
, indent
, "", "",
3506 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3508 col
= write_expression (file
, expr
-> data
.packet
.offset
,
3510 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3511 col
= write_expression (file
, expr
-> data
.packet
.len
,
3513 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3516 case expr_const_data
:
3517 col
= token_indent_data_string (file
, col
, indent
, "", "",
3518 &expr
-> data
.const_data
);
3521 case expr_extract_int8
:
3524 col
= token_print_indent (file
, col
, indent
, "", "",
3526 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3528 col
= write_expression (file
, expr
-> data
.extract_int
,
3530 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3531 sprintf (obuf
, "%d", width
);
3532 col
= token_print_indent (file
, col
, scol
, " ", "", obuf
);
3533 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3536 case expr_extract_int16
:
3540 case expr_extract_int32
:
3544 case expr_encode_int8
:
3547 col
= token_print_indent (file
, col
, indent
, "", "",
3549 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3551 col
= write_expression (file
, expr
-> data
.extract_int
,
3553 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3554 sprintf (obuf
, "%d", width
);
3555 col
= token_print_indent (file
, col
, scol
, " ", "", obuf
);
3556 col
= token_print_indent (file
, col
, indent
, "", "",
3560 case expr_encode_int16
:
3564 case expr_encode_int32
:
3568 case expr_const_int
:
3569 sprintf (obuf
, "%lu", expr
-> data
.const_int
);
3570 col
= token_print_indent (file
, col
, indent
, "", "", obuf
);
3575 goto print_option_name
;
3577 case expr_encapsulate
:
3578 col
= token_print_indent (file
, col
, indent
, "", "",
3580 col
= token_indent_data_string (file
, col
, indent
, " ", "",
3581 &expr
-> data
.encapsulate
);
3585 col
= token_print_indent (file
, col
, indent
, "", "", "known");
3589 col
= token_print_indent (file
, col
, indent
, "", "",
3591 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3593 col
= write_expression (file
, expr
-> data
.reverse
.width
,
3595 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3596 col
= write_expression (file
, expr
-> data
.reverse
.buffer
,
3598 col
= token_print_indent (file
, col
, indent
, "", "",
3602 case expr_leased_address
:
3603 col
= token_print_indent (file
, col
, indent
, "", "",
3607 case expr_client_state
:
3608 col
= token_print_indent (file
, col
, indent
, "", "",
3612 case expr_binary_to_ascii
:
3613 col
= token_print_indent (file
, col
, indent
, "", "",
3615 col
= token_print_indent (file
, col
, indent
, " ", "",
3618 col
= write_expression (file
, expr
-> data
.b2a
.base
,
3620 col
= token_print_indent (file
, col
, scol
, "", " ",
3622 col
= write_expression (file
, expr
-> data
.b2a
.width
,
3624 col
= token_print_indent (file
, col
, scol
, "", " ",
3626 col
= write_expression (file
, expr
-> data
.b2a
.separator
,
3628 col
= token_print_indent (file
, col
, scol
, "", " ",
3630 col
= write_expression (file
, expr
-> data
.b2a
.buffer
,
3632 col
= token_print_indent (file
, col
, indent
, "", "",
3636 case expr_config_option
:
3637 s
= "config-option";
3638 goto print_option_name
;
3640 case expr_host_decl_name
:
3641 col
= token_print_indent (file
, col
, indent
, "", "",
3645 case expr_pick_first_value
:
3647 col
= token_print_indent (file
, col
, indent
, "", "",
3648 "pick-first-value");
3649 col
= token_print_indent (file
, col
, indent
, " ", "",
3654 col
= write_expression (file
,
3655 e
-> data
.pick_first_value
.car
,
3658 /* We're being very lisp-like right now - instead of
3659 representing this expression as (first middle . last) we're
3660 representing it as (first middle last), which means that the
3661 tail cdr is always nil. Apologies to non-wisp-lizards - may
3662 this obscure way of describing the problem motivate you to
3663 learn more about the one true computing language. */
3664 if (!e
-> data
.pick_first_value
.cdr
)
3666 col
= token_print_indent (file
, col
, scol
, "", " ",
3668 if (e
-> data
.pick_first_value
.cdr
-> op
==
3669 expr_pick_first_value
) {
3670 e
= e
-> data
.pick_first_value
.cdr
;
3673 col
= write_expression (file
,
3674 e
-> data
.pick_first_value
.cdr
,
3677 col
= token_print_indent (file
, col
, indent
, "", "",
3681 case expr_lease_time
:
3682 col
= token_print_indent (file
, col
, indent
, "", "",
3687 col
= token_print_indent (file
, col
, indent
, "", "",
3692 col
= token_print_indent (file
, col
, indent
, "", "", "null");
3695 case expr_variable_reference
:
3696 col
= token_print_indent (file
, indent
, indent
, "", "",
3697 expr
-> data
.variable
);
3700 case expr_variable_exists
:
3701 col
= token_print_indent (file
, indent
, indent
, "", "",
3703 col
= token_print_indent (file
, col
, indent
, " ", "", "(");
3704 col
= token_print_indent (file
, col
, indent
, "", "",
3705 expr
-> data
.variable
);
3706 col
= token_print_indent (file
, col
, indent
, "", "", ")");
3709 case expr_gethostname
:
3710 col
= token_print_indent(file
, col
, indent
, "", "",
3715 col
= token_print_indent(file
, indent
, indent
, "", "",
3716 expr
->data
.funcall
.name
);
3717 col
= token_print_indent(file
, col
, indent
, " ", "", "(");
3720 e
= expr
->data
.funcall
.arglist
;
3723 col
= token_print_indent(file
, col
, indent
,
3726 col
= write_expression(file
, e
->data
.arg
.val
, col
,
3729 e
= e
->data
.arg
.next
;
3732 col
= token_print_indent(file
, col
, indent
, "", "", ")");
3736 col
= token_print_indent(file
, col
, indent
, "", "",
3738 col
= token_print_indent(file
, col
, indent
, " ", "", "(");
3740 col
= write_expression(file
, expr
->data
.v6relay
.relay
,
3742 col
= token_print_indent (file
, col
, scol
, "", " ", ",");
3743 col
= write_expression(file
, expr
->data
.v6relay
.roption
,
3745 col
= token_print_indent(file
, col
, indent
, "", "", ")");
3749 log_fatal ("invalid expression type in print_expression: %d",
3755 struct binding
*find_binding (struct binding_scope
*scope
, const char *name
)
3758 struct binding_scope
*s
;
3760 for (s
= scope
; s
; s
= s
-> outer
) {
3761 for (bp
= s
-> bindings
; bp
; bp
= bp
-> next
) {
3762 if (!strcasecmp (name
, bp
-> name
)) {
3767 return (struct binding
*)0;
3770 int free_bindings (struct binding_scope
*scope
, const char *file
, int line
)
3772 struct binding
*bp
, *next
;
3774 for (bp
= scope
-> bindings
; bp
; bp
= next
) {
3777 dfree (bp
-> name
, file
, line
);
3779 binding_value_dereference (&bp
-> value
, file
, line
);
3780 dfree (bp
, file
, line
);
3782 scope
-> bindings
= (struct binding
*)0;
3786 int binding_scope_dereference (ptr
, file
, line
)
3787 struct binding_scope
**ptr
;
3791 struct binding_scope
*binding_scope
;
3793 if (!ptr
|| !*ptr
) {
3794 log_error ("%s(%d): null pointer", file
, line
);
3795 #if defined (POINTER_DEBUG)
3802 binding_scope
= *ptr
;
3803 *ptr
= (struct binding_scope
*)0;
3804 --binding_scope
-> refcnt
;
3805 rc_register (file
, line
, ptr
,
3806 binding_scope
, binding_scope
-> refcnt
, 1, RC_MISC
);
3807 if (binding_scope
-> refcnt
> 0)
3810 if (binding_scope
-> refcnt
< 0) {
3811 log_error ("%s(%d): negative refcnt!", file
, line
);
3812 #if defined (DEBUG_RC_HISTORY)
3813 dump_rc_history (binding_scope
);
3815 #if defined (POINTER_DEBUG)
3822 free_bindings (binding_scope
, file
, line
);
3823 if (binding_scope
-> outer
)
3824 binding_scope_dereference (&binding_scope
-> outer
, MDL
);
3825 dfree (binding_scope
, file
, line
);
3829 int fundef_dereference (ptr
, file
, line
)
3830 struct fundef
**ptr
;
3835 struct string_list
*sp
, *next
;
3837 if ((ptr
== NULL
) || (*ptr
== NULL
)) {
3838 log_error ("%s(%d): null pointer", file
, line
);
3839 #if defined (POINTER_DEBUG)
3848 rc_register (file
, line
, ptr
, bp
, bp
-> refcnt
, 1, RC_MISC
);
3849 if (bp
-> refcnt
< 0) {
3850 log_error ("%s(%d): negative refcnt!", file
, line
);
3851 #if defined (DEBUG_RC_HISTORY)
3852 dump_rc_history (bp
);
3854 #if defined (POINTER_DEBUG)
3860 if (!bp
-> refcnt
) {
3861 for (sp
= bp
-> args
; sp
; sp
= next
) {
3863 dfree (sp
, file
, line
);
3865 if (bp
-> statements
)
3866 executable_statement_dereference (&bp
-> statements
,
3868 dfree (bp
, file
, line
);
3870 *ptr
= (struct fundef
*)0;
3874 #if defined (NOTYET) /* Post 3.0 final. */
3875 int data_subexpression_length (int *rv
,
3876 struct expression
*expr
)
3878 int crhs
, clhs
, llhs
, lrhs
;
3879 switch (expr
-> op
) {
3880 case expr_substring
:
3881 if (expr
-> data
.substring
.len
&&
3882 expr
-> data
.substring
.len
-> op
== expr_const_int
) {
3884 (int)expr
-> data
.substring
.len
-> data
.const_int
);
3891 if (expr
-> data
.suffix
.len
&&
3892 expr
-> data
.suffix
.len
-> op
== expr_const_int
) {
3894 (int)expr
-> data
.suffix
.len
-> data
.const_int
);
3900 return data_subexpression_length(rv
, expr
->data
.lcase
);
3903 return data_subexpression_length(rv
, expr
->data
.ucase
);
3906 clhs
= data_subexpression_length (&llhs
,
3907 expr
-> data
.concat
[0]);
3908 crhs
= data_subexpression_length (&lrhs
,
3909 expr
-> data
.concat
[1]);
3910 if (crhs
== 0 || clhs
== 0)
3919 case expr_const_data
:
3920 *rv
= expr
-> data
.const_data
.len
;
3924 return data_subexpression_length (rv
,
3925 expr
-> data
.reverse
.buffer
);
3927 case expr_leased_address
:
3928 case expr_lease_time
:
3932 case expr_pick_first_value
:
3933 clhs
= data_subexpression_length (&llhs
,
3934 expr
-> data
.concat
[0]);
3935 crhs
= data_subexpression_length (&lrhs
,
3936 expr
-> data
.concat
[1]);
3937 if (crhs
== 0 || clhs
== 0)
3946 clhs
= data_subexpression_length (&llhs
,
3947 expr
-> data
.v6relay
.relay
);
3948 crhs
= data_subexpression_length (&lrhs
,
3949 expr
-> data
.v6relay
.roption
);
3950 if (crhs
== 0 || clhs
== 0)
3956 case expr_binary_to_ascii
:
3957 case expr_config_option
:
3958 case expr_host_decl_name
:
3959 case expr_encapsulate
:
3962 case expr_host_lookup
:
3968 case expr_regex_match
:
3969 case expr_iregex_match
:
3973 case expr_extract_int8
:
3974 case expr_extract_int16
:
3975 case expr_extract_int32
:
3976 case expr_encode_int8
:
3977 case expr_encode_int16
:
3978 case expr_encode_int32
:
3979 case expr_const_int
:
3983 case expr_not_equal
:
3985 case expr_variable_exists
:
3986 case expr_variable_reference
:
3994 case expr_remainder
:
3995 case expr_binary_and
:
3996 case expr_binary_or
:
3997 case expr_binary_xor
:
3998 case expr_client_state
:
3999 case expr_gethostname
:
4005 int expr_valid_for_context (struct expression
*expr
,
4006 enum expression_context context
)
4008 /* We don't know at parse time what type of value a function may
4009 return, so we can't flag an error on it. */
4010 if (expr
-> op
== expr_funcall
||
4011 expr
-> op
== expr_variable_reference
)
4018 case context_boolean
:
4019 if (is_boolean_expression (expr
))
4024 if (is_data_expression (expr
))
4028 case context_numeric
:
4029 if (is_numeric_expression (expr
))
4033 case context_data_or_numeric
:
4034 if (is_numeric_expression (expr
) ||
4035 is_data_expression (expr
)) {
4040 case context_function
:
4041 if (expr
-> op
== expr_function
)
4049 struct binding
*create_binding (struct binding_scope
**scope
, const char *name
)
4051 struct binding
*binding
;
4054 if (!binding_scope_allocate (scope
, MDL
))
4055 return (struct binding
*)0;
4058 binding
= find_binding (*scope
, name
);
4060 binding
= dmalloc (sizeof *binding
, MDL
);
4062 return (struct binding
*)0;
4064 memset (binding
, 0, sizeof *binding
);
4065 binding
-> name
= dmalloc (strlen (name
) + 1, MDL
);
4066 if (!binding
-> name
) {
4067 dfree (binding
, MDL
);
4068 return (struct binding
*)0;
4070 strcpy (binding
-> name
, name
);
4072 binding
-> next
= (*scope
) -> bindings
;
4073 (*scope
) -> bindings
= binding
;
4080 int bind_ds_value (struct binding_scope
**scope
,
4082 struct data_string
*value
)
4084 struct binding
*binding
;
4086 binding
= create_binding (scope
, name
);
4090 if (binding
-> value
)
4091 binding_value_dereference (&binding
-> value
, MDL
);
4093 if (!binding_value_allocate (&binding
-> value
, MDL
))
4096 data_string_copy (&binding
-> value
-> value
.data
, value
, MDL
);
4097 binding
-> value
-> type
= binding_data
;
4103 int find_bound_string (struct data_string
*value
,
4104 struct binding_scope
*scope
,
4107 struct binding
*binding
;
4109 binding
= find_binding (scope
, name
);
4111 !binding
-> value
||
4112 binding
-> value
-> type
!= binding_data
)
4115 if (binding
-> value
-> value
.data
.terminated
) {
4116 data_string_copy (value
, &binding
-> value
-> value
.data
, MDL
);
4118 if (buffer_allocate (&value
->buffer
,
4119 binding
->value
->value
.data
.len
,
4124 memcpy (value
-> buffer
-> data
,
4125 binding
-> value
-> value
.data
.data
,
4126 binding
-> value
-> value
.data
.len
);
4127 value
-> data
= value
-> buffer
-> data
;
4128 value
-> len
= binding
-> value
-> value
.data
.len
;
4134 int unset (struct binding_scope
*scope
, const char *name
)
4136 struct binding
*binding
;
4138 binding
= find_binding (scope
, name
);
4140 if (binding
-> value
)
4141 binding_value_dereference
4142 (&binding
-> value
, MDL
);
4149 * \brief Adds two Dc-formatted lists into a single Dc-formatted list
4151 * Given two data_strings containing compressed lists, it constructs a
4152 * third data_string containing a single compressed list:
4154 * 1. Decompressing the first list into a buffer
4155 * 2. Decompressing the second list onto the end of the buffer
4156 * 3. Compressing the buffer into the result
4158 * If either list is empty, the result will be the equal to the compressed
4159 * content of the non-empty list. If both lists are empty, the result will
4160 * be an "empty" list: a 1 byte buffer containing 0x00.
4162 * It relies on two functions to decompress and compress:
4164 * - MRns_name_uncompress_list() - produces a null-terminated string of
4165 * comma-separated domain-names from a buffer containing "Dc" formatted
4168 * - MRns_name_compress_list() - produces a buffer containing "Dc" formatted
4169 * data from a null-terminated string containing comma-separated domain-names
4171 * \param result data_string which will contain the combined list
4173 * \param list1 data_string containing first Dc formatted list
4174 * \param list2 data_string containing second Dc formatted list
4175 * \return 0 if there is an error, the length of the new list when successful
4177 int concat_dclists (struct data_string
* result
,
4178 struct data_string
* list1
,
4179 struct data_string
* list2
)
4181 char uncompbuf
[32*NS_MAXCDNAME
];
4182 char *uncomp
= uncompbuf
;
4184 int compbuf_max
= 0;
4188 /* If not empty, uncompress first list into the uncompressed buffer */
4189 if (list1
&& (list1
->data
) && (list1
->len
)) {
4190 list_len
= MRns_name_uncompress_list(list1
->data
,
4194 log_error ("concat_dclists:"
4195 " error decompressing domain list 1");
4199 uncomp_len
= list_len
;
4203 /* If not empty, uncompress second list into the uncompressed buffer */
4204 if (list2
&& (list2
->data
) && (list2
->len
)) {
4205 /* If first list wasn't empty, add a comma */
4206 if (uncomp_len
> 0) {
4211 list_len
= MRns_name_uncompress_list(list2
->data
, list2
->len
,
4212 uncomp
, (sizeof(uncompbuf
)
4215 log_error ("concat_dclists:"
4216 " error decompressing domain list 2");
4220 uncomp_len
+= list_len
;
4224 /* If both lists were empty, return an "empty" result */
4225 if (uncomp_len
== 0) {
4226 if (!buffer_allocate (&result
->buffer
, 1, MDL
)) {
4227 log_error ("concat_dclists: empty list allocate fail");
4233 result
->data
= result
->buffer
->data
;
4237 /* Estimate the buffer size needed for decompression. The largest
4238 * decompression would if one where there are no repeated portions,
4239 * (i.e. no compressions). Therefore that size should be the
4240 * decompressed string length + 2 for each comma + a final null. Each
4241 * dot gets replaced with a length byte and is accounted for in string
4242 * length. Mininum length is * uncomp_len + 3. */
4243 compbuf_max
= uncomp_len
+ 3;
4245 for (i
= 0; i
< uncomp_len
; i
++)
4246 if (*uncomp
++ == ',')
4249 /* Allocate compression buffer based on estimated max */
4250 if (!buffer_allocate (&result
->buffer
, compbuf_max
, MDL
)) {
4251 log_error ("concat_dclists: No memory for result");
4256 /* Compress the combined list into result */
4257 list_len
= MRns_name_compress_list(uncompbuf
, uncomp_len
,
4258 result
->buffer
->data
, compbuf_max
);
4260 if (list_len
<= 0) {
4261 log_error ("concat_dlists: error compressing result");
4262 data_string_forget(result
, MDL
);
4267 /* Update result length to actual size */
4268 result
->len
= list_len
;
4269 result
->data
= result
->buffer
->data
;
4273 /* vim: set tabstop=8: */