|
@@ -1,452 +0,0 @@
|
|
|
-diff -urN dhcp-3.0.2.orig/common/conflex.c dhcp-3.0.2/common/conflex.c
|
|
|
---- dhcp-3.0.2.orig/common/conflex.c 2004-11-24 10:39:15.000000000 -0700
|
|
|
-+++ dhcp-3.0.2/common/conflex.c 2005-02-24 12:32:12.000000000 -0700
|
|
|
-@@ -676,6 +676,8 @@
|
|
|
- return EVAL;
|
|
|
- if (!strcasecmp (atom + 1, "ncapsulate"))
|
|
|
- return ENCAPSULATE;
|
|
|
-+ if (!strcasecmp (atom + 1, "xecute"))
|
|
|
-+ return EXECUTE;
|
|
|
- break;
|
|
|
- case 'f':
|
|
|
- if (!strcasecmp (atom + 1, "atal"))
|
|
|
-diff -urN dhcp-3.0.2.orig/common/dhcp-eval.5 dhcp-3.0.2/common/dhcp-eval.5
|
|
|
---- dhcp-3.0.2.orig/common/dhcp-eval.5 2005-01-19 13:00:52.000000000 -0700
|
|
|
-+++ dhcp-3.0.2/common/dhcp-eval.5 2005-02-24 12:32:12.000000000 -0700
|
|
|
-@@ -409,7 +409,32 @@
|
|
|
- Rebind - DHCP client is in the REBINDING state - it has an IP address,
|
|
|
- and is trying to contact any server to renew it. The next message to
|
|
|
- be sent will be a DHCPREQUEST, which will be broadcast.
|
|
|
--.RE
|
|
|
-+.PP
|
|
|
-+.B execute (\fIcommand-path\fB, \fIdata-expr1\fB ... \fIdata-exprN\fB)\fR
|
|
|
-+.PP
|
|
|
-+External command execution is possibly through execute expressions. Execute
|
|
|
-+takes a variable number of arguments, where the first is the command
|
|
|
-+name (full path or only the name of the executable) and following zero
|
|
|
-+or more are data-expressions which values will be passed as external
|
|
|
-+arguments. It returns the return code of the external command.
|
|
|
-+.PP
|
|
|
-+Execute is synchronous, and the program will block until the external
|
|
|
-+command being run has finished. Please note that lengthy program
|
|
|
-+execution (for example, in an "on commit" in the dhcpd) may result in
|
|
|
-+bad performance and timed out clients. Try keeping the execution times
|
|
|
-+short.
|
|
|
-+.PP
|
|
|
-+Passing user-supplied data might be dangerous. Check input buffers
|
|
|
-+and make sure the external command handles all kinds of "unusual"
|
|
|
-+characters (shell special characters in sh-scripts etc) correctly.
|
|
|
-+.PP
|
|
|
-+It is possible to use the execute expression in any context, not only
|
|
|
-+on events. If you put it in a regular scope in the configuration file
|
|
|
-+you will execute that command every time a scope is evaluated.
|
|
|
-+.PP
|
|
|
-+The execute expression is only available if you have defined ENABLE_EXECUTE
|
|
|
-+in site.h before compilation.
|
|
|
-+RE
|
|
|
- .SH REFERENCE: LOGGING
|
|
|
- Logging statements may be used to send information to the standard logging
|
|
|
- channels. A logging statement includes an optional priority (\fBfatal\fR,
|
|
|
-diff -urN dhcp-3.0.2.orig/common/parse.c dhcp-3.0.2/common/parse.c
|
|
|
---- dhcp-3.0.2.orig/common/parse.c 2004-09-30 14:38:31.000000000 -0600
|
|
|
-+++ dhcp-3.0.2/common/parse.c 2005-02-24 12:32:12.000000000 -0700
|
|
|
-@@ -3639,7 +3639,56 @@
|
|
|
- return 0;
|
|
|
- }
|
|
|
- break;
|
|
|
--
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ case EXECUTE:
|
|
|
-+ token = next_token (&val, (unsigned *)0, cfile);
|
|
|
-+
|
|
|
-+ if (!expression_allocate (expr, MDL))
|
|
|
-+ log_fatal ("can't allocate expression.");
|
|
|
-+
|
|
|
-+ token = next_token (&val, (unsigned *)0, cfile);
|
|
|
-+ if (token != LPAREN) {
|
|
|
-+ parse_warn (cfile, "left parenthesis expected.");
|
|
|
-+ skip_to_semi (cfile);
|
|
|
-+ *lose = 1;
|
|
|
-+ return 0;
|
|
|
-+ }
|
|
|
-+ token = next_token (&val, (unsigned *)0, cfile);
|
|
|
-+ (*expr) -> data.funcall.name =
|
|
|
-+ dmalloc (strlen (val) + 1, MDL);
|
|
|
-+ if (!(*expr)->data.funcall.name)
|
|
|
-+ log_fatal ("can't allocate command name");
|
|
|
-+ strcpy ((*expr) -> data.funcall.name, val);
|
|
|
-+ token = next_token (&val, (unsigned *)0, cfile);
|
|
|
-+ ep = &((*expr) -> data.funcall.arglist);
|
|
|
-+ while (token == COMMA) {
|
|
|
-+ if (!expression_allocate (ep, MDL))
|
|
|
-+ log_fatal ("can't allocate expression");
|
|
|
-+ if (!parse_data_expression (&(*ep) -> data.arg.val,
|
|
|
-+ cfile, lose)) {
|
|
|
-+ skip_to_semi (cfile);
|
|
|
-+ *lose = 1;
|
|
|
-+ return 0;
|
|
|
-+ }
|
|
|
-+ ep = &((*ep) -> data.arg.next);
|
|
|
-+ token = next_token (&val, (unsigned *)0, cfile);
|
|
|
-+ }
|
|
|
-+ (*expr) -> op = expr_execute;
|
|
|
-+ if (token != RPAREN) {
|
|
|
-+ parse_warn (cfile, "right parenthesis expected.");
|
|
|
-+ skip_to_semi (cfile);
|
|
|
-+ *lose = 1;
|
|
|
-+ return 0;
|
|
|
-+ }
|
|
|
-+ break;
|
|
|
-+ #else
|
|
|
-+ case EXECUTE:
|
|
|
-+ parse_warn (cfile, "define ENABLE_EXECUTE in site.h to enable execute expressions.");
|
|
|
-+ skip_to_semi (cfile);
|
|
|
-+ *lose = 1;
|
|
|
-+ return 0;
|
|
|
-+ break;
|
|
|
-+ #endif
|
|
|
- case ENCODE_INT:
|
|
|
- token = next_token (&val, (unsigned *)0, cfile);
|
|
|
- token = next_token (&val, (unsigned *)0, cfile);
|
|
|
-diff -urN dhcp-3.0.2.orig/common/print.c dhcp-3.0.2/common/print.c
|
|
|
---- dhcp-3.0.2.orig/common/print.c 2004-06-17 14:54:39.000000000 -0600
|
|
|
-+++ dhcp-3.0.2/common/print.c 2005-02-24 12:32:12.000000000 -0700
|
|
|
-@@ -459,6 +459,7 @@
|
|
|
- {
|
|
|
- unsigned rv, left;
|
|
|
- const char *s;
|
|
|
-+ struct expression* next_arg;
|
|
|
-
|
|
|
- switch (expr -> op) {
|
|
|
- case expr_none:
|
|
|
-@@ -483,7 +484,8 @@
|
|
|
- return rv;
|
|
|
- }
|
|
|
- break;
|
|
|
--
|
|
|
-+
|
|
|
-+
|
|
|
- case expr_equal:
|
|
|
- if (len > 6) {
|
|
|
- rv = 4;
|
|
|
-@@ -1024,6 +1026,29 @@
|
|
|
- buf [rv++] = 0;
|
|
|
- return rv;
|
|
|
- }
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ case expr_execute:
|
|
|
-+ rv = 11 + strlen (expr -> data.funcall.name);
|
|
|
-+ if (len > rv + 2) {
|
|
|
-+ sprintf (buf,
|
|
|
-+ "(execute \"%s\"",
|
|
|
-+ expr -> data.funcall.name);
|
|
|
-+ for(next_arg = expr -> data.funcall.arglist;
|
|
|
-+ next_arg;
|
|
|
-+ next_arg = next_arg -> data.arg.next) {
|
|
|
-+ if (len > rv + 3)
|
|
|
-+ buf [rv++] = ' ';
|
|
|
-+ rv += print_subexpression (next_arg ->
|
|
|
-+ data.arg.val,
|
|
|
-+ buf + rv,
|
|
|
-+ len - rv - 2);
|
|
|
-+ }
|
|
|
-+ buf [rv++] = ')';
|
|
|
-+ buf [rv] = 0;
|
|
|
-+ return rv;
|
|
|
-+ }
|
|
|
-+ break;
|
|
|
-+ #endif
|
|
|
- }
|
|
|
- return 0;
|
|
|
- }
|
|
|
-diff -urN dhcp-3.0.2.orig/common/tree.c dhcp-3.0.2/common/tree.c
|
|
|
---- dhcp-3.0.2.orig/common/tree.c 2004-11-24 10:39:16.000000000 -0700
|
|
|
-+++ dhcp-3.0.2/common/tree.c 2005-02-24 12:32:12.000000000 -0700
|
|
|
-@@ -50,6 +50,113 @@
|
|
|
- int resolver_inited = 0;
|
|
|
- #endif
|
|
|
-
|
|
|
-+#ifdef ENABLE_EXECUTE
|
|
|
-+static unsigned long execute (char** args)
|
|
|
-+{
|
|
|
-+pid_t p = fork();
|
|
|
-+if (p > 0) {
|
|
|
-+int status;
|
|
|
-+waitpid (p, &status, 0);
|
|
|
-+return WEXITSTATUS(status);
|
|
|
-+}
|
|
|
-+else if(p == 0) {
|
|
|
-+execvp (args[0], args);
|
|
|
-+log_error ("Unable to execute %s: %s", args[0],
|
|
|
-+strerror(errno));
|
|
|
-+_exit(127);
|
|
|
-+} else {
|
|
|
-+log_fatal ("unable to fork");
|
|
|
-+}
|
|
|
-+return 1; /* never reached */
|
|
|
-+}
|
|
|
-+
|
|
|
-+#define CAPACITY_INCREMENT 8
|
|
|
-+static void append_to_ary (char*** ary_ptr, int* ary_size, int* ary_capacity,
|
|
|
-+char* new_element)
|
|
|
-+{
|
|
|
-+(*ary_size)++;
|
|
|
-+if (*ary_size > *ary_capacity) {
|
|
|
-+char** new_ary;
|
|
|
-+int new_ary_capacity = *ary_capacity + CAPACITY_INCREMENT;
|
|
|
-+new_ary = dmalloc(new_ary_capacity*sizeof(char *), MDL);
|
|
|
-+if (!new_ary)
|
|
|
-+log_fatal ("no memory for array.");
|
|
|
-+if (*ary_ptr != NULL) {
|
|
|
-+memcpy (new_ary, *ary_ptr,
|
|
|
-+(*ary_capacity)*sizeof(char *));
|
|
|
-+dfree (*ary_ptr, MDL);
|
|
|
-+}
|
|
|
-+*ary_ptr = new_ary;
|
|
|
-+*ary_capacity = new_ary_capacity;
|
|
|
-+}
|
|
|
-+(*ary_ptr)[*ary_size-1] = new_element;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static char* data_string_to_char_string (struct data_string* d)
|
|
|
-+{
|
|
|
-+char* str = dmalloc (d->len+1, MDL);
|
|
|
-+if (!str)
|
|
|
-+log_fatal ("no memory for string.");
|
|
|
-+/* FIXME: should one use d -> buffer -> data or d -> data? are
|
|
|
-+they equivalent? */
|
|
|
-+strncpy (str, d -> data, d -> len);
|
|
|
-+str[d->len] = '\0';
|
|
|
-+return str;
|
|
|
-+}
|
|
|
-+
|
|
|
-+static int evaluate_execute (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 status;
|
|
|
-+int cmd_status;
|
|
|
-+int i;
|
|
|
-+struct data_string ds;
|
|
|
-+struct expression* next_arg;
|
|
|
-+char** arg_ary = NULL;
|
|
|
-+int arg_ary_size = 0;
|
|
|
-+int arg_ary_capacity = 0;
|
|
|
-+append_to_ary (&arg_ary, &arg_ary_size, &arg_ary_capacity,
|
|
|
-+ expr -> data.funcall.name);
|
|
|
-+for(next_arg = expr -> data.funcall.arglist;
|
|
|
-+next_arg;
|
|
|
-+next_arg = next_arg -> data.arg.next) {
|
|
|
-+memset (&ds, 0, sizeof ds);
|
|
|
-+status = (evaluate_data_expression
|
|
|
-+(&ds, packet,
|
|
|
-+lease, client_state, in_options,
|
|
|
-+cfg_options, scope,
|
|
|
-+next_arg -> data.arg.val,
|
|
|
-+MDL));
|
|
|
-+if (!status) {
|
|
|
-+if (arg_ary) {
|
|
|
-+for (i=1; i<arg_ary_size; i++)
|
|
|
-+dfree (arg_ary[i], MDL);
|
|
|
-+dfree(arg_ary, MDL);
|
|
|
-+}
|
|
|
-+return 0;
|
|
|
-+}
|
|
|
-+append_to_ary (&arg_ary, &arg_ary_size, &arg_ary_capacity,
|
|
|
-+ data_string_to_char_string(&ds));
|
|
|
-+data_string_forget (&ds, MDL);
|
|
|
-+}
|
|
|
-+#if defined (DEBUG_EXPRESSIONS)
|
|
|
-+log_debug ("exec: execute");
|
|
|
-+#endif
|
|
|
-+append_to_ary (&arg_ary, &arg_ary_size, &arg_ary_capacity, NULL);
|
|
|
-+*result = execute (arg_ary);
|
|
|
-+for (i=1; i<arg_ary_size-1; i++)
|
|
|
-+dfree (arg_ary[i], MDL);
|
|
|
-+dfree(arg_ary, MDL);
|
|
|
-+return 1;
|
|
|
-+}
|
|
|
-+#endif
|
|
|
-+
|
|
|
-+
|
|
|
- pair cons (car, cdr)
|
|
|
- caddr_t car;
|
|
|
- pair cdr;
|
|
|
-@@ -861,6 +968,9 @@
|
|
|
- case expr_extract_int8:
|
|
|
- case expr_extract_int16:
|
|
|
- case expr_extract_int32:
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ case expr_execute:
|
|
|
-+ #endif
|
|
|
- case expr_const_int:
|
|
|
- case expr_lease_time:
|
|
|
- case expr_dns_transaction:
|
|
|
-@@ -1224,6 +1334,9 @@
|
|
|
- case expr_extract_int8:
|
|
|
- case expr_extract_int16:
|
|
|
- case expr_extract_int32:
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ case expr_execute:
|
|
|
-+ #endif
|
|
|
- case expr_const_int:
|
|
|
- case expr_lease_time:
|
|
|
- case expr_dns_transaction:
|
|
|
-@@ -2087,6 +2200,9 @@
|
|
|
- case expr_extract_int8:
|
|
|
- case expr_extract_int16:
|
|
|
- case expr_extract_int32:
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ case expr_execute:
|
|
|
-+ #endif
|
|
|
- case expr_const_int:
|
|
|
- case expr_lease_time:
|
|
|
- case expr_dns_transaction:
|
|
|
-@@ -2595,7 +2711,12 @@
|
|
|
- #endif
|
|
|
- return 0;
|
|
|
- }
|
|
|
--
|
|
|
-+#ifdef ENABLE_EXECUTE
|
|
|
-+ case expr_execute:
|
|
|
-+ return evaluate_execute (result, packet, lease,
|
|
|
-+ client_state, in_options,
|
|
|
-+ cfg_options, scope, expr);
|
|
|
-+#endif
|
|
|
- case expr_ns_add:
|
|
|
- case expr_ns_delete:
|
|
|
- case expr_ns_exists:
|
|
|
-@@ -3008,6 +3129,9 @@
|
|
|
- return (expr -> op == expr_extract_int8 ||
|
|
|
- expr -> op == expr_extract_int16 ||
|
|
|
- expr -> op == expr_extract_int32 ||
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ expr -> op == expr_execute ||
|
|
|
-+ #endif
|
|
|
- expr -> op == expr_const_int ||
|
|
|
- expr -> op == expr_lease_time ||
|
|
|
- expr -> op == expr_dns_transaction ||
|
|
|
-@@ -3043,6 +3167,9 @@
|
|
|
- expr -> op == expr_extract_int8 ||
|
|
|
- expr -> op == expr_extract_int16 ||
|
|
|
- expr -> op == expr_extract_int32 ||
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ expr -> op == expr_execute ||
|
|
|
-+ #endif
|
|
|
- expr -> op == expr_dns_transaction);
|
|
|
- }
|
|
|
-
|
|
|
-@@ -3069,6 +3196,9 @@
|
|
|
- case expr_extract_int8:
|
|
|
- case expr_extract_int16:
|
|
|
- case expr_extract_int32:
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ case expr_execute:
|
|
|
-+ #endif
|
|
|
- case expr_encode_int8:
|
|
|
- case expr_encode_int16:
|
|
|
- case expr_encode_int32:
|
|
|
-@@ -3165,6 +3295,9 @@
|
|
|
- case expr_extract_int8:
|
|
|
- case expr_extract_int16:
|
|
|
- case expr_extract_int32:
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ case expr_execute:
|
|
|
-+ #endif
|
|
|
- case expr_encode_int8:
|
|
|
- case expr_encode_int16:
|
|
|
- case expr_encode_int32:
|
|
|
-@@ -3225,6 +3358,8 @@
|
|
|
- int firstp;
|
|
|
- {
|
|
|
- struct expression *e;
|
|
|
-+ struct expression* next_arg;
|
|
|
-+
|
|
|
- const char *s;
|
|
|
- char obuf [65];
|
|
|
- int scol;
|
|
|
-@@ -3696,7 +3831,27 @@
|
|
|
- expr -> data.variable);
|
|
|
- col = token_print_indent (file, col, indent, "", "", ")");
|
|
|
- break;
|
|
|
--
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ case expr_execute:
|
|
|
-+ col = token_print_indent (file, col, indent, "", "","execute");
|
|
|
-+ col = token_print_indent (file, col, indent, " ", "","(");
|
|
|
-+ scol = col;
|
|
|
-+ /* FIXME: use token_print_indent_concat() here? */
|
|
|
-+ col = token_print_indent (file, col, scol, "", "","\"");
|
|
|
-+ col = token_print_indent (file, col, scol, "", "",expr -> data.funcall.name);
|
|
|
-+ col = token_print_indent (file, col, scol, "", "","\"");
|
|
|
-+ for(next_arg = expr -> data.funcall.arglist;
|
|
|
-+ next_arg;
|
|
|
-+ next_arg = next_arg -> data.arg.next) {
|
|
|
-+ col = token_print_indent (file, col, scol, "", " ",",");
|
|
|
-+ col = write_expression (file,
|
|
|
-+ next_arg -> data.arg.val,
|
|
|
-+ col, scol, 0);
|
|
|
-+ }
|
|
|
-+ col = token_print_indent (file, col, indent, "", "",")");
|
|
|
-+
|
|
|
-+ break;
|
|
|
-+#endif
|
|
|
- default:
|
|
|
- log_fatal ("invalid expression type in print_expression: %d",
|
|
|
- expr -> op);
|
|
|
-@@ -3915,6 +4070,9 @@
|
|
|
- case expr_extract_int8:
|
|
|
- case expr_extract_int16:
|
|
|
- case expr_extract_int32:
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ case expr_execute:
|
|
|
-+ #endif
|
|
|
- case expr_encode_int8:
|
|
|
- case expr_encode_int16:
|
|
|
- case expr_encode_int32:
|
|
|
-diff -urN dhcp-3.0.2.orig/includes/dhctoken.h dhcp-3.0.2/includes/dhctoken.h
|
|
|
---- dhcp-3.0.2.orig/includes/dhctoken.h 2004-09-21 13:25:38.000000000 -0600
|
|
|
-+++ dhcp-3.0.2/includes/dhctoken.h 2005-02-24 12:33:21.000000000 -0700
|
|
|
-@@ -308,7 +308,8 @@
|
|
|
- DOMAIN_NAME = 613,
|
|
|
- DO_FORWARD_UPDATE = 614,
|
|
|
- KNOWN_CLIENTS = 615,
|
|
|
-- ATSFP = 616
|
|
|
-+ ATSFP = 616,
|
|
|
-+ EXECUTE = 616
|
|
|
- };
|
|
|
-
|
|
|
- #define is_identifier(x) ((x) >= FIRST_TOKEN && \
|
|
|
-diff -urN dhcp-3.0.2.orig/includes/site.h dhcp-3.0.2/includes/site.h
|
|
|
---- dhcp-3.0.2.orig/includes/site.h 2002-03-12 11:33:39.000000000 -0700
|
|
|
-+++ dhcp-3.0.2/includes/site.h 2005-02-24 12:32:12.000000000 -0700
|
|
|
-@@ -167,6 +167,12 @@
|
|
|
-
|
|
|
- /* #define DHCPD_LOG_FACILITY LOG_DAEMON */
|
|
|
-
|
|
|
-+/* Define this if you want to be able to execute external commands
|
|
|
-+ during conditional evaluation. */
|
|
|
-+
|
|
|
-+/* #define ENABLE_EXECUTE */
|
|
|
-+
|
|
|
-+
|
|
|
- /* Define this if you aren't debugging and you want to save memory
|
|
|
- (potentially a _lot_ of memory) by allocating leases in chunks rather
|
|
|
- than one at a time. */
|
|
|
-diff -urN dhcp-3.0.2.orig/includes/tree.h dhcp-3.0.2/includes/tree.h
|
|
|
---- dhcp-3.0.2.orig/includes/tree.h 2004-06-10 11:59:31.000000000 -0600
|
|
|
-+++ dhcp-3.0.2/includes/tree.h 2005-02-24 12:32:12.000000000 -0700
|
|
|
-@@ -150,6 +150,9 @@
|
|
|
- expr_hardware,
|
|
|
- expr_packet,
|
|
|
- expr_const_data,
|
|
|
-+ #ifdef ENABLE_EXECUTE
|
|
|
-+ expr_execute,
|
|
|
-+ #endif
|
|
|
- expr_extract_int8,
|
|
|
- expr_extract_int16,
|
|
|
- expr_extract_int32,
|