xref: /netbsd-src/external/mpl/dhcp/dist/common/execute.c (revision f407d9293b6650aa8c33d6a995f797bb6aaefd90)
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@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 
execute_statements(result,packet,lease,client_state,in_options,out_options,scope,statements,on_star)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 
execute_statements_in_scope(result,packet,lease,client_state,in_options,out_options,scope,group,limiting_group,on_star)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 
executable_statement_dereference(ptr,file,line)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 
write_statements(file,statements,indent)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 
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)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 
executable_statement_foreach(struct executable_statement * stmt,int (* callback)(struct executable_statement *,void *,int),void * vp,int condp)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