]> git.ipfire.org Git - thirdparty/dhcp.git/blob - common/tree.c
Fix compilation errors introduced in the last set of checkins.
[thirdparty/dhcp.git] / common / tree.c
1 /* tree.c
2
3 Routines for manipulating parse trees... */
4
5 /*
6 * Copyright (c) 1996-2000 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
12 *
13 * http://www.isc.org/isc-license-1.0.html.
14 *
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
18 *
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
21 */
22
23 #ifndef lint
24 static char copyright[] =
25 "$Id: tree.c,v 1.69 2000/01/26 14:55:35 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n";
26 #endif /* not lint */
27
28 #include "dhcpd.h"
29 #include <omapip/omapip_p.h>
30
31 struct binding_scope global_scope;
32
33 static int do_host_lookup PROTO ((struct data_string *,
34 struct dns_host_entry *));
35
36 pair cons (car, cdr)
37 caddr_t car;
38 pair cdr;
39 {
40 pair foo = (pair)dmalloc (sizeof *foo, MDL);
41 if (!foo)
42 log_fatal ("no memory for cons.");
43 foo -> car = car;
44 foo -> cdr = cdr;
45 return foo;
46 }
47
48 int make_const_option_cache (oc, buffer, data, len, option, file, line)
49 struct option_cache **oc;
50 struct buffer **buffer;
51 u_int8_t *data;
52 unsigned len;
53 struct option *option;
54 const char *file;
55 int line;
56 {
57 struct buffer *bp;
58
59 if (buffer) {
60 bp = *buffer;
61 *buffer = 0;
62 } else {
63 bp = (struct buffer *)0;
64 if (!buffer_allocate (&bp, len, file, line)) {
65 log_error ("%s(%d): can't allocate buffer.",
66 file, line);
67 return 0;
68 }
69 }
70
71 if (!option_cache_allocate (oc, file, line)) {
72 log_error ("%s(%d): can't allocate option cache.", file, line);
73 buffer_dereference (&bp, file, line);
74 return 0;
75 }
76
77 (*oc) -> data.len = len;
78 (*oc) -> data.data = &bp -> data [0];
79 (*oc) -> data.terminated = 0;
80 if (data)
81 memcpy (&bp -> data [0], data, len);
82 (*oc) -> option = option;
83 return 1;
84 }
85
86 int make_host_lookup (expr, name)
87 struct expression **expr;
88 const char *name;
89 {
90 if (!expression_allocate (expr, MDL)) {
91 log_error ("No memory for host lookup tree node.");
92 return 0;
93 }
94 (*expr) -> op = expr_host_lookup;
95 if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) {
96 expression_dereference (expr, MDL);
97 return 0;
98 }
99 return 1;
100 }
101
102 int enter_dns_host (dh, name)
103 struct dns_host_entry **dh;
104 const char *name;
105 {
106 /* XXX This should really keep a hash table of hostnames
107 XXX and just add a new reference to a hostname that
108 XXX already exists, if possible, rather than creating
109 XXX a new structure. */
110 if (!dns_host_entry_allocate (dh, name, MDL)) {
111 log_error ("Can't allocate space for new host.");
112 return 0;
113 }
114 return 1;
115 }
116
117 int make_const_data (expr, data, len, terminated, allocate)
118 struct expression **expr;
119 const unsigned char *data;
120 unsigned len;
121 int terminated;
122 int allocate;
123 {
124 struct expression *nt;
125
126 if (!expression_allocate (expr, MDL)) {
127 log_error ("No memory for make_const_data tree node.");
128 return 0;
129 }
130 nt = *expr;
131
132 if (len) {
133 if (allocate) {
134 if (!buffer_allocate (&nt -> data.const_data.buffer,
135 len + terminated, MDL)) {
136 log_error ("Can't allocate const_data buffer");
137 expression_dereference (expr, MDL);
138 return 0;
139 }
140 nt -> data.const_data.data =
141 &nt -> data.const_data.buffer -> data [0];
142 memcpy (nt -> data.const_data.buffer -> data,
143 data, len + terminated);
144 } else
145 nt -> data.const_data.data = data;
146 nt -> data.const_data.terminated = terminated;
147 } else
148 nt -> data.const_data.data = 0;
149
150 nt -> op = expr_const_data;
151 nt -> data.const_data.len = len;
152 return 1;
153 }
154
155 int make_const_int (expr, val)
156 struct expression **expr;
157 unsigned long val;
158 {
159 if (!expression_allocate (expr, MDL)) {
160 log_error ("No memory for make_const_data tree node.");
161 return 0;
162 }
163
164 (*expr) -> op = expr_const_int;
165 (*expr) -> data.const_int = val;
166 return 1;
167 }
168
169 int make_concat (expr, left, right)
170 struct expression **expr;
171 struct expression *left, *right;
172 {
173 /* If we're concatenating a null tree to a non-null tree, just
174 return the non-null tree; if both trees are null, return
175 a null tree. */
176 if (!left) {
177 if (!right)
178 return 0;
179 expression_reference (expr, right, MDL);
180 return 1;
181 }
182 if (!right) {
183 expression_reference (expr, left, MDL);
184 return 1;
185 }
186
187 /* Otherwise, allocate a new node to concatenate the two. */
188 if (!expression_allocate (expr, MDL)) {
189 log_error ("No memory for concatenation expression node.");
190 return 0;
191 }
192
193 (*expr) -> op = expr_concat;
194 expression_reference (&(*expr) -> data.concat [0], left, MDL);
195 expression_reference (&(*expr) -> data.concat [1], right, MDL);
196 return 1;
197 }
198
199 int make_encapsulation (expr, name)
200 struct expression **expr;
201 struct data_string *name;
202 {
203 /* Allocate a new node to store the encapsulation. */
204 if (!expression_allocate (expr, MDL)) {
205 log_error ("No memory for encapsulation expression node.");
206 return 0;
207 }
208
209 (*expr) -> op = expr_encapsulate;
210 data_string_copy (&(*expr) -> data.encapsulate, name, MDL);
211 return 1;
212 }
213
214 int make_substring (new, expr, offset, length)
215 struct expression **new;
216 struct expression *expr;
217 struct expression *offset;
218 struct expression *length;
219 {
220 /* Allocate an expression node to compute the substring. */
221 if (!expression_allocate (new, MDL)) {
222 log_error ("no memory for substring expression.");
223 return 0;
224 }
225 (*new) -> op = expr_substring;
226 expression_reference (&(*new) -> data.substring.expr, expr, MDL);
227 expression_reference (&(*new) -> data.substring.offset, offset, MDL);
228 expression_reference (&(*new) -> data.substring.len, length, MDL);
229 return 1;
230 }
231
232 int make_limit (new, expr, limit)
233 struct expression **new;
234 struct expression *expr;
235 int limit;
236 {
237 struct expression *rv;
238
239 /* Allocate a node to enforce a limit on evaluation. */
240 if (!expression_allocate (new, MDL))
241 log_error ("no memory for limit expression");
242 (*new) -> op = expr_substring;
243 expression_reference (&(*new) -> data.substring.expr, expr, MDL);
244
245 /* Offset is a constant 0. */
246 if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) {
247 log_error ("no memory for limit offset expression");
248 expression_dereference (new, MDL);
249 return 0;
250 }
251 (*new) -> data.substring.offset -> op = expr_const_int;
252 (*new) -> data.substring.offset -> data.const_int = 0;
253
254 /* Length is a constant: the specified limit. */
255 if (!expression_allocate (&(*new) -> data.substring.len, MDL)) {
256 log_error ("no memory for limit length expression");
257 expression_dereference (new, MDL);
258 return 0;
259 }
260 (*new) -> data.substring.len -> op = expr_const_int;
261 (*new) -> data.substring.len -> data.const_int = limit;
262
263 return 1;
264 }
265
266 int option_cache (oc, dp, expr, option)
267 struct option_cache **oc;
268 struct data_string *dp;
269 struct expression *expr;
270 struct option *option;
271 {
272 if (!option_cache_allocate (oc, MDL))
273 return 0;
274 if (dp)
275 data_string_copy (&(*oc) -> data, dp, MDL);
276 if (expr)
277 expression_reference (&(*oc) -> expression, expr, MDL);
278 (*oc) -> option = option;
279 return 1;
280 }
281
282 int make_let (result, name)
283 struct executable_statement **result;
284 const char *name;
285 {
286 if (!(executable_statement_allocate (result, MDL)))
287 return 0;
288
289 (*result) -> op = let_statement;
290 (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL);
291 if (!(*result) -> data.let.name) {
292 executable_statement_dereference (result, MDL);
293 return 0;
294 }
295 strcpy ((*result) -> data.let.name, name);
296 return 1;
297 }
298
299 static int do_host_lookup (result, dns)
300 struct data_string *result;
301 struct dns_host_entry *dns;
302 {
303 struct hostent *h;
304 unsigned i, count;
305 unsigned new_len;
306
307 #ifdef DEBUG_EVAL
308 log_debug ("time: now = %d dns = %d diff = %d",
309 cur_time, dns -> timeout, cur_time - dns -> timeout);
310 #endif
311
312 /* If the record hasn't timed out, just copy the data and return. */
313 if (cur_time <= dns -> timeout) {
314 #ifdef DEBUG_EVAL
315 log_debug ("easy copy: %d %s",
316 dns -> data.len,
317 (dns -> data.len > 4
318 ? inet_ntoa (*(struct in_addr *)(dns -> data.data))
319 : 0));
320 #endif
321 data_string_copy (result, &dns -> data, MDL);
322 return 1;
323 }
324 #ifdef DEBUG_EVAL
325 log_debug ("Looking up %s", dns -> hostname);
326 #endif
327
328 /* Otherwise, look it up... */
329 h = gethostbyname (dns -> hostname);
330 if (!h) {
331 #ifndef NO_H_ERRNO
332 switch (h_errno) {
333 case HOST_NOT_FOUND:
334 #endif
335 log_error ("%s: host unknown.", dns -> hostname);
336 #ifndef NO_H_ERRNO
337 break;
338 case TRY_AGAIN:
339 log_error ("%s: temporary name server failure",
340 dns -> hostname);
341 break;
342 case NO_RECOVERY:
343 log_error ("%s: name server failed", dns -> hostname);
344 break;
345 case NO_DATA:
346 log_error ("%s: no A record associated with address",
347 dns -> hostname);
348 }
349 #endif /* !NO_H_ERRNO */
350
351 /* Okay to try again after a minute. */
352 dns -> timeout = cur_time + 60;
353 data_string_forget (&dns -> data, MDL);
354 return 0;
355 }
356
357 #ifdef DEBUG_EVAL
358 log_debug ("Lookup succeeded; first address is %s",
359 inet_ntoa (h -> h_addr_list [0]));
360 #endif
361
362 /* Count the number of addresses we got... */
363 for (count = 0; h -> h_addr_list [count]; count++)
364 ;
365
366 /* Dereference the old data, if any. */
367 data_string_forget (&dns -> data, MDL);
368
369 /* Do we need to allocate more memory? */
370 new_len = count * h -> h_length;
371 if (!buffer_allocate (&dns -> data.buffer, new_len, MDL))
372 {
373 log_error ("No memory for %s.", dns -> hostname);
374 return 0;
375 }
376
377 dns -> data.data = &dns -> data.buffer -> data [0];
378 dns -> data.len = new_len;
379 dns -> data.terminated = 0;
380
381 /* Addresses are conveniently stored one to the buffer, so we
382 have to copy them out one at a time... :'( */
383 for (i = 0; i < count; i++) {
384 memcpy (&dns -> data.buffer -> data [h -> h_length * i],
385 h -> h_addr_list [i], (unsigned)(h -> h_length));
386 }
387 #ifdef DEBUG_EVAL
388 log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
389 *(int *)(dns -> buffer), h -> h_addr_list [0]);
390 #endif
391
392 /* XXX Set the timeout for an hour from now.
393 XXX This should really use the time on the DNS reply. */
394 dns -> timeout = cur_time + 3600;
395
396 #ifdef DEBUG_EVAL
397 log_debug ("hard copy: %d %s", dns -> data.len,
398 (dns -> data.len > 4
399 ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));
400 #endif
401 data_string_copy (result, &dns -> data, MDL);
402 return 1;
403 }
404
405 #if defined (NSUPDATE)
406 int evaluate_dns_expression (result, packet, lease, in_options,
407 cfg_options, scope, expr)
408 ns_updrec **result;
409 struct packet *packet;
410 struct lease *lease;
411 struct option_state *in_options;
412 struct option_state *cfg_options;
413 struct binding_scope *scope;
414 struct expression *expr;
415 {
416 ns_updrec *foo;
417 unsigned long ttl = 0;
418 char *tname;
419 struct data_string name, data;
420 int r0, r1, r2, r3;
421
422 if (!result || *result) {
423 log_error ("evaluate_dns_expression called with non-null %s",
424 "result pointer");
425 #if defined (POINTER_DEBUG)
426 abort ();
427 #else
428 return 0;
429 #endif
430 }
431
432 switch (expr -> op) {
433 #if defined (NSUPDATE)
434 case expr_ns_add:
435 r0 = evaluate_numeric_expression (&ttl, packet, lease,
436 in_options, cfg_options,
437 scope,
438 expr -> data.ns_add.ttl);
439 goto nsfinish;
440
441 case expr_ns_exists:
442 ttl = 1;
443
444 case expr_ns_delete:
445 case expr_ns_not_exists:
446 r0 = 1;
447 nsfinish:
448 memset (&name, 0, sizeof name);
449 r1 = evaluate_data_expression (&name, packet, lease,
450 in_options, cfg_options, scope,
451 expr -> data.ns_add.rrname);
452 if (r1) {
453 /* The result of the evaluation may or may not
454 be NUL-terminated, but we need it
455 terminated for sure, so we have to allocate
456 a buffer and terminate it. */
457 tname = dmalloc (name.len + 1, MDL);
458 if (!tname) {
459 r2 = 0;
460 r1 = 0;
461 data_string_forget (&name, MDL);
462 } else {
463 memcpy (tname, name.data, name.len);
464 tname [name.len] = 0;
465 memset (&data, 0, sizeof data);
466 r2 = evaluate_data_expression
467 (&data, packet, lease, in_options,
468 cfg_options, scope,
469 expr -> data.ns_add.rrdata);
470 }
471 } else
472 r2 = 0;
473 if (r0 && r1 && (r2 || expr -> op != expr_ns_add)) {
474 *result = res_mkupdrec (((expr -> op == expr_ns_add ||
475 expr -> op == expr_ns_delete)
476 ? S_UPDATE : S_PREREQ),
477 tname, expr -> data.ns_add.rrclass,
478 expr -> data.ns_add.rrtype, ttl);
479 if (!*result) {
480 ngood:
481 if (r2) {
482 data_string_forget (&data, MDL);
483 r2 = 0;
484 }
485 } else {
486 if (data.len) {
487 /* As a special case, if we get exactly
488 four bytes of data, it's an IP address
489 represented as a 32-bit quantity, which
490 is actually what we *should* be getting
491 here. Because res_mkupdrec is currently
492 broken and expects a dotted quad, convert
493 it. This should be fixed when the new
494 resolver is merged. */
495 if (data.len == 4) {
496 (*result) -> r_data = dmalloc (16, MDL);
497 if (!(*result) -> r_data)
498 goto dpngood;
499 sprintf ((*result) -> r_data,
500 "%d.%d.%d.%d",
501 data.data [0], data.data [1],
502 data.data [2], data.data [3]);
503 (*result) -> r_size =
504 strlen ((*result) -> r_data);
505 } else {
506 (*result) -> r_size = data.len;
507 (*result) -> r_data = dmalloc (data.len,
508 MDL);
509 if (!(*result) -> r_data) {
510 dpngood: /* double plus ungood. */
511 res_freeupdrec (*result);
512 *result = 0;
513 goto ngood;
514 }
515 memcpy ((*result) -> r_data,
516 data.data, data.len);
517 }
518 } else {
519 (*result) -> r_data = 0;
520 (*result) -> r_size = 0;
521 }
522 switch (expr -> op) {
523 case expr_ns_add:
524 (*result) -> r_opcode = ADD;
525 break;
526 case expr_ns_delete:
527 (*result) -> r_opcode = DELETE;
528 break;
529 case expr_ns_exists:
530 (*result) -> r_opcode = YXRRSET;
531 break;
532 case expr_ns_not_exists:
533 (*result) -> r_opcode = NXRRSET;
534 break;
535
536 /* Can't happen, but satisfy gcc. */
537 default:
538 break;
539 }
540 }
541 }
542 if (r1) {
543 data_string_forget (&name, MDL);
544 dfree (tname, MDL);
545 }
546 if (r2)
547 data_string_forget (&data, MDL);
548 /* One flaw in the thinking here: an IP address and an
549 ASCII string both look like data expressions, but
550 for A records, we want an ASCII string, not a
551 binary IP address. Do I need to turn binary IP
552 addresses into a seperate type? */
553 return (r0 && r1 &&
554 (r2 || expr -> op != expr_ns_add) && *result);
555
556 #else
557 case expr_ns_add:
558 case expr_ns_delete:
559 case expr_ns_exists:
560 case expr_ns_not_exists:
561 return 0;
562 #endif
563 case expr_check:
564 case expr_equal:
565 case expr_not_equal:
566 case expr_and:
567 case expr_or:
568 case expr_not:
569 case expr_match:
570 case expr_static:
571 case expr_known:
572 case expr_exists:
573 case expr_variable_exists:
574 log_error ("Boolean opcode in evaluate_dns_expression: %d",
575 expr -> op);
576 return 0;
577
578 case expr_none:
579 case expr_substring:
580 case expr_suffix:
581 case expr_option:
582 case expr_hardware:
583 case expr_const_data:
584 case expr_packet:
585 case expr_concat:
586 case expr_encapsulate:
587 case expr_host_lookup:
588 case expr_encode_int8:
589 case expr_encode_int16:
590 case expr_encode_int32:
591 case expr_binary_to_ascii:
592 case expr_reverse:
593 case expr_filename:
594 case expr_sname:
595 case expr_pick_first_value:
596 case expr_host_decl_name:
597 case expr_config_option:
598 case expr_leased_address:
599 case expr_null:
600 case expr_variable_reference:
601 log_error ("Data opcode in evaluate_dns_expression: %d",
602 expr -> op);
603 return 0;
604
605 case expr_extract_int8:
606 case expr_extract_int16:
607 case expr_extract_int32:
608 case expr_const_int:
609 case expr_lease_time:
610 case expr_dns_transaction:
611 log_error ("Numeric opcode in evaluate_dns_expression: %d",
612 expr -> op);
613 return 0;
614 }
615
616 log_error ("Bogus opcode in evaluate_dns_expression: %d",
617 expr -> op);
618 return 0;
619 }
620 #endif /* defined (NSUPDATE) */
621
622 int evaluate_boolean_expression (result, packet, lease, in_options,
623 cfg_options, scope, expr)
624 int *result;
625 struct packet *packet;
626 struct lease *lease;
627 struct option_state *in_options;
628 struct option_state *cfg_options;
629 struct binding_scope *scope;
630 struct expression *expr;
631 {
632 struct data_string left, right;
633 struct data_string rrtype, rrname, rrdata;
634 unsigned long ttl;
635 int srrtype, srrname, srrdata, sttl;
636 int bleft, bright;
637 int sleft, sright;
638 struct binding *binding;
639
640 switch (expr -> op) {
641 case expr_check:
642 *result = check_collection (packet, lease,
643 expr -> data.check);
644 #if defined (DEBUG_EXPRESSIONS)
645 log_debug ("bool: check (%s) returns %s",
646 expr -> data.check -> name, *result ? "true" : "false");
647 #endif
648 return 1;
649
650 case expr_equal:
651 case expr_not_equal:
652 memset (&left, 0, sizeof left);
653 sleft = evaluate_data_expression (&left, packet, lease,
654 in_options, cfg_options,
655 scope,
656 expr -> data.equal [0]);
657 memset (&right, 0, sizeof right);
658 sright = evaluate_data_expression (&right, packet, lease,
659 in_options, cfg_options,
660 scope,
661 expr -> data.equal [1]);
662 if (sleft && sright) {
663 if (left.len == right.len &&
664 !memcmp (left.data, right.data, left.len))
665 *result = expr -> op == expr_equal;
666 else
667 *result = expr -> op == expr_not_equal;
668 }
669
670 #if defined (DEBUG_EXPRESSIONS)
671 log_debug ("bool: %sequal (%s, %s) = %s",
672 expr -> op == expr_not_equal ? "not" : "",
673 (sleft
674 ? print_hex_1 (left.len, left.data, 30)
675 : "NULL"),
676 (sright
677 ? print_hex_2 (right.len, right.data, 30)
678 : "NULL"),
679 ((sleft && sright)
680 ? (*result ? "true" : "false")
681 : "NULL"));
682 #endif
683 if (sleft)
684 data_string_forget (&left, MDL);
685 if (sright)
686 data_string_forget (&right, MDL);
687 return sleft && sright;
688
689 case expr_and:
690 sleft = evaluate_boolean_expression (&bleft, packet, lease,
691 in_options, cfg_options,
692 scope,
693 expr -> data.and [0]);
694 sright = evaluate_boolean_expression (&bright, packet, lease,
695 in_options, cfg_options,
696 scope,
697 expr -> data.and [1]);
698
699 #if defined (DEBUG_EXPRESSIONS)
700 log_debug ("bool: and (%s, %s) = %s",
701 sleft ? (bleft ? "true" : "false") : "NULL",
702 sright ? (bright ? "true" : "false") : "NULL",
703 ((sleft && sright)
704 ? (bleft && bright ? "true" : "false") : "NULL"));
705 #endif
706 if (sleft && sright) {
707 *result = bleft && bright;
708 return 1;
709 }
710 return 0;
711
712 case expr_or:
713 sleft = evaluate_boolean_expression (&bleft, packet, lease,
714 in_options, cfg_options,
715 scope,
716 expr -> data.or [0]);
717 sright = evaluate_boolean_expression (&bright, packet, lease,
718 in_options, cfg_options,
719 scope,
720 expr -> data.or [1]);
721 #if defined (DEBUG_EXPRESSIONS)
722 log_debug ("bool: or (%s, %s) = %s",
723 sleft ? (bleft ? "true" : "false") : "NULL",
724 sright ? (bright ? "true" : "false") : "NULL",
725 ((sleft && sright)
726 ? (bleft || bright ? "true" : "false") : "NULL"));
727 #endif
728 if (sleft && sright) {
729 *result = bleft || bright;
730 return 1;
731 }
732 return 0;
733
734 case expr_not:
735 sleft = evaluate_boolean_expression (&bleft, packet, lease,
736 in_options, cfg_options,
737 scope,
738 expr -> data.not);
739 #if defined (DEBUG_EXPRESSIONS)
740 log_debug ("bool: not (%s) = %s",
741 sleft ? (bleft ? "true" : "false") : "NULL",
742 ((sleft && sright)
743 ? (!bleft ? "true" : "false") : "NULL"));
744
745 #endif
746 if (sleft) {
747 *result = !bleft;
748 return 1;
749 }
750 return 0;
751
752 case expr_exists:
753 memset (&left, 0, sizeof left);
754 if (!in_options ||
755 !((*expr -> data.option -> universe -> get_func)
756 (&left, expr -> data.exists -> universe,
757 packet, lease, in_options, cfg_options, in_options,
758 scope, expr -> data.exists -> code)))
759 *result = 0;
760 else {
761 *result = 1;
762 data_string_forget (&left, MDL);
763 }
764 #if defined (DEBUG_EXPRESSIONS)
765 log_debug ("bool: exists %s.%s = %s",
766 expr -> data.option -> universe -> name,
767 expr -> data.option -> name,
768 *result ? "true" : MDL);
769 #endif
770 return 1;
771
772 case expr_known:
773 if (!packet) {
774 #if defined (DEBUG_EXPRESSIONS)
775 log_debug ("bool: known = NULL");
776 #endif
777 return 0;
778 }
779 #if defined (DEBUG_EXPRESSIONS)
780 log_debug ("bool: known = %s",
781 packet -> known ? "true" : "false");
782 #endif
783 *result = packet -> known;
784 return 1;
785
786 case expr_static:
787 if (!lease || !(lease -> flags & STATIC_LEASE)) {
788 #if defined (DEBUG_EXPRESSIONS)
789 log_debug ("bool: static = false");
790 #endif
791 *result = 0;
792 return 1;
793 }
794 #if defined (DEBUG_EXPRESSIONS)
795 log_debug ("bool: static = true");
796 #endif
797 *result = 1;
798 return 1;
799
800 case expr_variable_exists:
801 binding = find_binding (scope, expr -> data.variable);
802
803 if (binding) {
804 if (binding -> value.data)
805 *result = 1;
806 else
807 *result = 0;
808 } else
809 *result = 0;
810 #if defined (DEBUG_EXPRESSIONS)
811 log_debug ("boolean: %s? = %s", expr -> variable,
812 s0 ? "true" : "false");
813 #endif
814 return 1;
815
816 case expr_none:
817 case expr_match:
818 case expr_substring:
819 case expr_suffix:
820 case expr_option:
821 case expr_hardware:
822 case expr_const_data:
823 case expr_packet:
824 case expr_concat:
825 case expr_encapsulate:
826 case expr_host_lookup:
827 case expr_encode_int8:
828 case expr_encode_int16:
829 case expr_encode_int32:
830 case expr_binary_to_ascii:
831 case expr_reverse:
832 case expr_pick_first_value:
833 case expr_host_decl_name:
834 case expr_config_option:
835 case expr_leased_address:
836 case expr_null:
837 case expr_variable_reference:
838 case expr_filename:
839 case expr_sname:
840 log_error ("Data opcode in evaluate_boolean_expression: %d",
841 expr -> op);
842 return 0;
843
844 case expr_extract_int8:
845 case expr_extract_int16:
846 case expr_extract_int32:
847 case expr_const_int:
848 case expr_lease_time:
849 case expr_dns_transaction:
850 log_error ("Numeric opcode in evaluate_boolean_expression: %d",
851 expr -> op);
852 return 0;
853
854 case expr_ns_add:
855 case expr_ns_delete:
856 case expr_ns_exists:
857 case expr_ns_not_exists:
858 log_error ("dns opcode in evaluate_boolean_expression: %d",
859 expr -> op);
860 return 0;
861 }
862
863 log_error ("Bogus opcode in evaluate_boolean_expression: %d",
864 expr -> op);
865 return 0;
866 }
867
868 int evaluate_data_expression (result, packet, lease,
869 in_options, cfg_options, scope, expr)
870 struct data_string *result;
871 struct packet *packet;
872 struct lease *lease;
873 struct option_state *in_options;
874 struct option_state *cfg_options;
875 struct binding_scope *scope;
876 struct expression *expr;
877 {
878 struct data_string data, other;
879 unsigned long offset, len, i;
880 int s0, s1, s2, s3;
881 int status;
882 struct binding *binding;
883 char *s;
884
885 switch (expr -> op) {
886 /* Extract N bytes starting at byte M of a data string. */
887 case expr_substring:
888 memset (&data, 0, sizeof data);
889 s0 = evaluate_data_expression (&data, packet, lease,
890 in_options, cfg_options, scope,
891 expr -> data.substring.expr);
892
893 /* Evaluate the offset and length. */
894 s1 = evaluate_numeric_expression
895 (&offset, packet, lease, in_options, cfg_options,
896 scope, expr -> data.substring.offset);
897 s2 = evaluate_numeric_expression (&len, packet, lease,
898 in_options, cfg_options,
899 scope,
900 expr -> data.substring.len);
901
902 if (s0 && s1 && s2) {
903 /* If the offset is after end of the string,
904 return an empty string. Otherwise, do the
905 adjustments and return what's left. */
906 if (data.len > offset) {
907 data_string_copy (result, &data, MDL);
908 result -> len -= offset;
909 if (result -> len > len) {
910 result -> len = len;
911 result -> terminated = 0;
912 }
913 result -> data += offset;
914 }
915 s3 = 1;
916 } else
917 s3 = 0;
918
919 #if defined (DEBUG_EXPRESSIONS)
920 log_debug ("data: substring (%s, %s, %s) = %s",
921 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
922 s1 ? print_dec_1 (offset) : "NULL",
923 s2 ? print_dec_2 (len) : "NULL",
924 (s3 ? print_hex_2 (result -> len, result -> data, 30)
925 : "NULL"));
926 #endif
927 if (s0)
928 data_string_forget (&data, MDL);
929 if (s3)
930 return 1;
931 return 0;
932
933
934 /* Extract the last N bytes of a data string. */
935 case expr_suffix:
936 memset (&data, 0, sizeof data);
937 s0 = evaluate_data_expression (&data, packet, lease,
938 in_options, cfg_options, scope,
939 expr -> data.suffix.expr);
940 /* Evaluate the length. */
941 s1 = evaluate_numeric_expression (&len, packet, lease,
942 in_options, cfg_options,
943 scope,
944 expr -> data.substring.len);
945 if (s0 && s1) {
946 data_string_copy (result, &data, MDL);
947
948 /* If we are returning the last N bytes of a
949 string whose length is <= N, just return
950 the string - otherwise, compute a new
951 starting address and decrease the
952 length. */
953 if (data.len > len) {
954 result -> data += data.len - len;
955 result -> len = len;
956 }
957 }
958
959 #if defined (DEBUG_EXPRESSIONS)
960 log_debug ("data: suffix (%s, %s) = %s",
961 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
962 s1 ? print_dec_1 (len) : "NULL",
963 ((s0 && s1)
964 ? print_hex_2 (result -> len, result -> data, 30)
965 : "NULL"));
966 #endif
967 return s0 && s1;
968
969 /* Extract an option. */
970 case expr_option:
971 if (in_options)
972 s0 = ((*expr -> data.option -> universe -> get_func)
973 (result, expr -> data.option -> universe,
974 packet, lease,
975 in_options, cfg_options, in_options,
976 scope, expr -> data.option -> code));
977 else
978 s0 = 0;
979
980 #if defined (DEBUG_EXPRESSIONS)
981 log_debug ("data: option %s.%s = %s",
982 expr -> data.option -> universe -> name,
983 expr -> data.option -> name,
984 s0 ? print_hex_1 (result -> len, result -> data, 60)
985 : "NULL");
986 #endif
987 return s0;
988
989 case expr_config_option:
990 if (cfg_options)
991 s0 = ((*expr -> data.option -> universe -> get_func)
992 (result, expr -> data.option -> universe,
993 packet, lease,
994 in_options, cfg_options, cfg_options,
995 scope, expr -> data.option -> code));
996 else
997 s0 = 0;
998
999 #if defined (DEBUG_EXPRESSIONS)
1000 log_debug ("data: config-option %s.%s = %s",
1001 expr -> data.option -> universe -> name,
1002 expr -> data.option -> name,
1003 s0 ? print_hex_1 (result -> len, result -> data, 60)
1004 : "NULL");
1005 #endif
1006 return s0;
1007
1008 /* Combine the hardware type and address. */
1009 case expr_hardware:
1010 if (!packet || !packet -> raw) {
1011 log_error ("data: hardware: raw packet not available");
1012 return 0;
1013 }
1014 if (packet -> raw -> hlen > sizeof packet -> raw -> chaddr) {
1015 log_error ("data: hardware: invalid hlen (%d)\n",
1016 packet -> raw -> hlen);
1017 return 0;
1018 }
1019 result -> len = packet -> raw -> hlen + 1;
1020 if (buffer_allocate (&result -> buffer, result -> len, MDL)) {
1021 result -> data = &result -> buffer -> data [0];
1022 result -> buffer -> data [0] = packet -> raw -> htype;
1023 memcpy (&result -> buffer -> data [1],
1024 packet -> raw -> chaddr,
1025 packet -> raw -> hlen);
1026 result -> terminated = 0;
1027 } else {
1028 log_error ("data: hardware: no memory for buffer.");
1029 return 0;
1030 }
1031 #if defined (DEBUG_EXPRESSIONS)
1032 log_debug ("data: hardware = %s",
1033 print_hex_1 (result -> len, result -> data, 60));
1034 #endif
1035 return 1;
1036
1037 /* Extract part of the raw packet. */
1038 case expr_packet:
1039 if (!packet || !packet -> raw) {
1040 log_error ("data: packet: raw packet not available");
1041 return 0;
1042 }
1043
1044 s0 = evaluate_numeric_expression (&offset, packet, lease,
1045 in_options, cfg_options,
1046 scope,
1047 expr -> data.packet.offset);
1048 s1 = evaluate_numeric_expression (&len,
1049 packet, lease,
1050 in_options, cfg_options,
1051 scope,
1052 expr -> data.packet.len);
1053 if (s0 && s1 && offset < packet -> packet_length) {
1054 if (offset + len > packet -> packet_length)
1055 result -> len =
1056 packet -> packet_length - offset;
1057 else
1058 result -> len = len;
1059 if (buffer_allocate (&result -> buffer,
1060 result -> len, MDL)) {
1061 result -> data = &result -> buffer -> data [0];
1062 memcpy (result -> buffer -> data,
1063 (((unsigned char *)(packet -> raw))
1064 + offset), result -> len);
1065 result -> terminated = 0;
1066 } else {
1067 log_error ("data: packet: no buffer memory.");
1068 return 0;
1069 }
1070 s2 = 1;
1071 } else
1072 s2 = 0;
1073 #if defined (DEBUG_EXPRESSIONS)
1074 log_debug ("data: packet (%ld, %ld) = %s",
1075 offset, len,
1076 s2 ? print_hex_1 (result -> len,
1077 result -> data, 60) : NULL);
1078 #endif
1079 return s2;
1080
1081 /* The encapsulation of all defined options in an
1082 option space... */
1083 case expr_encapsulate:
1084 if (cfg_options)
1085 s0 = option_space_encapsulate
1086 (result, packet, lease,
1087 in_options, cfg_options, scope,
1088 &expr -> data.encapsulate);
1089 else
1090 s0 = 0;
1091
1092 #if defined (DEBUG_EXPRESSIONS)
1093 log_debug ("data: encapsulate (%s) = %s",
1094 expr -> data.encapsulate.data,
1095 s0 ? print_hex_1 (result -> len,
1096 result -> data, 60) : "NULL");
1097 #endif
1098 return s0;
1099
1100 /* Some constant data... */
1101 case expr_const_data:
1102 #if defined (DEBUG_EXPRESSIONS)
1103 log_debug ("data: const = %s",
1104 print_hex_1 (expr -> data.const_data.len,
1105 expr -> data.const_data.data, 60));
1106 #endif
1107 data_string_copy (result,
1108 &expr -> data.const_data, MDL);
1109 return 1;
1110
1111 /* Hostname lookup... */
1112 case expr_host_lookup:
1113 s0 = do_host_lookup (result, expr -> data.host_lookup);
1114 #if defined (DEBUG_EXPRESSIONS)
1115 log_debug ("data: DNS lookup (%s) = %s",
1116 expr -> data.host_lookup -> hostname,
1117 (s0
1118 ? print_dotted_quads (result -> len, result -> data)
1119 : "NULL"));
1120 #endif
1121 return s0;
1122
1123 /* Concatenation... */
1124 case expr_concat:
1125 memset (&data, 0, sizeof data);
1126 s0 = evaluate_data_expression (&data, packet, lease,
1127 in_options, cfg_options, scope,
1128 expr -> data.concat [0]);
1129 memset (&other, 0, sizeof other);
1130 s1 = evaluate_data_expression (&other, packet, lease,
1131 in_options, cfg_options, scope,
1132 expr -> data.concat [1]);
1133
1134 if (s0 && s1) {
1135 result -> len = data.len + other.len;
1136 if (!buffer_allocate (&result -> buffer,
1137 (result -> len +
1138 other.terminated), MDL)) {
1139 log_error ("data: concat: no memory");
1140 result -> len = 0;
1141 data_string_forget (&data, MDL);
1142 data_string_forget (&other, MDL);
1143 return 0;
1144 }
1145 result -> data = &result -> buffer -> data [0];
1146 memcpy (result -> buffer -> data, data.data, data.len);
1147 memcpy (&result -> buffer -> data [data.len],
1148 other.data, other.len + other.terminated);
1149 } else if (s0)
1150 data_string_forget (&data, MDL);
1151 else if (s1)
1152 data_string_forget (&other, MDL);
1153 #if defined (DEBUG_EXPRESSIONS)
1154 log_debug ("data: concat (%s, %s) = %s",
1155 s0 ? print_hex_1 (data.len, data.data, 20) : "NULL",
1156 s1 ? print_hex_2 (other.len, other.data, 20) : "NULL",
1157 ((s0 && s1)
1158 ? print_hex_3 (result -> len, result -> data, 30)
1159 : "NULL"));
1160 #endif
1161 return s0 && s1;
1162
1163 case expr_encode_int8:
1164 s0 = evaluate_numeric_expression (&len, packet, lease,
1165 in_options, cfg_options,
1166 scope,
1167 expr -> data.packet.len);
1168 if (s0) {
1169 result -> len = 1;
1170 if (!buffer_allocate (&result -> buffer, 1, MDL)) {
1171 log_error ("data: encode_int8: no memory");
1172 result -> len = 0;
1173 s0 = 0;
1174 } else {
1175 result -> data = &result -> buffer -> data [0];
1176 result -> buffer -> data [0] = len;
1177 }
1178 } else
1179 result -> len = 0;
1180
1181 #if defined (DEBUG_EXPRESSIONS)
1182 if (!s0)
1183 log_debug ("data: encode_int8 (NULL) = NULL");
1184 else
1185 log_debug ("data: encode_int8 (%ld) = %s", len,
1186 print_hex_2 (result -> len,
1187 result -> data, 20));
1188 #endif
1189 return s0;
1190
1191
1192 case expr_encode_int16:
1193 s0 = evaluate_numeric_expression (&len, packet, lease,
1194 in_options, cfg_options,
1195 scope,
1196 expr -> data.packet.len);
1197 if (s0) {
1198 result -> len = 2;
1199 if (!buffer_allocate (&result -> buffer, 2, MDL)) {
1200 log_error ("data: encode_int16: no memory");
1201 result -> len = 0;
1202 s0 = 0;
1203 } else {
1204 result -> data = &result -> buffer -> data [0];
1205 putUShort (result -> buffer -> data, len);
1206 }
1207 } else
1208 result -> len = 0;
1209
1210 #if defined (DEBUG_EXPRESSIONS)
1211 if (!s0)
1212 log_debug ("data: encode_int16 (NULL) = NULL");
1213 else
1214 log_debug ("data: encode_int16 (%ld) = %s", len,
1215 print_hex_2 (result -> len,
1216 result -> data, 20));
1217 #endif
1218 return s0;
1219
1220 case expr_encode_int32:
1221 s0 = evaluate_numeric_expression (&len, packet, lease,
1222 in_options, cfg_options,
1223 scope,
1224 expr -> data.packet.len);
1225 if (s0) {
1226 result -> len = 4;
1227 if (!buffer_allocate (&result -> buffer, 4, MDL)) {
1228 log_error ("data: encode_int32: no memory");
1229 result -> len = 0;
1230 s0 = 0;
1231 } else {
1232 result -> data = &result -> buffer -> data [0];
1233 putULong (result -> buffer -> data, len);
1234 }
1235 } else
1236 result -> len = 0;
1237
1238 #if defined (DEBUG_EXPRESSIONS)
1239 if (!s0)
1240 log_debug ("data: encode_int32 (NULL) = NULL");
1241 else
1242 log_debug ("data: encode_int32 (%ld) = %s", len,
1243 print_hex_2 (result -> len,
1244 result -> data, 20));
1245 #endif
1246 return s0;
1247
1248 case expr_binary_to_ascii:
1249 /* Evaluate the base (offset) and width (len): */
1250 s0 = evaluate_numeric_expression
1251 (&offset, packet, lease, in_options, cfg_options,
1252 scope, expr -> data.b2a.base);
1253 s1 = evaluate_numeric_expression (&len, packet, lease,
1254 in_options, cfg_options,
1255 scope,
1256 expr -> data.b2a.width);
1257
1258 /* Evaluate the seperator string. */
1259 memset (&data, 0, sizeof data);
1260 s2 = evaluate_data_expression (&data, packet, lease,
1261 in_options, cfg_options, scope,
1262 expr -> data.b2a.seperator);
1263
1264 /* Evaluate the data to be converted. */
1265 memset (&other, 0, sizeof other);
1266 s3 = evaluate_data_expression (&other, packet, lease,
1267 in_options, cfg_options, scope,
1268 expr -> data.b2a.buffer);
1269
1270 if (s0 && s1 && s2 && s3) {
1271 unsigned buflen, i;
1272
1273 if (len != 8 && len != 16 && len != 32) {
1274 log_info ("binary_to_ascii: %s %ld!",
1275 "invalid width", len);
1276 goto b2a_out;
1277 }
1278 len /= 8;
1279
1280 /* The buffer must be a multiple of the number's
1281 width. */
1282 if (other.len % len) {
1283 log_info ("binary-to-ascii: %s %d %s %ld!",
1284 "length of buffer", other.len,
1285 "not a multiple of width", len);
1286 status = 0;
1287 goto b2a_out;
1288 }
1289
1290 /* Count the width of the output. */
1291 buflen = 0;
1292 for (i = 0; i < other.len; i += len) {
1293 if (len == 1) {
1294 if (offset == 8) {
1295 if (other.data [i] < 8)
1296 buflen++;
1297 else if (other.data [i] < 64)
1298 buflen += 2;
1299 else
1300 buflen += 3;
1301 } else if (offset == 10) {
1302 if (other.data [i] < 10)
1303 buflen++;
1304 else if (other.data [i] < 100)
1305 buflen += 2;
1306 else
1307 buflen += 3;
1308 } else if (offset == 10) {
1309 if (other.data [i] < 16)
1310 buflen++;
1311 else
1312 buflen += 2;
1313 } else
1314 buflen += (converted_length
1315 (&other.data [i],
1316 offset, 1));
1317 } else
1318 buflen += (converted_length
1319 (&other.data [i],
1320 offset, len));
1321 if (i + len != other.len)
1322 buflen += data.len;
1323 }
1324
1325 if (!buffer_allocate (&result -> buffer,
1326 buflen + 1, MDL)) {
1327 log_error ("data: binary-to-ascii: no memory");
1328 status = 0;
1329 goto b2a_out;
1330 }
1331 result -> data = &result -> buffer -> data [0];
1332 result -> len = buflen;
1333 result -> terminated = 1;
1334
1335 buflen = 0;
1336 for (i = 0; i < other.len; i += len) {
1337 buflen += (binary_to_ascii
1338 (&result -> buffer -> data [buflen],
1339 &other.data [i], offset, len));
1340 if (i + len != other.len) {
1341 memcpy (&result ->
1342 buffer -> data [buflen],
1343 data.data, data.len);
1344 buflen += data.len;
1345 }
1346 }
1347 /* NUL terminate. */
1348 result -> buffer -> data [buflen] = 0;
1349 status = 1;
1350 } else
1351 status = 0;
1352
1353 b2a_out:
1354 #if defined (DEBUG_EXPRESSIONS)
1355 log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
1356 s0 ? print_dec_1 (offset) : "NULL",
1357 s1 ? print_dec_2 (len) : "NULL",
1358 s2 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1359 s3 ? print_hex_2 (other.len, other.data, 30) : "NULL",
1360 (status ? print_hex_3 (result -> len, result -> data, 30)
1361 : "NULL"));
1362 #endif
1363 if (s2)
1364 data_string_forget (&data, MDL);
1365 if (s3)
1366 data_string_forget (&other, MDL);
1367 if (status)
1368 return 1;
1369 return 0;
1370
1371 case expr_reverse:
1372 /* Evaluate the width (len): */
1373 s0 = evaluate_numeric_expression
1374 (&len, packet, lease, in_options, cfg_options,
1375 scope, expr -> data.reverse.width);
1376
1377 /* Evaluate the data. */
1378 memset (&data, 0, sizeof data);
1379 s1 = evaluate_data_expression (&data, packet, lease,
1380 in_options, cfg_options, scope,
1381 expr -> data.reverse.buffer);
1382
1383 if (s0 && s1) {
1384 char *upper;
1385 int i;
1386
1387 /* The buffer must be a multiple of the number's
1388 width. */
1389 if (other.len % len) {
1390 log_info ("reverse: %s %d %s %ld!",
1391 "length of buffer", other.len,
1392 "not a multiple of width", len);
1393 status = 0;
1394 goto reverse_out;
1395 }
1396
1397 /* XXX reverse in place? I don't think we can. */
1398 if (!buffer_allocate (&result -> buffer,
1399 data.len, MDL)) {
1400 log_error ("data: reverse: no memory");
1401 status = 0;
1402 goto reverse_out;
1403 }
1404 result -> data = &result -> buffer -> data [0];
1405 result -> len = data.len;
1406 result -> terminated = 0;
1407
1408 for (i = 0; i < data.len; i += len) {
1409 memcpy (&result -> buffer -> data [i],
1410 &data.data [data.len - i - len], len);
1411 }
1412 status = 1;
1413 } else
1414 status = 0;
1415
1416 reverse_out:
1417 #if defined (DEBUG_EXPRESSIONS)
1418 log_debug ("data: reverse (%s, %s) = %s",
1419 s0 ? print_dec_1 (len) : "NULL",
1420 s1 ? print_hex_1 (data.len, data.data, 30) : "NULL",
1421 (status ? print_hex_3 (result -> len, result -> data, 30)
1422 : "NULL"));
1423 #endif
1424 if (s0)
1425 data_string_forget (&data, MDL);
1426 if (status)
1427 return 1;
1428 return 0;
1429
1430 case expr_leased_address:
1431 if (!lease) {
1432 log_error ("data: leased_address: not available");
1433 return 0;
1434 }
1435 result -> len = lease -> ip_addr.len;
1436 if (buffer_allocate (&result -> buffer, result -> len, MDL)) {
1437 result -> data = &result -> buffer -> data [0];
1438 memcpy (&result -> buffer -> data [0],
1439 lease -> ip_addr.iabuf, lease -> ip_addr.len);
1440 result -> terminated = 0;
1441 } else {
1442 log_error ("data: leased-address: no memory.");
1443 return 0;
1444 }
1445 #if defined (DEBUG_EXPRESSIONS)
1446 log_debug ("data: leased-address = %s",
1447 print_hex_1 (result -> len, result -> data, 60));
1448 #endif
1449 return 1;
1450
1451 case expr_pick_first_value:
1452 memset (&data, 0, sizeof data);
1453 if ((evaluate_data_expression
1454 (result, packet, lease, in_options, cfg_options, scope,
1455 expr -> data.pick_first_value.car))) {
1456 #if defined (DEBUG_EXPRESSIONS)
1457 log_debug ("data: pick_first_value (%s, ???)",
1458 print_hex_1 (result -> len,
1459 result -> data, 40));
1460 #endif
1461 return 1;
1462 }
1463
1464 if (expr -> data.pick_first_value.cdr &&
1465 (evaluate_data_expression
1466 (result, packet, lease, in_options, cfg_options, scope,
1467 expr -> data.pick_first_value.cdr))) {
1468 #if defined (DEBUG_EXPRESSIONS)
1469 log_debug ("data: pick_first_value (NULL, %s)",
1470 print_hex_1 (result -> len,
1471 result -> data, 40));
1472 #endif
1473 return 1;
1474 }
1475
1476 #if defined (DEBUG_EXPRESSIONS)
1477 log_debug ("data: pick_first_value (NULL, NULL) = NULL");
1478 #endif
1479 return 0;
1480
1481 case expr_host_decl_name:
1482 if (!lease || !lease -> host) {
1483 log_error ("data: host_decl_name: not available");
1484 return 0;
1485 }
1486 result -> len = strlen (lease -> host -> name);
1487 if (buffer_allocate (&result -> buffer,
1488 result -> len + 1, MDL)) {
1489 result -> data = &result -> buffer -> data [0];
1490 strcpy ((char *)&result -> buffer -> data [0],
1491 lease -> host -> name);
1492 result -> terminated = 1;
1493 } else {
1494 log_error ("data: host-decl-name: no memory.");
1495 return 0;
1496 }
1497 #if defined (DEBUG_EXPRESSIONS)
1498 log_debug ("data: host-decl-name = %s", lease -> host -> name);
1499 #endif
1500 return 1;
1501
1502 case expr_null:
1503 #if defined (DEBUG_EXPRESSIONS)
1504 log_debug ("data: null = NULL");
1505 #endif
1506 return 0;
1507
1508 case expr_variable_reference:
1509 binding = find_binding (scope, expr -> data.variable);
1510
1511 if (binding) {
1512 if (binding -> value.data) {
1513 data_string_copy (result,
1514 &binding -> value, MDL);
1515 s0 = 1;
1516 } else
1517 s0 = 0;
1518 } else
1519 s0 = 0;
1520 #if defined (DEBUG_EXPRESSIONS)
1521 log_debug ("data: %s = %s", expr -> variable,
1522 s0 ? print_hex_1 (result -> len,
1523 result -> data, 50);
1524 #endif
1525 return s0;
1526
1527 /* Extract the filename. */
1528 case expr_filename:
1529 if (packet && packet -> raw -> file [0]) {
1530 char *fn =
1531 memchr (packet -> raw -> file, 0,
1532 sizeof packet -> raw -> file);
1533 if (!fn)
1534 fn = ((char *)packet -> raw -> file +
1535 sizeof packet -> raw -> file);
1536 result -> len = fn - &(packet -> raw -> file [0]);
1537 if (buffer_allocate (&result -> buffer,
1538 result -> len + 1, MDL)) {
1539 result -> data = &result -> buffer -> data [0];
1540 memcpy (&result -> buffer -> data [0],
1541 packet -> raw -> file,
1542 result -> len);
1543 result -> buffer -> data [result -> len] = 0;
1544 result -> terminated = 1;
1545 s0 = 1;
1546 } else {
1547 log_error ("data: filename: no memory.");
1548 s0 = 0;
1549 }
1550 } else
1551 s0 = 0;
1552
1553 #if defined (DEBUG_EXPRESSIONS)
1554 log_info ("data: filename = \"%s\"",
1555 s0 ? result -> data : "NULL");
1556 #endif
1557 return s0;
1558
1559 /* Extract the server name. */
1560 case expr_sname:
1561 if (packet && packet -> raw -> sname [0]) {
1562 char *fn =
1563 memchr (packet -> raw -> sname, 0,
1564 sizeof packet -> raw -> sname);
1565 if (!fn)
1566 fn = ((char *)packet -> raw -> sname +
1567 sizeof packet -> raw -> sname);
1568 result -> len = fn - &packet -> raw -> sname [0];
1569 if (buffer_allocate (&result -> buffer,
1570 result -> len + 1, MDL)) {
1571 result -> data = &result -> buffer -> data [0];
1572 memcpy (&result -> buffer -> data [0],
1573 packet -> raw -> sname,
1574 result -> len);
1575 result -> buffer -> data [result -> len] = 0;
1576 result -> terminated = 1;
1577 s0 = 1;
1578 } else {
1579 log_error ("data: sname: no memory.");
1580 s0 = 0;
1581 }
1582 } else
1583 s0 = 0;
1584
1585 #if defined (DEBUG_EXPRESSIONS)
1586 log_info ("data: sname = \"%s\"",
1587 s0 ? result -> data : "NULL");
1588 #endif
1589 return s0;
1590
1591 case expr_check:
1592 case expr_equal:
1593 case expr_not_equal:
1594 case expr_and:
1595 case expr_or:
1596 case expr_not:
1597 case expr_match:
1598 case expr_static:
1599 case expr_known:
1600 case expr_none:
1601 case expr_exists:
1602 case expr_variable_exists:
1603 log_error ("Boolean opcode in evaluate_data_expression: %d",
1604 expr -> op);
1605 return 0;
1606
1607 case expr_extract_int8:
1608 case expr_extract_int16:
1609 case expr_extract_int32:
1610 case expr_const_int:
1611 case expr_lease_time:
1612 case expr_dns_transaction:
1613 log_error ("Numeric opcode in evaluate_data_expression: %d",
1614 expr -> op);
1615 return 0;
1616
1617 case expr_ns_add:
1618 case expr_ns_delete:
1619 case expr_ns_exists:
1620 case expr_ns_not_exists:
1621 log_error ("dns update opcode in evaluate_data_expression: %d",
1622 expr -> op);
1623 return 0;
1624 }
1625
1626 log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op);
1627 return 0;
1628 }
1629
1630 int evaluate_numeric_expression (result, packet, lease,
1631 in_options, cfg_options, scope, expr)
1632 unsigned long *result;
1633 struct packet *packet;
1634 struct lease *lease;
1635 struct option_state *in_options;
1636 struct option_state *cfg_options;
1637 struct binding_scope *scope;
1638 struct expression *expr;
1639 {
1640 struct data_string data;
1641 int status;
1642 #if defined (NSUPDATE)
1643 ns_updrec *nut;
1644 static struct __res_state res;
1645 ns_updque uq;
1646 static int inited;
1647 #endif
1648 struct expression *cur, *next;
1649
1650 switch (expr -> op) {
1651 case expr_check:
1652 case expr_equal:
1653 case expr_not_equal:
1654 case expr_and:
1655 case expr_or:
1656 case expr_not:
1657 case expr_match:
1658 case expr_static:
1659 case expr_known:
1660 case expr_none:
1661 case expr_exists:
1662 case expr_variable_exists:
1663 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
1664 expr -> op);
1665 return 0;
1666
1667 case expr_substring:
1668 case expr_suffix:
1669 case expr_option:
1670 case expr_hardware:
1671 case expr_const_data:
1672 case expr_packet:
1673 case expr_concat:
1674 case expr_encapsulate:
1675 case expr_host_lookup:
1676 case expr_encode_int8:
1677 case expr_encode_int16:
1678 case expr_encode_int32:
1679 case expr_binary_to_ascii:
1680 case expr_reverse:
1681 case expr_filename:
1682 case expr_sname:
1683 case expr_pick_first_value:
1684 case expr_host_decl_name:
1685 case expr_config_option:
1686 case expr_leased_address:
1687 case expr_null:
1688 case expr_variable_reference:
1689 log_error ("Data opcode in evaluate_numeric_expression: %d",
1690 expr -> op);
1691 return 0;
1692
1693 case expr_extract_int8:
1694 memset (&data, 0, sizeof data);
1695 status = evaluate_data_expression
1696 (&data, packet, lease, in_options, cfg_options,
1697 scope, expr -> data.extract_int);
1698 if (status)
1699 *result = data.data [0];
1700 #if defined (DEBUG_EXPRESSIONS)
1701 log_debug ("num: extract_int8 (%s) = %s",
1702 status ? print_hex_1 (data.len, data.data, 60) : "NULL",
1703 status ? print_dec_1 (*result) : "NULL" );
1704 #endif
1705 if (status) data_string_forget (&data, MDL);
1706 return status;
1707
1708 case expr_extract_int16:
1709 memset (&data, 0, sizeof data);
1710 status = (evaluate_data_expression
1711 (&data, packet, lease, in_options, cfg_options,
1712 scope, expr -> data.extract_int));
1713 if (status && data.len >= 2)
1714 *result = getUShort (data.data);
1715 #if defined (DEBUG_EXPRESSIONS)
1716 log_debug ("num: extract_int16 (%s) = %ld",
1717 ((status && data.len >= 2) ?
1718 print_hex_1 (data.len, data.data, 60) : "NULL"),
1719 *result);
1720 #endif
1721 if (status) data_string_forget (&data, MDL);
1722 return (status && data.len >= 2);
1723
1724 case expr_extract_int32:
1725 memset (&data, 0, sizeof data);
1726 status = (evaluate_data_expression
1727 (&data, packet, lease, in_options, cfg_options,
1728 scope, expr -> data.extract_int));
1729 if (status && data.len >= 4)
1730 *result = getULong (data.data);
1731 #if defined (DEBUG_EXPRESSIONS)
1732 log_debug ("num: extract_int32 (%s) = %ld",
1733 ((status && data.len >= 4) ?
1734 print_hex_1 (data.len, data.data, 60) : "NULL"),
1735 *result);
1736 #endif
1737 if (status) data_string_forget (&data, MDL);
1738 return (status && data.len >= 4);
1739
1740 case expr_const_int:
1741 *result = expr -> data.const_int;
1742 #if defined (DEBUG_EXPRESSIONS)
1743 log_debug ("number: CONSTANT = %ld", *result);
1744 #endif
1745 return 1;
1746
1747 case expr_lease_time:
1748 if (!lease) {
1749 log_error ("data: leased_lease: not available");
1750 return 0;
1751 }
1752 if (lease -> ends < cur_time) {
1753 log_error ("%s %lu when it is now %lu",
1754 "data: lease_time: lease ends at",
1755 lease -> ends, cur_time);
1756 return 0;
1757 }
1758 *result = lease -> ends - cur_time;
1759 #if defined (DEBUG_EXPRESSIONS)
1760 log_debug ("number: lease-time = (%lu - %lu) = %ld",
1761 lease -> ends,
1762 cur_time, *result);
1763 #endif
1764 return 1;
1765
1766 case expr_dns_transaction:
1767 #if !defined (NSUPDATE)
1768 return 0;
1769 #else
1770 if (!inited) {
1771 res_ninit (&res);
1772 inited = 1;
1773 }
1774 INIT_LIST (uq);
1775 cur = expr;
1776 do {
1777 next = cur -> data.dns_transaction.cdr;
1778 nut = 0;
1779 status = (evaluate_dns_expression
1780 (&nut, packet, lease, in_options, cfg_options,
1781 scope, cur -> data.dns_transaction.car));
1782 if (!status)
1783 goto dns_bad;
1784 APPEND (uq, nut, r_link);
1785 cur = next;
1786 } while (next);
1787
1788 /* Do the update and record the error code, if there was
1789 an error; otherwise set it to NOERROR. */
1790 if (res_nupdate (&res, HEAD (uq), NULL))
1791 *result = NOERROR;
1792 else
1793 /* The resolver doesn't return any actual error
1794 codes - just 1 for success, zero for failure! */
1795 /* *result = res.res_h_errno; */
1796 *result = SERVFAIL;
1797 status = 1;
1798
1799 print_dns_status ((int)*result, &uq);
1800
1801 dns_bad:
1802 while (!EMPTY (uq)) {
1803 ns_updrec *tmp = HEAD (uq);
1804 UNLINK (uq, tmp, r_link);
1805 if (tmp -> r_data) {
1806 dfree (tmp -> r_data, MDL);
1807 tmp -> r_data = (char *)0;
1808 }
1809 if (tmp -> r_dname) {
1810 dfree (tmp -> r_dname, MDL);
1811 tmp -> r_dname = (char *)0;
1812 }
1813 res_freeupdrec (tmp);
1814 }
1815 return status;
1816 #endif /* NSUPDATE */
1817
1818 case expr_ns_add:
1819 case expr_ns_delete:
1820 case expr_ns_exists:
1821 case expr_ns_not_exists:
1822 log_error ("dns opcode in evaluate_numeric_expression: %d",
1823 expr -> op);
1824 return 0;
1825 }
1826
1827 log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op);
1828 return 0;
1829 }
1830
1831 /* Return data hanging off of an option cache structure, or if there
1832 isn't any, evaluate the expression hanging off of it and return the
1833 result of that evaluation. There should never be both an expression
1834 and a valid data_string. */
1835
1836 int evaluate_option_cache (result, packet, lease,
1837 in_options, cfg_options, scope, oc, file, line)
1838 struct data_string *result;
1839 struct packet *packet;
1840 struct lease *lease;
1841 struct option_state *in_options;
1842 struct option_state *cfg_options;
1843 struct binding_scope *scope;
1844 struct option_cache *oc;
1845 const char *file;
1846 int line;
1847 {
1848 if (oc -> data.len) {
1849 data_string_copy (result, &oc -> data, file, line);
1850 return 1;
1851 }
1852 if (!oc -> expression)
1853 return 0;
1854 return evaluate_data_expression (result, packet, lease,
1855 in_options, cfg_options, scope,
1856 oc -> expression);
1857 }
1858
1859 /* Evaluate an option cache and extract a boolean from the result,
1860 returning the boolean. Return false if there is no data. */
1861
1862 int evaluate_boolean_option_cache (ignorep, packet, lease, in_options,
1863 cfg_options, scope, oc, file, line)
1864 int *ignorep;
1865 struct packet *packet;
1866 struct lease *lease;
1867 struct option_state *in_options;
1868 struct option_state *cfg_options;
1869 struct binding_scope *scope;
1870 struct option_cache *oc;
1871 const char *file;
1872 int line;
1873 {
1874 struct data_string ds;
1875 int result;
1876
1877 /* So that we can be called with option_lookup as an argument. */
1878 if (!oc || !in_options)
1879 return 0;
1880
1881 memset (&ds, 0, sizeof ds);
1882 if (!evaluate_option_cache (&ds, packet, lease, in_options,
1883 cfg_options, scope, oc, file, line))
1884 return 0;
1885
1886 if (ds.len) {
1887 result = ds.data [0];
1888 if (result == 2) {
1889 result = 0;
1890 *ignorep = 1;
1891 } else
1892 *ignorep = 0;
1893 } else
1894 result = 0; data_string_forget (&ds, MDL);
1895 return result;
1896 }
1897
1898
1899 /* Evaluate a boolean expression and return the result of the evaluation,
1900 or FALSE if it failed. */
1901
1902 int evaluate_boolean_expression_result (ignorep, packet, lease, in_options,
1903 cfg_options, scope, expr)
1904 int *ignorep;
1905 struct packet *packet;
1906 struct lease *lease;
1907 struct option_state *in_options;
1908 struct option_state *cfg_options;
1909 struct binding_scope *scope;
1910 struct expression *expr;
1911 {
1912 int result;
1913
1914 /* So that we can be called with option_lookup as an argument. */
1915 if (!expr)
1916 return 0;
1917
1918 if (!evaluate_boolean_expression (&result, packet, lease,
1919 in_options, cfg_options,
1920 scope, expr))
1921 return 0;
1922
1923 if (result == 2) {
1924 *ignorep = 1;
1925 result = 0;
1926 } else
1927 *ignorep = 0;
1928 return result;
1929 }
1930
1931
1932 /* Dereference an expression node, and if the reference count goes to zero,
1933 dereference any data it refers to, and then free it. */
1934 void expression_dereference (eptr, file, line)
1935 struct expression **eptr;
1936 const char *file;
1937 int line;
1938 {
1939 struct expression *expr = *eptr;
1940
1941 /* Zero the pointer. */
1942 *eptr = (struct expression *)0;
1943
1944 /* Decrement the reference count. If it's nonzero, we're
1945 done. */
1946 --(expr -> refcnt);
1947 rc_register (file, line, expr, expr -> refcnt);
1948 if (expr -> refcnt > 0)
1949 return;
1950 if (expr -> refcnt < 0) {
1951 log_error ("%s(%d): negative refcnt!", file, line);
1952 #if defined (DEBUG_RC_HISTORY)
1953 dump_rc_history ();
1954 #endif
1955 #if defined (POINTER_DEBUG)
1956 abort ();
1957 #else
1958 return;
1959 #endif
1960 }
1961
1962 /* Dereference subexpressions. */
1963 switch (expr -> op) {
1964 /* All the binary operators can be handled the same way. */
1965 case expr_equal:
1966 case expr_not_equal:
1967 case expr_concat:
1968 case expr_and:
1969 case expr_or:
1970 if (expr -> data.equal [0])
1971 expression_dereference (&expr -> data.equal [0],
1972 file, line);
1973 if (expr -> data.equal [1])
1974 expression_dereference (&expr -> data.equal [1],
1975 file, line);
1976 break;
1977
1978 case expr_substring:
1979 if (expr -> data.substring.expr)
1980 expression_dereference (&expr -> data.substring.expr,
1981 file, line);
1982 if (expr -> data.substring.offset)
1983 expression_dereference (&expr -> data.substring.offset,
1984 file, line);
1985 if (expr -> data.substring.len)
1986 expression_dereference (&expr -> data.substring.len,
1987 file, line);
1988 break;
1989
1990 case expr_suffix:
1991 if (expr -> data.suffix.expr)
1992 expression_dereference (&expr -> data.suffix.expr,
1993 file, line);
1994 if (expr -> data.suffix.len)
1995 expression_dereference (&expr -> data.suffix.len,
1996 file, line);
1997 break;
1998
1999 case expr_not:
2000 if (expr -> data.not)
2001 expression_dereference (&expr -> data.not, file, line);
2002 break;
2003
2004 case expr_packet:
2005 if (expr -> data.packet.offset)
2006 expression_dereference (&expr -> data.packet.offset,
2007 file, line);
2008 if (expr -> data.packet.len)
2009 expression_dereference (&expr -> data.packet.len,
2010 file, line);
2011 break;
2012
2013 case expr_extract_int8:
2014 case expr_extract_int16:
2015 case expr_extract_int32:
2016 if (expr -> data.extract_int)
2017 expression_dereference (&expr -> data.extract_int,
2018 file, line);
2019 break;
2020
2021 case expr_encode_int8:
2022 case expr_encode_int16:
2023 case expr_encode_int32:
2024 if (expr -> data.encode_int)
2025 expression_dereference (&expr -> data.encode_int,
2026 file, line);
2027 break;
2028
2029 case expr_encapsulate:
2030 case expr_const_data:
2031 data_string_forget (&expr -> data.const_data, file, line);
2032 break;
2033
2034 case expr_host_lookup:
2035 if (expr -> data.host_lookup)
2036 dns_host_entry_dereference (&expr -> data.host_lookup,
2037 file, line);
2038 break;
2039
2040 case expr_binary_to_ascii:
2041 if (expr -> data.b2a.base)
2042 expression_dereference (&expr -> data.b2a.base,
2043 file, line);
2044 if (expr -> data.b2a.width)
2045 expression_dereference (&expr -> data.b2a.width,
2046 file, line);
2047 if (expr -> data.b2a.seperator)
2048 expression_dereference (&expr -> data.b2a.seperator,
2049 file, line);
2050 if (expr -> data.b2a.buffer)
2051 expression_dereference (&expr -> data.b2a.buffer,
2052 file, line);
2053 break;
2054
2055 case expr_pick_first_value:
2056 if (expr -> data.pick_first_value.car)
2057 expression_dereference (&expr -> data.pick_first_value.car,
2058 file, line);
2059 if (expr -> data.pick_first_value.cdr)
2060 expression_dereference (&expr -> data.pick_first_value.cdr,
2061 file, line);
2062 break;
2063
2064 case expr_reverse:
2065 if (expr -> data.reverse.width)
2066 expression_dereference (&expr -> data.reverse.width,
2067 file, line);
2068 if (expr -> data.reverse.buffer)
2069 expression_dereference
2070 (&expr -> data.reverse.buffer, file, line);
2071 break;
2072
2073 case expr_dns_transaction:
2074 if (expr -> data.dns_transaction.car)
2075 expression_dereference (&expr -> data.dns_transaction.car,
2076 file, line);
2077 if (expr -> data.dns_transaction.cdr)
2078 expression_dereference (&expr -> data.dns_transaction.cdr,
2079 file, line);
2080 break;
2081
2082 case expr_ns_add:
2083 if (expr -> data.ns_add.rrname)
2084 expression_dereference (&expr -> data.ns_add.rrname,
2085 file, line);
2086 if (expr -> data.ns_add.rrdata)
2087 expression_dereference (&expr -> data.ns_add.rrdata,
2088 file, line);
2089 if (expr -> data.ns_add.ttl)
2090 expression_dereference (&expr -> data.ns_add.ttl,
2091 file, line);
2092 break;
2093
2094 case expr_ns_delete:
2095 case expr_ns_exists:
2096 case expr_ns_not_exists:
2097 if (expr -> data.ns_delete.rrname)
2098 expression_dereference (&expr -> data.ns_delete.rrname,
2099 file, line);
2100 if (expr -> data.ns_delete.rrdata)
2101 expression_dereference (&expr -> data.ns_delete.rrdata,
2102 file, line);
2103 break;
2104
2105 case expr_variable_reference:
2106 case expr_variable_exists:
2107 if (expr -> data.variable)
2108 dfree (expr -> data.variable, file, line);
2109 break;
2110
2111 /* No subexpressions. */
2112 case expr_leased_address:
2113 case expr_lease_time:
2114 case expr_filename:
2115 case expr_sname:
2116 case expr_const_int:
2117 case expr_check:
2118 case expr_option:
2119 case expr_hardware:
2120 case expr_exists:
2121 case expr_known:
2122 case expr_null:
2123 break;
2124
2125 default:
2126 break;
2127 }
2128 free_expression (expr, MDL);
2129 }
2130
2131 int is_dns_expression (expr)
2132 struct expression *expr;
2133 {
2134 return (expr -> op == expr_ns_add ||
2135 expr -> op == expr_ns_delete ||
2136 expr -> op == expr_ns_exists ||
2137 expr -> op == expr_ns_not_exists);
2138 }
2139
2140 int is_boolean_expression (expr)
2141 struct expression *expr;
2142 {
2143 return (expr -> op == expr_check ||
2144 expr -> op == expr_exists ||
2145 expr -> op == expr_variable_exists ||
2146 expr -> op == expr_equal ||
2147 expr -> op == expr_not_equal ||
2148 expr -> op == expr_and ||
2149 expr -> op == expr_or ||
2150 expr -> op == expr_not ||
2151 expr -> op == expr_known ||
2152 expr -> op == expr_static);
2153 }
2154
2155 int is_data_expression (expr)
2156 struct expression *expr;
2157 {
2158 return (expr -> op == expr_substring ||
2159 expr -> op == expr_suffix ||
2160 expr -> op == expr_option ||
2161 expr -> op == expr_hardware ||
2162 expr -> op == expr_const_data ||
2163 expr -> op == expr_packet ||
2164 expr -> op == expr_concat ||
2165 expr -> op == expr_encapsulate ||
2166 expr -> op == expr_encode_int8 ||
2167 expr -> op == expr_encode_int16 ||
2168 expr -> op == expr_encode_int32 ||
2169 expr -> op == expr_host_lookup ||
2170 expr -> op == expr_binary_to_ascii ||
2171 expr -> op == expr_filename ||
2172 expr -> op == expr_sname ||
2173 expr -> op == expr_reverse ||
2174 expr -> op == expr_pick_first_value ||
2175 expr -> op == expr_host_decl_name ||
2176 expr -> op == expr_leased_address ||
2177 expr -> op == expr_config_option ||
2178 expr -> op == expr_null ||
2179 expr -> op == expr_variable_reference);
2180 }
2181
2182 int is_numeric_expression (expr)
2183 struct expression *expr;
2184 {
2185 return (expr -> op == expr_extract_int8 ||
2186 expr -> op == expr_extract_int16 ||
2187 expr -> op == expr_extract_int32 ||
2188 expr -> op == expr_const_int ||
2189 expr -> op == expr_lease_time ||
2190 expr -> op == expr_dns_transaction);
2191 }
2192
2193 int is_compound_expression (expr)
2194 struct expression *expr;
2195 {
2196 return (expr -> op == expr_ns_add ||
2197 expr -> op == expr_ns_delete ||
2198 expr -> op == expr_ns_exists ||
2199 expr -> op == expr_ns_not_exists ||
2200 expr -> op == expr_substring ||
2201 expr -> op == expr_suffix ||
2202 expr -> op == expr_option ||
2203 expr -> op == expr_concat ||
2204 expr -> op == expr_encode_int8 ||
2205 expr -> op == expr_encode_int16 ||
2206 expr -> op == expr_encode_int32 ||
2207 expr -> op == expr_binary_to_ascii ||
2208 expr -> op == expr_reverse ||
2209 expr -> op == expr_pick_first_value ||
2210 expr -> op == expr_config_option ||
2211 expr -> op == expr_extract_int8 ||
2212 expr -> op == expr_extract_int16 ||
2213 expr -> op == expr_extract_int32 ||
2214 expr -> op == expr_dns_transaction);
2215 }
2216
2217 static int op_val PROTO ((enum expr_op));
2218
2219 static int op_val (op)
2220 enum expr_op op;
2221 {
2222 switch (op) {
2223 case expr_none:
2224 case expr_match:
2225 case expr_static:
2226 case expr_check:
2227 case expr_substring:
2228 case expr_suffix:
2229 case expr_concat:
2230 case expr_encapsulate:
2231 case expr_host_lookup:
2232 case expr_not:
2233 case expr_option:
2234 case expr_hardware:
2235 case expr_packet:
2236 case expr_const_data:
2237 case expr_extract_int8:
2238 case expr_extract_int16:
2239 case expr_extract_int32:
2240 case expr_encode_int8:
2241 case expr_encode_int16:
2242 case expr_encode_int32:
2243 case expr_const_int:
2244 case expr_exists:
2245 case expr_variable_exists:
2246 case expr_known:
2247 case expr_binary_to_ascii:
2248 case expr_reverse:
2249 case expr_filename:
2250 case expr_sname:
2251 case expr_pick_first_value:
2252 case expr_host_decl_name:
2253 case expr_config_option:
2254 case expr_leased_address:
2255 case expr_lease_time:
2256 case expr_dns_transaction:
2257 case expr_null:
2258 case expr_variable_reference:
2259 case expr_ns_add:
2260 case expr_ns_delete:
2261 case expr_ns_exists:
2262 case expr_ns_not_exists:
2263 return 100;
2264
2265 case expr_equal:
2266 case expr_not_equal:
2267 return 3;
2268
2269 case expr_and:
2270 return 1;
2271
2272 case expr_or:
2273 return 2;
2274 }
2275 return 100;
2276 }
2277
2278 int op_precedence (op1, op2)
2279 enum expr_op op1, op2;
2280 {
2281 int ov1, ov2;
2282
2283 return op_val (op1) - op_val (op2);
2284 }
2285
2286 enum expression_context op_context (op)
2287 enum expr_op op;
2288 {
2289 switch (op) {
2290 /* XXX Why aren't these specific? */
2291 case expr_none:
2292 case expr_match:
2293 case expr_static:
2294 case expr_check:
2295 case expr_substring:
2296 case expr_suffix:
2297 case expr_concat:
2298 case expr_encapsulate:
2299 case expr_host_lookup:
2300 case expr_not:
2301 case expr_option:
2302 case expr_hardware:
2303 case expr_packet:
2304 case expr_const_data:
2305 case expr_extract_int8:
2306 case expr_extract_int16:
2307 case expr_extract_int32:
2308 case expr_encode_int8:
2309 case expr_encode_int16:
2310 case expr_encode_int32:
2311 case expr_const_int:
2312 case expr_exists:
2313 case expr_variable_exists:
2314 case expr_known:
2315 case expr_binary_to_ascii:
2316 case expr_reverse:
2317 case expr_filename:
2318 case expr_sname:
2319 case expr_pick_first_value:
2320 case expr_host_decl_name:
2321 case expr_config_option:
2322 case expr_leased_address:
2323 case expr_lease_time:
2324 case expr_null:
2325 case expr_variable_reference:
2326 case expr_ns_add:
2327 case expr_ns_delete:
2328 case expr_ns_exists:
2329 case expr_ns_not_exists:
2330 case expr_dns_transaction:
2331 return context_any;
2332
2333 case expr_equal:
2334 case expr_not_equal:
2335 return context_data;
2336
2337 case expr_and:
2338 return context_boolean;
2339
2340 case expr_or:
2341 return context_boolean;
2342 }
2343 return context_any;
2344 }
2345
2346 int write_expression (file, expr, col, indent, firstp)
2347 FILE *file;
2348 struct expression *expr;
2349 int col;
2350 int indent;
2351 int firstp;
2352 {
2353 struct expression *e;
2354 const char *s;
2355 char obuf [65];
2356 int scol;
2357 int width;
2358
2359 /* If this promises to be a fat expression, start a new line. */
2360 if (!firstp && is_compound_expression (expr)) {
2361 indent_spaces (file, indent);
2362 col = indent;
2363 }
2364
2365 switch (expr -> op) {
2366 case expr_none:
2367 col = token_print_indent (file, col, indent, "", "", "null");
2368 break;
2369
2370 case expr_check:
2371 col = token_print_indent (file, col, indent, "", "", "check");
2372 col = token_print_indent_concat (file, col, indent,
2373 " ", "", "\"",
2374 expr -> data.check -> name,
2375 "\"", (char *)0);
2376 break;
2377
2378 case expr_not_equal:
2379 s = "!=";
2380 goto binary;
2381
2382 case expr_equal:
2383 s = "=";
2384 binary:
2385 col = write_expression (file, expr -> data.equal [0],
2386 col, indent, 1);
2387 col = token_print_indent (file, col, indent, " ", " ", s);
2388 col = write_expression (file, expr -> data.equal [1],
2389 col, indent + 2, 0);
2390 break;
2391
2392 case expr_substring:
2393 col = token_print_indent (file, col, indent, "", "",
2394 "substring");
2395 col = token_print_indent (file, col, indent, " ", "", "(");
2396 scol = col;
2397 col = write_expression (file, expr -> data.substring.expr,
2398 col, scol, 1);
2399 col = token_print_indent (file, col, indent, "", " ", ",");
2400 col = write_expression (file, expr -> data.substring.offset,
2401 col, indent, 0);
2402 col = token_print_indent (file, col, scol, "", " ", ",");
2403 col = write_expression (file, expr -> data.substring.len,
2404 col, scol, 0);
2405 col = token_print_indent (file, col, indent, "", "", ")");
2406 break;
2407
2408 case expr_suffix:
2409 col = token_print_indent (file, col, indent, "", "", "suffix");
2410 col = token_print_indent (file, col, indent, " ", "", "(");
2411 scol = col;
2412 col = write_expression (file, expr -> data.suffix.expr,
2413 col, scol, 1);
2414 col = token_print_indent (file, col, scol, "", " ", ",");
2415 col = write_expression (file, expr -> data.suffix.len,
2416 col, scol, 0);
2417 col = token_print_indent (file, col, indent, "", "", ")");
2418 break;
2419
2420 case expr_concat:
2421 e = expr;
2422 col = token_print_indent (file, col, indent, "", "",
2423 "concat");
2424 col = token_print_indent (file, col, indent, " ", "", "(");
2425 scol = col;
2426 firstp = 1;
2427 concat_again:
2428 col = write_expression (file, e -> data.concat [0],
2429 col, scol, firstp);
2430 firstp = 0;
2431 if (!e -> data.concat [1])
2432 goto no_concat_cdr;
2433 col = token_print_indent (file, col, scol, "", " ", ",");
2434 if (e -> data.concat [1] -> op == expr_concat) {
2435 e = e -> data.concat [1];
2436 goto concat_again;
2437 }
2438 col = write_expression (file, e -> data.concat [1],
2439 col, scol, 0);
2440 no_concat_cdr:
2441 col = token_print_indent (file, col, indent, "", "", ")");
2442 break;
2443
2444 case expr_host_lookup:
2445 col = token_print_indent (file, col, indent, "", "",
2446 "gethostbyname");
2447 col = token_print_indent (file, col, indent, " ", "", "(");
2448 col = token_print_indent_concat
2449 (file, col, indent, "", "",
2450 "\"", expr -> data.host_lookup -> hostname, "\"",
2451 (char *)0);
2452 col = token_print_indent (file, col, indent, "", "", ")");
2453 break;
2454
2455 case expr_and:
2456 s = "and";
2457 goto binary;
2458
2459 case expr_or:
2460 s = "or";
2461 goto binary;
2462
2463 case expr_not:
2464 col = token_print_indent (file, col, indent, "", " ", "not");
2465 col = write_expression (file,
2466 expr -> data.not, col, indent + 2, 1);
2467 break;
2468
2469 case expr_option:
2470 s = "option";
2471
2472 print_option_name:
2473 col = token_print_indent (file, col, indent, "", "", s);
2474
2475 if (expr -> data.option -> universe != &dhcp_universe) {
2476 col = token_print_indent (file, col, indent,
2477 " ", "",
2478 (expr -> data.option ->
2479 universe -> name));
2480 col = token_print_indent (file, col, indent, "", "",
2481 ".");
2482 col = token_print_indent (file, col, indent, "", "",
2483 expr -> data.option -> name);
2484 } else {
2485 col = token_print_indent (file, col, indent, " ", "",
2486 expr -> data.option -> name);
2487 }
2488 break;
2489
2490 case expr_hardware:
2491 col = token_print_indent (file, col, indent, "", "",
2492 "hardware");
2493 break;
2494
2495 case expr_packet:
2496 col = token_print_indent (file, col, indent, "", "",
2497 "packet");
2498 col = token_print_indent (file, col, indent, " ", "", "(");
2499 scol = col;
2500 col = write_expression (file, expr -> data.packet.offset,
2501 col, indent, 1);
2502 col = token_print_indent (file, col, scol, "", " ", ",");
2503 col = write_expression (file, expr -> data.packet.len,
2504 col, scol, 0);
2505 col = token_print_indent (file, col, indent, "", "", ")");
2506 break;
2507
2508 case expr_const_data:
2509 col = token_indent_data_string (file, col, indent, "", "",
2510 &expr -> data.const_data);
2511 break;
2512
2513 case expr_extract_int8:
2514 width = 8;
2515 extract_int:
2516 col = token_print_indent (file, col, indent, "", "",
2517 "extract-int");
2518 col = token_print_indent (file, col, indent, " ", "", "(");
2519 scol = col;
2520 col = write_expression (file, expr -> data.extract_int,
2521 col, indent, 1);
2522 col = token_print_indent (file, col, scol, "", " ", ",");
2523 sprintf (obuf, "%d", width);
2524 col = token_print_indent (file, col, scol, " ", "", obuf);
2525 col = token_print_indent (file, col, indent, "", "", ")");
2526 break;
2527
2528 case expr_extract_int16:
2529 width = 16;
2530 goto extract_int;
2531
2532 case expr_extract_int32:
2533 width = 32;
2534 goto extract_int;
2535
2536 case expr_encode_int8:
2537 width = 8;
2538 encode_int:
2539 col = token_print_indent (file, col, indent, "", "",
2540 "encode-int");
2541 col = token_print_indent (file, col, indent, " ", "", "(");
2542 scol = col;
2543 col = write_expression (file, expr -> data.extract_int,
2544 col, indent, 1);
2545 col = token_print_indent (file, col, scol, "", " ", ",");
2546 sprintf (obuf, "%d", width);
2547 col = token_print_indent (file, col, scol, " ", "", obuf);
2548 col = token_print_indent (file, col, indent, "", "",
2549 ")");
2550 break;
2551
2552 case expr_encode_int16:
2553 width = 16;
2554 goto encode_int;
2555
2556 case expr_encode_int32:
2557 width = 32;
2558 goto encode_int;
2559
2560 case expr_const_int:
2561 sprintf (obuf, "%lu", expr -> data.const_int);
2562 col = token_print_indent (file, col, indent, "", "", obuf);
2563 break;
2564
2565 case expr_exists:
2566 s = "exists";
2567 goto print_option_name;
2568
2569 case expr_encapsulate:
2570 col = token_print_indent (file, col, indent, "", "",
2571 "encapsulate");
2572 col = token_indent_data_string (file, col, indent, " ", "",
2573 &expr -> data.encapsulate);
2574 break;
2575
2576 case expr_known:
2577 col = token_print_indent (file, col, indent, "", "", "known");
2578 break;
2579
2580 case expr_reverse:
2581 col = token_print_indent (file, col, indent, "", "",
2582 "reverse");
2583 col = token_print_indent (file, col, indent, " ", "", "(");
2584 scol = col;
2585 col = write_expression (file, expr -> data.reverse.width,
2586 col, scol, 1);
2587 col = token_print_indent (file, col, scol, "", " ", ",");
2588 col = write_expression (file, expr -> data.reverse.buffer,
2589 col, scol, 0);
2590 col = token_print_indent (file, col, indent, "", "",
2591 ")");
2592 break;
2593
2594 case expr_leased_address:
2595 col = token_print_indent (file, col, indent, "", "",
2596 "leased-address");
2597 break;
2598
2599 case expr_binary_to_ascii:
2600 col = token_print_indent (file, col, indent, "", "",
2601 "binary-to-ascii");
2602 col = token_print_indent (file, col, indent, " ", "",
2603 "(");
2604 scol = col;
2605 col = write_expression (file, expr -> data.b2a.base,
2606 col, scol, 1);
2607 col = token_print_indent (file, col, scol, "", " ",
2608 ",");
2609 col = write_expression (file, expr -> data.b2a.width,
2610 col, scol, 0);
2611 col = token_print_indent (file, col, scol, "", " ",
2612 ",");
2613 col = write_expression (file, expr -> data.b2a.seperator,
2614 col, scol, 0);
2615 col = token_print_indent (file, col, scol, "", " ",
2616 ",");
2617 col = write_expression (file, expr -> data.b2a.buffer,
2618 col, scol, 0);
2619 col = token_print_indent (file, col, indent, "", "",
2620 ")");
2621 break;
2622
2623 case expr_config_option:
2624 s = "config-option";
2625 goto print_option_name;
2626
2627 case expr_host_decl_name:
2628 col = token_print_indent (file, col, indent, "", "",
2629 "host-decl-name");
2630 break;
2631
2632 case expr_pick_first_value:
2633 e = expr;
2634 col = token_print_indent (file, col, indent, "", "",
2635 "concat");
2636 col = token_print_indent (file, col, indent, " ", "",
2637 "(");
2638 scol = col;
2639 firstp = 1;
2640 pick_again:
2641 col = write_expression (file,
2642 e -> data.pick_first_value.car,
2643 col, scol, firstp);
2644 firstp = 0;
2645 /* We're being very lisp-like right now - instead of
2646 representing this expression as (first middle . last) we're
2647 representing it as (first middle last), which means that the
2648 tail cdr is always nil. Apologies to non-wisp-lizards - may
2649 this obscure way of describing the problem motivate you to
2650 learn more about the one true computing language. */
2651 if (!e -> data.pick_first_value.cdr)
2652 goto no_pick_cdr;
2653 col = token_print_indent (file, col, scol, "", " ",
2654 ",");
2655 if (e -> data.pick_first_value.cdr -> op ==
2656 expr_pick_first_value) {
2657 e = e -> data.pick_first_value.cdr;
2658 goto pick_again;
2659 }
2660 col = write_expression (file,
2661 e -> data.pick_first_value.cdr,
2662 col, scol, 0);
2663 no_pick_cdr:
2664 col = token_print_indent (file, col, indent, "", "",
2665 ")");
2666 break;
2667
2668 case expr_lease_time:
2669 col = token_print_indent (file, col, indent, "", "",
2670 "lease-time");
2671 break;
2672
2673 case expr_dns_transaction:
2674 col = token_print_indent (file, col, indent, "", "",
2675 "ns-update");
2676 col = token_print_indent (file, col, indent, " ", "",
2677 "(");
2678 scol = 0;
2679 for (e = expr;
2680 e && e -> op == expr_dns_transaction;
2681 e = e -> data.dns_transaction.cdr) {
2682 if (!scol) {
2683 scol = col;
2684 firstp = 1;
2685 } else
2686 firstp = 0;
2687 col = write_expression (file,
2688 e -> data.dns_transaction.car,
2689 col, scol, firstp);
2690 if (e -> data.dns_transaction.cdr)
2691 col = token_print_indent (file, col, scol,
2692 "", " ", ",");
2693 }
2694 if (e)
2695 col = write_expression (file, e, col, scol, 0);
2696 col = token_print_indent (file, col, indent, "", "", ")");
2697 break;
2698
2699 case expr_ns_add:
2700 col = token_print_indent (file, col, indent, "", "",
2701 "update");
2702 col = token_print_indent (file, col, indent, " ", "",
2703 "(");
2704 scol = col;
2705 sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
2706 col = token_print_indent (file, col, scol, "", "", obuf);
2707 col = token_print_indent (file, col, scol, "", " ",
2708 ",");
2709 sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
2710 col = token_print_indent (file, col, scol, "", "", obuf);
2711 col = token_print_indent (file, col, scol, "", " ",
2712 ",");
2713 col = write_expression (file, expr -> data.ns_add.rrname,
2714 col, scol, 0);
2715 col = token_print_indent (file, col, scol, "", " ",
2716 ",");
2717 col = write_expression (file, expr -> data.ns_add.rrdata,
2718 col, scol, 0);
2719 col = token_print_indent (file, col, scol, "", " ",
2720 ",");
2721 col = write_expression (file, expr -> data.ns_add.ttl,
2722 col, scol, 0);
2723 col = token_print_indent (file, col, indent, "", "",
2724 ")");
2725 break;
2726
2727 case expr_ns_delete:
2728 col = token_print_indent (file, col, indent, "", "",
2729 "delete");
2730 col = token_print_indent (file, col, indent, " ", "",
2731 "(");
2732 finish_ns_small:
2733 scol = col;
2734 sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
2735 col = token_print_indent (file, col, scol, "", "", obuf);
2736 col = token_print_indent (file, col, scol, "", " ",
2737 ",");
2738 sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
2739 col = token_print_indent (file, col, scol, "", "", obuf);
2740 col = token_print_indent (file, col, scol, "", " ",
2741 ",");
2742 col = write_expression (file, expr -> data.ns_add.rrname,
2743 col, scol, 0);
2744 col = token_print_indent (file, col, scol, "", " ",
2745 ",");
2746 col = write_expression (file, expr -> data.ns_add.rrdata,
2747 col, scol, 0);
2748 col = token_print_indent (file, col, indent, "", "",
2749 ")");
2750 break;
2751
2752 case expr_ns_exists:
2753 col = token_print_indent (file, col, indent, "", "",
2754 "exists");
2755 col = token_print_indent (file, col, indent, " ", "",
2756 "(");
2757 goto finish_ns_small;
2758
2759 case expr_ns_not_exists:
2760 col = token_print_indent (file, col, indent, "", "",
2761 "not exists");
2762 col = token_print_indent (file, col, indent, " ", "",
2763 "(");
2764 goto finish_ns_small;
2765
2766 case expr_static:
2767 col = token_print_indent (file, col, indent, "", "",
2768 "static");
2769 break;
2770
2771 case expr_null:
2772 col = token_print_indent (file, col, indent, "", "", "null");
2773 break;
2774
2775 case expr_variable_reference:
2776 col = token_print_indent (file, indent, indent, "", "",
2777 expr -> data.variable);
2778 break;
2779
2780 case expr_variable_exists:
2781 col = token_print_indent (file, indent, indent, "", "",
2782 "defined");
2783 col = token_print_indent (file, col, indent, " ", "", "(");
2784 col = token_print_indent (file, col, indent, "", "",
2785 expr -> data.variable);
2786 col = token_print_indent (file, col, indent, "", "", ")");
2787 break;
2788
2789 default:
2790 log_fatal ("invalid expression type in print_expression: %d",
2791 expr -> op);
2792 }
2793 return col;
2794 }
2795
2796 struct binding *find_binding (struct binding_scope *scope, const char *name)
2797 {
2798 struct binding *bp;
2799 struct binding_scope *s;
2800
2801 for (s = scope; s; s = s -> outer) {
2802 for (bp = s -> bindings; bp; bp = bp -> next) {
2803 if (!strcasecmp (name, bp -> name)) {
2804 return bp;
2805 }
2806 }
2807 }
2808 return (struct binding *)0;
2809 }
2810
2811 int free_bindings (struct binding_scope *scope, const char *file, int line)
2812 {
2813 struct binding *bp, *next;
2814
2815 for (bp = scope -> bindings; bp; bp = next) {
2816 next = bp -> next;
2817 if (bp -> name)
2818 dfree (bp -> name, file, line);
2819 if (bp -> value.data)
2820 data_string_forget (&bp -> value, file, line);
2821 dfree (bp, file, line);
2822 }
2823 scope -> bindings = (struct binding *)0;
2824 return 1;
2825 }
2826
2827 int binding_scope_dereference (ptr, file, line)
2828 struct binding_scope **ptr;
2829 const char *file;
2830 int line;
2831 {
2832 struct binding_scope *bp;
2833
2834 if (!ptr || !*ptr) {
2835 log_error ("%s(%d): null pointer", file, line);
2836 #if defined (POINTER_DEBUG)
2837 abort ();
2838 #else
2839 return 0;
2840 #endif
2841 }
2842
2843 if ((*ptr) -> bindings)
2844 free_bindings (*ptr, file, line);
2845 dfree ((*ptr), file, line);
2846 *ptr = (struct binding_scope *)0;
2847 return 1;
2848 }
2849
2850 /* vim: set tabstop=8: */