dhcp_xecute.patch 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. diff -urN dhcp-3.0.2.orig/common/conflex.c dhcp-3.0.2/common/conflex.c
  2. --- dhcp-3.0.2.orig/common/conflex.c 2004-11-24 10:39:15.000000000 -0700
  3. +++ dhcp-3.0.2/common/conflex.c 2005-02-24 12:32:12.000000000 -0700
  4. @@ -676,6 +676,8 @@
  5. return EVAL;
  6. if (!strcasecmp (atom + 1, "ncapsulate"))
  7. return ENCAPSULATE;
  8. + if (!strcasecmp (atom + 1, "xecute"))
  9. + return EXECUTE;
  10. break;
  11. case 'f':
  12. if (!strcasecmp (atom + 1, "atal"))
  13. diff -urN dhcp-3.0.2.orig/common/dhcp-eval.5 dhcp-3.0.2/common/dhcp-eval.5
  14. --- dhcp-3.0.2.orig/common/dhcp-eval.5 2005-01-19 13:00:52.000000000 -0700
  15. +++ dhcp-3.0.2/common/dhcp-eval.5 2005-02-24 12:32:12.000000000 -0700
  16. @@ -409,7 +409,32 @@
  17. Rebind - DHCP client is in the REBINDING state - it has an IP address,
  18. and is trying to contact any server to renew it. The next message to
  19. be sent will be a DHCPREQUEST, which will be broadcast.
  20. -.RE
  21. +.PP
  22. +.B execute (\fIcommand-path\fB, \fIdata-expr1\fB ... \fIdata-exprN\fB)\fR
  23. +.PP
  24. +External command execution is possibly through execute expressions. Execute
  25. +takes a variable number of arguments, where the first is the command
  26. +name (full path or only the name of the executable) and following zero
  27. +or more are data-expressions which values will be passed as external
  28. +arguments. It returns the return code of the external command.
  29. +.PP
  30. +Execute is synchronous, and the program will block until the external
  31. +command being run has finished. Please note that lengthy program
  32. +execution (for example, in an "on commit" in the dhcpd) may result in
  33. +bad performance and timed out clients. Try keeping the execution times
  34. +short.
  35. +.PP
  36. +Passing user-supplied data might be dangerous. Check input buffers
  37. +and make sure the external command handles all kinds of "unusual"
  38. +characters (shell special characters in sh-scripts etc) correctly.
  39. +.PP
  40. +It is possible to use the execute expression in any context, not only
  41. +on events. If you put it in a regular scope in the configuration file
  42. +you will execute that command every time a scope is evaluated.
  43. +.PP
  44. +The execute expression is only available if you have defined ENABLE_EXECUTE
  45. +in site.h before compilation.
  46. +RE
  47. .SH REFERENCE: LOGGING
  48. Logging statements may be used to send information to the standard logging
  49. channels. A logging statement includes an optional priority (\fBfatal\fR,
  50. diff -urN dhcp-3.0.2.orig/common/parse.c dhcp-3.0.2/common/parse.c
  51. --- dhcp-3.0.2.orig/common/parse.c 2004-09-30 14:38:31.000000000 -0600
  52. +++ dhcp-3.0.2/common/parse.c 2005-02-24 12:32:12.000000000 -0700
  53. @@ -3639,7 +3639,56 @@
  54. return 0;
  55. }
  56. break;
  57. -
  58. + #ifdef ENABLE_EXECUTE
  59. + case EXECUTE:
  60. + token = next_token (&val, (unsigned *)0, cfile);
  61. +
  62. + if (!expression_allocate (expr, MDL))
  63. + log_fatal ("can't allocate expression.");
  64. +
  65. + token = next_token (&val, (unsigned *)0, cfile);
  66. + if (token != LPAREN) {
  67. + parse_warn (cfile, "left parenthesis expected.");
  68. + skip_to_semi (cfile);
  69. + *lose = 1;
  70. + return 0;
  71. + }
  72. + token = next_token (&val, (unsigned *)0, cfile);
  73. + (*expr) -> data.funcall.name =
  74. + dmalloc (strlen (val) + 1, MDL);
  75. + if (!(*expr)->data.funcall.name)
  76. + log_fatal ("can't allocate command name");
  77. + strcpy ((*expr) -> data.funcall.name, val);
  78. + token = next_token (&val, (unsigned *)0, cfile);
  79. + ep = &((*expr) -> data.funcall.arglist);
  80. + while (token == COMMA) {
  81. + if (!expression_allocate (ep, MDL))
  82. + log_fatal ("can't allocate expression");
  83. + if (!parse_data_expression (&(*ep) -> data.arg.val,
  84. + cfile, lose)) {
  85. + skip_to_semi (cfile);
  86. + *lose = 1;
  87. + return 0;
  88. + }
  89. + ep = &((*ep) -> data.arg.next);
  90. + token = next_token (&val, (unsigned *)0, cfile);
  91. + }
  92. + (*expr) -> op = expr_execute;
  93. + if (token != RPAREN) {
  94. + parse_warn (cfile, "right parenthesis expected.");
  95. + skip_to_semi (cfile);
  96. + *lose = 1;
  97. + return 0;
  98. + }
  99. + break;
  100. + #else
  101. + case EXECUTE:
  102. + parse_warn (cfile, "define ENABLE_EXECUTE in site.h to enable execute expressions.");
  103. + skip_to_semi (cfile);
  104. + *lose = 1;
  105. + return 0;
  106. + break;
  107. + #endif
  108. case ENCODE_INT:
  109. token = next_token (&val, (unsigned *)0, cfile);
  110. token = next_token (&val, (unsigned *)0, cfile);
  111. diff -urN dhcp-3.0.2.orig/common/print.c dhcp-3.0.2/common/print.c
  112. --- dhcp-3.0.2.orig/common/print.c 2004-06-17 14:54:39.000000000 -0600
  113. +++ dhcp-3.0.2/common/print.c 2005-02-24 12:32:12.000000000 -0700
  114. @@ -459,6 +459,7 @@
  115. {
  116. unsigned rv, left;
  117. const char *s;
  118. + struct expression* next_arg;
  119. switch (expr -> op) {
  120. case expr_none:
  121. @@ -483,7 +484,8 @@
  122. return rv;
  123. }
  124. break;
  125. -
  126. +
  127. +
  128. case expr_equal:
  129. if (len > 6) {
  130. rv = 4;
  131. @@ -1024,6 +1026,29 @@
  132. buf [rv++] = 0;
  133. return rv;
  134. }
  135. + #ifdef ENABLE_EXECUTE
  136. + case expr_execute:
  137. + rv = 11 + strlen (expr -> data.funcall.name);
  138. + if (len > rv + 2) {
  139. + sprintf (buf,
  140. + "(execute \"%s\"",
  141. + expr -> data.funcall.name);
  142. + for(next_arg = expr -> data.funcall.arglist;
  143. + next_arg;
  144. + next_arg = next_arg -> data.arg.next) {
  145. + if (len > rv + 3)
  146. + buf [rv++] = ' ';
  147. + rv += print_subexpression (next_arg ->
  148. + data.arg.val,
  149. + buf + rv,
  150. + len - rv - 2);
  151. + }
  152. + buf [rv++] = ')';
  153. + buf [rv] = 0;
  154. + return rv;
  155. + }
  156. + break;
  157. + #endif
  158. }
  159. return 0;
  160. }
  161. diff -urN dhcp-3.0.2.orig/common/tree.c dhcp-3.0.2/common/tree.c
  162. --- dhcp-3.0.2.orig/common/tree.c 2004-11-24 10:39:16.000000000 -0700
  163. +++ dhcp-3.0.2/common/tree.c 2005-02-24 12:32:12.000000000 -0700
  164. @@ -50,6 +50,113 @@
  165. int resolver_inited = 0;
  166. #endif
  167. +#ifdef ENABLE_EXECUTE
  168. +static unsigned long execute (char** args)
  169. +{
  170. +pid_t p = fork();
  171. +if (p > 0) {
  172. +int status;
  173. +waitpid (p, &status, 0);
  174. +return WEXITSTATUS(status);
  175. +}
  176. +else if(p == 0) {
  177. +execvp (args[0], args);
  178. +log_error ("Unable to execute %s: %s", args[0],
  179. +strerror(errno));
  180. +_exit(127);
  181. +} else {
  182. +log_fatal ("unable to fork");
  183. +}
  184. +return 1; /* never reached */
  185. +}
  186. +
  187. +#define CAPACITY_INCREMENT 8
  188. +static void append_to_ary (char*** ary_ptr, int* ary_size, int* ary_capacity,
  189. +char* new_element)
  190. +{
  191. +(*ary_size)++;
  192. +if (*ary_size > *ary_capacity) {
  193. +char** new_ary;
  194. +int new_ary_capacity = *ary_capacity + CAPACITY_INCREMENT;
  195. +new_ary = dmalloc(new_ary_capacity*sizeof(char *), MDL);
  196. +if (!new_ary)
  197. +log_fatal ("no memory for array.");
  198. +if (*ary_ptr != NULL) {
  199. +memcpy (new_ary, *ary_ptr,
  200. +(*ary_capacity)*sizeof(char *));
  201. +dfree (*ary_ptr, MDL);
  202. +}
  203. +*ary_ptr = new_ary;
  204. +*ary_capacity = new_ary_capacity;
  205. +}
  206. +(*ary_ptr)[*ary_size-1] = new_element;
  207. +}
  208. +
  209. +static char* data_string_to_char_string (struct data_string* d)
  210. +{
  211. +char* str = dmalloc (d->len+1, MDL);
  212. +if (!str)
  213. +log_fatal ("no memory for string.");
  214. +/* FIXME: should one use d -> buffer -> data or d -> data? are
  215. +they equivalent? */
  216. +strncpy (str, d -> data, d -> len);
  217. +str[d->len] = '\0';
  218. +return str;
  219. +}
  220. +
  221. +static int evaluate_execute (unsigned long* result, struct packet *packet,
  222. +struct lease *lease,
  223. +struct client_state *client_state,
  224. +struct option_state *in_options,
  225. +struct option_state *cfg_options,
  226. +struct binding_scope **scope,
  227. +struct expression* expr)
  228. +{
  229. +int status;
  230. +int cmd_status;
  231. +int i;
  232. +struct data_string ds;
  233. +struct expression* next_arg;
  234. +char** arg_ary = NULL;
  235. +int arg_ary_size = 0;
  236. +int arg_ary_capacity = 0;
  237. +append_to_ary (&arg_ary, &arg_ary_size, &arg_ary_capacity,
  238. + expr -> data.funcall.name);
  239. +for(next_arg = expr -> data.funcall.arglist;
  240. +next_arg;
  241. +next_arg = next_arg -> data.arg.next) {
  242. +memset (&ds, 0, sizeof ds);
  243. +status = (evaluate_data_expression
  244. +(&ds, packet,
  245. +lease, client_state, in_options,
  246. +cfg_options, scope,
  247. +next_arg -> data.arg.val,
  248. +MDL));
  249. +if (!status) {
  250. +if (arg_ary) {
  251. +for (i=1; i<arg_ary_size; i++)
  252. +dfree (arg_ary[i], MDL);
  253. +dfree(arg_ary, MDL);
  254. +}
  255. +return 0;
  256. +}
  257. +append_to_ary (&arg_ary, &arg_ary_size, &arg_ary_capacity,
  258. + data_string_to_char_string(&ds));
  259. +data_string_forget (&ds, MDL);
  260. +}
  261. +#if defined (DEBUG_EXPRESSIONS)
  262. +log_debug ("exec: execute");
  263. +#endif
  264. +append_to_ary (&arg_ary, &arg_ary_size, &arg_ary_capacity, NULL);
  265. +*result = execute (arg_ary);
  266. +for (i=1; i<arg_ary_size-1; i++)
  267. +dfree (arg_ary[i], MDL);
  268. +dfree(arg_ary, MDL);
  269. +return 1;
  270. +}
  271. +#endif
  272. +
  273. +
  274. pair cons (car, cdr)
  275. caddr_t car;
  276. pair cdr;
  277. @@ -861,6 +968,9 @@
  278. case expr_extract_int8:
  279. case expr_extract_int16:
  280. case expr_extract_int32:
  281. + #ifdef ENABLE_EXECUTE
  282. + case expr_execute:
  283. + #endif
  284. case expr_const_int:
  285. case expr_lease_time:
  286. case expr_dns_transaction:
  287. @@ -1224,6 +1334,9 @@
  288. case expr_extract_int8:
  289. case expr_extract_int16:
  290. case expr_extract_int32:
  291. + #ifdef ENABLE_EXECUTE
  292. + case expr_execute:
  293. + #endif
  294. case expr_const_int:
  295. case expr_lease_time:
  296. case expr_dns_transaction:
  297. @@ -2087,6 +2200,9 @@
  298. case expr_extract_int8:
  299. case expr_extract_int16:
  300. case expr_extract_int32:
  301. + #ifdef ENABLE_EXECUTE
  302. + case expr_execute:
  303. + #endif
  304. case expr_const_int:
  305. case expr_lease_time:
  306. case expr_dns_transaction:
  307. @@ -2595,7 +2711,12 @@
  308. #endif
  309. return 0;
  310. }
  311. -
  312. +#ifdef ENABLE_EXECUTE
  313. + case expr_execute:
  314. + return evaluate_execute (result, packet, lease,
  315. + client_state, in_options,
  316. + cfg_options, scope, expr);
  317. +#endif
  318. case expr_ns_add:
  319. case expr_ns_delete:
  320. case expr_ns_exists:
  321. @@ -3008,6 +3129,9 @@
  322. return (expr -> op == expr_extract_int8 ||
  323. expr -> op == expr_extract_int16 ||
  324. expr -> op == expr_extract_int32 ||
  325. + #ifdef ENABLE_EXECUTE
  326. + expr -> op == expr_execute ||
  327. + #endif
  328. expr -> op == expr_const_int ||
  329. expr -> op == expr_lease_time ||
  330. expr -> op == expr_dns_transaction ||
  331. @@ -3043,6 +3167,9 @@
  332. expr -> op == expr_extract_int8 ||
  333. expr -> op == expr_extract_int16 ||
  334. expr -> op == expr_extract_int32 ||
  335. + #ifdef ENABLE_EXECUTE
  336. + expr -> op == expr_execute ||
  337. + #endif
  338. expr -> op == expr_dns_transaction);
  339. }
  340. @@ -3069,6 +3196,9 @@
  341. case expr_extract_int8:
  342. case expr_extract_int16:
  343. case expr_extract_int32:
  344. + #ifdef ENABLE_EXECUTE
  345. + case expr_execute:
  346. + #endif
  347. case expr_encode_int8:
  348. case expr_encode_int16:
  349. case expr_encode_int32:
  350. @@ -3165,6 +3295,9 @@
  351. case expr_extract_int8:
  352. case expr_extract_int16:
  353. case expr_extract_int32:
  354. + #ifdef ENABLE_EXECUTE
  355. + case expr_execute:
  356. + #endif
  357. case expr_encode_int8:
  358. case expr_encode_int16:
  359. case expr_encode_int32:
  360. @@ -3225,6 +3358,8 @@
  361. int firstp;
  362. {
  363. struct expression *e;
  364. + struct expression* next_arg;
  365. +
  366. const char *s;
  367. char obuf [65];
  368. int scol;
  369. @@ -3696,7 +3831,27 @@
  370. expr -> data.variable);
  371. col = token_print_indent (file, col, indent, "", "", ")");
  372. break;
  373. -
  374. + #ifdef ENABLE_EXECUTE
  375. + case expr_execute:
  376. + col = token_print_indent (file, col, indent, "", "","execute");
  377. + col = token_print_indent (file, col, indent, " ", "","(");
  378. + scol = col;
  379. + /* FIXME: use token_print_indent_concat() here? */
  380. + col = token_print_indent (file, col, scol, "", "","\"");
  381. + col = token_print_indent (file, col, scol, "", "",expr -> data.funcall.name);
  382. + col = token_print_indent (file, col, scol, "", "","\"");
  383. + for(next_arg = expr -> data.funcall.arglist;
  384. + next_arg;
  385. + next_arg = next_arg -> data.arg.next) {
  386. + col = token_print_indent (file, col, scol, "", " ",",");
  387. + col = write_expression (file,
  388. + next_arg -> data.arg.val,
  389. + col, scol, 0);
  390. + }
  391. + col = token_print_indent (file, col, indent, "", "",")");
  392. +
  393. + break;
  394. +#endif
  395. default:
  396. log_fatal ("invalid expression type in print_expression: %d",
  397. expr -> op);
  398. @@ -3915,6 +4070,9 @@
  399. case expr_extract_int8:
  400. case expr_extract_int16:
  401. case expr_extract_int32:
  402. + #ifdef ENABLE_EXECUTE
  403. + case expr_execute:
  404. + #endif
  405. case expr_encode_int8:
  406. case expr_encode_int16:
  407. case expr_encode_int32:
  408. diff -urN dhcp-3.0.2.orig/includes/dhctoken.h dhcp-3.0.2/includes/dhctoken.h
  409. --- dhcp-3.0.2.orig/includes/dhctoken.h 2004-09-21 13:25:38.000000000 -0600
  410. +++ dhcp-3.0.2/includes/dhctoken.h 2005-02-24 12:33:21.000000000 -0700
  411. @@ -308,7 +308,8 @@
  412. DOMAIN_NAME = 613,
  413. DO_FORWARD_UPDATE = 614,
  414. KNOWN_CLIENTS = 615,
  415. - ATSFP = 616
  416. + ATSFP = 616,
  417. + EXECUTE = 616
  418. };
  419. #define is_identifier(x) ((x) >= FIRST_TOKEN && \
  420. diff -urN dhcp-3.0.2.orig/includes/site.h dhcp-3.0.2/includes/site.h
  421. --- dhcp-3.0.2.orig/includes/site.h 2002-03-12 11:33:39.000000000 -0700
  422. +++ dhcp-3.0.2/includes/site.h 2005-02-24 12:32:12.000000000 -0700
  423. @@ -167,6 +167,12 @@
  424. /* #define DHCPD_LOG_FACILITY LOG_DAEMON */
  425. +/* Define this if you want to be able to execute external commands
  426. + during conditional evaluation. */
  427. +
  428. +/* #define ENABLE_EXECUTE */
  429. +
  430. +
  431. /* Define this if you aren't debugging and you want to save memory
  432. (potentially a _lot_ of memory) by allocating leases in chunks rather
  433. than one at a time. */
  434. diff -urN dhcp-3.0.2.orig/includes/tree.h dhcp-3.0.2/includes/tree.h
  435. --- dhcp-3.0.2.orig/includes/tree.h 2004-06-10 11:59:31.000000000 -0600
  436. +++ dhcp-3.0.2/includes/tree.h 2005-02-24 12:32:12.000000000 -0700
  437. @@ -150,6 +150,9 @@
  438. expr_hardware,
  439. expr_packet,
  440. expr_const_data,
  441. + #ifdef ENABLE_EXECUTE
  442. + expr_execute,
  443. + #endif
  444. expr_extract_int8,
  445. expr_extract_int16,
  446. expr_extract_int32,