ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
execute.c
Go to the documentation of this file.
1/* execute.c
2
3 Support for executable statements. */
4
5/*
6 * Copyright (C) 2004-2022 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 * PO Box 360
23 * Newmarket, NH 03857 USA
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
36 in_options, out_options, scope, statements,
37 on_star)
38 struct binding_value **result;
39 struct packet *packet;
40 struct lease *lease;
42 struct option_state *in_options;
43 struct option_state *out_options;
44 struct binding_scope **scope;
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)
65 switch (r->op) {
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,
74 on_star);
75#if defined (DEBUG_EXPRESSIONS)
76 log_debug ("exec: statements returns %d", status);
77#endif
78 if (!status) {
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))
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)
100 (&on_star->on_expiry, MDL);
101 if (r->data.on.statements)
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)
113 if (r->data.on.statements)
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)
124 (&on_star->on_commit, MDL);
125 if (r->data.on.statements)
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
139 in_options, out_options, scope,
140 r->data.s_switch.expr,
142#if defined (DEBUG_EXPRESSIONS)
143 log_debug ("exec: switch: case %lx", (unsigned long)e);
144#endif
145 if (status) {
147 (result, packet, lease, client_state,
148 in_options, out_options, scope, e,
149 on_star))) {
151 (&e, MDL);
153 (&r, MDL);
154 return 0;
155 }
157 }
158 break;
159
160 /* These have no effect when executed. */
161 case case_statement:
163 break;
164
165 case if_statement:
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;
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)) {
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));
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
308 return 1;
309
312#if defined (DEBUG_EXPRESSIONS)
313 log_debug ("exec: %s option %s.%s",
315 ? "supersede" : "send"),
317 r->data.option->option->name);
318 goto option_statement;
319#endif
321#if defined (DEBUG_EXPRESSIONS)
322 log_debug ("exec: default option %s.%s",
324 r->data.option->option->name);
325 goto option_statement;
326#endif
328#if defined (DEBUG_EXPRESSIONS)
329 log_debug ("exec: append option %s.%s",
331 r->data.option->option->name);
332 goto option_statement;
333#endif
335#if defined (DEBUG_EXPRESSIONS)
336 log_debug ("exec: prepend option %s.%s",
338 r->data.option->option->name);
339 option_statement:
340#endif
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)
387 (&binding->value, MDL);
388 if (r->op == set_statement) {
389 status = (evaluate_expression
390 (&binding->value, packet,
392 in_options, out_options,
393 scope, r->data.set.expr,
394 MDL));
395 } else {
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;
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)
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;
446 e = r;
447
448 next_let:
449 if (ns) {
450 binding = dmalloc(sizeof(*binding), MDL);
451 if (!binding) {
452 blb:
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
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 ==
491 e = e->data.let.statements;
492 goto next_let;
493 } else if (ns) {
494 if (scope && *scope)
496 *scope, MDL);
498 (result, packet, lease, client_state,
499 in_options, out_options,
500 &ns, e->data.let.statements, on_star);
501 }
502 if (ns)
504 break;
505
506 case log_statement:
507 memset (&ds, 0, sizeof ds);
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
542 /* If possible parse any options in a vendor option
543 * encapsulation, this may add options to the in_options
544 * option state */
546 in_options, out_options, scope);
547 break;
548
549 default:
550 log_error ("bogus statement type %d", r -> op);
551 break;
552 }
554 if (next) {
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
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;
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)
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
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)
665
666 switch ((*ptr) -> op) {
668 if ((*ptr) -> data.statements)
670 (&(*ptr) -> data.statements, file, line);
671 break;
672
673 case on_statement:
674 if ((*ptr) -> data.on.statements)
676 (&(*ptr) -> data.on.statements, file, line);
677 break;
678
679 case switch_statement:
680 if ((*ptr) -> data.s_switch.statements)
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)
700 (&(*ptr) -> data.ie.tc, file, line);
701 if ((*ptr) -> data.ie.fc)
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
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
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
760 FILE *file;
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) {
778 break;
779
780 case on_statement:
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, " {");
799 r -> data.on.statements,
800 indent + 2);
802 fprintf (file, "}");
803 } else {
804 fprintf (file, ";");
805 }
806 break;
807
808 case switch_statement:
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 "", "", ")");
817 col, indent, " ", "", "{");
819 indent + 2);
821 fprintf (file, "}");
822 break;
823
824 case case_statement:
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
836 fprintf (file, "default: ");
837 break;
838
839 case if_statement:
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) {
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) {
863 fprintf (file, "} else {");
865 indent + 2);
866 }
868 fprintf (file, "}");
869 break;
870
871 case eval_statement:
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:
881 fprintf (file, "return;");
882 break;
883
884 case add_statement:
886 fprintf (file, "add \"%s\"", r -> data.add -> name);
887 break;
888
889 case break_statement:
891 fprintf (file, "break;");
892 break;
893
896 s = "supersede";
897 goto option_statement;
898
900 s = "default";
901 goto option_statement;
902
904 s = "append";
905 goto option_statement;
906
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 }
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)
932 (file,
933 r -> data.option -> expression,
934 col, indent + 8, 1);
935 else
937 (file, col, indent + 8, "", "",
938 &r -> data.option -> data);
939
940 fprintf (file, ";"); /* XXX */
941 break;
942
943 case set_statement:
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:
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:
967 fprintf (file, "log ");
968 col = token_print_indent (file, indent + 4, indent + 4,
969 "", "", "(");
970 switch (r -> data.log.priority) {
972 (void) token_print_indent
973 (file, col, indent + 4, "",
974 " ", "fatal,");
975 break;
977 (void) token_print_indent
978 (file, col, indent + 4, "",
979 " ", "error,");
980 break;
982 (void) token_print_indent
983 (file, col, indent + 4, "",
984 " ", "debug,");
985 break;
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
1000
1001#ifdef ENABLE_EXECUTE
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 "", " ", ",");
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
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
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) {
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);
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;
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) {
1095 (&c, packet, lease, client_state,
1096 in_options, out_options,
1097 scope, s->data.c_case));
1098 if (sub && n == c) {
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) {
1115 return 1;
1116 }
1117 return 0;
1118}
1119
1121 int (*callback) (struct
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:
1137 callback, vp, 1))
1138 ok = 1;
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;
1150 break;
1152 break;
1154 break;
1156 break;
1158 break;
1161 (foo->data.statements, callback, vp, condp)))
1162 ok = 1;
1163 break;
1164 case on_statement:
1166 (foo->data.on.statements, callback, vp, 1)))
1167 ok = 1;
1168 break;
1169 case switch_statement:
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:
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:
1193 break;
1194 }
1195 }
1196 return ok;
1197}
#define RC_MISC
Definition alloc.h:56
#define rc_register(file, line, reference, addr, refcnt, d, f)
Definition alloc.h:88
void data_string_forget(struct data_string *data, const char *file, int line)
Definition alloc.c:1339
int fundef_reference(struct fundef **ptr, struct fundef *src, const char *file, int line)
Definition alloc.c:586
int executable_statement_reference(struct executable_statement **ptr, struct executable_statement *bp, const char *file, int line)
Definition alloc.c:972
int binding_scope_reference(struct binding_scope **ptr, struct binding_scope *bp, const char *file, int line)
Definition alloc.c:1227
int binding_scope_allocate(struct binding_scope **ptr, const char *file, int line)
Definition alloc.c:1194
int binding_value_allocate(struct binding_value **cptr, const char *file, int line)
Definition alloc.c:500
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
Definition options.c:2953
void set_option(struct universe *universe, struct option_state *options, struct option_cache *option, enum statement_op op)
Definition options.c:2403
void parse_vendor_option(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)
Parse a vendor option (option 43)
Definition options.c:4618
int token_indent_data_string(FILE *file, int col, int indent, const char *prefix, const char *suffix, struct data_string *data)
Definition print.c:1219
int token_print_indent_concat(FILE *file, int col, int indent, const char *prefix, const char *suffix,...)
Definition print.c:1181
void indent_spaces(FILE *file, int indent)
Definition print.c:1300
int token_print_indent(FILE *file, int col, int indent, const char *prefix, const char *suffix, const char *buf)
Definition print.c:1262
void classify(struct packet *packet, struct class *class)
Definition dhclient.c:1556
void indent(int)
struct universe dhcp_universe
const char int line
Definition dhcpd.h:3802
const char * file
Definition dhcpd.h:3802
int execute_statements(struct binding_value **result, 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 executable_statement *statements, struct on_star *on_star)
Definition execute.c:35
void execute_statements_in_scope(struct binding_value **result, 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 group *group, struct group *limiting_group, struct on_star *on_star)
Definition execute.c:570
int executable_statement_foreach(struct executable_statement *stmt, int(*callback)(struct executable_statement *, void *, int), void *vp, int condp)
Definition execute.c:1120
void write_statements(FILE *file, struct executable_statement *statements, int indent)
Definition execute.c:759
int executable_statement_dereference(struct executable_statement **ptr, const char *file, int line)
Definition execute.c:630
int 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)
Definition execute.c:1042
@ supersede_option_statement
Definition keama.h:170
@ statements_statement
Definition keama.h:174
@ unset_statement
Definition keama.h:180
@ switch_statement
Definition keama.h:176
@ if_statement
Definition keama.h:165
@ log_statement
Definition keama.h:183
@ null_statement
Definition keama.h:164
@ eval_statement
Definition keama.h:167
@ define_statement
Definition keama.h:182
@ on_statement
Definition keama.h:175
@ default_option_statement
Definition keama.h:169
@ default_statement
Definition keama.h:178
@ let_statement
Definition keama.h:181
@ prepend_option_statement
Definition keama.h:172
@ execute_statement
Definition keama.h:185
@ case_statement
Definition keama.h:177
@ send_option_statement
Definition keama.h:173
@ return_statement
Definition keama.h:184
@ vendor_opt_statement
Definition keama.h:186
@ append_option_statement
Definition keama.h:171
@ break_statement
Definition keama.h:168
@ set_statement
Definition keama.h:179
@ add_statement
Definition keama.h:166
#define MDL
Definition omapip.h:567
void * dmalloc(size_t, const char *, int)
Definition alloc.c:57
void dfree(void *, const char *, int)
Definition alloc.c:145
int log_error(const char *,...) __attribute__((__format__(__printf__
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
#define ON_RELEASE
Definition statement.h:74
#define ON_COMMIT
Definition statement.h:72
#define ON_EXPIRY
Definition statement.h:73
struct binding * bindings
Definition tree.h:126
struct binding_scope * outer
Definition tree.h:125
enum binding_value::@135246253323115003010247222006030375211205217247 type
union binding_value::value value
char * name
Definition tree.h:119
struct binding * next
Definition tree.h:118
struct binding_value * value
Definition tree.h:120
char * name
Definition dhcpd.h:1106
const unsigned char * data
Definition tree.h:78
unsigned len
Definition tree.h:79
struct executable_statement::@336221350347175166011011356261373334214214051201::@325210277324101252237043341265364212037303267157 s_switch
struct expression * eval
Definition statement.h:62
enum executable_statement::statement_op op
struct executable_statement * tc
Definition statement.h:59
struct executable_statement::@336221350347175166011011356261373334214214051201::@206325035353013171354256106236162033341037345150 set
enum executable_statement::@336221350347175166011011356261373334214214051201::@054036024254157344331216371041053101210136045205::@170066364270231075105257255130235107325336004011 priority
struct executable_statement::@336221350347175166011011356261373334214214051201::@114173066021273303314366177116061034061242304335 execute
struct executable_statement::@336221350347175166011011356261373334214214051201::@054036024254157344331216371041053101210136045205 log
struct executable_statement::@336221350347175166011011356261373334214214051201::@200067301215145050134342173232277303121035136232 ie
union executable_statement::@336221350347175166011011356261373334214214051201 data
struct expression * c_case
Definition statement.h:82
struct executable_statement::@336221350347175166011011356261373334214214051201::@206325035353013171354256106236162033341037345150 let
struct option_cache * option
Definition statement.h:65
struct expression * arglist
Definition statement.h:100
struct executable_statement * next
Definition statement.h:31
struct executable_statement * fc
Definition statement.h:59
struct executable_statement * statements
Definition statement.h:69
struct expression * expr
Definition statement.h:60
struct class * add
Definition statement.h:64
struct executable_statement::@336221350347175166011011356261373334214214051201::@240325212232200272321314266066265221125200273242 on
union expression::expr_union data
enum expr_op op
Definition tree.h:199
Definition dhcpd.h:962
struct group * next
Definition dhcpd.h:963
struct executable_statement * statements
Definition dhcpd.h:970
Definition dhcpd.h:560
struct on_star on_star
Definition dhcpd.h:583
struct executable_statement * on_commit
Definition dhcpd.h:555
struct executable_statement * on_expiry
Definition dhcpd.h:554
struct executable_statement * on_release
Definition dhcpd.h:556
struct option * option
Definition dhcpd.h:389
Definition tree.h:345
struct universe * universe
Definition tree.h:348
const char * name
Definition tree.h:346
const char * name
Definition tree.h:302
int binding_scope_dereference(struct binding_scope **ptr, const char *file, int line)
Definition tree.c:3786
int write_expression(FILE *file, struct expression *expr, int col, int indent, int firstp)
Definition tree.c:3298
int evaluate_expression(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct expression *expr, const char *file, int line)
Definition tree.c:500
struct binding * find_binding(struct binding_scope *scope, const char *name)
Definition tree.c:3755
void expression_dereference(struct expression **eptr, const char *file, int line)
Definition tree.c:2813
int evaluate_data_expression(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct expression *expr, const char *file, int line)
Definition tree.c:1126
int is_data_expression(struct expression *expr)
Definition tree.c:3048
int evaluate_boolean_expression(int *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct expression *expr)
Definition tree.c:694
int binding_value_dereference(struct binding_value **v, const char *file, int line)
Definition tree.c:652
int evaluate_numeric_expression(unsigned long *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct expression *expr)
Definition tree.c:2229
struct fundef * fundef
Definition tree.h:112
struct expression * next
Definition tree.h:270
struct expression * val
Definition tree.h:269
struct expression::expr_union::@155243052250312351005066334172140274044155221273 arg
struct fundef * func
Definition tree.h:276