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