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