]> git.ipfire.org Git - thirdparty/dhcp.git/blob - common/tree.c
DHCPv6 branch merged to HEAD.
[thirdparty/dhcp.git] / common / tree.c
1 /* tree.c
2
3 Routines for manipulating parse trees... */
4
5 /*
6 * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
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 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
26 *
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
33 */
34
35 #ifndef lint
36 static char copyright[] =
37 "$Id: tree.c,v 1.113 2007/05/08 23:05:20 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
39
40 #include "dhcpd.h"
41 #include <omapip/omapip_p.h>
42 #include <ctype.h>
43
44 struct binding_scope *global_scope;
45
46 static int do_host_lookup PROTO ((struct data_string *,
47 struct dns_host_entry *));
48
49 #ifdef NSUPDATE
50 struct __res_state resolver_state;
51 int resolver_inited = 0;
52 #endif
53
54 static void
55 append_to_ary(char **ary_ptr, int *ary_size, int ary_capacity,
56 char *new_element)
57 {
58 /* INSIST(ary_ptr != NULL); */
59 /* INSIST(ary_size != NULL); */
60 /* INSIST(ary_capacity > 1); */
61
62 if (new_element == NULL)
63 return;
64
65 if (*ary_size >= ary_capacity) {
66 log_fatal("Improbable error at %s:%d.", MDL);
67 return;
68 }
69
70 ary_ptr[(*ary_size)++] = new_element;
71 }
72
73 static char *
74 data_string_to_char_string(struct data_string *d)
75 {
76 char *str, *start, *end;
77 const unsigned char *pos;
78 int len;
79
80 if (d == NULL);
81 return NULL;
82
83 pos = d->data;
84
85 if (pos == NULL)
86 return NULL;
87
88 /* Per byte could be "\777" at worst, plus null terminator. */
89 len = (d->len * 4) + 1;
90 str = dmalloc(len, MDL);
91 if (!str)
92 return NULL;
93
94 start = str;
95 end = start + len;
96
97 if (pretty_escape(&start, end, &pos, pos + d->len) < 0) {
98 dfree(str, MDL);
99 return NULL;
100 }
101
102 /* dmalloc() sets the buffer to zero - there is no need to null
103 * terminate.
104 */
105
106 return str;
107 }
108
109 #define DS_SPRINTF_SIZE 128
110
111 /*
112 * If we are using a data_string structure to hold a NUL-terminated
113 * ASCII string, this function can be used to append a printf-formatted
114 * string to the end of it. The data_string structure will be resized to
115 * be big enough to hold the new string.
116 *
117 * If the append works, then 1 is returned.
118 *
119 * If it is not possible to allocate a buffer big enough to hold the
120 * new value, then the old data_string is unchanged, and 0 is returned.
121 */
122 int
123 data_string_sprintfa(struct data_string *ds, const char *fmt, ...) {
124 va_list args;
125 int cur_strlen;
126 int max;
127 int vsnprintf_ret;
128 int new_len;
129 struct buffer *tmp_buffer;
130
131 /*
132 * If the data_string is empty, then initialize it.
133 */
134 if (ds->data == NULL) {
135 /* INSIST(ds.buffer == NULL); */
136 if (!buffer_allocate(&ds->buffer, DS_SPRINTF_SIZE, MDL)) {
137 return 0;
138 }
139 ds->data = ds->buffer->data;
140 ds->len = DS_SPRINTF_SIZE;
141 *((char *)ds->data) = '\0';
142 }
143
144 /*
145 * Get the length of the string, and figure out how much space
146 * is left.
147 */
148 cur_strlen = strlen(ds->data);
149 max = ds->len - cur_strlen;
150
151 /*
152 * Use vsnprintf(), which won't write past our space, but will
153 * tell us how much space it wants.
154 */
155 va_start(args, fmt);
156 vsnprintf_ret = vsnprintf((char *)ds->data+cur_strlen, max, fmt, args);
157 /* INSIST(vsnprintf_ret >= 0); */
158
159 /*
160 * If our buffer is not big enough, we need a new buffer.
161 */
162 if (vsnprintf_ret >= max) {
163 /*
164 * Figure out a size big enough.
165 */
166 new_len = ds->len * 2;
167 while (new_len <= cur_strlen + vsnprintf_ret) {
168 new_len *= 2;
169 }
170
171 /*
172 * Create a new buffer and fill it.
173 */
174 tmp_buffer = NULL;
175 if (!buffer_allocate(&tmp_buffer, new_len, MDL)) {
176 /*
177 * If we can't create a big enough buffer,
178 * we should remove any truncated output that we had.
179 */
180 *((char *)ds->data+cur_strlen) = '\0';
181 va_end(args);
182 return 0;
183 }
184 memcpy(tmp_buffer->data, ds->data, cur_strlen);
185 vsprintf(tmp_buffer->data + cur_strlen, fmt, args);
186
187 /*
188 * Replace our old buffer with the new buffer.
189 */
190 buffer_dereference(&ds->buffer, MDL);
191 buffer_reference(&ds->buffer, tmp_buffer, MDL);
192 buffer_dereference(&tmp_buffer, MDL);
193 ds->data = ds->buffer->data;
194 ds->len = new_len;
195 }
196 va_end(args);
197 return 1;
198 }
199
200 pair cons (car, cdr)
201 caddr_t car;
202 pair cdr;
203 {
204 pair foo = (pair)dmalloc (sizeof *foo, MDL);
205 if (!foo)
206 log_fatal ("no memory for cons.");
207 foo -> car = car;
208 foo -> cdr = cdr;
209 return foo;
210 }
211
212 int make_const_option_cache (oc, buffer, data, len, option, file, line)
213 struct option_cache **oc;
214 struct buffer **buffer;
215 u_int8_t *data;
216 unsigned len;
217 struct option *option;
218 const char *file;
219 int line;
220 {
221 struct buffer *bp;
222
223 if (buffer) {
224 bp = *buffer;
225 *buffer = 0;
226 } else {
227 bp = (struct buffer *)0;
228 if (!buffer_allocate (&bp, len, file, line)) {
229 log_error ("%s(%d): can't allocate buffer.",
230 file, line);
231 return 0;
232 }
233 }
234
235 if (!option_cache_allocate (oc, file, line)) {
236 log_error ("%s(%d): can't allocate option cache.", file, line);
237 buffer_dereference (&bp, file, line);
238 return 0;
239 }
240
241 (*oc) -> data.len = len;
242 (*oc) -> data.buffer = bp;
243 (*oc) -> data.data = &bp -> data [0];
244 (*oc) -> data.terminated = 0;
245 if (data)
246 memcpy (&bp -> data [0], data, len);
247 option_reference(&((*oc)->option), option, MDL);
248 return 1;
249 }
250
251 int make_host_lookup (expr, name)
252 struct expression **expr;
253 const char *name;
254 {
255 if (!expression_allocate (expr, MDL)) {
256 log_error ("No memory for host lookup tree node.");
257 return 0;
258 }
259 (*expr) -> op = expr_host_lookup;
260 if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) {
261 expression_dereference (expr, MDL);
262 return 0;
263 }
264 return 1;
265 }
266
267 int enter_dns_host (dh, name)
268 struct dns_host_entry **dh;
269 const char *name;
270 {
271 /* XXX This should really keep a hash table of hostnames
272 XXX and just add a new reference to a hostname that
273 XXX already exists, if possible, rather than creating
274 XXX a new structure. */
275 if (!dns_host_entry_allocate (dh, name, MDL)) {
276 log_error ("Can't allocate space for new host.");
277 return 0;
278 }
279 return 1;
280 }
281
282 int make_const_data (struct expression **expr, const unsigned char *data,
283 unsigned len, int terminated, int allocate,
284 const char *file, int line)
285 {
286 struct expression *nt;
287
288 if (!expression_allocate (expr, file, line)) {
289 log_error ("No memory for make_const_data tree node.");
290 return 0;
291 }
292 nt = *expr;
293
294 if (len) {
295 if (allocate) {
296 if (!buffer_allocate (&nt -> data.const_data.buffer,
297 len + terminated, file, line)) {
298 log_error ("Can't allocate const_data buffer");
299 expression_dereference (expr, file, line);
300 return 0;
301 }
302 nt -> data.const_data.data =
303 &nt -> data.const_data.buffer -> data [0];
304 memcpy (nt -> data.const_data.buffer -> data,
305 data, len + terminated);
306 } else
307 nt -> data.const_data.data = data;
308 nt -> data.const_data.terminated = terminated;
309 } else
310 nt -> data.const_data.data = 0;
311
312 nt -> op = expr_const_data;
313 nt -> data.const_data.len = len;
314 return 1;
315 }
316
317 int make_const_int (expr, val)
318 struct expression **expr;
319 unsigned long val;
320 {
321 if (!expression_allocate (expr, MDL)) {
322 log_error ("No memory for make_const_int tree node.");
323 return 0;
324 }
325
326 (*expr) -> op = expr_const_int;
327 (*expr) -> data.const_int = val;
328 return 1;
329 }
330
331 int make_concat (expr, left, right)
332 struct expression **expr;
333 struct expression *left, *right;
334 {
335 /* If we're concatenating a null tree to a non-null tree, just
336 return the non-null tree; if both trees are null, return
337 a null tree. */
338 if (!left) {
339 if (!right)
340 return 0;
341 expression_reference (expr, right, MDL);
342 return 1;
343 }
344 if (!right) {
345 expression_reference (expr, left, MDL);
346 return 1;
347 }
348
349 /* Otherwise, allocate a new node to concatenate the two. */
350 if (!expression_allocate (expr, MDL)) {
351 log_error ("No memory for concatenation expression node.");
352 return 0;
353 }
354
355 (*expr) -> op = expr_concat;
356 expression_reference (&(*expr) -> data.concat [0], left, MDL);
357 expression_reference (&(*expr) -> data.concat [1], right, MDL);
358 return 1;
359 }
360
361 int make_encapsulation (expr, name)
362 struct expression **expr;
363 struct data_string *name;
364 {
365 /* Allocate a new node to store the encapsulation. */
366 if (!expression_allocate (expr, MDL)) {
367 log_error ("No memory for encapsulation expression node.");
368 return 0;
369 }
370
371 (*expr) -> op = expr_encapsulate;
372 data_string_copy (&(*expr) -> data.encapsulate, name, MDL);
373 return 1;
374 }
375
376 int make_substring (new, expr, offset, length)
377 struct expression **new;
378 struct expression *expr;
379 struct expression *offset;
380 struct expression *length;
381 {
382 /* Allocate an expression node to compute the substring. */
383 if (!expression_allocate (new, MDL)) {
384 log_error ("no memory for substring expression.");
385 return 0;
386 }
387 (*new) -> op = expr_substring;
388 expression_reference (&(*new) -> data.substring.expr, expr, MDL);
389 expression_reference (&(*new) -> data.substring.offset, offset, MDL);
390 expression_reference (&(*new) -> data.substring.len, length, MDL);
391 return 1;
392 }
393
394 int make_limit (new, expr, limit)
395 struct expression **new;
396 struct expression *expr;
397 int limit;
398 {
399 struct expression *rv;
400
401 /* Allocate a node to enforce a limit on evaluation. */
402 if (!expression_allocate (new, MDL))
403 log_error ("no memory for limit expression");
404 (*new) -> op = expr_substring;
405 expression_reference (&(*new) -> data.substring.expr, expr, MDL);
406
407 /* Offset is a constant 0. */
408 if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) {
409 log_error ("no memory for limit offset expression");
410 expression_dereference (new, MDL);
411 return 0;
412 }
413 (*new) -> data.substring.offset -> op = expr_const_int;
414 (*new) -> data.substring.offset -> data.const_int = 0;
415
416 /* Length is a constant: the specified limit. */
417 if (!expression_allocate (&(*new) -> data.substring.len, MDL)) {
418 log_error ("no memory for limit length expression");
419 expression_dereference (new, MDL);
420 return 0;
421 }
422 (*new) -> data.substring.len -> op = expr_const_int;
423 (*new) -> data.substring.len -> data.const_int = limit;
424
425 return 1;
426 }
427
428 int option_cache (struct option_cache **oc, struct data_string *dp,
429 struct expression *expr, struct option *option,
430 const char *file, int line)
431 {
432 if (!option_cache_allocate (oc, file, line))
433 return 0;
434 if (dp)
435 data_string_copy (&(*oc) -> data, dp, file, line);
436 if (expr)
437 expression_reference (&(*oc) -> expression, expr, file, line);
438 option_reference(&(*oc)->option, option, MDL);
439 return 1;
440 }
441
442 int make_let (result, name)
443 struct executable_statement **result;
444 const char *name;
445 {
446 if (!(executable_statement_allocate (result, MDL)))
447 return 0;
448
449 (*result) -> op = let_statement;
450 (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL);
451 if (!(*result) -> data.let.name) {
452 executable_statement_dereference (result, MDL);
453 return 0;
454 }
455 strcpy ((*result) -> data.let.name, name);
456 return 1;
457 }
458
459 static int do_host_lookup (result, dns)
460 struct data_string *result;
461 struct dns_host_entry *dns;
462 {
463 struct hostent *h;
464 unsigned i, count;
465 unsigned new_len;
466
467 #ifdef DEBUG_EVAL
468 log_debug ("time: now = %d dns = %d diff = %d",
469 cur_time, dns -> timeout, cur_time - dns -> timeout);
470 #endif
471
472 /* If the record hasn't timed out, just copy the data and return. */
473 if (cur_time <= dns -> timeout) {
474 #ifdef DEBUG_EVAL
475 log_debug ("easy copy: %d %s",
476 dns -> data.len,
477 (dns -> data.len > 4
478 ? inet_ntoa (*(struct in_addr *)(dns -> data.data))
479 : 0));
480 #endif
481 data_string_copy (result, &dns -> data, MDL);
482 return 1;
483 }
484 #ifdef DEBUG_EVAL
485 log_debug ("Looking up %s", dns -> hostname);
486 #endif
487
488 /* Otherwise, look it up... */
489 h = gethostbyname (dns -> hostname);
490 if (!h) {
491 #ifndef NO_H_ERRNO
492 switch (h_errno) {
493 case HOST_NOT_FOUND:
494 #endif
495 log_error ("%s: host unknown.", dns -> hostname);
496 #ifndef NO_H_ERRNO
497 break;
498 case TRY_AGAIN:
499 log_error ("%s: temporary name server failure",
500 dns -> hostname);
501 break;
502 case NO_RECOVERY:
503 log_error ("%s: name server failed", dns -> hostname);
504 break;
505 case NO_DATA:
506 log_error ("%s: no A record associated with address",
507 dns -> hostname);
508 }
509 #endif /* !NO_H_ERRNO */
510
511 /* Okay to try again after a minute. */
512 dns -> timeout = cur_time + 60;
513 data_string_forget (&dns -> data, MDL);
514 return 0;
515 }
516
517 #ifdef DEBUG_EVAL
518 log_debug ("Lookup succeeded; first address is %s",
519 inet_ntoa (h -> h_addr_list [0]));
520 #endif
521
522 /* Count the number of addresses we got... */
523 for (count = 0; h -> h_addr_list [count]; count++)
524 ;
525
526 /* Dereference the old data, if any. */
527 data_string_forget (&dns -> data, MDL);
528
529 /* Do we need to allocate more memory? */
530 new_len = count * h -> h_length;
531 if (!buffer_allocate (&dns -> data.buffer, new_len, MDL))
532 {
533 log_error ("No memory for %s.", dns -> hostname);
534 return 0;
535 }
536
537 dns -> data.data = &dns -> data.buffer -> data [0];
538 dns -> data.len = new_len;
539 dns -> data.terminated = 0;
540
541 /* Addresses are conveniently stored one to the buffer, so we
542 have to copy them out one at a time... :'( */
543 for (i = 0; i < count; i++) {
544 memcpy (&dns -> data.buffer -> data [h -> h_length * i],
545 h -> h_addr_list [i], (unsigned)(h -> h_length));
546 }
547 #ifdef DEBUG_EVAL
548 log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
549 *(int *)(dns -> buffer), h -> h_addr_list [0]);
550 #endif
551
552 /* XXX Set the timeout for an hour from now.
553 XXX This should really use the time on the DNS reply. */
554 dns -> timeout = cur_time + 3600;
555
556 #ifdef DEBUG_EVAL
557 log_debug ("hard copy: %d %s", dns -> data.len,
558 (dns -> data.len > 4
559 ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));
560 #endif
561 data_string_copy (result, &dns -> data, MDL);
562 return 1;
563 }
564
565 int evaluate_expression (result, packet, lease, client_state,
566 in_options, cfg_options, scope, expr, file, line)
567 struct binding_value **result;
568 struct packet *packet;
569 struct lease *lease;
570 struct client_state *client_state;
571 struct option_state *in_options;
572 struct option_state *cfg_options;
573 struct binding_scope **scope;
574 struct expression *expr;
575 const char *file;
576 int line;
577 {
578 struct binding_value *bv;
579 int status;
580 struct binding *binding;
581
582 bv = (struct binding_value *)0;
583
584 if (expr -> op == expr_variable_reference) {
585 if (!scope || !*scope)
586 return 0;
587
588 binding = find_binding (*scope, expr -> data.variable);
589
590 if (binding && binding -> value) {
591 if (result)
592 binding_value_reference (result,
593 binding -> value,
594 file, line);
595 return 1;
596 } else
597 return 0;
598 } else if (expr -> op == expr_funcall) {
599 struct string_list *s;
600 struct expression *arg;
601 struct binding_scope *ns;
602 struct binding *nb;
603
604 if (!scope || !*scope) {
605 log_error ("%s: no such function.",
606 expr -> data.funcall.name);
607 return 0;
608 }
609
610 binding = find_binding (*scope, expr -> data.funcall.name);
611
612 if (!binding || !binding -> value) {
613 log_error ("%s: no such function.",
614 expr -> data.funcall.name);
615 return 0;
616 }
617 if (binding -> value -> type != binding_function) {
618 log_error ("%s: not a function.",
619 expr -> data.funcall.name);
620 return 0;
621 }
622
623 /* Create a new binding scope in which to define
624 the arguments to the function. */
625 ns = (struct binding_scope *)0;
626 if (!binding_scope_allocate (&ns, MDL)) {
627 log_error ("%s: can't allocate argument scope.",
628 expr -> data.funcall.name);
629 return 0;
630 }
631
632 arg = expr -> data.funcall.arglist;
633 s = binding -> value -> value.fundef -> args;
634 while (arg && s) {
635 nb = dmalloc (sizeof *nb, MDL);
636 if (!nb) {
637 blb:
638 binding_scope_dereference (&ns, MDL);
639 return 0;
640 } else {
641 memset (nb, 0, sizeof *nb);
642 nb -> name = dmalloc (strlen (s -> string) + 1,
643 MDL);
644 if (nb -> name)
645 strcpy (nb -> name, s -> string);
646 else {
647 dfree (nb, MDL);
648 nb = (struct binding *)0;
649 goto blb;
650 }
651 }
652 evaluate_expression (&nb -> value, packet, lease,
653 client_state,
654 in_options, cfg_options, scope,
655 arg -> data.arg.val, file, line);
656 nb -> next = ns -> bindings;
657 ns -> bindings = nb;
658 arg = arg -> data.arg.next;
659 s = s -> next;
660 }
661 if (arg) {
662 log_error ("%s: too many arguments.",
663 expr -> data.funcall.name);
664 binding_scope_dereference (&ns, MDL);
665 return 0;
666 }
667 if (s) {
668 log_error ("%s: too few arguments.",
669 expr -> data.funcall.name);
670 binding_scope_dereference (&ns, MDL);
671 return 0;
672 }
673
674 if (scope && *scope)
675 binding_scope_reference (&ns -> outer, *scope, MDL);
676
677 status = (execute_statements
678 (&bv, packet,
679 lease, client_state, in_options, cfg_options, &ns,
680 binding -> value -> value.fundef -> statements));
681 binding_scope_dereference (&ns, MDL);
682
683 if (!bv)
684 return 1;
685 } else if (is_boolean_expression (expr)) {
686 if (!binding_value_allocate (&bv, MDL))
687 return 0;
688 bv -> type = binding_boolean;
689 status = (evaluate_boolean_expression
690 (&bv -> value.boolean, packet, lease, client_state,
691 in_options, cfg_options, scope, expr));
692 } else if (is_numeric_expression (expr)) {
693 if (!binding_value_allocate (&bv, MDL))
694 return 0;
695 bv -> type = binding_numeric;
696 status = (evaluate_numeric_expression
697 (&bv -> value.intval, packet, lease, client_state,
698 in_options, cfg_options, scope, expr));
699 } else if (is_data_expression (expr)) {
700 if (!binding_value_allocate (&bv, MDL))
701 return 0;
702 bv -> type = binding_data;
703 status = (evaluate_data_expression
704 (&bv -> value.data, packet, lease, client_state,
705 in_options, cfg_options, scope, expr, MDL));
706 } else if (is_dns_expression (expr)) {
707 #if defined (NSUPDATE)
708 if (!binding_value_allocate (&bv, MDL))
709 return 0;
710 bv -> type = binding_dns;
711 status = (evaluate_dns_expression
712 (&bv -> value.dns, packet, lease, client_state,
713 in_options, cfg_options, scope, expr));
714 #endif
715 } else {
716 log_error ("%s: invalid expression type: %d",
717 "evaluate_expression", expr -> op);
718 return 0;
719 }
720 if (result && status)
721 binding_value_reference (result, bv, file, line);
722 binding_value_dereference (&bv, MDL);
723
724 return status;
725 }
726
727 int binding_value_dereference (struct binding_value **v,
728 const char *file, int line)
729 {
730 struct binding_value *bv = *v;
731
732 *v = (struct binding_value *)0;
733
734 /* Decrement the reference count. If it's nonzero, we're
735 done. */
736 --(bv -> refcnt);
737 rc_register (file, line, v, bv, bv -> refcnt, 1, RC_MISC);
738 if (bv -> refcnt > 0)
739 return 1;
740 if (bv -> refcnt < 0) {
741 log_error ("%s(%d): negative refcnt!", file, line);
742 #if defined (DEBUG_RC_HISTORY)
743 dump_rc_history (bv);
744 #endif
745 #if defined (POINTER_DEBUG)
746 abort ();
747 #else
748 return 0;
749 #endif
750 }
751
752 switch (bv -> type) {
753 case binding_boolean:
754 case binding_numeric:
755 break;
756 case binding_data:
757 if (bv -> value.data.buffer)
758 data_string_forget (&bv -> value.data, file, line);
759 break;
760 case binding_dns:
761 #if defined (NSUPDATE)
762 if (bv -> value.dns) {
763 if (bv -> value.dns -> r_data) {
764 dfree (bv -> value.dns -> r_data_ephem, MDL);
765 bv -> value.dns -> r_data = (unsigned char *)0;
766 bv -> value.dns -> r_data_ephem =
767 (unsigned char *)0;
768 }
769 minires_freeupdrec (bv -> value.dns);
770 }
771 break;
772 #endif
773 default:
774 log_error ("%s(%d): invalid binding type: %d",
775 file, line, bv -> type);
776 return 0;
777 }
778 free_binding_value(bv, file, line);
779 return 1;
780 }
781
782 #if defined (NSUPDATE)
783 int evaluate_dns_expression (result, packet, lease, client_state, in_options,
784 cfg_options, scope, expr)
785 ns_updrec **result;
786 struct packet *packet;
787 struct lease *lease;
788 struct client_state *client_state;
789 struct option_state *in_options;
790 struct option_state *cfg_options;
791 struct binding_scope **scope;
792 struct expression *expr;
793 {
794 ns_updrec *foo;
795 unsigned long ttl = 0;
796 char *tname;
797 struct data_string name, data;
798 int r0, r1, r2, r3;
799
800 if (!result || *result) {
801 log_error ("evaluate_dns_expression called with non-null %s",
802 "result pointer");
803 #if defined (POINTER_DEBUG)
804 abort ();
805 #else
806 return 0;
807 #endif
808 }
809
810 switch (expr -> op) {
811 #if defined (NSUPDATE)
812 case expr_ns_add:
813 r0 = evaluate_numeric_expression (&ttl, packet, lease,
814 client_state,
815 in_options, cfg_options,
816 scope,
817 expr -> data.ns_add.ttl);
818 goto nsfinish;
819
820 case expr_ns_exists:
821 ttl = 1;
822
823 case expr_ns_delete:
824 case expr_ns_not_exists:
825 r0 = 1;
826 nsfinish:
827 memset (&name, 0, sizeof name);
828 r1 = evaluate_data_expression (&name, packet, lease,
829 client_state,
830 in_options, cfg_options, scope,
831 expr -> data.ns_add.rrname,
832 MDL);
833 if (r1) {
834 /* The result of the evaluation may or may not
835 be NUL-terminated, but we need it
836 terminated for sure, so we have to allocate
837 a buffer and terminate it. */
838 tname = dmalloc (name.len + 1, MDL);
839 if (!tname) {
840 r2 = 0;
841 r1 = 0;
842 data_string_forget (&name, MDL);
843 } else {
844 memcpy (tname, name.data, name.len);
845 tname [name.len] = 0;
846 memset (&data, 0, sizeof data);
847 r2 = evaluate_data_expression
848 (&data, packet, lease, client_state,
849 in_options, cfg_options, scope,
850 expr -> data.ns_add.rrdata, MDL);
851 }
852 } else {
853 r2 = 0;
854 tname = NULL;
855 }
856 if (r0 && r1 && (r2 || expr -> op != expr_ns_add)) {
857 *result = minires_mkupdrec (((expr -> op == expr_ns_add ||
858 expr -> op == expr_ns_delete)
859 ? S_UPDATE : S_PREREQ),
860 tname,
861 expr -> data.ns_add.rrclass,
862 expr -> data.ns_add.rrtype,
863 ttl);
864 if (!*result) {
865 ngood:
866 if (r2) {
867 data_string_forget (&data, MDL);
868 r2 = 0;
869 }
870 } else {
871 if (data.len) {
872 /* As a special case, if we get exactly
873 four bytes of data, it's an IP address
874 represented as a 32-bit quantity, which
875 is actually what we *should* be getting
876 here. Because res_mkupdrec is currently
877 broken and expects a dotted quad, convert
878 it. This should be fixed when the new
879 resolver is merged. */
880 if (data.len == 4) {
881 (*result) -> r_data_ephem =
882 dmalloc (16, MDL);
883 if (!(*result) -> r_data_ephem)
884 goto dpngood;
885 (*result) -> r_data =
886 (*result) -> r_data_ephem;
887 /*%Audit% 16 bytes max. %2004.06.17,Safe%*/
888 sprintf ((char *)(*result) -> r_data_ephem,
889 "%u.%u.%u.%u",
890 data.data [0] & 0xff,
891 data.data [1] & 0xff,
892 data.data [2] & 0xff,
893 data.data [3] & 0xff);
894 (*result) -> r_size =
895 strlen ((const char *)
896 (*result) -> r_data);
897 } else {
898 (*result) -> r_size = data.len;
899 (*result) -> r_data_ephem =
900 dmalloc (data.len, MDL);
901 if (!(*result) -> r_data_ephem) {
902 dpngood: /* double plus ungood. */
903 minires_freeupdrec (*result);
904 *result = 0;
905 goto ngood;
906 }
907 (*result) -> r_data =
908 (*result) -> r_data_ephem;
909 memcpy ((*result) -> r_data_ephem,
910 data.data, data.len);
911 }
912 } else {
913 (*result) -> r_data = 0;
914 (*result) -> r_size = 0;
915 }
916 switch (expr -> op) {
917 case expr_ns_add:
918 (*result) -> r_opcode = ADD;
919 break;
920 case expr_ns_delete:
921 (*result) -> r_opcode = DELETE;
922 break;
923 case expr_ns_exists:
924 (*result) -> r_opcode = YXRRSET;
925 break;
926 case expr_ns_not_exists:
927 (*result) -> r_opcode = NXRRSET;
928 break;
929
930 /* Can't happen, but satisfy gcc. */
931 default:
932 break;
933 }
934 }
935 }
936 if (r1) {
937 data_string_forget (&name, MDL);
938 dfree (tname, MDL);
939 }
940 if (r2)
941 data_string_forget (&data, MDL);
942 /* One flaw in the thinking here: an IP address and an
943 ASCII string both look like data expressions, but
944 for A records, we want an ASCII string, not a
945 binary IP address. Do I need to turn binary IP
946 addresses into a separate type? */
947 return (r0 && r1 &&
948 (r2 || expr -> op != expr_ns_add) && *result);
949
950 #else
951 case expr_ns_add:
952 case expr_ns_delete:
953 case expr_ns_exists:
954 case expr_ns_not_exists:
955 return 0;
956 #endif
957 case expr_funcall:
958 log_error ("%s: dns values for functions not supported.",
959 expr -> data.funcall.name);
960 break;
961
962 case expr_variable_reference:
963 log_error ("%s: dns values for variables not supported.",
964 expr -> data.variable);
965 break;
966
967 case expr_check:
968 case expr_equal:
969 case expr_not_equal:
970 case expr_and:
971 case expr_or:
972 case expr_not:
973 case expr_match:
974 case expr_static:
975 case expr_known:
976 case expr_exists:
977 case expr_variable_exists:
978 log_error ("Boolean opcode in evaluate_dns_expression: %d",
979 expr -> op);
980 return 0;
981
982 case expr_none:
983 case expr_substring:
984 case expr_suffix:
985 case expr_lcase:
986 case expr_ucase:
987 case expr_option:
988 case expr_hardware:
989 case expr_const_data:
990 case expr_packet:
991 case expr_concat:
992 case expr_encapsulate:
993 case expr_host_lookup:
994 case expr_encode_int8:
995 case expr_encode_int16:
996 case expr_encode_int32:
997 case expr_binary_to_ascii:
998 case expr_reverse:
999 case expr_filename:
1000 case expr_sname:
1001 case expr_pick_first_value:
1002 case expr_host_decl_name:
1003 case expr_config_option:
1004 case expr_leased_address:
1005 case expr_null:
1006 log_error ("Data opcode in evaluate_dns_expression: %d",
1007 expr -> op);
1008 return 0;
1009
1010 case expr_extract_int8:
1011 case expr_extract_int16:
1012 case expr_extract_int32:
1013 case expr_const_int:
1014 case expr_lease_time:
1015 case expr_dns_transaction:
1016 case expr_add:
1017 case expr_subtract:
1018 case expr_multiply:
1019 case expr_divide:
1020 case expr_remainder:
1021 case expr_binary_and:
1022 case expr_binary_or:
1023 case expr_binary_xor:
1024 case expr_client_state:
1025 log_error ("Numeric opcode in evaluate_dns_expression: %d",
1026 expr -> op);
1027 return 0;
1028
1029 case expr_function:
1030 log_error ("Function opcode in evaluate_dns_expression: %d",
1031 expr -> op);
1032 return 0;
1033
1034 case expr_arg:
1035 break;
1036 }
1037
1038 log_error ("Bogus opcode in evaluate_dns_expression: %d",
1039 expr -> op);
1040 return 0;
1041 }
1042 #endif /* defined (NSUPDATE) */
1043
1044 int evaluate_boolean_expression (result, packet, lease, client_state,
1045 in_options, cfg_options, scope, expr)
1046 int *result;
1047 struct packet *packet;
1048 struct lease *lease;
1049 struct client_state *client_state;
1050 struct option_state *in_options;
1051 struct option_state *cfg_options;
1052 struct binding_scope **scope;
1053 struct expression *expr;
1054 {
1055 struct data_string left, right;
1056 struct data_string rrtype, rrname, rrdata;
1057 unsigned long ttl;
1058 int srrtype, srrname, srrdata, sttl;
1059 int bleft, bright;
1060 int sleft, sright;
1061 struct binding *binding;
1062 struct binding_value *bv, *obv;
1063
1064 switch (expr -> op) {
1065 case expr_check:
1066 *result = check_collection (packet, lease,
1067 expr -> data.check);
1068 #if defined (DEBUG_EXPRESSIONS)
1069 log_debug ("bool: check (%s) returns %s",
1070 expr -> data.check -> name,
1071 *result ? "true" : "false");
1072 #endif
1073 return 1;
1074
1075 case expr_equal:
1076 case expr_not_equal:
1077 bv = obv = (struct binding_value *)0;
1078 sleft = evaluate_expression (&bv, packet, lease, client_state,
1079 in_options, cfg_options, scope,
1080 expr -> data.equal [0], MDL);
1081 sright = evaluate_expression (&obv, packet, lease,
1082 client_state, in_options,
1083 cfg_options, scope,
1084 expr -> data.equal [1], MDL);
1085 if (sleft && sright) {
1086 if (bv -> type != obv -> type)
1087 *result = expr -> op == expr_not_equal;
1088 else {
1089 switch (obv -> type) {
1090 case binding_boolean:
1091 if (bv -> value.boolean == obv -> value.boolean)
1092 *result = expr -> op == expr_equal;
1093 else
1094 *result = expr -> op == expr_not_equal;
1095 break;
1096
1097 case binding_data:
1098 if ((bv -> value.data.len ==
1099 obv -> value.data.len) &&
1100 !memcmp (bv -> value.data.data,
1101 obv -> value.data.data,
1102 obv -> value.data.len))
1103 *result = expr -> op == expr_equal;
1104 else
1105 *result = expr -> op == expr_not_equal;
1106 break;
1107
1108 case binding_numeric:
1109 if (bv -> value.intval == obv -> value.intval)
1110 *result = expr -> op == expr_equal;
1111 else
1112 *result = expr -> op == expr_not_equal;
1113 break;
1114
1115 case binding_dns:
1116 #if defined (NSUPDATE)
1117 /* XXX This should be a comparison for equal
1118 XXX values, not for identity. */
1119 if (bv -> value.dns == obv -> value.dns)
1120 *result = expr -> op == expr_equal;
1121 else
1122 *result = expr -> op == expr_not_equal;
1123 #else
1124 *result = expr -> op == expr_not_equal;
1125 #endif
1126 break;
1127
1128 case binding_function:
1129 if (bv -> value.fundef == obv -> value.fundef)
1130 *result = expr -> op == expr_equal;
1131 else
1132 *result = expr -> op == expr_not_equal;
1133 break;
1134 default:
1135 *result = expr -> op == expr_not_equal;
1136 break;
1137 }
1138 }
1139 } else if (!sleft && !sright)
1140 *result = expr -> op == expr_equal;
1141 else
1142 *result = expr -> op == expr_not_equal;
1143
1144 #if defined (DEBUG_EXPRESSIONS)
1145 log_debug ("bool: %sequal = %s",
1146 expr -> op == expr_not_equal ? "not" : "",
1147 (*result ? "true" : "false"));
1148 #endif
1149 if (sleft)
1150 binding_value_dereference (&bv, MDL);
1151 if (sright)
1152 binding_value_dereference (&obv, MDL);
1153 return 1;
1154
1155 case expr_and:
1156 sleft = evaluate_boolean_expression (&bleft, packet, lease,
1157 client_state,
1158 in_options, cfg_options,
1159 scope,
1160 expr -> data.and [0]);
1161 if (sleft && bleft)
1162 sright = evaluate_boolean_expression
1163 (&bright, packet, lease, client_state,
1164 in_options, cfg_options,
1165 scope, expr -> data.and [1]);
1166 else
1167 sright = bright = 0;
1168
1169 #if defined (DEBUG_EXPRESSIONS)
1170 log_debug ("bool: and (%s, %s) = %s",
1171 sleft ? (bleft ? "true" : "false") : "NULL",
1172 sright ? (bright ? "true" : "false") : "NULL",
1173 ((sleft && sright)
1174 ? (bleft && bright ? "true" : "false") : "NULL"));
1175 #endif
1176 if (sleft && sright) {
1177 *result = bleft && bright;
1178 return 1;
1179 }
1180 return 0;
1181
1182 case expr_or:
1183 bleft = bright = 0;
1184 sleft = evaluate_boolean_expression (&bleft, packet, lease,
1185 client_state,
1186 in_options, cfg_options,
1187 scope,
1188 expr -> data.or [0]);
1189 if (!sleft || !bleft)
1190 sright = evaluate_boolean_expression
1191 (&bright, packet, lease, client_state,
1192 in_options, cfg_options,
1193 scope, expr -> data.or [1]);
1194 else
1195 sright = 0;
1196 #if defined (DEBUG_EXPRESSIONS)
1197 log_debug ("bool: or (%s, %s) = %s",
1198 sleft ? (bleft ? "true" : "false") : "NULL",
1199 sright ? (bright ? "true" : "false") : "NULL",
1200 ((sleft || sright)
1201 ? (bleft || bright ? "true" : "false") : "NULL"));
1202 #endif
1203 if (sleft || sright) {
1204 *result = bleft || bright;
1205 return 1;
1206 }
1207 return 0;
1208
1209 case expr_not:
1210 sleft = evaluate_boolean_expression (&bleft, packet, lease,
1211 client_state,
1212 in_options, cfg_options,
1213 scope,
1214 expr -> data.not);
1215 #if defined (DEBUG_EXPRESSIONS)
1216 log_debug ("bool: not (%s) = %s",
1217 sleft ? (bleft ? "true" : "false") : "NULL",
1218 ((sleft && sright)
1219 ? (!bleft ? "true" : "false") : "NULL"));
1220
1221 #endif
1222 if (sleft) {
1223 *result = !bleft;
1224 return 1;
1225 }
1226 return 0;
1227
1228 case expr_exists:
1229 memset (&left, 0, sizeof left);
1230 if (!in_options ||
1231 !get_option (&left, expr -> data.exists -> universe,
1232 packet, lease, client_state,
1233 in_options, cfg_options, in_options,
1234 scope, expr -> data.exists -> code, MDL))
1235 *result = 0;
1236 else {
1237 *result = 1;
1238 data_string_forget (&left, MDL);
1239 }
1240 #if defined (DEBUG_EXPRESSIONS)
1241 log_debug ("bool: exists %s.%s = %s",
1242 expr -> data.option -> universe -> name,
1243 expr -> data.option -> name,
1244 *result ? "true" : "false");
1245 #endif
1246 return 1;
1247
1248 case expr_known:
1249 if (!packet) {
1250 #if defined (DEBUG_EXPRESSIONS)
1251 log_debug ("bool: known = NULL");
1252 #endif
1253 return 0;
1254 }
1255 #if defined (DEBUG_EXPRESSIONS)
1256 log_debug ("bool: known = %s",
1257 packet -> known ? "true" : "false");
1258 #endif
1259 *result = packet -> known;
1260 return 1;
1261
1262 case expr_static:
1263 if (!lease || !(lease -> flags & STATIC_LEASE)) {
1264 #if defined (DEBUG_EXPRESSIONS)
1265 log_debug ("bool: static = false (%s %s %s %d)",
1266 lease ? "y" : "n",
1267 (lease && (lease -> flags & STATIC_LEASE)
1268 ? "y" : "n"),
1269 piaddr (lease -> ip_addr),
1270 lease ? lease -> flags : 0);
1271 #endif
1272 *result = 0;
1273 return 1;
1274 }
1275 #if defined (DEBUG_EXPRESSIONS)
1276 log_debug ("bool: static = true");
1277 #endif
1278 *result = 1;
1279 return 1;
1280
1281 case expr_variable_exists:
1282 if (scope && *scope) {
1283 binding = find_binding (*scope, expr -> data.variable);
1284
1285 if (binding) {
1286 if (binding -> value)
1287 *result = 1;
1288 else
1289 *result = 0;
1290 } else
1291 *result = 0;
1292 } else
1293 *result = 0;
1294 #if defined (DEBUG_EXPRESSIONS)
1295 log_debug ("boolean: %s? = %s", expr -> data.variable,
1296 *result ? "true" : "false");
1297 #endif
1298 return 1;
1299
1300 case expr_variable_reference:
1301 if (scope && *scope) {
1302 binding = find_binding (*scope, expr -> data.variable);
1303
1304 if (binding && binding -> value) {
1305 if (binding -> value -> type ==
1306 binding_boolean) {
1307 *result = binding -> value -> value.boolean;
1308 sleft = 1;
1309 } else {
1310 log_error ("binding type %d in %s.",
1311 binding -> value -> type,
1312 "evaluate_boolean_expression");
1313 sleft = 0;
1314 }
1315 } else
1316 sleft = 0;
1317 } else
1318 sleft = 0;
1319 #if defined (DEBUG_EXPRESSIONS)
1320 log_debug ("boolean: %s = %s", expr -> data.variable,
1321 sleft ? (*result ? "true" : "false") : "NULL");
1322 #endif
1323 return sleft;
1324
1325 case expr_funcall:
1326 bv = (struct binding_value *)0;
1327 sleft = evaluate_expression (&bv, packet, lease, client_state,
1328 in_options, cfg_options,
1329 scope, expr, MDL);
1330 if (sleft) {
1331 if (bv -> type != binding_boolean)
1332 log_error ("%s() returned type %d in %s.",
1333 expr -> data.funcall.name,
1334 bv -> type,
1335 "evaluate_boolean_expression");
1336 else
1337 *result = bv -> value.boolean;
1338 binding_value_dereference (&bv, MDL);
1339 }
1340 #if defined (DEBUG_EXPRESSIONS)
1341 log_debug ("boolean: %s() = %s", expr -> data.funcall.name,
1342 sleft ? (*result ? "true" : "false") : "NULL");
1343 #endif
1344 break;
1345
1346 case expr_none:
1347 case expr_match:
1348 case expr_substring:
1349 case expr_suffix:
1350 case expr_lcase:
1351 case expr_ucase:
1352 case expr_option:
1353 case expr_hardware:
1354 case expr_const_data:
1355 case expr_packet:
1356 case expr_concat:
1357 case expr_encapsulate:
1358 case expr_host_lookup:
1359 case expr_encode_int8:
1360 case expr_encode_int16:
1361 case expr_encode_int32:
1362 case expr_binary_to_ascii:
1363 case expr_reverse:
1364 case expr_pick_first_value:
1365 case expr_host_decl_name:
1366 case expr_config_option:
1367 case expr_leased_address:
1368 case expr_null:
1369 case expr_filename:
1370 case expr_sname:
1371 log_error ("Data opcode in evaluate_boolean_expression: %d",
1372 expr -> op);
1373 return 0;
1374
1375 case expr_extract_int8:
1376 case expr_extract_int16:
1377 case expr_extract_int32:
1378 case expr_const_int:
1379 case expr_lease_time:
1380 case expr_dns_transaction:
1381 case expr_add:
1382 case expr_subtract:
1383 case expr_multiply:
1384 case expr_divide:
1385 case expr_remainder:
1386 case expr_binary_and:
1387 case expr_binary_or:
1388 case expr_binary_xor:
1389 case expr_client_state:
1390 log_error ("Numeric opcode in evaluate_boolean_expression: %d",
1391 expr -> op);
1392 return 0;
1393
1394 case expr_ns_add:
1395 case expr_ns_delete:
1396 case expr_ns_exists:
1397 case expr_ns_not_exists:
1398 log_error ("dns opcode in evaluate_boolean_expression: %d",
1399 expr -> op);
1400 return 0;
1401
1402 case expr_function:
1403 log_error ("function definition in evaluate_boolean_expr");
1404 return 0;
1405
1406 case expr_arg:
1407 break;
1408 }
1409
1410 log_error ("Bogus opcode in evaluate_boolean_expression: %d",
1411 expr -> op);
1412 return 0;
1413 }
1414
1415 int evaluate_data_expression (result, packet, lease, client_state,
1416 in_options, cfg_options, scope, expr, file, line)
1417 struct data_string *result;
1418 struct packet *packet;
1419 struct lease *lease;
1420 struct client_state *client_state;
1421 struct option_state *in_options;
1422 struct option_state *cfg_options;
1423 struct binding_scope **scope;
1424 struct expression *expr;
1425 const char *file;
1426 int line;
1427 {
1428 struct data_string data, other;
1429 unsigned long offset, len, i;
1430 int s0, s1, s2, s3;
1431 int status;
1432 struct binding *binding;
1433 unsigned char *s;
1434 struct binding_value *bv;
1435
1436 switch (expr -> op) {
1437 /* Extract N bytes starting at byte M of a data string. */
1438 case expr_substring:
1439 memset (&data, 0, sizeof data);
1440 s0 = evaluate_data_expression (&data, packet, lease,
1441 client_state,
1442 in_options, cfg_options, scope,
1443 expr -> data.substring.expr,
1444 MDL);
1445
1446 /* Evaluate the offset and length. */
1447 s1 = evaluate_numeric_expression
1448 (&offset, packet, lease, client_state, in_options,
1449 cfg_options, scope, expr -> data.substring.offset);
1450 s2 = evaluate_numeric_expression (&len, packet, lease,
1451 client_state,
1452 in_options, cfg_options,
1453 scope,
1454 expr -> data.substring.len);
1455
1456 if (s0 && s1 && s2) {
1457 /* If the offset is after end of the string,
1458 return an empty string. Otherwise, do the
1459 adjustments and return what's left. */
1460 if (data.len > offset) {
1461 data_string_copy (result, &data, file, line);
1462 result -> len -= offset;
1463 if (result -> len > len) {
1464 result -> len = len;
1465 result -> terminated = 0;
1466 }
1467 result -> data += offset;
1468 }
1469 s3 = 1;
1470 } else
1471 s3 = 0;
1472
1473 #if defined (DEBUG_EXPRESSIONS)
1474 log_debug ("data: substring (%s, %s, %s) = %s",
1475 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1476 s1 ? print_dec_1 (offset) : "NULL",
1477 s2 ? print_dec_2 (len) : "NULL",
1478 (s3 ? print_hex_2 (result -> len, result -> data, 30)
1479 : "NULL"));
1480 #endif
1481 if (s0)
1482 data_string_forget (&data, MDL);
1483 if (s3)
1484 return 1;
1485 return 0;
1486
1487 /* Extract the last N bytes of a data string. */
1488 case expr_suffix:
1489 memset (&data, 0, sizeof data);
1490 s0 = evaluate_data_expression (&data, packet, lease,
1491 client_state,
1492 in_options, cfg_options, scope,
1493 expr -> data.suffix.expr, MDL);
1494 /* Evaluate the length. */
1495 s1 = evaluate_numeric_expression (&len, packet, lease,
1496 client_state,
1497 in_options, cfg_options,
1498 scope,
1499 expr -> data.suffix.len);
1500 if (s0 && s1) {
1501 data_string_copy (result, &data, file, line);
1502
1503 /* If we are returning the last N bytes of a
1504 string whose length is <= N, just return
1505 the string - otherwise, compute a new
1506 starting address and decrease the
1507 length. */
1508 if (data.len > len) {
1509 result -> data += data.len - len;
1510 result -> len = len;
1511 }
1512 data_string_forget (&data, MDL);
1513 }
1514
1515 #if defined (DEBUG_EXPRESSIONS)
1516 log_debug ("data: suffix (%s, %s) = %s",
1517 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1518 s1 ? print_dec_1 (len) : "NULL",
1519 ((s0 && s1)
1520 ? print_hex_2 (result -> len, result -> data, 30)
1521 : "NULL"));
1522 #endif
1523 return s0 && s1;
1524
1525 /* Convert string to lowercase. */
1526 case expr_lcase:
1527 memset(&data, 0, sizeof data);
1528 s0 = evaluate_data_expression(&data, packet, lease,
1529 client_state,
1530 in_options, cfg_options, scope,
1531 expr->data.lcase, MDL);
1532 s1 = 0;
1533 if (s0) {
1534 result->len = data.len;
1535 if (buffer_allocate(&result->buffer,
1536 result->len + data.terminated,
1537 MDL)) {
1538 result->data = &result->buffer->data[0];
1539 memcpy(result->buffer->data, data.data,
1540 data.len + data.terminated);
1541 result->terminated = data.terminated;
1542 s = (unsigned char *)result->data;
1543 for (i = 0; i < result->len; i++, s++)
1544 *s = tolower(*s);
1545 s1 = 1;
1546 } else {
1547 log_error("data: lcase: no buffer memory.");
1548 }
1549 }
1550
1551 #if defined (DEBUG_EXPRESSIONS)
1552 log_debug("data: lcase (%s) = %s",
1553 s0 ? print_hex_1(data.len, data.data, 30) : "NULL",
1554 s1 ? print_hex_2(result->len, result->data, 30)
1555 : "NULL");
1556 #endif
1557 if (s0)
1558 data_string_forget(&data, MDL);
1559 return s1;
1560
1561 /* Convert string to uppercase. */
1562 case expr_ucase:
1563 memset(&data, 0, sizeof data);
1564 s0 = evaluate_data_expression(&data, packet, lease,
1565 client_state,
1566 in_options, cfg_options, scope,
1567 expr->data.lcase, MDL);
1568 s1 = 0;
1569 if (s0) {
1570 result->len = data.len;
1571 if (buffer_allocate(&result->buffer,
1572 result->len + data.terminated,
1573 file, line)) {
1574 result->data = &result->buffer->data[0];
1575 memcpy(result->buffer->data, data.data,
1576 data.len + data.terminated);
1577 result->terminated = data.terminated;
1578 s = (unsigned char *)result->data;
1579 for (i = 0; i < result->len; i++, s++)
1580 *s = toupper(*s);
1581 s1 = 1;
1582 } else {
1583 log_error("data: lcase: no buffer memory.");
1584 }
1585 }
1586
1587 #if defined (DEBUG_EXPRESSIONS)
1588 log_debug("data: ucase (%s) = %s",
1589 s0 ? print_hex_1(data.len, data.data, 30) : "NULL",
1590 s1 ? print_hex_2(result->len, result->data, 30)
1591 : "NULL");
1592 #endif
1593 if (s0)
1594 data_string_forget(&data, MDL);
1595 return s1;
1596
1597 /* Extract an option. */
1598 case expr_option:
1599 if (in_options)
1600 s0 = get_option (result,
1601 expr -> data.option -> universe,
1602 packet, lease, client_state,
1603 in_options, cfg_options, in_options,
1604 scope, expr -> data.option -> code,
1605 file, line);
1606 else
1607 s0 = 0;
1608
1609 #if defined (DEBUG_EXPRESSIONS)
1610 log_debug ("data: option %s.%s = %s",
1611 expr -> data.option -> universe -> name,
1612 expr -> data.option -> name,
1613 s0 ? print_hex_1 (result -> len, result -> data, 60)
1614 : "NULL");
1615 #endif
1616 return s0;
1617
1618 case expr_config_option:
1619 if (cfg_options)
1620 s0 = get_option (result,
1621 expr -> data.option -> universe,
1622 packet, lease, client_state,
1623 in_options, cfg_options, cfg_options,
1624 scope, expr -> data.option -> code,
1625 file, line);
1626 else
1627 s0 = 0;
1628
1629 #if defined (DEBUG_EXPRESSIONS)
1630 log_debug ("data: config-option %s.%s = %s",
1631 expr -> data.option -> universe -> name,
1632 expr -> data.option -> name,
1633 s0 ? print_hex_1 (result -> len, result -> data, 60)
1634 : "NULL");
1635 #endif
1636 return s0;
1637
1638 /* Combine the hardware type and address. */
1639 case expr_hardware:
1640 /* On the client, hardware is our hardware. */
1641 if (client_state) {
1642 memset (result, 0, sizeof *result);
1643 result -> data =
1644 client_state -> interface -> hw_address.hbuf;
1645 result -> len =
1646 client_state -> interface -> hw_address.hlen;
1647 #if defined (DEBUG_EXPRESSIONS)
1648 log_debug ("data: hardware = %s",
1649 print_hex_1 (result -> len,
1650 result -> data, 60));
1651 #endif
1652 return 1;
1653 }
1654
1655 /* The server cares about the client's hardware address,
1656 so only in the case where we are examining a packet can
1657 we return anything. */
1658 if (!packet || !packet -> raw) {
1659 log_error ("data: hardware: raw packet not available");
1660 return 0;
1661 }
1662 if (packet -> raw -> hlen > sizeof packet -> raw -> chaddr) {
1663 log_error ("data: hardware: invalid hlen (%d)\n",
1664 packet -> raw -> hlen);
1665 return 0;
1666 }
1667 result -> len = packet -> raw -> hlen + 1;
1668 if (buffer_allocate (&result -> buffer, result -> len,
1669 file, line)) {
1670 result -> data = &result -> buffer -> data [0];
1671 result -> buffer -> data [0] = packet -> raw -> htype;
1672 memcpy (&result -> buffer -> data [1],
1673 packet -> raw -> chaddr,
1674 packet -> raw -> hlen);
1675 result -> terminated = 0;
1676 } else {
1677 log_error ("data: hardware: no memory for buffer.");
1678 return 0;
1679 }
1680 #if defined (DEBUG_EXPRESSIONS)
1681 log_debug ("data: hardware = %s",
1682 print_hex_1 (result -> len, result -> data, 60));
1683 #endif
1684 return 1;
1685
1686 /* Extract part of the raw packet. */
1687 case expr_packet:
1688 if (!packet || !packet -> raw) {
1689 log_error ("data: packet: raw packet not available");
1690 return 0;
1691 }
1692
1693 s0 = evaluate_numeric_expression (&offset, packet, lease,
1694 client_state,
1695 in_options, cfg_options,
1696 scope,
1697 expr -> data.packet.offset);
1698 s1 = evaluate_numeric_expression (&len,
1699 packet, lease, client_state,
1700 in_options, cfg_options,
1701 scope,
1702 expr -> data.packet.len);
1703 if (s0 && s1 && offset < packet -> packet_length) {
1704 if (offset + len > packet -> packet_length)
1705 result -> len =
1706 packet -> packet_length - offset;
1707 else
1708 result -> len = len;
1709 if (buffer_allocate (&result -> buffer,
1710 result -> len, file, line)) {
1711 result -> data = &result -> buffer -> data [0];
1712 memcpy (result -> buffer -> data,
1713 (((unsigned char *)(packet -> raw))
1714 + offset), result -> len);
1715 result -> terminated = 0;
1716 } else {
1717 log_error ("data: packet: no buffer memory.");
1718 return 0;
1719 }
1720 s2 = 1;
1721 } else
1722 s2 = 0;
1723 #if defined (DEBUG_EXPRESSIONS)
1724 log_debug ("data: packet (%ld, %ld) = %s",
1725 offset, len,
1726 s2 ? print_hex_1 (result -> len,
1727 result -> data, 60) : NULL);
1728 #endif
1729 return s2;
1730
1731 /* The encapsulation of all defined options in an
1732 option space... */
1733 case expr_encapsulate:
1734 if (cfg_options)
1735 s0 = option_space_encapsulate
1736 (result, packet, lease, client_state,
1737 in_options, cfg_options, scope,
1738 &expr -> data.encapsulate);
1739 else
1740 s0 = 0;
1741
1742 #if defined (DEBUG_EXPRESSIONS)
1743 log_debug ("data: encapsulate (%s) = %s",
1744 expr -> data.encapsulate.data,
1745 s0 ? print_hex_1 (result -> len,
1746 result -> data, 60) : "NULL");
1747 #endif
1748 return s0;
1749
1750 /* Some constant data... */
1751 case expr_const_data:
1752 #if defined (DEBUG_EXPRESSIONS)
1753 log_debug ("data: const = %s",
1754 print_hex_1 (expr -> data.const_data.len,
1755 expr -> data.const_data.data, 60));
1756 #endif
1757 data_string_copy (result,
1758 &expr -> data.const_data, file, line);
1759 return 1;
1760
1761 /* Hostname lookup... */
1762 case expr_host_lookup:
1763 s0 = do_host_lookup (result, expr -> data.host_lookup);
1764 #if defined (DEBUG_EXPRESSIONS)
1765 log_debug ("data: DNS lookup (%s) = %s",
1766 expr -> data.host_lookup -> hostname,
1767 (s0
1768 ? print_dotted_quads (result -> len, result -> data)
1769 : "NULL"));
1770 #endif
1771 return s0;
1772
1773 /* Concatenation... */
1774 case expr_concat:
1775 memset (&data, 0, sizeof data);
1776 s0 = evaluate_data_expression (&data, packet, lease,
1777 client_state,
1778 in_options, cfg_options, scope,
1779 expr -> data.concat [0], MDL);
1780 memset (&other, 0, sizeof other);
1781 s1 = evaluate_data_expression (&other, packet, lease,
1782 client_state,
1783 in_options, cfg_options, scope,
1784 expr -> data.concat [1], MDL);
1785
1786 if (s0 && s1) {
1787 result -> len = data.len + other.len;
1788 if (!buffer_allocate (&result -> buffer,
1789 (result -> len + other.terminated),
1790 file, line)) {
1791 log_error ("data: concat: no memory");
1792 result -> len = 0;
1793 data_string_forget (&data, MDL);
1794 data_string_forget (&other, MDL);
1795 return 0;
1796 }
1797 result -> data = &result -> buffer -> data [0];
1798 memcpy (result -> buffer -> data, data.data, data.len);
1799 memcpy (&result -> buffer -> data [data.len],
1800 other.data, other.len + other.terminated);
1801 }
1802
1803 if (s0)
1804 data_string_forget (&data, MDL);
1805 if (s1)
1806 data_string_forget (&other, MDL);
1807 #if defined (DEBUG_EXPRESSIONS)
1808 log_debug ("data: concat (%s, %s) = %s",
1809 s0 ? print_hex_1 (data.len, data.data, 20) : "NULL",
1810 s1 ? print_hex_2 (other.len, other.data, 20) : "NULL",
1811 ((s0 && s1)
1812 ? print_hex_3 (result -> len, result -> data, 30)
1813 : "NULL"));
1814 #endif
1815 return s0 && s1;
1816
1817 case expr_encode_int8:
1818 s0 = evaluate_numeric_expression (&len, packet, lease,
1819 client_state,
1820 in_options, cfg_options,
1821 scope,
1822 expr -> data.encode_int);
1823 if (s0) {
1824 result -> len = 1;
1825 if (!buffer_allocate (&result -> buffer,
1826 1, file, line)) {
1827 log_error ("data: encode_int8: no memory");
1828 result -> len = 0;
1829 s0 = 0;
1830 } else {
1831 result -> data = &result -> buffer -> data [0];
1832 result -> buffer -> data [0] = len;
1833 }
1834 } else
1835 result -> len = 0;
1836
1837 #if defined (DEBUG_EXPRESSIONS)
1838 if (!s0)
1839 log_debug ("data: encode_int8 (NULL) = NULL");
1840 else
1841 log_debug ("data: encode_int8 (%ld) = %s", len,
1842 print_hex_2 (result -> len,
1843 result -> data, 20));
1844 #endif
1845 return s0;
1846
1847
1848 case expr_encode_int16:
1849 s0 = evaluate_numeric_expression (&len, packet, lease,
1850 client_state,
1851 in_options, cfg_options,
1852 scope,
1853 expr -> data.encode_int);
1854 if (s0) {
1855 result -> len = 2;
1856 if (!buffer_allocate (&result -> buffer, 2,
1857 file, line)) {
1858 log_error ("data: encode_int16: no memory");
1859 result -> len = 0;
1860 s0 = 0;
1861 } else {
1862 result -> data = &result -> buffer -> data [0];
1863 putUShort (result -> buffer -> data, len);
1864 }
1865 } else
1866 result -> len = 0;
1867
1868 #if defined (DEBUG_EXPRESSIONS)
1869 if (!s0)
1870 log_debug ("data: encode_int16 (NULL) = NULL");
1871 else
1872 log_debug ("data: encode_int16 (%ld) = %s", len,
1873 print_hex_2 (result -> len,
1874 result -> data, 20));
1875 #endif
1876 return s0;
1877
1878 case expr_encode_int32:
1879 s0 = evaluate_numeric_expression (&len, packet, lease,
1880 client_state,
1881 in_options, cfg_options,
1882 scope,
1883 expr -> data.encode_int);
1884 if (s0) {
1885 result -> len = 4;
1886 if (!buffer_allocate (&result -> buffer, 4,
1887 file, line)) {
1888 log_error ("data: encode_int32: no memory");
1889 result -> len = 0;
1890 s0 = 0;
1891 } else {
1892 result -> data = &result -> buffer -> data [0];
1893 putULong (result -> buffer -> data, len);
1894 }
1895 } else
1896 result -> len = 0;
1897
1898 #if defined (DEBUG_EXPRESSIONS)
1899 if (!s0)
1900 log_debug ("data: encode_int32 (NULL) = NULL");
1901 else
1902 log_debug ("data: encode_int32 (%ld) = %s", len,
1903 print_hex_2 (result -> len,
1904 result -> data, 20));
1905 #endif
1906 return s0;
1907
1908 case expr_binary_to_ascii:
1909 /* Evaluate the base (offset) and width (len): */
1910 s0 = evaluate_numeric_expression
1911 (&offset, packet, lease, client_state, in_options,
1912 cfg_options, scope, expr -> data.b2a.base);
1913 s1 = evaluate_numeric_expression (&len, packet, lease,
1914 client_state,
1915 in_options, cfg_options,
1916 scope,
1917 expr -> data.b2a.width);
1918
1919 /* Evaluate the separator string. */
1920 memset (&data, 0, sizeof data);
1921 s2 = evaluate_data_expression (&data, packet, lease,
1922 client_state,
1923 in_options, cfg_options, scope,
1924 expr -> data.b2a.separator,
1925 MDL);
1926
1927 /* Evaluate the data to be converted. */
1928 memset (&other, 0, sizeof other);
1929 s3 = evaluate_data_expression (&other, packet, lease,
1930 client_state,
1931 in_options, cfg_options, scope,
1932 expr -> data.b2a.buffer, MDL);
1933
1934 if (s0 && s1 && s2 && s3) {
1935 unsigned buflen, i;
1936
1937 if (len != 8 && len != 16 && len != 32) {
1938 log_info ("binary_to_ascii: %s %ld!",
1939 "invalid width", len);
1940 status = 0;
1941 goto b2a_out;
1942 }
1943 len /= 8;
1944
1945 /* The buffer must be a multiple of the number's
1946 width. */
1947 if (other.len % len) {
1948 log_info ("binary-to-ascii: %s %d %s %ld!",
1949 "length of buffer", other.len,
1950 "not a multiple of width", len);
1951 status = 0;
1952 goto b2a_out;
1953 }
1954
1955 /* Count the width of the output. */
1956 buflen = 0;
1957 for (i = 0; i < other.len; i += len) {
1958 if (len == 1) {
1959 if (offset == 8) {
1960 if (other.data [i] < 8)
1961 buflen++;
1962 else if (other.data [i] < 64)
1963 buflen += 2;
1964 else
1965 buflen += 3;
1966 } else if (offset == 10) {
1967 if (other.data [i] < 10)
1968 buflen++;
1969 else if (other.data [i] < 100)
1970 buflen += 2;
1971 else
1972 buflen += 3;
1973 } else if (offset == 16) {
1974 if (other.data [i] < 16)
1975 buflen++;
1976 else
1977 buflen += 2;
1978 } else
1979 buflen += (converted_length
1980 (&other.data [i],
1981 offset, 1));
1982 } else
1983 buflen += (converted_length
1984 (&other.data [i],
1985 offset, len));
1986 if (i + len != other.len)
1987 buflen += data.len;
1988 }
1989
1990 if (!buffer_allocate (&result -> buffer,
1991 buflen + 1, file, line)) {
1992 log_error ("data: binary-to-ascii: no memory");
1993 status = 0;
1994 goto b2a_out;
1995 }
1996 result -> data = &result -> buffer -> data [0];
1997 result -> len = buflen;
1998 result -> terminated = 1;
1999
2000 buflen = 0;
2001 for (i = 0; i < other.len; i += len) {
2002 buflen += (binary_to_ascii
2003 (&result -> buffer -> data [buflen],
2004 &other.data [i], offset, len));
2005 if (i + len != other.len) {
2006 memcpy (&result ->
2007 buffer -> data [buflen],
2008 data.data, data.len);
2009 buflen += data.len;
2010 }
2011 }
2012 /* NUL terminate. */
2013 result -> buffer -> data [buflen] = 0;
2014 status = 1;
2015 } else
2016 status = 0;
2017
2018 b2a_out:
2019 #if defined (DEBUG_EXPRESSIONS)
2020 log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
2021 s0 ? print_dec_1 (offset) : "NULL",
2022 s1 ? print_dec_2 (len) : "NULL",
2023 s2 ? print_hex_1 (data.len, data.data, 30) : "NULL",
2024 s3 ? print_hex_2 (other.len, other.data, 30) : "NULL",
2025 (status ? print_hex_3 (result -> len, result -> data, 30)
2026 : "NULL"));
2027 #endif
2028 if (s2)
2029 data_string_forget (&data, MDL);
2030 if (s3)
2031 data_string_forget (&other, MDL);
2032 if (status)
2033 return 1;
2034 return 0;
2035
2036 case expr_reverse:
2037 /* Evaluate the width (len): */
2038 s0 = evaluate_numeric_expression
2039 (&len, packet, lease, client_state, in_options,
2040 cfg_options, scope, expr -> data.reverse.width);
2041
2042 /* Evaluate the data. */
2043 memset (&data, 0, sizeof data);
2044 s1 = evaluate_data_expression (&data, packet, lease,
2045 client_state,
2046 in_options, cfg_options, scope,
2047 expr -> data.reverse.buffer,
2048 MDL);
2049
2050 if (s0 && s1) {
2051 char *upper;
2052 int i;
2053
2054 /* The buffer must be a multiple of the number's
2055 width. */
2056 if (data.len % len) {
2057 log_info ("reverse: %s %d %s %ld!",
2058 "length of buffer", data.len,
2059 "not a multiple of width", len);
2060 status = 0;
2061 goto reverse_out;
2062 }
2063
2064 /* XXX reverse in place? I don't think we can. */
2065 if (!buffer_allocate (&result -> buffer,
2066 data.len, file, line)) {
2067 log_error ("data: reverse: no memory");
2068 status = 0;
2069 goto reverse_out;
2070 }
2071 result -> data = &result -> buffer -> data [0];
2072 result -> len = data.len;
2073 result -> terminated = 0;
2074
2075 for (i = 0; i < data.len; i += len) {
2076 memcpy (&result -> buffer -> data [i],
2077 &data.data [data.len - i - len], len);
2078 }
2079 status = 1;
2080 } else
2081 status = 0;
2082
2083 reverse_out:
2084 #if defined (DEBUG_EXPRESSIONS)
2085 log_debug ("data: reverse (%s, %s) = %s",
2086 s0 ? print_dec_1 (len) : "NULL",
2087 s1 ? print_hex_1 (data.len, data.data, 30) : "NULL",
2088 (status ? print_hex_3 (result -> len, result -> data, 30)
2089 : "NULL"));
2090 #endif
2091 if (s0)
2092 data_string_forget (&data, MDL);
2093 if (status)
2094 return 1;
2095 return 0;
2096
2097 case expr_leased_address:
2098 if (!lease) {
2099 log_debug("data: \"leased-address\" configuration "
2100 "directive: there is no lease associated "
2101 "with this client.");
2102 return 0;
2103 }
2104 result -> len = lease -> ip_addr.len;
2105 if (buffer_allocate (&result -> buffer, result -> len,
2106 file, line)) {
2107 result -> data = &result -> buffer -> data [0];
2108 memcpy (&result -> buffer -> data [0],
2109 lease -> ip_addr.iabuf, lease -> ip_addr.len);
2110 result -> terminated = 0;
2111 } else {
2112 log_error ("data: leased-address: no memory.");
2113 return 0;
2114 }
2115 #if defined (DEBUG_EXPRESSIONS)
2116 log_debug ("data: leased-address = %s",
2117 print_hex_1 (result -> len, result -> data, 60));
2118 #endif
2119 return 1;
2120
2121 case expr_pick_first_value:
2122 memset (&data, 0, sizeof data);
2123 if ((evaluate_data_expression
2124 (result, packet,
2125 lease, client_state, in_options, cfg_options,
2126 scope, expr -> data.pick_first_value.car, MDL))) {
2127 #if defined (DEBUG_EXPRESSIONS)
2128 log_debug ("data: pick_first_value (%s, xxx)",
2129 print_hex_1 (result -> len,
2130 result -> data, 40));
2131 #endif
2132 return 1;
2133 }
2134
2135 if (expr -> data.pick_first_value.cdr &&
2136 (evaluate_data_expression
2137 (result, packet,
2138 lease, client_state, in_options, cfg_options,
2139 scope, expr -> data.pick_first_value.cdr, MDL))) {
2140 #if defined (DEBUG_EXPRESSIONS)
2141 log_debug ("data: pick_first_value (NULL, %s)",
2142 print_hex_1 (result -> len,
2143 result -> data, 40));
2144 #endif
2145 return 1;
2146 }
2147
2148 #if defined (DEBUG_EXPRESSIONS)
2149 log_debug ("data: pick_first_value (NULL, NULL) = NULL");
2150 #endif
2151 return 0;
2152
2153 case expr_host_decl_name:
2154 if (!lease || !lease -> host) {
2155 log_error ("data: host_decl_name: not available");
2156 return 0;
2157 }
2158 result -> len = strlen (lease -> host -> name);
2159 if (buffer_allocate (&result -> buffer,
2160 result -> len + 1, file, line)) {
2161 result -> data = &result -> buffer -> data [0];
2162 strcpy ((char *)&result -> buffer -> data [0],
2163 lease -> host -> name);
2164 result -> terminated = 1;
2165 } else {
2166 log_error ("data: host-decl-name: no memory.");
2167 return 0;
2168 }
2169 #if defined (DEBUG_EXPRESSIONS)
2170 log_debug ("data: host-decl-name = %s", lease -> host -> name);
2171 #endif
2172 return 1;
2173
2174 case expr_null:
2175 #if defined (DEBUG_EXPRESSIONS)
2176 log_debug ("data: null = NULL");
2177 #endif
2178 return 0;
2179
2180 case expr_variable_reference:
2181 if (scope && *scope) {
2182 binding = find_binding (*scope, expr -> data.variable);
2183
2184 if (binding && binding -> value) {
2185 if (binding -> value -> type == binding_data) {
2186 data_string_copy (result,
2187 &binding -> value -> value.data,
2188 file, line);
2189 s0 = 1;
2190 } else if (binding -> value -> type != binding_data) {
2191 log_error ("binding type %d in %s.",
2192 binding -> value -> type,
2193 "evaluate_data_expression");
2194 s0 = 0;
2195 } else
2196 s0 = 0;
2197 } else
2198 s0 = 0;
2199 } else
2200 s0 = 0;
2201 #if defined (DEBUG_EXPRESSIONS)
2202 log_debug ("data: %s = %s", expr -> data.variable,
2203 s0 ? print_hex_1 (result -> len,
2204 result -> data, 50) : "NULL");
2205 #endif
2206 return s0;
2207
2208 case expr_funcall:
2209 bv = (struct binding_value *)0;
2210 s0 = evaluate_expression (&bv, packet, lease, client_state,
2211 in_options, cfg_options,
2212 scope, expr, MDL);
2213 if (s0) {
2214 if (bv -> type != binding_data)
2215 log_error ("%s() returned type %d in %s.",
2216 expr -> data.funcall.name,
2217 bv -> type,
2218 "evaluate_data_expression");
2219 else
2220 data_string_copy (result, &bv -> value.data,
2221 file, line);
2222 binding_value_dereference (&bv, MDL);
2223 }
2224 #if defined (DEBUG_EXPRESSIONS)
2225 log_debug ("data: %s = %s", expr -> data.funcall.name,
2226 s0 ? print_hex_1 (result -> len,
2227 result -> data, 50) : "NULL");
2228 #endif
2229 break;
2230
2231 /* Extract the filename. */
2232 case expr_filename:
2233 if (packet && packet -> raw -> file [0]) {
2234 char *fn =
2235 memchr (packet -> raw -> file, 0,
2236 sizeof packet -> raw -> file);
2237 if (!fn)
2238 fn = ((char *)packet -> raw -> file +
2239 sizeof packet -> raw -> file);
2240 result -> len = fn - &(packet -> raw -> file [0]);
2241 if (buffer_allocate (&result -> buffer,
2242 result -> len + 1, file, line)) {
2243 result -> data = &result -> buffer -> data [0];
2244 memcpy (&result -> buffer -> data [0],
2245 packet -> raw -> file,
2246 result -> len);
2247 result -> buffer -> data [result -> len] = 0;
2248 result -> terminated = 1;
2249 s0 = 1;
2250 } else {
2251 log_error ("data: filename: no memory.");
2252 s0 = 0;
2253 }
2254 } else
2255 s0 = 0;
2256
2257 #if defined (DEBUG_EXPRESSIONS)
2258 log_info ("data: filename = \"%s\"",
2259 s0 ? (const char *)(result -> data) : "NULL");
2260 #endif
2261 return s0;
2262
2263 /* Extract the server name. */
2264 case expr_sname:
2265 if (packet && packet -> raw -> sname [0]) {
2266 char *fn =
2267 memchr (packet -> raw -> sname, 0,
2268 sizeof packet -> raw -> sname);
2269 if (!fn)
2270 fn = ((char *)packet -> raw -> sname +
2271 sizeof packet -> raw -> sname);
2272 result -> len = fn - &packet -> raw -> sname [0];
2273 if (buffer_allocate (&result -> buffer,
2274 result -> len + 1, file, line)) {
2275 result -> data = &result -> buffer -> data [0];
2276 memcpy (&result -> buffer -> data [0],
2277 packet -> raw -> sname,
2278 result -> len);
2279 result -> buffer -> data [result -> len] = 0;
2280 result -> terminated = 1;
2281 s0 = 1;
2282 } else {
2283 log_error ("data: sname: no memory.");
2284 s0 = 0;
2285 }
2286 } else
2287 s0 = 0;
2288
2289 #if defined (DEBUG_EXPRESSIONS)
2290 log_info ("data: sname = \"%s\"",
2291 s0 ? (const char *)(result -> data) : "NULL");
2292 #endif
2293 return s0;
2294
2295 case expr_check:
2296 case expr_equal:
2297 case expr_not_equal:
2298 case expr_and:
2299 case expr_or:
2300 case expr_not:
2301 case expr_match:
2302 case expr_static:
2303 case expr_known:
2304 case expr_none:
2305 case expr_exists:
2306 case expr_variable_exists:
2307 log_error ("Boolean opcode in evaluate_data_expression: %d",
2308 expr -> op);
2309 return 0;
2310
2311 case expr_extract_int8:
2312 case expr_extract_int16:
2313 case expr_extract_int32:
2314 case expr_const_int:
2315 case expr_lease_time:
2316 case expr_dns_transaction:
2317 case expr_add:
2318 case expr_subtract:
2319 case expr_multiply:
2320 case expr_divide:
2321 case expr_remainder:
2322 case expr_binary_and:
2323 case expr_binary_or:
2324 case expr_binary_xor:
2325 case expr_client_state:
2326 log_error ("Numeric opcode in evaluate_data_expression: %d",
2327 expr -> op);
2328 return 0;
2329
2330 case expr_ns_add:
2331 case expr_ns_delete:
2332 case expr_ns_exists:
2333 case expr_ns_not_exists:
2334 log_error ("dns update opcode in evaluate_data_expression: %d",
2335 expr -> op);
2336 return 0;
2337
2338 case expr_function:
2339 log_error ("function definition in evaluate_data_expression");
2340 return 0;
2341
2342 case expr_arg:
2343 break;
2344 }
2345
2346 log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op);
2347 return 0;
2348 }
2349
2350 int evaluate_numeric_expression (result, packet, lease, client_state,
2351 in_options, cfg_options, scope, expr)
2352 unsigned long *result;
2353 struct packet *packet;
2354 struct lease *lease;
2355 struct client_state *client_state;
2356 struct option_state *in_options;
2357 struct option_state *cfg_options;
2358 struct binding_scope **scope;
2359 struct expression *expr;
2360 {
2361 struct data_string data;
2362 int status, sleft, sright;
2363 #if defined (NSUPDATE)
2364 ns_updrec *nut;
2365 ns_updque uq;
2366 #endif
2367 struct expression *cur, *next;
2368 struct binding *binding;
2369 struct binding_value *bv;
2370 unsigned long ileft, iright;
2371
2372 switch (expr -> op) {
2373 case expr_check:
2374 case expr_equal:
2375 case expr_not_equal:
2376 case expr_and:
2377 case expr_or:
2378 case expr_not:
2379 case expr_match:
2380 case expr_static:
2381 case expr_known:
2382 case expr_none:
2383 case expr_exists:
2384 case expr_variable_exists:
2385 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
2386 expr -> op);
2387 return 0;
2388
2389 case expr_substring:
2390 case expr_suffix:
2391 case expr_lcase:
2392 case expr_ucase:
2393 case expr_option:
2394 case expr_hardware:
2395 case expr_const_data:
2396 case expr_packet:
2397 case expr_concat:
2398 case expr_encapsulate:
2399 case expr_host_lookup:
2400 case expr_encode_int8:
2401 case expr_encode_int16:
2402 case expr_encode_int32:
2403 case expr_binary_to_ascii:
2404 case expr_reverse:
2405 case expr_filename:
2406 case expr_sname:
2407 case expr_pick_first_value:
2408 case expr_host_decl_name:
2409 case expr_config_option:
2410 case expr_leased_address:
2411 case expr_null:
2412 log_error ("Data opcode in evaluate_numeric_expression: %d",
2413 expr -> op);
2414 return 0;
2415
2416 case expr_extract_int8:
2417 memset (&data, 0, sizeof data);
2418 status = evaluate_data_expression
2419 (&data, packet, lease, client_state, in_options,
2420 cfg_options, scope, expr -> data.extract_int, MDL);
2421 if (status)
2422 *result = data.data [0];
2423 #if defined (DEBUG_EXPRESSIONS)
2424 log_debug ("num: extract_int8 (%s) = %s",
2425 status ? print_hex_1 (data.len, data.data, 60) : "NULL",
2426 status ? print_dec_1 (*result) : "NULL" );
2427 #endif
2428 if (status) data_string_forget (&data, MDL);
2429 return status;
2430
2431 case expr_extract_int16:
2432 memset (&data, 0, sizeof data);
2433 status = (evaluate_data_expression
2434 (&data, packet, lease, client_state, in_options,
2435 cfg_options, scope, expr -> data.extract_int, MDL));
2436 if (status && data.len >= 2)
2437 *result = getUShort (data.data);
2438 #if defined (DEBUG_EXPRESSIONS)
2439 log_debug ("num: extract_int16 (%s) = %ld",
2440 ((status && data.len >= 2) ?
2441 print_hex_1 (data.len, data.data, 60) : "NULL"),
2442 *result);
2443 #endif
2444 if (status) data_string_forget (&data, MDL);
2445 return (status && data.len >= 2);
2446
2447 case expr_extract_int32:
2448 memset (&data, 0, sizeof data);
2449 status = (evaluate_data_expression
2450 (&data, packet, lease, client_state, in_options,
2451 cfg_options, scope, expr -> data.extract_int, MDL));
2452 if (status && data.len >= 4)
2453 *result = getULong (data.data);
2454 #if defined (DEBUG_EXPRESSIONS)
2455 log_debug ("num: extract_int32 (%s) = %ld",
2456 ((status && data.len >= 4) ?
2457 print_hex_1 (data.len, data.data, 60) : "NULL"),
2458 *result);
2459 #endif
2460 if (status) data_string_forget (&data, MDL);
2461 return (status && data.len >= 4);
2462
2463 case expr_const_int:
2464 *result = expr -> data.const_int;
2465 #if defined (DEBUG_EXPRESSIONS)
2466 log_debug ("number: CONSTANT = %ld", *result);
2467 #endif
2468 return 1;
2469
2470 case expr_lease_time:
2471 if (!lease) {
2472 log_error ("data: leased_lease: not available");
2473 return 0;
2474 }
2475 if (lease -> ends < cur_time) {
2476 log_error ("%s %lu when it is now %lu",
2477 "data: lease_time: lease ends at",
2478 (long)(lease -> ends), (long)cur_time);
2479 return 0;
2480 }
2481 *result = lease -> ends - cur_time;
2482 #if defined (DEBUG_EXPRESSIONS)
2483 log_debug ("number: lease-time = (%lu - %lu) = %ld",
2484 lease -> ends,
2485 cur_time, *result);
2486 #endif
2487 return 1;
2488
2489 case expr_dns_transaction:
2490 #if !defined (NSUPDATE)
2491 return 0;
2492 #else
2493 if (!resolver_inited) {
2494 minires_ninit (&resolver_state);
2495 resolver_inited = 1;
2496 resolver_state.retrans = 1;
2497 resolver_state.retry = 1;
2498 }
2499 ISC_LIST_INIT (uq);
2500 cur = expr;
2501 do {
2502 next = cur -> data.dns_transaction.cdr;
2503 nut = 0;
2504 status = (evaluate_dns_expression
2505 (&nut, packet,
2506 lease, client_state, in_options, cfg_options,
2507 scope, cur -> data.dns_transaction.car));
2508 if (!status)
2509 goto dns_bad;
2510 ISC_LIST_APPEND (uq, nut, r_link);
2511 cur = next;
2512 } while (next);
2513
2514 /* Do the update and record the error code, if there was
2515 an error; otherwise set it to NOERROR. */
2516 *result = minires_nupdate (&resolver_state,
2517 ISC_LIST_HEAD (uq));
2518 status = 1;
2519
2520 print_dns_status ((int)*result, &uq);
2521
2522 dns_bad:
2523 while (!ISC_LIST_EMPTY (uq)) {
2524 ns_updrec *tmp = ISC_LIST_HEAD (uq);
2525 ISC_LIST_UNLINK (uq, tmp, r_link);
2526 if (tmp -> r_data_ephem) {
2527 dfree (tmp -> r_data_ephem, MDL);
2528 tmp -> r_data = (unsigned char *)0;
2529 tmp -> r_data_ephem = (unsigned char *)0;
2530 }
2531 minires_freeupdrec (tmp);
2532 }
2533 return status;
2534 #endif /* NSUPDATE */
2535
2536 case expr_variable_reference:
2537 if (scope && *scope) {
2538 binding = find_binding (*scope, expr -> data.variable);
2539
2540 if (binding && binding -> value) {
2541 if (binding -> value -> type == binding_numeric) {
2542 *result = binding -> value -> value.intval;
2543 status = 1;
2544 } else {
2545 log_error ("binding type %d in %s.",
2546 binding -> value -> type,
2547 "evaluate_numeric_expression");
2548 status = 0;
2549 }
2550 } else
2551 status = 0;
2552 } else
2553 status = 0;
2554 #if defined (DEBUG_EXPRESSIONS)
2555 if (status)
2556 log_debug ("numeric: %s = %ld",
2557 expr -> data.variable, *result);
2558 else
2559 log_debug ("numeric: %s = NULL",
2560 expr -> data.variable);
2561 #endif
2562 return status;
2563
2564 case expr_funcall:
2565 bv = (struct binding_value *)0;
2566 status = evaluate_expression (&bv, packet, lease,
2567 client_state,
2568 in_options, cfg_options,
2569 scope, expr, MDL);
2570 if (status) {
2571 if (bv -> type != binding_numeric)
2572 log_error ("%s() returned type %d in %s.",
2573 expr -> data.funcall.name,
2574 bv -> type,
2575 "evaluate_numeric_expression");
2576 else
2577 *result = bv -> value.intval;
2578 binding_value_dereference (&bv, MDL);
2579 }
2580 #if defined (DEBUG_EXPRESSIONS)
2581 log_debug ("data: %s = %ld", expr -> data.funcall.name,
2582 status ? *result : 0);
2583 #endif
2584 break;
2585
2586 case expr_add:
2587 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2588 client_state,
2589 in_options, cfg_options,
2590 scope,
2591 expr -> data.and [0]);
2592 sright = evaluate_numeric_expression (&iright, packet, lease,
2593 client_state,
2594 in_options, cfg_options,
2595 scope,
2596 expr -> data.and [1]);
2597
2598 #if defined (DEBUG_EXPRESSIONS)
2599 if (sleft && sright)
2600 log_debug ("num: %ld + %ld = %ld",
2601 ileft, iright, ileft + iright);
2602 else if (sleft)
2603 log_debug ("num: %ld + NULL = NULL", ileft);
2604 else
2605 log_debug ("num: NULL + %ld = NULL", iright);
2606 #endif
2607 if (sleft && sright) {
2608 *result = ileft + iright;
2609 return 1;
2610 }
2611 return 0;
2612
2613 case expr_subtract:
2614 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2615 client_state,
2616 in_options, cfg_options,
2617 scope,
2618 expr -> data.and [0]);
2619 sright = evaluate_numeric_expression (&iright, packet, lease,
2620 client_state,
2621 in_options, cfg_options,
2622 scope,
2623 expr -> data.and [1]);
2624
2625 #if defined (DEBUG_EXPRESSIONS)
2626 if (sleft && sright)
2627 log_debug ("num: %ld - %ld = %ld",
2628 ileft, iright, ileft - iright);
2629 else if (sleft)
2630 log_debug ("num: %ld - NULL = NULL", ileft);
2631 else
2632 log_debug ("num: NULL - %ld = NULL", iright);
2633 #endif
2634 if (sleft && sright) {
2635 *result = ileft - iright;
2636 return 1;
2637 }
2638 return 0;
2639
2640 case expr_multiply:
2641 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2642 client_state,
2643 in_options, cfg_options,
2644 scope,
2645 expr -> data.and [0]);
2646 sright = evaluate_numeric_expression (&iright, packet, lease,
2647 client_state,
2648 in_options, cfg_options,
2649 scope,
2650 expr -> data.and [1]);
2651
2652 #if defined (DEBUG_EXPRESSIONS)
2653 if (sleft && sright)
2654 log_debug ("num: %ld * %ld = %ld",
2655 ileft, iright, ileft * iright);
2656 else if (sleft)
2657 log_debug ("num: %ld * NULL = NULL", ileft);
2658 else
2659 log_debug ("num: NULL * %ld = NULL", iright);
2660 #endif
2661 if (sleft && sright) {
2662 *result = ileft * iright;
2663 return 1;
2664 }
2665 return 0;
2666
2667 case expr_divide:
2668 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2669 client_state,
2670 in_options, cfg_options,
2671 scope,
2672 expr -> data.and [0]);
2673 sright = evaluate_numeric_expression (&iright, packet, lease,
2674 client_state,
2675 in_options, cfg_options,
2676 scope,
2677 expr -> data.and [1]);
2678
2679 #if defined (DEBUG_EXPRESSIONS)
2680 if (sleft && sright) {
2681 if (iright != 0)
2682 log_debug ("num: %ld / %ld = %ld",
2683 ileft, iright, ileft / iright);
2684 else
2685 log_debug ("num: %ld / %ld = NULL",
2686 ileft, iright);
2687 } else if (sleft)
2688 log_debug ("num: %ld / NULL = NULL", ileft);
2689 else
2690 log_debug ("num: NULL / %ld = NULL", iright);
2691 #endif
2692 if (sleft && sright && iright) {
2693 *result = ileft / iright;
2694 return 1;
2695 }
2696 return 0;
2697
2698 case expr_remainder:
2699 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2700 client_state,
2701 in_options, cfg_options,
2702 scope,
2703 expr -> data.and [0]);
2704 sright = evaluate_numeric_expression (&iright, packet, lease,
2705 client_state,
2706 in_options, cfg_options,
2707 scope,
2708 expr -> data.and [1]);
2709
2710 #if defined (DEBUG_EXPRESSIONS)
2711 if (sleft && sright) {
2712 if (iright != 0)
2713 log_debug ("num: %ld %% %ld = %ld",
2714 ileft, iright, ileft % iright);
2715 else
2716 log_debug ("num: %ld %% %ld = NULL",
2717 ileft, iright);
2718 } else if (sleft)
2719 log_debug ("num: %ld %% NULL = NULL", ileft);
2720 else
2721 log_debug ("num: NULL %% %ld = NULL", iright);
2722 #endif
2723 if (sleft && sright && iright) {
2724 *result = ileft % iright;
2725 return 1;
2726 }
2727 return 0;
2728
2729 case expr_binary_and:
2730 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2731 client_state,
2732 in_options, cfg_options,
2733 scope,
2734 expr -> data.and [0]);
2735 sright = evaluate_numeric_expression (&iright, packet, lease,
2736 client_state,
2737 in_options, cfg_options,
2738 scope,
2739 expr -> data.and [1]);
2740
2741 #if defined (DEBUG_EXPRESSIONS)
2742 if (sleft && sright)
2743 log_debug ("num: %ld | %ld = %ld",
2744 ileft, iright, ileft & iright);
2745 else if (sleft)
2746 log_debug ("num: %ld & NULL = NULL", ileft);
2747 else
2748 log_debug ("num: NULL & %ld = NULL", iright);
2749 #endif
2750 if (sleft && sright) {
2751 *result = ileft & iright;
2752 return 1;
2753 }
2754 return 0;
2755
2756 case expr_binary_or:
2757 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2758 client_state,
2759 in_options, cfg_options,
2760 scope,
2761 expr -> data.and [0]);
2762 sright = evaluate_numeric_expression (&iright, packet, lease,
2763 client_state,
2764 in_options, cfg_options,
2765 scope,
2766 expr -> data.and [1]);
2767
2768 #if defined (DEBUG_EXPRESSIONS)
2769 if (sleft && sright)
2770 log_debug ("num: %ld | %ld = %ld",
2771 ileft, iright, ileft | iright);
2772 else if (sleft)
2773 log_debug ("num: %ld | NULL = NULL", ileft);
2774 else
2775 log_debug ("num: NULL | %ld = NULL", iright);
2776 #endif
2777 if (sleft && sright) {
2778 *result = ileft | iright;
2779 return 1;
2780 }
2781 return 0;
2782
2783 case expr_binary_xor:
2784 sleft = evaluate_numeric_expression (&ileft, packet, lease,
2785 client_state,
2786 in_options, cfg_options,
2787 scope,
2788 expr -> data.and [0]);
2789 sright = evaluate_numeric_expression (&iright, packet, lease,
2790 client_state,
2791 in_options, cfg_options,
2792 scope,
2793 expr -> data.and [1]);
2794
2795 #if defined (DEBUG_EXPRESSIONS)
2796 if (sleft && sright)
2797 log_debug ("num: %ld ^ %ld = %ld",
2798 ileft, iright, ileft ^ iright);
2799 else if (sleft)
2800 log_debug ("num: %ld ^ NULL = NULL", ileft);
2801 else
2802 log_debug ("num: NULL ^ %ld = NULL", iright);
2803 #endif
2804 if (sleft && sright) {
2805 *result = ileft ^ iright;
2806 return 1;
2807 }
2808 return 0;
2809
2810 case expr_client_state:
2811 if (client_state) {
2812 #if defined (DEBUG_EXPRESSIONS)
2813 log_debug ("num: client-state = %d",
2814 client_state -> state);
2815 #endif
2816 *result = client_state -> state;
2817 return 1;
2818 } else {
2819 #if defined (DEBUG_EXPRESSIONS)
2820 log_debug ("num: client-state = NULL");
2821 #endif
2822 return 0;
2823 }
2824
2825 case expr_ns_add:
2826 case expr_ns_delete:
2827 case expr_ns_exists:
2828 case expr_ns_not_exists:
2829 log_error ("dns opcode in evaluate_numeric_expression: %d",
2830 expr -> op);
2831 return 0;
2832
2833 case expr_function:
2834 log_error ("function definition in evaluate_numeric_expr");
2835 return 0;
2836
2837 case expr_arg:
2838 break;
2839
2840 default:
2841 log_fatal("Impossible case at %s:%d. Undefined operator "
2842 "%d.", MDL, expr->op);
2843 break;
2844 }
2845
2846 log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op);
2847 return 0;
2848 }
2849
2850 /* Return data hanging off of an option cache structure, or if there
2851 isn't any, evaluate the expression hanging off of it and return the
2852 result of that evaluation. There should never be both an expression
2853 and a valid data_string. */
2854
2855 int evaluate_option_cache (result, packet, lease, client_state,
2856 in_options, cfg_options, scope, oc, file, line)
2857 struct data_string *result;
2858 struct packet *packet;
2859 struct lease *lease;
2860 struct client_state *client_state;
2861 struct option_state *in_options;
2862 struct option_state *cfg_options;
2863 struct binding_scope **scope;
2864 struct option_cache *oc;
2865 const char *file;
2866 int line;
2867 {
2868 if (oc->data.data != NULL) {
2869 data_string_copy (result, &oc -> data, file, line);
2870 return 1;
2871 }
2872 if (!oc -> expression)
2873 return 0;
2874 return evaluate_data_expression (result, packet, lease, client_state,
2875 in_options, cfg_options, scope,
2876 oc -> expression, file, line);
2877 }
2878
2879 /* Evaluate an option cache and extract a boolean from the result,
2880 returning the boolean. Return false if there is no data. */
2881
2882 int evaluate_boolean_option_cache (ignorep, packet,
2883 lease, client_state, in_options,
2884 cfg_options, scope, oc, file, line)
2885 int *ignorep;
2886 struct packet *packet;
2887 struct lease *lease;
2888 struct client_state *client_state;
2889 struct option_state *in_options;
2890 struct option_state *cfg_options;
2891 struct binding_scope **scope;
2892 struct option_cache *oc;
2893 const char *file;
2894 int line;
2895 {
2896 struct data_string ds;
2897 int result;
2898
2899 /* So that we can be called with option_lookup as an argument. */
2900 if (!oc || !in_options)
2901 return 0;
2902
2903 memset (&ds, 0, sizeof ds);
2904 if (!evaluate_option_cache (&ds, packet,
2905 lease, client_state, in_options,
2906 cfg_options, scope, oc, file, line))
2907 return 0;
2908
2909 if (ds.len) {
2910 result = ds.data [0];
2911 if (result == 2) {
2912 result = 0;
2913 *ignorep = 1;
2914 } else
2915 *ignorep = 0;
2916 } else
2917 result = 0;
2918 data_string_forget (&ds, MDL);
2919 return result;
2920 }
2921
2922
2923 /* Evaluate a boolean expression and return the result of the evaluation,
2924 or FALSE if it failed. */
2925
2926 int evaluate_boolean_expression_result (ignorep, packet, lease, client_state,
2927 in_options, cfg_options, scope, expr)
2928 int *ignorep;
2929 struct packet *packet;
2930 struct lease *lease;
2931 struct client_state *client_state;
2932 struct option_state *in_options;
2933 struct option_state *cfg_options;
2934 struct binding_scope **scope;
2935 struct expression *expr;
2936 {
2937 int result;
2938
2939 /* So that we can be called with option_lookup as an argument. */
2940 if (!expr)
2941 return 0;
2942
2943 if (!evaluate_boolean_expression (&result, packet, lease, client_state,
2944 in_options, cfg_options,
2945 scope, expr))
2946 return 0;
2947
2948 if (result == 2) {
2949 *ignorep = 1;
2950 result = 0;
2951 } else
2952 *ignorep = 0;
2953 return result;
2954 }
2955
2956
2957 /* Dereference an expression node, and if the reference count goes to zero,
2958 dereference any data it refers to, and then free it. */
2959 void expression_dereference (eptr, file, line)
2960 struct expression **eptr;
2961 const char *file;
2962 int line;
2963 {
2964 struct expression *expr = *eptr;
2965
2966 /* Zero the pointer. */
2967 *eptr = (struct expression *)0;
2968
2969 /* Decrement the reference count. If it's nonzero, we're
2970 done. */
2971 --(expr -> refcnt);
2972 rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC);
2973 if (expr -> refcnt > 0)
2974 return;
2975 if (expr -> refcnt < 0) {
2976 log_error ("%s(%d): negative refcnt!", file, line);
2977 #if defined (DEBUG_RC_HISTORY)
2978 dump_rc_history (expr);
2979 #endif
2980 #if defined (POINTER_DEBUG)
2981 abort ();
2982 #else
2983 return;
2984 #endif
2985 }
2986
2987 /* Dereference subexpressions. */
2988 switch (expr -> op) {
2989 /* All the binary operators can be handled the same way. */
2990 case expr_equal:
2991 case expr_not_equal:
2992 case expr_concat:
2993 case expr_and:
2994 case expr_or:
2995 case expr_add:
2996 case expr_subtract:
2997 case expr_multiply:
2998 case expr_divide:
2999 case expr_remainder:
3000 case expr_binary_and:
3001 case expr_binary_or:
3002 case expr_binary_xor:
3003 case expr_client_state:
3004 if (expr -> data.equal [0])
3005 expression_dereference (&expr -> data.equal [0],
3006 file, line);
3007 if (expr -> data.equal [1])
3008 expression_dereference (&expr -> data.equal [1],
3009 file, line);
3010 break;
3011
3012 case expr_substring:
3013 if (expr -> data.substring.expr)
3014 expression_dereference (&expr -> data.substring.expr,
3015 file, line);
3016 if (expr -> data.substring.offset)
3017 expression_dereference (&expr -> data.substring.offset,
3018 file, line);
3019 if (expr -> data.substring.len)
3020 expression_dereference (&expr -> data.substring.len,
3021 file, line);
3022 break;
3023
3024 case expr_suffix:
3025 if (expr -> data.suffix.expr)
3026 expression_dereference (&expr -> data.suffix.expr,
3027 file, line);
3028 if (expr -> data.suffix.len)
3029 expression_dereference (&expr -> data.suffix.len,
3030 file, line);
3031 break;
3032
3033 case expr_lcase:
3034 if (expr->data.lcase)
3035 expression_dereference(&expr->data.lcase, MDL);
3036 break;
3037
3038 case expr_ucase:
3039 if (expr->data.ucase)
3040 expression_dereference(&expr->data.ucase, MDL);
3041 break;
3042
3043 case expr_not:
3044 if (expr -> data.not)
3045 expression_dereference (&expr -> data.not, file, line);
3046 break;
3047
3048 case expr_packet:
3049 if (expr -> data.packet.offset)
3050 expression_dereference (&expr -> data.packet.offset,
3051 file, line);
3052 if (expr -> data.packet.len)
3053 expression_dereference (&expr -> data.packet.len,
3054 file, line);
3055 break;
3056
3057 case expr_extract_int8:
3058 case expr_extract_int16:
3059 case expr_extract_int32:
3060 if (expr -> data.extract_int)
3061 expression_dereference (&expr -> data.extract_int,
3062 file, line);
3063 break;
3064
3065 case expr_encode_int8:
3066 case expr_encode_int16:
3067 case expr_encode_int32:
3068 if (expr -> data.encode_int)
3069 expression_dereference (&expr -> data.encode_int,
3070 file, line);
3071 break;
3072
3073 case expr_encapsulate:
3074 case expr_const_data:
3075 data_string_forget (&expr -> data.const_data, file, line);
3076 break;
3077
3078 case expr_host_lookup:
3079 if (expr -> data.host_lookup)
3080 dns_host_entry_dereference (&expr -> data.host_lookup,
3081 file, line);
3082 break;
3083
3084 case expr_binary_to_ascii:
3085 if (expr -> data.b2a.base)
3086 expression_dereference (&expr -> data.b2a.base,
3087 file, line);
3088 if (expr -> data.b2a.width)
3089 expression_dereference (&expr -> data.b2a.width,
3090 file, line);
3091 if (expr -> data.b2a.separator)
3092 expression_dereference (&expr -> data.b2a.separator,
3093 file, line);
3094 if (expr -> data.b2a.buffer)
3095 expression_dereference (&expr -> data.b2a.buffer,
3096 file, line);
3097 break;
3098
3099 case expr_pick_first_value:
3100 if (expr -> data.pick_first_value.car)
3101 expression_dereference (&expr -> data.pick_first_value.car,
3102 file, line);
3103 if (expr -> data.pick_first_value.cdr)
3104 expression_dereference (&expr -> data.pick_first_value.cdr,
3105 file, line);
3106 break;
3107
3108 case expr_reverse:
3109 if (expr -> data.reverse.width)
3110 expression_dereference (&expr -> data.reverse.width,
3111 file, line);
3112 if (expr -> data.reverse.buffer)
3113 expression_dereference
3114 (&expr -> data.reverse.buffer, file, line);
3115 break;
3116
3117 case expr_dns_transaction:
3118 if (expr -> data.dns_transaction.car)
3119 expression_dereference (&expr -> data.dns_transaction.car,
3120 file, line);
3121 if (expr -> data.dns_transaction.cdr)
3122 expression_dereference (&expr -> data.dns_transaction.cdr,
3123 file, line);
3124 break;
3125
3126 case expr_ns_add:
3127 if (expr -> data.ns_add.rrname)
3128 expression_dereference (&expr -> data.ns_add.rrname,
3129 file, line);
3130 if (expr -> data.ns_add.rrdata)
3131 expression_dereference (&expr -> data.ns_add.rrdata,
3132 file, line);
3133 if (expr -> data.ns_add.ttl)
3134 expression_dereference (&expr -> data.ns_add.ttl,
3135 file, line);
3136 break;
3137
3138 case expr_ns_delete:
3139 case expr_ns_exists:
3140 case expr_ns_not_exists:
3141 if (expr -> data.ns_delete.rrname)
3142 expression_dereference (&expr -> data.ns_delete.rrname,
3143 file, line);
3144 if (expr -> data.ns_delete.rrdata)
3145 expression_dereference (&expr -> data.ns_delete.rrdata,
3146 file, line);
3147 break;
3148
3149 case expr_variable_reference:
3150 case expr_variable_exists:
3151 if (expr -> data.variable)
3152 dfree (expr -> data.variable, file, line);
3153 break;
3154
3155 case expr_funcall:
3156 if (expr -> data.funcall.name)
3157 dfree (expr -> data.funcall.name, file, line);
3158 if (expr -> data.funcall.arglist)
3159 expression_dereference (&expr -> data.funcall.arglist,
3160 file, line);
3161 break;
3162
3163 case expr_arg:
3164 if (expr -> data.arg.val)
3165 expression_dereference (&expr -> data.arg.val,
3166 file, line);
3167 if (expr -> data.arg.next)
3168 expression_dereference (&expr -> data.arg.next,
3169 file, line);
3170 break;
3171
3172 case expr_function:
3173 fundef_dereference (&expr -> data.func, file, line);
3174 break;
3175
3176 /* No subexpressions. */
3177 case expr_leased_address:
3178 case expr_lease_time:
3179 case expr_filename:
3180 case expr_sname:
3181 case expr_const_int:
3182 case expr_check:
3183 case expr_option:
3184 case expr_hardware:
3185 case expr_exists:
3186 case expr_known:
3187 case expr_null:
3188 break;
3189
3190 default:
3191 break;
3192 }
3193 free_expression (expr, MDL);
3194 }
3195
3196 int is_dns_expression (expr)
3197 struct expression *expr;
3198 {
3199 return (expr -> op == expr_ns_add ||
3200 expr -> op == expr_ns_delete ||
3201 expr -> op == expr_ns_exists ||
3202 expr -> op == expr_ns_not_exists);
3203 }
3204
3205 int is_boolean_expression (expr)
3206 struct expression *expr;
3207 {
3208 return (expr -> op == expr_check ||
3209 expr -> op == expr_exists ||
3210 expr -> op == expr_variable_exists ||
3211 expr -> op == expr_equal ||
3212 expr -> op == expr_not_equal ||
3213 expr -> op == expr_and ||
3214 expr -> op == expr_or ||
3215 expr -> op == expr_not ||
3216 expr -> op == expr_known ||
3217 expr -> op == expr_static);
3218 }
3219
3220 int is_data_expression (expr)
3221 struct expression *expr;
3222 {
3223 return (expr->op == expr_substring ||
3224 expr->op == expr_suffix ||
3225 expr->op == expr_lcase ||
3226 expr->op == expr_ucase ||
3227 expr->op == expr_option ||
3228 expr->op == expr_hardware ||
3229 expr->op == expr_const_data ||
3230 expr->op == expr_packet ||
3231 expr->op == expr_concat ||
3232 expr->op == expr_encapsulate ||
3233 expr->op == expr_encode_int8 ||
3234 expr->op == expr_encode_int16 ||
3235 expr->op == expr_encode_int32 ||
3236 expr->op == expr_host_lookup ||
3237 expr->op == expr_binary_to_ascii ||
3238 expr->op == expr_filename ||
3239 expr->op == expr_sname ||
3240 expr->op == expr_reverse ||
3241 expr->op == expr_pick_first_value ||
3242 expr->op == expr_host_decl_name ||
3243 expr->op == expr_leased_address ||
3244 expr->op == expr_config_option ||
3245 expr->op == expr_null);
3246 }
3247
3248 int is_numeric_expression (expr)
3249 struct expression *expr;
3250 {
3251 return (expr -> op == expr_extract_int8 ||
3252 expr -> op == expr_extract_int16 ||
3253 expr -> op == expr_extract_int32 ||
3254 expr -> op == expr_const_int ||
3255 expr -> op == expr_lease_time ||
3256 expr -> op == expr_dns_transaction ||
3257 expr -> op == expr_add ||
3258 expr -> op == expr_subtract ||
3259 expr -> op == expr_multiply ||
3260 expr -> op == expr_divide ||
3261 expr -> op == expr_remainder ||
3262 expr -> op == expr_binary_and ||
3263 expr -> op == expr_binary_or ||
3264 expr -> op == expr_binary_xor ||
3265 expr -> op == expr_client_state);
3266 }
3267
3268 int is_compound_expression (expr)
3269 struct expression *expr;
3270 {
3271 return (expr -> op == expr_ns_add ||
3272 expr -> op == expr_ns_delete ||
3273 expr -> op == expr_ns_exists ||
3274 expr -> op == expr_ns_not_exists ||
3275 expr -> op == expr_substring ||
3276 expr -> op == expr_suffix ||
3277 expr -> op == expr_option ||
3278 expr -> op == expr_concat ||
3279 expr -> op == expr_encode_int8 ||
3280 expr -> op == expr_encode_int16 ||
3281 expr -> op == expr_encode_int32 ||
3282 expr -> op == expr_binary_to_ascii ||
3283 expr -> op == expr_reverse ||
3284 expr -> op == expr_pick_first_value ||
3285 expr -> op == expr_config_option ||
3286 expr -> op == expr_extract_int8 ||
3287 expr -> op == expr_extract_int16 ||
3288 expr -> op == expr_extract_int32 ||
3289 expr -> op == expr_dns_transaction);
3290 }
3291
3292 static int op_val PROTO ((enum expr_op));
3293
3294 static int op_val (op)
3295 enum expr_op op;
3296 {
3297 switch (op) {
3298 case expr_none:
3299 case expr_match:
3300 case expr_static:
3301 case expr_check:
3302 case expr_substring:
3303 case expr_suffix:
3304 case expr_lcase:
3305 case expr_ucase:
3306 case expr_concat:
3307 case expr_encapsulate:
3308 case expr_host_lookup:
3309 case expr_not:
3310 case expr_option:
3311 case expr_hardware:
3312 case expr_packet:
3313 case expr_const_data:
3314 case expr_extract_int8:
3315 case expr_extract_int16:
3316 case expr_extract_int32:
3317 case expr_encode_int8:
3318 case expr_encode_int16:
3319 case expr_encode_int32:
3320 case expr_const_int:
3321 case expr_exists:
3322 case expr_variable_exists:
3323 case expr_known:
3324 case expr_binary_to_ascii:
3325 case expr_reverse:
3326 case expr_filename:
3327 case expr_sname:
3328 case expr_pick_first_value:
3329 case expr_host_decl_name:
3330 case expr_config_option:
3331 case expr_leased_address:
3332 case expr_lease_time:
3333 case expr_dns_transaction:
3334 case expr_null:
3335 case expr_variable_reference:
3336 case expr_ns_add:
3337 case expr_ns_delete:
3338 case expr_ns_exists:
3339 case expr_ns_not_exists:
3340 case expr_arg:
3341 case expr_funcall:
3342 case expr_function:
3343 /* XXXDPN: Need to assign sane precedences to these. */
3344 case expr_binary_and:
3345 case expr_binary_or:
3346 case expr_binary_xor:
3347 case expr_client_state:
3348 return 100;
3349
3350 case expr_equal:
3351 case expr_not_equal:
3352 return 4;
3353
3354 case expr_or:
3355 case expr_and:
3356 return 3;
3357
3358 case expr_add:
3359 case expr_subtract:
3360 return 2;
3361
3362 case expr_multiply:
3363 case expr_divide:
3364 case expr_remainder:
3365 return 1;
3366 }
3367 return 100;
3368 }
3369
3370 int op_precedence (op1, op2)
3371 enum expr_op op1, op2;
3372 {
3373 int ov1, ov2;
3374
3375 return op_val (op1) - op_val (op2);
3376 }
3377
3378 enum expression_context expression_context (struct expression *expr)
3379 {
3380 if (is_data_expression (expr))
3381 return context_data;
3382 if (is_numeric_expression (expr))
3383 return context_numeric;
3384 if (is_boolean_expression (expr))
3385 return context_boolean;
3386 if (is_dns_expression (expr))
3387 return context_dns;
3388 return context_any;
3389 }
3390
3391 enum expression_context op_context (op)
3392 enum expr_op op;
3393 {
3394 switch (op) {
3395 /* XXX Why aren't these specific? */
3396 case expr_none:
3397 case expr_match:
3398 case expr_static:
3399 case expr_check:
3400 case expr_substring:
3401 case expr_suffix:
3402 case expr_lcase:
3403 case expr_ucase:
3404 case expr_concat:
3405 case expr_encapsulate:
3406 case expr_host_lookup:
3407 case expr_not:
3408 case expr_option:
3409 case expr_hardware:
3410 case expr_packet:
3411 case expr_const_data:
3412 case expr_extract_int8:
3413 case expr_extract_int16:
3414 case expr_extract_int32:
3415 case expr_encode_int8:
3416 case expr_encode_int16:
3417 case expr_encode_int32:
3418 case expr_const_int:
3419 case expr_exists:
3420 case expr_variable_exists:
3421 case expr_known:
3422 case expr_binary_to_ascii:
3423 case expr_reverse:
3424 case expr_filename:
3425 case expr_sname:
3426 case expr_pick_first_value:
3427 case expr_host_decl_name:
3428 case expr_config_option:
3429 case expr_leased_address:
3430 case expr_lease_time:
3431 case expr_null:
3432 case expr_variable_reference:
3433 case expr_ns_add:
3434 case expr_ns_delete:
3435 case expr_ns_exists:
3436 case expr_ns_not_exists:
3437 case expr_dns_transaction:
3438 case expr_arg:
3439 case expr_funcall:
3440 case expr_function:
3441 return context_any;
3442
3443 case expr_equal:
3444 case expr_not_equal:
3445 return context_data;
3446
3447 case expr_and:
3448 return context_boolean;
3449
3450 case expr_or:
3451 return context_boolean;
3452
3453 case expr_add:
3454 case expr_subtract:
3455 case expr_multiply:
3456 case expr_divide:
3457 case expr_remainder:
3458 case expr_binary_and:
3459 case expr_binary_or:
3460 case expr_binary_xor:
3461 case expr_client_state:
3462 return context_numeric;
3463 }
3464 return context_any;
3465 }
3466
3467 int write_expression (file, expr, col, indent, firstp)
3468 FILE *file;
3469 struct expression *expr;
3470 int col;
3471 int indent;
3472 int firstp;
3473 {
3474 struct expression *e;
3475 struct expression *next_arg;
3476 const char *s;
3477 char obuf [65];
3478 int scol;
3479 int width;
3480
3481 /* If this promises to be a fat expression, start a new line. */
3482 if (!firstp && is_compound_expression (expr)) {
3483 indent_spaces (file, indent);
3484 col = indent;
3485 }
3486
3487 switch (expr -> op) {
3488 case expr_none:
3489 col = token_print_indent (file, col, indent, "", "", "null");
3490 break;
3491
3492 case expr_check:
3493 col = token_print_indent (file, col, indent, "", "", "check");
3494 col = token_print_indent_concat (file, col, indent,
3495 " ", "", "\"",
3496 expr -> data.check -> name,
3497 "\"", (char *)0);
3498 break;
3499
3500 case expr_not_equal:
3501 s = "!=";
3502 goto binary;
3503
3504 case expr_equal:
3505 s = "=";
3506 binary:
3507 col = write_expression (file, expr -> data.equal [0],
3508 col, indent, 1);
3509 col = token_print_indent (file, col, indent, " ", " ", s);
3510 col = write_expression (file, expr -> data.equal [1],
3511 col, indent + 2, 0);
3512 break;
3513
3514 case expr_substring:
3515 col = token_print_indent (file, col, indent, "", "",
3516 "substring");
3517 col = token_print_indent (file, col, indent, " ", "", "(");
3518 scol = col;
3519 col = write_expression (file, expr -> data.substring.expr,
3520 col, scol, 1);
3521 col = token_print_indent (file, col, indent, "", " ", ",");
3522 col = write_expression (file, expr -> data.substring.offset,
3523 col, indent, 0);
3524 col = token_print_indent (file, col, scol, "", " ", ",");
3525 col = write_expression (file, expr -> data.substring.len,
3526 col, scol, 0);
3527 col = token_print_indent (file, col, indent, "", "", ")");
3528 break;
3529
3530 case expr_suffix:
3531 col = token_print_indent (file, col, indent, "", "", "suffix");
3532 col = token_print_indent (file, col, indent, " ", "", "(");
3533 scol = col;
3534 col = write_expression (file, expr -> data.suffix.expr,
3535 col, scol, 1);
3536 col = token_print_indent (file, col, scol, "", " ", ",");
3537 col = write_expression (file, expr -> data.suffix.len,
3538 col, scol, 0);
3539 col = token_print_indent (file, col, indent, "", "", ")");
3540
3541 case expr_lcase:
3542 col = token_print_indent(file, col, indent, "", "", "lcase");
3543 col = token_print_indent(file, col, indent, " ", "", "(");
3544 scol = col;
3545 col = write_expression(file, expr->data.lcase, col, scol, 1);
3546 col = token_print_indent(file, col, indent, "", "", ")");
3547 break;
3548
3549 case expr_ucase:
3550 col = token_print_indent(file, col, indent, "", "", "ucase");
3551 col = token_print_indent(file, col, indent, " ", "", "(");
3552 scol = col;
3553 col = write_expression(file, expr->data.ucase, col, scol, 1);
3554 col = token_print_indent(file, col, indent, "", "", ")");
3555 break;
3556
3557 case expr_concat:
3558 e = expr;
3559 col = token_print_indent (file, col, indent, "", "",
3560 "concat");
3561 col = token_print_indent (file, col, indent, " ", "", "(");
3562 scol = col;
3563 firstp = 1;
3564 concat_again:
3565 col = write_expression (file, e -> data.concat [0],
3566 col, scol, firstp);
3567 firstp = 0;
3568 if (!e -> data.concat [1])
3569 goto no_concat_cdr;
3570 col = token_print_indent (file, col, scol, "", " ", ",");
3571 if (e -> data.concat [1] -> op == expr_concat) {
3572 e = e -> data.concat [1];
3573 goto concat_again;
3574 }
3575 col = write_expression (file, e -> data.concat [1],
3576 col, scol, 0);
3577 no_concat_cdr:
3578 col = token_print_indent (file, col, indent, "", "", ")");
3579 break;
3580
3581 case expr_host_lookup:
3582 col = token_print_indent (file, col, indent, "", "",
3583 "gethostbyname");
3584 col = token_print_indent (file, col, indent, " ", "", "(");
3585 col = token_print_indent_concat
3586 (file, col, indent, "", "",
3587 "\"", expr -> data.host_lookup -> hostname, "\"",
3588 (char *)0);
3589 col = token_print_indent (file, col, indent, "", "", ")");
3590 break;
3591
3592 case expr_add:
3593 s = "+";
3594 goto binary;
3595
3596 case expr_subtract:
3597 s = "-";
3598 goto binary;
3599
3600 case expr_multiply:
3601 s = "*";
3602 goto binary;
3603
3604 case expr_divide:
3605 s = "/";
3606 goto binary;
3607
3608 case expr_remainder:
3609 s = "%";
3610 goto binary;
3611
3612 case expr_binary_and:
3613 s = "&";
3614 goto binary;
3615
3616 case expr_binary_or:
3617 s = "|";
3618 goto binary;
3619
3620 case expr_binary_xor:
3621 s = "^";
3622 goto binary;
3623
3624 case expr_and:
3625 s = "and";
3626 goto binary;
3627
3628 case expr_or:
3629 s = "or";
3630 goto binary;
3631
3632 case expr_not:
3633 col = token_print_indent (file, col, indent, "", " ", "not");
3634 col = write_expression (file,
3635 expr -> data.not, col, indent + 2, 1);
3636 break;
3637
3638 case expr_option:
3639 s = "option";
3640
3641 print_option_name:
3642 col = token_print_indent (file, col, indent, "", "", s);
3643
3644 if (expr -> data.option -> universe != &dhcp_universe) {
3645 col = token_print_indent (file, col, indent,
3646 " ", "",
3647 (expr -> data.option ->
3648 universe -> name));
3649 col = token_print_indent (file, col, indent, "", "",
3650 ".");
3651 col = token_print_indent (file, col, indent, "", "",
3652 expr -> data.option -> name);
3653 } else {
3654 col = token_print_indent (file, col, indent, " ", "",
3655 expr -> data.option -> name);
3656 }
3657 break;
3658
3659 case expr_hardware:
3660 col = token_print_indent (file, col, indent, "", "",
3661 "hardware");
3662 break;
3663
3664 case expr_packet:
3665 col = token_print_indent (file, col, indent, "", "",
3666 "packet");
3667 col = token_print_indent (file, col, indent, " ", "", "(");
3668 scol = col;
3669 col = write_expression (file, expr -> data.packet.offset,
3670 col, indent, 1);
3671 col = token_print_indent (file, col, scol, "", " ", ",");
3672 col = write_expression (file, expr -> data.packet.len,
3673 col, scol, 0);
3674 col = token_print_indent (file, col, indent, "", "", ")");
3675 break;
3676
3677 case expr_const_data:
3678 col = token_indent_data_string (file, col, indent, "", "",
3679 &expr -> data.const_data);
3680 break;
3681
3682 case expr_extract_int8:
3683 width = 8;
3684 extract_int:
3685 col = token_print_indent (file, col, indent, "", "",
3686 "extract-int");
3687 col = token_print_indent (file, col, indent, " ", "", "(");
3688 scol = col;
3689 col = write_expression (file, expr -> data.extract_int,
3690 col, indent, 1);
3691 col = token_print_indent (file, col, scol, "", " ", ",");
3692 sprintf (obuf, "%d", width);
3693 col = token_print_indent (file, col, scol, " ", "", obuf);
3694 col = token_print_indent (file, col, indent, "", "", ")");
3695 break;
3696
3697 case expr_extract_int16:
3698 width = 16;
3699 goto extract_int;
3700
3701 case expr_extract_int32:
3702 width = 32;
3703 goto extract_int;
3704
3705 case expr_encode_int8:
3706 width = 8;
3707 encode_int:
3708 col = token_print_indent (file, col, indent, "", "",
3709 "encode-int");
3710 col = token_print_indent (file, col, indent, " ", "", "(");
3711 scol = col;
3712 col = write_expression (file, expr -> data.extract_int,
3713 col, indent, 1);
3714 col = token_print_indent (file, col, scol, "", " ", ",");
3715 sprintf (obuf, "%d", width);
3716 col = token_print_indent (file, col, scol, " ", "", obuf);
3717 col = token_print_indent (file, col, indent, "", "",
3718 ")");
3719 break;
3720
3721 case expr_encode_int16:
3722 width = 16;
3723 goto encode_int;
3724
3725 case expr_encode_int32:
3726 width = 32;
3727 goto encode_int;
3728
3729 case expr_const_int:
3730 sprintf (obuf, "%lu", expr -> data.const_int);
3731 col = token_print_indent (file, col, indent, "", "", obuf);
3732 break;
3733
3734 case expr_exists:
3735 s = "exists";
3736 goto print_option_name;
3737
3738 case expr_encapsulate:
3739 col = token_print_indent (file, col, indent, "", "",
3740 "encapsulate");
3741 col = token_indent_data_string (file, col, indent, " ", "",
3742 &expr -> data.encapsulate);
3743 break;
3744
3745 case expr_known:
3746 col = token_print_indent (file, col, indent, "", "", "known");
3747 break;
3748
3749 case expr_reverse:
3750 col = token_print_indent (file, col, indent, "", "",
3751 "reverse");
3752 col = token_print_indent (file, col, indent, " ", "", "(");
3753 scol = col;
3754 col = write_expression (file, expr -> data.reverse.width,
3755 col, scol, 1);
3756 col = token_print_indent (file, col, scol, "", " ", ",");
3757 col = write_expression (file, expr -> data.reverse.buffer,
3758 col, scol, 0);
3759 col = token_print_indent (file, col, indent, "", "",
3760 ")");
3761 break;
3762
3763 case expr_leased_address:
3764 col = token_print_indent (file, col, indent, "", "",
3765 "leased-address");
3766 break;
3767
3768 case expr_client_state:
3769 col = token_print_indent (file, col, indent, "", "",
3770 "client-state");
3771 break;
3772
3773 case expr_binary_to_ascii:
3774 col = token_print_indent (file, col, indent, "", "",
3775 "binary-to-ascii");
3776 col = token_print_indent (file, col, indent, " ", "",
3777 "(");
3778 scol = col;
3779 col = write_expression (file, expr -> data.b2a.base,
3780 col, scol, 1);
3781 col = token_print_indent (file, col, scol, "", " ",
3782 ",");
3783 col = write_expression (file, expr -> data.b2a.width,
3784 col, scol, 0);
3785 col = token_print_indent (file, col, scol, "", " ",
3786 ",");
3787 col = write_expression (file, expr -> data.b2a.separator,
3788 col, scol, 0);
3789 col = token_print_indent (file, col, scol, "", " ",
3790 ",");
3791 col = write_expression (file, expr -> data.b2a.buffer,
3792 col, scol, 0);
3793 col = token_print_indent (file, col, indent, "", "",
3794 ")");
3795 break;
3796
3797 case expr_config_option:
3798 s = "config-option";
3799 goto print_option_name;
3800
3801 case expr_host_decl_name:
3802 col = token_print_indent (file, col, indent, "", "",
3803 "host-decl-name");
3804 break;
3805
3806 case expr_pick_first_value:
3807 e = expr;
3808 col = token_print_indent (file, col, indent, "", "",
3809 "concat");
3810 col = token_print_indent (file, col, indent, " ", "",
3811 "(");
3812 scol = col;
3813 firstp = 1;
3814 pick_again:
3815 col = write_expression (file,
3816 e -> data.pick_first_value.car,
3817 col, scol, firstp);
3818 firstp = 0;
3819 /* We're being very lisp-like right now - instead of
3820 representing this expression as (first middle . last) we're
3821 representing it as (first middle last), which means that the
3822 tail cdr is always nil. Apologies to non-wisp-lizards - may
3823 this obscure way of describing the problem motivate you to
3824 learn more about the one true computing language. */
3825 if (!e -> data.pick_first_value.cdr)
3826 goto no_pick_cdr;
3827 col = token_print_indent (file, col, scol, "", " ",
3828 ",");
3829 if (e -> data.pick_first_value.cdr -> op ==
3830 expr_pick_first_value) {
3831 e = e -> data.pick_first_value.cdr;
3832 goto pick_again;
3833 }
3834 col = write_expression (file,
3835 e -> data.pick_first_value.cdr,
3836 col, scol, 0);
3837 no_pick_cdr:
3838 col = token_print_indent (file, col, indent, "", "",
3839 ")");
3840 break;
3841
3842 case expr_lease_time:
3843 col = token_print_indent (file, col, indent, "", "",
3844 "lease-time");
3845 break;
3846
3847 case expr_dns_transaction:
3848 col = token_print_indent (file, col, indent, "", "",
3849 "ns-update");
3850 col = token_print_indent (file, col, indent, " ", "",
3851 "(");
3852 scol = 0;
3853 for (e = expr;
3854 e && e -> op == expr_dns_transaction;
3855 e = e -> data.dns_transaction.cdr) {
3856 if (!scol) {
3857 scol = col;
3858 firstp = 1;
3859 } else
3860 firstp = 0;
3861 col = write_expression (file,
3862 e -> data.dns_transaction.car,
3863 col, scol, firstp);
3864 if (e -> data.dns_transaction.cdr)
3865 col = token_print_indent (file, col, scol,
3866 "", " ", ",");
3867 }
3868 if (e)
3869 col = write_expression (file, e, col, scol, 0);
3870 col = token_print_indent (file, col, indent, "", "", ")");
3871 break;
3872
3873 case expr_ns_add:
3874 col = token_print_indent (file, col, indent, "", "",
3875 "update");
3876 col = token_print_indent (file, col, indent, " ", "",
3877 "(");
3878 scol = col;
3879 sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
3880 col = token_print_indent (file, col, scol, "", "", obuf);
3881 col = token_print_indent (file, col, scol, "", " ",
3882 ",");
3883 sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
3884 col = token_print_indent (file, col, scol, "", "", obuf);
3885 col = token_print_indent (file, col, scol, "", " ",
3886 ",");
3887 col = write_expression (file, expr -> data.ns_add.rrname,
3888 col, scol, 0);
3889 col = token_print_indent (file, col, scol, "", " ",
3890 ",");
3891 col = write_expression (file, expr -> data.ns_add.rrdata,
3892 col, scol, 0);
3893 col = token_print_indent (file, col, scol, "", " ",
3894 ",");
3895 col = write_expression (file, expr -> data.ns_add.ttl,
3896 col, scol, 0);
3897 col = token_print_indent (file, col, indent, "", "",
3898 ")");
3899 break;
3900
3901 case expr_ns_delete:
3902 col = token_print_indent (file, col, indent, "", "",
3903 "delete");
3904 col = token_print_indent (file, col, indent, " ", "",
3905 "(");
3906 finish_ns_small:
3907 scol = col;
3908 sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
3909 col = token_print_indent (file, col, scol, "", "", obuf);
3910 col = token_print_indent (file, col, scol, "", " ",
3911 ",");
3912 sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
3913 col = token_print_indent (file, col, scol, "", "", obuf);
3914 col = token_print_indent (file, col, scol, "", " ",
3915 ",");
3916 col = write_expression (file, expr -> data.ns_add.rrname,
3917 col, scol, 0);
3918 col = token_print_indent (file, col, scol, "", " ",
3919 ",");
3920 col = write_expression (file, expr -> data.ns_add.rrdata,
3921 col, scol, 0);
3922 col = token_print_indent (file, col, indent, "", "",
3923 ")");
3924 break;
3925
3926 case expr_ns_exists:
3927 col = token_print_indent (file, col, indent, "", "",
3928 "exists");
3929 col = token_print_indent (file, col, indent, " ", "",
3930 "(");
3931 goto finish_ns_small;
3932
3933 case expr_ns_not_exists:
3934 col = token_print_indent (file, col, indent, "", "",
3935 "not exists");
3936 col = token_print_indent (file, col, indent, " ", "",
3937 "(");
3938 goto finish_ns_small;
3939
3940 case expr_static:
3941 col = token_print_indent (file, col, indent, "", "",
3942 "static");
3943 break;
3944
3945 case expr_null:
3946 col = token_print_indent (file, col, indent, "", "", "null");
3947 break;
3948
3949 case expr_variable_reference:
3950 col = token_print_indent (file, indent, indent, "", "",
3951 expr -> data.variable);
3952 break;
3953
3954 case expr_variable_exists:
3955 col = token_print_indent (file, indent, indent, "", "",
3956 "defined");
3957 col = token_print_indent (file, col, indent, " ", "", "(");
3958 col = token_print_indent (file, col, indent, "", "",
3959 expr -> data.variable);
3960 col = token_print_indent (file, col, indent, "", "", ")");
3961 break;
3962
3963 default:
3964 log_fatal ("invalid expression type in print_expression: %d",
3965 expr -> op);
3966 }
3967 return col;
3968 }
3969
3970 struct binding *find_binding (struct binding_scope *scope, const char *name)
3971 {
3972 struct binding *bp;
3973 struct binding_scope *s;
3974
3975 for (s = scope; s; s = s -> outer) {
3976 for (bp = s -> bindings; bp; bp = bp -> next) {
3977 if (!strcasecmp (name, bp -> name)) {
3978 return bp;
3979 }
3980 }
3981 }
3982 return (struct binding *)0;
3983 }
3984
3985 int free_bindings (struct binding_scope *scope, const char *file, int line)
3986 {
3987 struct binding *bp, *next;
3988
3989 for (bp = scope -> bindings; bp; bp = next) {
3990 next = bp -> next;
3991 if (bp -> name)
3992 dfree (bp -> name, file, line);
3993 if (bp -> value)
3994 binding_value_dereference (&bp -> value, file, line);
3995 dfree (bp, file, line);
3996 }
3997 scope -> bindings = (struct binding *)0;
3998 return 1;
3999 }
4000
4001 int binding_scope_dereference (ptr, file, line)
4002 struct binding_scope **ptr;
4003 const char *file;
4004 int line;
4005 {
4006 int i;
4007 struct binding_scope *binding_scope;
4008
4009 if (!ptr || !*ptr) {
4010 log_error ("%s(%d): null pointer", file, line);
4011 #if defined (POINTER_DEBUG)
4012 abort ();
4013 #else
4014 return 0;
4015 #endif
4016 }
4017
4018 binding_scope = *ptr;
4019 *ptr = (struct binding_scope *)0;
4020 --binding_scope -> refcnt;
4021 rc_register (file, line, ptr,
4022 binding_scope, binding_scope -> refcnt, 1, RC_MISC);
4023 if (binding_scope -> refcnt > 0)
4024 return 1;
4025
4026 if (binding_scope -> refcnt < 0) {
4027 log_error ("%s(%d): negative refcnt!", file, line);
4028 #if defined (DEBUG_RC_HISTORY)
4029 dump_rc_history (binding_scope);
4030 #endif
4031 #if defined (POINTER_DEBUG)
4032 abort ();
4033 #else
4034 return 0;
4035 #endif
4036 }
4037
4038 free_bindings (binding_scope, file, line);
4039 if (binding_scope -> outer)
4040 binding_scope_dereference (&binding_scope -> outer, MDL);
4041 dfree (binding_scope, file, line);
4042 return 1;
4043 }
4044
4045 int fundef_dereference (ptr, file, line)
4046 struct fundef **ptr;
4047 const char *file;
4048 int line;
4049 {
4050 struct fundef *bp = *ptr;
4051 struct string_list *sp, *next;
4052
4053 if (!ptr) {
4054 log_error ("%s(%d): null pointer", file, line);
4055 #if defined (POINTER_DEBUG)
4056 abort ();
4057 #else
4058 return 0;
4059 #endif
4060 }
4061
4062 if (!bp) {
4063 log_error ("%s(%d): null pointer", file, line);
4064 #if defined (POINTER_DEBUG)
4065 abort ();
4066 #else
4067 return 0;
4068 #endif
4069 }
4070
4071 bp -> refcnt--;
4072 rc_register (file, line, ptr, bp, bp -> refcnt, 1, RC_MISC);
4073 if (bp -> refcnt < 0) {
4074 log_error ("%s(%d): negative refcnt!", file, line);
4075 #if defined (DEBUG_RC_HISTORY)
4076 dump_rc_history (bp);
4077 #endif
4078 #if defined (POINTER_DEBUG)
4079 abort ();
4080 #else
4081 return 0;
4082 #endif
4083 }
4084 if (!bp -> refcnt) {
4085 for (sp = bp -> args; sp; sp = next) {
4086 next = sp -> next;
4087 dfree (sp, file, line);
4088 }
4089 if (bp -> statements)
4090 executable_statement_dereference (&bp -> statements,
4091 file, line);
4092 dfree (bp, file, line);
4093 }
4094 *ptr = (struct fundef *)0;
4095 return 1;
4096 }
4097
4098 #if defined (NOTYET) /* Post 3.0 final. */
4099 int data_subexpression_length (int *rv,
4100 struct expression *expr)
4101 {
4102 int crhs, clhs, llhs, lrhs;
4103 switch (expr -> op) {
4104 case expr_substring:
4105 if (expr -> data.substring.len &&
4106 expr -> data.substring.len -> op == expr_const_int) {
4107 (*rv =
4108 (int)expr -> data.substring.len -> data.const_int);
4109 return 1;
4110 }
4111 return 0;
4112
4113 case expr_packet:
4114 case expr_suffix:
4115 if (expr -> data.suffix.len &&
4116 expr -> data.suffix.len -> op == expr_const_int) {
4117 (*rv =
4118 (int)expr -> data.suffix.len -> data.const_int);
4119 return 1;
4120 }
4121 return 0;
4122
4123 case expr_lcase:
4124 return data_subexpression_length(rv, expr->data.lcase);
4125
4126 case expr_ucase:
4127 return data_subexpression_length(rv, expr->data.ucase);
4128
4129 case expr_concat:
4130 clhs = data_subexpression_length (&llhs,
4131 expr -> data.concat [0]);
4132 crhs = data_subexpression_length (&lrhs,
4133 expr -> data.concat [1]);
4134 if (crhs == 0 || clhs == 0)
4135 return 0;
4136 *rv = llhs + lrhs;
4137 return 1;
4138 break;
4139
4140 case expr_hardware:
4141 return 0;
4142
4143 case expr_const_data:
4144 *rv = expr -> data.const_data.len;
4145 return 2;
4146
4147 case expr_reverse:
4148 return data_subexpression_length (rv,
4149 expr -> data.reverse.buffer);
4150
4151 case expr_leased_address:
4152 case expr_lease_time:
4153 *rv = 4;
4154 return 2;
4155
4156 case expr_pick_first_value:
4157 clhs = data_subexpression_length (&llhs,
4158 expr -> data.concat [0]);
4159 crhs = data_subexpression_length (&lrhs,
4160 expr -> data.concat [1]);
4161 if (crhs == 0 || clhs == 0)
4162 return 0;
4163 if (llhs > lrhs)
4164 *rv = llhs;
4165 else
4166 *rv = lrhs;
4167 return 1;
4168
4169 case expr_binary_to_ascii:
4170 case expr_config_option:
4171 case expr_host_decl_name:
4172 case expr_encapsulate:
4173 case expr_filename:
4174 case expr_sname:
4175 case expr_host_lookup:
4176 case expr_option:
4177 case expr_none:
4178 case expr_match:
4179 case expr_check:
4180 case expr_equal:
4181 case expr_and:
4182 case expr_or:
4183 case expr_not:
4184 case expr_extract_int8:
4185 case expr_extract_int16:
4186 case expr_extract_int32:
4187 case expr_encode_int8:
4188 case expr_encode_int16:
4189 case expr_encode_int32:
4190 case expr_const_int:
4191 case expr_exists:
4192 case expr_known:
4193 case expr_dns_transaction:
4194 case expr_static:
4195 case expr_ns_add:
4196 case expr_ns_delete:
4197 case expr_ns_exists:
4198 case expr_ns_not_exists:
4199 case expr_not_equal:
4200 case expr_null:
4201 case expr_variable_exists:
4202 case expr_variable_reference:
4203 case expr_arg:
4204 case expr_funcall:
4205 case expr_function:
4206 case expr_add:
4207 case expr_subtract:
4208 case expr_multiply:
4209 case expr_divide:
4210 case expr_remainder:
4211 case expr_binary_and:
4212 case expr_binary_or:
4213 case expr_binary_xor:
4214 case expr_client_state:
4215 return 0;
4216 }
4217 return 0;
4218 }
4219
4220 int expr_valid_for_context (struct expression *expr,
4221 enum expression_context context)
4222 {
4223 /* We don't know at parse time what type of value a function may
4224 return, so we can't flag an error on it. */
4225 if (expr -> op == expr_funcall ||
4226 expr -> op == expr_variable_reference)
4227 return 1;
4228
4229 switch (context) {
4230 case context_any:
4231 return 1;
4232
4233 case context_boolean:
4234 if (is_boolean_expression (expr))
4235 return 1;
4236 return 0;
4237
4238 case context_data:
4239 if (is_data_expression (expr))
4240 return 1;
4241 return 0;
4242
4243 case context_numeric:
4244 if (is_numeric_expression (expr))
4245 return 1;
4246 return 0;
4247
4248 case context_dns:
4249 if (is_dns_expression (expr)) {
4250 return 1;
4251 }
4252 return 0;
4253
4254 case context_data_or_numeric:
4255 if (is_numeric_expression (expr) ||
4256 is_data_expression (expr)) {
4257 return 1;
4258 }
4259 return 0;
4260
4261 case context_function:
4262 if (expr -> op == expr_function)
4263 return 1;
4264 return 0;
4265 }
4266 return 0;
4267 }
4268 #endif /* NOTYET */
4269
4270 struct binding *create_binding (struct binding_scope **scope, const char *name)
4271 {
4272 struct binding *binding;
4273
4274 if (!*scope) {
4275 if (!binding_scope_allocate (scope, MDL))
4276 return (struct binding *)0;
4277 }
4278
4279 binding = find_binding (*scope, name);
4280 if (!binding) {
4281 binding = dmalloc (sizeof *binding, MDL);
4282 if (!binding)
4283 return (struct binding *)0;
4284
4285 memset (binding, 0, sizeof *binding);
4286 binding -> name = dmalloc (strlen (name) + 1, MDL);
4287 if (!binding -> name) {
4288 dfree (binding, MDL);
4289 return (struct binding *)0;
4290 }
4291 strcpy (binding -> name, name);
4292
4293 binding -> next = (*scope) -> bindings;
4294 (*scope) -> bindings = binding;
4295 }
4296
4297 return binding;
4298 }
4299
4300
4301 int bind_ds_value (struct binding_scope **scope,
4302 const char *name,
4303 struct data_string *value)
4304 {
4305 struct binding *binding;
4306
4307 binding = create_binding (scope, name);
4308 if (!binding)
4309 return 0;
4310
4311 if (binding -> value)
4312 binding_value_dereference (&binding -> value, MDL);
4313
4314 if (!binding_value_allocate (&binding -> value, MDL))
4315 return 0;
4316
4317 data_string_copy (&binding -> value -> value.data, value, MDL);
4318 binding -> value -> type = binding_data;
4319
4320 return 1;
4321 }
4322
4323
4324 int find_bound_string (struct data_string *value,
4325 struct binding_scope *scope,
4326 const char *name)
4327 {
4328 struct binding *binding;
4329
4330 binding = find_binding (scope, name);
4331 if (!binding ||
4332 !binding -> value ||
4333 binding -> value -> type != binding_data)
4334 return 0;
4335
4336 if (binding -> value -> value.data.terminated) {
4337 data_string_copy (value, &binding -> value -> value.data, MDL);
4338 } else {
4339 buffer_allocate (&value -> buffer,
4340 binding -> value -> value.data.len,
4341 MDL);
4342 if (!value -> buffer)
4343 return 0;
4344
4345 memcpy (value -> buffer -> data,
4346 binding -> value -> value.data.data,
4347 binding -> value -> value.data.len);
4348 value -> data = value -> buffer -> data;
4349 value -> len = binding -> value -> value.data.len;
4350 }
4351
4352 return 1;
4353 }
4354
4355 int unset (struct binding_scope *scope, const char *name)
4356 {
4357 struct binding *binding;
4358
4359 binding = find_binding (scope, name);
4360 if (binding) {
4361 if (binding -> value)
4362 binding_value_dereference
4363 (&binding -> value, MDL);
4364 return 1;
4365 }
4366 return 0;
4367 }
4368
4369 /* vim: set tabstop=8: */