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 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
;
287 dfree (binding
, MDL
);
288 binding
= (struct binding
*)0;
293 if (binding
-> value
)
294 binding_value_dereference
295 (&binding
-> value
, MDL
);
296 if (r
-> op
== set_statement
) {
297 status
= (evaluate_expression
298 (&binding
-> value
, packet
,
300 in_options
, out_options
,
301 scope
, r
-> data
.set
.expr
,
304 if (!(binding_value_allocate
305 (&binding
-> value
, MDL
))) {
306 dfree (binding
, MDL
);
307 binding
= (struct binding
*)0;
309 if (binding
-> value
) {
310 binding
-> value
-> type
=
313 (&binding
-> value
-> value
.fundef
,
314 r
-> data
.set
.expr
-> data
.func
,
319 #if defined (DEBUG_EXPRESSIONS)
320 log_debug ("exec: set %s%s", r
-> data
.set
.name
,
321 (binding
&& status
? "" : " (failed)"));
325 case unset_statement
:
326 if (!scope
|| !*scope
) {
330 binding
= find_binding (*scope
, r
-> data
.unset
);
332 if (binding
-> value
)
333 binding_value_dereference
334 (&binding
-> value
, MDL
);
338 #if defined (DEBUG_EXPRESSIONS)
339 log_debug ("exec: unset %s: %s", r
-> data
.unset
,
340 (status
? "found" : "not found"));
345 #if defined (DEBUG_EXPRESSIONS)
346 log_debug ("exec: let %s", r
-> data
.let
.name
);
348 ns
= (struct binding_scope
*)0;
349 binding_scope_allocate (&ns
, MDL
);
354 binding
= dmalloc (sizeof *binding
, MDL
);
355 memset (binding
, 0, sizeof *binding
);
358 binding_scope_dereference (&ns
, MDL
);
362 (e
-> data
.let
.name
+ 1),
365 strcpy (binding
-> name
,
368 dfree (binding
, MDL
);
369 binding
= (struct binding
*)0;
377 status
= (evaluate_expression
378 (&binding
-> value
, packet
, lease
,
380 in_options
, out_options
,
381 scope
, e
-> data
.set
.expr
, MDL
));
382 binding
-> next
= ns
-> bindings
;
383 ns
-> bindings
= binding
;
386 #if defined (DEBUG_EXPRESSIONS)
387 log_debug ("exec: let %s%s", e
-> data
.let
.name
,
388 (binding
&& status
? "" : "failed"));
390 if (!e
-> data
.let
.statements
) {
391 } else if (e
-> data
.let
.statements
-> op
==
393 e
= e
-> data
.let
.statements
;
397 binding_scope_reference (&ns
-> outer
,
400 (result
, packet
, lease
,
402 in_options
, out_options
,
403 &ns
, e
-> data
.let
.statements
);
406 binding_scope_dereference (&ns
, MDL
);
410 memset (&ds
, 0, sizeof ds
);
411 status
= (evaluate_data_expression
413 lease
, client_state
, in_options
,
414 out_options
, scope
, r
-> data
.log
.expr
,
417 #if defined (DEBUG_EXPRESSIONS)
418 log_debug ("exec: log");
422 switch (r
-> data
.log
.priority
) {
423 case log_priority_fatal
:
424 log_fatal ("%.*s", (int)ds
.len
,
427 case log_priority_error
:
428 log_error ("%.*s", (int)ds
.len
,
431 case log_priority_debug
:
432 log_debug ("%.*s", (int)ds
.len
,
435 case log_priority_info
:
436 log_info ("%.*s", (int)ds
.len
,
440 data_string_forget (&ds
, MDL
);
446 log_error ("bogus statement type %d", r
-> op
);
449 executable_statement_dereference (&r
, MDL
);
451 executable_statement_reference (&r
, next
, MDL
);
452 executable_statement_dereference (&next
, MDL
);
459 /* Execute all the statements in a particular scope, and all statements in
460 scopes outer from that scope, but if a particular limiting scope is
461 reached, do not execute statements in that scope or in scopes outer
462 from it. More specific scopes need to take precedence over less
463 specific scopes, so we recursively traverse the scope list, executing
464 the most outer scope first. */
466 void execute_statements_in_scope (result
, packet
,
467 lease
, client_state
, in_options
, out_options
,
468 scope
, group
, limiting_group
)
469 struct binding_value
**result
;
470 struct packet
*packet
;
472 struct client_state
*client_state
;
473 struct option_state
*in_options
;
474 struct option_state
*out_options
;
475 struct binding_scope
**scope
;
477 struct group
*limiting_group
;
481 /* If we've recursed as far as we can, return. */
485 /* As soon as we get to a scope that is outer than the limiting
486 scope, we are done. This is so that if somebody does something
487 like this, it does the expected thing:
489 domain-name "fugue.com";
492 domain-name "othello.fugue.com";
493 fixed-address 10.20.30.40;
495 subnet 10.20.30.0 netmask 255.255.255.0 {
496 domain-name "manhattan.fugue.com";
500 The problem with the above arrangement is that the host's
501 group nesting will be host -> shared-network -> top-level,
502 and the limiting scope when we evaluate the host's scope
503 will be the subnet -> shared-network -> top-level, so we need
504 to know when we evaluate the host's scope to stop before we
505 evaluate the shared-networks scope, because it's outer than
506 the limiting scope, which means we've already evaluated it. */
508 for (limit
= limiting_group
; limit
; limit
= limit
-> next
) {
514 execute_statements_in_scope (result
, packet
,
516 in_options
, out_options
, scope
,
517 group
-> next
, limiting_group
);
518 execute_statements (result
, packet
, lease
, client_state
, in_options
,
519 out_options
, scope
, group
-> statements
);
522 /* Dereference or free any subexpressions of a statement being freed. */
524 int executable_statement_dereference (ptr
, file
, line
)
525 struct executable_statement
**ptr
;
529 struct executable_statement
*bp
;
532 log_error ("%s(%d): null pointer", file
, line
);
533 #if defined (POINTER_DEBUG)
541 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
542 if ((*ptr
) -> refcnt
> 0) {
543 *ptr
= (struct executable_statement
*)0;
547 if ((*ptr
) -> refcnt
< 0) {
548 log_error ("%s(%d): negative refcnt!", file
, line
);
549 #if defined (DEBUG_RC_HISTORY)
550 dump_rc_history (*ptr
);
552 #if defined (POINTER_DEBUG)
560 executable_statement_dereference (&(*ptr
) -> next
, file
, line
);
562 switch ((*ptr
) -> op
) {
563 case statements_statement
:
564 if ((*ptr
) -> data
.statements
)
565 executable_statement_dereference
566 (&(*ptr
) -> data
.statements
, file
, line
);
570 if ((*ptr
) -> data
.on
.statements
)
571 executable_statement_dereference
572 (&(*ptr
) -> data
.on
.statements
, file
, line
);
575 case switch_statement
:
576 if ((*ptr
) -> data
.s_switch
.statements
)
577 executable_statement_dereference
578 (&(*ptr
) -> data
.on
.statements
, file
, line
);
579 if ((*ptr
) -> data
.s_switch
.expr
)
580 expression_dereference (&(*ptr
) -> data
.s_switch
.expr
,
585 if ((*ptr
) -> data
.s_switch
.expr
)
586 expression_dereference (&(*ptr
) -> data
.c_case
,
591 if ((*ptr
) -> data
.ie
.expr
)
592 expression_dereference (&(*ptr
) -> data
.ie
.expr
,
594 if ((*ptr
) -> data
.ie
.tc
)
595 executable_statement_dereference
596 (&(*ptr
) -> data
.ie
.tc
, file
, line
);
597 if ((*ptr
) -> data
.ie
.fc
)
598 executable_statement_dereference
599 (&(*ptr
) -> data
.ie
.fc
, file
, line
);
603 if ((*ptr
) -> data
.eval
)
604 expression_dereference (&(*ptr
) -> data
.eval
,
608 case return_statement
:
609 if ((*ptr
) -> data
.eval
)
610 expression_dereference (&(*ptr
) -> data
.eval
,
615 if ((*ptr
)->data
.set
.name
)
616 dfree ((*ptr
)->data
.set
.name
, file
, line
);
617 if ((*ptr
)->data
.set
.expr
)
618 expression_dereference (&(*ptr
) -> data
.set
.expr
,
622 case unset_statement
:
623 if ((*ptr
)->data
.unset
)
624 dfree ((*ptr
)->data
.unset
, file
, line
);
627 case supersede_option_statement
:
628 case send_option_statement
:
629 case default_option_statement
:
630 case append_option_statement
:
631 case prepend_option_statement
:
632 if ((*ptr
) -> data
.option
)
633 option_cache_dereference (&(*ptr
) -> data
.option
,
642 dfree ((*ptr
), file
, line
);
643 *ptr
= (struct executable_statement
*)0;
647 void write_statements (file
, statements
, indent
)
649 struct executable_statement
*statements
;
652 struct executable_statement
*r
, *x
;
655 const char *s
, *t
, *dot
;
661 for (r
= statements
; r
; r
= r
-> next
) {
663 case statements_statement
:
664 write_statements (file
, r
-> data
.statements
, indent
);
668 indent_spaces (file
, indent
);
669 fprintf (file
, "on ");
671 if (r
-> data
.on
.evtypes
& ON_EXPIRY
) {
672 fprintf (file
, "%sexpiry", s
);
675 if (r
-> data
.on
.evtypes
& ON_COMMIT
) {
676 fprintf (file
, "%scommit", s
);
679 if (r
-> data
.on
.evtypes
& ON_RELEASE
) {
680 fprintf (file
, "%srelease", s
);
683 if (r
-> data
.on
.statements
) {
684 fprintf (file
, " {");
685 write_statements (file
,
686 r
-> data
.on
.statements
,
688 indent_spaces (file
, indent
);
695 case switch_statement
:
696 indent_spaces (file
, indent
);
697 fprintf (file
, "switch (");
698 col
= write_expression (file
,
699 r
-> data
.s_switch
.expr
,
700 indent
+ 7, indent
+ 7, 1);
701 col
= token_print_indent (file
, col
, indent
+ 7,
703 token_print_indent (file
,
704 col
, indent
, " ", "", "{");
705 write_statements (file
, r
-> data
.s_switch
.statements
,
707 indent_spaces (file
, indent
);
712 indent_spaces (file
, indent
- 1);
713 fprintf (file
, "case ");
714 col
= write_expression (file
,
715 r
-> data
.s_switch
.expr
,
716 indent
+ 5, indent
+ 5, 1);
717 token_print_indent (file
, col
, indent
+ 5,
721 case default_statement
:
722 indent_spaces (file
, indent
- 1);
723 fprintf (file
, "default: ");
727 indent_spaces (file
, indent
);
728 fprintf (file
, "if ");
730 col
= write_expression (file
,
732 indent
+ 3, indent
+ 3, 1);
734 token_print_indent (file
, col
, indent
, " ", "", "{");
735 write_statements (file
, x
-> data
.ie
.tc
, indent
+ 2);
736 if (x
-> data
.ie
.fc
&&
737 x
-> data
.ie
.fc
-> op
== if_statement
&&
738 !x
-> data
.ie
.fc
-> next
) {
739 indent_spaces (file
, indent
);
740 fprintf (file
, "} elsif ");
742 col
= write_expression (file
,
748 if (x
-> data
.ie
.fc
) {
749 indent_spaces (file
, indent
);
750 fprintf (file
, "} else {");
751 write_statements (file
, x
-> data
.ie
.fc
,
754 indent_spaces (file
, indent
);
759 indent_spaces (file
, indent
);
760 fprintf (file
, "eval ");
761 col
= write_expression (file
, r
-> data
.eval
,
762 indent
+ 5, indent
+ 5, 1);
766 case return_statement
:
767 indent_spaces (file
, indent
);
768 fprintf (file
, "return;");
772 indent_spaces (file
, indent
);
773 fprintf (file
, "add \"%s\"", r
-> data
.add
-> name
);
776 case break_statement
:
777 indent_spaces (file
, indent
);
778 fprintf (file
, "break;");
781 case supersede_option_statement
:
782 case send_option_statement
:
784 goto option_statement
;
786 case default_option_statement
:
788 goto option_statement
;
790 case append_option_statement
:
792 goto option_statement
;
794 case prepend_option_statement
:
797 /* Note: the reason we don't try to pretty print
798 the option here is that the format of the option
799 may change in dhcpd.conf, and then when this
800 statement was read back, it would cause a syntax
802 if (r
-> data
.option
-> option
-> universe
==
807 t
= (r
-> data
.option
-> option
->
811 indent_spaces (file
, indent
);
812 fprintf (file
, "%s %s%s%s = ", s
, t
, dot
,
813 r
-> data
.option
-> option
-> name
);
814 col
= (indent
+ strlen (s
) + strlen (t
) +
815 strlen (dot
) + strlen (r
-> data
.option
->
816 option
-> name
) + 4);
817 if (r
-> data
.option
-> expression
)
820 r
-> data
.option
-> expression
,
823 token_indent_data_string
824 (file
, col
, indent
+ 8, "", "",
825 &r
-> data
.option
-> data
);
827 fprintf (file
, ";"); /* XXX */
831 indent_spaces (file
, indent
);
832 fprintf (file
, "set ");
833 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
834 "", "", r
-> data
.set
.name
);
835 col
= token_print_indent (file
, col
, indent
+ 4,
837 col
= write_expression (file
, r
-> data
.set
.expr
,
838 indent
+ 3, indent
+ 3, 0);
839 col
= token_print_indent (file
, col
, indent
+ 4,
843 case unset_statement
:
844 indent_spaces (file
, indent
);
845 fprintf (file
, "unset ");
846 col
= token_print_indent (file
, indent
+ 6, indent
+ 6,
847 "", "", r
-> data
.set
.name
);
848 col
= token_print_indent (file
, col
, indent
+ 6,
853 indent_spaces (file
, indent
);
854 fprintf (file
, "log ");
855 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
857 switch (r
-> data
.log
.priority
) {
858 case log_priority_fatal
:
859 col
= token_print_indent
860 (file
, col
, indent
+ 4, "",
863 case log_priority_error
:
864 col
= token_print_indent
865 (file
, col
, indent
+ 4, "",
868 case log_priority_debug
:
869 col
= token_print_indent
870 (file
, col
, indent
+ 4, "",
873 case log_priority_info
:
874 col
= token_print_indent
875 (file
, col
, indent
+ 4, "",
879 col
= write_expression (file
, r
-> data
.log
.expr
,
880 indent
+ 4, indent
+ 4, 0);
881 col
= token_print_indent (file
, col
, indent
+ 4,
887 log_fatal ("bogus statement type %d\n", r
-> op
);
892 /* Find a case statement in the sequence of executable statements that
893 matches the expression, and if found, return the following statement.
894 If no case statement matches, try to find a default statement and
895 return that (the default statement can precede all the case statements).
896 Otherwise, return the null statement. */
898 int find_matching_case (struct executable_statement
**ep
,
899 struct packet
*packet
, struct lease
*lease
,
900 struct client_state
*client_state
,
901 struct option_state
*in_options
,
902 struct option_state
*out_options
,
903 struct binding_scope
**scope
,
904 struct expression
*expr
,
905 struct executable_statement
*stmt
)
908 struct executable_statement
*s
;
911 if (is_data_expression (expr
)) {
912 struct executable_statement
*e
;
913 struct data_string cd
, ds
;
914 memset (&ds
, 0, sizeof ds
);
915 memset (&cd
, 0, sizeof cd
);
917 status
= (evaluate_data_expression (&ds
, packet
, lease
,
918 client_state
, in_options
,
919 out_options
, scope
, expr
,
922 for (s
= stmt
; s
; s
= s
-> next
) {
923 if (s
-> op
== case_statement
) {
924 sub
= (evaluate_data_expression
925 (&cd
, packet
, lease
, client_state
,
926 in_options
, out_options
,
927 scope
, s
-> data
.c_case
, MDL
));
928 if (sub
&& cd
.len
== ds
.len
&&
929 !memcmp (cd
.data
, ds
.data
, cd
.len
))
931 data_string_forget (&cd
, MDL
);
932 data_string_forget (&ds
, MDL
);
933 executable_statement_reference
934 (ep
, s
-> next
, MDL
);
937 data_string_forget (&cd
, MDL
);
940 data_string_forget (&ds
, MDL
);
944 status
= evaluate_numeric_expression (&n
, packet
, lease
,
946 in_options
, out_options
,
950 for (s
= stmt
; s
; s
= s
-> next
) {
951 if (s
-> op
== case_statement
) {
952 sub
= (evaluate_numeric_expression
953 (&c
, packet
, lease
, client_state
,
954 in_options
, out_options
,
955 scope
, s
-> data
.c_case
));
957 executable_statement_reference
958 (ep
, s
-> next
, MDL
);
966 /* If we didn't find a matching case statement, look for a default
967 statement and return the statement following it. */
968 for (s
= stmt
; s
; s
= s
-> next
)
969 if (s
-> op
== default_statement
)
972 executable_statement_reference (ep
, s
-> next
, MDL
);
978 int executable_statement_foreach (struct executable_statement
*stmt
,
979 int (*callback
) (struct
980 executable_statement
*,
984 struct executable_statement
*foo
;
988 for (foo
= stmt
; foo
; foo
= foo
-> next
) {
989 if ((*callback
) (foo
, vp
, condp
) != 0)
995 if (executable_statement_foreach (foo
-> data
.ie
.tc
,
998 if (executable_statement_foreach (foo
-> data
.ie
.fc
,
1004 case eval_statement
:
1006 case break_statement
:
1008 case default_option_statement
:
1010 case supersede_option_statement
:
1012 case append_option_statement
:
1014 case prepend_option_statement
:
1016 case send_option_statement
:
1018 case statements_statement
:
1019 if ((executable_statement_foreach
1020 (foo
-> data
.statements
, callback
, vp
, condp
)))
1024 if ((executable_statement_foreach
1025 (foo
-> data
.on
.statements
, callback
, vp
, 1)))
1028 case switch_statement
:
1029 if ((executable_statement_foreach
1030 (foo
-> data
.s_switch
.statements
, callback
, vp
, 1)))
1033 case case_statement
:
1035 case default_statement
:
1039 case unset_statement
:
1042 if ((executable_statement_foreach
1043 (foo
-> data
.let
.statements
, callback
, vp
, 0)))
1046 case define_statement
:
1049 case return_statement
: