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