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