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