ISC DHCP  4.3.6
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 <isc/util.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,
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;
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  if (!binding) {
445  blb:
447  } else {
448  memset(binding, 0, sizeof(*binding));
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 */
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 "example.com";
588  shared-network FOO {
589  host bar {
590  domain-name "othello.example.com";
591  fixed-address 10.20.30.40;
592  }
593  subnet 10.20.30.0 netmask 255.255.255.0 {
594  domain-name "manhattan.example.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)
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)
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:
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, " {");
792  r -> data.on.statements,
793  indent + 2);
795  fprintf (file, "}");
796  } else {
797  fprintf (file, ";");
798  }
799  break;
800 
801  case switch_statement:
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  "", "", ")");
810  col, indent, " ", "", "{");
811  write_statements (file, r -> data.s_switch.statements,
812  indent + 2);
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:
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) {
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) {
856  fprintf (file, "} else {");
857  write_statements (file, x -> data.ie.fc,
858  indent + 2);
859  }
861  fprintf (file, "}");
862  break;
863 
864  case eval_statement:
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:
874  fprintf (file, "return;");
875  break;
876 
877  case add_statement:
879  fprintf (file, "add \"%s\"", r -> data.add -> name);
880  break;
881 
882  case break_statement:
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  }
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:
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:
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:
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 
994 #ifdef ENABLE_EXECUTE
996  col = token_print_indent(file, indent + 4, indent + 4,
997  "", "", "execute");
998  col = token_print_indent(file, col, indent + 4, " ", "",
999  "(");
1000  col = token_print_indent_concat(file, col, indent + 4,
1001  "", "", "\"",
1002  r->data.execute.command,
1003  "\"", (char *)0);
1004  for (expr = r->data.execute.arglist; expr; expr = expr->data.arg.next) {
1005  col = token_print_indent(file, col, indent + 4,
1006  "", " ", ",");
1008  col, indent + 4, 0);
1009  }
1010  (void) token_print_indent(file, col, indent + 4,
1011  "", "", ");");
1012 #else /* !ENABLE_EXECUTE */
1013  log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
1014  "is not defined).", MDL);
1015 #endif /* ENABLE_EXECUTE */
1016  break;
1017 
1018  case vendor_opt_statement:
1020  fprintf (file, "parse-vendor-option;");
1021  break;
1022 
1023  default:
1024  log_fatal ("bogus statement type %d\n", r -> op);
1025  }
1026  }
1027 }
1028 
1029 /* Find a case statement in the sequence of executable statements that
1030  matches the expression, and if found, return the following statement.
1031  If no case statement matches, try to find a default statement and
1032  return that (the default statement can precede all the case statements).
1033  Otherwise, return the null statement. */
1034 
1036  struct packet *packet, struct lease *lease,
1037  struct client_state *client_state,
1038  struct option_state *in_options,
1039  struct option_state *out_options,
1040  struct binding_scope **scope,
1041  struct expression *expr,
1042  struct executable_statement *stmt)
1043 {
1044  int status, sub;
1045  struct executable_statement *s;
1046 
1047  if (is_data_expression (expr)) {
1048  struct data_string cd, ds;
1049  memset (&ds, 0, sizeof ds);
1050  memset (&cd, 0, sizeof cd);
1051 
1052  status = (evaluate_data_expression (&ds, packet, lease,
1053  client_state, in_options,
1054  out_options, scope, expr,
1055  MDL));
1056  if (status) {
1057  for (s = stmt; s; s = s -> next) {
1058  if (s -> op == case_statement) {
1060  (&cd, packet, lease, client_state,
1061  in_options, out_options,
1062  scope, s->data.c_case, MDL));
1063  if (sub && cd.len == ds.len &&
1064  !memcmp (cd.data, ds.data, cd.len))
1065  {
1066  data_string_forget (&cd, MDL);
1067  data_string_forget (&ds, MDL);
1069  (ep, s->next, MDL);
1070  return 1;
1071  }
1072  data_string_forget (&cd, MDL);
1073  }
1074  }
1075  data_string_forget (&ds, MDL);
1076  }
1077  } else {
1078  unsigned long n, c;
1079  status = evaluate_numeric_expression (&n, packet, lease,
1080  client_state,
1081  in_options, out_options,
1082  scope, expr);
1083 
1084  if (status) {
1085  for (s = stmt; s; s = s->next) {
1086  if (s -> op == case_statement) {
1088  (&c, packet, lease, client_state,
1089  in_options, out_options,
1090  scope, s->data.c_case));
1091  if (sub && n == c) {
1093  (ep, s->next, MDL);
1094  return 1;
1095  }
1096  }
1097  }
1098  }
1099  }
1100 
1101  /* If we didn't find a matching case statement, look for a default
1102  statement and return the statement following it. */
1103  for (s = stmt; s; s = s->next)
1104  if (s->op == default_statement)
1105  break;
1106  if (s) {
1108  return 1;
1109  }
1110  return 0;
1111 }
1112 
1114  int (*callback) (struct
1116  void *, int),
1117  void *vp, int condp)
1118 {
1119  struct executable_statement *foo;
1120  int ok = 0;
1121 
1122  for (foo = stmt; foo; foo = foo->next) {
1123  if ((*callback) (foo, vp, condp) != 0)
1124  ok = 1;
1125  switch (foo->op) {
1126  case null_statement:
1127  break;
1128  case if_statement:
1129  if (executable_statement_foreach (foo->data.ie.tc,
1130  callback, vp, 1))
1131  ok = 1;
1132  if (executable_statement_foreach (foo->data.ie.fc,
1133  callback, vp, 1))
1134  ok = 1;
1135  break;
1136  case add_statement:
1137  break;
1138  case eval_statement:
1139  break;
1140  case break_statement:
1141  break;
1143  break;
1145  break;
1147  break;
1149  break;
1150  case send_option_statement:
1151  break;
1152  case statements_statement:
1154  (foo->data.statements, callback, vp, condp)))
1155  ok = 1;
1156  break;
1157  case on_statement:
1159  (foo->data.on.statements, callback, vp, 1)))
1160  ok = 1;
1161  break;
1162  case switch_statement:
1164  (foo->data.s_switch.statements, callback, vp, 1)))
1165  ok = 1;
1166  break;
1167  case case_statement:
1168  break;
1169  case default_statement:
1170  break;
1171  case set_statement:
1172  break;
1173  case unset_statement:
1174  break;
1175  case let_statement:
1177  (foo->data.let.statements, callback, vp, 0)))
1178  ok = 1;
1179  break;
1180  case define_statement:
1181  break;
1182  case log_statement:
1183  case return_statement:
1184  case execute_statement:
1185  case vendor_opt_statement:
1186  break;
1187  }
1188  }
1189  return ok;
1190 }
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:3728
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:2349
struct on_star on_star
Definition: dhcpd.h:580
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:557
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
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
Definition: options.c:2899
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:553
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:4509
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:1035
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:550
Definition: tree.h:302
char * name
Definition: dhcpd.h:1076
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:940
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:1423
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:933
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:145
struct executable_statement::@7::@11 let
const char * name
Definition: tree.h:347
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:1126
void * dmalloc(size_t, const char *, int)
Definition: alloc.c:57
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:1113
union executable_statement::@7 data
union binding_value::value value
#define ON_COMMIT
Definition: statement.h:73
Definition: dhcpd.h:932
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:551
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:3728
#define ON_RELEASE
Definition: statement.h:75
struct executable_statement * on_commit
Definition: dhcpd.h:552
const unsigned char * data
Definition: tree.h:79
struct expression * eval
Definition: statement.h:63
#define RC_MISC
Definition: alloc.h:56