1*83ee113eSDavid van Moolenbroek /* $NetBSD: execute.c,v 1.1.1.3 2014/07/12 11:57:44 spz Exp $ */
2*83ee113eSDavid van Moolenbroek /* execute.c
3*83ee113eSDavid van Moolenbroek
4*83ee113eSDavid van Moolenbroek Support for executable statements. */
5*83ee113eSDavid van Moolenbroek
6*83ee113eSDavid van Moolenbroek /*
7*83ee113eSDavid van Moolenbroek * Copyright (c) 2009,2013,2014 by Internet Systems Consortium, Inc. ("ISC")
8*83ee113eSDavid van Moolenbroek * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
9*83ee113eSDavid van Moolenbroek * Copyright (c) 1998-2003 by Internet Software Consortium
10*83ee113eSDavid van Moolenbroek *
11*83ee113eSDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any
12*83ee113eSDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
13*83ee113eSDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
14*83ee113eSDavid van Moolenbroek *
15*83ee113eSDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16*83ee113eSDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17*83ee113eSDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18*83ee113eSDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19*83ee113eSDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20*83ee113eSDavid van Moolenbroek * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21*83ee113eSDavid van Moolenbroek * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22*83ee113eSDavid van Moolenbroek *
23*83ee113eSDavid van Moolenbroek * Internet Systems Consortium, Inc.
24*83ee113eSDavid van Moolenbroek * 950 Charter Street
25*83ee113eSDavid van Moolenbroek * Redwood City, CA 94063
26*83ee113eSDavid van Moolenbroek * <info@isc.org>
27*83ee113eSDavid van Moolenbroek * https://www.isc.org/
28*83ee113eSDavid van Moolenbroek *
29*83ee113eSDavid van Moolenbroek */
30*83ee113eSDavid van Moolenbroek
31*83ee113eSDavid van Moolenbroek #include <sys/cdefs.h>
32*83ee113eSDavid van Moolenbroek __RCSID("$NetBSD: execute.c,v 1.1.1.3 2014/07/12 11:57:44 spz Exp $");
33*83ee113eSDavid van Moolenbroek
34*83ee113eSDavid van Moolenbroek #include "dhcpd.h"
35*83ee113eSDavid van Moolenbroek #include <omapip/omapip_p.h>
36*83ee113eSDavid van Moolenbroek #include <sys/types.h>
37*83ee113eSDavid van Moolenbroek #include <sys/wait.h>
38*83ee113eSDavid van Moolenbroek
execute_statements(result,packet,lease,client_state,in_options,out_options,scope,statements,on_star)39*83ee113eSDavid van Moolenbroek int execute_statements (result, packet, lease, client_state,
40*83ee113eSDavid van Moolenbroek in_options, out_options, scope, statements,
41*83ee113eSDavid van Moolenbroek on_star)
42*83ee113eSDavid van Moolenbroek struct binding_value **result;
43*83ee113eSDavid van Moolenbroek struct packet *packet;
44*83ee113eSDavid van Moolenbroek struct lease *lease;
45*83ee113eSDavid van Moolenbroek struct client_state *client_state;
46*83ee113eSDavid van Moolenbroek struct option_state *in_options;
47*83ee113eSDavid van Moolenbroek struct option_state *out_options;
48*83ee113eSDavid van Moolenbroek struct binding_scope **scope;
49*83ee113eSDavid van Moolenbroek struct executable_statement *statements;
50*83ee113eSDavid van Moolenbroek struct on_star *on_star;
51*83ee113eSDavid van Moolenbroek {
52*83ee113eSDavid van Moolenbroek struct executable_statement *r, *e, *next;
53*83ee113eSDavid van Moolenbroek int rc;
54*83ee113eSDavid van Moolenbroek int status;
55*83ee113eSDavid van Moolenbroek struct binding *binding;
56*83ee113eSDavid van Moolenbroek struct data_string ds;
57*83ee113eSDavid van Moolenbroek struct binding_scope *ns;
58*83ee113eSDavid van Moolenbroek
59*83ee113eSDavid van Moolenbroek if (!statements)
60*83ee113eSDavid van Moolenbroek return 1;
61*83ee113eSDavid van Moolenbroek
62*83ee113eSDavid van Moolenbroek r = NULL;
63*83ee113eSDavid van Moolenbroek next = NULL;
64*83ee113eSDavid van Moolenbroek e = NULL;
65*83ee113eSDavid van Moolenbroek executable_statement_reference (&r, statements, MDL);
66*83ee113eSDavid van Moolenbroek while (r && !(result && *result)) {
67*83ee113eSDavid van Moolenbroek if (r->next)
68*83ee113eSDavid van Moolenbroek executable_statement_reference (&next, r->next, MDL);
69*83ee113eSDavid van Moolenbroek switch (r->op) {
70*83ee113eSDavid van Moolenbroek case statements_statement:
71*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
72*83ee113eSDavid van Moolenbroek log_debug ("exec: statements");
73*83ee113eSDavid van Moolenbroek #endif
74*83ee113eSDavid van Moolenbroek status = execute_statements (result, packet, lease,
75*83ee113eSDavid van Moolenbroek client_state, in_options,
76*83ee113eSDavid van Moolenbroek out_options, scope,
77*83ee113eSDavid van Moolenbroek r->data.statements,
78*83ee113eSDavid van Moolenbroek on_star);
79*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
80*83ee113eSDavid van Moolenbroek log_debug ("exec: statements returns %d", status);
81*83ee113eSDavid van Moolenbroek #endif
82*83ee113eSDavid van Moolenbroek if (!status)
83*83ee113eSDavid van Moolenbroek return 0;
84*83ee113eSDavid van Moolenbroek break;
85*83ee113eSDavid van Moolenbroek
86*83ee113eSDavid van Moolenbroek case on_statement:
87*83ee113eSDavid van Moolenbroek /*
88*83ee113eSDavid van Moolenbroek * if we haven't been passed an on_star block but
89*83ee113eSDavid van Moolenbroek * do have a lease, use the one from the lease
90*83ee113eSDavid van Moolenbroek * This handles the previous v4 calls.
91*83ee113eSDavid van Moolenbroek */
92*83ee113eSDavid van Moolenbroek if ((on_star == NULL) && (lease != NULL))
93*83ee113eSDavid van Moolenbroek on_star = &lease->on_star;
94*83ee113eSDavid van Moolenbroek
95*83ee113eSDavid van Moolenbroek if (on_star != NULL) {
96*83ee113eSDavid van Moolenbroek if (r->data.on.evtypes & ON_EXPIRY) {
97*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
98*83ee113eSDavid van Moolenbroek log_debug ("exec: on expiry");
99*83ee113eSDavid van Moolenbroek #endif
100*83ee113eSDavid van Moolenbroek if (on_star->on_expiry)
101*83ee113eSDavid van Moolenbroek executable_statement_dereference
102*83ee113eSDavid van Moolenbroek (&on_star->on_expiry, MDL);
103*83ee113eSDavid van Moolenbroek if (r->data.on.statements)
104*83ee113eSDavid van Moolenbroek executable_statement_reference
105*83ee113eSDavid van Moolenbroek (&on_star->on_expiry,
106*83ee113eSDavid van Moolenbroek r->data.on.statements, MDL);
107*83ee113eSDavid van Moolenbroek }
108*83ee113eSDavid van Moolenbroek if (r->data.on.evtypes & ON_RELEASE) {
109*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
110*83ee113eSDavid van Moolenbroek log_debug ("exec: on release");
111*83ee113eSDavid van Moolenbroek #endif
112*83ee113eSDavid van Moolenbroek if (on_star->on_release)
113*83ee113eSDavid van Moolenbroek executable_statement_dereference
114*83ee113eSDavid van Moolenbroek (&on_star->on_release, MDL);
115*83ee113eSDavid van Moolenbroek if (r->data.on.statements)
116*83ee113eSDavid van Moolenbroek executable_statement_reference
117*83ee113eSDavid van Moolenbroek (&on_star->on_release,
118*83ee113eSDavid van Moolenbroek r->data.on.statements, MDL);
119*83ee113eSDavid van Moolenbroek }
120*83ee113eSDavid van Moolenbroek if (r->data.on.evtypes & ON_COMMIT) {
121*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
122*83ee113eSDavid van Moolenbroek log_debug ("exec: on commit");
123*83ee113eSDavid van Moolenbroek #endif
124*83ee113eSDavid van Moolenbroek if (on_star->on_commit)
125*83ee113eSDavid van Moolenbroek executable_statement_dereference
126*83ee113eSDavid van Moolenbroek (&on_star->on_commit, MDL);
127*83ee113eSDavid van Moolenbroek if (r->data.on.statements)
128*83ee113eSDavid van Moolenbroek executable_statement_reference
129*83ee113eSDavid van Moolenbroek (&on_star->on_commit,
130*83ee113eSDavid van Moolenbroek r->data.on.statements, MDL);
131*83ee113eSDavid van Moolenbroek }
132*83ee113eSDavid van Moolenbroek }
133*83ee113eSDavid van Moolenbroek break;
134*83ee113eSDavid van Moolenbroek
135*83ee113eSDavid van Moolenbroek case switch_statement:
136*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
137*83ee113eSDavid van Moolenbroek log_debug ("exec: switch");
138*83ee113eSDavid van Moolenbroek #endif
139*83ee113eSDavid van Moolenbroek status = (find_matching_case
140*83ee113eSDavid van Moolenbroek (&e, packet, lease, client_state,
141*83ee113eSDavid van Moolenbroek in_options, out_options, scope,
142*83ee113eSDavid van Moolenbroek r->data.s_switch.expr,
143*83ee113eSDavid van Moolenbroek r->data.s_switch.statements));
144*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
145*83ee113eSDavid van Moolenbroek log_debug ("exec: switch: case %lx", (unsigned long)e);
146*83ee113eSDavid van Moolenbroek #endif
147*83ee113eSDavid van Moolenbroek if (status) {
148*83ee113eSDavid van Moolenbroek if (!(execute_statements
149*83ee113eSDavid van Moolenbroek (result, packet, lease, client_state,
150*83ee113eSDavid van Moolenbroek in_options, out_options, scope, e,
151*83ee113eSDavid van Moolenbroek on_star))) {
152*83ee113eSDavid van Moolenbroek executable_statement_dereference
153*83ee113eSDavid van Moolenbroek (&e, MDL);
154*83ee113eSDavid van Moolenbroek return 0;
155*83ee113eSDavid van Moolenbroek }
156*83ee113eSDavid van Moolenbroek executable_statement_dereference (&e, MDL);
157*83ee113eSDavid van Moolenbroek }
158*83ee113eSDavid van Moolenbroek break;
159*83ee113eSDavid van Moolenbroek
160*83ee113eSDavid van Moolenbroek /* These have no effect when executed. */
161*83ee113eSDavid van Moolenbroek case case_statement:
162*83ee113eSDavid van Moolenbroek case default_statement:
163*83ee113eSDavid van Moolenbroek break;
164*83ee113eSDavid van Moolenbroek
165*83ee113eSDavid van Moolenbroek case if_statement:
166*83ee113eSDavid van Moolenbroek status = (evaluate_boolean_expression
167*83ee113eSDavid van Moolenbroek (&rc, packet,
168*83ee113eSDavid van Moolenbroek lease, client_state, in_options,
169*83ee113eSDavid van Moolenbroek out_options, scope, r->data.ie.expr));
170*83ee113eSDavid van Moolenbroek
171*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
172*83ee113eSDavid van Moolenbroek log_debug ("exec: if %s", (status
173*83ee113eSDavid van Moolenbroek ? (rc ? "true" : "false")
174*83ee113eSDavid van Moolenbroek : "NULL"));
175*83ee113eSDavid van Moolenbroek #endif
176*83ee113eSDavid van Moolenbroek /* XXX Treat NULL as false */
177*83ee113eSDavid van Moolenbroek if (!status)
178*83ee113eSDavid van Moolenbroek rc = 0;
179*83ee113eSDavid van Moolenbroek if (!execute_statements
180*83ee113eSDavid van Moolenbroek (result, packet, lease, client_state,
181*83ee113eSDavid van Moolenbroek in_options, out_options, scope,
182*83ee113eSDavid van Moolenbroek rc ? r->data.ie.tc : r->data.ie.fc,
183*83ee113eSDavid van Moolenbroek on_star))
184*83ee113eSDavid van Moolenbroek return 0;
185*83ee113eSDavid van Moolenbroek break;
186*83ee113eSDavid van Moolenbroek
187*83ee113eSDavid van Moolenbroek case eval_statement:
188*83ee113eSDavid van Moolenbroek status = evaluate_expression
189*83ee113eSDavid van Moolenbroek (NULL, packet, lease, client_state, in_options,
190*83ee113eSDavid van Moolenbroek out_options, scope, r->data.eval, MDL);
191*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
192*83ee113eSDavid van Moolenbroek log_debug ("exec: evaluate: %s",
193*83ee113eSDavid van Moolenbroek (status ? "succeeded" : "failed"));
194*83ee113eSDavid van Moolenbroek #else
195*83ee113eSDavid van Moolenbroek POST(status);
196*83ee113eSDavid van Moolenbroek #endif
197*83ee113eSDavid van Moolenbroek break;
198*83ee113eSDavid van Moolenbroek
199*83ee113eSDavid van Moolenbroek case execute_statement: {
200*83ee113eSDavid van Moolenbroek #ifdef ENABLE_EXECUTE
201*83ee113eSDavid van Moolenbroek struct expression *expr;
202*83ee113eSDavid van Moolenbroek char **argv;
203*83ee113eSDavid van Moolenbroek int i, argc = r->data.execute.argc;
204*83ee113eSDavid van Moolenbroek pid_t p;
205*83ee113eSDavid van Moolenbroek
206*83ee113eSDavid van Moolenbroek /* save room for the command and the NULL terminator */
207*83ee113eSDavid van Moolenbroek argv = dmalloc((argc + 2) * sizeof(*argv), MDL);
208*83ee113eSDavid van Moolenbroek if (!argv)
209*83ee113eSDavid van Moolenbroek break;
210*83ee113eSDavid van Moolenbroek
211*83ee113eSDavid van Moolenbroek argv[0] = dmalloc(strlen(r->data.execute.command) + 1,
212*83ee113eSDavid van Moolenbroek MDL);
213*83ee113eSDavid van Moolenbroek if (argv[0]) {
214*83ee113eSDavid van Moolenbroek strcpy(argv[0], r->data.execute.command);
215*83ee113eSDavid van Moolenbroek } else {
216*83ee113eSDavid van Moolenbroek goto execute_out;
217*83ee113eSDavid van Moolenbroek }
218*83ee113eSDavid van Moolenbroek
219*83ee113eSDavid van Moolenbroek log_debug("execute_statement argv[0] = %s", argv[0]);
220*83ee113eSDavid van Moolenbroek
221*83ee113eSDavid van Moolenbroek for (i = 1, expr = r->data.execute.arglist; expr;
222*83ee113eSDavid van Moolenbroek expr = expr->data.arg.next, i++) {
223*83ee113eSDavid van Moolenbroek memset (&ds, 0, sizeof(ds));
224*83ee113eSDavid van Moolenbroek status = (evaluate_data_expression
225*83ee113eSDavid van Moolenbroek (&ds, packet,
226*83ee113eSDavid van Moolenbroek lease, client_state, in_options,
227*83ee113eSDavid van Moolenbroek out_options, scope,
228*83ee113eSDavid van Moolenbroek expr->data.arg.val, MDL));
229*83ee113eSDavid van Moolenbroek if (status) {
230*83ee113eSDavid van Moolenbroek argv[i] = dmalloc(ds.len + 1, MDL);
231*83ee113eSDavid van Moolenbroek if (argv[i]) {
232*83ee113eSDavid van Moolenbroek memcpy(argv[i], ds.data,
233*83ee113eSDavid van Moolenbroek ds.len);
234*83ee113eSDavid van Moolenbroek argv[i][ds.len] = 0;
235*83ee113eSDavid van Moolenbroek log_debug("execute_statement argv[%d] = %s", i, argv[i]);
236*83ee113eSDavid van Moolenbroek }
237*83ee113eSDavid van Moolenbroek data_string_forget (&ds, MDL);
238*83ee113eSDavid van Moolenbroek if (!argv[i]) {
239*83ee113eSDavid van Moolenbroek log_debug("execute_statement failed argv[%d]", i);
240*83ee113eSDavid van Moolenbroek goto execute_out;
241*83ee113eSDavid van Moolenbroek }
242*83ee113eSDavid van Moolenbroek } else {
243*83ee113eSDavid van Moolenbroek log_debug("execute: bad arg %d", i);
244*83ee113eSDavid van Moolenbroek goto execute_out;
245*83ee113eSDavid van Moolenbroek }
246*83ee113eSDavid van Moolenbroek }
247*83ee113eSDavid van Moolenbroek argv[i] = NULL;
248*83ee113eSDavid van Moolenbroek
249*83ee113eSDavid van Moolenbroek if ((p = fork()) > 0) {
250*83ee113eSDavid van Moolenbroek int status;
251*83ee113eSDavid van Moolenbroek waitpid(p, &status, 0);
252*83ee113eSDavid van Moolenbroek
253*83ee113eSDavid van Moolenbroek if (status) {
254*83ee113eSDavid van Moolenbroek log_error("execute: %s exit status %d",
255*83ee113eSDavid van Moolenbroek argv[0], status);
256*83ee113eSDavid van Moolenbroek }
257*83ee113eSDavid van Moolenbroek } else if (p == 0) {
258*83ee113eSDavid van Moolenbroek execvp(argv[0], argv);
259*83ee113eSDavid van Moolenbroek log_error("Unable to execute %s: %m", argv[0]);
260*83ee113eSDavid van Moolenbroek _exit(127);
261*83ee113eSDavid van Moolenbroek } else {
262*83ee113eSDavid van Moolenbroek log_error("execute: fork() failed");
263*83ee113eSDavid van Moolenbroek }
264*83ee113eSDavid van Moolenbroek
265*83ee113eSDavid van Moolenbroek execute_out:
266*83ee113eSDavid van Moolenbroek for (i = 0; i <= argc; i++) {
267*83ee113eSDavid van Moolenbroek if(argv[i])
268*83ee113eSDavid van Moolenbroek dfree(argv[i], MDL);
269*83ee113eSDavid van Moolenbroek }
270*83ee113eSDavid van Moolenbroek
271*83ee113eSDavid van Moolenbroek dfree(argv, MDL);
272*83ee113eSDavid van Moolenbroek #else /* !ENABLE_EXECUTE */
273*83ee113eSDavid van Moolenbroek log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
274*83ee113eSDavid van Moolenbroek "is not defined).", MDL);
275*83ee113eSDavid van Moolenbroek #endif /* ENABLE_EXECUTE */
276*83ee113eSDavid van Moolenbroek break;
277*83ee113eSDavid van Moolenbroek }
278*83ee113eSDavid van Moolenbroek
279*83ee113eSDavid van Moolenbroek case return_statement:
280*83ee113eSDavid van Moolenbroek status = evaluate_expression
281*83ee113eSDavid van Moolenbroek (result, packet,
282*83ee113eSDavid van Moolenbroek lease, client_state, in_options,
283*83ee113eSDavid van Moolenbroek out_options, scope, r -> data.retval, MDL);
284*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
285*83ee113eSDavid van Moolenbroek log_debug ("exec: return: %s",
286*83ee113eSDavid van Moolenbroek (status ? "succeeded" : "failed"));
287*83ee113eSDavid van Moolenbroek #else
288*83ee113eSDavid van Moolenbroek POST(status);
289*83ee113eSDavid van Moolenbroek #endif
290*83ee113eSDavid van Moolenbroek break;
291*83ee113eSDavid van Moolenbroek
292*83ee113eSDavid van Moolenbroek case add_statement:
293*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
294*83ee113eSDavid van Moolenbroek log_debug ("exec: add %s", (r->data.add->name
295*83ee113eSDavid van Moolenbroek ? r->data.add->name
296*83ee113eSDavid van Moolenbroek : "<unnamed class>"));
297*83ee113eSDavid van Moolenbroek #endif
298*83ee113eSDavid van Moolenbroek classify (packet, r->data.add);
299*83ee113eSDavid van Moolenbroek break;
300*83ee113eSDavid van Moolenbroek
301*83ee113eSDavid van Moolenbroek case break_statement:
302*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
303*83ee113eSDavid van Moolenbroek log_debug ("exec: break");
304*83ee113eSDavid van Moolenbroek #endif
305*83ee113eSDavid van Moolenbroek return 1;
306*83ee113eSDavid van Moolenbroek
307*83ee113eSDavid van Moolenbroek case supersede_option_statement:
308*83ee113eSDavid van Moolenbroek case send_option_statement:
309*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
310*83ee113eSDavid van Moolenbroek log_debug ("exec: %s option %s.%s",
311*83ee113eSDavid van Moolenbroek (r->op == supersede_option_statement
312*83ee113eSDavid van Moolenbroek ? "supersede" : "send"),
313*83ee113eSDavid van Moolenbroek r->data.option->option->universe->name,
314*83ee113eSDavid van Moolenbroek r->data.option->option->name);
315*83ee113eSDavid van Moolenbroek goto option_statement;
316*83ee113eSDavid van Moolenbroek #endif
317*83ee113eSDavid van Moolenbroek case default_option_statement:
318*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
319*83ee113eSDavid van Moolenbroek log_debug ("exec: default option %s.%s",
320*83ee113eSDavid van Moolenbroek r->data.option->option->universe->name,
321*83ee113eSDavid van Moolenbroek r->data.option->option->name);
322*83ee113eSDavid van Moolenbroek goto option_statement;
323*83ee113eSDavid van Moolenbroek #endif
324*83ee113eSDavid van Moolenbroek case append_option_statement:
325*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
326*83ee113eSDavid van Moolenbroek log_debug ("exec: append option %s.%s",
327*83ee113eSDavid van Moolenbroek r->data.option->option->universe->name,
328*83ee113eSDavid van Moolenbroek r->data.option->option->name);
329*83ee113eSDavid van Moolenbroek goto option_statement;
330*83ee113eSDavid van Moolenbroek #endif
331*83ee113eSDavid van Moolenbroek case prepend_option_statement:
332*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
333*83ee113eSDavid van Moolenbroek log_debug ("exec: prepend option %s.%s",
334*83ee113eSDavid van Moolenbroek r->data.option->option->universe->name,
335*83ee113eSDavid van Moolenbroek r->data.option->option->name);
336*83ee113eSDavid van Moolenbroek option_statement:
337*83ee113eSDavid van Moolenbroek #endif
338*83ee113eSDavid van Moolenbroek set_option (r->data.option->option->universe,
339*83ee113eSDavid van Moolenbroek out_options, r->data.option, r->op);
340*83ee113eSDavid van Moolenbroek break;
341*83ee113eSDavid van Moolenbroek
342*83ee113eSDavid van Moolenbroek case set_statement:
343*83ee113eSDavid van Moolenbroek case define_statement:
344*83ee113eSDavid van Moolenbroek status = 1;
345*83ee113eSDavid van Moolenbroek if (!scope) {
346*83ee113eSDavid van Moolenbroek log_error("set %s: no scope",
347*83ee113eSDavid van Moolenbroek r->data.set.name);
348*83ee113eSDavid van Moolenbroek break;
349*83ee113eSDavid van Moolenbroek }
350*83ee113eSDavid van Moolenbroek if (!*scope) {
351*83ee113eSDavid van Moolenbroek if (!binding_scope_allocate(scope, MDL)) {
352*83ee113eSDavid van Moolenbroek log_error("set %s: can't allocate scope",
353*83ee113eSDavid van Moolenbroek r->data.set.name);
354*83ee113eSDavid van Moolenbroek break;
355*83ee113eSDavid van Moolenbroek }
356*83ee113eSDavid van Moolenbroek }
357*83ee113eSDavid van Moolenbroek binding = find_binding(*scope, r->data.set.name);
358*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
359*83ee113eSDavid van Moolenbroek log_debug("exec: set %s", r->data.set.name);
360*83ee113eSDavid van Moolenbroek #else
361*83ee113eSDavid van Moolenbroek POST(status);
362*83ee113eSDavid van Moolenbroek #endif
363*83ee113eSDavid van Moolenbroek if (binding == NULL) {
364*83ee113eSDavid van Moolenbroek binding = dmalloc(sizeof(*binding), MDL);
365*83ee113eSDavid van Moolenbroek if (binding != NULL) {
366*83ee113eSDavid van Moolenbroek memset(binding, 0, sizeof(*binding));
367*83ee113eSDavid van Moolenbroek binding->name =
368*83ee113eSDavid van Moolenbroek dmalloc(strlen
369*83ee113eSDavid van Moolenbroek (r->data.set.name) + 1,
370*83ee113eSDavid van Moolenbroek MDL);
371*83ee113eSDavid van Moolenbroek if (binding->name != NULL) {
372*83ee113eSDavid van Moolenbroek strcpy(binding->name, r->data.set.name);
373*83ee113eSDavid van Moolenbroek binding->next = (*scope)->bindings;
374*83ee113eSDavid van Moolenbroek (*scope)->bindings = binding;
375*83ee113eSDavid van Moolenbroek } else {
376*83ee113eSDavid van Moolenbroek dfree(binding, MDL);
377*83ee113eSDavid van Moolenbroek binding = NULL;
378*83ee113eSDavid van Moolenbroek }
379*83ee113eSDavid van Moolenbroek }
380*83ee113eSDavid van Moolenbroek }
381*83ee113eSDavid van Moolenbroek if (binding != NULL) {
382*83ee113eSDavid van Moolenbroek if (binding->value != NULL)
383*83ee113eSDavid van Moolenbroek binding_value_dereference
384*83ee113eSDavid van Moolenbroek (&binding->value, MDL);
385*83ee113eSDavid van Moolenbroek if (r->op == set_statement) {
386*83ee113eSDavid van Moolenbroek status = (evaluate_expression
387*83ee113eSDavid van Moolenbroek (&binding->value, packet,
388*83ee113eSDavid van Moolenbroek lease, client_state,
389*83ee113eSDavid van Moolenbroek in_options, out_options,
390*83ee113eSDavid van Moolenbroek scope, r->data.set.expr,
391*83ee113eSDavid van Moolenbroek MDL));
392*83ee113eSDavid van Moolenbroek } else {
393*83ee113eSDavid van Moolenbroek if (!(binding_value_allocate
394*83ee113eSDavid van Moolenbroek (&binding->value, MDL))) {
395*83ee113eSDavid van Moolenbroek dfree(binding, MDL);
396*83ee113eSDavid van Moolenbroek binding = NULL;
397*83ee113eSDavid van Moolenbroek }
398*83ee113eSDavid van Moolenbroek if ((binding != NULL) &&
399*83ee113eSDavid van Moolenbroek (binding->value != NULL)) {
400*83ee113eSDavid van Moolenbroek binding->value->type =
401*83ee113eSDavid van Moolenbroek binding_function;
402*83ee113eSDavid van Moolenbroek (fundef_reference
403*83ee113eSDavid van Moolenbroek (&binding->value->value.fundef,
404*83ee113eSDavid van Moolenbroek r->data.set.expr->data.func,
405*83ee113eSDavid van Moolenbroek MDL));
406*83ee113eSDavid van Moolenbroek }
407*83ee113eSDavid van Moolenbroek }
408*83ee113eSDavid van Moolenbroek }
409*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
410*83ee113eSDavid van Moolenbroek log_debug ("exec: set %s%s", r -> data.set.name,
411*83ee113eSDavid van Moolenbroek (binding && status ? "" : " (failed)"));
412*83ee113eSDavid van Moolenbroek #else
413*83ee113eSDavid van Moolenbroek POST(status);
414*83ee113eSDavid van Moolenbroek #endif
415*83ee113eSDavid van Moolenbroek break;
416*83ee113eSDavid van Moolenbroek
417*83ee113eSDavid van Moolenbroek case unset_statement:
418*83ee113eSDavid van Moolenbroek if (!scope || !*scope)
419*83ee113eSDavid van Moolenbroek break;
420*83ee113eSDavid van Moolenbroek binding = find_binding (*scope, r->data.unset);
421*83ee113eSDavid van Moolenbroek if (binding) {
422*83ee113eSDavid van Moolenbroek if (binding->value)
423*83ee113eSDavid van Moolenbroek binding_value_dereference
424*83ee113eSDavid van Moolenbroek (&binding->value, MDL);
425*83ee113eSDavid van Moolenbroek status = 1;
426*83ee113eSDavid van Moolenbroek } else
427*83ee113eSDavid van Moolenbroek status = 0;
428*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
429*83ee113eSDavid van Moolenbroek log_debug ("exec: unset %s: %s", r->data.unset,
430*83ee113eSDavid van Moolenbroek (status ? "found" : "not found"));
431*83ee113eSDavid van Moolenbroek #else
432*83ee113eSDavid van Moolenbroek POST(status);
433*83ee113eSDavid van Moolenbroek #endif
434*83ee113eSDavid van Moolenbroek break;
435*83ee113eSDavid van Moolenbroek
436*83ee113eSDavid van Moolenbroek case let_statement:
437*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
438*83ee113eSDavid van Moolenbroek log_debug("exec: let %s", r->data.let.name);
439*83ee113eSDavid van Moolenbroek #endif
440*83ee113eSDavid van Moolenbroek status = 0;
441*83ee113eSDavid van Moolenbroek ns = NULL;
442*83ee113eSDavid van Moolenbroek binding_scope_allocate (&ns, MDL);
443*83ee113eSDavid van Moolenbroek e = r;
444*83ee113eSDavid van Moolenbroek
445*83ee113eSDavid van Moolenbroek next_let:
446*83ee113eSDavid van Moolenbroek if (ns) {
447*83ee113eSDavid van Moolenbroek binding = dmalloc(sizeof(*binding), MDL);
448*83ee113eSDavid van Moolenbroek memset(binding, 0, sizeof(*binding));
449*83ee113eSDavid van Moolenbroek if (!binding) {
450*83ee113eSDavid van Moolenbroek blb:
451*83ee113eSDavid van Moolenbroek binding_scope_dereference(&ns, MDL);
452*83ee113eSDavid van Moolenbroek } else {
453*83ee113eSDavid van Moolenbroek binding->name =
454*83ee113eSDavid van Moolenbroek dmalloc(strlen
455*83ee113eSDavid van Moolenbroek (e->data.let.name + 1),
456*83ee113eSDavid van Moolenbroek MDL);
457*83ee113eSDavid van Moolenbroek if (binding->name)
458*83ee113eSDavid van Moolenbroek strcpy(binding->name,
459*83ee113eSDavid van Moolenbroek e->data.let.name);
460*83ee113eSDavid van Moolenbroek else {
461*83ee113eSDavid van Moolenbroek dfree(binding, MDL);
462*83ee113eSDavid van Moolenbroek binding = NULL;
463*83ee113eSDavid van Moolenbroek goto blb;
464*83ee113eSDavid van Moolenbroek }
465*83ee113eSDavid van Moolenbroek }
466*83ee113eSDavid van Moolenbroek } else
467*83ee113eSDavid van Moolenbroek binding = NULL;
468*83ee113eSDavid van Moolenbroek
469*83ee113eSDavid van Moolenbroek if (ns && binding) {
470*83ee113eSDavid van Moolenbroek status = (evaluate_expression
471*83ee113eSDavid van Moolenbroek (&binding->value, packet, lease,
472*83ee113eSDavid van Moolenbroek client_state,
473*83ee113eSDavid van Moolenbroek in_options, out_options,
474*83ee113eSDavid van Moolenbroek scope, e->data.set.expr, MDL));
475*83ee113eSDavid van Moolenbroek binding->next = ns->bindings;
476*83ee113eSDavid van Moolenbroek ns->bindings = binding;
477*83ee113eSDavid van Moolenbroek }
478*83ee113eSDavid van Moolenbroek
479*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
480*83ee113eSDavid van Moolenbroek log_debug("exec: let %s%s", e->data.let.name,
481*83ee113eSDavid van Moolenbroek (binding && status ? "" : "failed"));
482*83ee113eSDavid van Moolenbroek #else
483*83ee113eSDavid van Moolenbroek POST(status);
484*83ee113eSDavid van Moolenbroek #endif
485*83ee113eSDavid van Moolenbroek if (!e->data.let.statements) {
486*83ee113eSDavid van Moolenbroek } else if (e->data.let.statements->op ==
487*83ee113eSDavid van Moolenbroek let_statement) {
488*83ee113eSDavid van Moolenbroek e = e->data.let.statements;
489*83ee113eSDavid van Moolenbroek goto next_let;
490*83ee113eSDavid van Moolenbroek } else if (ns) {
491*83ee113eSDavid van Moolenbroek if (scope && *scope)
492*83ee113eSDavid van Moolenbroek binding_scope_reference(&ns->outer,
493*83ee113eSDavid van Moolenbroek *scope, MDL);
494*83ee113eSDavid van Moolenbroek execute_statements
495*83ee113eSDavid van Moolenbroek (result, packet, lease, client_state,
496*83ee113eSDavid van Moolenbroek in_options, out_options,
497*83ee113eSDavid van Moolenbroek &ns, e->data.let.statements, on_star);
498*83ee113eSDavid van Moolenbroek }
499*83ee113eSDavid van Moolenbroek if (ns)
500*83ee113eSDavid van Moolenbroek binding_scope_dereference(&ns, MDL);
501*83ee113eSDavid van Moolenbroek break;
502*83ee113eSDavid van Moolenbroek
503*83ee113eSDavid van Moolenbroek case log_statement:
504*83ee113eSDavid van Moolenbroek memset (&ds, 0, sizeof ds);
505*83ee113eSDavid van Moolenbroek status = (evaluate_data_expression
506*83ee113eSDavid van Moolenbroek (&ds, packet,
507*83ee113eSDavid van Moolenbroek lease, client_state, in_options,
508*83ee113eSDavid van Moolenbroek out_options, scope, r->data.log.expr, MDL));
509*83ee113eSDavid van Moolenbroek
510*83ee113eSDavid van Moolenbroek #if defined (DEBUG_EXPRESSIONS)
511*83ee113eSDavid van Moolenbroek log_debug ("exec: log");
512*83ee113eSDavid van Moolenbroek #endif
513*83ee113eSDavid van Moolenbroek
514*83ee113eSDavid van Moolenbroek if (status) {
515*83ee113eSDavid van Moolenbroek switch (r->data.log.priority) {
516*83ee113eSDavid van Moolenbroek case log_priority_fatal:
517*83ee113eSDavid van Moolenbroek log_fatal ("%.*s", (int)ds.len,
518*83ee113eSDavid van Moolenbroek ds.data);
519*83ee113eSDavid van Moolenbroek break;
520*83ee113eSDavid van Moolenbroek case log_priority_error:
521*83ee113eSDavid van Moolenbroek log_error ("%.*s", (int)ds.len,
522*83ee113eSDavid van Moolenbroek ds.data);
523*83ee113eSDavid van Moolenbroek break;
524*83ee113eSDavid van Moolenbroek case log_priority_debug:
525*83ee113eSDavid van Moolenbroek log_debug ("%.*s", (int)ds.len,
526*83ee113eSDavid van Moolenbroek ds.data);
527*83ee113eSDavid van Moolenbroek break;
528*83ee113eSDavid van Moolenbroek case log_priority_info:
529*83ee113eSDavid van Moolenbroek log_info ("%.*s", (int)ds.len,
530*83ee113eSDavid van Moolenbroek ds.data);
531*83ee113eSDavid van Moolenbroek break;
532*83ee113eSDavid van Moolenbroek }
533*83ee113eSDavid van Moolenbroek data_string_forget (&ds, MDL);
534*83ee113eSDavid van Moolenbroek }
535*83ee113eSDavid van Moolenbroek
536*83ee113eSDavid van Moolenbroek break;
537*83ee113eSDavid van Moolenbroek
538*83ee113eSDavid van Moolenbroek default:
539*83ee113eSDavid van Moolenbroek log_error ("bogus statement type %d", r -> op);
540*83ee113eSDavid van Moolenbroek break;
541*83ee113eSDavid van Moolenbroek }
542*83ee113eSDavid van Moolenbroek executable_statement_dereference (&r, MDL);
543*83ee113eSDavid van Moolenbroek if (next) {
544*83ee113eSDavid van Moolenbroek executable_statement_reference (&r, next, MDL);
545*83ee113eSDavid van Moolenbroek executable_statement_dereference (&next, MDL);
546*83ee113eSDavid van Moolenbroek }
547*83ee113eSDavid van Moolenbroek }
548*83ee113eSDavid van Moolenbroek
549*83ee113eSDavid van Moolenbroek return 1;
550*83ee113eSDavid van Moolenbroek }
551*83ee113eSDavid van Moolenbroek
552*83ee113eSDavid van Moolenbroek /* Execute all the statements in a particular scope, and all statements in
553*83ee113eSDavid van Moolenbroek scopes outer from that scope, but if a particular limiting scope is
554*83ee113eSDavid van Moolenbroek reached, do not execute statements in that scope or in scopes outer
555*83ee113eSDavid van Moolenbroek from it. More specific scopes need to take precedence over less
556*83ee113eSDavid van Moolenbroek specific scopes, so we recursively traverse the scope list, executing
557*83ee113eSDavid van Moolenbroek the most outer scope first. */
558*83ee113eSDavid van Moolenbroek
execute_statements_in_scope(result,packet,lease,client_state,in_options,out_options,scope,group,limiting_group,on_star)559*83ee113eSDavid van Moolenbroek void execute_statements_in_scope (result, packet,
560*83ee113eSDavid van Moolenbroek lease, client_state, in_options, out_options,
561*83ee113eSDavid van Moolenbroek scope, group, limiting_group, on_star)
562*83ee113eSDavid van Moolenbroek struct binding_value **result;
563*83ee113eSDavid van Moolenbroek struct packet *packet;
564*83ee113eSDavid van Moolenbroek struct lease *lease;
565*83ee113eSDavid van Moolenbroek struct client_state *client_state;
566*83ee113eSDavid van Moolenbroek struct option_state *in_options;
567*83ee113eSDavid van Moolenbroek struct option_state *out_options;
568*83ee113eSDavid van Moolenbroek struct binding_scope **scope;
569*83ee113eSDavid van Moolenbroek struct group *group;
570*83ee113eSDavid van Moolenbroek struct group *limiting_group;
571*83ee113eSDavid van Moolenbroek struct on_star *on_star;
572*83ee113eSDavid van Moolenbroek {
573*83ee113eSDavid van Moolenbroek struct group *limit;
574*83ee113eSDavid van Moolenbroek
575*83ee113eSDavid van Moolenbroek /* If we've recursed as far as we can, return. */
576*83ee113eSDavid van Moolenbroek if (!group)
577*83ee113eSDavid van Moolenbroek return;
578*83ee113eSDavid van Moolenbroek
579*83ee113eSDavid van Moolenbroek /* As soon as we get to a scope that is outer than the limiting
580*83ee113eSDavid van Moolenbroek scope, we are done. This is so that if somebody does something
581*83ee113eSDavid van Moolenbroek like this, it does the expected thing:
582*83ee113eSDavid van Moolenbroek
583*83ee113eSDavid van Moolenbroek domain-name "fugue.com";
584*83ee113eSDavid van Moolenbroek shared-network FOO {
585*83ee113eSDavid van Moolenbroek host bar {
586*83ee113eSDavid van Moolenbroek domain-name "othello.fugue.com";
587*83ee113eSDavid van Moolenbroek fixed-address 10.20.30.40;
588*83ee113eSDavid van Moolenbroek }
589*83ee113eSDavid van Moolenbroek subnet 10.20.30.0 netmask 255.255.255.0 {
590*83ee113eSDavid van Moolenbroek domain-name "manhattan.fugue.com";
591*83ee113eSDavid van Moolenbroek }
592*83ee113eSDavid van Moolenbroek }
593*83ee113eSDavid van Moolenbroek
594*83ee113eSDavid van Moolenbroek The problem with the above arrangement is that the host's
595*83ee113eSDavid van Moolenbroek group nesting will be host -> shared-network -> top-level,
596*83ee113eSDavid van Moolenbroek and the limiting scope when we evaluate the host's scope
597*83ee113eSDavid van Moolenbroek will be the subnet -> shared-network -> top-level, so we need
598*83ee113eSDavid van Moolenbroek to know when we evaluate the host's scope to stop before we
599*83ee113eSDavid van Moolenbroek evaluate the shared-networks scope, because it's outer than
600*83ee113eSDavid van Moolenbroek the limiting scope, which means we've already evaluated it. */
601*83ee113eSDavid van Moolenbroek
602*83ee113eSDavid van Moolenbroek for (limit = limiting_group; limit; limit = limit -> next) {
603*83ee113eSDavid van Moolenbroek if (group == limit)
604*83ee113eSDavid van Moolenbroek return;
605*83ee113eSDavid van Moolenbroek }
606*83ee113eSDavid van Moolenbroek
607*83ee113eSDavid van Moolenbroek if (group -> next)
608*83ee113eSDavid van Moolenbroek execute_statements_in_scope (result, packet,
609*83ee113eSDavid van Moolenbroek lease, client_state,
610*83ee113eSDavid van Moolenbroek in_options, out_options, scope,
611*83ee113eSDavid van Moolenbroek group->next, limiting_group,
612*83ee113eSDavid van Moolenbroek on_star);
613*83ee113eSDavid van Moolenbroek execute_statements (result, packet, lease, client_state, in_options,
614*83ee113eSDavid van Moolenbroek out_options, scope, group->statements, on_star);
615*83ee113eSDavid van Moolenbroek }
616*83ee113eSDavid van Moolenbroek
617*83ee113eSDavid van Moolenbroek /* Dereference or free any subexpressions of a statement being freed. */
618*83ee113eSDavid van Moolenbroek
executable_statement_dereference(ptr,file,line)619*83ee113eSDavid van Moolenbroek int executable_statement_dereference (ptr, file, line)
620*83ee113eSDavid van Moolenbroek struct executable_statement **ptr;
621*83ee113eSDavid van Moolenbroek const char *file;
622*83ee113eSDavid van Moolenbroek int line;
623*83ee113eSDavid van Moolenbroek {
624*83ee113eSDavid van Moolenbroek if (!ptr || !*ptr) {
625*83ee113eSDavid van Moolenbroek log_error ("%s(%d): null pointer", file, line);
626*83ee113eSDavid van Moolenbroek #if defined (POINTER_DEBUG)
627*83ee113eSDavid van Moolenbroek abort ();
628*83ee113eSDavid van Moolenbroek #else
629*83ee113eSDavid van Moolenbroek return 0;
630*83ee113eSDavid van Moolenbroek #endif
631*83ee113eSDavid van Moolenbroek }
632*83ee113eSDavid van Moolenbroek
633*83ee113eSDavid van Moolenbroek (*ptr) -> refcnt--;
634*83ee113eSDavid van Moolenbroek rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
635*83ee113eSDavid van Moolenbroek if ((*ptr) -> refcnt > 0) {
636*83ee113eSDavid van Moolenbroek *ptr = (struct executable_statement *)0;
637*83ee113eSDavid van Moolenbroek return 1;
638*83ee113eSDavid van Moolenbroek }
639*83ee113eSDavid van Moolenbroek
640*83ee113eSDavid van Moolenbroek if ((*ptr) -> refcnt < 0) {
641*83ee113eSDavid van Moolenbroek log_error ("%s(%d): negative refcnt!", file, line);
642*83ee113eSDavid van Moolenbroek #if defined (DEBUG_RC_HISTORY)
643*83ee113eSDavid van Moolenbroek dump_rc_history (*ptr);
644*83ee113eSDavid van Moolenbroek #endif
645*83ee113eSDavid van Moolenbroek #if defined (POINTER_DEBUG)
646*83ee113eSDavid van Moolenbroek abort ();
647*83ee113eSDavid van Moolenbroek #else
648*83ee113eSDavid van Moolenbroek return 0;
649*83ee113eSDavid van Moolenbroek #endif
650*83ee113eSDavid van Moolenbroek }
651*83ee113eSDavid van Moolenbroek
652*83ee113eSDavid van Moolenbroek if ((*ptr) -> next)
653*83ee113eSDavid van Moolenbroek executable_statement_dereference (&(*ptr) -> next, file, line);
654*83ee113eSDavid van Moolenbroek
655*83ee113eSDavid van Moolenbroek switch ((*ptr) -> op) {
656*83ee113eSDavid van Moolenbroek case statements_statement:
657*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.statements)
658*83ee113eSDavid van Moolenbroek executable_statement_dereference
659*83ee113eSDavid van Moolenbroek (&(*ptr) -> data.statements, file, line);
660*83ee113eSDavid van Moolenbroek break;
661*83ee113eSDavid van Moolenbroek
662*83ee113eSDavid van Moolenbroek case on_statement:
663*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.on.statements)
664*83ee113eSDavid van Moolenbroek executable_statement_dereference
665*83ee113eSDavid van Moolenbroek (&(*ptr) -> data.on.statements, file, line);
666*83ee113eSDavid van Moolenbroek break;
667*83ee113eSDavid van Moolenbroek
668*83ee113eSDavid van Moolenbroek case switch_statement:
669*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.s_switch.statements)
670*83ee113eSDavid van Moolenbroek executable_statement_dereference
671*83ee113eSDavid van Moolenbroek (&(*ptr) -> data.on.statements, file, line);
672*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.s_switch.expr)
673*83ee113eSDavid van Moolenbroek expression_dereference (&(*ptr) -> data.s_switch.expr,
674*83ee113eSDavid van Moolenbroek file, line);
675*83ee113eSDavid van Moolenbroek break;
676*83ee113eSDavid van Moolenbroek
677*83ee113eSDavid van Moolenbroek case case_statement:
678*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.s_switch.expr)
679*83ee113eSDavid van Moolenbroek expression_dereference (&(*ptr) -> data.c_case,
680*83ee113eSDavid van Moolenbroek file, line);
681*83ee113eSDavid van Moolenbroek break;
682*83ee113eSDavid van Moolenbroek
683*83ee113eSDavid van Moolenbroek case if_statement:
684*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.ie.expr)
685*83ee113eSDavid van Moolenbroek expression_dereference (&(*ptr) -> data.ie.expr,
686*83ee113eSDavid van Moolenbroek file, line);
687*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.ie.tc)
688*83ee113eSDavid van Moolenbroek executable_statement_dereference
689*83ee113eSDavid van Moolenbroek (&(*ptr) -> data.ie.tc, file, line);
690*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.ie.fc)
691*83ee113eSDavid van Moolenbroek executable_statement_dereference
692*83ee113eSDavid van Moolenbroek (&(*ptr) -> data.ie.fc, file, line);
693*83ee113eSDavid van Moolenbroek break;
694*83ee113eSDavid van Moolenbroek
695*83ee113eSDavid van Moolenbroek case eval_statement:
696*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.eval)
697*83ee113eSDavid van Moolenbroek expression_dereference (&(*ptr) -> data.eval,
698*83ee113eSDavid van Moolenbroek file, line);
699*83ee113eSDavid van Moolenbroek break;
700*83ee113eSDavid van Moolenbroek
701*83ee113eSDavid van Moolenbroek case return_statement:
702*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.eval)
703*83ee113eSDavid van Moolenbroek expression_dereference (&(*ptr) -> data.eval,
704*83ee113eSDavid van Moolenbroek file, line);
705*83ee113eSDavid van Moolenbroek break;
706*83ee113eSDavid van Moolenbroek
707*83ee113eSDavid van Moolenbroek case set_statement:
708*83ee113eSDavid van Moolenbroek if ((*ptr)->data.set.name)
709*83ee113eSDavid van Moolenbroek dfree ((*ptr)->data.set.name, file, line);
710*83ee113eSDavid van Moolenbroek if ((*ptr)->data.set.expr)
711*83ee113eSDavid van Moolenbroek expression_dereference (&(*ptr) -> data.set.expr,
712*83ee113eSDavid van Moolenbroek file, line);
713*83ee113eSDavid van Moolenbroek break;
714*83ee113eSDavid van Moolenbroek
715*83ee113eSDavid van Moolenbroek case unset_statement:
716*83ee113eSDavid van Moolenbroek if ((*ptr)->data.unset)
717*83ee113eSDavid van Moolenbroek dfree ((*ptr)->data.unset, file, line);
718*83ee113eSDavid van Moolenbroek break;
719*83ee113eSDavid van Moolenbroek
720*83ee113eSDavid van Moolenbroek case execute_statement:
721*83ee113eSDavid van Moolenbroek if ((*ptr)->data.execute.command)
722*83ee113eSDavid van Moolenbroek dfree ((*ptr)->data.execute.command, file, line);
723*83ee113eSDavid van Moolenbroek if ((*ptr)->data.execute.arglist)
724*83ee113eSDavid van Moolenbroek expression_dereference (&(*ptr) -> data.execute.arglist,
725*83ee113eSDavid van Moolenbroek file, line);
726*83ee113eSDavid van Moolenbroek break;
727*83ee113eSDavid van Moolenbroek
728*83ee113eSDavid van Moolenbroek case supersede_option_statement:
729*83ee113eSDavid van Moolenbroek case send_option_statement:
730*83ee113eSDavid van Moolenbroek case default_option_statement:
731*83ee113eSDavid van Moolenbroek case append_option_statement:
732*83ee113eSDavid van Moolenbroek case prepend_option_statement:
733*83ee113eSDavid van Moolenbroek if ((*ptr) -> data.option)
734*83ee113eSDavid van Moolenbroek option_cache_dereference (&(*ptr) -> data.option,
735*83ee113eSDavid van Moolenbroek file, line);
736*83ee113eSDavid van Moolenbroek break;
737*83ee113eSDavid van Moolenbroek
738*83ee113eSDavid van Moolenbroek default:
739*83ee113eSDavid van Moolenbroek /* Nothing to do. */
740*83ee113eSDavid van Moolenbroek break;
741*83ee113eSDavid van Moolenbroek }
742*83ee113eSDavid van Moolenbroek
743*83ee113eSDavid van Moolenbroek dfree ((*ptr), file, line);
744*83ee113eSDavid van Moolenbroek *ptr = (struct executable_statement *)0;
745*83ee113eSDavid van Moolenbroek return 1;
746*83ee113eSDavid van Moolenbroek }
747*83ee113eSDavid van Moolenbroek
write_statements(file,statements,indent)748*83ee113eSDavid van Moolenbroek void write_statements (file, statements, indent)
749*83ee113eSDavid van Moolenbroek FILE *file;
750*83ee113eSDavid van Moolenbroek struct executable_statement *statements;
751*83ee113eSDavid van Moolenbroek int indent;
752*83ee113eSDavid van Moolenbroek {
753*83ee113eSDavid van Moolenbroek #if defined ENABLE_EXECUTE
754*83ee113eSDavid van Moolenbroek struct expression *expr;
755*83ee113eSDavid van Moolenbroek #endif
756*83ee113eSDavid van Moolenbroek struct executable_statement *r, *x;
757*83ee113eSDavid van Moolenbroek const char *s, *t, *dot;
758*83ee113eSDavid van Moolenbroek int col;
759*83ee113eSDavid van Moolenbroek
760*83ee113eSDavid van Moolenbroek if (!statements)
761*83ee113eSDavid van Moolenbroek return;
762*83ee113eSDavid van Moolenbroek
763*83ee113eSDavid van Moolenbroek for (r = statements; r; r = r -> next) {
764*83ee113eSDavid van Moolenbroek switch (r -> op) {
765*83ee113eSDavid van Moolenbroek case statements_statement:
766*83ee113eSDavid van Moolenbroek write_statements (file, r -> data.statements, indent);
767*83ee113eSDavid van Moolenbroek break;
768*83ee113eSDavid van Moolenbroek
769*83ee113eSDavid van Moolenbroek case on_statement:
770*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
771*83ee113eSDavid van Moolenbroek fprintf (file, "on ");
772*83ee113eSDavid van Moolenbroek s = "";
773*83ee113eSDavid van Moolenbroek if (r -> data.on.evtypes & ON_EXPIRY) {
774*83ee113eSDavid van Moolenbroek fprintf (file, "%sexpiry", s);
775*83ee113eSDavid van Moolenbroek s = " or ";
776*83ee113eSDavid van Moolenbroek }
777*83ee113eSDavid van Moolenbroek if (r -> data.on.evtypes & ON_COMMIT) {
778*83ee113eSDavid van Moolenbroek fprintf (file, "%scommit", s);
779*83ee113eSDavid van Moolenbroek s = " or ";
780*83ee113eSDavid van Moolenbroek }
781*83ee113eSDavid van Moolenbroek if (r -> data.on.evtypes & ON_RELEASE) {
782*83ee113eSDavid van Moolenbroek fprintf (file, "%srelease", s);
783*83ee113eSDavid van Moolenbroek /* s = " or "; */
784*83ee113eSDavid van Moolenbroek }
785*83ee113eSDavid van Moolenbroek if (r -> data.on.statements) {
786*83ee113eSDavid van Moolenbroek fprintf (file, " {");
787*83ee113eSDavid van Moolenbroek write_statements (file,
788*83ee113eSDavid van Moolenbroek r -> data.on.statements,
789*83ee113eSDavid van Moolenbroek indent + 2);
790*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
791*83ee113eSDavid van Moolenbroek fprintf (file, "}");
792*83ee113eSDavid van Moolenbroek } else {
793*83ee113eSDavid van Moolenbroek fprintf (file, ";");
794*83ee113eSDavid van Moolenbroek }
795*83ee113eSDavid van Moolenbroek break;
796*83ee113eSDavid van Moolenbroek
797*83ee113eSDavid van Moolenbroek case switch_statement:
798*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
799*83ee113eSDavid van Moolenbroek fprintf (file, "switch (");
800*83ee113eSDavid van Moolenbroek col = write_expression (file,
801*83ee113eSDavid van Moolenbroek r -> data.s_switch.expr,
802*83ee113eSDavid van Moolenbroek indent + 7, indent + 7, 1);
803*83ee113eSDavid van Moolenbroek col = token_print_indent (file, col, indent + 7,
804*83ee113eSDavid van Moolenbroek "", "", ")");
805*83ee113eSDavid van Moolenbroek token_print_indent (file,
806*83ee113eSDavid van Moolenbroek col, indent, " ", "", "{");
807*83ee113eSDavid van Moolenbroek write_statements (file, r -> data.s_switch.statements,
808*83ee113eSDavid van Moolenbroek indent + 2);
809*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
810*83ee113eSDavid van Moolenbroek fprintf (file, "}");
811*83ee113eSDavid van Moolenbroek break;
812*83ee113eSDavid van Moolenbroek
813*83ee113eSDavid van Moolenbroek case case_statement:
814*83ee113eSDavid van Moolenbroek indent_spaces (file, indent - 1);
815*83ee113eSDavid van Moolenbroek fprintf (file, "case ");
816*83ee113eSDavid van Moolenbroek col = write_expression (file,
817*83ee113eSDavid van Moolenbroek r -> data.s_switch.expr,
818*83ee113eSDavid van Moolenbroek indent + 5, indent + 5, 1);
819*83ee113eSDavid van Moolenbroek token_print_indent (file, col, indent + 5,
820*83ee113eSDavid van Moolenbroek "", "", ":");
821*83ee113eSDavid van Moolenbroek break;
822*83ee113eSDavid van Moolenbroek
823*83ee113eSDavid van Moolenbroek case default_statement:
824*83ee113eSDavid van Moolenbroek indent_spaces (file, indent - 1);
825*83ee113eSDavid van Moolenbroek fprintf (file, "default: ");
826*83ee113eSDavid van Moolenbroek break;
827*83ee113eSDavid van Moolenbroek
828*83ee113eSDavid van Moolenbroek case if_statement:
829*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
830*83ee113eSDavid van Moolenbroek fprintf (file, "if ");
831*83ee113eSDavid van Moolenbroek x = r;
832*83ee113eSDavid van Moolenbroek col = write_expression (file,
833*83ee113eSDavid van Moolenbroek x -> data.ie.expr,
834*83ee113eSDavid van Moolenbroek indent + 3, indent + 3, 1);
835*83ee113eSDavid van Moolenbroek else_if:
836*83ee113eSDavid van Moolenbroek token_print_indent (file, col, indent, " ", "", "{");
837*83ee113eSDavid van Moolenbroek write_statements (file, x -> data.ie.tc, indent + 2);
838*83ee113eSDavid van Moolenbroek if (x -> data.ie.fc &&
839*83ee113eSDavid van Moolenbroek x -> data.ie.fc -> op == if_statement &&
840*83ee113eSDavid van Moolenbroek !x -> data.ie.fc -> next) {
841*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
842*83ee113eSDavid van Moolenbroek fprintf (file, "} elsif ");
843*83ee113eSDavid van Moolenbroek x = x -> data.ie.fc;
844*83ee113eSDavid van Moolenbroek col = write_expression (file,
845*83ee113eSDavid van Moolenbroek x -> data.ie.expr,
846*83ee113eSDavid van Moolenbroek indent + 6,
847*83ee113eSDavid van Moolenbroek indent + 6, 1);
848*83ee113eSDavid van Moolenbroek goto else_if;
849*83ee113eSDavid van Moolenbroek }
850*83ee113eSDavid van Moolenbroek if (x -> data.ie.fc) {
851*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
852*83ee113eSDavid van Moolenbroek fprintf (file, "} else {");
853*83ee113eSDavid van Moolenbroek write_statements (file, x -> data.ie.fc,
854*83ee113eSDavid van Moolenbroek indent + 2);
855*83ee113eSDavid van Moolenbroek }
856*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
857*83ee113eSDavid van Moolenbroek fprintf (file, "}");
858*83ee113eSDavid van Moolenbroek break;
859*83ee113eSDavid van Moolenbroek
860*83ee113eSDavid van Moolenbroek case eval_statement:
861*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
862*83ee113eSDavid van Moolenbroek fprintf (file, "eval ");
863*83ee113eSDavid van Moolenbroek (void) write_expression (file, r -> data.eval,
864*83ee113eSDavid van Moolenbroek indent + 5, indent + 5, 1);
865*83ee113eSDavid van Moolenbroek fprintf (file, ";");
866*83ee113eSDavid van Moolenbroek break;
867*83ee113eSDavid van Moolenbroek
868*83ee113eSDavid van Moolenbroek case return_statement:
869*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
870*83ee113eSDavid van Moolenbroek fprintf (file, "return;");
871*83ee113eSDavid van Moolenbroek break;
872*83ee113eSDavid van Moolenbroek
873*83ee113eSDavid van Moolenbroek case add_statement:
874*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
875*83ee113eSDavid van Moolenbroek fprintf (file, "add \"%s\"", r -> data.add -> name);
876*83ee113eSDavid van Moolenbroek break;
877*83ee113eSDavid van Moolenbroek
878*83ee113eSDavid van Moolenbroek case break_statement:
879*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
880*83ee113eSDavid van Moolenbroek fprintf (file, "break;");
881*83ee113eSDavid van Moolenbroek break;
882*83ee113eSDavid van Moolenbroek
883*83ee113eSDavid van Moolenbroek case supersede_option_statement:
884*83ee113eSDavid van Moolenbroek case send_option_statement:
885*83ee113eSDavid van Moolenbroek s = "supersede";
886*83ee113eSDavid van Moolenbroek goto option_statement;
887*83ee113eSDavid van Moolenbroek
888*83ee113eSDavid van Moolenbroek case default_option_statement:
889*83ee113eSDavid van Moolenbroek s = "default";
890*83ee113eSDavid van Moolenbroek goto option_statement;
891*83ee113eSDavid van Moolenbroek
892*83ee113eSDavid van Moolenbroek case append_option_statement:
893*83ee113eSDavid van Moolenbroek s = "append";
894*83ee113eSDavid van Moolenbroek goto option_statement;
895*83ee113eSDavid van Moolenbroek
896*83ee113eSDavid van Moolenbroek case prepend_option_statement:
897*83ee113eSDavid van Moolenbroek s = "prepend";
898*83ee113eSDavid van Moolenbroek option_statement:
899*83ee113eSDavid van Moolenbroek /* Note: the reason we don't try to pretty print
900*83ee113eSDavid van Moolenbroek the option here is that the format of the option
901*83ee113eSDavid van Moolenbroek may change in dhcpd.conf, and then when this
902*83ee113eSDavid van Moolenbroek statement was read back, it would cause a syntax
903*83ee113eSDavid van Moolenbroek error. */
904*83ee113eSDavid van Moolenbroek if (r -> data.option -> option -> universe ==
905*83ee113eSDavid van Moolenbroek &dhcp_universe) {
906*83ee113eSDavid van Moolenbroek t = "";
907*83ee113eSDavid van Moolenbroek dot = "";
908*83ee113eSDavid van Moolenbroek } else {
909*83ee113eSDavid van Moolenbroek t = (r -> data.option -> option ->
910*83ee113eSDavid van Moolenbroek universe -> name);
911*83ee113eSDavid van Moolenbroek dot = ".";
912*83ee113eSDavid van Moolenbroek }
913*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
914*83ee113eSDavid van Moolenbroek fprintf (file, "%s %s%s%s = ", s, t, dot,
915*83ee113eSDavid van Moolenbroek r -> data.option -> option -> name);
916*83ee113eSDavid van Moolenbroek col = (indent + strlen (s) + strlen (t) +
917*83ee113eSDavid van Moolenbroek strlen (dot) + strlen (r -> data.option ->
918*83ee113eSDavid van Moolenbroek option -> name) + 4);
919*83ee113eSDavid van Moolenbroek if (r -> data.option -> expression)
920*83ee113eSDavid van Moolenbroek write_expression
921*83ee113eSDavid van Moolenbroek (file,
922*83ee113eSDavid van Moolenbroek r -> data.option -> expression,
923*83ee113eSDavid van Moolenbroek col, indent + 8, 1);
924*83ee113eSDavid van Moolenbroek else
925*83ee113eSDavid van Moolenbroek token_indent_data_string
926*83ee113eSDavid van Moolenbroek (file, col, indent + 8, "", "",
927*83ee113eSDavid van Moolenbroek &r -> data.option -> data);
928*83ee113eSDavid van Moolenbroek
929*83ee113eSDavid van Moolenbroek fprintf (file, ";"); /* XXX */
930*83ee113eSDavid van Moolenbroek break;
931*83ee113eSDavid van Moolenbroek
932*83ee113eSDavid van Moolenbroek case set_statement:
933*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
934*83ee113eSDavid van Moolenbroek fprintf (file, "set ");
935*83ee113eSDavid van Moolenbroek col = token_print_indent (file, indent + 4, indent + 4,
936*83ee113eSDavid van Moolenbroek "", "", r -> data.set.name);
937*83ee113eSDavid van Moolenbroek (void) token_print_indent (file, col, indent + 4,
938*83ee113eSDavid van Moolenbroek " ", " ", "=");
939*83ee113eSDavid van Moolenbroek col = write_expression (file, r -> data.set.expr,
940*83ee113eSDavid van Moolenbroek indent + 3, indent + 3, 0);
941*83ee113eSDavid van Moolenbroek (void) token_print_indent (file, col, indent + 4,
942*83ee113eSDavid van Moolenbroek " ", "", ";");
943*83ee113eSDavid van Moolenbroek break;
944*83ee113eSDavid van Moolenbroek
945*83ee113eSDavid van Moolenbroek case unset_statement:
946*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
947*83ee113eSDavid van Moolenbroek fprintf (file, "unset ");
948*83ee113eSDavid van Moolenbroek col = token_print_indent (file, indent + 6, indent + 6,
949*83ee113eSDavid van Moolenbroek "", "", r -> data.set.name);
950*83ee113eSDavid van Moolenbroek (void) token_print_indent (file, col, indent + 6,
951*83ee113eSDavid van Moolenbroek " ", "", ";");
952*83ee113eSDavid van Moolenbroek break;
953*83ee113eSDavid van Moolenbroek
954*83ee113eSDavid van Moolenbroek case log_statement:
955*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
956*83ee113eSDavid van Moolenbroek fprintf (file, "log ");
957*83ee113eSDavid van Moolenbroek col = token_print_indent (file, indent + 4, indent + 4,
958*83ee113eSDavid van Moolenbroek "", "", "(");
959*83ee113eSDavid van Moolenbroek switch (r -> data.log.priority) {
960*83ee113eSDavid van Moolenbroek case log_priority_fatal:
961*83ee113eSDavid van Moolenbroek (void) token_print_indent
962*83ee113eSDavid van Moolenbroek (file, col, indent + 4, "",
963*83ee113eSDavid van Moolenbroek " ", "fatal,");
964*83ee113eSDavid van Moolenbroek break;
965*83ee113eSDavid van Moolenbroek case log_priority_error:
966*83ee113eSDavid van Moolenbroek (void) token_print_indent
967*83ee113eSDavid van Moolenbroek (file, col, indent + 4, "",
968*83ee113eSDavid van Moolenbroek " ", "error,");
969*83ee113eSDavid van Moolenbroek break;
970*83ee113eSDavid van Moolenbroek case log_priority_debug:
971*83ee113eSDavid van Moolenbroek (void) token_print_indent
972*83ee113eSDavid van Moolenbroek (file, col, indent + 4, "",
973*83ee113eSDavid van Moolenbroek " ", "debug,");
974*83ee113eSDavid van Moolenbroek break;
975*83ee113eSDavid van Moolenbroek case log_priority_info:
976*83ee113eSDavid van Moolenbroek (void) token_print_indent
977*83ee113eSDavid van Moolenbroek (file, col, indent + 4, "",
978*83ee113eSDavid van Moolenbroek " ", "info,");
979*83ee113eSDavid van Moolenbroek break;
980*83ee113eSDavid van Moolenbroek }
981*83ee113eSDavid van Moolenbroek col = write_expression (file, r -> data.log.expr,
982*83ee113eSDavid van Moolenbroek indent + 4, indent + 4, 0);
983*83ee113eSDavid van Moolenbroek (void) token_print_indent (file, col, indent + 4,
984*83ee113eSDavid van Moolenbroek "", "", ");");
985*83ee113eSDavid van Moolenbroek
986*83ee113eSDavid van Moolenbroek break;
987*83ee113eSDavid van Moolenbroek
988*83ee113eSDavid van Moolenbroek case execute_statement:
989*83ee113eSDavid van Moolenbroek #ifdef ENABLE_EXECUTE
990*83ee113eSDavid van Moolenbroek indent_spaces (file, indent);
991*83ee113eSDavid van Moolenbroek col = token_print_indent(file, indent + 4, indent + 4,
992*83ee113eSDavid van Moolenbroek "", "", "execute");
993*83ee113eSDavid van Moolenbroek col = token_print_indent(file, col, indent + 4, " ", "",
994*83ee113eSDavid van Moolenbroek "(");
995*83ee113eSDavid van Moolenbroek col = token_print_indent(file, col, indent + 4, "\"", "\"", r->data.execute.command);
996*83ee113eSDavid van Moolenbroek for (expr = r->data.execute.arglist; expr; expr = expr->data.arg.next) {
997*83ee113eSDavid van Moolenbroek col = token_print_indent(file, col, indent + 4, "", " ", ",");
998*83ee113eSDavid van Moolenbroek col = write_expression (file, expr->data.arg.val, col, indent + 4, 0);
999*83ee113eSDavid van Moolenbroek }
1000*83ee113eSDavid van Moolenbroek (void) token_print_indent(file, col, indent + 4, "", "", ");");
1001*83ee113eSDavid van Moolenbroek #else /* !ENABLE_EXECUTE */
1002*83ee113eSDavid van Moolenbroek log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
1003*83ee113eSDavid van Moolenbroek "is not defined).", MDL);
1004*83ee113eSDavid van Moolenbroek #endif /* ENABLE_EXECUTE */
1005*83ee113eSDavid van Moolenbroek break;
1006*83ee113eSDavid van Moolenbroek
1007*83ee113eSDavid van Moolenbroek default:
1008*83ee113eSDavid van Moolenbroek log_fatal ("bogus statement type %d\n", r -> op);
1009*83ee113eSDavid van Moolenbroek }
1010*83ee113eSDavid van Moolenbroek }
1011*83ee113eSDavid van Moolenbroek }
1012*83ee113eSDavid van Moolenbroek
1013*83ee113eSDavid van Moolenbroek /* Find a case statement in the sequence of executable statements that
1014*83ee113eSDavid van Moolenbroek matches the expression, and if found, return the following statement.
1015*83ee113eSDavid van Moolenbroek If no case statement matches, try to find a default statement and
1016*83ee113eSDavid van Moolenbroek return that (the default statement can precede all the case statements).
1017*83ee113eSDavid van Moolenbroek Otherwise, return the null statement. */
1018*83ee113eSDavid van Moolenbroek
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)1019*83ee113eSDavid van Moolenbroek int find_matching_case (struct executable_statement **ep,
1020*83ee113eSDavid van Moolenbroek struct packet *packet, struct lease *lease,
1021*83ee113eSDavid van Moolenbroek struct client_state *client_state,
1022*83ee113eSDavid van Moolenbroek struct option_state *in_options,
1023*83ee113eSDavid van Moolenbroek struct option_state *out_options,
1024*83ee113eSDavid van Moolenbroek struct binding_scope **scope,
1025*83ee113eSDavid van Moolenbroek struct expression *expr,
1026*83ee113eSDavid van Moolenbroek struct executable_statement *stmt)
1027*83ee113eSDavid van Moolenbroek {
1028*83ee113eSDavid van Moolenbroek int status, sub;
1029*83ee113eSDavid van Moolenbroek struct executable_statement *s;
1030*83ee113eSDavid van Moolenbroek
1031*83ee113eSDavid van Moolenbroek if (is_data_expression (expr)) {
1032*83ee113eSDavid van Moolenbroek struct data_string cd, ds;
1033*83ee113eSDavid van Moolenbroek memset (&ds, 0, sizeof ds);
1034*83ee113eSDavid van Moolenbroek memset (&cd, 0, sizeof cd);
1035*83ee113eSDavid van Moolenbroek
1036*83ee113eSDavid van Moolenbroek status = (evaluate_data_expression (&ds, packet, lease,
1037*83ee113eSDavid van Moolenbroek client_state, in_options,
1038*83ee113eSDavid van Moolenbroek out_options, scope, expr,
1039*83ee113eSDavid van Moolenbroek MDL));
1040*83ee113eSDavid van Moolenbroek if (status) {
1041*83ee113eSDavid van Moolenbroek for (s = stmt; s; s = s -> next) {
1042*83ee113eSDavid van Moolenbroek if (s -> op == case_statement) {
1043*83ee113eSDavid van Moolenbroek sub = (evaluate_data_expression
1044*83ee113eSDavid van Moolenbroek (&cd, packet, lease, client_state,
1045*83ee113eSDavid van Moolenbroek in_options, out_options,
1046*83ee113eSDavid van Moolenbroek scope, s->data.c_case, MDL));
1047*83ee113eSDavid van Moolenbroek if (sub && cd.len == ds.len &&
1048*83ee113eSDavid van Moolenbroek !memcmp (cd.data, ds.data, cd.len))
1049*83ee113eSDavid van Moolenbroek {
1050*83ee113eSDavid van Moolenbroek data_string_forget (&cd, MDL);
1051*83ee113eSDavid van Moolenbroek data_string_forget (&ds, MDL);
1052*83ee113eSDavid van Moolenbroek executable_statement_reference
1053*83ee113eSDavid van Moolenbroek (ep, s->next, MDL);
1054*83ee113eSDavid van Moolenbroek return 1;
1055*83ee113eSDavid van Moolenbroek }
1056*83ee113eSDavid van Moolenbroek data_string_forget (&cd, MDL);
1057*83ee113eSDavid van Moolenbroek }
1058*83ee113eSDavid van Moolenbroek }
1059*83ee113eSDavid van Moolenbroek data_string_forget (&ds, MDL);
1060*83ee113eSDavid van Moolenbroek }
1061*83ee113eSDavid van Moolenbroek } else {
1062*83ee113eSDavid van Moolenbroek unsigned long n, c;
1063*83ee113eSDavid van Moolenbroek status = evaluate_numeric_expression (&n, packet, lease,
1064*83ee113eSDavid van Moolenbroek client_state,
1065*83ee113eSDavid van Moolenbroek in_options, out_options,
1066*83ee113eSDavid van Moolenbroek scope, expr);
1067*83ee113eSDavid van Moolenbroek
1068*83ee113eSDavid van Moolenbroek if (status) {
1069*83ee113eSDavid van Moolenbroek for (s = stmt; s; s = s->next) {
1070*83ee113eSDavid van Moolenbroek if (s -> op == case_statement) {
1071*83ee113eSDavid van Moolenbroek sub = (evaluate_numeric_expression
1072*83ee113eSDavid van Moolenbroek (&c, packet, lease, client_state,
1073*83ee113eSDavid van Moolenbroek in_options, out_options,
1074*83ee113eSDavid van Moolenbroek scope, s->data.c_case));
1075*83ee113eSDavid van Moolenbroek if (sub && n == c) {
1076*83ee113eSDavid van Moolenbroek executable_statement_reference
1077*83ee113eSDavid van Moolenbroek (ep, s->next, MDL);
1078*83ee113eSDavid van Moolenbroek return 1;
1079*83ee113eSDavid van Moolenbroek }
1080*83ee113eSDavid van Moolenbroek }
1081*83ee113eSDavid van Moolenbroek }
1082*83ee113eSDavid van Moolenbroek }
1083*83ee113eSDavid van Moolenbroek }
1084*83ee113eSDavid van Moolenbroek
1085*83ee113eSDavid van Moolenbroek /* If we didn't find a matching case statement, look for a default
1086*83ee113eSDavid van Moolenbroek statement and return the statement following it. */
1087*83ee113eSDavid van Moolenbroek for (s = stmt; s; s = s->next)
1088*83ee113eSDavid van Moolenbroek if (s->op == default_statement)
1089*83ee113eSDavid van Moolenbroek break;
1090*83ee113eSDavid van Moolenbroek if (s) {
1091*83ee113eSDavid van Moolenbroek executable_statement_reference (ep, s->next, MDL);
1092*83ee113eSDavid van Moolenbroek return 1;
1093*83ee113eSDavid van Moolenbroek }
1094*83ee113eSDavid van Moolenbroek return 0;
1095*83ee113eSDavid van Moolenbroek }
1096*83ee113eSDavid van Moolenbroek
executable_statement_foreach(struct executable_statement * stmt,int (* callback)(struct executable_statement *,void *,int),void * vp,int condp)1097*83ee113eSDavid van Moolenbroek int executable_statement_foreach (struct executable_statement *stmt,
1098*83ee113eSDavid van Moolenbroek int (*callback) (struct
1099*83ee113eSDavid van Moolenbroek executable_statement *,
1100*83ee113eSDavid van Moolenbroek void *, int),
1101*83ee113eSDavid van Moolenbroek void *vp, int condp)
1102*83ee113eSDavid van Moolenbroek {
1103*83ee113eSDavid van Moolenbroek struct executable_statement *foo;
1104*83ee113eSDavid van Moolenbroek int ok = 0;
1105*83ee113eSDavid van Moolenbroek
1106*83ee113eSDavid van Moolenbroek for (foo = stmt; foo; foo = foo->next) {
1107*83ee113eSDavid van Moolenbroek if ((*callback) (foo, vp, condp) != 0)
1108*83ee113eSDavid van Moolenbroek ok = 1;
1109*83ee113eSDavid van Moolenbroek switch (foo->op) {
1110*83ee113eSDavid van Moolenbroek case null_statement:
1111*83ee113eSDavid van Moolenbroek break;
1112*83ee113eSDavid van Moolenbroek case if_statement:
1113*83ee113eSDavid van Moolenbroek if (executable_statement_foreach (foo->data.ie.tc,
1114*83ee113eSDavid van Moolenbroek callback, vp, 1))
1115*83ee113eSDavid van Moolenbroek ok = 1;
1116*83ee113eSDavid van Moolenbroek if (executable_statement_foreach (foo->data.ie.fc,
1117*83ee113eSDavid van Moolenbroek callback, vp, 1))
1118*83ee113eSDavid van Moolenbroek ok = 1;
1119*83ee113eSDavid van Moolenbroek break;
1120*83ee113eSDavid van Moolenbroek case add_statement:
1121*83ee113eSDavid van Moolenbroek break;
1122*83ee113eSDavid van Moolenbroek case eval_statement:
1123*83ee113eSDavid van Moolenbroek break;
1124*83ee113eSDavid van Moolenbroek case break_statement:
1125*83ee113eSDavid van Moolenbroek break;
1126*83ee113eSDavid van Moolenbroek case default_option_statement:
1127*83ee113eSDavid van Moolenbroek break;
1128*83ee113eSDavid van Moolenbroek case supersede_option_statement:
1129*83ee113eSDavid van Moolenbroek break;
1130*83ee113eSDavid van Moolenbroek case append_option_statement:
1131*83ee113eSDavid van Moolenbroek break;
1132*83ee113eSDavid van Moolenbroek case prepend_option_statement:
1133*83ee113eSDavid van Moolenbroek break;
1134*83ee113eSDavid van Moolenbroek case send_option_statement:
1135*83ee113eSDavid van Moolenbroek break;
1136*83ee113eSDavid van Moolenbroek case statements_statement:
1137*83ee113eSDavid van Moolenbroek if ((executable_statement_foreach
1138*83ee113eSDavid van Moolenbroek (foo->data.statements, callback, vp, condp)))
1139*83ee113eSDavid van Moolenbroek ok = 1;
1140*83ee113eSDavid van Moolenbroek break;
1141*83ee113eSDavid van Moolenbroek case on_statement:
1142*83ee113eSDavid van Moolenbroek if ((executable_statement_foreach
1143*83ee113eSDavid van Moolenbroek (foo->data.on.statements, callback, vp, 1)))
1144*83ee113eSDavid van Moolenbroek ok = 1;
1145*83ee113eSDavid van Moolenbroek break;
1146*83ee113eSDavid van Moolenbroek case switch_statement:
1147*83ee113eSDavid van Moolenbroek if ((executable_statement_foreach
1148*83ee113eSDavid van Moolenbroek (foo->data.s_switch.statements, callback, vp, 1)))
1149*83ee113eSDavid van Moolenbroek ok = 1;
1150*83ee113eSDavid van Moolenbroek break;
1151*83ee113eSDavid van Moolenbroek case case_statement:
1152*83ee113eSDavid van Moolenbroek break;
1153*83ee113eSDavid van Moolenbroek case default_statement:
1154*83ee113eSDavid van Moolenbroek break;
1155*83ee113eSDavid van Moolenbroek case set_statement:
1156*83ee113eSDavid van Moolenbroek break;
1157*83ee113eSDavid van Moolenbroek case unset_statement:
1158*83ee113eSDavid van Moolenbroek break;
1159*83ee113eSDavid van Moolenbroek case let_statement:
1160*83ee113eSDavid van Moolenbroek if ((executable_statement_foreach
1161*83ee113eSDavid van Moolenbroek (foo->data.let.statements, callback, vp, 0)))
1162*83ee113eSDavid van Moolenbroek ok = 1;
1163*83ee113eSDavid van Moolenbroek break;
1164*83ee113eSDavid van Moolenbroek case define_statement:
1165*83ee113eSDavid van Moolenbroek break;
1166*83ee113eSDavid van Moolenbroek case log_statement:
1167*83ee113eSDavid van Moolenbroek case return_statement:
1168*83ee113eSDavid van Moolenbroek case execute_statement:
1169*83ee113eSDavid van Moolenbroek break;
1170*83ee113eSDavid van Moolenbroek }
1171*83ee113eSDavid van Moolenbroek }
1172*83ee113eSDavid van Moolenbroek return ok;
1173*83ee113eSDavid van Moolenbroek }
1174