ISC DHCP  4.3.0
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) 2009,2013,2014 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;
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  default:
535  log_error ("bogus statement type %d", r -> op);
536  break;
537  }
539  if (next) {
542  }
543  }
544 
545  return 1;
546 }
547 
548 /* Execute all the statements in a particular scope, and all statements in
549  scopes outer from that scope, but if a particular limiting scope is
550  reached, do not execute statements in that scope or in scopes outer
551  from it. More specific scopes need to take precedence over less
552  specific scopes, so we recursively traverse the scope list, executing
553  the most outer scope first. */
554 
555 void execute_statements_in_scope (result, packet,
556  lease, client_state, in_options, out_options,
557  scope, group, limiting_group, on_star)
558  struct binding_value **result;
559  struct packet *packet;
560  struct lease *lease;
561  struct client_state *client_state;
562  struct option_state *in_options;
563  struct option_state *out_options;
564  struct binding_scope **scope;
565  struct group *group;
566  struct group *limiting_group;
567  struct on_star *on_star;
568 {
569  struct group *limit;
570 
571  /* If we've recursed as far as we can, return. */
572  if (!group)
573  return;
574 
575  /* As soon as we get to a scope that is outer than the limiting
576  scope, we are done. This is so that if somebody does something
577  like this, it does the expected thing:
578 
579  domain-name "fugue.com";
580  shared-network FOO {
581  host bar {
582  domain-name "othello.fugue.com";
583  fixed-address 10.20.30.40;
584  }
585  subnet 10.20.30.0 netmask 255.255.255.0 {
586  domain-name "manhattan.fugue.com";
587  }
588  }
589 
590  The problem with the above arrangement is that the host's
591  group nesting will be host -> shared-network -> top-level,
592  and the limiting scope when we evaluate the host's scope
593  will be the subnet -> shared-network -> top-level, so we need
594  to know when we evaluate the host's scope to stop before we
595  evaluate the shared-networks scope, because it's outer than
596  the limiting scope, which means we've already evaluated it. */
597 
598  for (limit = limiting_group; limit; limit = limit -> next) {
599  if (group == limit)
600  return;
601  }
602 
603  if (group -> next)
604  execute_statements_in_scope (result, packet,
605  lease, client_state,
606  in_options, out_options, scope,
607  group->next, limiting_group,
608  on_star);
609  execute_statements (result, packet, lease, client_state, in_options,
610  out_options, scope, group->statements, on_star);
611 }
612 
613 /* Dereference or free any subexpressions of a statement being freed. */
614 
616  struct executable_statement **ptr;
617  const char *file;
618  int line;
619 {
620  if (!ptr || !*ptr) {
621  log_error ("%s(%d): null pointer", file, line);
622 #if defined (POINTER_DEBUG)
623  abort ();
624 #else
625  return 0;
626 #endif
627  }
628 
629  (*ptr) -> refcnt--;
630  rc_register (file, line, ptr, *ptr, (*ptr) -> refcnt, 1, RC_MISC);
631  if ((*ptr) -> refcnt > 0) {
632  *ptr = (struct executable_statement *)0;
633  return 1;
634  }
635 
636  if ((*ptr) -> refcnt < 0) {
637  log_error ("%s(%d): negative refcnt!", file, line);
638 #if defined (DEBUG_RC_HISTORY)
639  dump_rc_history (*ptr);
640 #endif
641 #if defined (POINTER_DEBUG)
642  abort ();
643 #else
644  return 0;
645 #endif
646  }
647 
648  if ((*ptr) -> next)
650 
651  switch ((*ptr) -> op) {
653  if ((*ptr) -> data.statements)
655  (&(*ptr) -> data.statements, file, line);
656  break;
657 
658  case on_statement:
659  if ((*ptr) -> data.on.statements)
661  (&(*ptr) -> data.on.statements, file, line);
662  break;
663 
664  case switch_statement:
665  if ((*ptr) -> data.s_switch.statements)
667  (&(*ptr) -> data.on.statements, file, line);
668  if ((*ptr) -> data.s_switch.expr)
669  expression_dereference (&(*ptr) -> data.s_switch.expr,
670  file, line);
671  break;
672 
673  case case_statement:
674  if ((*ptr) -> data.s_switch.expr)
675  expression_dereference (&(*ptr) -> data.c_case,
676  file, line);
677  break;
678 
679  case if_statement:
680  if ((*ptr) -> data.ie.expr)
681  expression_dereference (&(*ptr) -> data.ie.expr,
682  file, line);
683  if ((*ptr) -> data.ie.tc)
685  (&(*ptr) -> data.ie.tc, file, line);
686  if ((*ptr) -> data.ie.fc)
688  (&(*ptr) -> data.ie.fc, file, line);
689  break;
690 
691  case eval_statement:
692  if ((*ptr) -> data.eval)
693  expression_dereference (&(*ptr) -> data.eval,
694  file, line);
695  break;
696 
697  case return_statement:
698  if ((*ptr) -> data.eval)
699  expression_dereference (&(*ptr) -> data.eval,
700  file, line);
701  break;
702 
703  case set_statement:
704  if ((*ptr)->data.set.name)
705  dfree ((*ptr)->data.set.name, file, line);
706  if ((*ptr)->data.set.expr)
707  expression_dereference (&(*ptr) -> data.set.expr,
708  file, line);
709  break;
710 
711  case unset_statement:
712  if ((*ptr)->data.unset)
713  dfree ((*ptr)->data.unset, file, line);
714  break;
715 
716  case execute_statement:
717  if ((*ptr)->data.execute.command)
718  dfree ((*ptr)->data.execute.command, file, line);
719  if ((*ptr)->data.execute.arglist)
720  expression_dereference (&(*ptr) -> data.execute.arglist,
721  file, line);
722  break;
723 
729  if ((*ptr) -> data.option)
730  option_cache_dereference (&(*ptr) -> data.option,
731  file, line);
732  break;
733 
734  default:
735  /* Nothing to do. */
736  break;
737  }
738 
739  dfree ((*ptr), file, line);
740  *ptr = (struct executable_statement *)0;
741  return 1;
742 }
743 
744 void write_statements (file, statements, indent)
745  FILE *file;
747  int indent;
748 {
749 #if defined ENABLE_EXECUTE
750  struct expression *expr;
751 #endif
752  struct executable_statement *r, *x;
753  const char *s, *t, *dot;
754  int col;
755 
756  if (!statements)
757  return;
758 
759  for (r = statements; r; r = r -> next) {
760  switch (r -> op) {
762  write_statements (file, r -> data.statements, indent);
763  break;
764 
765  case on_statement:
767  fprintf (file, "on ");
768  s = "";
769  if (r -> data.on.evtypes & ON_EXPIRY) {
770  fprintf (file, "%sexpiry", s);
771  s = " or ";
772  }
773  if (r -> data.on.evtypes & ON_COMMIT) {
774  fprintf (file, "%scommit", s);
775  s = " or ";
776  }
777  if (r -> data.on.evtypes & ON_RELEASE) {
778  fprintf (file, "%srelease", s);
779  /* s = " or "; */
780  }
781  if (r -> data.on.statements) {
782  fprintf (file, " {");
784  r -> data.on.statements,
785  indent + 2);
787  fprintf (file, "}");
788  } else {
789  fprintf (file, ";");
790  }
791  break;
792 
793  case switch_statement:
795  fprintf (file, "switch (");
796  col = write_expression (file,
797  r -> data.s_switch.expr,
798  indent + 7, indent + 7, 1);
799  col = token_print_indent (file, col, indent + 7,
800  "", "", ")");
802  col, indent, " ", "", "{");
803  write_statements (file, r -> data.s_switch.statements,
804  indent + 2);
806  fprintf (file, "}");
807  break;
808 
809  case case_statement:
810  indent_spaces (file, indent - 1);
811  fprintf (file, "case ");
812  col = write_expression (file,
813  r -> data.s_switch.expr,
814  indent + 5, indent + 5, 1);
815  token_print_indent (file, col, indent + 5,
816  "", "", ":");
817  break;
818 
819  case default_statement:
820  indent_spaces (file, indent - 1);
821  fprintf (file, "default: ");
822  break;
823 
824  case if_statement:
826  fprintf (file, "if ");
827  x = r;
828  col = write_expression (file,
829  x -> data.ie.expr,
830  indent + 3, indent + 3, 1);
831  else_if:
832  token_print_indent (file, col, indent, " ", "", "{");
833  write_statements (file, x -> data.ie.tc, indent + 2);
834  if (x -> data.ie.fc &&
835  x -> data.ie.fc -> op == if_statement &&
836  !x -> data.ie.fc -> next) {
838  fprintf (file, "} elsif ");
839  x = x -> data.ie.fc;
840  col = write_expression (file,
841  x -> data.ie.expr,
842  indent + 6,
843  indent + 6, 1);
844  goto else_if;
845  }
846  if (x -> data.ie.fc) {
848  fprintf (file, "} else {");
849  write_statements (file, x -> data.ie.fc,
850  indent + 2);
851  }
853  fprintf (file, "}");
854  break;
855 
856  case eval_statement:
858  fprintf (file, "eval ");
859  (void) write_expression (file, r -> data.eval,
860  indent + 5, indent + 5, 1);
861  fprintf (file, ";");
862  break;
863 
864  case return_statement:
866  fprintf (file, "return;");
867  break;
868 
869  case add_statement:
871  fprintf (file, "add \"%s\"", r -> data.add -> name);
872  break;
873 
874  case break_statement:
876  fprintf (file, "break;");
877  break;
878 
881  s = "supersede";
882  goto option_statement;
883 
885  s = "default";
886  goto option_statement;
887 
889  s = "append";
890  goto option_statement;
891 
893  s = "prepend";
894  option_statement:
895  /* Note: the reason we don't try to pretty print
896  the option here is that the format of the option
897  may change in dhcpd.conf, and then when this
898  statement was read back, it would cause a syntax
899  error. */
900  if (r -> data.option -> option -> universe ==
901  &dhcp_universe) {
902  t = "";
903  dot = "";
904  } else {
905  t = (r -> data.option -> option ->
906  universe -> name);
907  dot = ".";
908  }
910  fprintf (file, "%s %s%s%s = ", s, t, dot,
911  r -> data.option -> option -> name);
912  col = (indent + strlen (s) + strlen (t) +
913  strlen (dot) + strlen (r -> data.option ->
914  option -> name) + 4);
915  if (r -> data.option -> expression)
917  (file,
918  r -> data.option -> expression,
919  col, indent + 8, 1);
920  else
922  (file, col, indent + 8, "", "",
923  &r -> data.option -> data);
924 
925  fprintf (file, ";"); /* XXX */
926  break;
927 
928  case set_statement:
930  fprintf (file, "set ");
931  col = token_print_indent (file, indent + 4, indent + 4,
932  "", "", r -> data.set.name);
933  (void) token_print_indent (file, col, indent + 4,
934  " ", " ", "=");
935  col = write_expression (file, r -> data.set.expr,
936  indent + 3, indent + 3, 0);
937  (void) token_print_indent (file, col, indent + 4,
938  " ", "", ";");
939  break;
940 
941  case unset_statement:
943  fprintf (file, "unset ");
944  col = token_print_indent (file, indent + 6, indent + 6,
945  "", "", r -> data.set.name);
946  (void) token_print_indent (file, col, indent + 6,
947  " ", "", ";");
948  break;
949 
950  case log_statement:
952  fprintf (file, "log ");
953  col = token_print_indent (file, indent + 4, indent + 4,
954  "", "", "(");
955  switch (r -> data.log.priority) {
956  case log_priority_fatal:
957  (void) token_print_indent
958  (file, col, indent + 4, "",
959  " ", "fatal,");
960  break;
961  case log_priority_error:
962  (void) token_print_indent
963  (file, col, indent + 4, "",
964  " ", "error,");
965  break;
966  case log_priority_debug:
967  (void) token_print_indent
968  (file, col, indent + 4, "",
969  " ", "debug,");
970  break;
971  case log_priority_info:
972  (void) token_print_indent
973  (file, col, indent + 4, "",
974  " ", "info,");
975  break;
976  }
977  col = write_expression (file, r -> data.log.expr,
978  indent + 4, indent + 4, 0);
979  (void) token_print_indent (file, col, indent + 4,
980  "", "", ");");
981 
982  break;
983 
984  case execute_statement:
985 #ifdef ENABLE_EXECUTE
987  col = token_print_indent(file, indent + 4, indent + 4,
988  "", "", "execute");
989  col = token_print_indent(file, col, indent + 4, " ", "",
990  "(");
991  col = token_print_indent(file, col, indent + 4, "\"", "\"", r->data.execute.command);
992  for (expr = r->data.execute.arglist; expr; expr = expr->data.arg.next) {
993  col = token_print_indent(file, col, indent + 4, "", " ", ",");
994  col = write_expression (file, expr->data.arg.val, col, indent + 4, 0);
995  }
996  (void) token_print_indent(file, col, indent + 4, "", "", ");");
997 #else /* !ENABLE_EXECUTE */
998  log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
999  "is not defined).", MDL);
1000 #endif /* ENABLE_EXECUTE */
1001  break;
1002 
1003  default:
1004  log_fatal ("bogus statement type %d\n", r -> op);
1005  }
1006  }
1007 }
1008 
1009 /* Find a case statement in the sequence of executable statements that
1010  matches the expression, and if found, return the following statement.
1011  If no case statement matches, try to find a default statement and
1012  return that (the default statement can precede all the case statements).
1013  Otherwise, return the null statement. */
1014 
1016  struct packet *packet, struct lease *lease,
1017  struct client_state *client_state,
1018  struct option_state *in_options,
1019  struct option_state *out_options,
1020  struct binding_scope **scope,
1021  struct expression *expr,
1022  struct executable_statement *stmt)
1023 {
1024  int status, sub;
1025  struct executable_statement *s;
1026 
1027  if (is_data_expression (expr)) {
1028  struct data_string cd, ds;
1029  memset (&ds, 0, sizeof ds);
1030  memset (&cd, 0, sizeof cd);
1031 
1032  status = (evaluate_data_expression (&ds, packet, lease,
1033  client_state, in_options,
1034  out_options, scope, expr,
1035  MDL));
1036  if (status) {
1037  for (s = stmt; s; s = s -> next) {
1038  if (s -> op == case_statement) {
1040  (&cd, packet, lease, client_state,
1041  in_options, out_options,
1042  scope, s->data.c_case, MDL));
1043  if (sub && cd.len == ds.len &&
1044  !memcmp (cd.data, ds.data, cd.len))
1045  {
1046  data_string_forget (&cd, MDL);
1047  data_string_forget (&ds, MDL);
1049  (ep, s->next, MDL);
1050  return 1;
1051  }
1052  data_string_forget (&cd, MDL);
1053  }
1054  }
1055  data_string_forget (&ds, MDL);
1056  }
1057  } else {
1058  unsigned long n, c;
1059  status = evaluate_numeric_expression (&n, packet, lease,
1060  client_state,
1061  in_options, out_options,
1062  scope, expr);
1063 
1064  if (status) {
1065  for (s = stmt; s; s = s->next) {
1066  if (s -> op == case_statement) {
1068  (&c, packet, lease, client_state,
1069  in_options, out_options,
1070  scope, s->data.c_case));
1071  if (sub && n == c) {
1073  (ep, s->next, MDL);
1074  return 1;
1075  }
1076  }
1077  }
1078  }
1079  }
1080 
1081  /* If we didn't find a matching case statement, look for a default
1082  statement and return the statement following it. */
1083  for (s = stmt; s; s = s->next)
1084  if (s->op == default_statement)
1085  break;
1086  if (s) {
1088  return 1;
1089  }
1090  return 0;
1091 }
1092 
1094  int (*callback) (struct
1096  void *, int),
1097  void *vp, int condp)
1098 {
1099  struct executable_statement *foo;
1100  int ok = 0;
1101 
1102  for (foo = stmt; foo; foo = foo->next) {
1103  if ((*callback) (foo, vp, condp) != 0)
1104  ok = 1;
1105  switch (foo->op) {
1106  case null_statement:
1107  break;
1108  case if_statement:
1109  if (executable_statement_foreach (foo->data.ie.tc,
1110  callback, vp, 1))
1111  ok = 1;
1112  if (executable_statement_foreach (foo->data.ie.fc,
1113  callback, vp, 1))
1114  ok = 1;
1115  break;
1116  case add_statement:
1117  break;
1118  case eval_statement:
1119  break;
1120  case break_statement:
1121  break;
1123  break;
1125  break;
1127  break;
1129  break;
1130  case send_option_statement:
1131  break;
1132  case statements_statement:
1134  (foo->data.statements, callback, vp, condp)))
1135  ok = 1;
1136  break;
1137  case on_statement:
1139  (foo->data.on.statements, callback, vp, 1)))
1140  ok = 1;
1141  break;
1142  case switch_statement:
1144  (foo->data.s_switch.statements, callback, vp, 1)))
1145  ok = 1;
1146  break;
1147  case case_statement:
1148  break;
1149  case default_statement:
1150  break;
1151  case set_statement:
1152  break;
1153  case unset_statement:
1154  break;
1155  case let_statement:
1157  (foo->data.let.statements, callback, vp, 0)))
1158  ok = 1;
1159  break;
1160  case define_statement:
1161  break;
1162  case log_statement:
1163  case return_statement:
1164  case execute_statement:
1165  break;
1166  }
1167  }
1168  return ok;
1169 }
const char * name
Definition: tree.h:302
enum expr_op op
Definition: tree.h:199
#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:3535
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:2173
struct on_star on_star
Definition: dhcpd.h:523
struct universe * universe
Definition: tree.h:348
int binding_value_dereference(struct binding_value **v, const char *file, int line)
Definition: tree.c:653
Definition: dhcpd.h:507
unsigned len
Definition: tree.h:80
int executable_statement_dereference(struct executable_statement **ptr, const char *file, int line)
Definition: execute.c:615
struct expression * val
Definition: tree.h:269
struct class * add
Definition: statement.h:63
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:2699
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:503
struct universe dhcp_universe
void data_string_forget(struct data_string *data, const char *file, int line)
Definition: alloc.c:1276
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:2173
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:1015
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:3722
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:31
struct expression * expr
Definition: statement.h:59
Definition: dhcpd.h:500
Definition: tree.h:301
char * name
Definition: dhcpd.h:979
void expression_dereference(struct expression **eptr, const char *file, int line)
Definition: tree.c:2751
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:857
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:555
Definition: tree.h:345
char * name
Definition: tree.h:120
void classify(struct packet *packet, struct class *class)
Definition: dhclient.c:1234
struct option_cache * option
Definition: statement.h:64
int binding_scope_allocate(struct binding_scope **ptr, const char *file, int line)
Definition: alloc.c:1195
struct group * next
Definition: dhcpd.h:850
struct executable_statement::@7::@10 s_switch
Definition: dhcpd.h:369
struct expression * next
Definition: tree.h:270
void dfree(void *, const char *, int)
Definition: alloc.c:131
struct executable_statement::@7::@11 let
const char * name
Definition: tree.h:346
struct option * option
Definition: dhcpd.h:353
int int log_info(const char *,...) __attribute__((__format__(__printf__
void write_statements(FILE *file, struct executable_statement *statements, int indent)
Definition: execute.c:744
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:1114
struct executable_statement::@7::@9 on
int executable_statement_foreach(struct executable_statement *stmt, int(*callback)(struct executable_statement *, void *, int), void *vp, int condp)
Definition: execute.c:1093
union executable_statement::@7 data
union binding_value::value value
#define ON_COMMIT
Definition: statement.h:71
Definition: dhcpd.h:849
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:72
struct executable_statement::@7::@8 ie
int is_data_expression(struct expression *expr)
Definition: tree.c:2986
struct binding_value * value
Definition: tree.h:121
struct executable_statement * statements
Definition: statement.h:68
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:81
struct executable_statement * on_expiry
Definition: dhcpd.h:501
int write_expression(FILE *file, struct expression *expr, int col, int indent, int firstp)
Definition: tree.c:3234
struct binding * find_binding(struct binding_scope *scope, const char *name)
Definition: tree.c:3691
const char * file
Definition: dhcpd.h:3535
#define ON_RELEASE
Definition: statement.h:73
struct executable_statement * on_commit
Definition: dhcpd.h:502
const unsigned char * data
Definition: tree.h:79
struct expression * eval
Definition: statement.h:61
#define RC_MISC
Definition: alloc.h:56