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