]> git.ipfire.org Git - thirdparty/dhcp.git/blob - common/execute.c
Checkpoint: code done, need tests
[thirdparty/dhcp.git] / common / execute.c
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
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
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
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
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
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
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 }