3 Support for executable statements. */
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1998-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
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.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
36 static char copyright
[] =
37 "$Id$ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
41 #include <omapip/omapip_p.h>
43 int execute_statements (result
, packet
, lease
, client_state
,
44 in_options
, out_options
, scope
, statements
)
45 struct binding_value
**result
;
46 struct packet
*packet
;
48 struct client_state
*client_state
;
49 struct option_state
*in_options
;
50 struct option_state
*out_options
;
51 struct binding_scope
**scope
;
52 struct executable_statement
*statements
;
54 struct executable_statement
*r
, *e
, *next
;
58 __unused
struct binding_scope
*outer
;
59 struct binding
*binding
;
60 struct data_string ds
;
61 struct binding_scope
*ns
;
66 r
= (struct executable_statement
*)0;
67 next
= (struct executable_statement
*)0;
68 e
= (struct executable_statement
*)0;
69 executable_statement_reference (&r
, statements
, MDL
);
70 while (r
&& !(result
&& *result
)) {
72 executable_statement_reference (&next
, r
-> next
, MDL
);
74 case statements_statement
:
75 #if defined (DEBUG_EXPRESSIONS)
76 log_debug ("exec: statements");
78 status
= execute_statements (result
, packet
, lease
,
79 client_state
, in_options
,
81 r
-> data
.statements
);
82 #if defined (DEBUG_EXPRESSIONS)
83 log_debug ("exec: statements returns %d", status
);
91 if (r
-> data
.on
.evtypes
& ON_EXPIRY
) {
92 #if defined (DEBUG_EXPRESSIONS)
93 log_debug ("exec: on expiry");
95 if (lease
-> on_expiry
)
96 executable_statement_dereference
97 (&lease
-> on_expiry
, MDL
);
98 if (r
-> data
.on
.statements
)
99 executable_statement_reference
100 (&lease
-> on_expiry
,
101 r
-> data
.on
.statements
, MDL
);
103 if (r
-> data
.on
.evtypes
& ON_RELEASE
) {
104 #if defined (DEBUG_EXPRESSIONS)
105 log_debug ("exec: on release");
107 if (lease
-> on_release
)
108 executable_statement_dereference
109 (&lease
-> on_release
, MDL
);
110 if (r
-> data
.on
.statements
)
111 executable_statement_reference
112 (&lease
-> on_release
,
113 r
-> data
.on
.statements
, MDL
);
115 if (r
-> data
.on
.evtypes
& ON_COMMIT
) {
116 #if defined (DEBUG_EXPRESSIONS)
117 log_debug ("exec: on commit");
119 if (lease
-> on_commit
)
120 executable_statement_dereference
121 (&lease
-> on_commit
, MDL
);
122 if (r
-> data
.on
.statements
)
123 executable_statement_reference
124 (&lease
-> on_commit
,
125 r
-> data
.on
.statements
, MDL
);
130 case switch_statement
:
131 #if defined (DEBUG_EXPRESSIONS)
132 log_debug ("exec: switch");
134 status
= (find_matching_case
135 (&e
, packet
, lease
, client_state
,
136 in_options
, out_options
, scope
,
137 r
-> data
.s_switch
.expr
,
138 r
-> data
.s_switch
.statements
));
139 #if defined (DEBUG_EXPRESSIONS)
140 log_debug ("exec: switch: case %lx", (unsigned long)e
);
143 if (!(execute_statements
144 (result
, packet
, lease
, client_state
,
145 in_options
, out_options
, scope
, e
))) {
146 executable_statement_dereference
150 executable_statement_dereference (&e
, MDL
);
154 /* These have no effect when executed. */
156 case default_statement
:
160 status
= (evaluate_boolean_expression
162 lease
, client_state
, in_options
,
163 out_options
, scope
, r
-> data
.ie
.expr
));
165 #if defined (DEBUG_EXPRESSIONS)
166 log_debug ("exec: if %s", (status
167 ? (rc
? "true" : "false")
170 /* XXX Treat NULL as false */
173 if (!execute_statements
174 (result
, packet
, lease
, client_state
,
175 in_options
, out_options
, scope
,
176 rc
? r
-> data
.ie
.tc
: r
-> data
.ie
.fc
))
181 status
= evaluate_expression
182 ((struct binding_value
**)0,
183 packet
, lease
, client_state
, in_options
,
184 out_options
, scope
, r
-> data
.eval
, MDL
);
185 #if defined (DEBUG_EXPRESSIONS)
186 log_debug ("exec: evaluate: %s",
187 (status
? "succeeded" : "failed"));
191 case return_statement
:
192 status
= evaluate_expression
194 lease
, client_state
, in_options
,
195 out_options
, scope
, r
-> data
.retval
, MDL
);
196 #if defined (DEBUG_EXPRESSIONS)
197 log_debug ("exec: return: %s",
198 (status
? "succeeded" : "failed"));
203 #if defined (DEBUG_EXPRESSIONS)
204 log_debug ("exec: add %s", (r
-> data
.add
-> name
205 ? r
-> data
.add
-> name
206 : "<unnamed class>"));
208 classify (packet
, r
-> data
.add
);
211 case break_statement
:
212 #if defined (DEBUG_EXPRESSIONS)
213 log_debug ("exec: break");
217 case supersede_option_statement
:
218 case send_option_statement
:
219 #if defined (DEBUG_EXPRESSIONS)
220 log_debug ("exec: %s option %s.%s",
221 (r
-> op
== supersede_option_statement
222 ? "supersede" : "send"),
223 r
-> data
.option
-> option
-> universe
-> name
,
224 r
-> data
.option
-> option
-> name
);
225 goto option_statement
;
227 case default_option_statement
:
228 #if defined (DEBUG_EXPRESSIONS)
229 log_debug ("exec: default option %s.%s",
230 r
-> data
.option
-> option
-> universe
-> name
,
231 r
-> data
.option
-> option
-> name
);
232 goto option_statement
;
234 case append_option_statement
:
235 #if defined (DEBUG_EXPRESSIONS)
236 log_debug ("exec: append option %s.%s",
237 r
-> data
.option
-> option
-> universe
-> name
,
238 r
-> data
.option
-> option
-> name
);
239 goto option_statement
;
241 case prepend_option_statement
:
242 #if defined (DEBUG_EXPRESSIONS)
243 log_debug ("exec: prepend option %s.%s",
244 r
-> data
.option
-> option
-> universe
-> name
,
245 r
-> data
.option
-> option
-> name
);
248 set_option (r
-> data
.option
-> option
-> universe
,
249 out_options
, r
-> data
.option
, r
-> op
);
253 case define_statement
:
255 log_error ("set %s: no scope",
261 if (!binding_scope_allocate (scope
, MDL
)) {
262 log_error ("set %s: can't allocate scope",
268 binding
= find_binding (*scope
, r
-> data
.set
.name
);
269 #if defined (DEBUG_EXPRESSIONS)
270 log_debug ("exec: set %s", r
-> data
.set
.name
);
273 binding
= dmalloc (sizeof *binding
, MDL
);
275 memset (binding
, 0, sizeof *binding
);
278 (r
-> data
.set
.name
) + 1,
280 if (binding
-> name
) {
281 strcpy (binding
-> name
,
283 binding
-> next
= (*scope
) -> bindings
;
284 (*scope
) -> bindings
= binding
;
286 dfree (binding
, MDL
);
287 binding
= (struct binding
*)0;
292 if (binding
-> value
)
293 binding_value_dereference
294 (&binding
-> value
, MDL
);
295 if (r
-> op
== set_statement
) {
296 status
= (evaluate_expression
297 (&binding
-> value
, packet
,
299 in_options
, out_options
,
300 scope
, r
-> data
.set
.expr
,
303 if (!(binding_value_allocate
304 (&binding
-> value
, MDL
))) {
305 dfree (binding
, MDL
);
306 binding
= (struct binding
*)0;
308 if (binding
-> value
) {
309 binding
-> value
-> type
=
312 (&binding
-> value
-> value
.fundef
,
313 r
-> data
.set
.expr
-> data
.func
,
318 #if defined (DEBUG_EXPRESSIONS)
319 log_debug ("exec: set %s%s", r
-> data
.set
.name
,
320 (binding
&& status
? "" : " (failed)"));
324 case unset_statement
:
325 if (!scope
|| !*scope
) {
329 binding
= find_binding (*scope
, r
-> data
.unset
);
331 if (binding
-> value
)
332 binding_value_dereference
333 (&binding
-> value
, MDL
);
337 #if defined (DEBUG_EXPRESSIONS)
338 log_debug ("exec: unset %s: %s", r
-> data
.unset
,
339 (status
? "found" : "not found"));
344 #if defined (DEBUG_EXPRESSIONS)
345 log_debug ("exec: let %s", r
-> data
.let
.name
);
347 ns
= (struct binding_scope
*)0;
348 binding_scope_allocate (&ns
, MDL
);
353 binding
= dmalloc (sizeof *binding
, MDL
);
354 memset (binding
, 0, sizeof *binding
);
357 binding_scope_dereference (&ns
, MDL
);
361 (e
-> data
.let
.name
+ 1),
364 strcpy (binding
-> name
,
367 dfree (binding
, MDL
);
368 binding
= (struct binding
*)0;
376 status
= (evaluate_expression
377 (&binding
-> value
, packet
, lease
,
379 in_options
, out_options
,
380 scope
, e
-> data
.set
.expr
, MDL
));
381 binding
-> next
= ns
-> bindings
;
382 ns
-> bindings
= binding
;
385 #if defined (DEBUG_EXPRESSIONS)
386 log_debug ("exec: let %s%s", e
-> data
.let
.name
,
387 (binding
&& status
? "" : "failed"));
389 if (!e
-> data
.let
.statements
) {
390 } else if (e
-> data
.let
.statements
-> op
==
392 e
= e
-> data
.let
.statements
;
396 binding_scope_reference (&ns
-> outer
,
399 (result
, packet
, lease
,
401 in_options
, out_options
,
402 &ns
, e
-> data
.let
.statements
);
405 binding_scope_dereference (&ns
, MDL
);
409 memset (&ds
, 0, sizeof ds
);
410 status
= (evaluate_data_expression
412 lease
, client_state
, in_options
,
413 out_options
, scope
, r
-> data
.log
.expr
,
416 #if defined (DEBUG_EXPRESSIONS)
417 log_debug ("exec: log");
421 switch (r
-> data
.log
.priority
) {
422 case log_priority_fatal
:
423 log_fatal ("%.*s", (int)ds
.len
,
426 case log_priority_error
:
427 log_error ("%.*s", (int)ds
.len
,
430 case log_priority_debug
:
431 log_debug ("%.*s", (int)ds
.len
,
434 case log_priority_info
:
435 log_info ("%.*s", (int)ds
.len
,
439 data_string_forget (&ds
, MDL
);
445 log_error ("bogus statement type %d", r
-> op
);
448 executable_statement_dereference (&r
, MDL
);
450 executable_statement_reference (&r
, next
, MDL
);
451 executable_statement_dereference (&next
, MDL
);
458 /* Execute all the statements in a particular scope, and all statements in
459 scopes outer from that scope, but if a particular limiting scope is
460 reached, do not execute statements in that scope or in scopes outer
461 from it. More specific scopes need to take precedence over less
462 specific scopes, so we recursively traverse the scope list, executing
463 the most outer scope first. */
465 void execute_statements_in_scope (result
, packet
,
466 lease
, client_state
, in_options
, out_options
,
467 scope
, group
, limiting_group
)
468 struct binding_value
**result
;
469 struct packet
*packet
;
471 struct client_state
*client_state
;
472 struct option_state
*in_options
;
473 struct option_state
*out_options
;
474 struct binding_scope
**scope
;
476 struct group
*limiting_group
;
480 /* If we've recursed as far as we can, return. */
484 /* As soon as we get to a scope that is outer than the limiting
485 scope, we are done. This is so that if somebody does something
486 like this, it does the expected thing:
488 domain-name "fugue.com";
491 domain-name "othello.fugue.com";
492 fixed-address 10.20.30.40;
494 subnet 10.20.30.0 netmask 255.255.255.0 {
495 domain-name "manhattan.fugue.com";
499 The problem with the above arrangement is that the host's
500 group nesting will be host -> shared-network -> top-level,
501 and the limiting scope when we evaluate the host's scope
502 will be the subnet -> shared-network -> top-level, so we need
503 to know when we evaluate the host's scope to stop before we
504 evaluate the shared-networks scope, because it's outer than
505 the limiting scope, which means we've already evaluated it. */
507 for (limit
= limiting_group
; limit
; limit
= limit
-> next
) {
513 execute_statements_in_scope (result
, packet
,
515 in_options
, out_options
, scope
,
516 group
-> next
, limiting_group
);
517 execute_statements (result
, packet
, lease
, client_state
, in_options
,
518 out_options
, scope
, group
-> statements
);
521 /* Dereference or free any subexpressions of a statement being freed. */
523 int executable_statement_dereference (ptr
, file
, line
)
524 struct executable_statement
**ptr
;
528 // struct executable_statement *bp;
531 log_error ("%s(%d): null pointer", file
, line
);
532 #if defined (POINTER_DEBUG)
540 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
541 if ((*ptr
) -> refcnt
> 0) {
542 *ptr
= (struct executable_statement
*)0;
546 if ((*ptr
) -> refcnt
< 0) {
547 log_error ("%s(%d): negative refcnt!", file
, line
);
548 #if defined (DEBUG_RC_HISTORY)
549 dump_rc_history (*ptr
);
551 #if defined (POINTER_DEBUG)
559 executable_statement_dereference (&(*ptr
) -> next
, file
, line
);
561 switch ((*ptr
) -> op
) {
562 case statements_statement
:
563 if ((*ptr
) -> data
.statements
)
564 executable_statement_dereference
565 (&(*ptr
) -> data
.statements
, file
, line
);
569 if ((*ptr
) -> data
.on
.statements
)
570 executable_statement_dereference
571 (&(*ptr
) -> data
.on
.statements
, file
, line
);
574 case switch_statement
:
575 if ((*ptr
) -> data
.s_switch
.statements
)
576 executable_statement_dereference
577 (&(*ptr
) -> data
.on
.statements
, file
, line
);
578 if ((*ptr
) -> data
.s_switch
.expr
)
579 expression_dereference (&(*ptr
) -> data
.s_switch
.expr
,
584 if ((*ptr
) -> data
.s_switch
.expr
)
585 expression_dereference (&(*ptr
) -> data
.c_case
,
590 if ((*ptr
) -> data
.ie
.expr
)
591 expression_dereference (&(*ptr
) -> data
.ie
.expr
,
593 if ((*ptr
) -> data
.ie
.tc
)
594 executable_statement_dereference
595 (&(*ptr
) -> data
.ie
.tc
, file
, line
);
596 if ((*ptr
) -> data
.ie
.fc
)
597 executable_statement_dereference
598 (&(*ptr
) -> data
.ie
.fc
, file
, line
);
602 if ((*ptr
) -> data
.eval
)
603 expression_dereference (&(*ptr
) -> data
.eval
,
607 case return_statement
:
608 if ((*ptr
) -> data
.eval
)
609 expression_dereference (&(*ptr
) -> data
.eval
,
614 if ((*ptr
)->data
.set
.name
)
615 dfree ((*ptr
)->data
.set
.name
, file
, line
);
616 if ((*ptr
)->data
.set
.expr
)
617 expression_dereference (&(*ptr
) -> data
.set
.expr
,
621 case unset_statement
:
622 if ((*ptr
)->data
.unset
)
623 dfree ((*ptr
)->data
.unset
, file
, line
);
626 case supersede_option_statement
:
627 case send_option_statement
:
628 case default_option_statement
:
629 case append_option_statement
:
630 case prepend_option_statement
:
631 if ((*ptr
) -> data
.option
)
632 option_cache_dereference (&(*ptr
) -> data
.option
,
641 dfree ((*ptr
), file
, line
);
642 *ptr
= (struct executable_statement
*)0;
646 void write_statements (file
, statements
, indent
)
648 struct executable_statement
*statements
;
651 struct executable_statement
*r
, *x
;
654 const char *s
, *t
, *dot
;
660 for (r
= statements
; r
; r
= r
-> next
) {
662 case statements_statement
:
663 write_statements (file
, r
-> data
.statements
, indent
);
667 indent_spaces (file
, indent
);
668 fprintf (file
, "on ");
670 if (r
-> data
.on
.evtypes
& ON_EXPIRY
) {
671 fprintf (file
, "%sexpiry", s
);
674 if (r
-> data
.on
.evtypes
& ON_COMMIT
) {
675 fprintf (file
, "%scommit", s
);
678 if (r
-> data
.on
.evtypes
& ON_RELEASE
) {
679 fprintf (file
, "%srelease", s
);
682 if (r
-> data
.on
.statements
) {
683 fprintf (file
, " {");
684 write_statements (file
,
685 r
-> data
.on
.statements
,
687 indent_spaces (file
, indent
);
694 case switch_statement
:
695 indent_spaces (file
, indent
);
696 fprintf (file
, "switch (");
697 col
= write_expression (file
,
698 r
-> data
.s_switch
.expr
,
699 indent
+ 7, indent
+ 7, 1);
700 col
= token_print_indent (file
, col
, indent
+ 7,
702 token_print_indent (file
,
703 col
, indent
, " ", "", "{");
704 write_statements (file
, r
-> data
.s_switch
.statements
,
706 indent_spaces (file
, indent
);
711 indent_spaces (file
, indent
- 1);
712 fprintf (file
, "case ");
713 col
= write_expression (file
,
714 r
-> data
.s_switch
.expr
,
715 indent
+ 5, indent
+ 5, 1);
716 token_print_indent (file
, col
, indent
+ 5,
720 case default_statement
:
721 indent_spaces (file
, indent
- 1);
722 fprintf (file
, "default: ");
726 indent_spaces (file
, indent
);
727 fprintf (file
, "if ");
729 col
= write_expression (file
,
731 indent
+ 3, indent
+ 3, 1);
733 token_print_indent (file
, col
, indent
, " ", "", "{");
734 write_statements (file
, x
-> data
.ie
.tc
, indent
+ 2);
735 if (x
-> data
.ie
.fc
&&
736 x
-> data
.ie
.fc
-> op
== if_statement
&&
737 !x
-> data
.ie
.fc
-> next
) {
738 indent_spaces (file
, indent
);
739 fprintf (file
, "} elsif ");
741 col
= write_expression (file
,
747 if (x
-> data
.ie
.fc
) {
748 indent_spaces (file
, indent
);
749 fprintf (file
, "} else {");
750 write_statements (file
, x
-> data
.ie
.fc
,
753 indent_spaces (file
, indent
);
758 indent_spaces (file
, indent
);
759 fprintf (file
, "eval ");
760 col
= write_expression (file
, r
-> data
.eval
,
761 indent
+ 5, indent
+ 5, 1);
765 case return_statement
:
766 indent_spaces (file
, indent
);
767 fprintf (file
, "return;");
771 indent_spaces (file
, indent
);
772 fprintf (file
, "add \"%s\"", r
-> data
.add
-> name
);
775 case break_statement
:
776 indent_spaces (file
, indent
);
777 fprintf (file
, "break;");
780 case supersede_option_statement
:
781 case send_option_statement
:
783 goto option_statement
;
785 case default_option_statement
:
787 goto option_statement
;
789 case append_option_statement
:
791 goto option_statement
;
793 case prepend_option_statement
:
796 /* Note: the reason we don't try to pretty print
797 the option here is that the format of the option
798 may change in dhcpd.conf, and then when this
799 statement was read back, it would cause a syntax
801 if (r
-> data
.option
-> option
-> universe
==
806 t
= (r
-> data
.option
-> option
->
810 indent_spaces (file
, indent
);
811 fprintf (file
, "%s %s%s%s = ", s
, t
, dot
,
812 r
-> data
.option
-> option
-> name
);
813 col
= (indent
+ strlen (s
) + strlen (t
) +
814 strlen (dot
) + strlen (r
-> data
.option
->
815 option
-> name
) + 4);
816 if (r
-> data
.option
-> expression
)
819 r
-> data
.option
-> expression
,
822 token_indent_data_string
823 (file
, col
, indent
+ 8, "", "",
824 &r
-> data
.option
-> data
);
826 fprintf (file
, ";"); /* XXX */
830 indent_spaces (file
, indent
);
831 fprintf (file
, "set ");
832 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
833 "", "", r
-> data
.set
.name
);
834 col
= token_print_indent (file
, col
, indent
+ 4,
836 col
= write_expression (file
, r
-> data
.set
.expr
,
837 indent
+ 3, indent
+ 3, 0);
838 col
= token_print_indent (file
, col
, indent
+ 4,
842 case unset_statement
:
843 indent_spaces (file
, indent
);
844 fprintf (file
, "unset ");
845 col
= token_print_indent (file
, indent
+ 6, indent
+ 6,
846 "", "", r
-> data
.set
.name
);
847 col
= token_print_indent (file
, col
, indent
+ 6,
852 indent_spaces (file
, indent
);
853 fprintf (file
, "log ");
854 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
856 switch (r
-> data
.log
.priority
) {
857 case log_priority_fatal
:
858 col
= token_print_indent
859 (file
, col
, indent
+ 4, "",
862 case log_priority_error
:
863 col
= token_print_indent
864 (file
, col
, indent
+ 4, "",
867 case log_priority_debug
:
868 col
= token_print_indent
869 (file
, col
, indent
+ 4, "",
872 case log_priority_info
:
873 col
= token_print_indent
874 (file
, col
, indent
+ 4, "",
878 col
= write_expression (file
, r
-> data
.log
.expr
,
879 indent
+ 4, indent
+ 4, 0);
880 col
= token_print_indent (file
, col
, indent
+ 4,
886 log_fatal ("bogus statement type %d\n", r
-> op
);
891 /* Find a case statement in the sequence of executable statements that
892 matches the expression, and if found, return the following statement.
893 If no case statement matches, try to find a default statement and
894 return that (the default statement can precede all the case statements).
895 Otherwise, return the null statement. */
897 int find_matching_case (struct executable_statement
**ep
,
898 struct packet
*packet
, struct lease
*lease
,
899 struct client_state
*client_state
,
900 struct option_state
*in_options
,
901 struct option_state
*out_options
,
902 struct binding_scope
**scope
,
903 struct expression
*expr
,
904 struct executable_statement
*stmt
)
907 struct executable_statement
*s
;
908 // unsigned long foo;
910 if (is_data_expression (expr
)) {
911 // struct executable_statement *e;
912 struct data_string cd
, ds
;
913 memset (&ds
, 0, sizeof ds
);
914 memset (&cd
, 0, sizeof cd
);
916 status
= (evaluate_data_expression (&ds
, packet
, lease
,
917 client_state
, in_options
,
918 out_options
, scope
, expr
,
921 for (s
= stmt
; s
; s
= s
-> next
) {
922 if (s
-> op
== case_statement
) {
923 sub
= (evaluate_data_expression
924 (&cd
, packet
, lease
, client_state
,
925 in_options
, out_options
,
926 scope
, s
-> data
.c_case
, MDL
));
927 if (sub
&& cd
.len
== ds
.len
&&
928 !memcmp (cd
.data
, ds
.data
, cd
.len
))
930 data_string_forget (&cd
, MDL
);
931 data_string_forget (&ds
, MDL
);
932 executable_statement_reference
933 (ep
, s
-> next
, MDL
);
936 data_string_forget (&cd
, MDL
);
939 data_string_forget (&ds
, MDL
);
943 status
= evaluate_numeric_expression (&n
, packet
, lease
,
945 in_options
, out_options
,
949 for (s
= stmt
; s
; s
= s
-> next
) {
950 if (s
-> op
== case_statement
) {
951 sub
= (evaluate_numeric_expression
952 (&c
, packet
, lease
, client_state
,
953 in_options
, out_options
,
954 scope
, s
-> data
.c_case
));
956 executable_statement_reference
957 (ep
, s
-> next
, MDL
);
965 /* If we didn't find a matching case statement, look for a default
966 statement and return the statement following it. */
967 for (s
= stmt
; s
; s
= s
-> next
)
968 if (s
-> op
== default_statement
)
971 executable_statement_reference (ep
, s
-> next
, MDL
);
977 int executable_statement_foreach (struct executable_statement
*stmt
,
978 int (*callback
) (struct
979 executable_statement
*,
983 struct executable_statement
*foo
;
987 for (foo
= stmt
; foo
; foo
= foo
-> next
) {
988 if ((*callback
) (foo
, vp
, condp
) != 0)
994 if (executable_statement_foreach (foo
-> data
.ie
.tc
,
997 if (executable_statement_foreach (foo
-> data
.ie
.fc
,
1003 case eval_statement
:
1005 case break_statement
:
1007 case default_option_statement
:
1009 case supersede_option_statement
:
1011 case append_option_statement
:
1013 case prepend_option_statement
:
1015 case send_option_statement
:
1017 case statements_statement
:
1018 if ((executable_statement_foreach
1019 (foo
-> data
.statements
, callback
, vp
, condp
)))
1023 if ((executable_statement_foreach
1024 (foo
-> data
.on
.statements
, callback
, vp
, 1)))
1027 case switch_statement
:
1028 if ((executable_statement_foreach
1029 (foo
-> data
.s_switch
.statements
, callback
, vp
, 1)))
1032 case case_statement
:
1034 case default_statement
:
1038 case unset_statement
:
1041 if ((executable_statement_foreach
1042 (foo
-> data
.let
.statements
, callback
, vp
, 0)))
1045 case define_statement
:
1048 case return_statement
: