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