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