1/* execute.c 2 3 Support for executable statements. */ 4 5/* 6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 7 * Copyright (c) 1998-2003 by Internet Software Consortium 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 * 21 * Internet Systems Consortium, Inc. 22 * 950 Charter Street 23 * Redwood City, CA 94063 24 * <info@isc.org> 25 * http://www.isc.org/ 26 * 27 * This software has been written for Internet Systems Consortium 28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. 29 * To learn more about Internet Systems Consortium, see 30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises, 31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see 32 * ``http://www.nominum.com''. 33 */ 34 35#ifndef lint 36static char copyright[] = 37"$Id: execute.c,v 1.7 2005/08/11 17:13:21 drochner Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; 38#endif /* not lint */ 39 40#include "dhcpd.h" 41#include <omapip/omapip_p.h> 42 43int execute_statements (result, packet, lease, client_state, 44 in_options, out_options, scope, statements) 45 struct binding_value **result; 46 struct packet *packet; 47 struct lease *lease; 48 struct client_state *client_state; 49 struct option_state *in_options; 50 struct option_state *out_options; 51 struct binding_scope **scope; 52 struct executable_statement *statements; 53{ 54 struct executable_statement *r, *e, *next; 55 int rc; 56 int status; 57 struct binding *binding; 58 struct data_string ds; 59 struct binding_scope *ns; 60 61 if (!statements) 62 return 1; 63 64 r = (struct executable_statement *)0; 65 next = (struct executable_statement *)0; 66 e = (struct executable_statement *)0; 67 executable_statement_reference (&r, statements, MDL); 68 while (r && !(result && *result)) { 69 if (r -> next) 70 executable_statement_reference (&next, r -> next, MDL); 71 switch (r -> op) { 72 case statements_statement: 73#if defined (DEBUG_EXPRESSIONS) 74 log_debug ("exec: statements"); 75#endif 76 status = execute_statements (result, packet, lease, 77 client_state, in_options, 78 out_options, scope, 79 r -> data.statements); 80#if defined (DEBUG_EXPRESSIONS) 81 log_debug ("exec: statements returns %d", status); 82#endif 83 if (!status) 84 return 0; 85 break; 86 87 case on_statement: 88 if (lease) { 89 if (r -> data.on.evtypes & ON_EXPIRY) { 90#if defined (DEBUG_EXPRESSIONS) 91 log_debug ("exec: on expiry"); 92#endif 93 if (lease -> on_expiry) 94 executable_statement_dereference 95 (&lease -> on_expiry, MDL); 96 if (r -> data.on.statements) 97 executable_statement_reference 98 (&lease -> on_expiry, 99 r -> data.on.statements, MDL); 100 } 101 if (r -> data.on.evtypes & ON_RELEASE) { 102#if defined (DEBUG_EXPRESSIONS) 103 log_debug ("exec: on release"); 104#endif 105 if (lease -> on_release) 106 executable_statement_dereference 107 (&lease -> on_release, MDL); 108 if (r -> data.on.statements) 109 executable_statement_reference 110 (&lease -> on_release, 111 r -> data.on.statements, MDL); 112 } 113 if (r -> data.on.evtypes & ON_COMMIT) { 114#if defined (DEBUG_EXPRESSIONS) 115 log_debug ("exec: on commit"); 116#endif 117 if (lease -> on_commit) 118 executable_statement_dereference 119 (&lease -> on_commit, MDL); 120 if (r -> data.on.statements) 121 executable_statement_reference 122 (&lease -> on_commit, 123 r -> data.on.statements, MDL); 124 } 125 } 126 break; 127 128 case switch_statement: 129#if defined (DEBUG_EXPRESSIONS) 130 log_debug ("exec: switch"); 131#endif 132 status = (find_matching_case 133 (&e, packet, lease, client_state, 134 in_options, out_options, scope, 135 r -> data.s_switch.expr, 136 r -> data.s_switch.statements)); 137#if defined (DEBUG_EXPRESSIONS) 138 log_debug ("exec: switch: case %lx", (unsigned long)e); 139#endif 140 if (status) { 141 if (!(execute_statements 142 (result, packet, lease, client_state, 143 in_options, out_options, scope, e))) { 144 executable_statement_dereference 145 (&e, MDL); 146 return 0; 147 } 148 executable_statement_dereference (&e, MDL); 149 } 150 break; 151 152 /* These have no effect when executed. */ 153 case case_statement: 154 case default_statement: 155 break; 156 157 case if_statement: 158 status = (evaluate_boolean_expression 159 (&rc, packet, 160 lease, client_state, in_options, 161 out_options, scope, r -> data.ie.expr)); 162 163#if defined (DEBUG_EXPRESSIONS) 164 log_debug ("exec: if %s", (status 165 ? (rc ? "true" : "false") 166 : "NULL")); 167#endif 168 /* XXX Treat NULL as false */ 169 if (!status) 170 rc = 0; 171 if (!execute_statements 172 (result, packet, lease, client_state, 173 in_options, out_options, scope, 174 rc ? r -> data.ie.tc : r -> data.ie.fc)) 175 return 0; 176 break; 177 178 case eval_statement: 179 status = evaluate_expression 180 ((struct binding_value **)0, 181 packet, lease, client_state, in_options, 182 out_options, scope, r -> data.eval, MDL); 183#if defined (DEBUG_EXPRESSIONS) 184 log_debug ("exec: evaluate: %s", 185 (status ? "succeeded" : "failed")); 186#endif 187 break; 188 189 case return_statement: 190 status = evaluate_expression 191 (result, packet, 192 lease, client_state, in_options, 193 out_options, scope, r -> data.retval, MDL); 194#if defined (DEBUG_EXPRESSIONS) 195 log_debug ("exec: return: %s", 196 (status ? "succeeded" : "failed")); 197#endif 198 break; 199 200 case add_statement: 201#if defined (DEBUG_EXPRESSIONS) 202 log_debug ("exec: add %s", (r -> data.add -> name 203 ? r -> data.add -> name 204 : "<unnamed class>")); 205#endif 206 classify (packet, r -> data.add); 207 break; 208 209 case break_statement: 210#if defined (DEBUG_EXPRESSIONS) 211 log_debug ("exec: break"); 212#endif 213 return 1; 214 215 case supersede_option_statement: 216 case send_option_statement: 217#if defined (DEBUG_EXPRESSIONS) 218 log_debug ("exec: %s option %s.%s", 219 (r -> op == supersede_option_statement 220 ? "supersede" : "send"), 221 r -> data.option -> option -> universe -> name, 222 r -> data.option -> option -> name); 223 goto option_statement; 224#endif 225 case default_option_statement: 226#if defined (DEBUG_EXPRESSIONS) 227 log_debug ("exec: default option %s.%s", 228 r -> data.option -> option -> universe -> name, 229 r -> data.option -> option -> name); 230 goto option_statement; 231#endif 232 case append_option_statement: 233#if defined (DEBUG_EXPRESSIONS) 234 log_debug ("exec: append option %s.%s", 235 r -> data.option -> option -> universe -> name, 236 r -> data.option -> option -> name); 237 goto option_statement; 238#endif 239 case prepend_option_statement: 240#if defined (DEBUG_EXPRESSIONS) 241 log_debug ("exec: prepend option %s.%s", 242 r -> data.option -> option -> universe -> name, 243 r -> data.option -> option -> name); 244 option_statement: 245#endif 246 set_option (r -> data.option -> option -> universe, 247 out_options, r -> data.option, r -> op); 248 break; 249 250 case set_statement: 251 case define_statement: 252 if (!scope) { 253 log_error ("set %s: no scope", 254 r -> data.set.name); 255 status = 0; 256 break; 257 } 258 if (!*scope) { 259 if (!binding_scope_allocate (scope, MDL)) { 260 log_error ("set %s: can't allocate scope", 261 r -> data.set.name); 262 status = 0; 263 break; 264 } 265 } 266 binding = find_binding (*scope, r -> data.set.name); 267#if defined (DEBUG_EXPRESSIONS) 268 log_debug ("exec: set %s", r -> data.set.name); 269#endif 270 if (!binding) { 271 binding = dmalloc (sizeof *binding, MDL); 272 if (binding) { 273 memset (binding, 0, sizeof *binding); 274 binding -> name = 275 dmalloc (strlen 276 (r -> data.set.name) + 1, 277 MDL); 278 if (binding -> name) { 279 strcpy (binding -> name, 280 r -> data.set.name); 281 binding -> next = (*scope) -> bindings; 282 (*scope) -> bindings = binding; 283 } else { 284 dfree (binding, MDL); 285 binding = (struct binding *)0; 286 } 287 } 288 } 289 if (binding) { 290 if (binding -> value) 291 binding_value_dereference 292 (&binding -> value, MDL); 293 if (r -> op == set_statement) { 294 status = (evaluate_expression 295 (&binding -> value, packet, 296 lease, client_state, 297 in_options, out_options, 298 scope, r -> data.set.expr, 299 MDL)); 300 } else { 301 if (!(binding_value_allocate 302 (&binding -> value, MDL))) { 303 dfree (binding, MDL); 304 binding = (struct binding *)0; 305 } 306 if (binding -> value) { 307 binding -> value -> type = 308 binding_function; 309 (fundef_reference 310 (&binding -> value -> value.fundef, 311 r -> data.set.expr -> data.func, 312 MDL)); 313 } 314 } 315 } 316#if defined (DEBUG_EXPRESSIONS) 317 log_debug ("exec: set %s%s", r -> data.set.name, 318 (binding && status ? "" : " (failed)")); 319#endif 320 break; 321 322 case unset_statement: 323 if (!scope || !*scope) { 324 status = 0; 325 break; 326 } 327 binding = find_binding (*scope, r -> data.unset); 328 if (binding) { 329 if (binding -> value) 330 binding_value_dereference 331 (&binding -> value, MDL); 332 status = 1; 333 } else 334 status = 0; 335#if defined (DEBUG_EXPRESSIONS) 336 log_debug ("exec: unset %s: %s", r -> data.unset, 337 (status ? "found" : "not found")); 338#endif 339 break; 340 341 case let_statement: 342#if defined (DEBUG_EXPRESSIONS) 343 log_debug ("exec: let %s", r -> data.let.name); 344#endif 345 ns = (struct binding_scope *)0; 346 binding = (struct binding *)0; 347 binding_scope_allocate (&ns, MDL); 348 e = r; 349 350 next_let: 351 if (ns) { 352 binding = dmalloc (sizeof *binding, MDL); 353 memset (binding, 0, sizeof *binding); 354 if (!binding) { 355 blb: 356 binding_scope_dereference (&ns, MDL); 357 } else { 358 binding -> name = 359 dmalloc (strlen 360 (e -> data.let.name + 1), 361 MDL); 362 if (binding -> name) 363 strcpy (binding -> name, 364 e -> data.let.name); 365 else { 366 dfree (binding, MDL); 367 binding = (struct binding *)0; 368 goto blb; 369 } 370 } 371 } else 372 binding = NULL; 373 374 if (ns && binding) { 375 status = (evaluate_expression 376 (&binding -> value, packet, lease, 377 client_state, 378 in_options, out_options, 379 scope, e -> data.set.expr, MDL)); 380 binding -> next = ns -> bindings; 381 ns -> bindings = binding; 382 } 383 384#if defined (DEBUG_EXPRESSIONS) 385 log_debug ("exec: let %s%s", e -> data.let.name, 386 (binding && status ? "" : "failed")); 387#endif 388 if (!e -> data.let.statements) { 389 } else if (e -> data.let.statements -> op == 390 let_statement) { 391 e = e -> data.let.statements; 392 goto next_let; 393 } else if (ns) { 394 if (scope && *scope) 395 binding_scope_reference (&ns -> outer, 396 *scope, MDL); 397 execute_statements 398 (result, packet, lease, 399 client_state, 400 in_options, out_options, 401 &ns, e -> data.let.statements); 402 } 403 if (ns) 404 binding_scope_dereference (&ns, MDL); 405 break; 406 407 case log_statement: 408 memset (&ds, 0, sizeof ds); 409 status = (evaluate_data_expression 410 (&ds, packet, 411 lease, client_state, in_options, 412 out_options, scope, r -> data.log.expr, 413 MDL)); 414 415#if defined (DEBUG_EXPRESSIONS) 416 log_debug ("exec: log"); 417#endif 418 419 if (status) { 420 switch (r -> data.log.priority) { 421 case log_priority_fatal: 422 log_fatal ("%.*s", (int)ds.len, 423 ds.data); 424 break; 425 case log_priority_error: 426 log_error ("%.*s", (int)ds.len, 427 ds.data); 428 break; 429 case log_priority_debug: 430 log_debug ("%.*s", (int)ds.len, 431 ds.data); 432 break; 433 case log_priority_info: 434 log_info ("%.*s", (int)ds.len, 435 ds.data); 436 break; 437 } 438 data_string_forget (&ds, MDL); 439 } 440 441 break; 442 443 default: 444 log_error ("bogus statement type %d", r -> op); 445 break; 446 } 447 executable_statement_dereference (&r, MDL); 448 if (next) { 449 executable_statement_reference (&r, next, MDL); 450 executable_statement_dereference (&next, MDL); 451 } 452 } 453 454 return 1; 455} 456 457/* Execute all the statements in a particular scope, and all statements in 458 scopes outer from that scope, but if a particular limiting scope is 459 reached, do not execute statements in that scope or in scopes outer 460 from it. More specific scopes need to take precedence over less 461 specific scopes, so we recursively traverse the scope list, executing 462 the most outer scope first. */ 463 464void execute_statements_in_scope (result, packet, 465 lease, client_state, in_options, out_options, 466 scope, group, limiting_group) 467 struct binding_value **result; 468 struct packet *packet; 469 struct lease *lease; 470 struct client_state *client_state; 471 struct option_state *in_options; 472 struct option_state *out_options; 473 struct binding_scope **scope; 474 struct group *group; 475 struct group *limiting_group; 476{ 477 struct group *limit; 478 479 /* If we've recursed as far as we can, return. */ 480 if (!group) 481 return; 482 483 /* As soon as we get to a scope that is outer than the limiting 484 scope, we are done. This is so that if somebody does something 485 like this, it does the expected thing: 486 487 domain-name "fugue.com"; 488 shared-network FOO { 489 host bar { 490 domain-name "othello.fugue.com"; 491 fixed-address 10.20.30.40; 492 } 493 subnet 10.20.30.0 netmask 255.255.255.0 { 494 domain-name "manhattan.fugue.com"; 495 } 496 } 497 498 The problem with the above arrangement is that the host's 499 group nesting will be host -> shared-network -> top-level, 500 and the limiting scope when we evaluate the host's scope 501 will be the subnet -> shared-network -> top-level, so we need 502 to know when we evaluate the host's scope to stop before we 503 evaluate the shared-networks scope, because it's outer than 504 the limiting scope, which means we've already evaluated it. */ 505 506 for (limit = limiting_group; limit; limit = limit -> next) { 507 if (group == limit) 508 return; 509 } 510 511 if (group -> next) 512 execute_statements_in_scope (result, packet, 513 lease, client_state, 514 in_options, out_options, scope, 515 group -> next, limiting_group); 516 execute_statements (result, packet, lease, client_state, in_options, 517 out_options, scope, group -> statements); 518} 519 520/* Dereference or free any subexpressions of a statement being freed. */ 521 522int executable_statement_dereference (ptr, file, line) 523 struct executable_statement **ptr; 524 const char *file; 525 int line; 526{ 527 528 if (!ptr || !*ptr) { 529 log_error ("%s(%d): null pointer", file, line); 530#if defined (POINTER_DEBUG) 531 abort (); 532#else 533 return 0; 534#endif 535 } 536 537 (*ptr) -> refcnt--; 538 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC); 539 if ((*ptr) -> refcnt > 0) { 540 *ptr = (struct executable_statement *)0; 541 return 1; 542 } 543 544 if ((*ptr) -> refcnt < 0) { 545 log_error ("%s(%d): negative refcnt!", file, line); 546#if defined (DEBUG_RC_HISTORY) 547 dump_rc_history (*ptr); 548#endif 549#if defined (POINTER_DEBUG) 550 abort (); 551#else 552 return 0; 553#endif 554 } 555 556 if ((*ptr) -> next) 557 executable_statement_dereference (&(*ptr) -> next, file, line); 558 559 switch ((*ptr) -> op) { 560 case statements_statement: 561 if ((*ptr) -> data.statements) 562 executable_statement_dereference 563 (&(*ptr) -> data.statements, file, line); 564 break; 565 566 case on_statement: 567 if ((*ptr) -> data.on.statements) 568 executable_statement_dereference 569 (&(*ptr) -> data.on.statements, file, line); 570 break; 571 572 case switch_statement: 573 if ((*ptr) -> data.s_switch.statements) 574 executable_statement_dereference 575 (&(*ptr) -> data.on.statements, file, line); 576 if ((*ptr) -> data.s_switch.expr) 577 expression_dereference (&(*ptr) -> data.s_switch.expr, 578 file, line); 579 break; 580 581 case case_statement: 582 if ((*ptr) -> data.s_switch.expr) 583 expression_dereference (&(*ptr) -> data.c_case, 584 file, line); 585 break; 586 587 case if_statement: 588 if ((*ptr) -> data.ie.expr) 589 expression_dereference (&(*ptr) -> data.ie.expr, 590 file, line); 591 if ((*ptr) -> data.ie.tc) 592 executable_statement_dereference 593 (&(*ptr) -> data.ie.tc, file, line); 594 if ((*ptr) -> data.ie.fc) 595 executable_statement_dereference 596 (&(*ptr) -> data.ie.fc, file, line); 597 break; 598 599 case eval_statement: 600 if ((*ptr) -> data.eval) 601 expression_dereference (&(*ptr) -> data.eval, 602 file, line); 603 break; 604 605 case return_statement: 606 if ((*ptr) -> data.eval) 607 expression_dereference (&(*ptr) -> data.eval, 608 file, line); 609 break; 610 611 case set_statement: 612 if ((*ptr)->data.set.name) 613 dfree ((*ptr)->data.set.name, file, line); 614 if ((*ptr)->data.set.expr) 615 expression_dereference (&(*ptr) -> data.set.expr, 616 file, line); 617 break; 618 619 case unset_statement: 620 if ((*ptr)->data.unset) 621 dfree ((*ptr)->data.unset, file, line); 622 break; 623 624 case supersede_option_statement: 625 case send_option_statement: 626 case default_option_statement: 627 case append_option_statement: 628 case prepend_option_statement: 629 if ((*ptr) -> data.option) 630 option_cache_dereference (&(*ptr) -> data.option, 631 file, line); 632 break; 633 634 default: 635 /* Nothing to do. */ 636 break; 637 } 638 639 dfree ((*ptr), file, line); 640 *ptr = (struct executable_statement *)0; 641 return 1; 642} 643 644void write_statements (file, statements, indent) 645 FILE *file; 646 struct executable_statement *statements; 647 int indent; 648{ 649 struct executable_statement *r, *x; 650 const char *s, *t, *dot; 651 int col; 652 653 if (!statements) 654 return; 655 656 col = 0; /* XXXGCC -Wuninitialized */ 657 658 for (r = statements; r; r = r -> next) { 659 switch (r -> op) { 660 case statements_statement: 661 write_statements (file, r -> data.statements, indent); 662 break; 663 664 case on_statement: 665 indent_spaces (file, indent); 666 fprintf (file, "on "); 667 s = ""; 668 if (r -> data.on.evtypes & ON_EXPIRY) { 669 fprintf (file, "%sexpiry", s); 670 s = " or "; 671 } 672 if (r -> data.on.evtypes & ON_COMMIT) { 673 fprintf (file, "%scommit", s); 674 s = "or"; 675 } 676 if (r -> data.on.evtypes & ON_RELEASE) { 677 fprintf (file, "%srelease", s); 678 s = "or"; 679 } 680 if (r -> data.on.statements) { 681 fprintf (file, " {"); 682 write_statements (file, 683 r -> data.on.statements, 684 indent + 2); 685 indent_spaces (file, indent); 686 fprintf (file, "}"); 687 } else { 688 fprintf (file, ";"); 689 } 690 break; 691 692 case switch_statement: 693 indent_spaces (file, indent); 694 fprintf (file, "switch ("); 695 col = write_expression (file, 696 r -> data.s_switch.expr, 697 indent + 7, indent + 7, 1); 698 col = token_print_indent (file, col, indent + 7, 699 "", "", ")"); 700 token_print_indent (file, 701 col, indent, " ", "", "{"); 702 write_statements (file, r -> data.s_switch.statements, 703 indent + 2); 704 indent_spaces (file, indent); 705 fprintf (file, "}"); 706 break; 707 708 case case_statement: 709 indent_spaces (file, indent - 1); 710 fprintf (file, "case "); 711 col = write_expression (file, 712 r -> data.s_switch.expr, 713 indent + 5, indent + 5, 1); 714 token_print_indent (file, col, indent + 5, 715 "", "", ":"); 716 break; 717 718 case default_statement: 719 indent_spaces (file, indent - 1); 720 fprintf (file, "default: "); 721 break; 722 723 case if_statement: 724 indent_spaces (file, indent); 725 fprintf (file, "if "); 726 x = r; 727 col = write_expression (file, 728 x -> data.ie.expr, 729 indent + 3, indent + 3, 1); 730 else_if: 731 token_print_indent (file, col, indent, " ", "", "{"); 732 write_statements (file, x -> data.ie.tc, indent + 2); 733 if (x -> data.ie.fc && 734 x -> data.ie.fc -> op == if_statement && 735 !x -> data.ie.fc -> next) { 736 indent_spaces (file, indent); 737 fprintf (file, "} elsif "); 738 x = x -> data.ie.fc; 739 col = write_expression (file, 740 x -> data.ie.expr, 741 indent + 6, 742 indent + 6, 1); 743 goto else_if; 744 } 745 if (x -> data.ie.fc) { 746 indent_spaces (file, indent); 747 fprintf (file, "} else {"); 748 write_statements (file, x -> data.ie.fc, 749 indent + 2); 750 } 751 indent_spaces (file, indent); 752 fprintf (file, "}"); 753 break; 754 755 case eval_statement: 756 indent_spaces (file, indent); 757 fprintf (file, "eval "); 758 col = write_expression (file, r -> data.eval, 759 indent + 5, indent + 5, 1); 760 fprintf (file, ";"); 761 break; 762 763 case return_statement: 764 indent_spaces (file, indent); 765 fprintf (file, "return;"); 766 break; 767 768 case add_statement: 769 indent_spaces (file, indent); 770 fprintf (file, "add \"%s\"", r -> data.add -> name); 771 break; 772 773 case break_statement: 774 indent_spaces (file, indent); 775 fprintf (file, "break;"); 776 break; 777 778 case supersede_option_statement: 779 case send_option_statement: 780 s = "supersede"; 781 goto option_statement; 782 783 case default_option_statement: 784 s = "default"; 785 goto option_statement; 786 787 case append_option_statement: 788 s = "append"; 789 goto option_statement; 790 791 case prepend_option_statement: 792 s = "prepend"; 793 option_statement: 794 /* Note: the reason we don't try to pretty print 795 the option here is that the format of the option 796 may change in dhcpd.conf, and then when this 797 statement was read back, it would cause a syntax 798 error. */ 799 if (r -> data.option -> option -> universe == 800 &dhcp_universe) { 801 t = ""; 802 dot = ""; 803 } else { 804 t = (r -> data.option -> option -> 805 universe -> name); 806 dot = "."; 807 } 808 indent_spaces (file, indent); 809 fprintf (file, "%s %s%s%s = ", s, t, dot, 810 r -> data.option -> option -> name); 811 col = (indent + strlen (s) + strlen (t) + 812 strlen (dot) + strlen (r -> data.option -> 813 option -> name) + 4); 814 if (r -> data.option -> expression) 815 write_expression 816 (file, 817 r -> data.option -> expression, 818 col, indent + 8, 1); 819 else 820 token_indent_data_string 821 (file, col, indent + 8, "", "", 822 &r -> data.option -> data); 823 824 fprintf (file, ";"); /* XXX */ 825 break; 826 827 case set_statement: 828 indent_spaces (file, indent); 829 fprintf (file, "set "); 830 col = token_print_indent (file, indent + 4, indent + 4, 831 "", "", r -> data.set.name); 832 col = token_print_indent (file, col, indent + 4, 833 " ", " ", "="); 834 col = write_expression (file, r -> data.set.expr, 835 indent + 3, indent + 3, 0); 836 col = token_print_indent (file, col, indent + 4, 837 " ", "", ";"); 838 break; 839 840 case unset_statement: 841 indent_spaces (file, indent); 842 fprintf (file, "unset "); 843 col = token_print_indent (file, indent + 6, indent + 6, 844 "", "", r -> data.set.name); 845 col = token_print_indent (file, col, indent + 6, 846 " ", "", ";"); 847 break; 848 849 case log_statement: 850 indent_spaces (file, indent); 851 fprintf (file, "log "); 852 col = token_print_indent (file, indent + 4, indent + 4, 853 "", "", "("); 854 switch (r -> data.log.priority) { 855 case log_priority_fatal: 856 col = token_print_indent 857 (file, col, indent + 4, "", 858 " ", "fatal,"); 859 break; 860 case log_priority_error: 861 col = token_print_indent 862 (file, col, indent + 4, "", 863 " ", "error,"); 864 break; 865 case log_priority_debug: 866 col = token_print_indent 867 (file, col, indent + 4, "", 868 " ", "debug,"); 869 break; 870 case log_priority_info: 871 col = token_print_indent 872 (file, col, indent + 4, "", 873 " ", "info,"); 874 break; 875 } 876 col = write_expression (file, r -> data.log.expr, 877 indent + 4, indent + 4, 0); 878 col = token_print_indent (file, col, indent + 4, 879 "", "", ");"); 880 881 break; 882 883 default: 884 log_fatal ("bogus statement type %d\n", r -> op); 885 } 886 } 887} 888 889/* Find a case statement in the sequence of executable statements that 890 matches the expression, and if found, return the following statement. 891 If no case statement matches, try to find a default statement and 892 return that (the default statement can precede all the case statements). 893 Otherwise, return the null statement. */ 894 895int find_matching_case (struct executable_statement **ep, 896 struct packet *packet, struct lease *lease, 897 struct client_state *client_state, 898 struct option_state *in_options, 899 struct option_state *out_options, 900 struct binding_scope **scope, 901 struct expression *expr, 902 struct executable_statement *stmt) 903{ 904 int status, sub; 905 struct executable_statement *s; 906 907 if (is_data_expression (expr)) { 908 struct data_string cd, ds; 909 memset (&ds, 0, sizeof ds); 910 memset (&cd, 0, sizeof cd); 911 912 status = (evaluate_data_expression (&ds, packet, lease, 913 client_state, in_options, 914 out_options, scope, expr, 915 MDL)); 916 if (status) { 917 for (s = stmt; s; s = s -> next) { 918 if (s -> op == case_statement) { 919 sub = (evaluate_data_expression 920 (&cd, packet, lease, client_state, 921 in_options, out_options, 922 scope, s -> data.c_case, MDL)); 923 if (sub && cd.len == ds.len && 924 !memcmp (cd.data, ds.data, cd.len)) 925 { 926 data_string_forget (&cd, MDL); 927 data_string_forget (&ds, MDL); 928 executable_statement_reference 929 (ep, s -> next, MDL); 930 return 1; 931 } 932 data_string_forget (&cd, MDL); 933 } 934 } 935 data_string_forget (&ds, MDL); 936 } 937 } else { 938 unsigned long n, c; 939 status = evaluate_numeric_expression (&n, packet, lease, 940 client_state, 941 in_options, out_options, 942 scope, expr); 943 944 if (status) { 945 for (s = stmt; s; s = s -> next) { 946 if (s -> op == case_statement) { 947 sub = (evaluate_numeric_expression 948 (&c, packet, lease, client_state, 949 in_options, out_options, 950 scope, s -> data.c_case)); 951 if (sub && n == c) { 952 executable_statement_reference 953 (ep, s -> next, MDL); 954 return 1; 955 } 956 } 957 } 958 } 959 } 960 961 /* If we didn't find a matching case statement, look for a default 962 statement and return the statement following it. */ 963 for (s = stmt; s; s = s -> next) 964 if (s -> op == default_statement) 965 break; 966 if (s) { 967 executable_statement_reference (ep, s -> next, MDL); 968 return 1; 969 } 970 return 0; 971} 972 973int executable_statement_foreach (struct executable_statement *stmt, 974 int (*callback) (struct 975 executable_statement *, 976 void *, int), 977 void *vp, int condp) 978{ 979 struct executable_statement *foo; 980 int ok = 0; 981 982 for (foo = stmt; foo; foo = foo -> next) { 983 if ((*callback) (foo, vp, condp) != 0) 984 ok = 1; 985 switch (foo -> op) { 986 case null_statement: 987 break; 988 case if_statement: 989 if (executable_statement_foreach (foo -> data.ie.tc, 990 callback, vp, 1)) 991 ok = 1; 992 if (executable_statement_foreach (foo -> data.ie.fc, 993 callback, vp, 1)) 994 ok = 1; 995 break; 996 case add_statement: 997 break; 998 case eval_statement: 999 break; 1000 case break_statement: 1001 break; 1002 case default_option_statement: 1003 break; 1004 case supersede_option_statement: 1005 break; 1006 case append_option_statement: 1007 break; 1008 case prepend_option_statement: 1009 break; 1010 case send_option_statement: 1011 break; 1012 case statements_statement: 1013 if ((executable_statement_foreach 1014 (foo -> data.statements, callback, vp, condp))) 1015 ok = 1; 1016 break; 1017 case on_statement: 1018 if ((executable_statement_foreach 1019 (foo -> data.on.statements, callback, vp, 1))) 1020 ok = 1; 1021 break; 1022 case switch_statement: 1023 if ((executable_statement_foreach 1024 (foo -> data.s_switch.statements, callback, vp, 1))) 1025 ok = 1; 1026 break; 1027 case case_statement: 1028 break; 1029 case default_statement: 1030 break; 1031 case set_statement: 1032 break; 1033 case unset_statement: 1034 break; 1035 case let_statement: 1036 if ((executable_statement_foreach 1037 (foo -> data.let.statements, callback, vp, 0))) 1038 ok = 1; 1039 break; 1040 case define_statement: 1041 break; 1042 case log_statement: 1043 case return_statement: 1044 break; 1045 } 1046 } 1047 return ok; 1048} 1049