]> git.ipfire.org Git - thirdparty/dhcp.git/blob - common/tree.c
copy rights update
[thirdparty/dhcp.git] / common / tree.c
1 /* tree.c
2
3 Routines for manipulating parse trees... */
4
5 /*
6 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
8 *
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/.
12 *
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.
20 *
21 * Internet Systems Consortium, Inc.
22 * PO Box 360
23 * Newmarket, NH 03857 USA
24 * <info@isc.org>
25 * https://www.isc.org/
26 *
27 */
28
29 #include "dhcpd.h"
30 #include <omapip/omapip_p.h>
31 #include <ctype.h>
32 #include <sys/wait.h>
33
34 #ifdef HAVE_REGEX_H
35 # include <regex.h>
36 #endif
37
38 struct binding_scope *global_scope;
39
40 static int do_host_lookup (struct data_string *, struct dns_host_entry *);
41
42 #define DS_SPRINTF_SIZE 128
43
44 /*
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.
49 *
50 * If the append works, then 1 is returned.
51 *
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.
54 */
55 int
56 data_string_sprintfa(struct data_string *ds, const char *fmt, ...) {
57 va_list args;
58 int cur_strlen;
59 int max;
60 int vsnprintf_ret;
61 int new_len;
62 struct buffer *tmp_buffer;
63
64 /*
65 * If the data_string is empty, then initialize it.
66 */
67 if (ds->data == NULL) {
68 /* INSIST(ds.buffer == NULL); */
69 if (!buffer_allocate(&ds->buffer, DS_SPRINTF_SIZE, MDL)) {
70 return 0;
71 }
72 ds->data = ds->buffer->data;
73 ds->len = DS_SPRINTF_SIZE;
74 *((char *)ds->data) = '\0';
75 }
76
77 /*
78 * Get the length of the string, and figure out how much space
79 * is left.
80 */
81 cur_strlen = strlen((char *)ds->data);
82 max = ds->len - cur_strlen;
83
84 /*
85 * Use vsnprintf(), which won't write past our space, but will
86 * tell us how much space it wants.
87 */
88 va_start(args, fmt);
89 vsnprintf_ret = vsnprintf((char *)ds->data+cur_strlen, max, fmt, args);
90 va_end(args);
91 /* INSIST(vsnprintf_ret >= 0); */
92
93 /*
94 * If our buffer is not big enough, we need a new buffer.
95 */
96 if (vsnprintf_ret >= max) {
97 /*
98 * Figure out a size big enough.
99 */
100 new_len = ds->len * 2;
101 while (new_len <= cur_strlen + vsnprintf_ret) {
102 new_len *= 2;
103 }
104
105 /*
106 * Create a new buffer and fill it.
107 */
108 tmp_buffer = NULL;
109 if (!buffer_allocate(&tmp_buffer, new_len, MDL)) {
110 /*
111 * If we can't create a big enough buffer,
112 * we should remove any truncated output that we had.
113 */
114 *((char *)ds->data+cur_strlen) = '\0';
115 va_end(args);
116 return 0;
117 }
118 memcpy(tmp_buffer->data, ds->data, cur_strlen);
119
120 /* Rerun the vsprintf. */
121 va_start(args, fmt);
122 vsprintf((char *)tmp_buffer->data + cur_strlen, fmt, args);
123 va_end(args);
124
125 /*
126 * Replace our old buffer with the new buffer.
127 */
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;
132 ds->len = new_len;
133 }
134 return 1;
135 }
136
137 pair cons (car, cdr)
138 caddr_t car;
139 pair cdr;
140 {
141 pair foo = (pair)dmalloc (sizeof *foo, MDL);
142 if (!foo)
143 log_fatal ("no memory for cons.");
144 foo -> car = car;
145 foo -> cdr = cdr;
146 return foo;
147 }
148
149 int make_const_option_cache (oc, buffer, data, len, option, file, line)
150 struct option_cache **oc;
151 struct buffer **buffer;
152 u_int8_t *data;
153 unsigned len;
154 struct option *option;
155 const char *file;
156 int line;
157 {
158 struct buffer *bp;
159
160 if (buffer) {
161 bp = *buffer;
162 *buffer = 0;
163 } else {
164 bp = (struct buffer *)0;
165 if (!buffer_allocate (&bp, len, file, line)) {
166 log_error ("%s(%d): can't allocate buffer.",
167 file, line);
168 return 0;
169 }
170 }
171
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);
175 return 0;
176 }
177
178 (*oc) -> data.len = len;
179 (*oc) -> data.buffer = bp;
180 (*oc) -> data.data = &bp -> data [0];
181 (*oc) -> data.terminated = 0;
182 if (data)
183 memcpy (&bp -> data [0], data, len);
184 option_reference(&((*oc)->option), option, MDL);
185 return 1;
186 }
187
188 int make_host_lookup (expr, name)
189 struct expression **expr;
190 const char *name;
191 {
192 if (!expression_allocate (expr, MDL)) {
193 log_error ("No memory for host lookup tree node.");
194 return 0;
195 }
196 (*expr) -> op = expr_host_lookup;
197 if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) {
198 expression_dereference (expr, MDL);
199 return 0;
200 }
201 return 1;
202 }
203
204 int enter_dns_host (dh, name)
205 struct dns_host_entry **dh;
206 const char *name;
207 {
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.");
214 return 0;
215 }
216 return 1;
217 }
218
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)
222 {
223 struct expression *nt;
224
225 if (!expression_allocate (expr, file, line)) {
226 log_error ("No memory for make_const_data tree node.");
227 return 0;
228 }
229 nt = *expr;
230
231 if (len) {
232 if (allocate) {
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);
237 return 0;
238 }
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);
243 } else
244 nt -> data.const_data.data = data;
245 nt -> data.const_data.terminated = terminated;
246 } else
247 nt -> data.const_data.data = 0;
248
249 nt -> op = expr_const_data;
250 nt -> data.const_data.len = len;
251 return 1;
252 }
253
254 int make_const_int (expr, val)
255 struct expression **expr;
256 unsigned long val;
257 {
258 if (!expression_allocate (expr, MDL)) {
259 log_error ("No memory for make_const_int tree node.");
260 return 0;
261 }
262
263 (*expr) -> op = expr_const_int;
264 (*expr) -> data.const_int = val;
265 return 1;
266 }
267
268 int make_concat (expr, left, right)
269 struct expression **expr;
270 struct expression *left, *right;
271 {
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
274 a null tree. */
275 if (!left) {
276 if (!right)
277 return 0;
278 expression_reference (expr, right, MDL);
279 return 1;
280 }
281 if (!right) {
282 expression_reference (expr, left, MDL);
283 return 1;
284 }
285
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.");
289 return 0;
290 }
291
292 (*expr) -> op = expr_concat;
293 expression_reference (&(*expr) -> data.concat [0], left, MDL);
294 expression_reference (&(*expr) -> data.concat [1], right, MDL);
295 return 1;
296 }
297
298 int make_encapsulation (expr, name)
299 struct expression **expr;
300 struct data_string *name;
301 {
302 /* Allocate a new node to store the encapsulation. */
303 if (!expression_allocate (expr, MDL)) {
304 log_error ("No memory for encapsulation expression node.");
305 return 0;
306 }
307
308 (*expr) -> op = expr_encapsulate;
309 data_string_copy (&(*expr) -> data.encapsulate, name, MDL);
310 return 1;
311 }
312
313 int make_substring (new, expr, offset, length)
314 struct expression **new;
315 struct expression *expr;
316 struct expression *offset;
317 struct expression *length;
318 {
319 /* Allocate an expression node to compute the substring. */
320 if (!expression_allocate (new, MDL)) {
321 log_error ("no memory for substring expression.");
322 return 0;
323 }
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);
328 return 1;
329 }
330
331 int make_limit (new, expr, limit)
332 struct expression **new;
333 struct expression *expr;
334 int limit;
335 {
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);
341
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);
346 return 0;
347 }
348 (*new) -> data.substring.offset -> op = expr_const_int;
349 (*new) -> data.substring.offset -> data.const_int = 0;
350
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);
355 return 0;
356 }
357 (*new) -> data.substring.len -> op = expr_const_int;
358 (*new) -> data.substring.len -> data.const_int = limit;
359
360 return 1;
361 }
362
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)
366 {
367 if (!option_cache_allocate (oc, file, line))
368 return 0;
369 if (dp)
370 data_string_copy (&(*oc) -> data, dp, file, line);
371 if (expr)
372 expression_reference (&(*oc) -> expression, expr, file, line);
373 option_reference(&(*oc)->option, option, MDL);
374 return 1;
375 }
376
377 int make_let (result, name)
378 struct executable_statement **result;
379 const char *name;
380 {
381 if (!(executable_statement_allocate (result, MDL)))
382 return 0;
383
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);
388 return 0;
389 }
390 strcpy ((*result) -> data.let.name, name);
391 return 1;
392 }
393
394 static int do_host_lookup (result, dns)
395 struct data_string *result;
396 struct dns_host_entry *dns;
397 {
398 struct hostent *h;
399 unsigned i, count;
400 unsigned new_len;
401
402 #ifdef DEBUG_EVAL
403 log_debug ("time: now = %d dns = %d diff = %d",
404 cur_time, dns -> timeout, cur_time - dns -> timeout);
405 #endif
406
407 /* If the record hasn't timed out, just copy the data and return. */
408 if (cur_time <= dns -> timeout) {
409 #ifdef DEBUG_EVAL
410 log_debug ("easy copy: %d %s",
411 dns -> data.len,
412 (dns -> data.len > 4
413 ? inet_ntoa (*(struct in_addr *)(dns -> data.data))
414 : 0));
415 #endif
416 data_string_copy (result, &dns -> data, MDL);
417 return 1;
418 }
419 #ifdef DEBUG_EVAL
420 log_debug ("Looking up %s", dns -> hostname);
421 #endif
422
423 /* Otherwise, look it up... */
424 h = gethostbyname (dns -> hostname);
425 if (!h) {
426 #ifndef NO_H_ERRNO
427 switch (h_errno) {
428 case HOST_NOT_FOUND:
429 #endif
430 log_error ("%s: host unknown.", dns -> hostname);
431 #ifndef NO_H_ERRNO
432 break;
433 case TRY_AGAIN:
434 log_error ("%s: temporary name server failure",
435 dns -> hostname);
436 break;
437 case NO_RECOVERY:
438 log_error ("%s: name server failed", dns -> hostname);
439 break;
440 case NO_DATA:
441 log_error ("%s: no A record associated with address",
442 dns -> hostname);
443 }
444 #endif /* !NO_H_ERRNO */
445
446 /* Okay to try again after a minute. */
447 dns -> timeout = cur_time + 60;
448 data_string_forget (&dns -> data, MDL);
449 return 0;
450 }
451
452 #ifdef DEBUG_EVAL
453 log_debug ("Lookup succeeded; first address is %s",
454 inet_ntoa (h -> h_addr_list [0]));
455 #endif
456
457 /* Count the number of addresses we got... */
458 for (count = 0; h -> h_addr_list [count]; count++)
459 ;
460
461 /* Dereference the old data, if any. */
462 data_string_forget (&dns -> data, MDL);
463
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))
467 {
468 log_error ("No memory for %s.", dns -> hostname);
469 return 0;
470 }
471
472 dns -> data.data = &dns -> data.buffer -> data [0];
473 dns -> data.len = new_len;
474 dns -> data.terminated = 0;
475
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));
481 }
482 #ifdef DEBUG_EVAL
483 log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
484 *(int *)(dns -> buffer), h -> h_addr_list [0]);
485 #endif
486
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;
490
491 #ifdef DEBUG_EVAL
492 log_debug ("hard copy: %d %s", dns -> data.len,
493 (dns -> data.len > 4
494 ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));
495 #endif
496 data_string_copy (result, &dns -> data, MDL);
497 return 1;
498 }
499
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;
504 struct lease *lease;
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;
510 const char *file;
511 int line;
512 {
513 struct binding_value *bv;
514 int status;
515 struct binding *binding;
516
517 bv = (struct binding_value *)0;
518
519 if (expr -> op == expr_variable_reference) {
520 if (!scope || !*scope)
521 return 0;
522
523 binding = find_binding (*scope, expr -> data.variable);
524
525 if (binding && binding -> value) {
526 if (result)
527 binding_value_reference (result,
528 binding -> value,
529 file, line);
530 return 1;
531 } else
532 return 0;
533 } else if (expr -> op == expr_funcall) {
534 struct string_list *s;
535 struct expression *arg;
536 struct binding_scope *ns;
537 struct binding *nb;
538
539 if (!scope || !*scope) {
540 log_error ("%s: no such function.",
541 expr -> data.funcall.name);
542 return 0;
543 }
544
545 binding = find_binding (*scope, expr -> data.funcall.name);
546
547 if (!binding || !binding -> value) {
548 log_error ("%s: no such function.",
549 expr -> data.funcall.name);
550 return 0;
551 }
552 if (binding -> value -> type != binding_function) {
553 log_error ("%s: not a function.",
554 expr -> data.funcall.name);
555 return 0;
556 }
557
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);
564 return 0;
565 }
566
567 arg = expr -> data.funcall.arglist;
568 s = binding -> value -> value.fundef -> args;
569 while (arg && s) {
570 nb = dmalloc (sizeof *nb, MDL);
571 if (!nb) {
572 blb:
573 binding_scope_dereference (&ns, MDL);
574 return 0;
575 } else {
576 memset (nb, 0, sizeof *nb);
577 nb -> name = dmalloc (strlen (s -> string) + 1,
578 MDL);
579 if (nb -> name)
580 strcpy (nb -> name, s -> string);
581 else {
582 dfree (nb, MDL);
583 goto blb;
584 }
585 }
586 evaluate_expression (&nb -> value, packet, lease,
587 client_state,
588 in_options, cfg_options, scope,
589 arg -> data.arg.val, file, line);
590 nb -> next = ns -> bindings;
591 ns -> bindings = nb;
592 arg = arg -> data.arg.next;
593 s = s -> next;
594 }
595 if (arg) {
596 log_error ("%s: too many arguments.",
597 expr -> data.funcall.name);
598 binding_scope_dereference (&ns, MDL);
599 return 0;
600 }
601 if (s) {
602 log_error ("%s: too few arguments.",
603 expr -> data.funcall.name);
604 binding_scope_dereference (&ns, MDL);
605 return 0;
606 }
607
608 if (scope && *scope)
609 binding_scope_reference (&ns -> outer, *scope, MDL);
610
611 status = (execute_statements
612 (&bv, packet,
613 lease, client_state, in_options, cfg_options, &ns,
614 binding->value->value.fundef->statements, NULL));
615 binding_scope_dereference (&ns, MDL);
616
617 if (!bv)
618 return 1;
619 } else if (is_boolean_expression (expr)) {
620 if (!binding_value_allocate (&bv, MDL))
621 return 0;
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))
628 return 0;
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))
635 return 0;
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));
640 } else {
641 log_error ("%s: invalid expression type: %d",
642 "evaluate_expression", expr -> op);
643 return 0;
644 }
645 if (result && status)
646 binding_value_reference (result, bv, file, line);
647 binding_value_dereference (&bv, MDL);
648
649 return status;
650 }
651
652 int binding_value_dereference (struct binding_value **v,
653 const char *file, int line)
654 {
655 struct binding_value *bv = *v;
656
657 *v = (struct binding_value *)0;
658
659 /* Decrement the reference count. If it's nonzero, we're
660 done. */
661 --(bv -> refcnt);
662 rc_register (file, line, v, bv, bv -> refcnt, 1, RC_MISC);
663 if (bv -> refcnt > 0)
664 return 1;
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);
669 #endif
670 #if defined (POINTER_DEBUG)
671 abort ();
672 #else
673 return 0;
674 #endif
675 }
676
677 switch (bv -> type) {
678 case binding_boolean:
679 case binding_numeric:
680 break;
681 case binding_data:
682 if (bv -> value.data.buffer)
683 data_string_forget (&bv -> value.data, file, line);
684 break;
685 default:
686 log_error ("%s(%d): invalid binding type: %d",
687 file, line, bv -> type);
688 return 0;
689 }
690 free_binding_value(bv, file, line);
691 return 1;
692 }
693
694 int evaluate_boolean_expression (result, packet, lease, client_state,
695 in_options, cfg_options, scope, expr)
696 int *result;
697 struct packet *packet;
698 struct lease *lease;
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;
704 {
705 struct data_string left, right;
706 int bleft, bright;
707 int sleft, sright;
708 struct binding *binding;
709 struct binding_value *bv, *obv;
710 #ifdef HAVE_REGEX_H
711 int regflags = REG_EXTENDED | REG_NOSUB;
712 regex_t re;
713 #endif
714
715 switch (expr -> op) {
716 case expr_check:
717 *result = check_collection (packet, lease,
718 expr -> data.check);
719 #if defined (DEBUG_EXPRESSIONS)
720 log_debug ("bool: check (%s) returns %s",
721 expr -> data.check -> name,
722 *result ? "true" : "false");
723 #endif
724 return 1;
725
726 case expr_equal:
727 case expr_not_equal:
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,
734 cfg_options, scope,
735 expr -> data.equal [1], MDL);
736 if (sleft && sright) {
737 if (bv -> type != obv -> type)
738 *result = expr -> op == expr_not_equal;
739 else {
740 switch (obv -> type) {
741 case binding_boolean:
742 if (bv -> value.boolean == obv -> value.boolean)
743 *result = expr -> op == expr_equal;
744 else
745 *result = expr -> op == expr_not_equal;
746 break;
747
748 case binding_data:
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;
755 else
756 *result = expr -> op == expr_not_equal;
757 break;
758
759 case binding_numeric:
760 if (bv -> value.intval == obv -> value.intval)
761 *result = expr -> op == expr_equal;
762 else
763 *result = expr -> op == expr_not_equal;
764 break;
765
766 case binding_function:
767 if (bv -> value.fundef == obv -> value.fundef)
768 *result = expr -> op == expr_equal;
769 else
770 *result = expr -> op == expr_not_equal;
771 break;
772 default:
773 *result = expr -> op == expr_not_equal;
774 break;
775 }
776 }
777 } else if (!sleft && !sright)
778 *result = expr -> op == expr_equal;
779 else
780 *result = expr -> op == expr_not_equal;
781
782 #if defined (DEBUG_EXPRESSIONS)
783 log_debug ("bool: %sequal = %s",
784 expr -> op == expr_not_equal ? "not" : "",
785 (*result ? "true" : "false"));
786 #endif
787 if (sleft)
788 binding_value_dereference (&bv, MDL);
789 if (sright)
790 binding_value_dereference (&obv, MDL);
791 return 1;
792
793 case expr_iregex_match:
794 #ifdef HAVE_REGEX_H
795 regflags |= REG_ICASE;
796 #endif
797 /* FALL THROUGH */
798 case expr_regex_match:
799 #ifdef HAVE_REGEX_H
800 memset(&left, 0, sizeof left);
801 bleft = evaluate_data_expression(&left, packet, lease,
802 client_state,
803 in_options, cfg_options,
804 scope,
805 expr->data.equal[0], MDL);
806
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.
810 */
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 */
815 bleft = 0;
816 }
817
818 memset(&right, 0, sizeof right);
819 bright = evaluate_data_expression(&right, packet, lease,
820 client_state,
821 in_options, cfg_options,
822 scope,
823 expr->data.equal[1], MDL);
824
825 *result = 0;
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))
831 *result = 1;
832
833 #if defined (DEBUG_EXPRESSIONS)
834 log_debug("bool: %s ~= %s yields %s",
835 bleft ? print_hex_1(left.len, left.data, 20)
836 : "NULL",
837 bright ? print_hex_2 (right.len, right.data, 20)
838 : "NULL",
839 *result ? "true" : "false");
840 #endif
841
842 if (bleft)
843 data_string_forget(&left, MDL);
844 if (bright)
845 data_string_forget(&right, MDL);
846
847 regfree(&re);
848
849 /*
850 * If we have bleft and bright then we have a good
851 * syntax, otherwise not.
852 *
853 * XXX: we don't warn on invalid regular expression
854 * syntax, should we?
855 */
856 return bleft && bright;
857 #else
858 /* It shouldn't be possible to configure a regex operator
859 * when there's no support.
860 */
861 log_fatal("Impossible condition at %s:%d.", MDL);
862 break;
863 #endif
864
865 case expr_and:
866 sleft = evaluate_boolean_expression (&bleft, packet, lease,
867 client_state,
868 in_options, cfg_options,
869 scope,
870 expr -> data.and [0]);
871 if (sleft && bleft)
872 sright = evaluate_boolean_expression
873 (&bright, packet, lease, client_state,
874 in_options, cfg_options,
875 scope, expr -> data.and [1]);
876 else
877 sright = bright = 0;
878
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",
883 ((sleft && sright)
884 ? (bleft && bright ? "true" : "false") : "NULL"));
885 #endif
886 if (sleft && sright) {
887 *result = bleft && bright;
888 return 1;
889 }
890 return 0;
891
892 case expr_or:
893 bleft = bright = 0;
894 sleft = evaluate_boolean_expression (&bleft, packet, lease,
895 client_state,
896 in_options, cfg_options,
897 scope,
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]);
904 else
905 sright = 0;
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",
910 ((sleft || sright)
911 ? (bleft || bright ? "true" : "false") : "NULL"));
912 #endif
913 if (sleft || sright) {
914 *result = bleft || bright;
915 return 1;
916 }
917 return 0;
918
919 case expr_not:
920 sleft = evaluate_boolean_expression(&bleft, packet, lease,
921 client_state,
922 in_options, cfg_options,
923 scope,
924 expr->data.not);
925 #if defined (DEBUG_EXPRESSIONS)
926 log_debug("bool: not (%s) = %s",
927 sleft ? (bleft ? "true" : "false") : "NULL",
928 sleft ? (!bleft ? "true" : "false") : "NULL");
929 #endif
930 if (sleft) {
931 *result = !bleft;
932 return 1;
933 }
934 return 0;
935
936 case expr_exists:
937 memset (&left, 0, sizeof left);
938 if (!in_options ||
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))
943 *result = 0;
944 else {
945 *result = 1;
946 data_string_forget (&left, MDL);
947 }
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");
953 #endif
954 return 1;
955
956 case expr_known:
957 if (!packet) {
958 #if defined (DEBUG_EXPRESSIONS)
959 log_debug ("bool: known = NULL");
960 #endif
961 return 0;
962 }
963 #if defined (DEBUG_EXPRESSIONS)
964 log_debug ("bool: known = %s",
965 packet -> known ? "true" : "false");
966 #endif
967 *result = packet -> known;
968 return 1;
969
970 case expr_static:
971 if (!lease || !(lease -> flags & STATIC_LEASE)) {
972 #if defined (DEBUG_EXPRESSIONS)
973 log_debug ("bool: static = false (%s %s %s %d)",
974 lease ? "y" : "n",
975 (lease && (lease -> flags & STATIC_LEASE)
976 ? "y" : "n"),
977 piaddr (lease -> ip_addr),
978 lease ? lease -> flags : 0);
979 #endif
980 *result = 0;
981 return 1;
982 }
983 #if defined (DEBUG_EXPRESSIONS)
984 log_debug ("bool: static = true");
985 #endif
986 *result = 1;
987 return 1;
988
989 case expr_variable_exists:
990 if (scope && *scope) {
991 binding = find_binding (*scope, expr -> data.variable);
992
993 if (binding) {
994 if (binding -> value)
995 *result = 1;
996 else
997 *result = 0;
998 } else
999 *result = 0;
1000 } else
1001 *result = 0;
1002 #if defined (DEBUG_EXPRESSIONS)
1003 log_debug ("boolean: %s? = %s", expr -> data.variable,
1004 *result ? "true" : "false");
1005 #endif
1006 return 1;
1007
1008 case expr_variable_reference:
1009 if (scope && *scope) {
1010 binding = find_binding (*scope, expr -> data.variable);
1011
1012 if (binding && binding -> value) {
1013 if (binding -> value -> type ==
1014 binding_boolean) {
1015 *result = binding -> value -> value.boolean;
1016 sleft = 1;
1017 } else {
1018 log_error ("binding type %d in %s.",
1019 binding -> value -> type,
1020 "evaluate_boolean_expression");
1021 sleft = 0;
1022 }
1023 } else
1024 sleft = 0;
1025 } else
1026 sleft = 0;
1027 #if defined (DEBUG_EXPRESSIONS)
1028 log_debug ("boolean: %s = %s", expr -> data.variable,
1029 sleft ? (*result ? "true" : "false") : "NULL");
1030 #endif
1031 return sleft;
1032
1033 case expr_funcall:
1034 bv = (struct binding_value *)0;
1035 sleft = evaluate_expression (&bv, packet, lease, client_state,
1036 in_options, cfg_options,
1037 scope, expr, MDL);
1038 if (sleft) {
1039 if (bv -> type != binding_boolean)
1040 log_error ("%s() returned type %d in %s.",
1041 expr -> data.funcall.name,
1042 bv -> type,
1043 "evaluate_boolean_expression");
1044 else
1045 *result = bv -> value.boolean;
1046 binding_value_dereference (&bv, MDL);
1047 }
1048 #if defined (DEBUG_EXPRESSIONS)
1049 log_debug ("boolean: %s() = %s", expr -> data.funcall.name,
1050 sleft ? (*result ? "true" : "false") : "NULL");
1051 #endif
1052 break;
1053
1054 case expr_none:
1055 case expr_match:
1056 case expr_substring:
1057 case expr_suffix:
1058 case expr_lcase:
1059 case expr_ucase:
1060 case expr_option:
1061 case expr_hardware:
1062 case expr_const_data:
1063 case expr_packet:
1064 case expr_concat:
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:
1071 case expr_reverse:
1072 case expr_pick_first_value:
1073 case expr_host_decl_name:
1074 case expr_config_option:
1075 case expr_leased_address:
1076 case expr_null:
1077 case expr_filename:
1078 case expr_sname:
1079 case expr_gethostname:
1080 case expr_v6relay:
1081 case expr_concat_dclist:
1082 log_error ("Data opcode in evaluate_boolean_expression: %d",
1083 expr -> op);
1084 return 0;
1085
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:
1092 case expr_add:
1093 case expr_subtract:
1094 case expr_multiply:
1095 case expr_divide:
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",
1102 expr -> op);
1103 return 0;
1104
1105 case expr_ns_add:
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",
1110 expr -> op);
1111 return 0;
1112
1113 case expr_function:
1114 log_error ("function definition in evaluate_boolean_expr");
1115 return 0;
1116
1117 case expr_arg:
1118 break;
1119 }
1120
1121 log_error ("Bogus opcode in evaluate_boolean_expression: %d",
1122 expr -> op);
1123 return 0;
1124 }
1125
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;
1136 const char *file;
1137 int line;
1138 {
1139 struct data_string data, other;
1140 unsigned long offset, len, i;
1141 int s0, s1, s2, s3;
1142 int status;
1143 struct binding *binding;
1144 unsigned char *s;
1145 struct binding_value *bv;
1146 struct packet *relay_packet;
1147 struct option_state *relay_options;
1148
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,
1154 client_state,
1155 in_options, cfg_options, scope,
1156 expr -> data.substring.expr,
1157 MDL);
1158
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,
1164 client_state,
1165 in_options, cfg_options,
1166 scope,
1167 expr -> data.substring.len);
1168
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;
1179 }
1180 result -> data += offset;
1181 }
1182 s3 = 1;
1183 } else
1184 s3 = 0;
1185
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)
1192 : "NULL"));
1193 #endif
1194 if (s0)
1195 data_string_forget (&data, MDL);
1196 if (s3)
1197 return 1;
1198 return 0;
1199
1200 /* Extract the last N bytes of a data string. */
1201 case expr_suffix:
1202 memset (&data, 0, sizeof data);
1203 s0 = evaluate_data_expression (&data, packet, lease,
1204 client_state,
1205 in_options, cfg_options, scope,
1206 expr -> data.suffix.expr, MDL);
1207 /* Evaluate the length. */
1208 s1 = evaluate_numeric_expression (&len, packet, lease,
1209 client_state,
1210 in_options, cfg_options,
1211 scope,
1212 expr -> data.suffix.len);
1213 if (s0 && s1) {
1214 data_string_copy (result, &data, file, line);
1215
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
1220 length. */
1221 if (data.len > len) {
1222 result -> data += data.len - len;
1223 result -> len = len;
1224 }
1225
1226 data_string_forget (&data, MDL);
1227 }
1228
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",
1233 ((s0 && s1)
1234 ? print_hex_2 (result -> len, result -> data, 30)
1235 : "NULL"));
1236 #endif
1237
1238 return s0 && s1;
1239
1240 /* Convert string to lowercase. */
1241 case expr_lcase:
1242 memset(&data, 0, sizeof data);
1243 s0 = evaluate_data_expression(&data, packet, lease,
1244 client_state,
1245 in_options, cfg_options, scope,
1246 expr->data.lcase, MDL);
1247 s1 = 0;
1248 if (s0) {
1249 result->len = data.len;
1250 if (buffer_allocate(&result->buffer,
1251 result->len + data.terminated,
1252 MDL)) {
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++)
1259 *s = tolower(*s);
1260 s1 = 1;
1261 } else {
1262 log_error("data: lcase: no buffer memory.");
1263 }
1264 }
1265
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)
1270 : "NULL");
1271 #endif
1272 if (s0)
1273 data_string_forget(&data, MDL);
1274 return s1;
1275
1276 /* Convert string to uppercase. */
1277 case expr_ucase:
1278 memset(&data, 0, sizeof data);
1279 s0 = evaluate_data_expression(&data, packet, lease,
1280 client_state,
1281 in_options, cfg_options, scope,
1282 expr->data.lcase, MDL);
1283 s1 = 0;
1284 if (s0) {
1285 result->len = data.len;
1286 if (buffer_allocate(&result->buffer,
1287 result->len + data.terminated,
1288 file, line)) {
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++)
1295 *s = toupper(*s);
1296 s1 = 1;
1297 } else {
1298 log_error("data: lcase: no buffer memory.");
1299 }
1300 }
1301
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)
1306 : "NULL");
1307 #endif
1308 if (s0)
1309 data_string_forget(&data, MDL);
1310
1311 return s1;
1312
1313 /* Extract an option. */
1314 case expr_option:
1315 if (in_options)
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,
1321 file, line);
1322 else
1323 s0 = 0;
1324
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)
1330 : "NULL");
1331 #endif
1332 return s0;
1333
1334 case expr_config_option:
1335 if (cfg_options)
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,
1341 file, line);
1342 else
1343 s0 = 0;
1344
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)
1350 : "NULL");
1351 #endif
1352 return s0;
1353
1354 /* Combine the hardware type and address. */
1355 case expr_hardware:
1356 /* On the client, hardware is our hardware. */
1357 if (client_state) {
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));
1364 #endif
1365 return (1);
1366 }
1367
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. */
1371
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",
1375 packet->raw->hlen);
1376 return (0);
1377 }
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;
1385 } else {
1386 log_error("data: hardware: "
1387 "no memory for buffer.");
1388 return (0);
1389 }
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;
1397 } else {
1398 log_error("data: hardware: "
1399 "no memory for buffer.");
1400 return (0);
1401 }
1402 } else {
1403 log_error("data: hardware: no raw packet or lease "
1404 "is available");
1405 return (0);
1406 }
1407
1408 #if defined (DEBUG_EXPRESSIONS)
1409 log_debug("data: hardware = %s",
1410 print_hex_1(result->len, result->data, 60));
1411 #endif
1412 return (1);
1413
1414 /* Extract part of the raw packet. */
1415 case expr_packet:
1416 if (!packet || !packet -> raw) {
1417 log_error ("data: packet: raw packet not available");
1418 return 0;
1419 }
1420
1421 s0 = evaluate_numeric_expression (&offset, packet, lease,
1422 client_state,
1423 in_options, cfg_options,
1424 scope,
1425 expr -> data.packet.offset);
1426 s1 = evaluate_numeric_expression (&len,
1427 packet, lease, client_state,
1428 in_options, cfg_options,
1429 scope,
1430 expr -> data.packet.len);
1431 if (s0 && s1 && offset < packet -> packet_length) {
1432 if (offset + len > packet -> packet_length)
1433 result -> len =
1434 packet -> packet_length - offset;
1435 else
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;
1444 } else {
1445 log_error ("data: packet: no buffer memory.");
1446 return 0;
1447 }
1448 s2 = 1;
1449 } else
1450 s2 = 0;
1451 #if defined (DEBUG_EXPRESSIONS)
1452 log_debug ("data: packet (%ld, %ld) = %s",
1453 offset, len,
1454 s2 ? print_hex_1 (result -> len,
1455 result -> data, 60) : NULL);
1456 #endif
1457 return s2;
1458
1459 /* The encapsulation of all defined options in an
1460 option space... */
1461 case expr_encapsulate:
1462 if (cfg_options)
1463 s0 = option_space_encapsulate
1464 (result, packet, lease, client_state,
1465 in_options, cfg_options, scope,
1466 &expr -> data.encapsulate);
1467 else
1468 s0 = 0;
1469
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");
1475 #endif
1476 return s0;
1477
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));
1484 #endif
1485 data_string_copy (result,
1486 &expr -> data.const_data, file, line);
1487 return 1;
1488
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,
1495 (s0
1496 ? print_dotted_quads (result -> len, result -> data)
1497 : "NULL"));
1498 #endif
1499 return s0;
1500
1501 /* Concatenation... */
1502 case expr_concat:
1503 memset (&data, 0, sizeof data);
1504 s0 = evaluate_data_expression (&data, packet, lease,
1505 client_state,
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,
1510 client_state,
1511 in_options, cfg_options, scope,
1512 expr -> data.concat [1], MDL);
1513
1514 if (s0 && s1) {
1515 result -> len = data.len + other.len;
1516 if (!buffer_allocate (&result -> buffer,
1517 (result -> len + other.terminated),
1518 file, line)) {
1519 log_error ("data: concat: no memory");
1520 result -> len = 0;
1521 data_string_forget (&data, MDL);
1522 data_string_forget (&other, MDL);
1523 return 0;
1524 }
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);
1529 }
1530
1531 if (s0)
1532 data_string_forget (&data, MDL);
1533 if (s1)
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",
1539 ((s0 && s1)
1540 ? print_hex_3 (result -> len, result -> data, 30)
1541 : "NULL"));
1542 #endif
1543 return s0 && s1;
1544
1545 case expr_encode_int8:
1546 s0 = evaluate_numeric_expression (&len, packet, lease,
1547 client_state,
1548 in_options, cfg_options,
1549 scope,
1550 expr -> data.encode_int);
1551 if (s0) {
1552 result -> len = 1;
1553 if (!buffer_allocate (&result -> buffer,
1554 1, file, line)) {
1555 log_error ("data: encode_int8: no memory");
1556 result -> len = 0;
1557 s0 = 0;
1558 } else {
1559 result -> data = &result -> buffer -> data [0];
1560 result -> buffer -> data [0] = len;
1561 }
1562 } else
1563 result -> len = 0;
1564
1565 #if defined (DEBUG_EXPRESSIONS)
1566 if (!s0)
1567 log_debug ("data: encode_int8 (NULL) = NULL");
1568 else
1569 log_debug ("data: encode_int8 (%ld) = %s", len,
1570 print_hex_2 (result -> len,
1571 result -> data, 20));
1572 #endif
1573 return s0;
1574
1575
1576 case expr_encode_int16:
1577 s0 = evaluate_numeric_expression (&len, packet, lease,
1578 client_state,
1579 in_options, cfg_options,
1580 scope,
1581 expr -> data.encode_int);
1582 if (s0) {
1583 result -> len = 2;
1584 if (!buffer_allocate (&result -> buffer, 2,
1585 file, line)) {
1586 log_error ("data: encode_int16: no memory");
1587 result -> len = 0;
1588 s0 = 0;
1589 } else {
1590 result -> data = &result -> buffer -> data [0];
1591 putUShort (result -> buffer -> data, len);
1592 }
1593 } else
1594 result -> len = 0;
1595
1596 #if defined (DEBUG_EXPRESSIONS)
1597 if (!s0)
1598 log_debug ("data: encode_int16 (NULL) = NULL");
1599 else
1600 log_debug ("data: encode_int16 (%ld) = %s", len,
1601 print_hex_2 (result -> len,
1602 result -> data, 20));
1603 #endif
1604 return s0;
1605
1606 case expr_encode_int32:
1607 s0 = evaluate_numeric_expression (&len, packet, lease,
1608 client_state,
1609 in_options, cfg_options,
1610 scope,
1611 expr -> data.encode_int);
1612 if (s0) {
1613 result -> len = 4;
1614 if (!buffer_allocate (&result -> buffer, 4,
1615 file, line)) {
1616 log_error ("data: encode_int32: no memory");
1617 result -> len = 0;
1618 s0 = 0;
1619 } else {
1620 result -> data = &result -> buffer -> data [0];
1621 putULong (result -> buffer -> data, len);
1622 }
1623 } else
1624 result -> len = 0;
1625
1626 #if defined (DEBUG_EXPRESSIONS)
1627 if (!s0)
1628 log_debug ("data: encode_int32 (NULL) = NULL");
1629 else
1630 log_debug ("data: encode_int32 (%ld) = %s", len,
1631 print_hex_2 (result -> len,
1632 result -> data, 20));
1633 #endif
1634 return s0;
1635
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,
1642 client_state,
1643 in_options, cfg_options,
1644 scope,
1645 expr -> data.b2a.width);
1646
1647 /* Evaluate the separator string. */
1648 memset (&data, 0, sizeof data);
1649 s2 = evaluate_data_expression (&data, packet, lease,
1650 client_state,
1651 in_options, cfg_options, scope,
1652 expr -> data.b2a.separator,
1653 MDL);
1654
1655 /* Evaluate the data to be converted. */
1656 memset (&other, 0, sizeof other);
1657 s3 = evaluate_data_expression (&other, packet, lease,
1658 client_state,
1659 in_options, cfg_options, scope,
1660 expr -> data.b2a.buffer, MDL);
1661
1662 if (s0 && s1 && s2 && s3) {
1663 unsigned buflen, i;
1664
1665 if (len != 8 && len != 16 && len != 32) {
1666 log_info ("binary_to_ascii: %s %ld!",
1667 "invalid width", len);
1668 status = 0;
1669 goto b2a_out;
1670 }
1671 len /= 8;
1672
1673 /* The buffer must be a multiple of the number's
1674 width. */
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);
1679 status = 0;
1680 goto b2a_out;
1681 }
1682
1683 /* Count the width of the output. */
1684 buflen = 0;
1685 for (i = 0; i < other.len; i += len) {
1686 if (len == 1) {
1687 if (offset == 8) {
1688 if (other.data [i] < 8)
1689 buflen++;
1690 else if (other.data [i] < 64)
1691 buflen += 2;
1692 else
1693 buflen += 3;
1694 } else if (offset == 10) {
1695 if (other.data [i] < 10)
1696 buflen++;
1697 else if (other.data [i] < 100)
1698 buflen += 2;
1699 else
1700 buflen += 3;
1701 } else if (offset == 16) {
1702 if (other.data [i] < 16)
1703 buflen++;
1704 else
1705 buflen += 2;
1706 } else
1707 buflen += (converted_length
1708 (&other.data [i],
1709 offset, 1));
1710 } else
1711 buflen += (converted_length
1712 (&other.data [i],
1713 offset, len));
1714 if (i + len != other.len)
1715 buflen += data.len;
1716 }
1717
1718 if (!buffer_allocate (&result -> buffer,
1719 buflen + 1, file, line)) {
1720 log_error ("data: binary-to-ascii: no memory");
1721 status = 0;
1722 goto b2a_out;
1723 }
1724 result -> data = &result -> buffer -> data [0];
1725 result -> len = buflen;
1726 result -> terminated = 1;
1727
1728 buflen = 0;
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) {
1734 memcpy (&result ->
1735 buffer -> data [buflen],
1736 data.data, data.len);
1737 buflen += data.len;
1738 }
1739 }
1740 /* NUL terminate. */
1741 result -> buffer -> data [buflen] = 0;
1742 status = 1;
1743 } else
1744 status = 0;
1745
1746 b2a_out:
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)
1754 : "NULL"));
1755 #endif
1756 if (s2)
1757 data_string_forget (&data, MDL);
1758 if (s3)
1759 data_string_forget (&other, MDL);
1760 if (status)
1761 return 1;
1762 return 0;
1763
1764 case expr_reverse:
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);
1769
1770 /* Evaluate the data. */
1771 memset (&data, 0, sizeof data);
1772 s1 = evaluate_data_expression (&data, packet, lease,
1773 client_state,
1774 in_options, cfg_options, scope,
1775 expr -> data.reverse.buffer,
1776 MDL);
1777
1778 if (s0 && s1) {
1779 int i;
1780
1781 /* The buffer must be a multiple of the number's
1782 width. */
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);
1787 status = 0;
1788 goto reverse_out;
1789 }
1790
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");
1795 status = 0;
1796 goto reverse_out;
1797 }
1798 result -> data = &result -> buffer -> data [0];
1799 result -> len = data.len;
1800 result -> terminated = 0;
1801
1802 for (i = 0; i < data.len; i += len) {
1803 memcpy (&result -> buffer -> data [i],
1804 &data.data [data.len - i - len], len);
1805 }
1806 status = 1;
1807 } else
1808 status = 0;
1809
1810 reverse_out:
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)
1816 : "NULL"));
1817 #endif
1818 if (s0)
1819 data_string_forget (&data, MDL);
1820 if (status)
1821 return 1;
1822 return 0;
1823
1824 case expr_leased_address:
1825 if (!lease) {
1826 log_debug("data: \"leased-address\" configuration "
1827 "directive: there is no lease associated "
1828 "with this client.");
1829 return 0;
1830 }
1831 result -> len = lease -> ip_addr.len;
1832 if (buffer_allocate (&result -> buffer, result -> len,
1833 file, line)) {
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;
1838 } else {
1839 log_error ("data: leased-address: no memory.");
1840 return 0;
1841 }
1842 #if defined (DEBUG_EXPRESSIONS)
1843 log_debug ("data: leased-address = %s",
1844 print_hex_1 (result -> len, result -> data, 60));
1845 #endif
1846 return 1;
1847
1848 case expr_pick_first_value:
1849 memset (&data, 0, sizeof data);
1850 if ((evaluate_data_expression
1851 (result, packet,
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));
1858 #endif
1859 return 1;
1860 }
1861
1862 if (expr -> data.pick_first_value.cdr &&
1863 (evaluate_data_expression
1864 (result, packet,
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));
1871 #endif
1872 return 1;
1873 }
1874
1875 #if defined (DEBUG_EXPRESSIONS)
1876 log_debug ("data: pick_first_value (NULL, NULL) = NULL");
1877 #endif
1878 return 0;
1879
1880 case expr_host_decl_name:
1881 if (!lease || !lease -> host) {
1882 log_error ("data: host_decl_name: not available");
1883 return 0;
1884 }
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;
1892 } else {
1893 log_error ("data: host-decl-name: no memory.");
1894 return 0;
1895 }
1896 #if defined (DEBUG_EXPRESSIONS)
1897 log_debug ("data: host-decl-name = %s", lease -> host -> name);
1898 #endif
1899 return 1;
1900
1901 case expr_null:
1902 #if defined (DEBUG_EXPRESSIONS)
1903 log_debug ("data: null = NULL");
1904 #endif
1905 return 0;
1906
1907 case expr_variable_reference:
1908 if (scope && *scope) {
1909 binding = find_binding (*scope, expr -> data.variable);
1910
1911 if (binding && binding -> value) {
1912 if (binding -> value -> type == binding_data) {
1913 data_string_copy (result,
1914 &binding -> value -> value.data,
1915 file, line);
1916 s0 = 1;
1917 } else if (binding -> value -> type != binding_data) {
1918 log_error ("binding type %d in %s.",
1919 binding -> value -> type,
1920 "evaluate_data_expression");
1921 s0 = 0;
1922 } else
1923 s0 = 0;
1924 } else
1925 s0 = 0;
1926 } else
1927 s0 = 0;
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");
1932 #endif
1933 return s0;
1934
1935 case expr_funcall:
1936 bv = (struct binding_value *)0;
1937 s0 = evaluate_expression (&bv, packet, lease, client_state,
1938 in_options, cfg_options,
1939 scope, expr, MDL);
1940 if (s0) {
1941 if (bv -> type != binding_data)
1942 log_error ("%s() returned type %d in %s.",
1943 expr -> data.funcall.name,
1944 bv -> type,
1945 "evaluate_data_expression");
1946 else
1947 data_string_copy (result, &bv -> value.data,
1948 file, line);
1949 binding_value_dereference (&bv, MDL);
1950 }
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");
1955 #endif
1956 break;
1957
1958 /* Extract the filename. */
1959 case expr_filename:
1960 if (packet && packet -> raw -> file [0]) {
1961 char *fn =
1962 memchr (packet -> raw -> file, 0,
1963 sizeof packet -> raw -> file);
1964 if (!fn)
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,
1973 result -> len);
1974 result -> buffer -> data [result -> len] = 0;
1975 result -> terminated = 1;
1976 s0 = 1;
1977 } else {
1978 log_error ("data: filename: no memory.");
1979 s0 = 0;
1980 }
1981 } else
1982 s0 = 0;
1983
1984 #if defined (DEBUG_EXPRESSIONS)
1985 log_info ("data: filename = \"%s\"",
1986 s0 ? (const char *)(result -> data) : "NULL");
1987 #endif
1988 return s0;
1989
1990 /* Extract the server name. */
1991 case expr_sname:
1992 if (packet && packet -> raw -> sname [0]) {
1993 char *fn =
1994 memchr (packet -> raw -> sname, 0,
1995 sizeof packet -> raw -> sname);
1996 if (!fn)
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,
2005 result -> len);
2006 result -> buffer -> data [result -> len] = 0;
2007 result -> terminated = 1;
2008 s0 = 1;
2009 } else {
2010 log_error ("data: sname: no memory.");
2011 s0 = 0;
2012 }
2013 } else
2014 s0 = 0;
2015
2016 #if defined (DEBUG_EXPRESSIONS)
2017 log_info ("data: sname = \"%s\"",
2018 s0 ? (const char *)(result -> data) : "NULL");
2019 #endif
2020 return s0;
2021
2022 /* Provide the system's local hostname as a return value. */
2023 case expr_gethostname:
2024 /*
2025 * Allocate a buffer to return.
2026 *
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).
2030 */
2031 memset(result, 0, sizeof(*result));
2032 if (!buffer_allocate(&result->buffer, 255, file, line)) {
2033 log_error("data: gethostname(): no memory for buffer");
2034 return 0;
2035 }
2036 result->data = result->buffer->data;
2037
2038 /*
2039 * On successful completion, gethostname() resturns 0. It may
2040 * not null-terminate the string if there was insufficient
2041 * space.
2042 */
2043 if (!gethostname((char *)result->buffer->data, 255)) {
2044 if (result->buffer->data[255] == '\0')
2045 result->len =
2046 strlen((char *)result->buffer->data);
2047 else
2048 result->len = 255;
2049 return 1;
2050 }
2051
2052 data_string_forget(result, MDL);
2053 return 0;
2054
2055 /* Find an option within a v6relay context
2056 *
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.
2065 *
2066 * The data expression in roption is evaluated in that
2067 * context and the result returned.
2068 */
2069 case expr_v6relay:
2070 len = 0;
2071 s1 = 0;
2072 memset (&data, 0, sizeof data);
2073
2074 /* Evaluate the relay count */
2075 s0 = evaluate_numeric_expression(&len, packet, lease,
2076 client_state,
2077 in_options, cfg_options,
2078 scope,
2079 expr->data.v6relay.relay);
2080
2081 /* no number or an obviously invalid number */
2082 if ((s0 == 0) ||
2083 ((len > 0) &&
2084 ((packet == NULL) ||
2085 (packet->dhcpv6_container_packet == NULL)))) {
2086 #if defined (DEBUG_EXPRESSIONS)
2087 log_debug("data: v6relay(%lu) = NULL", len);
2088 #endif
2089 return (0);
2090 }
2091
2092 /* Find the correct packet for the requested relay */
2093 i = len;
2094 relay_packet = packet;
2095 relay_options = in_options;
2096 while ((i != 0) &&
2097 (relay_packet->dhcpv6_container_packet != NULL)) {
2098 relay_packet = relay_packet->dhcpv6_container_packet;
2099 relay_options = relay_packet->options;
2100 i--;
2101 }
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);
2106 #endif
2107 return (0);
2108 }
2109
2110 s1 = evaluate_data_expression(&data, relay_packet, lease,
2111 client_state, relay_options,
2112 cfg_options, scope,
2113 expr->data.v6relay.roption,
2114 MDL);
2115
2116 if (s1) {
2117 data_string_copy(result, &data, file, line);
2118 data_string_forget(&data, MDL);
2119 }
2120
2121 #if defined (DEBUG_EXPRESSIONS)
2122 log_debug("data: v6relay(%lu) = %s", len,
2123 s1 ? print_hex_3(result->len, result->data, 30)
2124 : "NULL");
2125 #endif
2126 return (s1);
2127
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);
2133 int outcome = 0;
2134 s0 = evaluate_data_expression(&data, packet, lease,
2135 client_state,
2136 in_options, cfg_options, scope,
2137 expr->data.concat[0], MDL);
2138
2139 memset (&other, 0, sizeof other);
2140 s1 = evaluate_data_expression (&other, packet, lease,
2141 client_state,
2142 in_options, cfg_options, scope,
2143 expr->data.concat[1], MDL);
2144
2145 if (s0 && s1) {
2146 outcome = concat_dclists(result, &data, &other);
2147 if (outcome == 0) {
2148 log_error ("data: concat_dclist failed");
2149 }
2150 }
2151
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)
2155 : "NULL"),
2156 (s1 ? print_hex_2(other.len, other.data, other.len)
2157 : "NULL"),
2158 (((s0 && s1) && result->len > 0)
2159 ? print_hex_3 (result->len, result->data, result->len)
2160 : "NULL"));
2161 #endif
2162 if (s0)
2163 data_string_forget (&data, MDL);
2164
2165 if (s1)
2166 data_string_forget (&other, MDL);
2167
2168 return (outcome);
2169 } /* expr_concat_dclist */
2170
2171 case expr_check:
2172 case expr_equal:
2173 case expr_not_equal:
2174 case expr_regex_match:
2175 case expr_iregex_match:
2176 case expr_and:
2177 case expr_or:
2178 case expr_not:
2179 case expr_match:
2180 case expr_static:
2181 case expr_known:
2182 case expr_none:
2183 case expr_exists:
2184 case expr_variable_exists:
2185 log_error ("Boolean opcode in evaluate_data_expression: %d",
2186 expr -> op);
2187 return 0;
2188
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:
2195 case expr_add:
2196 case expr_subtract:
2197 case expr_multiply:
2198 case expr_divide:
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",
2205 expr -> op);
2206 return 0;
2207
2208 case expr_ns_add:
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",
2213 expr -> op);
2214 return 0;
2215
2216 case expr_function:
2217 log_error ("function definition in evaluate_data_expression");
2218 return 0;
2219
2220 case expr_arg:
2221 break;
2222
2223 }
2224
2225 log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op);
2226 return 0;
2227 }
2228
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;
2239 {
2240 struct data_string data;
2241 int status, sleft, sright;
2242
2243 struct binding *binding;
2244 struct binding_value *bv;
2245 unsigned long ileft, iright;
2246 int rc = 0;
2247
2248 switch (expr -> op) {
2249 case expr_check:
2250 case expr_equal:
2251 case expr_not_equal:
2252 case expr_regex_match:
2253 case expr_iregex_match:
2254 case expr_and:
2255 case expr_or:
2256 case expr_not:
2257 case expr_match:
2258 case expr_static:
2259 case expr_known:
2260 case expr_none:
2261 case expr_exists:
2262 case expr_variable_exists:
2263 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
2264 expr -> op);
2265 return 0;
2266
2267 case expr_substring:
2268 case expr_suffix:
2269 case expr_lcase:
2270 case expr_ucase:
2271 case expr_option:
2272 case expr_hardware:
2273 case expr_const_data:
2274 case expr_packet:
2275 case expr_concat:
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:
2282 case expr_reverse:
2283 case expr_filename:
2284 case expr_sname:
2285 case expr_pick_first_value:
2286 case expr_host_decl_name:
2287 case expr_config_option:
2288 case expr_leased_address:
2289 case expr_null:
2290 case expr_gethostname:
2291 case expr_v6relay:
2292 log_error ("Data opcode in evaluate_numeric_expression: %d",
2293 expr -> op);
2294 return 0;
2295
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);
2301 if (status)
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" );
2307 #endif
2308 if (status) data_string_forget (&data, MDL);
2309 return status;
2310
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);
2318 rc = 1;
2319 }
2320 #if defined (DEBUG_EXPRESSIONS)
2321 if (rc == 1) {
2322 log_debug("num: extract_int16 (%s) = %ld",
2323 print_hex_1(data.len, data.data, 60),
2324 *result);
2325 } else {
2326 log_debug("num: extract_int16 (NULL) = NULL");
2327 }
2328 #endif
2329 if (status)
2330 data_string_forget(&data, MDL);
2331
2332 return (rc);
2333
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);
2341 rc = 1;
2342 }
2343 #if defined (DEBUG_EXPRESSIONS)
2344 if (rc == 1) {
2345 log_debug ("num: extract_int32 (%s) = %ld",
2346 print_hex_1 (data.len, data.data, 60),
2347 *result);
2348 } else {
2349 log_debug ("num: extract_int32 (NULL) = NULL");
2350 }
2351 #endif
2352 if (status) data_string_forget (&data, MDL);
2353 return (rc);
2354
2355 case expr_const_int:
2356 *result = expr -> data.const_int;
2357 #if defined (DEBUG_EXPRESSIONS)
2358 log_debug ("number: CONSTANT = %ld", *result);
2359 #endif
2360 return 1;
2361
2362 case expr_lease_time:
2363 if (!lease) {
2364 log_error("data: leased_lease: not available");
2365 return (0);
2366 }
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);
2371 return (0);
2372 }
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);
2378 #endif
2379 return (1);
2380
2381 case expr_variable_reference:
2382 if (scope && *scope) {
2383 binding = find_binding (*scope, expr -> data.variable);
2384
2385 if (binding && binding -> value) {
2386 if (binding -> value -> type == binding_numeric) {
2387 *result = binding -> value -> value.intval;
2388 status = 1;
2389 } else {
2390 log_error ("binding type %d in %s.",
2391 binding -> value -> type,
2392 "evaluate_numeric_expression");
2393 status = 0;
2394 }
2395 } else
2396 status = 0;
2397 } else
2398 status = 0;
2399 #if defined (DEBUG_EXPRESSIONS)
2400 if (status)
2401 log_debug ("numeric: %s = %ld",
2402 expr -> data.variable, *result);
2403 else
2404 log_debug ("numeric: %s = NULL",
2405 expr -> data.variable);
2406 #endif
2407 return status;
2408
2409 case expr_funcall:
2410 bv = (struct binding_value *)0;
2411 status = evaluate_expression (&bv, packet, lease,
2412 client_state,
2413 in_options, cfg_options,
2414 scope, expr, MDL);
2415 if (status) {
2416 if (bv -> type != binding_numeric)
2417 log_error ("%s() returned type %d in %s.",
2418 expr -> data.funcall.name,
2419 bv -> type,
2420 "evaluate_numeric_expression");
2421 else
2422 *result = bv -> value.intval;
2423 binding_value_dereference (&bv, MDL);
2424 }
2425 #if defined (DEBUG_EXPRESSIONS)
2426 log_debug ("data: %s = %ld", expr -> data.funcall.name,
2427 status ? *result : 0);
2428 #endif
2429 break;
2430
2431 case expr_add:
2432 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2433 client_state,
2434 in_options, cfg_options,
2435 scope,
2436 expr -> data.and [0]);
2437 sright = evaluate_numeric_expression (&iright, packet, lease,
2438 client_state,
2439 in_options, cfg_options,
2440 scope,
2441 expr -> data.and [1]);
2442
2443 #if defined (DEBUG_EXPRESSIONS)
2444 if (sleft && sright)
2445 log_debug ("num: %ld + %ld = %ld",
2446 ileft, iright, ileft + iright);
2447 else if (sleft)
2448 log_debug ("num: %ld + NULL = NULL", ileft);
2449 else
2450 log_debug ("num: NULL + %ld = NULL", iright);
2451 #endif
2452 if (sleft && sright) {
2453 *result = ileft + iright;
2454 return 1;
2455 }
2456 return 0;
2457
2458 case expr_subtract:
2459 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2460 client_state,
2461 in_options, cfg_options,
2462 scope,
2463 expr -> data.and [0]);
2464 sright = evaluate_numeric_expression (&iright, packet, lease,
2465 client_state,
2466 in_options, cfg_options,
2467 scope,
2468 expr -> data.and [1]);
2469
2470 #if defined (DEBUG_EXPRESSIONS)
2471 if (sleft && sright)
2472 log_debug ("num: %ld - %ld = %ld",
2473 ileft, iright, ileft - iright);
2474 else if (sleft)
2475 log_debug ("num: %ld - NULL = NULL", ileft);
2476 else
2477 log_debug ("num: NULL - %ld = NULL", iright);
2478 #endif
2479 if (sleft && sright) {
2480 *result = ileft - iright;
2481 return 1;
2482 }
2483 return 0;
2484
2485 case expr_multiply:
2486 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2487 client_state,
2488 in_options, cfg_options,
2489 scope,
2490 expr -> data.and [0]);
2491 sright = evaluate_numeric_expression (&iright, packet, lease,
2492 client_state,
2493 in_options, cfg_options,
2494 scope,
2495 expr -> data.and [1]);
2496
2497 #if defined (DEBUG_EXPRESSIONS)
2498 if (sleft && sright)
2499 log_debug ("num: %ld * %ld = %ld",
2500 ileft, iright, ileft * iright);
2501 else if (sleft)
2502 log_debug ("num: %ld * NULL = NULL", ileft);
2503 else
2504 log_debug ("num: NULL * %ld = NULL", iright);
2505 #endif
2506 if (sleft && sright) {
2507 *result = ileft * iright;
2508 return 1;
2509 }
2510 return 0;
2511
2512 case expr_divide:
2513 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2514 client_state,
2515 in_options, cfg_options,
2516 scope,
2517 expr -> data.and [0]);
2518 sright = evaluate_numeric_expression (&iright, packet, lease,
2519 client_state,
2520 in_options, cfg_options,
2521 scope,
2522 expr -> data.and [1]);
2523
2524 #if defined (DEBUG_EXPRESSIONS)
2525 if (sleft && sright) {
2526 if (iright != 0)
2527 log_debug ("num: %ld / %ld = %ld",
2528 ileft, iright, ileft / iright);
2529 else
2530 log_debug ("num: %ld / %ld = NULL",
2531 ileft, iright);
2532 } else if (sleft)
2533 log_debug ("num: %ld / NULL = NULL", ileft);
2534 else
2535 log_debug ("num: NULL / %ld = NULL", iright);
2536 #endif
2537 if (sleft && sright && iright) {
2538 *result = ileft / iright;
2539 return 1;
2540 }
2541 return 0;
2542
2543 case expr_remainder:
2544 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2545 client_state,
2546 in_options, cfg_options,
2547 scope,
2548 expr -> data.and [0]);
2549 sright = evaluate_numeric_expression (&iright, packet, lease,
2550 client_state,
2551 in_options, cfg_options,
2552 scope,
2553 expr -> data.and [1]);
2554
2555 #if defined (DEBUG_EXPRESSIONS)
2556 if (sleft && sright) {
2557 if (iright != 0)
2558 log_debug ("num: %ld %% %ld = %ld",
2559 ileft, iright, ileft % iright);
2560 else
2561 log_debug ("num: %ld %% %ld = NULL",
2562 ileft, iright);
2563 } else if (sleft)
2564 log_debug ("num: %ld %% NULL = NULL", ileft);
2565 else
2566 log_debug ("num: NULL %% %ld = NULL", iright);
2567 #endif
2568 if (sleft && sright && iright) {
2569 *result = ileft % iright;
2570 return 1;
2571 }
2572 return 0;
2573
2574 case expr_binary_and:
2575 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2576 client_state,
2577 in_options, cfg_options,
2578 scope,
2579 expr -> data.and [0]);
2580 sright = evaluate_numeric_expression (&iright, packet, lease,
2581 client_state,
2582 in_options, cfg_options,
2583 scope,
2584 expr -> data.and [1]);
2585
2586 #if defined (DEBUG_EXPRESSIONS)
2587 if (sleft && sright)
2588 log_debug ("num: %ld | %ld = %ld",
2589 ileft, iright, ileft & iright);
2590 else if (sleft)
2591 log_debug ("num: %ld & NULL = NULL", ileft);
2592 else
2593 log_debug ("num: NULL & %ld = NULL", iright);
2594 #endif
2595 if (sleft && sright) {
2596 *result = ileft & iright;
2597 return 1;
2598 }
2599 return 0;
2600
2601 case expr_binary_or:
2602 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2603 client_state,
2604 in_options, cfg_options,
2605 scope,
2606 expr -> data.and [0]);
2607 sright = evaluate_numeric_expression (&iright, packet, lease,
2608 client_state,
2609 in_options, cfg_options,
2610 scope,
2611 expr -> data.and [1]);
2612
2613 #if defined (DEBUG_EXPRESSIONS)
2614 if (sleft && sright)
2615 log_debug ("num: %ld | %ld = %ld",
2616 ileft, iright, ileft | iright);
2617 else if (sleft)
2618 log_debug ("num: %ld | NULL = NULL", ileft);
2619 else
2620 log_debug ("num: NULL | %ld = NULL", iright);
2621 #endif
2622 if (sleft && sright) {
2623 *result = ileft | iright;
2624 return 1;
2625 }
2626 return 0;
2627
2628 case expr_binary_xor:
2629 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2630 client_state,
2631 in_options, cfg_options,
2632 scope,
2633 expr -> data.and [0]);
2634 sright = evaluate_numeric_expression (&iright, packet, lease,
2635 client_state,
2636 in_options, cfg_options,
2637 scope,
2638 expr -> data.and [1]);
2639
2640 #if defined (DEBUG_EXPRESSIONS)
2641 if (sleft && sright)
2642 log_debug ("num: %ld ^ %ld = %ld",
2643 ileft, iright, ileft ^ iright);
2644 else if (sleft)
2645 log_debug ("num: %ld ^ NULL = NULL", ileft);
2646 else
2647 log_debug ("num: NULL ^ %ld = NULL", iright);
2648 #endif
2649 if (sleft && sright) {
2650 *result = ileft ^ iright;
2651 return 1;
2652 }
2653 return 0;
2654
2655 case expr_client_state:
2656 if (client_state) {
2657 #if defined (DEBUG_EXPRESSIONS)
2658 log_debug ("num: client-state = %d",
2659 client_state -> state);
2660 #endif
2661 *result = client_state -> state;
2662 return 1;
2663 } else {
2664 #if defined (DEBUG_EXPRESSIONS)
2665 log_debug ("num: client-state = NULL");
2666 #endif
2667 return 0;
2668 }
2669
2670 case expr_function:
2671 log_error ("function definition in evaluate_numeric_expr");
2672 return 0;
2673
2674 case expr_arg:
2675 break;
2676
2677 default:
2678 log_fatal("Impossible case at %s:%d. Undefined operator "
2679 "%d.", MDL, expr->op);
2680 break;
2681 }
2682
2683 log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op);
2684 return 0;
2685 }
2686
2687 /*
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.
2692 *
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
2696 * be modified
2697 */
2698
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;
2709 const char *file;
2710 int line;
2711 {
2712 if (oc->data.data != NULL) {
2713 data_string_copy (result, &oc -> data, file, line);
2714 return 1;
2715 }
2716 if (!oc -> expression)
2717 return 0;
2718 return evaluate_data_expression (result, packet, lease, client_state,
2719 in_options, cfg_options, scope,
2720 oc -> expression, file, line);
2721 }
2722
2723 /* Evaluate an option cache and extract a boolean from the result.
2724 * The boolean option cache is actually a trinary value where:
2725 *
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
2729 *
2730 * This supports both classic boolean flags on/off as well as the
2731 * allow/deny/ignore keywords
2732 */
2733 int evaluate_boolean_option_cache (ignorep, packet,
2734 lease, client_state, in_options,
2735 cfg_options, scope, oc, file, line)
2736 int *ignorep;
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;
2744 const char *file;
2745 int line;
2746 {
2747 int result = 0;
2748 if (ignorep)
2749 *ignorep = 0;
2750
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;
2755
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,
2760 line)) {
2761 /* We have a value for the option set result and
2762 * ignore parameter accordingly. */
2763 if (ds.len) {
2764 if (ds.data[0] == 1)
2765 result = 1;
2766 else if ((ds.data[0] == 2) && (ignorep != NULL))
2767 *ignorep = 1;
2768 }
2769
2770 data_string_forget(&ds, MDL);
2771 }
2772 }
2773
2774 return (result);
2775 }
2776
2777 /* Evaluate a boolean expression and return the result of the evaluation,
2778 or FALSE if it failed. */
2779
2780 int evaluate_boolean_expression_result (ignorep, packet, lease, client_state,
2781 in_options, cfg_options, scope, expr)
2782 int *ignorep;
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;
2790 {
2791 int result;
2792
2793 /* So that we can be called with option_lookup as an argument. */
2794 if (!expr)
2795 return 0;
2796
2797 if (!evaluate_boolean_expression (&result, packet, lease, client_state,
2798 in_options, cfg_options,
2799 scope, expr))
2800 return 0;
2801
2802 if (result == 2) {
2803 *ignorep = 1;
2804 result = 0;
2805 } else
2806 *ignorep = 0;
2807 return result;
2808 }
2809
2810
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;
2815 const char *file;
2816 int line;
2817 {
2818 struct expression *expr = *eptr;
2819
2820 /* Zero the pointer. */
2821 *eptr = (struct expression *)0;
2822
2823 /* Decrement the reference count. If it's nonzero, we're
2824 done. */
2825 --(expr -> refcnt);
2826 rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC);
2827 if (expr -> refcnt > 0)
2828 return;
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);
2833 #endif
2834 #if defined (POINTER_DEBUG)
2835 abort ();
2836 #else
2837 return;
2838 #endif
2839 }
2840
2841 /* Dereference subexpressions. */
2842 switch (expr -> op) {
2843 /* All the binary operators can be handled the same way. */
2844 case expr_equal:
2845 case expr_not_equal:
2846 case expr_regex_match:
2847 case expr_iregex_match:
2848 case expr_concat:
2849 case expr_and:
2850 case expr_or:
2851 case expr_add:
2852 case expr_subtract:
2853 case expr_multiply:
2854 case expr_divide:
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],
2862 file, line);
2863 if (expr -> data.equal [1])
2864 expression_dereference (&expr -> data.equal [1],
2865 file, line);
2866 break;
2867
2868 case expr_substring:
2869 if (expr -> data.substring.expr)
2870 expression_dereference (&expr -> data.substring.expr,
2871 file, line);
2872 if (expr -> data.substring.offset)
2873 expression_dereference (&expr -> data.substring.offset,
2874 file, line);
2875 if (expr -> data.substring.len)
2876 expression_dereference (&expr -> data.substring.len,
2877 file, line);
2878 break;
2879
2880 case expr_suffix:
2881 if (expr -> data.suffix.expr)
2882 expression_dereference (&expr -> data.suffix.expr,
2883 file, line);
2884 if (expr -> data.suffix.len)
2885 expression_dereference (&expr -> data.suffix.len,
2886 file, line);
2887 break;
2888
2889 case expr_lcase:
2890 if (expr->data.lcase)
2891 expression_dereference(&expr->data.lcase, MDL);
2892 break;
2893
2894 case expr_ucase:
2895 if (expr->data.ucase)
2896 expression_dereference(&expr->data.ucase, MDL);
2897 break;
2898
2899 case expr_not:
2900 if (expr -> data.not)
2901 expression_dereference (&expr -> data.not, file, line);
2902 break;
2903
2904 case expr_packet:
2905 if (expr -> data.packet.offset)
2906 expression_dereference (&expr -> data.packet.offset,
2907 file, line);
2908 if (expr -> data.packet.len)
2909 expression_dereference (&expr -> data.packet.len,
2910 file, line);
2911 break;
2912
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,
2918 file, line);
2919 break;
2920
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,
2926 file, line);
2927 break;
2928
2929 case expr_encapsulate:
2930 case expr_const_data:
2931 data_string_forget (&expr -> data.const_data, file, line);
2932 break;
2933
2934 case expr_host_lookup:
2935 if (expr -> data.host_lookup)
2936 dns_host_entry_dereference (&expr -> data.host_lookup,
2937 file, line);
2938 break;
2939
2940 case expr_binary_to_ascii:
2941 if (expr -> data.b2a.base)
2942 expression_dereference (&expr -> data.b2a.base,
2943 file, line);
2944 if (expr -> data.b2a.width)
2945 expression_dereference (&expr -> data.b2a.width,
2946 file, line);
2947 if (expr -> data.b2a.separator)
2948 expression_dereference (&expr -> data.b2a.separator,
2949 file, line);
2950 if (expr -> data.b2a.buffer)
2951 expression_dereference (&expr -> data.b2a.buffer,
2952 file, line);
2953 break;
2954
2955 case expr_pick_first_value:
2956 if (expr -> data.pick_first_value.car)
2957 expression_dereference (&expr -> data.pick_first_value.car,
2958 file, line);
2959 if (expr -> data.pick_first_value.cdr)
2960 expression_dereference (&expr -> data.pick_first_value.cdr,
2961 file, line);
2962 break;
2963
2964 case expr_reverse:
2965 if (expr -> data.reverse.width)
2966 expression_dereference (&expr -> data.reverse.width,
2967 file, line);
2968 if (expr -> data.reverse.buffer)
2969 expression_dereference
2970 (&expr -> data.reverse.buffer, file, line);
2971 break;
2972
2973 case expr_variable_reference:
2974 case expr_variable_exists:
2975 if (expr -> data.variable)
2976 dfree (expr -> data.variable, file, line);
2977 break;
2978
2979 case expr_funcall:
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,
2984 file, line);
2985 break;
2986
2987 case expr_arg:
2988 if (expr -> data.arg.val)
2989 expression_dereference (&expr -> data.arg.val,
2990 file, line);
2991 if (expr -> data.arg.next)
2992 expression_dereference (&expr -> data.arg.next,
2993 file, line);
2994 break;
2995
2996 case expr_function:
2997 fundef_dereference (&expr -> data.func, file, line);
2998 break;
2999
3000 case expr_v6relay:
3001 if (expr->data.v6relay.relay)
3002 expression_dereference(&expr->data.v6relay.relay,
3003 file, line);
3004
3005 if (expr->data.v6relay.roption)
3006 expression_dereference(&expr->data.v6relay.roption,
3007 file, line);
3008 break;
3009
3010 /* No subexpressions. */
3011 case expr_leased_address:
3012 case expr_lease_time:
3013 case expr_filename:
3014 case expr_sname:
3015 case expr_const_int:
3016 case expr_check:
3017 case expr_option:
3018 case expr_hardware:
3019 case expr_exists:
3020 case expr_known:
3021 case expr_null:
3022 case expr_gethostname:
3023 break;
3024
3025 default:
3026 break;
3027 }
3028 free_expression (expr, MDL);
3029 }
3030
3031 int is_boolean_expression (expr)
3032 struct expression *expr;
3033 {
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);
3046 }
3047
3048 int is_data_expression (expr)
3049 struct expression *expr;
3050 {
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);
3076 }
3077
3078 int is_numeric_expression (expr)
3079 struct expression *expr;
3080 {
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);
3095 }
3096
3097 int is_compound_expression (expr)
3098 struct expression *expr;
3099 {
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);
3115 }
3116
3117 static int op_val (enum expr_op);
3118
3119 static int op_val (op)
3120 enum expr_op op;
3121 {
3122 switch (op) {
3123 case expr_none:
3124 case expr_match:
3125 case expr_static:
3126 case expr_check:
3127 case expr_substring:
3128 case expr_suffix:
3129 case expr_lcase:
3130 case expr_ucase:
3131 case expr_concat:
3132 case expr_encapsulate:
3133 case expr_host_lookup:
3134 case expr_not:
3135 case expr_option:
3136 case expr_hardware:
3137 case expr_packet:
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:
3146 case expr_exists:
3147 case expr_variable_exists:
3148 case expr_known:
3149 case expr_binary_to_ascii:
3150 case expr_reverse:
3151 case expr_filename:
3152 case expr_sname:
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:
3159 case expr_null:
3160 case expr_variable_reference:
3161 case expr_ns_add:
3162 case expr_ns_delete:
3163 case expr_ns_exists:
3164 case expr_ns_not_exists:
3165 case expr_arg:
3166 case expr_funcall:
3167 case expr_function:
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:
3174 case expr_v6relay:
3175 case expr_concat_dclist:
3176 return 100;
3177
3178 case expr_equal:
3179 case expr_not_equal:
3180 case expr_regex_match:
3181 case expr_iregex_match:
3182 return 4;
3183
3184 case expr_or:
3185 case expr_and:
3186 return 3;
3187
3188 case expr_add:
3189 case expr_subtract:
3190 return 2;
3191
3192 case expr_multiply:
3193 case expr_divide:
3194 case expr_remainder:
3195 return 1;
3196 }
3197 return 100;
3198 }
3199
3200 int op_precedence (op1, op2)
3201 enum expr_op op1, op2;
3202 {
3203 return op_val (op1) - op_val (op2);
3204 }
3205
3206 enum expression_context expression_context (struct expression *expr)
3207 {
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;
3214 return context_any;
3215 }
3216
3217 enum expression_context op_context (op)
3218 enum expr_op op;
3219 {
3220 switch (op) {
3221 /* XXX Why aren't these specific? */
3222 case expr_none:
3223 case expr_match:
3224 case expr_static:
3225 case expr_check:
3226 case expr_substring:
3227 case expr_suffix:
3228 case expr_lcase:
3229 case expr_ucase:
3230 case expr_concat:
3231 case expr_encapsulate:
3232 case expr_host_lookup:
3233 case expr_not:
3234 case expr_option:
3235 case expr_hardware:
3236 case expr_packet:
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:
3245 case expr_exists:
3246 case expr_variable_exists:
3247 case expr_known:
3248 case expr_binary_to_ascii:
3249 case expr_reverse:
3250 case expr_filename:
3251 case expr_sname:
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:
3257 case expr_null:
3258 case expr_variable_reference:
3259 case expr_ns_add:
3260 case expr_ns_delete:
3261 case expr_ns_exists:
3262 case expr_ns_not_exists:
3263 case expr_dns_transaction:
3264 case expr_arg:
3265 case expr_funcall:
3266 case expr_function:
3267 case expr_gethostname:
3268 case expr_v6relay:
3269 case expr_concat_dclist:
3270 return context_any;
3271
3272 case expr_equal:
3273 case expr_not_equal:
3274 case expr_regex_match:
3275 case expr_iregex_match:
3276 return context_data;
3277
3278 case expr_and:
3279 return context_boolean;
3280
3281 case expr_or:
3282 return context_boolean;
3283
3284 case expr_add:
3285 case expr_subtract:
3286 case expr_multiply:
3287 case expr_divide:
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;
3294 }
3295 return context_any;
3296 }
3297
3298 int write_expression (file, expr, col, indent, firstp)
3299 FILE *file;
3300 struct expression *expr;
3301 int col;
3302 int indent;
3303 int firstp;
3304 {
3305 struct expression *e;
3306 const char *s;
3307 char obuf [65];
3308 int scol;
3309 int width;
3310
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);
3314 col = indent;
3315 }
3316
3317 switch (expr -> op) {
3318 case expr_none:
3319 col = token_print_indent (file, col, indent, "", "", "null");
3320 break;
3321
3322 case expr_check:
3323 col = token_print_indent (file, col, indent, "", "", "check");
3324 col = token_print_indent_concat (file, col, indent,
3325 " ", "", "\"",
3326 expr -> data.check -> name,
3327 "\"", (char *)0);
3328 break;
3329
3330 case expr_regex_match:
3331 s = "~=";
3332 goto binary;
3333
3334 case expr_iregex_match:
3335 s = "~~";
3336 goto binary;
3337
3338 case expr_not_equal:
3339 s = "!=";
3340 goto binary;
3341
3342 case expr_equal:
3343 s = "=";
3344 binary:
3345 col = write_expression (file, expr -> data.equal [0],
3346 col, indent, 1);
3347 col = token_print_indent (file, col, indent, " ", " ", s);
3348 col = write_expression (file, expr -> data.equal [1],
3349 col, indent + 2, 0);
3350 break;
3351
3352 case expr_substring:
3353 col = token_print_indent (file, col, indent, "", "",
3354 "substring");
3355 col = token_print_indent (file, col, indent, " ", "", "(");
3356 scol = col;
3357 col = write_expression (file, expr -> data.substring.expr,
3358 col, scol, 1);
3359 col = token_print_indent (file, col, indent, "", " ", ",");
3360 col = write_expression (file, expr -> data.substring.offset,
3361 col, indent, 0);
3362 col = token_print_indent (file, col, scol, "", " ", ",");
3363 col = write_expression (file, expr -> data.substring.len,
3364 col, scol, 0);
3365 col = token_print_indent (file, col, indent, "", "", ")");
3366 break;
3367
3368 case expr_suffix:
3369 col = token_print_indent (file, col, indent, "", "", "suffix");
3370 col = token_print_indent (file, col, indent, " ", "", "(");
3371 scol = col;
3372 col = write_expression (file, expr -> data.suffix.expr,
3373 col, scol, 1);
3374 col = token_print_indent (file, col, scol, "", " ", ",");
3375 col = write_expression (file, expr -> data.suffix.len,
3376 col, scol, 0);
3377 col = token_print_indent (file, col, indent, "", "", ")");
3378 break;
3379
3380 case expr_lcase:
3381 col = token_print_indent(file, col, indent, "", "", "lcase");
3382 col = token_print_indent(file, col, indent, " ", "", "(");
3383 scol = col;
3384 col = write_expression(file, expr->data.lcase, col, scol, 1);
3385 col = token_print_indent(file, col, indent, "", "", ")");
3386 break;
3387
3388 case expr_ucase:
3389 col = token_print_indent(file, col, indent, "", "", "ucase");
3390 col = token_print_indent(file, col, indent, " ", "", "(");
3391 scol = col;
3392 col = write_expression(file, expr->data.ucase, col, scol, 1);
3393 col = token_print_indent(file, col, indent, "", "", ")");
3394 break;
3395
3396 case expr_concat:
3397 e = expr;
3398 col = token_print_indent (file, col, indent, "", "",
3399 "concat");
3400 col = token_print_indent (file, col, indent, " ", "", "(");
3401 scol = col;
3402 firstp = 1;
3403 concat_again:
3404 col = write_expression (file, e -> data.concat [0],
3405 col, scol, firstp);
3406 firstp = 0;
3407 if (!e -> data.concat [1])
3408 goto no_concat_cdr;
3409 col = token_print_indent (file, col, scol, "", " ", ",");
3410 if (e -> data.concat [1] -> op == expr_concat) {
3411 e = e -> data.concat [1];
3412 goto concat_again;
3413 }
3414 col = write_expression (file, e -> data.concat [1],
3415 col, scol, 0);
3416 no_concat_cdr:
3417 col = token_print_indent (file, col, indent, "", "", ")");
3418 break;
3419
3420 case expr_host_lookup:
3421 col = token_print_indent (file, col, indent, "", "",
3422 "gethostbyname");
3423 col = token_print_indent (file, col, indent, " ", "", "(");
3424 col = token_print_indent_concat
3425 (file, col, indent, "", "",
3426 "\"", expr -> data.host_lookup -> hostname, "\"",
3427 (char *)0);
3428 col = token_print_indent (file, col, indent, "", "", ")");
3429 break;
3430
3431 case expr_add:
3432 s = "+";
3433 goto binary;
3434
3435 case expr_subtract:
3436 s = "-";
3437 goto binary;
3438
3439 case expr_multiply:
3440 s = "*";
3441 goto binary;
3442
3443 case expr_divide:
3444 s = "/";
3445 goto binary;
3446
3447 case expr_remainder:
3448 s = "%";
3449 goto binary;
3450
3451 case expr_binary_and:
3452 s = "&";
3453 goto binary;
3454
3455 case expr_binary_or:
3456 s = "|";
3457 goto binary;
3458
3459 case expr_binary_xor:
3460 s = "^";
3461 goto binary;
3462
3463 case expr_and:
3464 s = "and";
3465 goto binary;
3466
3467 case expr_or:
3468 s = "or";
3469 goto binary;
3470
3471 case expr_not:
3472 col = token_print_indent (file, col, indent, "", " ", "not");
3473 col = write_expression (file,
3474 expr -> data.not, col, indent + 2, 1);
3475 break;
3476
3477 case expr_option:
3478 s = "option";
3479
3480 print_option_name:
3481 col = token_print_indent (file, col, indent, "", "", s);
3482
3483 if (expr -> data.option -> universe != &dhcp_universe) {
3484 col = token_print_indent (file, col, indent,
3485 " ", "",
3486 (expr -> data.option ->
3487 universe -> name));
3488 col = token_print_indent (file, col, indent, "", "",
3489 ".");
3490 col = token_print_indent (file, col, indent, "", "",
3491 expr -> data.option -> name);
3492 } else {
3493 col = token_print_indent (file, col, indent, " ", "",
3494 expr -> data.option -> name);
3495 }
3496 break;
3497
3498 case expr_hardware:
3499 col = token_print_indent (file, col, indent, "", "",
3500 "hardware");
3501 break;
3502
3503 case expr_packet:
3504 col = token_print_indent (file, col, indent, "", "",
3505 "packet");
3506 col = token_print_indent (file, col, indent, " ", "", "(");
3507 scol = col;
3508 col = write_expression (file, expr -> data.packet.offset,
3509 col, indent, 1);
3510 col = token_print_indent (file, col, scol, "", " ", ",");
3511 col = write_expression (file, expr -> data.packet.len,
3512 col, scol, 0);
3513 col = token_print_indent (file, col, indent, "", "", ")");
3514 break;
3515
3516 case expr_const_data:
3517 col = token_indent_data_string (file, col, indent, "", "",
3518 &expr -> data.const_data);
3519 break;
3520
3521 case expr_extract_int8:
3522 width = 8;
3523 extract_int:
3524 col = token_print_indent (file, col, indent, "", "",
3525 "extract-int");
3526 col = token_print_indent (file, col, indent, " ", "", "(");
3527 scol = col;
3528 col = write_expression (file, expr -> data.extract_int,
3529 col, indent, 1);
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, "", "", ")");
3534 break;
3535
3536 case expr_extract_int16:
3537 width = 16;
3538 goto extract_int;
3539
3540 case expr_extract_int32:
3541 width = 32;
3542 goto extract_int;
3543
3544 case expr_encode_int8:
3545 width = 8;
3546 encode_int:
3547 col = token_print_indent (file, col, indent, "", "",
3548 "encode-int");
3549 col = token_print_indent (file, col, indent, " ", "", "(");
3550 scol = col;
3551 col = write_expression (file, expr -> data.extract_int,
3552 col, indent, 1);
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, "", "",
3557 ")");
3558 break;
3559
3560 case expr_encode_int16:
3561 width = 16;
3562 goto encode_int;
3563
3564 case expr_encode_int32:
3565 width = 32;
3566 goto encode_int;
3567
3568 case expr_const_int:
3569 sprintf (obuf, "%lu", expr -> data.const_int);
3570 col = token_print_indent (file, col, indent, "", "", obuf);
3571 break;
3572
3573 case expr_exists:
3574 s = "exists";
3575 goto print_option_name;
3576
3577 case expr_encapsulate:
3578 col = token_print_indent (file, col, indent, "", "",
3579 "encapsulate");
3580 col = token_indent_data_string (file, col, indent, " ", "",
3581 &expr -> data.encapsulate);
3582 break;
3583
3584 case expr_known:
3585 col = token_print_indent (file, col, indent, "", "", "known");
3586 break;
3587
3588 case expr_reverse:
3589 col = token_print_indent (file, col, indent, "", "",
3590 "reverse");
3591 col = token_print_indent (file, col, indent, " ", "", "(");
3592 scol = col;
3593 col = write_expression (file, expr -> data.reverse.width,
3594 col, scol, 1);
3595 col = token_print_indent (file, col, scol, "", " ", ",");
3596 col = write_expression (file, expr -> data.reverse.buffer,
3597 col, scol, 0);
3598 col = token_print_indent (file, col, indent, "", "",
3599 ")");
3600 break;
3601
3602 case expr_leased_address:
3603 col = token_print_indent (file, col, indent, "", "",
3604 "leased-address");
3605 break;
3606
3607 case expr_client_state:
3608 col = token_print_indent (file, col, indent, "", "",
3609 "client-state");
3610 break;
3611
3612 case expr_binary_to_ascii:
3613 col = token_print_indent (file, col, indent, "", "",
3614 "binary-to-ascii");
3615 col = token_print_indent (file, col, indent, " ", "",
3616 "(");
3617 scol = col;
3618 col = write_expression (file, expr -> data.b2a.base,
3619 col, scol, 1);
3620 col = token_print_indent (file, col, scol, "", " ",
3621 ",");
3622 col = write_expression (file, expr -> data.b2a.width,
3623 col, scol, 0);
3624 col = token_print_indent (file, col, scol, "", " ",
3625 ",");
3626 col = write_expression (file, expr -> data.b2a.separator,
3627 col, scol, 0);
3628 col = token_print_indent (file, col, scol, "", " ",
3629 ",");
3630 col = write_expression (file, expr -> data.b2a.buffer,
3631 col, scol, 0);
3632 col = token_print_indent (file, col, indent, "", "",
3633 ")");
3634 break;
3635
3636 case expr_config_option:
3637 s = "config-option";
3638 goto print_option_name;
3639
3640 case expr_host_decl_name:
3641 col = token_print_indent (file, col, indent, "", "",
3642 "host-decl-name");
3643 break;
3644
3645 case expr_pick_first_value:
3646 e = expr;
3647 col = token_print_indent (file, col, indent, "", "",
3648 "pick-first-value");
3649 col = token_print_indent (file, col, indent, " ", "",
3650 "(");
3651 scol = col;
3652 firstp = 1;
3653 pick_again:
3654 col = write_expression (file,
3655 e -> data.pick_first_value.car,
3656 col, scol, firstp);
3657 firstp = 0;
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)
3665 goto no_pick_cdr;
3666 col = token_print_indent (file, col, scol, "", " ",
3667 ",");
3668 if (e -> data.pick_first_value.cdr -> op ==
3669 expr_pick_first_value) {
3670 e = e -> data.pick_first_value.cdr;
3671 goto pick_again;
3672 }
3673 col = write_expression (file,
3674 e -> data.pick_first_value.cdr,
3675 col, scol, 0);
3676 no_pick_cdr:
3677 col = token_print_indent (file, col, indent, "", "",
3678 ")");
3679 break;
3680
3681 case expr_lease_time:
3682 col = token_print_indent (file, col, indent, "", "",
3683 "lease-time");
3684 break;
3685
3686 case expr_static:
3687 col = token_print_indent (file, col, indent, "", "",
3688 "static");
3689 break;
3690
3691 case expr_null:
3692 col = token_print_indent (file, col, indent, "", "", "null");
3693 break;
3694
3695 case expr_variable_reference:
3696 col = token_print_indent (file, indent, indent, "", "",
3697 expr -> data.variable);
3698 break;
3699
3700 case expr_variable_exists:
3701 col = token_print_indent (file, indent, indent, "", "",
3702 "defined");
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, "", "", ")");
3707 break;
3708
3709 case expr_gethostname:
3710 col = token_print_indent(file, col, indent, "", "",
3711 "gethostname()");
3712 break;
3713
3714 case expr_funcall:
3715 col = token_print_indent(file, indent, indent, "", "",
3716 expr->data.funcall.name);
3717 col = token_print_indent(file, col, indent, " ", "", "(");
3718
3719 firstp = 1;
3720 e = expr->data.funcall.arglist;
3721 while (e != NULL) {
3722 if (!firstp)
3723 col = token_print_indent(file, col, indent,
3724 "", " ", ",");
3725
3726 col = write_expression(file, e->data.arg.val, col,
3727 indent, firstp);
3728 firstp = 0;
3729 e = e->data.arg.next;
3730 }
3731
3732 col = token_print_indent(file, col, indent, "", "", ")");
3733 break;
3734
3735 case expr_v6relay:
3736 col = token_print_indent(file, col, indent, "", "",
3737 "v6relay");
3738 col = token_print_indent(file, col, indent, " ", "", "(");
3739 scol = col;
3740 col = write_expression(file, expr->data.v6relay.relay,
3741 col, scol, 1);
3742 col = token_print_indent (file, col, scol, "", " ", ",");
3743 col = write_expression(file, expr->data.v6relay.roption,
3744 col, scol, 0);
3745 col = token_print_indent(file, col, indent, "", "", ")");
3746 break;
3747
3748 default:
3749 log_fatal ("invalid expression type in print_expression: %d",
3750 expr -> op);
3751 }
3752 return col;
3753 }
3754
3755 struct binding *find_binding (struct binding_scope *scope, const char *name)
3756 {
3757 struct binding *bp;
3758 struct binding_scope *s;
3759
3760 for (s = scope; s; s = s -> outer) {
3761 for (bp = s -> bindings; bp; bp = bp -> next) {
3762 if (!strcasecmp (name, bp -> name)) {
3763 return bp;
3764 }
3765 }
3766 }
3767 return (struct binding *)0;
3768 }
3769
3770 int free_bindings (struct binding_scope *scope, const char *file, int line)
3771 {
3772 struct binding *bp, *next;
3773
3774 for (bp = scope -> bindings; bp; bp = next) {
3775 next = bp -> next;
3776 if (bp -> name)
3777 dfree (bp -> name, file, line);
3778 if (bp -> value)
3779 binding_value_dereference (&bp -> value, file, line);
3780 dfree (bp, file, line);
3781 }
3782 scope -> bindings = (struct binding *)0;
3783 return 1;
3784 }
3785
3786 int binding_scope_dereference (ptr, file, line)
3787 struct binding_scope **ptr;
3788 const char *file;
3789 int line;
3790 {
3791 struct binding_scope *binding_scope;
3792
3793 if (!ptr || !*ptr) {
3794 log_error ("%s(%d): null pointer", file, line);
3795 #if defined (POINTER_DEBUG)
3796 abort ();
3797 #else
3798 return 0;
3799 #endif
3800 }
3801
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)
3808 return 1;
3809
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);
3814 #endif
3815 #if defined (POINTER_DEBUG)
3816 abort ();
3817 #else
3818 return 0;
3819 #endif
3820 }
3821
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);
3826 return 1;
3827 }
3828
3829 int fundef_dereference (ptr, file, line)
3830 struct fundef **ptr;
3831 const char *file;
3832 int line;
3833 {
3834 struct fundef *bp;
3835 struct string_list *sp, *next;
3836
3837 if ((ptr == NULL) || (*ptr == NULL)) {
3838 log_error ("%s(%d): null pointer", file, line);
3839 #if defined (POINTER_DEBUG)
3840 abort ();
3841 #else
3842 return 0;
3843 #endif
3844 }
3845
3846 bp = *ptr;
3847 bp -> refcnt--;
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);
3853 #endif
3854 #if defined (POINTER_DEBUG)
3855 abort ();
3856 #else
3857 return 0;
3858 #endif
3859 }
3860 if (!bp -> refcnt) {
3861 for (sp = bp -> args; sp; sp = next) {
3862 next = sp -> next;
3863 dfree (sp, file, line);
3864 }
3865 if (bp -> statements)
3866 executable_statement_dereference (&bp -> statements,
3867 file, line);
3868 dfree (bp, file, line);
3869 }
3870 *ptr = (struct fundef *)0;
3871 return 1;
3872 }
3873
3874 #if defined (NOTYET) /* Post 3.0 final. */
3875 int data_subexpression_length (int *rv,
3876 struct expression *expr)
3877 {
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) {
3883 (*rv =
3884 (int)expr -> data.substring.len -> data.const_int);
3885 return 1;
3886 }
3887 return 0;
3888
3889 case expr_packet:
3890 case expr_suffix:
3891 if (expr -> data.suffix.len &&
3892 expr -> data.suffix.len -> op == expr_const_int) {
3893 (*rv =
3894 (int)expr -> data.suffix.len -> data.const_int);
3895 return 1;
3896 }
3897 return 0;
3898
3899 case expr_lcase:
3900 return data_subexpression_length(rv, expr->data.lcase);
3901
3902 case expr_ucase:
3903 return data_subexpression_length(rv, expr->data.ucase);
3904
3905 case expr_concat:
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)
3911 return 0;
3912 *rv = llhs + lrhs;
3913 return 1;
3914 break;
3915
3916 case expr_hardware:
3917 return 0;
3918
3919 case expr_const_data:
3920 *rv = expr -> data.const_data.len;
3921 return 2;
3922
3923 case expr_reverse:
3924 return data_subexpression_length (rv,
3925 expr -> data.reverse.buffer);
3926
3927 case expr_leased_address:
3928 case expr_lease_time:
3929 *rv = 4;
3930 return 2;
3931
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)
3938 return 0;
3939 if (llhs > lrhs)
3940 *rv = llhs;
3941 else
3942 *rv = lrhs;
3943 return 1;
3944
3945 case expr_v6relay:
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)
3951 return 0;
3952 *rv = llhs + lrhs;
3953 return 1;
3954 break;
3955
3956 case expr_binary_to_ascii:
3957 case expr_config_option:
3958 case expr_host_decl_name:
3959 case expr_encapsulate:
3960 case expr_filename:
3961 case expr_sname:
3962 case expr_host_lookup:
3963 case expr_option:
3964 case expr_none:
3965 case expr_match:
3966 case expr_check:
3967 case expr_equal:
3968 case expr_regex_match:
3969 case expr_iregex_match:
3970 case expr_and:
3971 case expr_or:
3972 case expr_not:
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:
3980 case expr_exists:
3981 case expr_known:
3982 case expr_static:
3983 case expr_not_equal:
3984 case expr_null:
3985 case expr_variable_exists:
3986 case expr_variable_reference:
3987 case expr_arg:
3988 case expr_funcall:
3989 case expr_function:
3990 case expr_add:
3991 case expr_subtract:
3992 case expr_multiply:
3993 case expr_divide:
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:
4000 return 0;
4001 }
4002 return 0;
4003 }
4004
4005 int expr_valid_for_context (struct expression *expr,
4006 enum expression_context context)
4007 {
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)
4012 return 1;
4013
4014 switch (context) {
4015 case context_any:
4016 return 1;
4017
4018 case context_boolean:
4019 if (is_boolean_expression (expr))
4020 return 1;
4021 return 0;
4022
4023 case context_data:
4024 if (is_data_expression (expr))
4025 return 1;
4026 return 0;
4027
4028 case context_numeric:
4029 if (is_numeric_expression (expr))
4030 return 1;
4031 return 0;
4032
4033 case context_data_or_numeric:
4034 if (is_numeric_expression (expr) ||
4035 is_data_expression (expr)) {
4036 return 1;
4037 }
4038 return 0;
4039
4040 case context_function:
4041 if (expr -> op == expr_function)
4042 return 1;
4043 return 0;
4044 }
4045 return 0;
4046 }
4047 #endif /* NOTYET */
4048
4049 struct binding *create_binding (struct binding_scope **scope, const char *name)
4050 {
4051 struct binding *binding;
4052
4053 if (!*scope) {
4054 if (!binding_scope_allocate (scope, MDL))
4055 return (struct binding *)0;
4056 }
4057
4058 binding = find_binding (*scope, name);
4059 if (!binding) {
4060 binding = dmalloc (sizeof *binding, MDL);
4061 if (!binding)
4062 return (struct binding *)0;
4063
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;
4069 }
4070 strcpy (binding -> name, name);
4071
4072 binding -> next = (*scope) -> bindings;
4073 (*scope) -> bindings = binding;
4074 }
4075
4076 return binding;
4077 }
4078
4079
4080 int bind_ds_value (struct binding_scope **scope,
4081 const char *name,
4082 struct data_string *value)
4083 {
4084 struct binding *binding;
4085
4086 binding = create_binding (scope, name);
4087 if (!binding)
4088 return 0;
4089
4090 if (binding -> value)
4091 binding_value_dereference (&binding -> value, MDL);
4092
4093 if (!binding_value_allocate (&binding -> value, MDL))
4094 return 0;
4095
4096 data_string_copy (&binding -> value -> value.data, value, MDL);
4097 binding -> value -> type = binding_data;
4098
4099 return 1;
4100 }
4101
4102
4103 int find_bound_string (struct data_string *value,
4104 struct binding_scope *scope,
4105 const char *name)
4106 {
4107 struct binding *binding;
4108
4109 binding = find_binding (scope, name);
4110 if (!binding ||
4111 !binding -> value ||
4112 binding -> value -> type != binding_data)
4113 return 0;
4114
4115 if (binding -> value -> value.data.terminated) {
4116 data_string_copy (value, &binding -> value -> value.data, MDL);
4117 } else {
4118 if (buffer_allocate (&value->buffer,
4119 binding->value->value.data.len,
4120 MDL) == 0) {
4121 return 0;
4122 }
4123
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;
4129 }
4130
4131 return 1;
4132 }
4133
4134 int unset (struct binding_scope *scope, const char *name)
4135 {
4136 struct binding *binding;
4137
4138 binding = find_binding (scope, name);
4139 if (binding) {
4140 if (binding -> value)
4141 binding_value_dereference
4142 (&binding -> value, MDL);
4143 return 1;
4144 }
4145 return 0;
4146 }
4147
4148 /*!
4149 * \brief Adds two Dc-formatted lists into a single Dc-formatted list
4150 *
4151 * Given two data_strings containing compressed lists, it constructs a
4152 * third data_string containing a single compressed list:
4153 *
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
4157 *
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.
4161 *
4162 * It relies on two functions to decompress and compress:
4163 *
4164 * - MRns_name_uncompress_list() - produces a null-terminated string of
4165 * comma-separated domain-names from a buffer containing "Dc" formatted
4166 * data
4167 *
4168 * - MRns_name_compress_list() - produces a buffer containing "Dc" formatted
4169 * data from a null-terminated string containing comma-separated domain-names
4170 *
4171 * \param result data_string which will contain the combined list
4172 * in Dc format
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
4176 */
4177 int concat_dclists (struct data_string* result,
4178 struct data_string* list1,
4179 struct data_string* list2)
4180 {
4181 char uncompbuf[32*NS_MAXCDNAME];
4182 char *uncomp = uncompbuf;
4183 int uncomp_len = 0;
4184 int compbuf_max = 0;
4185 int list_len = 0;
4186 int i;
4187
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,
4191 list1->len, uncomp,
4192 sizeof(uncompbuf));
4193 if (list_len < 0) {
4194 log_error ("concat_dclists:"
4195 " error decompressing domain list 1");
4196 return (0);
4197 }
4198
4199 uncomp_len = list_len;
4200 uncomp += list_len;
4201 }
4202
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) {
4207 *uncomp++ = ',';
4208 uncomp_len++;
4209 }
4210
4211 list_len = MRns_name_uncompress_list(list2->data, list2->len,
4212 uncomp, (sizeof(uncompbuf)
4213 - uncomp_len));
4214 if (list_len < 0) {
4215 log_error ("concat_dclists:"
4216 " error decompressing domain list 2");
4217 return (0);
4218 }
4219
4220 uncomp_len += list_len;
4221 uncomp += list_len;
4222 }
4223
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");
4228 result->len = 0;
4229 return (0);
4230 }
4231
4232 result->len = 1;
4233 result->data = result->buffer->data;
4234 return (1);
4235 }
4236
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;
4244 uncomp = uncompbuf;
4245 for (i = 0; i < uncomp_len; i++)
4246 if (*uncomp++ == ',')
4247 compbuf_max += 2;
4248
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");
4252 result->len = 0;
4253 return (0);
4254 }
4255
4256 /* Compress the combined list into result */
4257 list_len = MRns_name_compress_list(uncompbuf, uncomp_len,
4258 result->buffer->data, compbuf_max);
4259
4260 if (list_len <= 0) {
4261 log_error ("concat_dlists: error compressing result");
4262 data_string_forget(result, MDL);
4263 result->len = 0;
4264 return (0);
4265 }
4266
4267 /* Update result length to actual size */
4268 result->len = list_len;
4269 result->data = result->buffer->data;
4270 return (list_len);
4271 }
4272
4273 /* vim: set tabstop=8: */