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