32 #include <sys/types.h>
36 in_options, out_options, scope, statements,
62 while (r && !(result && *result)) {
66 case statements_statement:
67 #if defined (DEBUG_EXPRESSIONS)
71 client_state, in_options,
75 #if defined (DEBUG_EXPRESSIONS)
76 log_debug (
"exec: statements returns %d", status);
88 if ((on_star == NULL) && (lease != NULL))
91 if (on_star != NULL) {
93 #if defined (DEBUG_EXPRESSIONS)
105 #if defined (DEBUG_EXPRESSIONS)
111 if (r->
data.
on.statements)
117 #if defined (DEBUG_EXPRESSIONS)
123 if (r->
data.
on.statements)
131 case switch_statement:
132 #if defined (DEBUG_EXPRESSIONS)
136 (&e, packet, lease, client_state,
137 in_options, out_options, scope,
140 #if defined (DEBUG_EXPRESSIONS)
141 log_debug (
"exec: switch: case %lx", (
unsigned long)e);
145 (result, packet, lease, client_state,
146 in_options, out_options, scope, e,
158 case default_statement:
164 lease, client_state, in_options,
165 out_options, scope, r->
data.
ie.expr));
167 #if defined (DEBUG_EXPRESSIONS)
169 ? (rc ?
"true" :
"false")
176 (result, packet, lease, client_state,
177 in_options, out_options, scope,
185 (NULL, packet, lease, client_state, in_options,
187 #if defined (DEBUG_EXPRESSIONS)
189 (status ?
"succeeded" :
"failed"));
195 case execute_statement: {
196 #ifdef ENABLE_EXECUTE
203 argv =
dmalloc((argc + 2) *
sizeof(*argv),
MDL);
215 log_debug(
"execute_statement argv[0] = %s", argv[0]);
219 memset (&ds, 0,
sizeof(ds));
222 lease, client_state, in_options,
228 memcpy(argv[i], ds.
data,
231 log_debug(
"execute_statement argv[%d] = %s", i, argv[i]);
235 log_debug(
"execute_statement failed argv[%d]", i);
245 if ((p = fork()) > 0) {
247 waitpid(p, &status, 0);
254 execvp(argv[0], argv);
255 log_error(
"Unable to execute %s: %m", argv[0]);
262 for (i = 0; i <= argc; i++) {
269 log_fatal(
"Impossible case at %s:%d (ENABLE_EXECUTE "
270 "is not defined).",
MDL);
275 case return_statement:
278 lease, client_state, in_options,
279 out_options, scope, r ->
data.retval,
MDL);
280 #if defined (DEBUG_EXPRESSIONS)
282 (status ?
"succeeded" :
"failed"));
289 #if defined (DEBUG_EXPRESSIONS)
292 :
"<unnamed class>"));
297 case break_statement:
298 #if defined (DEBUG_EXPRESSIONS)
303 case supersede_option_statement:
304 case send_option_statement:
305 #if defined (DEBUG_EXPRESSIONS)
307 (r->
op == supersede_option_statement
308 ?
"supersede" :
"send"),
311 goto option_statement;
313 case default_option_statement:
314 #if defined (DEBUG_EXPRESSIONS)
318 goto option_statement;
320 case append_option_statement:
321 #if defined (DEBUG_EXPRESSIONS)
325 goto option_statement;
327 case prepend_option_statement:
328 #if defined (DEBUG_EXPRESSIONS)
339 case define_statement:
348 log_error(
"set %s: can't allocate scope",
354 #if defined (DEBUG_EXPRESSIONS)
359 if (binding == NULL) {
361 if (binding != NULL) {
362 memset(binding, 0,
sizeof(*binding));
367 if (binding->
name != NULL) {
369 binding->
next = (*scope)->bindings;
370 (*scope)->bindings = binding;
377 if (binding != NULL) {
378 if (binding->
value != NULL)
381 if (r->
op == set_statement) {
383 (&binding->
value, packet,
385 in_options, out_options,
394 if ((binding != NULL) &&
395 (binding->
value != NULL)) {
405 #if defined (DEBUG_EXPRESSIONS)
407 (binding && status ?
"" :
" (failed)"));
413 case unset_statement:
414 if (!scope || !*scope)
424 #if defined (DEBUG_EXPRESSIONS)
426 (status ?
"found" :
"not found"));
433 #if defined (DEBUG_EXPRESSIONS)
448 memset(binding, 0,
sizeof(*binding));
451 (e->data.let.name + 1),
467 (&binding->
value, packet, lease,
469 in_options, out_options,
470 scope, e->data.set.expr,
MDL));
475 #if defined (DEBUG_EXPRESSIONS)
476 log_debug(
"exec: let %s%s", e->data.let.name,
477 (binding && status ?
"" :
"failed"));
481 if (!e->data.let.statements) {
482 }
else if (e->data.let.statements->op ==
484 e = e->data.let.statements;
491 (result, packet, lease, client_state,
492 in_options, out_options,
493 &ns, e->data.let.statements, on_star);
500 memset (&ds, 0,
sizeof ds);
503 lease, client_state, in_options,
506 #if defined (DEBUG_EXPRESSIONS)
511 switch (r->
data.
log.priority) {
512 case log_priority_fatal:
516 case log_priority_error:
520 case log_priority_debug:
524 case log_priority_info:
534 case vendor_opt_statement:
539 in_options, out_options, scope);
574 struct group *limiting_group;
606 for (limit = limiting_group; limit; limit = limit ->
next) {
614 in_options, out_options, scope,
615 group->
next, limiting_group,
618 out_options, scope, group->
statements, on_star);
629 log_error (
"%s(%d): null pointer", file, line);
630 #if defined (POINTER_DEBUG)
639 if ((*ptr) ->
refcnt > 0) {
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);
649 #if defined (POINTER_DEBUG)
659 switch ((*ptr) ->
op) {
661 if ((*ptr) ->
data.statements)
663 (&(*ptr) ->
data.statements, file, line);
667 if ((*ptr) ->
data.on.statements)
669 (&(*ptr) ->
data.on.statements, file, line);
673 if ((*ptr) ->
data.s_switch.statements)
675 (&(*ptr) ->
data.on.statements, file, line);
676 if ((*ptr) ->
data.s_switch.expr)
682 if ((*ptr) ->
data.s_switch.expr)
688 if ((*ptr) ->
data.ie.expr)
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);
700 if ((*ptr) ->
data.eval)
706 if ((*ptr) ->
data.eval)
712 if ((*ptr)->data.set.name)
713 dfree ((*ptr)->data.set.name, file, line);
714 if ((*ptr)->data.set.expr)
720 if ((*ptr)->data.unset)
721 dfree ((*ptr)->data.unset, file, line);
725 if ((*ptr)->data.execute.command)
726 dfree ((*ptr)->data.execute.command, file, line);
727 if ((*ptr)->data.execute.arglist)
737 if ((*ptr) ->
data.option)
747 dfree ((*ptr), file, line);
757 #if defined ENABLE_EXECUTE
761 const char *s, *t, *dot;
767 for (r = statements; r; r = r ->
next) {
775 fprintf (file,
"on ");
778 fprintf (file,
"%sexpiry", s);
782 fprintf (file,
"%scommit", s);
786 fprintf (file,
"%srelease", s);
789 if (r ->
data.on.statements) {
790 fprintf (file,
" {");
792 r ->
data.on.statements,
803 fprintf (file,
"switch (");
805 r ->
data.s_switch.expr,
806 indent + 7, indent + 7, 1);
810 col, indent,
" ",
"",
"{");
819 fprintf (file,
"case ");
821 r ->
data.s_switch.expr,
822 indent + 5, indent + 5, 1);
829 fprintf (file,
"default: ");
834 fprintf (file,
"if ");
838 indent + 3, indent + 3, 1);
842 if (x ->
data.ie.fc &&
846 fprintf (file,
"} elsif ");
854 if (x ->
data.ie.fc) {
856 fprintf (file,
"} else {");
866 fprintf (file,
"eval ");
868 indent + 5, indent + 5, 1);
874 fprintf (file,
"return;");
879 fprintf (file,
"add \"%s\"", r ->
data.add ->
name);
884 fprintf (file,
"break;");
890 goto option_statement;
894 goto option_statement;
898 goto option_statement;
918 fprintf (file,
"%s %s%s%s = ", s, t, dot,
920 col = (indent + strlen (s) + strlen (t) +
921 strlen (dot) + strlen (r ->
data.option ->
930 (file, col, indent + 8,
"",
"",
938 fprintf (file,
"set ");
940 "",
"", r ->
data.set.name);
944 indent + 3, indent + 3, 0);
951 fprintf (file,
"unset ");
953 "",
"", r ->
data.set.name);
960 fprintf (file,
"log ");
963 switch (r ->
data.log.priority) {
966 (file, col, indent + 4,
"",
971 (file, col, indent + 4,
"",
976 (file, col, indent + 4,
"",
981 (file, col, indent + 4,
"",
986 indent + 4, indent + 4, 0);
994 #ifdef ENABLE_EXECUTE
1008 col, indent + 4, 0);
1013 log_fatal(
"Impossible case at %s:%d (ENABLE_EXECUTE "
1014 "is not defined).",
MDL);
1020 fprintf (file,
"parse-vendor-option;");
1049 memset (&ds, 0,
sizeof ds);
1050 memset (&cd, 0,
sizeof cd);
1053 client_state, in_options,
1054 out_options, scope, expr,
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,
1063 if (sub && cd.
len == ds.
len &&
1081 in_options, out_options,
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,
1091 if (sub && n == c) {
1103 for (s = stmt; s; s = s->
next)
1104 if (s->
op == default_statement)
1114 int (*callback) (
struct
1117 void *vp,
int condp)
1122 for (foo = stmt; foo; foo = foo->
next) {
1123 if ((*callback) (foo, vp, condp) != 0)
1159 (foo->
data.
on.statements, callback, vp, 1)))
1177 (foo->
data.
let.statements, callback, vp, 0)))
#define rc_register(file, line, reference, addr, refcnt, d, f)
struct executable_statement::@7::@13 execute
int executable_statement_reference(struct executable_statement **ptr, struct executable_statement *bp, const char *file, int line)
int fundef_reference(struct fundef **ptr, struct fundef *src, const char *file, int line)
void set_option(struct universe *universe, struct option_state *options, struct option_cache *option, enum statement_op op)
struct universe * universe
int token_indent_data_string(FILE *file, int col, int indent, const char *prefix, const char *suffix, struct data_string *data)
int binding_value_dereference(struct binding_value **v, const char *file, int line)
int executable_statement_dereference(struct executable_statement **ptr, const char *file, int line)
struct expression::expr_union::@25 arg
struct binding_scope * outer
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
int executable_statement_foreach(struct executable_statement *stmt, int(*callback)(structexecutable_statement *, void *, int), void *vp, int condp)
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)
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
enum executable_statement::statement_op op
struct executable_statement * on_release
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)
struct universe dhcp_universe
void data_string_forget(struct data_string *data, const char *file, int line)
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)
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)
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)
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)
struct executable_statement * next
log_fatal("no memory for uname information.")
void indent_spaces(FILE *file, int indent)
void expression_dereference(struct expression **eptr, const char *file, int line)
struct executable_statement::@7::@11 set
int binding_value_allocate(struct binding_value **cptr, const char *file, int line)
struct executable_statement * statements
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)
void classify(struct packet *packet, struct class *class)
struct option_cache * option
int binding_scope_allocate(struct binding_scope **ptr, const char *file, int line)
struct executable_statement::@7::@10 s_switch
struct executable_statement::@7::@11 let
int int log_info(const char *,...) __attribute__((__format__(__printf__
void write_statements(FILE *file, struct executable_statement *statements, int indent)
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)
void * dmalloc(size_t, const char *, int)
struct executable_statement::@7::@9 on
union executable_statement::@7 data
union binding_value::value value
struct binding * bindings
int binding_scope_reference(struct binding_scope **ptr, struct binding_scope *bp, const char *file, int line)
int token_print_indent_concat(FILE *file, int col, int indent, const char *prefix, const char *suffix,...)
struct executable_statement::@7::@8 ie
int is_data_expression(struct expression *expr)
struct binding_value * value
struct executable_statement * statements
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)
int token_print_indent(FILE *file, int col, int indent, const char *prefix, const char *suffix, const char *buf)
struct expression * c_case
struct executable_statement * on_expiry
int write_expression(FILE *file, struct expression *expr, int col, int indent, int firstp)
struct binding * find_binding(struct binding_scope *scope, const char *name)
struct executable_statement * on_commit
const unsigned char * data