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