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