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: execute.c,v 1.7 2005/08/11 17:13:21 drochner Exp $ 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
;
57 struct binding
*binding
;
58 struct data_string ds
;
59 struct binding_scope
*ns
;
64 r
= (struct executable_statement
*)0;
65 next
= (struct executable_statement
*)0;
66 e
= (struct executable_statement
*)0;
67 executable_statement_reference (&r
, statements
, MDL
);
68 while (r
&& !(result
&& *result
)) {
70 executable_statement_reference (&next
, r
-> next
, MDL
);
72 case statements_statement
:
73 #if defined (DEBUG_EXPRESSIONS)
74 log_debug ("exec: statements");
76 status
= execute_statements (result
, packet
, lease
,
77 client_state
, in_options
,
79 r
-> data
.statements
);
80 #if defined (DEBUG_EXPRESSIONS)
81 log_debug ("exec: statements returns %d", status
);
89 if (r
-> data
.on
.evtypes
& ON_EXPIRY
) {
90 #if defined (DEBUG_EXPRESSIONS)
91 log_debug ("exec: on expiry");
93 if (lease
-> on_expiry
)
94 executable_statement_dereference
95 (&lease
-> on_expiry
, MDL
);
96 if (r
-> data
.on
.statements
)
97 executable_statement_reference
99 r
-> data
.on
.statements
, MDL
);
101 if (r
-> data
.on
.evtypes
& ON_RELEASE
) {
102 #if defined (DEBUG_EXPRESSIONS)
103 log_debug ("exec: on release");
105 if (lease
-> on_release
)
106 executable_statement_dereference
107 (&lease
-> on_release
, MDL
);
108 if (r
-> data
.on
.statements
)
109 executable_statement_reference
110 (&lease
-> on_release
,
111 r
-> data
.on
.statements
, MDL
);
113 if (r
-> data
.on
.evtypes
& ON_COMMIT
) {
114 #if defined (DEBUG_EXPRESSIONS)
115 log_debug ("exec: on commit");
117 if (lease
-> on_commit
)
118 executable_statement_dereference
119 (&lease
-> on_commit
, MDL
);
120 if (r
-> data
.on
.statements
)
121 executable_statement_reference
122 (&lease
-> on_commit
,
123 r
-> data
.on
.statements
, MDL
);
128 case switch_statement
:
129 #if defined (DEBUG_EXPRESSIONS)
130 log_debug ("exec: switch");
132 status
= (find_matching_case
133 (&e
, packet
, lease
, client_state
,
134 in_options
, out_options
, scope
,
135 r
-> data
.s_switch
.expr
,
136 r
-> data
.s_switch
.statements
));
137 #if defined (DEBUG_EXPRESSIONS)
138 log_debug ("exec: switch: case %lx", (unsigned long)e
);
141 if (!(execute_statements
142 (result
, packet
, lease
, client_state
,
143 in_options
, out_options
, scope
, e
))) {
144 executable_statement_dereference
148 executable_statement_dereference (&e
, MDL
);
152 /* These have no effect when executed. */
154 case default_statement
:
158 status
= (evaluate_boolean_expression
160 lease
, client_state
, in_options
,
161 out_options
, scope
, r
-> data
.ie
.expr
));
163 #if defined (DEBUG_EXPRESSIONS)
164 log_debug ("exec: if %s", (status
165 ? (rc
? "true" : "false")
168 /* XXX Treat NULL as false */
171 if (!execute_statements
172 (result
, packet
, lease
, client_state
,
173 in_options
, out_options
, scope
,
174 rc
? r
-> data
.ie
.tc
: r
-> data
.ie
.fc
))
179 status
= evaluate_expression
180 ((struct binding_value
**)0,
181 packet
, lease
, client_state
, in_options
,
182 out_options
, scope
, r
-> data
.eval
, MDL
);
183 #if defined (DEBUG_EXPRESSIONS)
184 log_debug ("exec: evaluate: %s",
185 (status
? "succeeded" : "failed"));
189 case return_statement
:
190 status
= evaluate_expression
192 lease
, client_state
, in_options
,
193 out_options
, scope
, r
-> data
.retval
, MDL
);
194 #if defined (DEBUG_EXPRESSIONS)
195 log_debug ("exec: return: %s",
196 (status
? "succeeded" : "failed"));
201 #if defined (DEBUG_EXPRESSIONS)
202 log_debug ("exec: add %s", (r
-> data
.add
-> name
203 ? r
-> data
.add
-> name
204 : "<unnamed class>"));
206 classify (packet
, r
-> data
.add
);
209 case break_statement
:
210 #if defined (DEBUG_EXPRESSIONS)
211 log_debug ("exec: break");
215 case supersede_option_statement
:
216 case send_option_statement
:
217 #if defined (DEBUG_EXPRESSIONS)
218 log_debug ("exec: %s option %s.%s",
219 (r
-> op
== supersede_option_statement
220 ? "supersede" : "send"),
221 r
-> data
.option
-> option
-> universe
-> name
,
222 r
-> data
.option
-> option
-> name
);
223 goto option_statement
;
225 case default_option_statement
:
226 #if defined (DEBUG_EXPRESSIONS)
227 log_debug ("exec: default option %s.%s",
228 r
-> data
.option
-> option
-> universe
-> name
,
229 r
-> data
.option
-> option
-> name
);
230 goto option_statement
;
232 case append_option_statement
:
233 #if defined (DEBUG_EXPRESSIONS)
234 log_debug ("exec: append option %s.%s",
235 r
-> data
.option
-> option
-> universe
-> name
,
236 r
-> data
.option
-> option
-> name
);
237 goto option_statement
;
239 case prepend_option_statement
:
240 #if defined (DEBUG_EXPRESSIONS)
241 log_debug ("exec: prepend option %s.%s",
242 r
-> data
.option
-> option
-> universe
-> name
,
243 r
-> data
.option
-> option
-> name
);
246 set_option (r
-> data
.option
-> option
-> universe
,
247 out_options
, r
-> data
.option
, r
-> op
);
251 case define_statement
:
253 log_error ("set %s: no scope",
259 if (!binding_scope_allocate (scope
, MDL
)) {
260 log_error ("set %s: can't allocate scope",
266 binding
= find_binding (*scope
, r
-> data
.set
.name
);
267 #if defined (DEBUG_EXPRESSIONS)
268 log_debug ("exec: set %s", r
-> data
.set
.name
);
271 binding
= dmalloc (sizeof *binding
, MDL
);
273 memset (binding
, 0, sizeof *binding
);
276 (r
-> data
.set
.name
) + 1,
278 if (binding
-> name
) {
279 strcpy (binding
-> name
,
281 binding
-> next
= (*scope
) -> bindings
;
282 (*scope
) -> bindings
= binding
;
284 dfree (binding
, MDL
);
285 binding
= (struct binding
*)0;
290 if (binding
-> value
)
291 binding_value_dereference
292 (&binding
-> value
, MDL
);
293 if (r
-> op
== set_statement
) {
294 status
= (evaluate_expression
295 (&binding
-> value
, packet
,
297 in_options
, out_options
,
298 scope
, r
-> data
.set
.expr
,
301 if (!(binding_value_allocate
302 (&binding
-> value
, MDL
))) {
303 dfree (binding
, MDL
);
304 binding
= (struct binding
*)0;
306 if (binding
-> value
) {
307 binding
-> value
-> type
=
310 (&binding
-> value
-> value
.fundef
,
311 r
-> data
.set
.expr
-> data
.func
,
316 #if defined (DEBUG_EXPRESSIONS)
317 log_debug ("exec: set %s%s", r
-> data
.set
.name
,
318 (binding
&& status
? "" : " (failed)"));
322 case unset_statement
:
323 if (!scope
|| !*scope
) {
327 binding
= find_binding (*scope
, r
-> data
.unset
);
329 if (binding
-> value
)
330 binding_value_dereference
331 (&binding
-> value
, MDL
);
335 #if defined (DEBUG_EXPRESSIONS)
336 log_debug ("exec: unset %s: %s", r
-> data
.unset
,
337 (status
? "found" : "not found"));
342 #if defined (DEBUG_EXPRESSIONS)
343 log_debug ("exec: let %s", r
-> data
.let
.name
);
345 ns
= (struct binding_scope
*)0;
346 binding
= (struct binding
*)0;
347 binding_scope_allocate (&ns
, MDL
);
352 binding
= dmalloc (sizeof *binding
, MDL
);
353 memset (binding
, 0, sizeof *binding
);
356 binding_scope_dereference (&ns
, MDL
);
360 (e
-> data
.let
.name
+ 1),
363 strcpy (binding
-> name
,
366 dfree (binding
, MDL
);
367 binding
= (struct binding
*)0;
375 status
= (evaluate_expression
376 (&binding
-> value
, packet
, lease
,
378 in_options
, out_options
,
379 scope
, e
-> data
.set
.expr
, MDL
));
380 binding
-> next
= ns
-> bindings
;
381 ns
-> bindings
= binding
;
384 #if defined (DEBUG_EXPRESSIONS)
385 log_debug ("exec: let %s%s", e
-> data
.let
.name
,
386 (binding
&& status
? "" : "failed"));
388 if (!e
-> data
.let
.statements
) {
389 } else if (e
-> data
.let
.statements
-> op
==
391 e
= e
-> data
.let
.statements
;
395 binding_scope_reference (&ns
-> outer
,
398 (result
, packet
, lease
,
400 in_options
, out_options
,
401 &ns
, e
-> data
.let
.statements
);
404 binding_scope_dereference (&ns
, MDL
);
408 memset (&ds
, 0, sizeof ds
);
409 status
= (evaluate_data_expression
411 lease
, client_state
, in_options
,
412 out_options
, scope
, r
-> data
.log
.expr
,
415 #if defined (DEBUG_EXPRESSIONS)
416 log_debug ("exec: log");
420 switch (r
-> data
.log
.priority
) {
421 case log_priority_fatal
:
422 log_fatal ("%.*s", (int)ds
.len
,
425 case log_priority_error
:
426 log_error ("%.*s", (int)ds
.len
,
429 case log_priority_debug
:
430 log_debug ("%.*s", (int)ds
.len
,
433 case log_priority_info
:
434 log_info ("%.*s", (int)ds
.len
,
438 data_string_forget (&ds
, MDL
);
444 log_error ("bogus statement type %d", r
-> op
);
447 executable_statement_dereference (&r
, MDL
);
449 executable_statement_reference (&r
, next
, MDL
);
450 executable_statement_dereference (&next
, MDL
);
457 /* Execute all the statements in a particular scope, and all statements in
458 scopes outer from that scope, but if a particular limiting scope is
459 reached, do not execute statements in that scope or in scopes outer
460 from it. More specific scopes need to take precedence over less
461 specific scopes, so we recursively traverse the scope list, executing
462 the most outer scope first. */
464 void execute_statements_in_scope (result
, packet
,
465 lease
, client_state
, in_options
, out_options
,
466 scope
, group
, limiting_group
)
467 struct binding_value
**result
;
468 struct packet
*packet
;
470 struct client_state
*client_state
;
471 struct option_state
*in_options
;
472 struct option_state
*out_options
;
473 struct binding_scope
**scope
;
475 struct group
*limiting_group
;
479 /* If we've recursed as far as we can, return. */
483 /* As soon as we get to a scope that is outer than the limiting
484 scope, we are done. This is so that if somebody does something
485 like this, it does the expected thing:
487 domain-name "fugue.com";
490 domain-name "othello.fugue.com";
491 fixed-address 10.20.30.40;
493 subnet 10.20.30.0 netmask 255.255.255.0 {
494 domain-name "manhattan.fugue.com";
498 The problem with the above arrangement is that the host's
499 group nesting will be host -> shared-network -> top-level,
500 and the limiting scope when we evaluate the host's scope
501 will be the subnet -> shared-network -> top-level, so we need
502 to know when we evaluate the host's scope to stop before we
503 evaluate the shared-networks scope, because it's outer than
504 the limiting scope, which means we've already evaluated it. */
506 for (limit
= limiting_group
; limit
; limit
= limit
-> next
) {
512 execute_statements_in_scope (result
, packet
,
514 in_options
, out_options
, scope
,
515 group
-> next
, limiting_group
);
516 execute_statements (result
, packet
, lease
, client_state
, in_options
,
517 out_options
, scope
, group
-> statements
);
520 /* Dereference or free any subexpressions of a statement being freed. */
522 int executable_statement_dereference (ptr
, file
, line
)
523 struct executable_statement
**ptr
;
529 log_error ("%s(%d): null pointer", file
, line
);
530 #if defined (POINTER_DEBUG)
538 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
539 if ((*ptr
) -> refcnt
> 0) {
540 *ptr
= (struct executable_statement
*)0;
544 if ((*ptr
) -> refcnt
< 0) {
545 log_error ("%s(%d): negative refcnt!", file
, line
);
546 #if defined (DEBUG_RC_HISTORY)
547 dump_rc_history (*ptr
);
549 #if defined (POINTER_DEBUG)
557 executable_statement_dereference (&(*ptr
) -> next
, file
, line
);
559 switch ((*ptr
) -> op
) {
560 case statements_statement
:
561 if ((*ptr
) -> data
.statements
)
562 executable_statement_dereference
563 (&(*ptr
) -> data
.statements
, file
, line
);
567 if ((*ptr
) -> data
.on
.statements
)
568 executable_statement_dereference
569 (&(*ptr
) -> data
.on
.statements
, file
, line
);
572 case switch_statement
:
573 if ((*ptr
) -> data
.s_switch
.statements
)
574 executable_statement_dereference
575 (&(*ptr
) -> data
.on
.statements
, file
, line
);
576 if ((*ptr
) -> data
.s_switch
.expr
)
577 expression_dereference (&(*ptr
) -> data
.s_switch
.expr
,
582 if ((*ptr
) -> data
.s_switch
.expr
)
583 expression_dereference (&(*ptr
) -> data
.c_case
,
588 if ((*ptr
) -> data
.ie
.expr
)
589 expression_dereference (&(*ptr
) -> data
.ie
.expr
,
591 if ((*ptr
) -> data
.ie
.tc
)
592 executable_statement_dereference
593 (&(*ptr
) -> data
.ie
.tc
, file
, line
);
594 if ((*ptr
) -> data
.ie
.fc
)
595 executable_statement_dereference
596 (&(*ptr
) -> data
.ie
.fc
, file
, line
);
600 if ((*ptr
) -> data
.eval
)
601 expression_dereference (&(*ptr
) -> data
.eval
,
605 case return_statement
:
606 if ((*ptr
) -> data
.eval
)
607 expression_dereference (&(*ptr
) -> data
.eval
,
612 if ((*ptr
)->data
.set
.name
)
613 dfree ((*ptr
)->data
.set
.name
, file
, line
);
614 if ((*ptr
)->data
.set
.expr
)
615 expression_dereference (&(*ptr
) -> data
.set
.expr
,
619 case unset_statement
:
620 if ((*ptr
)->data
.unset
)
621 dfree ((*ptr
)->data
.unset
, file
, line
);
624 case supersede_option_statement
:
625 case send_option_statement
:
626 case default_option_statement
:
627 case append_option_statement
:
628 case prepend_option_statement
:
629 if ((*ptr
) -> data
.option
)
630 option_cache_dereference (&(*ptr
) -> data
.option
,
639 dfree ((*ptr
), file
, line
);
640 *ptr
= (struct executable_statement
*)0;
644 void write_statements (file
, statements
, indent
)
646 struct executable_statement
*statements
;
649 struct executable_statement
*r
, *x
;
650 const char *s
, *t
, *dot
;
656 col
= 0; /* XXXGCC -Wuninitialized */
658 for (r
= statements
; r
; r
= r
-> next
) {
660 case statements_statement
:
661 write_statements (file
, r
-> data
.statements
, indent
);
665 indent_spaces (file
, indent
);
666 fprintf (file
, "on ");
668 if (r
-> data
.on
.evtypes
& ON_EXPIRY
) {
669 fprintf (file
, "%sexpiry", s
);
672 if (r
-> data
.on
.evtypes
& ON_COMMIT
) {
673 fprintf (file
, "%scommit", s
);
676 if (r
-> data
.on
.evtypes
& ON_RELEASE
) {
677 fprintf (file
, "%srelease", s
);
680 if (r
-> data
.on
.statements
) {
681 fprintf (file
, " {");
682 write_statements (file
,
683 r
-> data
.on
.statements
,
685 indent_spaces (file
, indent
);
692 case switch_statement
:
693 indent_spaces (file
, indent
);
694 fprintf (file
, "switch (");
695 col
= write_expression (file
,
696 r
-> data
.s_switch
.expr
,
697 indent
+ 7, indent
+ 7, 1);
698 col
= token_print_indent (file
, col
, indent
+ 7,
700 token_print_indent (file
,
701 col
, indent
, " ", "", "{");
702 write_statements (file
, r
-> data
.s_switch
.statements
,
704 indent_spaces (file
, indent
);
709 indent_spaces (file
, indent
- 1);
710 fprintf (file
, "case ");
711 col
= write_expression (file
,
712 r
-> data
.s_switch
.expr
,
713 indent
+ 5, indent
+ 5, 1);
714 token_print_indent (file
, col
, indent
+ 5,
718 case default_statement
:
719 indent_spaces (file
, indent
- 1);
720 fprintf (file
, "default: ");
724 indent_spaces (file
, indent
);
725 fprintf (file
, "if ");
727 col
= write_expression (file
,
729 indent
+ 3, indent
+ 3, 1);
731 token_print_indent (file
, col
, indent
, " ", "", "{");
732 write_statements (file
, x
-> data
.ie
.tc
, indent
+ 2);
733 if (x
-> data
.ie
.fc
&&
734 x
-> data
.ie
.fc
-> op
== if_statement
&&
735 !x
-> data
.ie
.fc
-> next
) {
736 indent_spaces (file
, indent
);
737 fprintf (file
, "} elsif ");
739 col
= write_expression (file
,
745 if (x
-> data
.ie
.fc
) {
746 indent_spaces (file
, indent
);
747 fprintf (file
, "} else {");
748 write_statements (file
, x
-> data
.ie
.fc
,
751 indent_spaces (file
, indent
);
756 indent_spaces (file
, indent
);
757 fprintf (file
, "eval ");
758 col
= write_expression (file
, r
-> data
.eval
,
759 indent
+ 5, indent
+ 5, 1);
763 case return_statement
:
764 indent_spaces (file
, indent
);
765 fprintf (file
, "return;");
769 indent_spaces (file
, indent
);
770 fprintf (file
, "add \"%s\"", r
-> data
.add
-> name
);
773 case break_statement
:
774 indent_spaces (file
, indent
);
775 fprintf (file
, "break;");
778 case supersede_option_statement
:
779 case send_option_statement
:
781 goto option_statement
;
783 case default_option_statement
:
785 goto option_statement
;
787 case append_option_statement
:
789 goto option_statement
;
791 case prepend_option_statement
:
794 /* Note: the reason we don't try to pretty print
795 the option here is that the format of the option
796 may change in dhcpd.conf, and then when this
797 statement was read back, it would cause a syntax
799 if (r
-> data
.option
-> option
-> universe
==
804 t
= (r
-> data
.option
-> option
->
808 indent_spaces (file
, indent
);
809 fprintf (file
, "%s %s%s%s = ", s
, t
, dot
,
810 r
-> data
.option
-> option
-> name
);
811 col
= (indent
+ strlen (s
) + strlen (t
) +
812 strlen (dot
) + strlen (r
-> data
.option
->
813 option
-> name
) + 4);
814 if (r
-> data
.option
-> expression
)
817 r
-> data
.option
-> expression
,
820 token_indent_data_string
821 (file
, col
, indent
+ 8, "", "",
822 &r
-> data
.option
-> data
);
824 fprintf (file
, ";"); /* XXX */
828 indent_spaces (file
, indent
);
829 fprintf (file
, "set ");
830 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
831 "", "", r
-> data
.set
.name
);
832 col
= token_print_indent (file
, col
, indent
+ 4,
834 col
= write_expression (file
, r
-> data
.set
.expr
,
835 indent
+ 3, indent
+ 3, 0);
836 col
= token_print_indent (file
, col
, indent
+ 4,
840 case unset_statement
:
841 indent_spaces (file
, indent
);
842 fprintf (file
, "unset ");
843 col
= token_print_indent (file
, indent
+ 6, indent
+ 6,
844 "", "", r
-> data
.set
.name
);
845 col
= token_print_indent (file
, col
, indent
+ 6,
850 indent_spaces (file
, indent
);
851 fprintf (file
, "log ");
852 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
854 switch (r
-> data
.log
.priority
) {
855 case log_priority_fatal
:
856 col
= token_print_indent
857 (file
, col
, indent
+ 4, "",
860 case log_priority_error
:
861 col
= token_print_indent
862 (file
, col
, indent
+ 4, "",
865 case log_priority_debug
:
866 col
= token_print_indent
867 (file
, col
, indent
+ 4, "",
870 case log_priority_info
:
871 col
= token_print_indent
872 (file
, col
, indent
+ 4, "",
876 col
= write_expression (file
, r
-> data
.log
.expr
,
877 indent
+ 4, indent
+ 4, 0);
878 col
= token_print_indent (file
, col
, indent
+ 4,
884 log_fatal ("bogus statement type %d\n", r
-> op
);
889 /* Find a case statement in the sequence of executable statements that
890 matches the expression, and if found, return the following statement.
891 If no case statement matches, try to find a default statement and
892 return that (the default statement can precede all the case statements).
893 Otherwise, return the null statement. */
895 int find_matching_case (struct executable_statement
**ep
,
896 struct packet
*packet
, struct lease
*lease
,
897 struct client_state
*client_state
,
898 struct option_state
*in_options
,
899 struct option_state
*out_options
,
900 struct binding_scope
**scope
,
901 struct expression
*expr
,
902 struct executable_statement
*stmt
)
905 struct executable_statement
*s
;
907 if (is_data_expression (expr
)) {
908 struct data_string cd
, ds
;
909 memset (&ds
, 0, sizeof ds
);
910 memset (&cd
, 0, sizeof cd
);
912 status
= (evaluate_data_expression (&ds
, packet
, lease
,
913 client_state
, in_options
,
914 out_options
, scope
, expr
,
917 for (s
= stmt
; s
; s
= s
-> next
) {
918 if (s
-> op
== case_statement
) {
919 sub
= (evaluate_data_expression
920 (&cd
, packet
, lease
, client_state
,
921 in_options
, out_options
,
922 scope
, s
-> data
.c_case
, MDL
));
923 if (sub
&& cd
.len
== ds
.len
&&
924 !memcmp (cd
.data
, ds
.data
, cd
.len
))
926 data_string_forget (&cd
, MDL
);
927 data_string_forget (&ds
, MDL
);
928 executable_statement_reference
929 (ep
, s
-> next
, MDL
);
932 data_string_forget (&cd
, MDL
);
935 data_string_forget (&ds
, MDL
);
939 status
= evaluate_numeric_expression (&n
, packet
, lease
,
941 in_options
, out_options
,
945 for (s
= stmt
; s
; s
= s
-> next
) {
946 if (s
-> op
== case_statement
) {
947 sub
= (evaluate_numeric_expression
948 (&c
, packet
, lease
, client_state
,
949 in_options
, out_options
,
950 scope
, s
-> data
.c_case
));
952 executable_statement_reference
953 (ep
, s
-> next
, MDL
);
961 /* If we didn't find a matching case statement, look for a default
962 statement and return the statement following it. */
963 for (s
= stmt
; s
; s
= s
-> next
)
964 if (s
-> op
== default_statement
)
967 executable_statement_reference (ep
, s
-> next
, MDL
);
973 int executable_statement_foreach (struct executable_statement
*stmt
,
974 int (*callback
) (struct
975 executable_statement
*,
979 struct executable_statement
*foo
;
982 for (foo
= stmt
; foo
; foo
= foo
-> next
) {
983 if ((*callback
) (foo
, vp
, condp
) != 0)
989 if (executable_statement_foreach (foo
-> data
.ie
.tc
,
992 if (executable_statement_foreach (foo
-> data
.ie
.fc
,
1000 case break_statement
:
1002 case default_option_statement
:
1004 case supersede_option_statement
:
1006 case append_option_statement
:
1008 case prepend_option_statement
:
1010 case send_option_statement
:
1012 case statements_statement
:
1013 if ((executable_statement_foreach
1014 (foo
-> data
.statements
, callback
, vp
, condp
)))
1018 if ((executable_statement_foreach
1019 (foo
-> data
.on
.statements
, callback
, vp
, 1)))
1022 case switch_statement
:
1023 if ((executable_statement_foreach
1024 (foo
-> data
.s_switch
.statements
, callback
, vp
, 1)))
1027 case case_statement
:
1029 case default_statement
:
1033 case unset_statement
:
1036 if ((executable_statement_foreach
1037 (foo
-> data
.let
.statements
, callback
, vp
, 0)))
1040 case define_statement
:
1043 case return_statement
: