]> git.ipfire.org Git - thirdparty/dhcp.git/blame - common/execute.c
MASSIVE merge from V3-RELEASE-BRANCH into HEAD. HEAD and V3-RELEASE are
[thirdparty/dhcp.git] / common / execute.c
CommitLineData
055fa312
TL
1/* execute.c
2
3 Support for executable statements. */
4
5/*
98311e4b
DH
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1998-2003 by Internet Software Consortium
055fa312 8 *
98311e4b
DH
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.
055fa312 12 *
98311e4b
DH
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.
055fa312 20 *
98311e4b
DH
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
49733f31 26 *
98311e4b 27 * This software has been written for Internet Systems Consortium
49733f31 28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
98311e4b 29 * To learn more about Internet Systems Consortium, see
49733f31
TL
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''.
055fa312
TL
33 */
34
35#ifndef lint
36static char copyright[] =
98311e4b 37"$Id: execute.c,v 1.47 2005/03/17 20:14:58 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
055fa312
TL
38#endif /* not lint */
39
40#include "dhcpd.h"
4bd8800e 41#include <omapip/omapip_p.h>
055fa312 42
63b4fbf9
TL
43int execute_statements (result, packet, lease, client_state,
44 in_options, out_options, scope, statements)
1b234d44 45 struct binding_value **result;
055fa312 46 struct packet *packet;
da38df14 47 struct lease *lease;
63b4fbf9 48 struct client_state *client_state;
a1933e2d
TL
49 struct option_state *in_options;
50 struct option_state *out_options;
6ceb9118 51 struct binding_scope **scope;
055fa312
TL
52 struct executable_statement *statements;
53{
a75826c6 54 struct executable_statement *r, *e, *next;
1b234d44 55 int rc;
a1933e2d 56 int status;
f6a30e8d
TL
57 unsigned long num;
58 struct binding_scope *outer;
91c82d9f
TL
59 struct binding *binding;
60 struct data_string ds;
f6a30e8d 61 struct binding_scope *ns;
055fa312
TL
62
63 if (!statements)
64 return 1;
65
a75826c6
TL
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);
1b234d44 70 while (r && !(result && *result)) {
a75826c6
TL
71 if (r -> next)
72 executable_statement_reference (&next, r -> next, MDL);
055fa312 73 switch (r -> op) {
79a65726 74 case statements_statement:
8ad81818 75#if defined (DEBUG_EXPRESSIONS)
e92653f1 76 log_debug ("exec: statements");
8ad81818 77#endif
1b234d44 78 status = execute_statements (result, packet, lease,
63b4fbf9
TL
79 client_state, in_options,
80 out_options, scope,
8ad81818
TL
81 r -> data.statements);
82#if defined (DEBUG_EXPRESSIONS)
e92653f1 83 log_debug ("exec: statements returns %d", status);
8ad81818
TL
84#endif
85 if (!status)
79a65726
TL
86 return 0;
87 break;
88
89 case on_statement:
90 if (lease) {
91c82d9f 91 if (r -> data.on.evtypes & ON_EXPIRY) {
9615e0e6
TL
92#if defined (DEBUG_EXPRESSIONS)
93 log_debug ("exec: on expiry");
94#endif
91c82d9f 95 if (lease -> on_expiry)
79a65726 96 executable_statement_dereference
4bd8800e 97 (&lease -> on_expiry, MDL);
f6a30e8d
TL
98 if (r -> data.on.statements)
99 executable_statement_reference
100 (&lease -> on_expiry,
4bd8800e 101 r -> data.on.statements, MDL);
91c82d9f
TL
102 }
103 if (r -> data.on.evtypes & ON_RELEASE) {
9615e0e6
TL
104#if defined (DEBUG_EXPRESSIONS)
105 log_debug ("exec: on release");
106#endif
91c82d9f
TL
107 if (lease -> on_release)
108 executable_statement_dereference
4bd8800e 109 (&lease -> on_release, MDL);
f6a30e8d
TL
110 if (r -> data.on.statements)
111 executable_statement_reference
112 (&lease -> on_release,
4bd8800e 113 r -> data.on.statements, MDL);
91c82d9f
TL
114 }
115 if (r -> data.on.evtypes & ON_COMMIT) {
9615e0e6
TL
116#if defined (DEBUG_EXPRESSIONS)
117 log_debug ("exec: on commit");
118#endif
91c82d9f
TL
119 if (lease -> on_commit)
120 executable_statement_dereference
4bd8800e 121 (&lease -> on_commit, MDL);
f6a30e8d
TL
122 if (r -> data.on.statements)
123 executable_statement_reference
124 (&lease -> on_commit,
4bd8800e 125 r -> data.on.statements, MDL);
91c82d9f 126 }
79a65726
TL
127 }
128 break;
129
91c82d9f 130 case switch_statement:
9615e0e6
TL
131#if defined (DEBUG_EXPRESSIONS)
132 log_debug ("exec: switch");
133#endif
a75826c6 134 status = (find_matching_case
63b4fbf9 135 (&e, packet, lease, client_state,
a75826c6
TL
136 in_options, out_options, scope,
137 r -> data.s_switch.expr,
138 r -> data.s_switch.statements));
9615e0e6
TL
139#if defined (DEBUG_EXPRESSIONS)
140 log_debug ("exec: switch: case %lx", (unsigned long)e);
141#endif
a75826c6
TL
142 if (status) {
143 if (!(execute_statements
63b4fbf9 144 (result, packet, lease, client_state,
a75826c6
TL
145 in_options, out_options, scope, e))) {
146 executable_statement_dereference
147 (&e, MDL);
148 return 0;
149 }
150 executable_statement_dereference (&e, MDL);
151 }
9615e0e6 152 break;
91c82d9f
TL
153
154 /* These have no effect when executed. */
155 case case_statement:
156 case default_statement:
157 break;
158
055fa312 159 case if_statement:
6ceb9118 160 status = (evaluate_boolean_expression
63b4fbf9
TL
161 (&rc, packet,
162 lease, client_state, in_options,
6ceb9118 163 out_options, scope, r -> data.ie.expr));
a1933e2d
TL
164
165#if defined (DEBUG_EXPRESSIONS)
27b3a58f 166 log_debug ("exec: if %s", (status
1b234d44 167 ? (rc ? "true" : "false")
a1933e2d
TL
168 : "NULL"));
169#endif
170 /* XXX Treat NULL as false */
171 if (!status)
1b234d44 172 rc = 0;
055fa312 173 if (!execute_statements
63b4fbf9 174 (result, packet, lease, client_state,
1b234d44 175 in_options, out_options, scope,
d758ad8c 176 rc ? r -> data.ie.tc : r -> data.ie.fc))
055fa312
TL
177 return 0;
178 break;
179
180 case eval_statement:
08514fb8
TL
181 status = evaluate_expression
182 ((struct binding_value **)0,
63b4fbf9 183 packet, lease, client_state, in_options,
d758ad8c 184 out_options, scope, r -> data.eval, MDL);
a1933e2d 185#if defined (DEBUG_EXPRESSIONS)
27b3a58f 186 log_debug ("exec: evaluate: %s",
9615e0e6 187 (status ? "succeeded" : "failed"));
a1933e2d 188#endif
055fa312
TL
189 break;
190
1b234d44
DN
191 case return_statement:
192 status = evaluate_expression
63b4fbf9
TL
193 (result, packet,
194 lease, client_state, in_options,
d758ad8c 195 out_options, scope, r -> data.retval, MDL);
1b234d44
DN
196#if defined (DEBUG_EXPRESSIONS)
197 log_debug ("exec: return: %s",
198 (status ? "succeeded" : "failed"));
199#endif
200 break;
201
055fa312 202 case add_statement:
a1933e2d 203#if defined (DEBUG_EXPRESSIONS)
27b3a58f 204 log_debug ("exec: add %s", (r -> data.add -> name
a1933e2d
TL
205 ? r -> data.add -> name
206 : "<unnamed class>"));
207#endif
055fa312
TL
208 classify (packet, r -> data.add);
209 break;
210
211 case break_statement:
a1933e2d 212#if defined (DEBUG_EXPRESSIONS)
27b3a58f 213 log_debug ("exec: break");
a1933e2d 214#endif
9615e0e6 215 return 1;
055fa312
TL
216
217 case supersede_option_statement:
33454222 218 case send_option_statement:
a1933e2d 219#if defined (DEBUG_EXPRESSIONS)
33454222
TL
220 log_debug ("exec: %s option %s.%s",
221 (r -> op == supersede_option_statement
222 ? "supersede" : "send"),
a1933e2d
TL
223 r -> data.option -> option -> universe -> name,
224 r -> data.option -> option -> name);
225 goto option_statement;
226#endif
055fa312 227 case default_option_statement:
a1933e2d 228#if defined (DEBUG_EXPRESSIONS)
27b3a58f 229 log_debug ("exec: default option %s.%s",
a1933e2d
TL
230 r -> data.option -> option -> universe -> name,
231 r -> data.option -> option -> name);
232 goto option_statement;
233#endif
055fa312 234 case append_option_statement:
a1933e2d 235#if defined (DEBUG_EXPRESSIONS)
27b3a58f 236 log_debug ("exec: append option %s.%s",
a1933e2d
TL
237 r -> data.option -> option -> universe -> name,
238 r -> data.option -> option -> name);
239 goto option_statement;
240#endif
055fa312 241 case prepend_option_statement:
a1933e2d 242#if defined (DEBUG_EXPRESSIONS)
27b3a58f 243 log_debug ("exec: prepend option %s.%s",
a1933e2d
TL
244 r -> data.option -> option -> universe -> name,
245 r -> data.option -> option -> name);
246 option_statement:
247#endif
85c14386
TL
248 set_option (r -> data.option -> option -> universe,
249 out_options, r -> data.option, r -> op);
055fa312
TL
250 break;
251
91c82d9f 252 case set_statement:
1b234d44 253 case define_statement:
6ceb9118
TL
254 if (!scope) {
255 log_error ("set %s: no scope",
256 r -> data.set.name);
257 status = 0;
258 break;
259 }
260 if (!*scope) {
261 if (!binding_scope_allocate (scope, MDL)) {
262 log_error ("set %s: can't allocate scope",
263 r -> data.set.name);
264 status = 0;
265 break;
266 }
267 }
268 binding = find_binding (*scope, r -> data.set.name);
9615e0e6
TL
269#if defined (DEBUG_EXPRESSIONS)
270 log_debug ("exec: set %s", r -> data.set.name);
271#endif
7530a0ab 272 if (!binding) {
4bd8800e 273 binding = dmalloc (sizeof *binding, MDL);
91c82d9f 274 if (binding) {
55321a21 275 memset (binding, 0, sizeof *binding);
91c82d9f
TL
276 binding -> name =
277 dmalloc (strlen
3dc96064 278 (r -> data.set.name) + 1,
4bd8800e 279 MDL);
f6a30e8d 280 if (binding -> name) {
91c82d9f
TL
281 strcpy (binding -> name,
282 r -> data.set.name);
349c525e
DN
283 binding -> next = (*scope) -> bindings;
284 (*scope) -> bindings = binding;
f6a30e8d
TL
285 } else {
286 badalloc:
4bd8800e 287 dfree (binding, MDL);
f6a30e8d
TL
288 binding = (struct binding *)0;
289 }
290 }
91c82d9f
TL
291 }
292 if (binding) {
08514fb8
TL
293 if (binding -> value)
294 binding_value_dereference
295 (&binding -> value, MDL);
1b234d44
DN
296 if (r -> op == set_statement) {
297 status = (evaluate_expression
298 (&binding -> value, packet,
63b4fbf9
TL
299 lease, client_state,
300 in_options, out_options,
d758ad8c
TL
301 scope, r -> data.set.expr,
302 MDL));
1b234d44
DN
303 } else {
304 if (!(binding_value_allocate
305 (&binding -> value, MDL))) {
306 dfree (binding, MDL);
307 binding = (struct binding *)0;
308 }
309 if (binding -> value) {
310 binding -> value -> type =
311 binding_function;
312 (fundef_reference
313 (&binding -> value -> value.fundef,
314 r -> data.set.expr -> data.func,
315 MDL));
316 }
317 }
91c82d9f 318 }
91c82d9f 319#if defined (DEBUG_EXPRESSIONS)
08514fb8
TL
320 log_debug ("exec: set %s%s", r -> data.set.name,
321 (binding && status ? "" : " (failed)"));
91c82d9f
TL
322#endif
323 break;
324
f6a30e8d 325 case unset_statement:
6ceb9118
TL
326 if (!scope || !*scope) {
327 status = 0;
328 break;
329 }
330 binding = find_binding (*scope, r -> data.unset);
f6a30e8d 331 if (binding) {
08514fb8
TL
332 if (binding -> value)
333 binding_value_dereference
334 (&binding -> value, MDL);
f6a30e8d
TL
335 status = 1;
336 } else
337 status = 0;
338#if defined (DEBUG_EXPRESSIONS)
339 log_debug ("exec: unset %s: %s", r -> data.unset,
08514fb8 340 (status ? "found" : "not found"));
f6a30e8d
TL
341#endif
342 break;
343
344 case let_statement:
9615e0e6
TL
345#if defined (DEBUG_EXPRESSIONS)
346 log_debug ("exec: let %s", r -> data.let.name);
347#endif
f6a30e8d 348 ns = (struct binding_scope *)0;
4bd8800e 349 binding_scope_allocate (&ns, MDL);
08514fb8 350 e = r;
f6a30e8d
TL
351
352 next_let:
353 if (ns) {
4bd8800e 354 binding = dmalloc (sizeof *binding, MDL);
55321a21 355 memset (binding, 0, sizeof *binding);
f6a30e8d
TL
356 if (!binding) {
357 blb:
4bd8800e 358 binding_scope_dereference (&ns, MDL);
f6a30e8d
TL
359 } else {
360 binding -> name =
361 dmalloc (strlen
08514fb8 362 (e -> data.let.name + 1),
4bd8800e 363 MDL);
f6a30e8d
TL
364 if (binding -> name)
365 strcpy (binding -> name,
08514fb8 366 e -> data.let.name);
f6a30e8d 367 else {
4bd8800e 368 dfree (binding, MDL);
f6a30e8d
TL
369 binding = (struct binding *)0;
370 goto blb;
371 }
372 }
98311e4b
DH
373 } else
374 binding = NULL;
375
08514fb8
TL
376 if (ns && binding) {
377 status = (evaluate_expression
378 (&binding -> value, packet, lease,
63b4fbf9 379 client_state,
08514fb8 380 in_options, out_options,
d758ad8c 381 scope, e -> data.set.expr, MDL));
f6a30e8d
TL
382 binding -> next = ns -> bindings;
383 ns -> bindings = binding;
384 }
385
f6a30e8d 386#if defined (DEBUG_EXPRESSIONS)
08514fb8
TL
387 log_debug ("exec: let %s%s", e -> data.let.name,
388 (binding && status ? "" : "failed"));
f6a30e8d 389#endif
08514fb8
TL
390 if (!e -> data.let.statements) {
391 } else if (e -> data.let.statements -> op ==
f6a30e8d 392 let_statement) {
08514fb8 393 e = e -> data.let.statements;
f6a30e8d
TL
394 goto next_let;
395 } else if (ns) {
6ceb9118
TL
396 if (scope && *scope)
397 binding_scope_reference (&ns -> outer,
398 *scope, MDL);
f6a30e8d 399 execute_statements
1b234d44 400 (result, packet, lease,
63b4fbf9 401 client_state,
1b234d44 402 in_options, out_options,
6ceb9118 403 &ns, e -> data.let.statements);
f6a30e8d
TL
404 }
405 if (ns)
4bd8800e 406 binding_scope_dereference (&ns, MDL);
f6a30e8d
TL
407 break;
408
e7a9c293
DN
409 case log_statement:
410 memset (&ds, 0, sizeof ds);
411 status = (evaluate_data_expression
63b4fbf9
TL
412 (&ds, packet,
413 lease, client_state, in_options,
d758ad8c
TL
414 out_options, scope, r -> data.log.expr,
415 MDL));
e7a9c293
DN
416
417#if defined (DEBUG_EXPRESSIONS)
418 log_debug ("exec: log");
419#endif
420
421 if (status) {
422 switch (r -> data.log.priority) {
423 case log_priority_fatal:
424 log_fatal ("%.*s", (int)ds.len,
98311e4b 425 ds.data);
e7a9c293
DN
426 break;
427 case log_priority_error:
428 log_error ("%.*s", (int)ds.len,
98311e4b 429 ds.data);
e7a9c293
DN
430 break;
431 case log_priority_debug:
432 log_debug ("%.*s", (int)ds.len,
98311e4b 433 ds.data);
e7a9c293
DN
434 break;
435 case log_priority_info:
436 log_info ("%.*s", (int)ds.len,
98311e4b 437 ds.data);
e7a9c293
DN
438 break;
439 }
440 data_string_forget (&ds, MDL);
441 }
442
443 break;
444
055fa312 445 default:
2bf47722
TL
446 log_error ("bogus statement type %d", r -> op);
447 break;
055fa312 448 }
a75826c6
TL
449 executable_statement_dereference (&r, MDL);
450 if (next) {
451 executable_statement_reference (&r, next, MDL);
452 executable_statement_dereference (&next, MDL);
453 }
055fa312
TL
454 }
455
456 return 1;
457}
458
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
8e7a5c42
TL
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. */
055fa312 465
63b4fbf9
TL
466void execute_statements_in_scope (result, packet,
467 lease, client_state, in_options, out_options,
468 scope, group, limiting_group)
1b234d44 469 struct binding_value **result;
055fa312 470 struct packet *packet;
da38df14 471 struct lease *lease;
63b4fbf9 472 struct client_state *client_state;
8e7a5c42
TL
473 struct option_state *in_options;
474 struct option_state *out_options;
6ceb9118 475 struct binding_scope **scope;
055fa312
TL
476 struct group *group;
477 struct group *limiting_group;
478{
74f45f96
TL
479 struct group *limit;
480
195ce2f8
TL
481 /* If we've recursed as far as we can, return. */
482 if (!group)
483 return;
484
74f45f96
TL
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:
488
489 domain-name "fugue.com";
490 shared-network FOO {
491 host bar {
492 domain-name "othello.fugue.com";
493 fixed-address 10.20.30.40;
494 }
495 subnet 10.20.30.0 netmask 255.255.255.0 {
496 domain-name "manhattan.fugue.com";
497 }
498 }
499
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. */
507
508 for (limit = limiting_group; limit; limit = limit -> next) {
509 if (group == limit)
510 return;
511 }
055fa312 512
8e7a5c42 513 if (group -> next)
63b4fbf9
TL
514 execute_statements_in_scope (result, packet,
515 lease, client_state,
f6a30e8d 516 in_options, out_options, scope,
8e7a5c42 517 group -> next, limiting_group);
63b4fbf9
TL
518 execute_statements (result, packet, lease, client_state, in_options,
519 out_options, scope, group -> statements);
055fa312 520}
d938be7b
TL
521
522/* Dereference or free any subexpressions of a statement being freed. */
523
4bd8800e 524int executable_statement_dereference (ptr, file, line)
d938be7b 525 struct executable_statement **ptr;
4bd8800e
TL
526 const char *file;
527 int line;
d938be7b
TL
528{
529 struct executable_statement *bp;
530
531 if (!ptr || !*ptr) {
4bd8800e 532 log_error ("%s(%d): null pointer", file, line);
d938be7b
TL
533#if defined (POINTER_DEBUG)
534 abort ();
535#else
536 return 0;
537#endif
538 }
539
540 (*ptr) -> refcnt--;
98311e4b 541 rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
f6a30e8d 542 if ((*ptr) -> refcnt > 0) {
d938be7b
TL
543 *ptr = (struct executable_statement *)0;
544 return 1;
545 }
546
f6a30e8d 547 if ((*ptr) -> refcnt < 0) {
4bd8800e 548 log_error ("%s(%d): negative refcnt!", file, line);
f6a30e8d 549#if defined (DEBUG_RC_HISTORY)
d758ad8c 550 dump_rc_history (*ptr);
f6a30e8d
TL
551#endif
552#if defined (POINTER_DEBUG)
553 abort ();
554#else
555 return 0;
556#endif
557 }
558
d938be7b 559 if ((*ptr) -> next)
4bd8800e 560 executable_statement_dereference (&(*ptr) -> next, file, line);
d938be7b
TL
561
562 switch ((*ptr) -> op) {
563 case statements_statement:
ba6cb47a
TL
564 if ((*ptr) -> data.statements)
565 executable_statement_dereference
4bd8800e 566 (&(*ptr) -> data.statements, file, line);
d938be7b
TL
567 break;
568
569 case on_statement:
ba6cb47a
TL
570 if ((*ptr) -> data.on.statements)
571 executable_statement_dereference
4bd8800e 572 (&(*ptr) -> data.on.statements, file, line);
d938be7b
TL
573 break;
574
91c82d9f
TL
575 case switch_statement:
576 if ((*ptr) -> data.s_switch.statements)
577 executable_statement_dereference
4bd8800e 578 (&(*ptr) -> data.on.statements, file, line);
91c82d9f
TL
579 if ((*ptr) -> data.s_switch.expr)
580 expression_dereference (&(*ptr) -> data.s_switch.expr,
4bd8800e 581 file, line);
91c82d9f
TL
582 break;
583
584 case case_statement:
585 if ((*ptr) -> data.s_switch.expr)
586 expression_dereference (&(*ptr) -> data.c_case,
4bd8800e 587 file, line);
91c82d9f
TL
588 break;
589
d938be7b 590 case if_statement:
ba6cb47a 591 if ((*ptr) -> data.ie.expr)
4bd8800e
TL
592 expression_dereference (&(*ptr) -> data.ie.expr,
593 file, line);
d758ad8c 594 if ((*ptr) -> data.ie.tc)
ba6cb47a 595 executable_statement_dereference
d758ad8c
TL
596 (&(*ptr) -> data.ie.tc, file, line);
597 if ((*ptr) -> data.ie.fc)
d938be7b 598 executable_statement_dereference
d758ad8c 599 (&(*ptr) -> data.ie.fc, file, line);
d938be7b
TL
600 break;
601
602 case eval_statement:
ba6cb47a 603 if ((*ptr) -> data.eval)
4bd8800e
TL
604 expression_dereference (&(*ptr) -> data.eval,
605 file, line);
d938be7b
TL
606 break;
607
1b234d44
DN
608 case return_statement:
609 if ((*ptr) -> data.eval)
610 expression_dereference (&(*ptr) -> data.eval,
611 file, line);
612 break;
613
91c82d9f
TL
614 case set_statement:
615 if ((*ptr)->data.set.name)
4bd8800e 616 dfree ((*ptr)->data.set.name, file, line);
91c82d9f
TL
617 if ((*ptr)->data.set.expr)
618 expression_dereference (&(*ptr) -> data.set.expr,
4bd8800e 619 file, line);
91c82d9f
TL
620 break;
621
f6a30e8d
TL
622 case unset_statement:
623 if ((*ptr)->data.unset)
4bd8800e 624 dfree ((*ptr)->data.unset, file, line);
f6a30e8d
TL
625 break;
626
d938be7b 627 case supersede_option_statement:
33454222 628 case send_option_statement:
d938be7b
TL
629 case default_option_statement:
630 case append_option_statement:
631 case prepend_option_statement:
ba6cb47a
TL
632 if ((*ptr) -> data.option)
633 option_cache_dereference (&(*ptr) -> data.option,
4bd8800e 634 file, line);
d938be7b
TL
635 break;
636
637 default:
638 /* Nothing to do. */
8a6dfe4c 639 break;
d938be7b
TL
640 }
641
4bd8800e 642 dfree ((*ptr), file, line);
d938be7b
TL
643 *ptr = (struct executable_statement *)0;
644 return 1;
645}
fa098be8
TL
646
647void write_statements (file, statements, indent)
648 FILE *file;
649 struct executable_statement *statements;
650 int indent;
651{
652 struct executable_statement *r, *x;
653 int result;
654 int status;
b1b7b521 655 const char *s, *t, *dot;
fa098be8
TL
656 int col;
657
658 if (!statements)
659 return;
660
661 for (r = statements; r; r = r -> next) {
662 switch (r -> op) {
663 case statements_statement:
664 write_statements (file, r -> data.statements, indent);
665 break;
666
667 case on_statement:
fa098be8 668 indent_spaces (file, indent);
91c82d9f
TL
669 fprintf (file, "on ");
670 s = "";
671 if (r -> data.on.evtypes & ON_EXPIRY) {
f6a30e8d
TL
672 fprintf (file, "%sexpiry", s);
673 s = " or ";
91c82d9f
TL
674 }
675 if (r -> data.on.evtypes & ON_COMMIT) {
f6a30e8d 676 fprintf (file, "%scommit", s);
91c82d9f
TL
677 s = "or";
678 }
679 if (r -> data.on.evtypes & ON_RELEASE) {
f6a30e8d 680 fprintf (file, "%srelease", s);
91c82d9f
TL
681 s = "or";
682 }
f6a30e8d
TL
683 if (r -> data.on.statements) {
684 fprintf (file, " {");
685 write_statements (file,
686 r -> data.on.statements,
687 indent + 2);
688 indent_spaces (file, indent);
689 fprintf (file, "}");
690 } else {
691 fprintf (file, ";");
692 }
fa098be8
TL
693 break;
694
91c82d9f
TL
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,
702 "", "", ")");
703 token_print_indent (file,
704 col, indent, " ", "", "{");
705 write_statements (file, r -> data.s_switch.statements,
706 indent + 2);
707 indent_spaces (file, indent);
708 fprintf (file, "}");
709 break;
710
711 case case_statement:
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,
718 "", "", ":");
719 break;
720
721 case default_statement:
722 indent_spaces (file, indent - 1);
723 fprintf (file, "default: ");
724 break;
725
fa098be8
TL
726 case if_statement:
727 indent_spaces (file, indent);
728 fprintf (file, "if ");
729 x = r;
730 col = write_expression (file,
731 x -> data.ie.expr,
91c82d9f 732 indent + 3, indent + 3, 1);
fa098be8
TL
733 else_if:
734 token_print_indent (file, col, indent, " ", "", "{");
d758ad8c
TL
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) {
fa098be8
TL
739 indent_spaces (file, indent);
740 fprintf (file, "} elsif ");
d758ad8c 741 x = x -> data.ie.fc;
fa098be8
TL
742 col = write_expression (file,
743 x -> data.ie.expr,
744 indent + 6,
91c82d9f 745 indent + 6, 1);
fa098be8
TL
746 goto else_if;
747 }
d758ad8c 748 if (x -> data.ie.fc) {
fa098be8
TL
749 indent_spaces (file, indent);
750 fprintf (file, "} else {");
d758ad8c 751 write_statements (file, x -> data.ie.fc,
fa098be8
TL
752 indent + 2);
753 }
754 indent_spaces (file, indent);
755 fprintf (file, "}");
756 break;
757
758 case eval_statement:
759 indent_spaces (file, indent);
760 fprintf (file, "eval ");
761 col = write_expression (file, r -> data.eval,
91c82d9f 762 indent + 5, indent + 5, 1);
fa098be8
TL
763 fprintf (file, ";");
764 break;
765
1b234d44
DN
766 case return_statement:
767 indent_spaces (file, indent);
768 fprintf (file, "return;");
769 break;
770
fa098be8
TL
771 case add_statement:
772 indent_spaces (file, indent);
773 fprintf (file, "add \"%s\"", r -> data.add -> name);
774 break;
775
776 case break_statement:
777 indent_spaces (file, indent);
778 fprintf (file, "break;");
779 break;
780
781 case supersede_option_statement:
33454222 782 case send_option_statement:
fa098be8
TL
783 s = "supersede";
784 goto option_statement;
785
786 case default_option_statement:
787 s = "default";
788 goto option_statement;
789
790 case append_option_statement:
791 s = "append";
792 goto option_statement;
793
794 case prepend_option_statement:
795 s = "prepend";
796 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
801 error. */
802 if (r -> data.option -> option -> universe ==
803 &dhcp_universe) {
c9b01dcf 804 t = "";
fa098be8
TL
805 dot = "";
806 } else {
807 t = (r -> data.option -> option ->
808 universe -> name);
809 dot = ".";
810 }
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)
818 write_expression
819 (file,
820 r -> data.option -> expression,
91c82d9f 821 col, indent + 8, 1);
fa098be8
TL
822 else
823 token_indent_data_string
824 (file, col, indent + 8, "", "",
825 &r -> data.option -> data);
826
827 fprintf (file, ";"); /* XXX */
828 break;
829
91c82d9f
TL
830 case set_statement:
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,
836 " ", " ", "=");
837 col = write_expression (file, r -> data.set.expr,
838 indent + 3, indent + 3, 0);
839 col = token_print_indent (file, col, indent + 4,
840 " ", "", ";");
841 break;
842
f6a30e8d
TL
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,
849 " ", "", ";");
850 break;
81beacfb
DN
851
852 case log_statement:
853 indent_spaces (file, indent);
854 fprintf (file, "log ");
98311e4b 855 col = token_print_indent (file, indent + 4, indent + 4,
81beacfb
DN
856 "", "", "(");
857 switch (r -> data.log.priority) {
858 case log_priority_fatal:
859 col = token_print_indent
860 (file, col, indent + 4, "",
861 " ", "fatal,");
862 break;
863 case log_priority_error:
864 col = token_print_indent
865 (file, col, indent + 4, "",
866 " ", "error,");
867 break;
868 case log_priority_debug:
869 col = token_print_indent
870 (file, col, indent + 4, "",
871 " ", "debug,");
872 break;
873 case log_priority_info:
874 col = token_print_indent
875 (file, col, indent + 4, "",
876 " ", "info,");
877 break;
878 }
879 col = write_expression (file, r -> data.log.expr,
880 indent + 4, indent + 4, 0);
881 col = token_print_indent (file, col, indent + 4,
882 "", "", ");");
883
884 break;
f6a30e8d 885
fa098be8
TL
886 default:
887 log_fatal ("bogus statement type %d\n", r -> op);
888 }
889 }
890}
91c82d9f
TL
891
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. */
897
a75826c6
TL
898int find_matching_case (struct executable_statement **ep,
899 struct packet *packet, struct lease *lease,
63b4fbf9 900 struct client_state *client_state,
a75826c6
TL
901 struct option_state *in_options,
902 struct option_state *out_options,
6ceb9118 903 struct binding_scope **scope,
a75826c6
TL
904 struct expression *expr,
905 struct executable_statement *stmt)
91c82d9f
TL
906{
907 int status, sub;
908 struct executable_statement *s;
909 unsigned long foo;
910
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);
916
f6a30e8d 917 status = (evaluate_data_expression (&ds, packet, lease,
63b4fbf9 918 client_state, in_options,
d758ad8c
TL
919 out_options, scope, expr,
920 MDL));
91c82d9f
TL
921 if (status) {
922 for (s = stmt; s; s = s -> next) {
923 if (s -> op == case_statement) {
924 sub = (evaluate_data_expression
63b4fbf9
TL
925 (&cd, packet, lease, client_state,
926 in_options, out_options,
d758ad8c 927 scope, s -> data.c_case, MDL));
91c82d9f
TL
928 if (sub && cd.len == ds.len &&
929 !memcmp (cd.data, ds.data, cd.len))
930 {
4bd8800e
TL
931 data_string_forget (&cd, MDL);
932 data_string_forget (&ds, MDL);
a75826c6
TL
933 executable_statement_reference
934 (ep, s -> next, MDL);
935 return 1;
91c82d9f 936 }
4bd8800e 937 data_string_forget (&cd, MDL);
91c82d9f
TL
938 }
939 }
4bd8800e 940 data_string_forget (&ds, MDL);
91c82d9f
TL
941 }
942 } else {
943 unsigned long n, c;
f6a30e8d 944 status = evaluate_numeric_expression (&n, packet, lease,
63b4fbf9 945 client_state,
f6a30e8d
TL
946 in_options, out_options,
947 scope, expr);
91c82d9f
TL
948
949 if (status) {
950 for (s = stmt; s; s = s -> next) {
951 if (s -> op == case_statement) {
952 sub = (evaluate_numeric_expression
63b4fbf9
TL
953 (&c, packet, lease, client_state,
954 in_options, out_options,
955 scope, s -> data.c_case));
a75826c6
TL
956 if (sub && n == c) {
957 executable_statement_reference
958 (ep, s -> next, MDL);
959 return 1;
960 }
91c82d9f
TL
961 }
962 }
963 }
964 }
965
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)
970 break;
a75826c6
TL
971 if (s) {
972 executable_statement_reference (ep, s -> next, MDL);
973 return 1;
974 }
975 return 0;
91c82d9f 976}
d758ad8c
TL
977
978int executable_statement_foreach (struct executable_statement *stmt,
979 int (*callback) (struct
980 executable_statement *,
981 void *, int),
982 void *vp, int condp)
983{
984 struct executable_statement *foo;
985 int ok = 0;
986 int result;
987
988 for (foo = stmt; foo; foo = foo -> next) {
989 if ((*callback) (foo, vp, condp) != 0)
990 ok = 1;
991 switch (foo -> op) {
992 case null_statement:
993 break;
994 case if_statement:
a609e69b 995 if (executable_statement_foreach (foo -> data.ie.tc,
d758ad8c
TL
996 callback, vp, 1))
997 ok = 1;
a609e69b 998 if (executable_statement_foreach (foo -> data.ie.fc,
d758ad8c
TL
999 callback, vp, 1))
1000 ok = 1;
1001 break;
1002 case add_statement:
1003 break;
1004 case eval_statement:
1005 break;
1006 case break_statement:
1007 break;
1008 case default_option_statement:
1009 break;
1010 case supersede_option_statement:
1011 break;
1012 case append_option_statement:
1013 break;
1014 case prepend_option_statement:
1015 break;
1016 case send_option_statement:
1017 break;
1018 case statements_statement:
1019 if ((executable_statement_foreach
a609e69b 1020 (foo -> data.statements, callback, vp, condp)))
d758ad8c
TL
1021 ok = 1;
1022 break;
1023 case on_statement:
1024 if ((executable_statement_foreach
a609e69b 1025 (foo -> data.on.statements, callback, vp, 1)))
d758ad8c
TL
1026 ok = 1;
1027 break;
1028 case switch_statement:
1029 if ((executable_statement_foreach
a609e69b 1030 (foo -> data.s_switch.statements, callback, vp, 1)))
d758ad8c
TL
1031 ok = 1;
1032 break;
1033 case case_statement:
1034 break;
1035 case default_statement:
1036 break;
1037 case set_statement:
1038 break;
1039 case unset_statement:
1040 break;
1041 case let_statement:
1042 if ((executable_statement_foreach
a609e69b 1043 (foo -> data.let.statements, callback, vp, 0)))
d758ad8c
TL
1044 ok = 1;
1045 break;
1046 case define_statement:
1047 break;
1048 case log_statement:
1049 case return_statement:
1050 break;
1051 }
1052 }
1053 return ok;
1054}