From 9cc9476c35294e43a1e42bd9752d5fae30a76c19 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Wed, 16 Feb 2005 19:48:03 +0000 Subject: more dhcp updates --- package/dhcp/dhcp_xecute.patch | 452 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 package/dhcp/dhcp_xecute.patch (limited to 'package/dhcp/dhcp_xecute.patch') diff --git a/package/dhcp/dhcp_xecute.patch b/package/dhcp/dhcp_xecute.patch new file mode 100644 index 000000000..358af5ff9 --- /dev/null +++ b/package/dhcp/dhcp_xecute.patch @@ -0,0 +1,452 @@ +diff -urN dhcp-3.0.1.orig/common/conflex.c dhcp-3.0.1/common/conflex.c +--- dhcp-3.0.1.orig/common/conflex.c 2004-06-10 11:59:14.000000000 -0600 ++++ dhcp-3.0.1/common/conflex.c 2005-02-16 12:41:43.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.1.orig/common/dhcp-eval.5 dhcp-3.0.1/common/dhcp-eval.5 +--- dhcp-3.0.1.orig/common/dhcp-eval.5 2004-06-10 11:59:15.000000000 -0600 ++++ dhcp-3.0.1/common/dhcp-eval.5 2005-02-16 12:41:43.000000000 -0700 +@@ -408,7 +408,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.1.orig/common/parse.c dhcp-3.0.1/common/parse.c +--- dhcp-3.0.1.orig/common/parse.c 2004-06-17 14:54:38.000000000 -0600 ++++ dhcp-3.0.1/common/parse.c 2005-02-16 12:41:43.000000000 -0700 +@@ -3636,7 +3636,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.1.orig/common/print.c dhcp-3.0.1/common/print.c +--- dhcp-3.0.1.orig/common/print.c 2004-06-17 14:54:39.000000000 -0600 ++++ dhcp-3.0.1/common/print.c 2005-02-16 12:41:43.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.1.orig/common/tree.c dhcp-3.0.1/common/tree.c +--- dhcp-3.0.1.orig/common/tree.c 2004-06-17 14:54:39.000000000 -0600 ++++ dhcp-3.0.1/common/tree.c 2005-02-16 12:41:43.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 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 || +@@ -3040,6 +3164,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); + } + +@@ -3066,6 +3193,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: +@@ -3160,6 +3290,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: +@@ -3220,6 +3353,8 @@ + int firstp; + { + struct expression *e; ++ struct expression* next_arg; ++ + const char *s; + char obuf [65]; + int scol; +@@ -3691,7 +3826,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); +@@ -3910,6 +4065,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.1.orig/includes/dhctoken.h dhcp-3.0.1/includes/dhctoken.h +--- dhcp-3.0.1.orig/includes/dhctoken.h 2004-06-10 11:59:30.000000000 -0600 ++++ dhcp-3.0.1/includes/dhctoken.h 2005-02-16 12:41:43.000000000 -0700 +@@ -307,7 +307,8 @@ + REMOVE = 611, + REFRESH = 612, + DOMAIN_NAME = 613, +- DO_FORWARD_UPDATE = 614 ++ DO_FORWARD_UPDATE = 614, ++ EXECUTE = 614 + }; + + #define is_identifier(x) ((x) >= FIRST_TOKEN && \ +diff -urN dhcp-3.0.1.orig/includes/site.h dhcp-3.0.1/includes/site.h +--- dhcp-3.0.1.orig/includes/site.h 2002-03-12 11:33:39.000000000 -0700 ++++ dhcp-3.0.1/includes/site.h 2005-02-16 12:41:43.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.1.orig/includes/tree.h dhcp-3.0.1/includes/tree.h +--- dhcp-3.0.1.orig/includes/tree.h 2004-06-10 11:59:31.000000000 -0600 ++++ dhcp-3.0.1/includes/tree.h 2005-02-16 12:41:43.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, -- cgit v1.2.3