]> git.ipfire.org Git - thirdparty/dhcp.git/blob - common/tree.c
Update license.
[thirdparty/dhcp.git] / common / tree.c
1 /* tree.c
2
3 Routines for manipulating parse trees... */
4
5 /*
6 * Copyright (c) 1996-1999 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.23 1999/03/16 05:50:37 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
30 static int do_host_lookup PROTO ((struct data_string *,
31 struct dns_host_entry *));
32
33 pair cons (car, cdr)
34 caddr_t car;
35 pair cdr;
36 {
37 pair foo = (pair)dmalloc (sizeof *foo, "cons");
38 if (!foo)
39 log_fatal ("no memory for cons.");
40 foo -> car = car;
41 foo -> cdr = cdr;
42 return foo;
43 }
44
45 int make_const_option_cache (oc, buffer, data, len, option, name)
46 struct option_cache **oc;
47 struct buffer **buffer;
48 u_int8_t *data;
49 int len;
50 struct option *option;
51 char *name;
52 {
53 struct buffer *bp;
54
55 if (buffer) {
56 bp = *buffer;
57 *buffer = 0;
58 } else {
59 bp = (struct buffer *)0;
60 if (!buffer_allocate (&bp, len, name)) {
61 log_error ("%s: can't allocate buffer.", name);
62 return 0;
63 }
64 }
65
66 if (!option_cache_allocate (oc, name)) {
67 log_error ("%s: can't allocate option cache.");
68 buffer_dereference (&bp, name);
69 return 0;
70 }
71
72 (*oc) -> data.len = len;
73 (*oc) -> data.data = &bp -> data [0];
74 (*oc) -> data.terminated = 0;
75 if (data)
76 memcpy ((*oc) -> data.data, data, len);
77 (*oc) -> option = option;
78 return 1;
79 }
80
81 int make_host_lookup (expr, name)
82 struct expression **expr;
83 char *name;
84 {
85 if (!expression_allocate (expr, "make_host_lookup")) {
86 log_error ("No memory for host lookup tree node.");
87 return 0;
88 }
89 (*expr) -> op = expr_host_lookup;
90 if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) {
91 expression_dereference (expr, "make_host_lookup");
92 return 0;
93 }
94 return 1;
95 }
96
97 int enter_dns_host (dh, name)
98 struct dns_host_entry **dh;
99 char *name;
100 {
101 /* XXX This should really keep a hash table of hostnames
102 XXX and just add a new reference to a hostname that
103 XXX already exists, if possible, rather than creating
104 XXX a new structure. */
105 if (!dns_host_entry_allocate (dh, name, "enter_dns_host")) {
106 log_error ("Can't allocate space for new host.");
107 return 0;
108 }
109 return 1;
110 }
111
112 int make_const_data (expr, data, len, terminated, allocate)
113 struct expression **expr;
114 unsigned char *data;
115 int len;
116 int terminated;
117 int allocate;
118 {
119 struct expression *nt;
120
121 if (!expression_allocate (expr, "make_host_lookup")) {
122 log_error ("No memory for make_const_data tree node.");
123 return 0;
124 }
125 nt = *expr;
126
127 if (len) {
128 if (allocate) {
129 if (!buffer_allocate (&nt -> data.const_data.buffer,
130 len + terminated,
131 "make_const_data")) {
132 log_error ("Can't allocate const_data buffer.");
133 expression_dereference (expr,
134 "make_const_data");
135 return 0;
136 }
137 nt -> data.const_data.data =
138 &nt -> data.const_data.buffer -> data [0];
139 memcpy (nt -> data.const_data.data,
140 data, len + terminated);
141 } else
142 nt -> data.const_data.data = data;
143 nt -> data.const_data.terminated = terminated;
144 } else
145 nt -> data.const_data.data = 0;
146
147 nt -> op = expr_const_data;
148 nt -> data.const_data.len = len;
149 return 1;
150 }
151
152 int make_concat (expr, left, right)
153 struct expression **expr;
154 struct expression *left, *right;
155 {
156 /* If we're concatenating a null tree to a non-null tree, just
157 return the non-null tree; if both trees are null, return
158 a null tree. */
159 if (!left) {
160 if (!right)
161 return 0;
162 expression_reference (expr, right, "make_concat");
163 return 1;
164 }
165 if (!right) {
166 expression_reference (expr, left, "make_concat");
167 return 1;
168 }
169
170 /* Otherwise, allocate a new node to concatenate the two. */
171 if (!expression_allocate (expr, "make_concat")) {
172 log_error ("No memory for concatenation expression node.");
173 return 0;
174 }
175
176 (*expr) -> op = expr_concat;
177 expression_reference (&(*expr) -> data.concat [0],
178 left, "make_concat");
179 expression_reference (&(*expr) -> data.concat [1],
180 right, "make_concat");
181 return 1;
182 }
183
184 int make_substring (new, expr, offset, length)
185 struct expression **new;
186 struct expression *expr;
187 struct expression *offset;
188 struct expression *length;
189 {
190 /* Allocate an expression node to compute the substring. */
191 if (!expression_allocate (new, "make_substring")) {
192 log_error ("no memory for substring expression.");
193 return 0;
194 }
195 (*new) -> op = expr_substring;
196 expression_reference (&(*new) -> data.substring.expr,
197 expr, "make_concat");
198 expression_reference (&(*new) -> data.substring.offset,
199 offset, "make_concat");
200 expression_reference (&(*new) -> data.substring.len,
201 length, "make_concat");
202 return 1;
203 }
204
205 int make_limit (new, expr, limit)
206 struct expression **new;
207 struct expression *expr;
208 int limit;
209 {
210 struct expression *rv;
211
212 /* Allocate a node to enforce a limit on evaluation. */
213 if (!expression_allocate (new, "make_limit"))
214 log_error ("no memory for limit expression");
215 (*new) -> op = expr_substring;
216 expression_reference (&(*new) -> data.substring.expr,
217 expr, "make_limit");
218
219 /* Offset is a constant 0. */
220 if (!expression_allocate (&(*new) -> data.substring.offset,
221 "make_limit")) {
222 log_error ("no memory for limit offset expression");
223 expression_dereference (new, "make_limit");
224 return 0;
225 }
226 (*new) -> data.substring.offset -> op = expr_const_int;
227 (*new) -> data.substring.offset -> data.const_int = 0;
228
229 /* Length is a constant: the specified limit. */
230 if (!expression_allocate (&(*new) -> data.substring.len,
231 "make_limit")) {
232 log_error ("no memory for limit length expression");
233 expression_dereference (new, "make_limit");
234 return 0;
235 }
236 (*new) -> data.substring.len -> op = expr_const_int;
237 (*new) -> data.substring.len -> data.const_int = limit;
238
239 return 1;
240 }
241
242 int option_cache (oc, dp, expr, option)
243 struct option_cache **oc;
244 struct data_string *dp;
245 struct expression *expr;
246 struct option *option;
247 {
248 if (!option_cache_allocate (oc, "option_cache"))
249 return 0;
250 if (dp)
251 data_string_copy (&(*oc) -> data, dp, "option_cache");
252 if (expr)
253 expression_reference (&(*oc) -> expression,
254 expr, "option_cache");
255 (*oc) -> option = option;
256 return 1;
257 }
258
259 int do_host_lookup (result, dns)
260 struct data_string *result;
261 struct dns_host_entry *dns;
262 {
263 struct hostent *h;
264 int i, count;
265 int new_len;
266
267 #ifdef DEBUG_EVAL
268 log_debug ("time: now = %d dns = %d %d diff = %d",
269 cur_time, dns -> timeout, cur_time - dns -> timeout);
270 #endif
271
272 /* If the record hasn't timed out, just copy the data and return. */
273 if (cur_time <= dns -> timeout) {
274 #ifdef DEBUG_EVAL
275 log_debug ("easy copy: %d %s",
276 dns -> data.len,
277 (dns -> data.len > 4
278 ? inet_ntoa (*(struct in_addr *)(dns -> data.data))
279 : 0));
280 #endif
281 data_string_copy (result, &dns -> data, "do_host_lookup");
282 return 1;
283 }
284 #ifdef DEBUG_EVAL
285 log_debug ("Looking up %s", dns -> hostname);
286 #endif
287
288 /* Otherwise, look it up... */
289 h = gethostbyname (dns -> hostname);
290 if (!h) {
291 #ifndef NO_H_ERRNO
292 switch (h_errno) {
293 case HOST_NOT_FOUND:
294 #endif
295 log_error ("%s: host unknown.", dns -> hostname);
296 #ifndef NO_H_ERRNO
297 break;
298 case TRY_AGAIN:
299 log_error ("%s: temporary name server failure",
300 dns -> hostname);
301 break;
302 case NO_RECOVERY:
303 log_error ("%s: name server failed", dns -> hostname);
304 break;
305 case NO_DATA:
306 log_error ("%s: no A record associated with address",
307 dns -> hostname);
308 }
309 #endif /* !NO_H_ERRNO */
310
311 /* Okay to try again after a minute. */
312 dns -> timeout = cur_time + 60;
313 data_string_forget (&dns -> data, "do_host_lookup");
314 return 0;
315 }
316
317 #ifdef DEBUG_EVAL
318 log_debug ("Lookup succeeded; first address is %s",
319 inet_ntoa (h -> h_addr_list [0]));
320 #endif
321
322 /* Count the number of addresses we got... */
323 for (count = 0; h -> h_addr_list [count]; count++)
324 ;
325
326 /* Dereference the old data, if any. */
327 data_string_forget (&dns -> data, "do_host_lookup");
328
329 /* Do we need to allocate more memory? */
330 new_len = count * h -> h_length;
331 if (!buffer_allocate (&dns -> data.buffer, new_len, "do_host_lookup"))
332 {
333 log_error ("No memory for %s.", dns -> hostname);
334 return 0;
335 }
336
337 dns -> data.data = &dns -> data.buffer -> data [0];
338 dns -> data.len = new_len;
339 dns -> data.terminated = 0;
340
341 /* Addresses are conveniently stored one to the buffer, so we
342 have to copy them out one at a time... :'( */
343 for (i = 0; i < count; i++) {
344 memcpy (&dns -> data.data [h -> h_length * i],
345 h -> h_addr_list [i], h -> h_length);
346 }
347 #ifdef DEBUG_EVAL
348 log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
349 *(int *)(dns -> buffer), h -> h_addr_list [0]);
350 #endif
351
352 /* XXX Set the timeout for an hour from now.
353 XXX This should really use the time on the DNS reply. */
354 dns -> timeout = cur_time + 3600;
355
356 #ifdef DEBUG_EVAL
357 log_debug ("hard copy: %d %s", dns -> data.len,
358 (dns -> data.len > 4
359 ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));
360 #endif
361 data_string_copy (result, &dns -> data, "do_host_lookup");
362 return 1;
363 }
364
365 int evaluate_boolean_expression (result, packet, options, expr)
366 int *result;
367 struct packet *packet;
368 struct option_state *options;
369 struct expression *expr;
370 {
371 struct data_string left, right;
372 int bleft, bright;
373 int sleft, sright;
374
375 switch (expr -> op) {
376 case expr_check:
377 *result = check_collection (packet, expr -> data.check);
378 #if defined (DEBUG_EXPRESSIONS)
379 log_info ("bool: check (%s) returns %s",
380 expr -> data.check -> name, *result ? "true" : "false");
381 #endif
382 return 1;
383
384 case expr_equal:
385 memset (&left, 0, sizeof left);
386 sleft = evaluate_data_expression (&left, packet, options,
387 expr -> data.equal [0]);
388 memset (&right, 0, sizeof right);
389 sright = evaluate_data_expression (&right, packet, options,
390 expr -> data.equal [1]);
391 if (sleft && sright) {
392 if (left.len == right.len &&
393 !memcmp (left.data, right.data, left.len))
394 *result = 1;
395 else
396 *result = 0;
397 }
398
399 #if defined (DEBUG_EXPRESSIONS)
400 log_info ("bool: equal (%s, %s) = %s",
401 sleft ? print_hex_1 (left.len, left.data, 30) : "NULL",
402 sright ? print_hex_2 (right.len,
403 right.data, 30) : "NULL",
404 ((sleft && sright)
405 ? (*result ? "true" : "false")
406 : "NULL"));
407 #endif
408 if (sleft)
409 data_string_forget (&left,
410 "evaluate_boolean_expression");
411 if (sright)
412 data_string_forget (&right,
413 "evaluate_boolean_expression");
414 return sleft && sright;
415
416 case expr_and:
417 sleft = evaluate_boolean_expression (&bleft, packet, options,
418 expr -> data.and [0]);
419 sright = evaluate_boolean_expression (&bright, packet, options,
420 expr -> data.and [1]);
421
422 #if defined (DEBUG_EXPRESSIONS)
423 log_info ("bool: and (%s, %s) = %s",
424 sleft ? (bleft ? "true" : "false") : "NULL",
425 sright ? (bright ? "true" : "false") : "NULL",
426 ((sleft && sright)
427 ? (bleft && bright ? "true" : "false") : "NULL"));
428 #endif
429 if (sleft && sright) {
430 *result = bleft && bright;
431 return 1;
432 }
433 return 0;
434
435 case expr_or:
436 sleft = evaluate_boolean_expression (&bleft, packet, options,
437 expr -> data.or [0]);
438 sright = evaluate_boolean_expression (&bright, packet, options,
439 expr -> data.or [1]);
440 #if defined (DEBUG_EXPRESSIONS)
441 log_info ("bool: or (%s, %s) = %s",
442 sleft ? (bleft ? "true" : "false") : "NULL",
443 sright ? (bright ? "true" : "false") : "NULL",
444 ((sleft && sright)
445 ? (bleft || bright ? "true" : "false") : "NULL"));
446 #endif
447 if (sleft && sright) {
448 *result = bleft || bright;
449 return 1;
450 }
451 return 0;
452
453 case expr_not:
454 sleft = evaluate_boolean_expression (&bleft, packet, options,
455 expr -> data.not);
456 #if defined (DEBUG_EXPRESSIONS)
457 log_info ("bool: not (%s) = %s",
458 sleft ? (bleft ? "true" : "false") : "NULL",
459 ((sleft && sright)
460 ? (!bleft ? "true" : "false") : "NULL"));
461
462 #endif
463 if (sleft) {
464 *result = !bleft;
465 return 1;
466 }
467 return 0;
468
469 case expr_exists:
470 memset (&left, 0, sizeof left);
471 if (!((*expr -> data.option -> universe -> lookup_func)
472 (&left, options, expr -> data.exists -> code)))
473 *result = 0;
474 else {
475 *result = 1;
476 data_string_forget (&left,
477 "evaluate_boolean_expression");
478 }
479 #if defined (DEBUG_EXPRESSIONS)
480 log_info ("data: exists %s.%s = %s",
481 expr -> data.option -> universe -> name,
482 expr -> data.option -> name, *result ? "true" : "false");
483 #endif
484 return 1;
485
486 case expr_substring:
487 case expr_suffix:
488 case expr_option:
489 case expr_hardware:
490 case expr_const_data:
491 case expr_packet:
492 case expr_concat:
493 case expr_host_lookup:
494 log_error ("Data opcode in evaluate_boolean_expression: %d",
495 expr -> op);
496 return 0;
497
498 case expr_extract_int8:
499 case expr_extract_int16:
500 case expr_extract_int32:
501 case expr_const_int:
502 log_error ("Numeric opcode in evaluate_boolean_expression: %d",
503 expr -> op);
504 return 0;
505 }
506
507 log_error ("Bogus opcode in evaluate_boolean_expression: %d", expr -> op);
508 return 0;
509 }
510
511 int evaluate_data_expression (result, packet, options, expr)
512 struct data_string *result;
513 struct packet *packet;
514 struct option_state *options;
515 struct expression *expr;
516 {
517 struct data_string data, other;
518 unsigned long offset, len;
519 int s0, s1, s2, s3;
520
521 switch (expr -> op) {
522 /* Extract N bytes starting at byte M of a data string. */
523 case expr_substring:
524 memset (&data, 0, sizeof data);
525 s0 = evaluate_data_expression (&data, packet, options,
526 expr -> data.substring.expr);
527
528 /* Evaluate the offset and length. */
529 s1 = evaluate_numeric_expression
530 (&offset,
531 packet, options, expr -> data.substring.offset);
532 s2 = evaluate_numeric_expression (&len, packet, options,
533 expr -> data.substring.len);
534
535 if (s0 && s1 && s2) {
536 /* If the offset is after end of the string,
537 return an empty string. Otherwise, do the
538 adjustments and return what's left. */
539 if (data.len > offset) {
540 data_string_copy (result, &data,
541 "evaluate_data_expression");
542 result -> len -= offset;
543 if (result -> len > len) {
544 result -> len = len;
545 result -> terminated = 0;
546 }
547 result -> data += offset;
548 }
549 s3 = 1;
550 } else
551 s3 = 0;
552
553 #if defined (DEBUG_EXPRESSIONS)
554 log_info ("data: substring (%s, %s, %s) = %s",
555 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
556 s1 ? print_dec_1 (offset) : "NULL",
557 s2 ? print_dec_2 (len) : "NULL",
558 (s3 ? print_hex_2 (result -> len, result -> data, 30)
559 : "NULL"));
560 #endif
561 if (s3)
562 return 1;
563 data_string_forget (&data, "evaluate_data_expression");
564 return 0;
565
566
567 /* Extract the last N bytes of a data string. */
568 case expr_suffix:
569 memset (&data, 0, sizeof data);
570 s0 = evaluate_data_expression (&data, packet, options,
571 expr -> data.suffix.expr);
572 /* Evaluate the length. */
573 s1 = evaluate_numeric_expression (&len, packet, options,
574 expr -> data.substring.len);
575 if (s0 && s1) {
576 data_string_copy (result, &data,
577 "evaluate_data_expression");
578
579 /* If we are returning the last N bytes of a
580 string whose length is <= N, just return
581 the string - otherwise, compute a new
582 starting address and decrease the
583 length. */
584 if (data.len > len) {
585 result -> data += data.len - len;
586 result -> len = len;
587 }
588 }
589
590 #if defined (DEBUG_EXPRESSIONS)
591 log_info ("data: suffix (%s, %d) = %s",
592 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
593 s1 ? print_dec_1 (len) : "NULL",
594 ((s0 && s1)
595 ? print_hex_2 (result -> len, result -> data, 30)
596 : NULL));
597 #endif
598 return 1;
599
600 /* Extract an option. */
601 case expr_option:
602 s0 = ((*expr -> data.option -> universe -> lookup_func)
603 (result, &packet -> options,
604 expr -> data.option -> code));
605 #if defined (DEBUG_EXPRESSIONS)
606 log_info ("data: option %s.%s = %s",
607 expr -> data.option -> universe -> name,
608 expr -> data.option -> name,
609 s0 ? print_hex_1 (result -> len, result -> data, 60)
610 : "NULL");
611 #endif
612 return s0;
613
614 /* Combine the hardware type and address. */
615 case expr_hardware:
616 if (!packet || !packet -> raw) {
617 log_error ("data: hardware: raw packet not available");
618 return 0;
619 }
620 if (packet -> raw -> hlen > sizeof packet -> raw -> chaddr) {
621 log_error ("data: hardware: invalid hlen (%d)\n",
622 packet -> raw -> hlen);
623 return 0;
624 }
625 result -> len = packet -> raw -> hlen + 1;
626 if (buffer_allocate (&result -> buffer, result -> len,
627 "evaluate_data_expression")) {
628 result -> data = &result -> buffer -> data [0];
629 result -> data [0] = packet -> raw -> htype;
630 memcpy (&result -> data [1], packet -> raw -> chaddr,
631 packet -> raw -> hlen);
632 result -> terminated = 0;
633 } else {
634 log_error ("data: hardware: no memory for buffer.");
635 return 0;
636 }
637 #if defined (DEBUG_EXPRESSIONS)
638 log_info ("data: hardware = %s",
639 print_hex_1 (result -> len, result -> data, 60));
640 #endif
641 return 1;
642
643 /* Extract part of the raw packet. */
644 case expr_packet:
645 if (!packet || !packet -> raw) {
646 log_error ("data: packet: raw packet not available");
647 return 0;
648 }
649
650 s0 = evaluate_numeric_expression (&len, packet, options,
651 expr -> data.packet.len);
652 s1 = evaluate_numeric_expression (&offset, packet, options,
653 expr -> data.packet.len);
654 if (s0 && s1 && offset < packet -> packet_length) {
655 if (offset + len > packet -> packet_length)
656 result -> len =
657 packet -> packet_length - offset;
658 else
659 result -> len = len;
660 if (buffer_allocate (&result -> buffer, result -> len,
661 "evaluate_data_expression")) {
662 result -> data = &result -> buffer -> data [0];
663 memcpy (result -> data,
664 (((unsigned char *)(packet -> raw))
665 + offset), result -> len);
666 result -> terminated = 0;
667 } else {
668 log_error ("data: packet: no memory for buffer.");
669 return 0;
670 }
671 s2 = 1;
672 } else
673 s2 = 0;
674 #if defined (DEBUG_EXPRESSIONS)
675 log_info ("data: packet (%d, %d) = %s",
676 offset, len,
677 s2 ? print_hex_1 (result -> len,
678 result -> data, 60) : NULL);
679 #endif
680 return s2;
681
682 /* Some constant data... */
683 case expr_const_data:
684 #if defined (DEBUG_EXPRESSIONS)
685 log_info ("data: const = %s",
686 print_hex_1 (expr -> data.const_data.len,
687 expr -> data.const_data.data, 60));
688 #endif
689 data_string_copy (result,
690 &expr -> data.const_data,
691 "evaluate_data_expression");
692 return 1;
693
694 /* Hostname lookup... */
695 case expr_host_lookup:
696 s0 = do_host_lookup (result, expr -> data.host_lookup);
697 #if defined (DEBUG_EXPRESSIONS)
698 log_info ("data: DNS lookup (%s) = %s",
699 expr -> data.host_lookup -> hostname,
700 (s0
701 ? print_dotted_quads (result -> len, result -> data)
702 : "NULL"));
703 #endif
704 return s0;
705
706 /* Concatenation... */
707 case expr_concat:
708 memset (&data, 0, sizeof data);
709 s0 = evaluate_data_expression (&data, packet, options,
710 expr -> data.concat [0]);
711 memset (&other, 0, sizeof other);
712 s1 = evaluate_data_expression (&other, packet, options,
713 expr -> data.concat [1]);
714
715 if (s0 && s1) {
716 result -> len = data.len + other.len;
717 if (!buffer_allocate (&result -> buffer,
718 (result -> len +
719 other.terminated),
720 "expr_concat")) {
721 log_error ("data: concat: no memory");
722 result -> len = 0;
723 data_string_forget (&data, "expr_concat");
724 data_string_forget (&other, "expr_concat");
725 return 0;
726 }
727 result -> data = &result -> buffer -> data [0];
728 memcpy (result -> data, data.data, data.len);
729 memcpy (&result -> data [data.len],
730 other.data, other.len + other.terminated);
731 } else if (s0)
732 data_string_copy (result, &data, "expr_concat");
733 else if (s1)
734 data_string_copy (result, &other, "expr_concat");
735 #if defined (DEBUG_EXPRESSIONS)
736 log_info ("data: concat (%s, %s) = %s",
737 s0 ? print_hex_1 (data.len, data.data, 20) : "NULL",
738 s1 ? print_hex_2 (other.len, other.data, 20) : "NULL",
739 ((s0 || s1)
740 ? print_hex_3 (result -> len, result -> data, 30)
741 : "NULL"));
742 #endif
743 return s0 || s1;
744
745 case expr_check:
746 case expr_equal:
747 case expr_and:
748 case expr_or:
749 case expr_not:
750 case expr_match:
751 log_error ("Boolean opcode in evaluate_data_expression: %d",
752 expr -> op);
753 return 0;
754
755 case expr_extract_int8:
756 case expr_extract_int16:
757 case expr_extract_int32:
758 case expr_const_int:
759 log_error ("Numeric opcode in evaluate_data_expression: %d",
760 expr -> op);
761 return 0;
762 }
763
764 log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op);
765 return 0;
766 }
767
768 int evaluate_numeric_expression (result, packet, options, expr)
769 unsigned long *result;
770 struct packet *packet;
771 struct option_state *options;
772 struct expression *expr;
773 {
774 struct data_string data;
775 int status;
776
777 switch (expr -> op) {
778 case expr_check:
779 case expr_equal:
780 case expr_and:
781 case expr_or:
782 case expr_not:
783 case expr_match:
784 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
785 expr -> op);
786 return 0;
787
788 case expr_substring:
789 case expr_suffix:
790 case expr_option:
791 case expr_hardware:
792 case expr_const_data:
793 case expr_packet:
794 case expr_concat:
795 case expr_host_lookup:
796 log_error ("Data opcode in evaluate_numeric_expression: %d",
797 expr -> op);
798 return 0;
799
800 case expr_extract_int8:
801 memset (&data, 0, sizeof data);
802 status = evaluate_data_expression
803 (&data, packet,
804 options, expr -> data.extract_int);
805 if (status)
806 *result = data.data [0];
807 #if defined (DEBUG_EXPRESSIONS)
808 log_info ("num: extract_int8 (%s) = %s",
809 status ? print_hex_1 (data.len, data.data, 60) : "NULL",
810 status ? print_dec_1 (*result) : "NULL" );
811 #endif
812 if (status)
813 data_string_forget (&data, "expr_extract_int8");
814 return status;
815
816 case expr_extract_int16:
817 memset (&data, 0, sizeof data);
818 status = (evaluate_data_expression
819 (&data, packet, options,
820 expr -> data.extract_int));
821 if (status && data.len >= 2)
822 *result = getUShort (data.data);
823 #if defined (DEBUG_EXPRESSIONS)
824 log_info ("num: extract_int16 (%s) = %ld",
825 ((status && data.len >= 2) ?
826 print_hex_1 (data.len, data.data, 60) : "NULL"),
827 *result);
828 #endif
829 if (status)
830 data_string_forget (&data, "expr_extract_int16");
831 return (status && data.len >= 2);
832
833 case expr_extract_int32:
834 memset (&data, 0, sizeof data);
835 status = (evaluate_data_expression
836 (&data, packet, options,
837 expr -> data.extract_int));
838 if (status && data.len >= 4)
839 *result = getULong (data.data);
840 #if defined (DEBUG_EXPRESSIONS)
841 log_info ("num: extract_int32 (%s) = %ld",
842 ((status && data.len >= 4) ?
843 print_hex_1 (data.len, data.data, 60) : "NULL"),
844 *result);
845 #endif
846 if (status)
847 data_string_forget (&data, "expr_extract_int32");
848 return (status && data.len >= 4);
849
850 case expr_const_int:
851 *result = expr -> data.const_int;
852 return 1;
853 }
854
855 log_error ("Bogus opcode in evaluate_numeric_expression: %d", expr -> op);
856 return 0;
857 }
858
859 /* Return data hanging off of an option cache structure, or if there
860 isn't any, evaluate the expression hanging off of it and return the
861 result of that evaluation. There should never be both an expression
862 and a valid data_string. */
863
864 int evaluate_option_cache (result, packet, options, oc)
865 struct data_string *result;
866 struct packet *packet;
867 struct option_state *options;
868 struct option_cache *oc;
869 {
870 if (oc -> data.len) {
871 data_string_copy (result,
872 &oc -> data, "evaluate_option_cache");
873 return 1;
874 }
875 if (!oc -> expression)
876 return 0;
877 return evaluate_data_expression (result,
878 packet, options, oc -> expression);
879 }
880
881 /* Evaluate an option cache and extract a boolean from the result,
882 returning the boolean. Return false if there is no data. */
883
884 int evaluate_boolean_option_cache (packet, options, oc)
885 struct packet *packet;
886 struct option_state *options;
887 struct option_cache *oc;
888 {
889 struct data_string ds;
890 int result;
891
892 /* So that we can be called with option_lookup as an argument. */
893 if (!oc)
894 return 0;
895
896 memset (&ds, 0, sizeof ds);
897 if (!evaluate_option_cache (&ds, packet, options, oc))
898 return 0;
899
900 if (ds.len && ds.data [0])
901 result = 1;
902 else
903 result = 0;
904 data_string_forget (&ds, "evaluate_boolean_option_cache");
905 return result;
906 }
907
908
909 /* Evaluate a boolean expression and return the result of the evaluation,
910 or FALSE if it failed. */
911
912 int evaluate_boolean_expression_result (packet, options, expr)
913 struct packet *packet;
914 struct option_state *options;
915 struct expression *expr;
916 {
917 int result;
918
919 /* So that we can be called with option_lookup as an argument. */
920 if (!expr)
921 return 0;
922
923 if (!evaluate_boolean_expression (&result, packet, options, expr))
924 return 0;
925
926 return result;
927 }
928
929
930 /* Dereference an expression node, and if the reference count goes to zero,
931 dereference any data it refers to, and then free it. */
932 void expression_dereference (eptr, name)
933 struct expression **eptr;
934 char *name;
935 {
936 struct expression *expr = *eptr;
937
938 /* Zero the pointer. */
939 *eptr = (struct expression *)0;
940
941 /* Decrement the reference count. If it's nonzero, we're
942 done. */
943 if (--(expr -> refcnt) > 0)
944 return;
945 if (expr -> refcnt < 0) {
946 log_error ("expression_dereference: negative refcnt!");
947 abort ();
948 }
949
950 /* Dereference subexpressions. */
951 switch (expr -> op) {
952 /* All the binary operators can be handled the same way. */
953 case expr_equal:
954 case expr_concat:
955 case expr_and:
956 case expr_or:
957 if (expr -> data.equal [0])
958 expression_dereference (&expr -> data.equal [0], name);
959 if (expr -> data.equal [1])
960 expression_dereference (&expr -> data.equal [1], name);
961 break;
962
963 case expr_substring:
964 if (expr -> data.substring.expr)
965 expression_dereference (&expr -> data.substring.expr,
966 name);
967 if (expr -> data.substring.offset)
968 expression_dereference (&expr -> data.substring.offset,
969 name);
970 if (expr -> data.substring.len)
971 expression_dereference (&expr -> data.substring.len,
972 name);
973 break;
974
975 case expr_suffix:
976 if (expr -> data.suffix.expr)
977 expression_dereference (&expr -> data.suffix.expr,
978 name);
979 if (expr -> data.suffix.len)
980 expression_dereference (&expr -> data.suffix.len,
981 name);
982 break;
983
984 case expr_not:
985 if (expr -> data.not)
986 expression_dereference (&expr -> data.not, name);
987 break;
988
989 case expr_packet:
990 if (expr -> data.packet.offset)
991 expression_dereference (&expr -> data.packet.offset,
992 name);
993 if (expr -> data.packet.len)
994 expression_dereference (&expr -> data.packet.len,
995 name);
996 break;
997
998 case expr_extract_int8:
999 case expr_extract_int16:
1000 case expr_extract_int32:
1001 if (expr -> data.extract_int)
1002 expression_dereference (&expr -> data.extract_int,
1003 name);
1004 break;
1005
1006 case expr_const_data:
1007 data_string_forget (&expr -> data.const_data, name);
1008 break;
1009
1010 case expr_host_lookup:
1011 if (expr -> data.host_lookup)
1012 dns_host_entry_dereference (&expr -> data.host_lookup,
1013 name);
1014 break;
1015
1016 /* No subexpressions. */
1017 case expr_const_int:
1018 case expr_check:
1019 case expr_option:
1020 case expr_hardware:
1021 case expr_exists:
1022 break;
1023
1024 default:
1025 break;
1026 }
1027
1028 free_expression (expr, "expression_dereference");
1029 }
1030
1031
1032 /* Free all of the state in an option state buffer. The buffer itself is
1033 not freed, since these buffers are always contained in other structures. */
1034
1035 void option_state_dereference (state)
1036 struct option_state *state;
1037 {
1038 int i;
1039 struct agent_options *a, *na;
1040 struct option_tag *ot, *not;
1041 pair cp, next;
1042
1043 /* Having done the cons_options(), we can release the tree_cache
1044 entries. */
1045 for (i = 0; i < OPTION_HASH_SIZE; i++) {
1046 for (cp = state -> dhcp_hash [i]; cp; cp = next) {
1047 next = cp -> cdr;
1048 option_cache_dereference
1049 ((struct option_cache **)&cp -> car,
1050 "option_state_dereference");
1051 free_pair (cp, "option_state_dereference");
1052 }
1053 for (cp = state -> server_hash [i]; cp; cp = next) {
1054 next = cp -> cdr;
1055 option_cache_dereference
1056 ((struct option_cache **)&cp -> car,
1057 "option_state_dereference");
1058 }
1059 }
1060
1061 /* We can also release the agent options, if any... */
1062 for (a = state -> agent_options; a; a = na) {
1063 na = a -> next;
1064 for (ot = a -> first; ot; ot = not) {
1065 not = ot -> next;
1066 free (ot);
1067 }
1068 }
1069 }
1070
1071 /* Make a copy of the data in data_string, upping the buffer reference
1072 count if there's a buffer. */
1073
1074 void data_string_copy (dest, src, name)
1075 struct data_string *dest;
1076 struct data_string *src;
1077 char *name;
1078 {
1079 if (src -> buffer)
1080 buffer_reference (&dest -> buffer, src -> buffer, name);
1081 dest -> data = src -> data;
1082 dest -> terminated = src -> terminated;
1083 dest -> len = src -> len;
1084 }
1085
1086 /* Release the reference count to a data string's buffer (if any) and
1087 zero out the other information, yielding the null data string. */
1088
1089 void data_string_forget (data, name)
1090 struct data_string *data;
1091 char *name;
1092 {
1093 if (data -> buffer)
1094 buffer_dereference (&data -> buffer, name);
1095 memset (data, 0, sizeof *data);
1096 }
1097
1098 /* Make a copy of the data in data_string, upping the buffer reference
1099 count if there's a buffer. */
1100
1101 void data_string_truncate (dp, len)
1102 struct data_string *dp;
1103 int len;
1104 {
1105 if (len < dp -> len) {
1106 dp -> terminated = 0;
1107 dp -> len = len;
1108 }
1109 }
1110
1111 int is_boolean_expression (expr)
1112 struct expression *expr;
1113 {
1114 return (expr -> op == expr_check ||
1115 expr -> op == expr_equal ||
1116 expr -> op == expr_and ||
1117 expr -> op == expr_or ||
1118 expr -> op == expr_not);
1119 }
1120
1121 int is_data_expression (expr)
1122 struct expression *expr;
1123 {
1124 return (expr -> op == expr_substring ||
1125 expr -> op == expr_suffix ||
1126 expr -> op == expr_option ||
1127 expr -> op == expr_hardware ||
1128 expr -> op == expr_const_data ||
1129 expr -> op == expr_packet ||
1130 expr -> op == expr_concat ||
1131 expr -> op == expr_host_lookup);
1132 }
1133
1134 int is_numeric_expression (expr)
1135 struct expression *expr;
1136 {
1137 return (expr -> op == expr_extract_int8 ||
1138 expr -> op == expr_extract_int16 ||
1139 expr -> op == expr_extract_int32 ||
1140 expr -> op == expr_const_int);
1141 }
1142
1143 static int op_val PROTO ((enum expr_op));
1144
1145 static int op_val (op)
1146 enum expr_op op;
1147 {
1148 switch (op) {
1149 case expr_none:
1150 case expr_match:
1151 case expr_check:
1152 case expr_substring:
1153 case expr_suffix:
1154 case expr_concat:
1155 case expr_host_lookup:
1156 case expr_not:
1157 case expr_option:
1158 case expr_hardware:
1159 case expr_packet:
1160 case expr_const_data:
1161 case expr_extract_int8:
1162 case expr_extract_int16:
1163 case expr_extract_int32:
1164 case expr_const_int:
1165 case expr_exists:
1166 return 100;
1167
1168 case expr_equal:
1169 return 3;
1170
1171 case expr_and:
1172 return 1;
1173
1174 case expr_or:
1175 return 2;
1176 }
1177 return 100;
1178 }
1179
1180 int op_precedence (op1, op2)
1181 enum expr_op op1, op2;
1182 {
1183 int ov1, ov2;
1184
1185 return op_val (op1) - op_val (op2);
1186 }
1187
1188 enum expression_context op_context (op)
1189 enum expr_op op;
1190 {
1191 switch (op) {
1192 case expr_none:
1193 case expr_match:
1194 case expr_check:
1195 case expr_substring:
1196 case expr_suffix:
1197 case expr_concat:
1198 case expr_host_lookup:
1199 case expr_not:
1200 case expr_option:
1201 case expr_hardware:
1202 case expr_packet:
1203 case expr_const_data:
1204 case expr_extract_int8:
1205 case expr_extract_int16:
1206 case expr_extract_int32:
1207 case expr_const_int:
1208 case expr_exists:
1209 return context_any;
1210
1211 case expr_equal:
1212 return context_data;
1213
1214 case expr_and:
1215 return context_boolean;
1216
1217 case expr_or:
1218 return context_boolean;
1219 }
1220 return context_any;
1221 }