31 #include <sys/types.h> 35 in_options, out_options, scope, statements,
61 while (r && !(result && *result)) {
65 case statements_statement:
66 #if defined (DEBUG_EXPRESSIONS) 70 client_state, in_options,
74 #if defined (DEBUG_EXPRESSIONS) 75 log_debug (
"exec: statements returns %d", status);
87 if ((on_star == NULL) && (lease != NULL))
90 if (on_star != NULL) {
92 #if defined (DEBUG_EXPRESSIONS) 104 #if defined (DEBUG_EXPRESSIONS) 110 if (r->
data.
on.statements)
116 #if defined (DEBUG_EXPRESSIONS) 122 if (r->
data.
on.statements)
130 case switch_statement:
131 #if defined (DEBUG_EXPRESSIONS) 135 (&e, packet, lease, client_state,
136 in_options, out_options, scope,
139 #if defined (DEBUG_EXPRESSIONS) 140 log_debug (
"exec: switch: case %lx", (
unsigned long)e);
144 (result, packet, lease, client_state,
145 in_options, out_options, scope, e,
157 case default_statement:
163 lease, client_state, in_options,
164 out_options, scope, r->
data.
ie.expr));
166 #if defined (DEBUG_EXPRESSIONS) 168 ? (rc ?
"true" :
"false")
175 (result, packet, lease, client_state,
176 in_options, out_options, scope,
184 (NULL, packet, lease, client_state, in_options,
186 #if defined (DEBUG_EXPRESSIONS) 188 (status ?
"succeeded" :
"failed"));
194 case execute_statement: {
195 #ifdef ENABLE_EXECUTE 202 argv =
dmalloc((argc + 2) *
sizeof(*argv),
MDL);
214 log_debug(
"execute_statement argv[0] = %s", argv[0]);
218 memset (&ds, 0,
sizeof(ds));
221 lease, client_state, in_options,
227 memcpy(argv[i], ds.
data,
230 log_debug(
"execute_statement argv[%d] = %s", i, argv[i]);
234 log_debug(
"execute_statement failed argv[%d]", i);
244 if ((p = fork()) > 0) {
246 waitpid(p, &status, 0);
253 execvp(argv[0], argv);
254 log_error(
"Unable to execute %s: %m", argv[0]);
261 for (i = 0; i <= argc; i++) {
268 log_fatal(
"Impossible case at %s:%d (ENABLE_EXECUTE " 269 "is not defined).",
MDL);
274 case return_statement:
277 lease, client_state, in_options,
278 out_options, scope, r ->
data.retval,
MDL);
279 #if defined (DEBUG_EXPRESSIONS) 281 (status ?
"succeeded" :
"failed"));
288 #if defined (DEBUG_EXPRESSIONS) 291 :
"<unnamed class>"));
296 case break_statement:
297 #if defined (DEBUG_EXPRESSIONS) 302 case supersede_option_statement:
303 case send_option_statement:
304 #if defined (DEBUG_EXPRESSIONS) 306 (r->
op == supersede_option_statement
307 ?
"supersede" :
"send"),
310 goto option_statement;
312 case default_option_statement:
313 #if defined (DEBUG_EXPRESSIONS) 317 goto option_statement;
319 case append_option_statement:
320 #if defined (DEBUG_EXPRESSIONS) 324 goto option_statement;
326 case prepend_option_statement:
327 #if defined (DEBUG_EXPRESSIONS) 338 case define_statement:
347 log_error(
"set %s: can't allocate scope",
353 #if defined (DEBUG_EXPRESSIONS) 358 if (binding == NULL) {
360 if (binding != NULL) {
361 memset(binding, 0,
sizeof(*binding));
366 if (binding->
name != NULL) {
368 binding->
next = (*scope)->bindings;
369 (*scope)->bindings = binding;
376 if (binding != NULL) {
377 if (binding->
value != NULL)
380 if (r->
op == set_statement) {
382 (&binding->
value, packet,
384 in_options, out_options,
393 if ((binding != NULL) &&
394 (binding->
value != NULL)) {
404 #if defined (DEBUG_EXPRESSIONS) 406 (binding && status ?
"" :
" (failed)"));
412 case unset_statement:
413 if (!scope || !*scope)
423 #if defined (DEBUG_EXPRESSIONS) 425 (status ?
"found" :
"not found"));
432 #if defined (DEBUG_EXPRESSIONS) 447 memset(binding, 0,
sizeof(*binding));
450 (e->data.let.name + 1),
453 strcpy(binding->
name,
466 (&binding->
value, packet, lease,
468 in_options, out_options,
469 scope, e->data.set.expr,
MDL));
474 #if defined (DEBUG_EXPRESSIONS) 475 log_debug(
"exec: let %s%s", e->data.let.name,
476 (binding && status ?
"" :
"failed"));
480 if (!e->data.let.statements) {
481 }
else if (e->data.let.statements->op ==
483 e = e->data.let.statements;
490 (result, packet, lease, client_state,
491 in_options, out_options,
492 &ns, e->data.let.statements, on_star);
499 memset (&ds, 0,
sizeof ds);
502 lease, client_state, in_options,
505 #if defined (DEBUG_EXPRESSIONS) 510 switch (r->
data.
log.priority) {
511 case log_priority_fatal:
515 case log_priority_error:
519 case log_priority_debug:
523 case log_priority_info:
533 case vendor_opt_statement:
538 in_options, out_options, scope);
573 struct group *limiting_group;
605 for (limit = limiting_group; limit; limit = limit ->
next) {
613 in_options, out_options, scope,
614 group->
next, limiting_group,
617 out_options, scope, group->
statements, on_star);
628 log_error (
"%s(%d): null pointer", file, line);
629 #if defined (POINTER_DEBUG) 638 if ((*ptr) ->
refcnt > 0) {
643 if ((*ptr) ->
refcnt < 0) {
644 log_error (
"%s(%d): negative refcnt!", file, line);
645 #if defined (DEBUG_RC_HISTORY) 646 dump_rc_history (*ptr);
648 #if defined (POINTER_DEBUG) 658 switch ((*ptr) ->
op) {
660 if ((*ptr) ->
data.statements)
662 (&(*ptr) ->
data.statements, file, line);
666 if ((*ptr) ->
data.on.statements)
668 (&(*ptr) ->
data.on.statements, file, line);
672 if ((*ptr) ->
data.s_switch.statements)
674 (&(*ptr) ->
data.on.statements, file, line);
675 if ((*ptr) ->
data.s_switch.expr)
681 if ((*ptr) ->
data.s_switch.expr)
687 if ((*ptr) ->
data.ie.expr)
690 if ((*ptr) ->
data.ie.tc)
692 (&(*ptr) ->
data.ie.tc, file, line);
693 if ((*ptr) ->
data.ie.fc)
695 (&(*ptr) ->
data.ie.fc, file, line);
699 if ((*ptr) ->
data.eval)
705 if ((*ptr) ->
data.eval)
711 if ((*ptr)->data.set.name)
712 dfree ((*ptr)->data.set.name, file, line);
713 if ((*ptr)->data.set.expr)
719 if ((*ptr)->data.unset)
720 dfree ((*ptr)->data.unset, file, line);
724 if ((*ptr)->data.execute.command)
725 dfree ((*ptr)->data.execute.command, file, line);
726 if ((*ptr)->data.execute.arglist)
736 if ((*ptr) ->
data.option)
746 dfree ((*ptr), file, line);
756 #if defined ENABLE_EXECUTE 760 const char *s, *t, *dot;
766 for (r = statements; r; r = r ->
next) {
774 fprintf (file,
"on ");
777 fprintf (file,
"%sexpiry", s);
781 fprintf (file,
"%scommit", s);
785 fprintf (file,
"%srelease", s);
788 if (r ->
data.on.statements) {
789 fprintf (file,
" {");
791 r ->
data.on.statements,
802 fprintf (file,
"switch (");
804 r ->
data.s_switch.expr,
805 indent + 7, indent + 7, 1);
809 col, indent,
" ",
"",
"{");
818 fprintf (file,
"case ");
820 r ->
data.s_switch.expr,
821 indent + 5, indent + 5, 1);
828 fprintf (file,
"default: ");
833 fprintf (file,
"if ");
837 indent + 3, indent + 3, 1);
841 if (x ->
data.ie.fc &&
845 fprintf (file,
"} elsif ");
853 if (x ->
data.ie.fc) {
855 fprintf (file,
"} else {");
865 fprintf (file,
"eval ");
867 indent + 5, indent + 5, 1);
873 fprintf (file,
"return;");
878 fprintf (file,
"add \"%s\"", r ->
data.add ->
name);
883 fprintf (file,
"break;");
889 goto option_statement;
893 goto option_statement;
897 goto option_statement;
917 fprintf (file,
"%s %s%s%s = ", s, t, dot,
919 col = (indent + strlen (s) + strlen (t) +
920 strlen (dot) + strlen (r ->
data.option ->
929 (file, col, indent + 8,
"",
"",
937 fprintf (file,
"set ");
939 "",
"", r ->
data.set.name);
943 indent + 3, indent + 3, 0);
950 fprintf (file,
"unset ");
952 "",
"", r ->
data.set.name);
959 fprintf (file,
"log ");
962 switch (r ->
data.log.priority) {
965 (file, col, indent + 4,
"",
970 (file, col, indent + 4,
"",
975 (file, col, indent + 4,
"",
980 (file, col, indent + 4,
"",
985 indent + 4, indent + 4, 0);
993 #ifdef ENABLE_EXECUTE 1007 col, indent + 4, 0);
1012 log_fatal(
"Impossible case at %s:%d (ENABLE_EXECUTE " 1013 "is not defined).",
MDL);
1019 fprintf (file,
"parse-vendor-option;");
1048 memset (&ds, 0,
sizeof ds);
1049 memset (&cd, 0,
sizeof cd);
1052 client_state, in_options,
1053 out_options, scope, expr,
1056 for (s = stmt; s; s = s -> next) {
1057 if (s -> op == case_statement) {
1059 (&cd, packet, lease, client_state,
1060 in_options, out_options,
1062 if (sub && cd.
len == ds.
len &&
1080 in_options, out_options,
1084 for (s = stmt; s; s = s->
next) {
1085 if (s -> op == case_statement) {
1087 (&c, packet, lease, client_state,
1088 in_options, out_options,
1090 if (sub && n == c) {
1102 for (s = stmt; s; s = s->
next)
1103 if (s->
op == default_statement)
1113 int (*callback) (
struct 1116 void *vp,
int condp)
1121 for (foo = stmt; foo; foo = foo->
next) {
1122 if ((*callback) (foo, vp, condp) != 0)
1158 (foo->
data.
on.statements, callback, vp, 1)))
1176 (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
void * dmalloc(unsigned, const char *, int)
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
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
void indent_spaces(FILE *file, int indent)
void expression_dereference(struct expression **eptr, const char *file, int line)
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)
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
void dfree(void *, const char *, int)
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)
struct executable_statement::@7::@9 on
union executable_statement::@7 data
union binding_value::value value
int executable_statement_foreach(struct executable_statement *stmt, int(*callback)(struct executable_statement *, void *, int), void *vp, int condp)
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