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