00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "dhcpd.h"
00031 #include <omapip/omapip_p.h>
00032 #include <ctype.h>
00033 #include <sys/wait.h>
00034
00035 #ifdef HAVE_REGEX_H
00036 # include <regex.h>
00037 #endif
00038
00039 struct binding_scope *global_scope;
00040
00041 static int do_host_lookup (struct data_string *, struct dns_host_entry *);
00042
00043 #define DS_SPRINTF_SIZE 128
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 int
00057 data_string_sprintfa(struct data_string *ds, const char *fmt, ...) {
00058 va_list args;
00059 int cur_strlen;
00060 int max;
00061 int vsnprintf_ret;
00062 int new_len;
00063 struct buffer *tmp_buffer;
00064
00065
00066
00067
00068 if (ds->data == NULL) {
00069
00070 if (!buffer_allocate(&ds->buffer, DS_SPRINTF_SIZE, MDL)) {
00071 return 0;
00072 }
00073 ds->data = ds->buffer->data;
00074 ds->len = DS_SPRINTF_SIZE;
00075 *((char *)ds->data) = '\0';
00076 }
00077
00078
00079
00080
00081
00082 cur_strlen = strlen((char *)ds->data);
00083 max = ds->len - cur_strlen;
00084
00085
00086
00087
00088
00089 va_start(args, fmt);
00090 vsnprintf_ret = vsnprintf((char *)ds->data+cur_strlen, max, fmt, args);
00091 va_end(args);
00092
00093
00094
00095
00096
00097 if (vsnprintf_ret >= max) {
00098
00099
00100
00101 new_len = ds->len * 2;
00102 while (new_len <= cur_strlen + vsnprintf_ret) {
00103 new_len *= 2;
00104 }
00105
00106
00107
00108
00109 tmp_buffer = NULL;
00110 if (!buffer_allocate(&tmp_buffer, new_len, MDL)) {
00111
00112
00113
00114
00115 *((char *)ds->data+cur_strlen) = '\0';
00116 va_end(args);
00117 return 0;
00118 }
00119 memcpy(tmp_buffer->data, ds->data, cur_strlen);
00120
00121
00122 va_start(args, fmt);
00123 vsprintf((char *)tmp_buffer->data + cur_strlen, fmt, args);
00124 va_end(args);
00125
00126
00127
00128
00129 buffer_dereference(&ds->buffer, MDL);
00130 buffer_reference(&ds->buffer, tmp_buffer, MDL);
00131 buffer_dereference(&tmp_buffer, MDL);
00132 ds->data = ds->buffer->data;
00133 ds->len = new_len;
00134 }
00135 return 1;
00136 }
00137
00138 pair cons (car, cdr)
00139 caddr_t car;
00140 pair cdr;
00141 {
00142 pair foo = (pair)dmalloc (sizeof *foo, MDL);
00143 if (!foo)
00144 log_fatal ("no memory for cons.");
00145 foo -> car = car;
00146 foo -> cdr = cdr;
00147 return foo;
00148 }
00149
00150 int make_const_option_cache (oc, buffer, data, len, option, file, line)
00151 struct option_cache **oc;
00152 struct buffer **buffer;
00153 u_int8_t *data;
00154 unsigned len;
00155 struct option *option;
00156 const char *file;
00157 int line;
00158 {
00159 struct buffer *bp;
00160
00161 if (buffer) {
00162 bp = *buffer;
00163 *buffer = 0;
00164 } else {
00165 bp = (struct buffer *)0;
00166 if (!buffer_allocate (&bp, len, file, line)) {
00167 log_error ("%s(%d): can't allocate buffer.",
00168 file, line);
00169 return 0;
00170 }
00171 }
00172
00173 if (!option_cache_allocate (oc, file, line)) {
00174 log_error ("%s(%d): can't allocate option cache.", file, line);
00175 buffer_dereference (&bp, file, line);
00176 return 0;
00177 }
00178
00179 (*oc) -> data.len = len;
00180 (*oc) -> data.buffer = bp;
00181 (*oc) -> data.data = &bp -> data [0];
00182 (*oc) -> data.terminated = 0;
00183 if (data)
00184 memcpy (&bp -> data [0], data, len);
00185 option_reference(&((*oc)->option), option, MDL);
00186 return 1;
00187 }
00188
00189 int make_host_lookup (expr, name)
00190 struct expression **expr;
00191 const char *name;
00192 {
00193 if (!expression_allocate (expr, MDL)) {
00194 log_error ("No memory for host lookup tree node.");
00195 return 0;
00196 }
00197 (*expr) -> op = expr_host_lookup;
00198 if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) {
00199 expression_dereference (expr, MDL);
00200 return 0;
00201 }
00202 return 1;
00203 }
00204
00205 int enter_dns_host (dh, name)
00206 struct dns_host_entry **dh;
00207 const char *name;
00208 {
00209
00210
00211
00212
00213 if (!dns_host_entry_allocate (dh, name, MDL)) {
00214 log_error ("Can't allocate space for new host.");
00215 return 0;
00216 }
00217 return 1;
00218 }
00219
00220 int make_const_data (struct expression **expr, const unsigned char *data,
00221 unsigned len, int terminated, int allocate,
00222 const char *file, int line)
00223 {
00224 struct expression *nt;
00225
00226 if (!expression_allocate (expr, file, line)) {
00227 log_error ("No memory for make_const_data tree node.");
00228 return 0;
00229 }
00230 nt = *expr;
00231
00232 if (len) {
00233 if (allocate) {
00234 if (!buffer_allocate (&nt -> data.const_data.buffer,
00235 len + terminated, file, line)) {
00236 log_error ("Can't allocate const_data buffer");
00237 expression_dereference (expr, file, line);
00238 return 0;
00239 }
00240 nt -> data.const_data.data =
00241 &nt -> data.const_data.buffer -> data [0];
00242 memcpy (nt -> data.const_data.buffer -> data,
00243 data, len + terminated);
00244 } else
00245 nt -> data.const_data.data = data;
00246 nt -> data.const_data.terminated = terminated;
00247 } else
00248 nt -> data.const_data.data = 0;
00249
00250 nt -> op = expr_const_data;
00251 nt -> data.const_data.len = len;
00252 return 1;
00253 }
00254
00255 int make_const_int (expr, val)
00256 struct expression **expr;
00257 unsigned long val;
00258 {
00259 if (!expression_allocate (expr, MDL)) {
00260 log_error ("No memory for make_const_int tree node.");
00261 return 0;
00262 }
00263
00264 (*expr) -> op = expr_const_int;
00265 (*expr) -> data.const_int = val;
00266 return 1;
00267 }
00268
00269 int make_concat (expr, left, right)
00270 struct expression **expr;
00271 struct expression *left, *right;
00272 {
00273
00274
00275
00276 if (!left) {
00277 if (!right)
00278 return 0;
00279 expression_reference (expr, right, MDL);
00280 return 1;
00281 }
00282 if (!right) {
00283 expression_reference (expr, left, MDL);
00284 return 1;
00285 }
00286
00287
00288 if (!expression_allocate (expr, MDL)) {
00289 log_error ("No memory for concatenation expression node.");
00290 return 0;
00291 }
00292
00293 (*expr) -> op = expr_concat;
00294 expression_reference (&(*expr) -> data.concat [0], left, MDL);
00295 expression_reference (&(*expr) -> data.concat [1], right, MDL);
00296 return 1;
00297 }
00298
00299 int make_encapsulation (expr, name)
00300 struct expression **expr;
00301 struct data_string *name;
00302 {
00303
00304 if (!expression_allocate (expr, MDL)) {
00305 log_error ("No memory for encapsulation expression node.");
00306 return 0;
00307 }
00308
00309 (*expr) -> op = expr_encapsulate;
00310 data_string_copy (&(*expr) -> data.encapsulate, name, MDL);
00311 return 1;
00312 }
00313
00314 int make_substring (new, expr, offset, length)
00315 struct expression **new;
00316 struct expression *expr;
00317 struct expression *offset;
00318 struct expression *length;
00319 {
00320
00321 if (!expression_allocate (new, MDL)) {
00322 log_error ("no memory for substring expression.");
00323 return 0;
00324 }
00325 (*new) -> op = expr_substring;
00326 expression_reference (&(*new) -> data.substring.expr, expr, MDL);
00327 expression_reference (&(*new) -> data.substring.offset, offset, MDL);
00328 expression_reference (&(*new) -> data.substring.len, length, MDL);
00329 return 1;
00330 }
00331
00332 int make_limit (new, expr, limit)
00333 struct expression **new;
00334 struct expression *expr;
00335 int limit;
00336 {
00337
00338 if (!expression_allocate (new, MDL))
00339 log_error ("no memory for limit expression");
00340 (*new) -> op = expr_substring;
00341 expression_reference (&(*new) -> data.substring.expr, expr, MDL);
00342
00343
00344 if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) {
00345 log_error ("no memory for limit offset expression");
00346 expression_dereference (new, MDL);
00347 return 0;
00348 }
00349 (*new) -> data.substring.offset -> op = expr_const_int;
00350 (*new) -> data.substring.offset -> data.const_int = 0;
00351
00352
00353 if (!expression_allocate (&(*new) -> data.substring.len, MDL)) {
00354 log_error ("no memory for limit length expression");
00355 expression_dereference (new, MDL);
00356 return 0;
00357 }
00358 (*new) -> data.substring.len -> op = expr_const_int;
00359 (*new) -> data.substring.len -> data.const_int = limit;
00360
00361 return 1;
00362 }
00363
00364 int option_cache (struct option_cache **oc, struct data_string *dp,
00365 struct expression *expr, struct option *option,
00366 const char *file, int line)
00367 {
00368 if (!option_cache_allocate (oc, file, line))
00369 return 0;
00370 if (dp)
00371 data_string_copy (&(*oc) -> data, dp, file, line);
00372 if (expr)
00373 expression_reference (&(*oc) -> expression, expr, file, line);
00374 option_reference(&(*oc)->option, option, MDL);
00375 return 1;
00376 }
00377
00378 int make_let (result, name)
00379 struct executable_statement **result;
00380 const char *name;
00381 {
00382 if (!(executable_statement_allocate (result, MDL)))
00383 return 0;
00384
00385 (*result) -> op = let_statement;
00386 (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL);
00387 if (!(*result) -> data.let.name) {
00388 executable_statement_dereference (result, MDL);
00389 return 0;
00390 }
00391 strcpy ((*result) -> data.let.name, name);
00392 return 1;
00393 }
00394
00395 static int do_host_lookup (result, dns)
00396 struct data_string *result;
00397 struct dns_host_entry *dns;
00398 {
00399 struct hostent *h;
00400 unsigned i, count;
00401 unsigned new_len;
00402
00403 #ifdef DEBUG_EVAL
00404 log_debug ("time: now = %d dns = %d diff = %d",
00405 cur_time, dns -> timeout, cur_time - dns -> timeout);
00406 #endif
00407
00408
00409 if (cur_time <= dns -> timeout) {
00410 #ifdef DEBUG_EVAL
00411 log_debug ("easy copy: %d %s",
00412 dns -> data.len,
00413 (dns -> data.len > 4
00414 ? inet_ntoa (*(struct in_addr *)(dns -> data.data))
00415 : 0));
00416 #endif
00417 data_string_copy (result, &dns -> data, MDL);
00418 return 1;
00419 }
00420 #ifdef DEBUG_EVAL
00421 log_debug ("Looking up %s", dns -> hostname);
00422 #endif
00423
00424
00425 h = gethostbyname (dns -> hostname);
00426 if (!h) {
00427 #ifndef NO_H_ERRNO
00428 switch (h_errno) {
00429 case HOST_NOT_FOUND:
00430 #endif
00431 log_error ("%s: host unknown.", dns -> hostname);
00432 #ifndef NO_H_ERRNO
00433 break;
00434 case TRY_AGAIN:
00435 log_error ("%s: temporary name server failure",
00436 dns -> hostname);
00437 break;
00438 case NO_RECOVERY:
00439 log_error ("%s: name server failed", dns -> hostname);
00440 break;
00441 case NO_DATA:
00442 log_error ("%s: no A record associated with address",
00443 dns -> hostname);
00444 }
00445 #endif
00446
00447
00448 dns -> timeout = cur_time + 60;
00449 data_string_forget (&dns -> data, MDL);
00450 return 0;
00451 }
00452
00453 #ifdef DEBUG_EVAL
00454 log_debug ("Lookup succeeded; first address is %s",
00455 inet_ntoa (h -> h_addr_list [0]));
00456 #endif
00457
00458
00459 for (count = 0; h -> h_addr_list [count]; count++)
00460 ;
00461
00462
00463 data_string_forget (&dns -> data, MDL);
00464
00465
00466 new_len = count * h -> h_length;
00467 if (!buffer_allocate (&dns -> data.buffer, new_len, MDL))
00468 {
00469 log_error ("No memory for %s.", dns -> hostname);
00470 return 0;
00471 }
00472
00473 dns -> data.data = &dns -> data.buffer -> data [0];
00474 dns -> data.len = new_len;
00475 dns -> data.terminated = 0;
00476
00477
00478
00479 for (i = 0; i < count; i++) {
00480 memcpy (&dns -> data.buffer -> data [h -> h_length * i],
00481 h -> h_addr_list [i], (unsigned)(h -> h_length));
00482 }
00483 #ifdef DEBUG_EVAL
00484 log_debug ("dns -> data: %x h -> h_addr_list [0]: %x",
00485 *(int *)(dns -> buffer), h -> h_addr_list [0]);
00486 #endif
00487
00488
00489
00490 dns -> timeout = cur_time + 3600;
00491
00492 #ifdef DEBUG_EVAL
00493 log_debug ("hard copy: %d %s", dns -> data.len,
00494 (dns -> data.len > 4
00495 ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));
00496 #endif
00497 data_string_copy (result, &dns -> data, MDL);
00498 return 1;
00499 }
00500
00501 int evaluate_expression (result, packet, lease, client_state,
00502 in_options, cfg_options, scope, expr, file, line)
00503 struct binding_value **result;
00504 struct packet *packet;
00505 struct lease *lease;
00506 struct client_state *client_state;
00507 struct option_state *in_options;
00508 struct option_state *cfg_options;
00509 struct binding_scope **scope;
00510 struct expression *expr;
00511 const char *file;
00512 int line;
00513 {
00514 struct binding_value *bv;
00515 int status;
00516 struct binding *binding;
00517
00518 bv = (struct binding_value *)0;
00519
00520 if (expr -> op == expr_variable_reference) {
00521 if (!scope || !*scope)
00522 return 0;
00523
00524 binding = find_binding (*scope, expr -> data.variable);
00525
00526 if (binding && binding -> value) {
00527 if (result)
00528 binding_value_reference (result,
00529 binding -> value,
00530 file, line);
00531 return 1;
00532 } else
00533 return 0;
00534 } else if (expr -> op == expr_funcall) {
00535 struct string_list *s;
00536 struct expression *arg;
00537 struct binding_scope *ns;
00538 struct binding *nb;
00539
00540 if (!scope || !*scope) {
00541 log_error ("%s: no such function.",
00542 expr -> data.funcall.name);
00543 return 0;
00544 }
00545
00546 binding = find_binding (*scope, expr -> data.funcall.name);
00547
00548 if (!binding || !binding -> value) {
00549 log_error ("%s: no such function.",
00550 expr -> data.funcall.name);
00551 return 0;
00552 }
00553 if (binding -> value -> type != binding_function) {
00554 log_error ("%s: not a function.",
00555 expr -> data.funcall.name);
00556 return 0;
00557 }
00558
00559
00560
00561 ns = (struct binding_scope *)0;
00562 if (!binding_scope_allocate (&ns, MDL)) {
00563 log_error ("%s: can't allocate argument scope.",
00564 expr -> data.funcall.name);
00565 return 0;
00566 }
00567
00568 arg = expr -> data.funcall.arglist;
00569 s = binding -> value -> value.fundef -> args;
00570 while (arg && s) {
00571 nb = dmalloc (sizeof *nb, MDL);
00572 if (!nb) {
00573 blb:
00574 binding_scope_dereference (&ns, MDL);
00575 return 0;
00576 } else {
00577 memset (nb, 0, sizeof *nb);
00578 nb -> name = dmalloc (strlen (s -> string) + 1,
00579 MDL);
00580 if (nb -> name)
00581 strcpy (nb -> name, s -> string);
00582 else {
00583 dfree (nb, MDL);
00584 goto blb;
00585 }
00586 }
00587 evaluate_expression (&nb -> value, packet, lease,
00588 client_state,
00589 in_options, cfg_options, scope,
00590 arg -> data.arg.val, file, line);
00591 nb -> next = ns -> bindings;
00592 ns -> bindings = nb;
00593 arg = arg -> data.arg.next;
00594 s = s -> next;
00595 }
00596 if (arg) {
00597 log_error ("%s: too many arguments.",
00598 expr -> data.funcall.name);
00599 binding_scope_dereference (&ns, MDL);
00600 return 0;
00601 }
00602 if (s) {
00603 log_error ("%s: too few arguments.",
00604 expr -> data.funcall.name);
00605 binding_scope_dereference (&ns, MDL);
00606 return 0;
00607 }
00608
00609 if (scope && *scope)
00610 binding_scope_reference (&ns -> outer, *scope, MDL);
00611
00612 status = (execute_statements
00613 (&bv, packet,
00614 lease, client_state, in_options, cfg_options, &ns,
00615 binding->value->value.fundef->statements, NULL));
00616 binding_scope_dereference (&ns, MDL);
00617
00618 if (!bv)
00619 return 1;
00620 } else if (is_boolean_expression (expr)) {
00621 if (!binding_value_allocate (&bv, MDL))
00622 return 0;
00623 bv -> type = binding_boolean;
00624 status = (evaluate_boolean_expression
00625 (&bv -> value.boolean, packet, lease, client_state,
00626 in_options, cfg_options, scope, expr));
00627 } else if (is_numeric_expression (expr)) {
00628 if (!binding_value_allocate (&bv, MDL))
00629 return 0;
00630 bv -> type = binding_numeric;
00631 status = (evaluate_numeric_expression
00632 (&bv -> value.intval, packet, lease, client_state,
00633 in_options, cfg_options, scope, expr));
00634 } else if (is_data_expression (expr)) {
00635 if (!binding_value_allocate (&bv, MDL))
00636 return 0;
00637 bv -> type = binding_data;
00638 status = (evaluate_data_expression
00639 (&bv -> value.data, packet, lease, client_state,
00640 in_options, cfg_options, scope, expr, MDL));
00641 } else {
00642 log_error ("%s: invalid expression type: %d",
00643 "evaluate_expression", expr -> op);
00644 return 0;
00645 }
00646 if (result && status)
00647 binding_value_reference (result, bv, file, line);
00648 binding_value_dereference (&bv, MDL);
00649
00650 return status;
00651 }
00652
00653 int binding_value_dereference (struct binding_value **v,
00654 const char *file, int line)
00655 {
00656 struct binding_value *bv = *v;
00657
00658 *v = (struct binding_value *)0;
00659
00660
00661
00662 --(bv -> refcnt);
00663 rc_register (file, line, v, bv, bv -> refcnt, 1, RC_MISC);
00664 if (bv -> refcnt > 0)
00665 return 1;
00666 if (bv -> refcnt < 0) {
00667 log_error ("%s(%d): negative refcnt!", file, line);
00668 #if defined (DEBUG_RC_HISTORY)
00669 dump_rc_history (bv);
00670 #endif
00671 #if defined (POINTER_DEBUG)
00672 abort ();
00673 #else
00674 return 0;
00675 #endif
00676 }
00677
00678 switch (bv -> type) {
00679 case binding_boolean:
00680 case binding_numeric:
00681 break;
00682 case binding_data:
00683 if (bv -> value.data.buffer)
00684 data_string_forget (&bv -> value.data, file, line);
00685 break;
00686 default:
00687 log_error ("%s(%d): invalid binding type: %d",
00688 file, line, bv -> type);
00689 return 0;
00690 }
00691 free_binding_value(bv, file, line);
00692 return 1;
00693 }
00694
00695 int evaluate_boolean_expression (result, packet, lease, client_state,
00696 in_options, cfg_options, scope, expr)
00697 int *result;
00698 struct packet *packet;
00699 struct lease *lease;
00700 struct client_state *client_state;
00701 struct option_state *in_options;
00702 struct option_state *cfg_options;
00703 struct binding_scope **scope;
00704 struct expression *expr;
00705 {
00706 struct data_string left, right;
00707 int bleft, bright;
00708 int sleft, sright;
00709 struct binding *binding;
00710 struct binding_value *bv, *obv;
00711 #ifdef HAVE_REGEX_H
00712 int regflags = REG_EXTENDED | REG_NOSUB;
00713 regex_t re;
00714 #endif
00715
00716 switch (expr -> op) {
00717 case expr_check:
00718 *result = check_collection (packet, lease,
00719 expr -> data.check);
00720 #if defined (DEBUG_EXPRESSIONS)
00721 log_debug ("bool: check (%s) returns %s",
00722 expr -> data.check -> name,
00723 *result ? "true" : "false");
00724 #endif
00725 return 1;
00726
00727 case expr_equal:
00728 case expr_not_equal:
00729 bv = obv = (struct binding_value *)0;
00730 sleft = evaluate_expression (&bv, packet, lease, client_state,
00731 in_options, cfg_options, scope,
00732 expr -> data.equal [0], MDL);
00733 sright = evaluate_expression (&obv, packet, lease,
00734 client_state, in_options,
00735 cfg_options, scope,
00736 expr -> data.equal [1], MDL);
00737 if (sleft && sright) {
00738 if (bv -> type != obv -> type)
00739 *result = expr -> op == expr_not_equal;
00740 else {
00741 switch (obv -> type) {
00742 case binding_boolean:
00743 if (bv -> value.boolean == obv -> value.boolean)
00744 *result = expr -> op == expr_equal;
00745 else
00746 *result = expr -> op == expr_not_equal;
00747 break;
00748
00749 case binding_data:
00750 if ((bv -> value.data.len ==
00751 obv -> value.data.len) &&
00752 !memcmp (bv -> value.data.data,
00753 obv -> value.data.data,
00754 obv -> value.data.len))
00755 *result = expr -> op == expr_equal;
00756 else
00757 *result = expr -> op == expr_not_equal;
00758 break;
00759
00760 case binding_numeric:
00761 if (bv -> value.intval == obv -> value.intval)
00762 *result = expr -> op == expr_equal;
00763 else
00764 *result = expr -> op == expr_not_equal;
00765 break;
00766
00767 case binding_function:
00768 if (bv -> value.fundef == obv -> value.fundef)
00769 *result = expr -> op == expr_equal;
00770 else
00771 *result = expr -> op == expr_not_equal;
00772 break;
00773 default:
00774 *result = expr -> op == expr_not_equal;
00775 break;
00776 }
00777 }
00778 } else if (!sleft && !sright)
00779 *result = expr -> op == expr_equal;
00780 else
00781 *result = expr -> op == expr_not_equal;
00782
00783 #if defined (DEBUG_EXPRESSIONS)
00784 log_debug ("bool: %sequal = %s",
00785 expr -> op == expr_not_equal ? "not" : "",
00786 (*result ? "true" : "false"));
00787 #endif
00788 if (sleft)
00789 binding_value_dereference (&bv, MDL);
00790 if (sright)
00791 binding_value_dereference (&obv, MDL);
00792 return 1;
00793
00794 case expr_iregex_match:
00795 #ifdef HAVE_REGEX_H
00796 regflags |= REG_ICASE;
00797 #endif
00798
00799 case expr_regex_match:
00800 #ifdef HAVE_REGEX_H
00801 memset(&left, 0, sizeof left);
00802 bleft = evaluate_data_expression(&left, packet, lease,
00803 client_state,
00804 in_options, cfg_options,
00805 scope,
00806 expr->data.equal[0], MDL);
00807 memset(&right, 0, sizeof right);
00808 bright = evaluate_data_expression(&right, packet, lease,
00809 client_state,
00810 in_options, cfg_options,
00811 scope,
00812 expr->data.equal[1], MDL);
00813
00814 *result = 0;
00815 memset(&re, 0, sizeof(re));
00816 if (bleft && bright &&
00817 (left.data != NULL) && (right.data != NULL) &&
00818 (regcomp(&re, (char *)right.data, regflags) == 0) &&
00819 (regexec(&re, (char *)left.data, (size_t)0, NULL, 0) == 0))
00820 *result = 1;
00821
00822 #if defined (DEBUG_EXPRESSIONS)
00823 log_debug("bool: %s ~= %s yields %s",
00824 bleft ? print_hex_1(left.len, left.data, 20)
00825 : "NULL",
00826 bright ? print_hex_2 (right.len, right.data, 20)
00827 : "NULL",
00828 *result ? "true" : "false");
00829 #endif
00830
00831 if (bleft)
00832 data_string_forget(&left, MDL);
00833 if (bright)
00834 data_string_forget(&right, MDL);
00835
00836 regfree(&re);
00837
00838
00839
00840
00841
00842
00843
00844
00845 return bleft && bright;
00846 #else
00847
00848
00849
00850 log_fatal("Impossible condition at %s:%d.", MDL);
00851 break;
00852 #endif
00853
00854 case expr_and:
00855 sleft = evaluate_boolean_expression (&bleft, packet, lease,
00856 client_state,
00857 in_options, cfg_options,
00858 scope,
00859 expr -> data.and [0]);
00860 if (sleft && bleft)
00861 sright = evaluate_boolean_expression
00862 (&bright, packet, lease, client_state,
00863 in_options, cfg_options,
00864 scope, expr -> data.and [1]);
00865 else
00866 sright = bright = 0;
00867
00868 #if defined (DEBUG_EXPRESSIONS)
00869 log_debug ("bool: and (%s, %s) = %s",
00870 sleft ? (bleft ? "true" : "false") : "NULL",
00871 sright ? (bright ? "true" : "false") : "NULL",
00872 ((sleft && sright)
00873 ? (bleft && bright ? "true" : "false") : "NULL"));
00874 #endif
00875 if (sleft && sright) {
00876 *result = bleft && bright;
00877 return 1;
00878 }
00879 return 0;
00880
00881 case expr_or:
00882 bleft = bright = 0;
00883 sleft = evaluate_boolean_expression (&bleft, packet, lease,
00884 client_state,
00885 in_options, cfg_options,
00886 scope,
00887 expr -> data.or [0]);
00888 if (!sleft || !bleft)
00889 sright = evaluate_boolean_expression
00890 (&bright, packet, lease, client_state,
00891 in_options, cfg_options,
00892 scope, expr -> data.or [1]);
00893 else
00894 sright = 0;
00895 #if defined (DEBUG_EXPRESSIONS)
00896 log_debug ("bool: or (%s, %s) = %s",
00897 sleft ? (bleft ? "true" : "false") : "NULL",
00898 sright ? (bright ? "true" : "false") : "NULL",
00899 ((sleft || sright)
00900 ? (bleft || bright ? "true" : "false") : "NULL"));
00901 #endif
00902 if (sleft || sright) {
00903 *result = bleft || bright;
00904 return 1;
00905 }
00906 return 0;
00907
00908 case expr_not:
00909 sleft = evaluate_boolean_expression(&bleft, packet, lease,
00910 client_state,
00911 in_options, cfg_options,
00912 scope,
00913 expr->data.not);
00914 #if defined (DEBUG_EXPRESSIONS)
00915 log_debug("bool: not (%s) = %s",
00916 sleft ? (bleft ? "true" : "false") : "NULL",
00917 sleft ? (!bleft ? "true" : "false") : "NULL");
00918 #endif
00919 if (sleft) {
00920 *result = !bleft;
00921 return 1;
00922 }
00923 return 0;
00924
00925 case expr_exists:
00926 memset (&left, 0, sizeof left);
00927 if (!in_options ||
00928 !get_option (&left, expr -> data.exists -> universe,
00929 packet, lease, client_state,
00930 in_options, cfg_options, in_options,
00931 scope, expr -> data.exists -> code, MDL))
00932 *result = 0;
00933 else {
00934 *result = 1;
00935 data_string_forget (&left, MDL);
00936 }
00937 #if defined (DEBUG_EXPRESSIONS)
00938 log_debug ("bool: exists %s.%s = %s",
00939 expr -> data.option -> universe -> name,
00940 expr -> data.option -> name,
00941 *result ? "true" : "false");
00942 #endif
00943 return 1;
00944
00945 case expr_known:
00946 if (!packet) {
00947 #if defined (DEBUG_EXPRESSIONS)
00948 log_debug ("bool: known = NULL");
00949 #endif
00950 return 0;
00951 }
00952 #if defined (DEBUG_EXPRESSIONS)
00953 log_debug ("bool: known = %s",
00954 packet -> known ? "true" : "false");
00955 #endif
00956 *result = packet -> known;
00957 return 1;
00958
00959 case expr_static:
00960 if (!lease || !(lease -> flags & STATIC_LEASE)) {
00961 #if defined (DEBUG_EXPRESSIONS)
00962 log_debug ("bool: static = false (%s %s %s %d)",
00963 lease ? "y" : "n",
00964 (lease && (lease -> flags & STATIC_LEASE)
00965 ? "y" : "n"),
00966 piaddr (lease -> ip_addr),
00967 lease ? lease -> flags : 0);
00968 #endif
00969 *result = 0;
00970 return 1;
00971 }
00972 #if defined (DEBUG_EXPRESSIONS)
00973 log_debug ("bool: static = true");
00974 #endif
00975 *result = 1;
00976 return 1;
00977
00978 case expr_variable_exists:
00979 if (scope && *scope) {
00980 binding = find_binding (*scope, expr -> data.variable);
00981
00982 if (binding) {
00983 if (binding -> value)
00984 *result = 1;
00985 else
00986 *result = 0;
00987 } else
00988 *result = 0;
00989 } else
00990 *result = 0;
00991 #if defined (DEBUG_EXPRESSIONS)
00992 log_debug ("boolean: %s? = %s", expr -> data.variable,
00993 *result ? "true" : "false");
00994 #endif
00995 return 1;
00996
00997 case expr_variable_reference:
00998 if (scope && *scope) {
00999 binding = find_binding (*scope, expr -> data.variable);
01000
01001 if (binding && binding -> value) {
01002 if (binding -> value -> type ==
01003 binding_boolean) {
01004 *result = binding -> value -> value.boolean;
01005 sleft = 1;
01006 } else {
01007 log_error ("binding type %d in %s.",
01008 binding -> value -> type,
01009 "evaluate_boolean_expression");
01010 sleft = 0;
01011 }
01012 } else
01013 sleft = 0;
01014 } else
01015 sleft = 0;
01016 #if defined (DEBUG_EXPRESSIONS)
01017 log_debug ("boolean: %s = %s", expr -> data.variable,
01018 sleft ? (*result ? "true" : "false") : "NULL");
01019 #endif
01020 return sleft;
01021
01022 case expr_funcall:
01023 bv = (struct binding_value *)0;
01024 sleft = evaluate_expression (&bv, packet, lease, client_state,
01025 in_options, cfg_options,
01026 scope, expr, MDL);
01027 if (sleft) {
01028 if (bv -> type != binding_boolean)
01029 log_error ("%s() returned type %d in %s.",
01030 expr -> data.funcall.name,
01031 bv -> type,
01032 "evaluate_boolean_expression");
01033 else
01034 *result = bv -> value.boolean;
01035 binding_value_dereference (&bv, MDL);
01036 }
01037 #if defined (DEBUG_EXPRESSIONS)
01038 log_debug ("boolean: %s() = %s", expr -> data.funcall.name,
01039 sleft ? (*result ? "true" : "false") : "NULL");
01040 #endif
01041 break;
01042
01043 case expr_none:
01044 case expr_match:
01045 case expr_substring:
01046 case expr_suffix:
01047 case expr_lcase:
01048 case expr_ucase:
01049 case expr_option:
01050 case expr_hardware:
01051 case expr_const_data:
01052 case expr_packet:
01053 case expr_concat:
01054 case expr_encapsulate:
01055 case expr_host_lookup:
01056 case expr_encode_int8:
01057 case expr_encode_int16:
01058 case expr_encode_int32:
01059 case expr_binary_to_ascii:
01060 case expr_reverse:
01061 case expr_pick_first_value:
01062 case expr_host_decl_name:
01063 case expr_config_option:
01064 case expr_leased_address:
01065 case expr_null:
01066 case expr_filename:
01067 case expr_sname:
01068 case expr_gethostname:
01069 case expr_v6relay:
01070 log_error ("Data opcode in evaluate_boolean_expression: %d",
01071 expr -> op);
01072 return 0;
01073
01074 case expr_extract_int8:
01075 case expr_extract_int16:
01076 case expr_extract_int32:
01077 case expr_const_int:
01078 case expr_lease_time:
01079 case expr_dns_transaction:
01080 case expr_add:
01081 case expr_subtract:
01082 case expr_multiply:
01083 case expr_divide:
01084 case expr_remainder:
01085 case expr_binary_and:
01086 case expr_binary_or:
01087 case expr_binary_xor:
01088 case expr_client_state:
01089 log_error ("Numeric opcode in evaluate_boolean_expression: %d",
01090 expr -> op);
01091 return 0;
01092
01093 case expr_ns_add:
01094 case expr_ns_delete:
01095 case expr_ns_exists:
01096 case expr_ns_not_exists:
01097 log_error ("dns opcode in evaluate_boolean_expression: %d",
01098 expr -> op);
01099 return 0;
01100
01101 case expr_function:
01102 log_error ("function definition in evaluate_boolean_expr");
01103 return 0;
01104
01105 case expr_arg:
01106 break;
01107 }
01108
01109 log_error ("Bogus opcode in evaluate_boolean_expression: %d",
01110 expr -> op);
01111 return 0;
01112 }
01113
01114 int evaluate_data_expression (result, packet, lease, client_state,
01115 in_options, cfg_options, scope, expr, file, line)
01116 struct data_string *result;
01117 struct packet *packet;
01118 struct lease *lease;
01119 struct client_state *client_state;
01120 struct option_state *in_options;
01121 struct option_state *cfg_options;
01122 struct binding_scope **scope;
01123 struct expression *expr;
01124 const char *file;
01125 int line;
01126 {
01127 struct data_string data, other;
01128 unsigned long offset, len, i;
01129 int s0, s1, s2, s3;
01130 int status;
01131 struct binding *binding;
01132 unsigned char *s;
01133 struct binding_value *bv;
01134 struct packet *relay_packet;
01135 struct option_state *relay_options;
01136
01137 switch (expr -> op) {
01138
01139 case expr_substring:
01140 memset (&data, 0, sizeof data);
01141 s0 = evaluate_data_expression (&data, packet, lease,
01142 client_state,
01143 in_options, cfg_options, scope,
01144 expr -> data.substring.expr,
01145 MDL);
01146
01147
01148 s1 = evaluate_numeric_expression
01149 (&offset, packet, lease, client_state, in_options,
01150 cfg_options, scope, expr -> data.substring.offset);
01151 s2 = evaluate_numeric_expression (&len, packet, lease,
01152 client_state,
01153 in_options, cfg_options,
01154 scope,
01155 expr -> data.substring.len);
01156
01157 if (s0 && s1 && s2) {
01158
01159
01160
01161 if (data.len > offset) {
01162 data_string_copy (result, &data, file, line);
01163 result -> len -= offset;
01164 if (result -> len > len) {
01165 result -> len = len;
01166 result -> terminated = 0;
01167 }
01168 result -> data += offset;
01169 }
01170 s3 = 1;
01171 } else
01172 s3 = 0;
01173
01174 #if defined (DEBUG_EXPRESSIONS)
01175 log_debug ("data: substring (%s, %s, %s) = %s",
01176 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
01177 s1 ? print_dec_1 (offset) : "NULL",
01178 s2 ? print_dec_2 (len) : "NULL",
01179 (s3 ? print_hex_2 (result -> len, result -> data, 30)
01180 : "NULL"));
01181 #endif
01182 if (s0)
01183 data_string_forget (&data, MDL);
01184 if (s3)
01185 return 1;
01186 return 0;
01187
01188
01189 case expr_suffix:
01190 memset (&data, 0, sizeof data);
01191 s0 = evaluate_data_expression (&data, packet, lease,
01192 client_state,
01193 in_options, cfg_options, scope,
01194 expr -> data.suffix.expr, MDL);
01195
01196 s1 = evaluate_numeric_expression (&len, packet, lease,
01197 client_state,
01198 in_options, cfg_options,
01199 scope,
01200 expr -> data.suffix.len);
01201 if (s0 && s1) {
01202 data_string_copy (result, &data, file, line);
01203
01204
01205
01206
01207
01208
01209 if (data.len > len) {
01210 result -> data += data.len - len;
01211 result -> len = len;
01212 }
01213
01214 data_string_forget (&data, MDL);
01215 }
01216
01217 #if defined (DEBUG_EXPRESSIONS)
01218 log_debug ("data: suffix (%s, %s) = %s",
01219 s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
01220 s1 ? print_dec_1 (len) : "NULL",
01221 ((s0 && s1)
01222 ? print_hex_2 (result -> len, result -> data, 30)
01223 : "NULL"));
01224 #endif
01225
01226 return s0 && s1;
01227
01228
01229 case expr_lcase:
01230 memset(&data, 0, sizeof data);
01231 s0 = evaluate_data_expression(&data, packet, lease,
01232 client_state,
01233 in_options, cfg_options, scope,
01234 expr->data.lcase, MDL);
01235 s1 = 0;
01236 if (s0) {
01237 result->len = data.len;
01238 if (buffer_allocate(&result->buffer,
01239 result->len + data.terminated,
01240 MDL)) {
01241 result->data = &result->buffer->data[0];
01242 memcpy(result->buffer->data, data.data,
01243 data.len + data.terminated);
01244 result->terminated = data.terminated;
01245 s = (unsigned char *)result->data;
01246 for (i = 0; i < result->len; i++, s++)
01247 *s = tolower(*s);
01248 s1 = 1;
01249 } else {
01250 log_error("data: lcase: no buffer memory.");
01251 }
01252 }
01253
01254 #if defined (DEBUG_EXPRESSIONS)
01255 log_debug("data: lcase (%s) = %s",
01256 s0 ? print_hex_1(data.len, data.data, 30) : "NULL",
01257 s1 ? print_hex_2(result->len, result->data, 30)
01258 : "NULL");
01259 #endif
01260 if (s0)
01261 data_string_forget(&data, MDL);
01262 return s1;
01263
01264
01265 case expr_ucase:
01266 memset(&data, 0, sizeof data);
01267 s0 = evaluate_data_expression(&data, packet, lease,
01268 client_state,
01269 in_options, cfg_options, scope,
01270 expr->data.lcase, MDL);
01271 s1 = 0;
01272 if (s0) {
01273 result->len = data.len;
01274 if (buffer_allocate(&result->buffer,
01275 result->len + data.terminated,
01276 file, line)) {
01277 result->data = &result->buffer->data[0];
01278 memcpy(result->buffer->data, data.data,
01279 data.len + data.terminated);
01280 result->terminated = data.terminated;
01281 s = (unsigned char *)result->data;
01282 for (i = 0; i < result->len; i++, s++)
01283 *s = toupper(*s);
01284 s1 = 1;
01285 } else {
01286 log_error("data: lcase: no buffer memory.");
01287 }
01288 }
01289
01290 #if defined (DEBUG_EXPRESSIONS)
01291 log_debug("data: ucase (%s) = %s",
01292 s0 ? print_hex_1(data.len, data.data, 30) : "NULL",
01293 s1 ? print_hex_2(result->len, result->data, 30)
01294 : "NULL");
01295 #endif
01296 if (s0)
01297 data_string_forget(&data, MDL);
01298
01299 return s1;
01300
01301
01302 case expr_option:
01303 if (in_options)
01304 s0 = get_option (result,
01305 expr -> data.option -> universe,
01306 packet, lease, client_state,
01307 in_options, cfg_options, in_options,
01308 scope, expr -> data.option -> code,
01309 file, line);
01310 else
01311 s0 = 0;
01312
01313 #if defined (DEBUG_EXPRESSIONS)
01314 log_debug ("data: option %s.%s = %s",
01315 expr -> data.option -> universe -> name,
01316 expr -> data.option -> name,
01317 s0 ? print_hex_1 (result -> len, result -> data, 60)
01318 : "NULL");
01319 #endif
01320 return s0;
01321
01322 case expr_config_option:
01323 if (cfg_options)
01324 s0 = get_option (result,
01325 expr -> data.option -> universe,
01326 packet, lease, client_state,
01327 in_options, cfg_options, cfg_options,
01328 scope, expr -> data.option -> code,
01329 file, line);
01330 else
01331 s0 = 0;
01332
01333 #if defined (DEBUG_EXPRESSIONS)
01334 log_debug ("data: config-option %s.%s = %s",
01335 expr -> data.option -> universe -> name,
01336 expr -> data.option -> name,
01337 s0 ? print_hex_1 (result -> len, result -> data, 60)
01338 : "NULL");
01339 #endif
01340 return s0;
01341
01342
01343 case expr_hardware:
01344
01345 if (client_state) {
01346 memset(result, 0, sizeof(*result));
01347 result->data = client_state->interface->hw_address.hbuf;
01348 result->len = client_state->interface->hw_address.hlen;
01349 #if defined (DEBUG_EXPRESSIONS)
01350 log_debug("data: hardware = %s",
01351 print_hex_1(result->len, result->data, 60));
01352 #endif
01353 return (1);
01354 }
01355
01356
01357
01358
01359
01360 if (packet != NULL && packet->raw != NULL) {
01361 if (packet->raw->hlen > sizeof(packet->raw->chaddr)) {
01362 log_error("data: hardware: invalid hlen (%d)\n",
01363 packet->raw->hlen);
01364 return (0);
01365 }
01366 result->len = packet->raw->hlen + 1;
01367 if (buffer_allocate(&result->buffer, result->len, MDL)){
01368 result->data = &result->buffer->data[0];
01369 result->buffer->data[0] = packet->raw->htype;
01370 memcpy(&result->buffer->data[1],
01371 packet->raw->chaddr, packet->raw->hlen);
01372 result->terminated = 0;
01373 } else {
01374 log_error("data: hardware: "
01375 "no memory for buffer.");
01376 return (0);
01377 }
01378 } else if (lease != NULL) {
01379 result->len = lease->hardware_addr.hlen;
01380 if (buffer_allocate(&result->buffer, result->len, MDL)){
01381 result->data = &result->buffer->data[0];
01382 memcpy(result->buffer->data,
01383 lease->hardware_addr.hbuf, result->len);
01384 result->terminated = 0;
01385 } else {
01386 log_error("data: hardware: "
01387 "no memory for buffer.");
01388 return (0);
01389 }
01390 } else {
01391 log_error("data: hardware: no raw packet or lease "
01392 "is available");
01393 return (0);
01394 }
01395
01396 #if defined (DEBUG_EXPRESSIONS)
01397 log_debug("data: hardware = %s",
01398 print_hex_1(result->len, result->data, 60));
01399 #endif
01400 return (1);
01401
01402
01403 case expr_packet:
01404 if (!packet || !packet -> raw) {
01405 log_error ("data: packet: raw packet not available");
01406 return 0;
01407 }
01408
01409 s0 = evaluate_numeric_expression (&offset, packet, lease,
01410 client_state,
01411 in_options, cfg_options,
01412 scope,
01413 expr -> data.packet.offset);
01414 s1 = evaluate_numeric_expression (&len,
01415 packet, lease, client_state,
01416 in_options, cfg_options,
01417 scope,
01418 expr -> data.packet.len);
01419 if (s0 && s1 && offset < packet -> packet_length) {
01420 if (offset + len > packet -> packet_length)
01421 result -> len =
01422 packet -> packet_length - offset;
01423 else
01424 result -> len = len;
01425 if (buffer_allocate (&result -> buffer,
01426 result -> len, file, line)) {
01427 result -> data = &result -> buffer -> data [0];
01428 memcpy (result -> buffer -> data,
01429 (((unsigned char *)(packet -> raw))
01430 + offset), result -> len);
01431 result -> terminated = 0;
01432 } else {
01433 log_error ("data: packet: no buffer memory.");
01434 return 0;
01435 }
01436 s2 = 1;
01437 } else
01438 s2 = 0;
01439 #if defined (DEBUG_EXPRESSIONS)
01440 log_debug ("data: packet (%ld, %ld) = %s",
01441 offset, len,
01442 s2 ? print_hex_1 (result -> len,
01443 result -> data, 60) : NULL);
01444 #endif
01445 return s2;
01446
01447
01448
01449 case expr_encapsulate:
01450 if (cfg_options)
01451 s0 = option_space_encapsulate
01452 (result, packet, lease, client_state,
01453 in_options, cfg_options, scope,
01454 &expr -> data.encapsulate);
01455 else
01456 s0 = 0;
01457
01458 #if defined (DEBUG_EXPRESSIONS)
01459 log_debug ("data: encapsulate (%s) = %s",
01460 expr -> data.encapsulate.data,
01461 s0 ? print_hex_1 (result -> len,
01462 result -> data, 60) : "NULL");
01463 #endif
01464 return s0;
01465
01466
01467 case expr_const_data:
01468 #if defined (DEBUG_EXPRESSIONS)
01469 log_debug ("data: const = %s",
01470 print_hex_1 (expr -> data.const_data.len,
01471 expr -> data.const_data.data, 60));
01472 #endif
01473 data_string_copy (result,
01474 &expr -> data.const_data, file, line);
01475 return 1;
01476
01477
01478 case expr_host_lookup:
01479 s0 = do_host_lookup (result, expr -> data.host_lookup);
01480 #if defined (DEBUG_EXPRESSIONS)
01481 log_debug ("data: DNS lookup (%s) = %s",
01482 expr -> data.host_lookup -> hostname,
01483 (s0
01484 ? print_dotted_quads (result -> len, result -> data)
01485 : "NULL"));
01486 #endif
01487 return s0;
01488
01489
01490 case expr_concat:
01491 memset (&data, 0, sizeof data);
01492 s0 = evaluate_data_expression (&data, packet, lease,
01493 client_state,
01494 in_options, cfg_options, scope,
01495 expr -> data.concat [0], MDL);
01496 memset (&other, 0, sizeof other);
01497 s1 = evaluate_data_expression (&other, packet, lease,
01498 client_state,
01499 in_options, cfg_options, scope,
01500 expr -> data.concat [1], MDL);
01501
01502 if (s0 && s1) {
01503 result -> len = data.len + other.len;
01504 if (!buffer_allocate (&result -> buffer,
01505 (result -> len + other.terminated),
01506 file, line)) {
01507 log_error ("data: concat: no memory");
01508 result -> len = 0;
01509 data_string_forget (&data, MDL);
01510 data_string_forget (&other, MDL);
01511 return 0;
01512 }
01513 result -> data = &result -> buffer -> data [0];
01514 memcpy (result -> buffer -> data, data.data, data.len);
01515 memcpy (&result -> buffer -> data [data.len],
01516 other.data, other.len + other.terminated);
01517 }
01518
01519 if (s0)
01520 data_string_forget (&data, MDL);
01521 if (s1)
01522 data_string_forget (&other, MDL);
01523 #if defined (DEBUG_EXPRESSIONS)
01524 log_debug ("data: concat (%s, %s) = %s",
01525 s0 ? print_hex_1 (data.len, data.data, 20) : "NULL",
01526 s1 ? print_hex_2 (other.len, other.data, 20) : "NULL",
01527 ((s0 && s1)
01528 ? print_hex_3 (result -> len, result -> data, 30)
01529 : "NULL"));
01530 #endif
01531 return s0 && s1;
01532
01533 case expr_encode_int8:
01534 s0 = evaluate_numeric_expression (&len, packet, lease,
01535 client_state,
01536 in_options, cfg_options,
01537 scope,
01538 expr -> data.encode_int);
01539 if (s0) {
01540 result -> len = 1;
01541 if (!buffer_allocate (&result -> buffer,
01542 1, file, line)) {
01543 log_error ("data: encode_int8: no memory");
01544 result -> len = 0;
01545 s0 = 0;
01546 } else {
01547 result -> data = &result -> buffer -> data [0];
01548 result -> buffer -> data [0] = len;
01549 }
01550 } else
01551 result -> len = 0;
01552
01553 #if defined (DEBUG_EXPRESSIONS)
01554 if (!s0)
01555 log_debug ("data: encode_int8 (NULL) = NULL");
01556 else
01557 log_debug ("data: encode_int8 (%ld) = %s", len,
01558 print_hex_2 (result -> len,
01559 result -> data, 20));
01560 #endif
01561 return s0;
01562
01563
01564 case expr_encode_int16:
01565 s0 = evaluate_numeric_expression (&len, packet, lease,
01566 client_state,
01567 in_options, cfg_options,
01568 scope,
01569 expr -> data.encode_int);
01570 if (s0) {
01571 result -> len = 2;
01572 if (!buffer_allocate (&result -> buffer, 2,
01573 file, line)) {
01574 log_error ("data: encode_int16: no memory");
01575 result -> len = 0;
01576 s0 = 0;
01577 } else {
01578 result -> data = &result -> buffer -> data [0];
01579 putUShort (result -> buffer -> data, len);
01580 }
01581 } else
01582 result -> len = 0;
01583
01584 #if defined (DEBUG_EXPRESSIONS)
01585 if (!s0)
01586 log_debug ("data: encode_int16 (NULL) = NULL");
01587 else
01588 log_debug ("data: encode_int16 (%ld) = %s", len,
01589 print_hex_2 (result -> len,
01590 result -> data, 20));
01591 #endif
01592 return s0;
01593
01594 case expr_encode_int32:
01595 s0 = evaluate_numeric_expression (&len, packet, lease,
01596 client_state,
01597 in_options, cfg_options,
01598 scope,
01599 expr -> data.encode_int);
01600 if (s0) {
01601 result -> len = 4;
01602 if (!buffer_allocate (&result -> buffer, 4,
01603 file, line)) {
01604 log_error ("data: encode_int32: no memory");
01605 result -> len = 0;
01606 s0 = 0;
01607 } else {
01608 result -> data = &result -> buffer -> data [0];
01609 putULong (result -> buffer -> data, len);
01610 }
01611 } else
01612 result -> len = 0;
01613
01614 #if defined (DEBUG_EXPRESSIONS)
01615 if (!s0)
01616 log_debug ("data: encode_int32 (NULL) = NULL");
01617 else
01618 log_debug ("data: encode_int32 (%ld) = %s", len,
01619 print_hex_2 (result -> len,
01620 result -> data, 20));
01621 #endif
01622 return s0;
01623
01624 case expr_binary_to_ascii:
01625
01626 s0 = evaluate_numeric_expression
01627 (&offset, packet, lease, client_state, in_options,
01628 cfg_options, scope, expr -> data.b2a.base);
01629 s1 = evaluate_numeric_expression (&len, packet, lease,
01630 client_state,
01631 in_options, cfg_options,
01632 scope,
01633 expr -> data.b2a.width);
01634
01635
01636 memset (&data, 0, sizeof data);
01637 s2 = evaluate_data_expression (&data, packet, lease,
01638 client_state,
01639 in_options, cfg_options, scope,
01640 expr -> data.b2a.separator,
01641 MDL);
01642
01643
01644 memset (&other, 0, sizeof other);
01645 s3 = evaluate_data_expression (&other, packet, lease,
01646 client_state,
01647 in_options, cfg_options, scope,
01648 expr -> data.b2a.buffer, MDL);
01649
01650 if (s0 && s1 && s2 && s3) {
01651 unsigned buflen, i;
01652
01653 if (len != 8 && len != 16 && len != 32) {
01654 log_info ("binary_to_ascii: %s %ld!",
01655 "invalid width", len);
01656 status = 0;
01657 goto b2a_out;
01658 }
01659 len /= 8;
01660
01661
01662
01663 if (other.len % len) {
01664 log_info ("binary-to-ascii: %s %d %s %ld!",
01665 "length of buffer", other.len,
01666 "not a multiple of width", len);
01667 status = 0;
01668 goto b2a_out;
01669 }
01670
01671
01672 buflen = 0;
01673 for (i = 0; i < other.len; i += len) {
01674 if (len == 1) {
01675 if (offset == 8) {
01676 if (other.data [i] < 8)
01677 buflen++;
01678 else if (other.data [i] < 64)
01679 buflen += 2;
01680 else
01681 buflen += 3;
01682 } else if (offset == 10) {
01683 if (other.data [i] < 10)
01684 buflen++;
01685 else if (other.data [i] < 100)
01686 buflen += 2;
01687 else
01688 buflen += 3;
01689 } else if (offset == 16) {
01690 if (other.data [i] < 16)
01691 buflen++;
01692 else
01693 buflen += 2;
01694 } else
01695 buflen += (converted_length
01696 (&other.data [i],
01697 offset, 1));
01698 } else
01699 buflen += (converted_length
01700 (&other.data [i],
01701 offset, len));
01702 if (i + len != other.len)
01703 buflen += data.len;
01704 }
01705
01706 if (!buffer_allocate (&result -> buffer,
01707 buflen + 1, file, line)) {
01708 log_error ("data: binary-to-ascii: no memory");
01709 status = 0;
01710 goto b2a_out;
01711 }
01712 result -> data = &result -> buffer -> data [0];
01713 result -> len = buflen;
01714 result -> terminated = 1;
01715
01716 buflen = 0;
01717 for (i = 0; i < other.len; i += len) {
01718 buflen += (binary_to_ascii
01719 (&result -> buffer -> data [buflen],
01720 &other.data [i], offset, len));
01721 if (i + len != other.len) {
01722 memcpy (&result ->
01723 buffer -> data [buflen],
01724 data.data, data.len);
01725 buflen += data.len;
01726 }
01727 }
01728
01729 result -> buffer -> data [buflen] = 0;
01730 status = 1;
01731 } else
01732 status = 0;
01733
01734 b2a_out:
01735 #if defined (DEBUG_EXPRESSIONS)
01736 log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
01737 s0 ? print_dec_1 (offset) : "NULL",
01738 s1 ? print_dec_2 (len) : "NULL",
01739 s2 ? print_hex_1 (data.len, data.data, 30) : "NULL",
01740 s3 ? print_hex_2 (other.len, other.data, 30) : "NULL",
01741 (status ? print_hex_3 (result -> len, result -> data, 30)
01742 : "NULL"));
01743 #endif
01744 if (s2)
01745 data_string_forget (&data, MDL);
01746 if (s3)
01747 data_string_forget (&other, MDL);
01748 if (status)
01749 return 1;
01750 return 0;
01751
01752 case expr_reverse:
01753
01754 s0 = evaluate_numeric_expression
01755 (&len, packet, lease, client_state, in_options,
01756 cfg_options, scope, expr -> data.reverse.width);
01757
01758
01759 memset (&data, 0, sizeof data);
01760 s1 = evaluate_data_expression (&data, packet, lease,
01761 client_state,
01762 in_options, cfg_options, scope,
01763 expr -> data.reverse.buffer,
01764 MDL);
01765
01766 if (s0 && s1) {
01767 int i;
01768
01769
01770
01771 if (data.len % len) {
01772 log_info ("reverse: %s %d %s %ld!",
01773 "length of buffer", data.len,
01774 "not a multiple of width", len);
01775 status = 0;
01776 goto reverse_out;
01777 }
01778
01779
01780 if (!buffer_allocate (&result -> buffer,
01781 data.len, file, line)) {
01782 log_error ("data: reverse: no memory");
01783 status = 0;
01784 goto reverse_out;
01785 }
01786 result -> data = &result -> buffer -> data [0];
01787 result -> len = data.len;
01788 result -> terminated = 0;
01789
01790 for (i = 0; i < data.len; i += len) {
01791 memcpy (&result -> buffer -> data [i],
01792 &data.data [data.len - i - len], len);
01793 }
01794 status = 1;
01795 } else
01796 status = 0;
01797
01798 reverse_out:
01799 #if defined (DEBUG_EXPRESSIONS)
01800 log_debug ("data: reverse (%s, %s) = %s",
01801 s0 ? print_dec_1 (len) : "NULL",
01802 s1 ? print_hex_1 (data.len, data.data, 30) : "NULL",
01803 (status ? print_hex_3 (result -> len, result -> data, 30)
01804 : "NULL"));
01805 #endif
01806 if (s0)
01807 data_string_forget (&data, MDL);
01808 if (status)
01809 return 1;
01810 return 0;
01811
01812 case expr_leased_address:
01813 if (!lease) {
01814 log_debug("data: \"leased-address\" configuration "
01815 "directive: there is no lease associated "
01816 "with this client.");
01817 return 0;
01818 }
01819 result -> len = lease -> ip_addr.len;
01820 if (buffer_allocate (&result -> buffer, result -> len,
01821 file, line)) {
01822 result -> data = &result -> buffer -> data [0];
01823 memcpy (&result -> buffer -> data [0],
01824 lease -> ip_addr.iabuf, lease -> ip_addr.len);
01825 result -> terminated = 0;
01826 } else {
01827 log_error ("data: leased-address: no memory.");
01828 return 0;
01829 }
01830 #if defined (DEBUG_EXPRESSIONS)
01831 log_debug ("data: leased-address = %s",
01832 print_hex_1 (result -> len, result -> data, 60));
01833 #endif
01834 return 1;
01835
01836 case expr_pick_first_value:
01837 memset (&data, 0, sizeof data);
01838 if ((evaluate_data_expression
01839 (result, packet,
01840 lease, client_state, in_options, cfg_options,
01841 scope, expr -> data.pick_first_value.car, MDL))) {
01842 #if defined (DEBUG_EXPRESSIONS)
01843 log_debug ("data: pick_first_value (%s, xxx)",
01844 print_hex_1 (result -> len,
01845 result -> data, 40));
01846 #endif
01847 return 1;
01848 }
01849
01850 if (expr -> data.pick_first_value.cdr &&
01851 (evaluate_data_expression
01852 (result, packet,
01853 lease, client_state, in_options, cfg_options,
01854 scope, expr -> data.pick_first_value.cdr, MDL))) {
01855 #if defined (DEBUG_EXPRESSIONS)
01856 log_debug ("data: pick_first_value (NULL, %s)",
01857 print_hex_1 (result -> len,
01858 result -> data, 40));
01859 #endif
01860 return 1;
01861 }
01862
01863 #if defined (DEBUG_EXPRESSIONS)
01864 log_debug ("data: pick_first_value (NULL, NULL) = NULL");
01865 #endif
01866 return 0;
01867
01868 case expr_host_decl_name:
01869 if (!lease || !lease -> host) {
01870 log_error ("data: host_decl_name: not available");
01871 return 0;
01872 }
01873 result -> len = strlen (lease -> host -> name);
01874 if (buffer_allocate (&result -> buffer,
01875 result -> len + 1, file, line)) {
01876 result -> data = &result -> buffer -> data [0];
01877 strcpy ((char *)&result -> buffer -> data [0],
01878 lease -> host -> name);
01879 result -> terminated = 1;
01880 } else {
01881 log_error ("data: host-decl-name: no memory.");
01882 return 0;
01883 }
01884 #if defined (DEBUG_EXPRESSIONS)
01885 log_debug ("data: host-decl-name = %s", lease -> host -> name);
01886 #endif
01887 return 1;
01888
01889 case expr_null:
01890 #if defined (DEBUG_EXPRESSIONS)
01891 log_debug ("data: null = NULL");
01892 #endif
01893 return 0;
01894
01895 case expr_variable_reference:
01896 if (scope && *scope) {
01897 binding = find_binding (*scope, expr -> data.variable);
01898
01899 if (binding && binding -> value) {
01900 if (binding -> value -> type == binding_data) {
01901 data_string_copy (result,
01902 &binding -> value -> value.data,
01903 file, line);
01904 s0 = 1;
01905 } else if (binding -> value -> type != binding_data) {
01906 log_error ("binding type %d in %s.",
01907 binding -> value -> type,
01908 "evaluate_data_expression");
01909 s0 = 0;
01910 } else
01911 s0 = 0;
01912 } else
01913 s0 = 0;
01914 } else
01915 s0 = 0;
01916 #if defined (DEBUG_EXPRESSIONS)
01917 log_debug ("data: %s = %s", expr -> data.variable,
01918 s0 ? print_hex_1 (result -> len,
01919 result -> data, 50) : "NULL");
01920 #endif
01921 return s0;
01922
01923 case expr_funcall:
01924 bv = (struct binding_value *)0;
01925 s0 = evaluate_expression (&bv, packet, lease, client_state,
01926 in_options, cfg_options,
01927 scope, expr, MDL);
01928 if (s0) {
01929 if (bv -> type != binding_data)
01930 log_error ("%s() returned type %d in %s.",
01931 expr -> data.funcall.name,
01932 bv -> type,
01933 "evaluate_data_expression");
01934 else
01935 data_string_copy (result, &bv -> value.data,
01936 file, line);
01937 binding_value_dereference (&bv, MDL);
01938 }
01939 #if defined (DEBUG_EXPRESSIONS)
01940 log_debug ("data: %s = %s", expr -> data.funcall.name,
01941 s0 ? print_hex_1 (result -> len,
01942 result -> data, 50) : "NULL");
01943 #endif
01944 break;
01945
01946
01947 case expr_filename:
01948 if (packet && packet -> raw -> file [0]) {
01949 char *fn =
01950 memchr (packet -> raw -> file, 0,
01951 sizeof packet -> raw -> file);
01952 if (!fn)
01953 fn = ((char *)packet -> raw -> file +
01954 sizeof packet -> raw -> file);
01955 result -> len = fn - &(packet -> raw -> file [0]);
01956 if (buffer_allocate (&result -> buffer,
01957 result -> len + 1, file, line)) {
01958 result -> data = &result -> buffer -> data [0];
01959 memcpy (&result -> buffer -> data [0],
01960 packet -> raw -> file,
01961 result -> len);
01962 result -> buffer -> data [result -> len] = 0;
01963 result -> terminated = 1;
01964 s0 = 1;
01965 } else {
01966 log_error ("data: filename: no memory.");
01967 s0 = 0;
01968 }
01969 } else
01970 s0 = 0;
01971
01972 #if defined (DEBUG_EXPRESSIONS)
01973 log_info ("data: filename = \"%s\"",
01974 s0 ? (const char *)(result -> data) : "NULL");
01975 #endif
01976 return s0;
01977
01978
01979 case expr_sname:
01980 if (packet && packet -> raw -> sname [0]) {
01981 char *fn =
01982 memchr (packet -> raw -> sname, 0,
01983 sizeof packet -> raw -> sname);
01984 if (!fn)
01985 fn = ((char *)packet -> raw -> sname +
01986 sizeof packet -> raw -> sname);
01987 result -> len = fn - &packet -> raw -> sname [0];
01988 if (buffer_allocate (&result -> buffer,
01989 result -> len + 1, file, line)) {
01990 result -> data = &result -> buffer -> data [0];
01991 memcpy (&result -> buffer -> data [0],
01992 packet -> raw -> sname,
01993 result -> len);
01994 result -> buffer -> data [result -> len] = 0;
01995 result -> terminated = 1;
01996 s0 = 1;
01997 } else {
01998 log_error ("data: sname: no memory.");
01999 s0 = 0;
02000 }
02001 } else
02002 s0 = 0;
02003
02004 #if defined (DEBUG_EXPRESSIONS)
02005 log_info ("data: sname = \"%s\"",
02006 s0 ? (const char *)(result -> data) : "NULL");
02007 #endif
02008 return s0;
02009
02010
02011 case expr_gethostname:
02012
02013
02014
02015
02016
02017
02018
02019 memset(result, 0, sizeof(*result));
02020 if (!buffer_allocate(&result->buffer, 255, file, line)) {
02021 log_error("data: gethostname(): no memory for buffer");
02022 return 0;
02023 }
02024 result->data = result->buffer->data;
02025
02026
02027
02028
02029
02030
02031 if (!gethostname((char *)result->buffer->data, 255)) {
02032 if (result->buffer->data[255] == '\0')
02033 result->len =
02034 strlen((char *)result->buffer->data);
02035 else
02036 result->len = 255;
02037 return 1;
02038 }
02039
02040 data_string_forget(result, MDL);
02041 return 0;
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057 case expr_v6relay:
02058 len = 0;
02059 s1 = 0;
02060 memset (&data, 0, sizeof data);
02061
02062
02063 s0 = evaluate_numeric_expression(&len, packet, lease,
02064 client_state,
02065 in_options, cfg_options,
02066 scope,
02067 expr->data.v6relay.relay);
02068
02069
02070 if ((s0 == 0) ||
02071 ((len > 0) &&
02072 ((packet == NULL) ||
02073 (packet->dhcpv6_container_packet == NULL)))) {
02074 #if defined (DEBUG_EXPRESSIONS)
02075 log_debug("data: v6relay(%d) = NULL", len);
02076 #endif
02077 return (0);
02078 }
02079
02080
02081 i = len;
02082 relay_packet = packet;
02083 relay_options = in_options;
02084 while ((i != 0) &&
02085 (relay_packet->dhcpv6_container_packet != NULL)) {
02086 relay_packet = relay_packet->dhcpv6_container_packet;
02087 relay_options = relay_packet->options;
02088 i--;
02089 }
02090
02091 if ((len <= MAX_V6RELAY_HOPS) && (i != 0)) {
02092 #if defined (DEBUG_EXPRESSIONS)
02093 log_debug("data: v6relay(%d) = NULL", len);
02094 #endif
02095 return (0);
02096 }
02097
02098 s1 = evaluate_data_expression(&data, relay_packet, lease,
02099 client_state, relay_options,
02100 cfg_options, scope,
02101 expr->data.v6relay.roption,
02102 MDL);
02103
02104 if (s1) {
02105 data_string_copy(result, &data, file, line);
02106 data_string_forget(&data, MDL);
02107 }
02108
02109 #if defined (DEBUG_EXPRESSIONS)
02110 log_debug("data: v6relay(%d) = %s", len,
02111 s1 ? print_hex_3(result->len, result->data, 30)
02112 : "NULL");
02113 #endif
02114 return (s1);
02115
02116 case expr_check:
02117 case expr_equal:
02118 case expr_not_equal:
02119 case expr_regex_match:
02120 case expr_iregex_match:
02121 case expr_and:
02122 case expr_or:
02123 case expr_not:
02124 case expr_match:
02125 case expr_static:
02126 case expr_known:
02127 case expr_none:
02128 case expr_exists:
02129 case expr_variable_exists:
02130 log_error ("Boolean opcode in evaluate_data_expression: %d",
02131 expr -> op);
02132 return 0;
02133
02134 case expr_extract_int8:
02135 case expr_extract_int16:
02136 case expr_extract_int32:
02137 case expr_const_int:
02138 case expr_lease_time:
02139 case expr_dns_transaction:
02140 case expr_add:
02141 case expr_subtract:
02142 case expr_multiply:
02143 case expr_divide:
02144 case expr_remainder:
02145 case expr_binary_and:
02146 case expr_binary_or:
02147 case expr_binary_xor:
02148 case expr_client_state:
02149 log_error ("Numeric opcode in evaluate_data_expression: %d",
02150 expr -> op);
02151 return 0;
02152
02153 case expr_ns_add:
02154 case expr_ns_delete:
02155 case expr_ns_exists:
02156 case expr_ns_not_exists:
02157 log_error ("dns opcode in evaluate_boolean_expression: %d",
02158 expr -> op);
02159 return 0;
02160
02161 case expr_function:
02162 log_error ("function definition in evaluate_data_expression");
02163 return 0;
02164
02165 case expr_arg:
02166 break;
02167 }
02168
02169 log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op);
02170 return 0;
02171 }
02172
02173 int evaluate_numeric_expression (result, packet, lease, client_state,
02174 in_options, cfg_options, scope, expr)
02175 unsigned long *result;
02176 struct packet *packet;
02177 struct lease *lease;
02178 struct client_state *client_state;
02179 struct option_state *in_options;
02180 struct option_state *cfg_options;
02181 struct binding_scope **scope;
02182 struct expression *expr;
02183 {
02184 struct data_string data;
02185 int status, sleft, sright;
02186
02187 struct binding *binding;
02188 struct binding_value *bv;
02189 unsigned long ileft, iright;
02190 int rc = 0;
02191
02192 switch (expr -> op) {
02193 case expr_check:
02194 case expr_equal:
02195 case expr_not_equal:
02196 case expr_regex_match:
02197 case expr_iregex_match:
02198 case expr_and:
02199 case expr_or:
02200 case expr_not:
02201 case expr_match:
02202 case expr_static:
02203 case expr_known:
02204 case expr_none:
02205 case expr_exists:
02206 case expr_variable_exists:
02207 log_error ("Boolean opcode in evaluate_numeric_expression: %d",
02208 expr -> op);
02209 return 0;
02210
02211 case expr_substring:
02212 case expr_suffix:
02213 case expr_lcase:
02214 case expr_ucase:
02215 case expr_option:
02216 case expr_hardware:
02217 case expr_const_data:
02218 case expr_packet:
02219 case expr_concat:
02220 case expr_encapsulate:
02221 case expr_host_lookup:
02222 case expr_encode_int8:
02223 case expr_encode_int16:
02224 case expr_encode_int32:
02225 case expr_binary_to_ascii:
02226 case expr_reverse:
02227 case expr_filename:
02228 case expr_sname:
02229 case expr_pick_first_value:
02230 case expr_host_decl_name:
02231 case expr_config_option:
02232 case expr_leased_address:
02233 case expr_null:
02234 case expr_gethostname:
02235 case expr_v6relay:
02236 log_error ("Data opcode in evaluate_numeric_expression: %d",
02237 expr -> op);
02238 return 0;
02239
02240 case expr_extract_int8:
02241 memset (&data, 0, sizeof data);
02242 status = evaluate_data_expression
02243 (&data, packet, lease, client_state, in_options,
02244 cfg_options, scope, expr -> data.extract_int, MDL);
02245 if (status)
02246 *result = data.data [0];
02247 #if defined (DEBUG_EXPRESSIONS)
02248 log_debug ("num: extract_int8 (%s) = %s",
02249 status ? print_hex_1 (data.len, data.data, 60) : "NULL",
02250 status ? print_dec_1 (*result) : "NULL" );
02251 #endif
02252 if (status) data_string_forget (&data, MDL);
02253 return status;
02254
02255 case expr_extract_int16:
02256 memset(&data, 0, sizeof(data));
02257 status = (evaluate_data_expression
02258 (&data, packet, lease, client_state, in_options,
02259 cfg_options, scope, expr->data.extract_int, MDL));
02260 if (status && data.len >= 2) {
02261 *result = getUShort(data.data);
02262 rc = 1;
02263 }
02264 #if defined (DEBUG_EXPRESSIONS)
02265 if (rc == 1) {
02266 log_debug("num: extract_int16 (%s) = %ld",
02267 print_hex_1(data.len, data.data, 60),
02268 *result);
02269 } else {
02270 log_debug("num: extract_int16 (NULL) = NULL");
02271 }
02272 #endif
02273 if (status)
02274 data_string_forget(&data, MDL);
02275
02276 return (rc);
02277
02278 case expr_extract_int32:
02279 memset (&data, 0, sizeof data);
02280 status = (evaluate_data_expression
02281 (&data, packet, lease, client_state, in_options,
02282 cfg_options, scope, expr -> data.extract_int, MDL));
02283 if (status && data.len >= 4) {
02284 *result = getULong (data.data);
02285 rc = 1;
02286 }
02287 #if defined (DEBUG_EXPRESSIONS)
02288 if (rc == 1) {
02289 log_debug ("num: extract_int32 (%s) = %ld",
02290 print_hex_1 (data.len, data.data, 60),
02291 *result);
02292 } else {
02293 log_debug ("num: extract_int32 (NULL) = NULL");
02294 }
02295 #endif
02296 if (status) data_string_forget (&data, MDL);
02297 return (rc);
02298
02299 case expr_const_int:
02300 *result = expr -> data.const_int;
02301 #if defined (DEBUG_EXPRESSIONS)
02302 log_debug ("number: CONSTANT = %ld", *result);
02303 #endif
02304 return 1;
02305
02306 case expr_lease_time:
02307 if (!lease) {
02308 log_error("data: leased_lease: not available");
02309 return (0);
02310 }
02311 if (lease->ends < cur_time) {
02312 log_error("%s %lu when it is now %lu",
02313 "data: lease_time: lease ends at",
02314 (long)(lease->ends), (long)cur_time);
02315 return (0);
02316 }
02317 *result = lease->ends - cur_time;
02318 #if defined (DEBUG_EXPRESSIONS)
02319 log_debug("number: lease-time = (%lu - %lu) = %ld",
02320 (long unsigned)lease->ends,
02321 (long unsigned)cur_time, *result);
02322 #endif
02323 return (1);
02324
02325 case expr_variable_reference:
02326 if (scope && *scope) {
02327 binding = find_binding (*scope, expr -> data.variable);
02328
02329 if (binding && binding -> value) {
02330 if (binding -> value -> type == binding_numeric) {
02331 *result = binding -> value -> value.intval;
02332 status = 1;
02333 } else {
02334 log_error ("binding type %d in %s.",
02335 binding -> value -> type,
02336 "evaluate_numeric_expression");
02337 status = 0;
02338 }
02339 } else
02340 status = 0;
02341 } else
02342 status = 0;
02343 #if defined (DEBUG_EXPRESSIONS)
02344 if (status)
02345 log_debug ("numeric: %s = %ld",
02346 expr -> data.variable, *result);
02347 else
02348 log_debug ("numeric: %s = NULL",
02349 expr -> data.variable);
02350 #endif
02351 return status;
02352
02353 case expr_funcall:
02354 bv = (struct binding_value *)0;
02355 status = evaluate_expression (&bv, packet, lease,
02356 client_state,
02357 in_options, cfg_options,
02358 scope, expr, MDL);
02359 if (status) {
02360 if (bv -> type != binding_numeric)
02361 log_error ("%s() returned type %d in %s.",
02362 expr -> data.funcall.name,
02363 bv -> type,
02364 "evaluate_numeric_expression");
02365 else
02366 *result = bv -> value.intval;
02367 binding_value_dereference (&bv, MDL);
02368 }
02369 #if defined (DEBUG_EXPRESSIONS)
02370 log_debug ("data: %s = %ld", expr -> data.funcall.name,
02371 status ? *result : 0);
02372 #endif
02373 break;
02374
02375 case expr_add:
02376 sleft = evaluate_numeric_expression (&ileft, packet, lease,
02377 client_state,
02378 in_options, cfg_options,
02379 scope,
02380 expr -> data.and [0]);
02381 sright = evaluate_numeric_expression (&iright, packet, lease,
02382 client_state,
02383 in_options, cfg_options,
02384 scope,
02385 expr -> data.and [1]);
02386
02387 #if defined (DEBUG_EXPRESSIONS)
02388 if (sleft && sright)
02389 log_debug ("num: %ld + %ld = %ld",
02390 ileft, iright, ileft + iright);
02391 else if (sleft)
02392 log_debug ("num: %ld + NULL = NULL", ileft);
02393 else
02394 log_debug ("num: NULL + %ld = NULL", iright);
02395 #endif
02396 if (sleft && sright) {
02397 *result = ileft + iright;
02398 return 1;
02399 }
02400 return 0;
02401
02402 case expr_subtract:
02403 sleft = evaluate_numeric_expression (&ileft, packet, lease,
02404 client_state,
02405 in_options, cfg_options,
02406 scope,
02407 expr -> data.and [0]);
02408 sright = evaluate_numeric_expression (&iright, packet, lease,
02409 client_state,
02410 in_options, cfg_options,
02411 scope,
02412 expr -> data.and [1]);
02413
02414 #if defined (DEBUG_EXPRESSIONS)
02415 if (sleft && sright)
02416 log_debug ("num: %ld - %ld = %ld",
02417 ileft, iright, ileft - iright);
02418 else if (sleft)
02419 log_debug ("num: %ld - NULL = NULL", ileft);
02420 else
02421 log_debug ("num: NULL - %ld = NULL", iright);
02422 #endif
02423 if (sleft && sright) {
02424 *result = ileft - iright;
02425 return 1;
02426 }
02427 return 0;
02428
02429 case expr_multiply:
02430 sleft = evaluate_numeric_expression (&ileft, packet, lease,
02431 client_state,
02432 in_options, cfg_options,
02433 scope,
02434 expr -> data.and [0]);
02435 sright = evaluate_numeric_expression (&iright, packet, lease,
02436 client_state,
02437 in_options, cfg_options,
02438 scope,
02439 expr -> data.and [1]);
02440
02441 #if defined (DEBUG_EXPRESSIONS)
02442 if (sleft && sright)
02443 log_debug ("num: %ld * %ld = %ld",
02444 ileft, iright, ileft * iright);
02445 else if (sleft)
02446 log_debug ("num: %ld * NULL = NULL", ileft);
02447 else
02448 log_debug ("num: NULL * %ld = NULL", iright);
02449 #endif
02450 if (sleft && sright) {
02451 *result = ileft * iright;
02452 return 1;
02453 }
02454 return 0;
02455
02456 case expr_divide:
02457 sleft = evaluate_numeric_expression (&ileft, packet, lease,
02458 client_state,
02459 in_options, cfg_options,
02460 scope,
02461 expr -> data.and [0]);
02462 sright = evaluate_numeric_expression (&iright, packet, lease,
02463 client_state,
02464 in_options, cfg_options,
02465 scope,
02466 expr -> data.and [1]);
02467
02468 #if defined (DEBUG_EXPRESSIONS)
02469 if (sleft && sright) {
02470 if (iright != 0)
02471 log_debug ("num: %ld / %ld = %ld",
02472 ileft, iright, ileft / iright);
02473 else
02474 log_debug ("num: %ld / %ld = NULL",
02475 ileft, iright);
02476 } else if (sleft)
02477 log_debug ("num: %ld / NULL = NULL", ileft);
02478 else
02479 log_debug ("num: NULL / %ld = NULL", iright);
02480 #endif
02481 if (sleft && sright && iright) {
02482 *result = ileft / iright;
02483 return 1;
02484 }
02485 return 0;
02486
02487 case expr_remainder:
02488 sleft = evaluate_numeric_expression (&ileft, packet, lease,
02489 client_state,
02490 in_options, cfg_options,
02491 scope,
02492 expr -> data.and [0]);
02493 sright = evaluate_numeric_expression (&iright, packet, lease,
02494 client_state,
02495 in_options, cfg_options,
02496 scope,
02497 expr -> data.and [1]);
02498
02499 #if defined (DEBUG_EXPRESSIONS)
02500 if (sleft && sright) {
02501 if (iright != 0)
02502 log_debug ("num: %ld %% %ld = %ld",
02503 ileft, iright, ileft % iright);
02504 else
02505 log_debug ("num: %ld %% %ld = NULL",
02506 ileft, iright);
02507 } else if (sleft)
02508 log_debug ("num: %ld %% NULL = NULL", ileft);
02509 else
02510 log_debug ("num: NULL %% %ld = NULL", iright);
02511 #endif
02512 if (sleft && sright && iright) {
02513 *result = ileft % iright;
02514 return 1;
02515 }
02516 return 0;
02517
02518 case expr_binary_and:
02519 sleft = evaluate_numeric_expression (&ileft, packet, lease,
02520 client_state,
02521 in_options, cfg_options,
02522 scope,
02523 expr -> data.and [0]);
02524 sright = evaluate_numeric_expression (&iright, packet, lease,
02525 client_state,
02526 in_options, cfg_options,
02527 scope,
02528 expr -> data.and [1]);
02529
02530 #if defined (DEBUG_EXPRESSIONS)
02531 if (sleft && sright)
02532 log_debug ("num: %ld | %ld = %ld",
02533 ileft, iright, ileft & iright);
02534 else if (sleft)
02535 log_debug ("num: %ld & NULL = NULL", ileft);
02536 else
02537 log_debug ("num: NULL & %ld = NULL", iright);
02538 #endif
02539 if (sleft && sright) {
02540 *result = ileft & iright;
02541 return 1;
02542 }
02543 return 0;
02544
02545 case expr_binary_or:
02546 sleft = evaluate_numeric_expression (&ileft, packet, lease,
02547 client_state,
02548 in_options, cfg_options,
02549 scope,
02550 expr -> data.and [0]);
02551 sright = evaluate_numeric_expression (&iright, packet, lease,
02552 client_state,
02553 in_options, cfg_options,
02554 scope,
02555 expr -> data.and [1]);
02556
02557 #if defined (DEBUG_EXPRESSIONS)
02558 if (sleft && sright)
02559 log_debug ("num: %ld | %ld = %ld",
02560 ileft, iright, ileft | iright);
02561 else if (sleft)
02562 log_debug ("num: %ld | NULL = NULL", ileft);
02563 else
02564 log_debug ("num: NULL | %ld = NULL", iright);
02565 #endif
02566 if (sleft && sright) {
02567 *result = ileft | iright;
02568 return 1;
02569 }
02570 return 0;
02571
02572 case expr_binary_xor:
02573 sleft = evaluate_numeric_expression (&ileft, packet, lease,
02574 client_state,
02575 in_options, cfg_options,
02576 scope,
02577 expr -> data.and [0]);
02578 sright = evaluate_numeric_expression (&iright, packet, lease,
02579 client_state,
02580 in_options, cfg_options,
02581 scope,
02582 expr -> data.and [1]);
02583
02584 #if defined (DEBUG_EXPRESSIONS)
02585 if (sleft && sright)
02586 log_debug ("num: %ld ^ %ld = %ld",
02587 ileft, iright, ileft ^ iright);
02588 else if (sleft)
02589 log_debug ("num: %ld ^ NULL = NULL", ileft);
02590 else
02591 log_debug ("num: NULL ^ %ld = NULL", iright);
02592 #endif
02593 if (sleft && sright) {
02594 *result = ileft ^ iright;
02595 return 1;
02596 }
02597 return 0;
02598
02599 case expr_client_state:
02600 if (client_state) {
02601 #if defined (DEBUG_EXPRESSIONS)
02602 log_debug ("num: client-state = %d",
02603 client_state -> state);
02604 #endif
02605 *result = client_state -> state;
02606 return 1;
02607 } else {
02608 #if defined (DEBUG_EXPRESSIONS)
02609 log_debug ("num: client-state = NULL");
02610 #endif
02611 return 0;
02612 }
02613
02614 case expr_function:
02615 log_error ("function definition in evaluate_numeric_expr");
02616 return 0;
02617
02618 case expr_arg:
02619 break;
02620
02621 default:
02622 log_fatal("Impossible case at %s:%d. Undefined operator "
02623 "%d.", MDL, expr->op);
02624 break;
02625 }
02626
02627 log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op);
02628 return 0;
02629 }
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643 int evaluate_option_cache (result, packet, lease, client_state,
02644 in_options, cfg_options, scope, oc, file, line)
02645 struct data_string *result;
02646 struct packet *packet;
02647 struct lease *lease;
02648 struct client_state *client_state;
02649 struct option_state *in_options;
02650 struct option_state *cfg_options;
02651 struct binding_scope **scope;
02652 struct option_cache *oc;
02653 const char *file;
02654 int line;
02655 {
02656 if (oc->data.data != NULL) {
02657 data_string_copy (result, &oc -> data, file, line);
02658 return 1;
02659 }
02660 if (!oc -> expression)
02661 return 0;
02662 return evaluate_data_expression (result, packet, lease, client_state,
02663 in_options, cfg_options, scope,
02664 oc -> expression, file, line);
02665 }
02666
02667
02668
02669
02670 int evaluate_boolean_option_cache (ignorep, packet,
02671 lease, client_state, in_options,
02672 cfg_options, scope, oc, file, line)
02673 int *ignorep;
02674 struct packet *packet;
02675 struct lease *lease;
02676 struct client_state *client_state;
02677 struct option_state *in_options;
02678 struct option_state *cfg_options;
02679 struct binding_scope **scope;
02680 struct option_cache *oc;
02681 const char *file;
02682 int line;
02683 {
02684 struct data_string ds;
02685 int result;
02686
02687
02688 if (!oc || !in_options)
02689 return 0;
02690
02691 memset (&ds, 0, sizeof ds);
02692 if (!evaluate_option_cache (&ds, packet,
02693 lease, client_state, in_options,
02694 cfg_options, scope, oc, file, line))
02695 return 0;
02696
02697
02698
02699
02700 if (ds.len) {
02701 result = ds.data [0];
02702 if (result == 2) {
02703 result = 0;
02704 if (ignorep != NULL)
02705 *ignorep = 1;
02706 } else if (ignorep != NULL)
02707 *ignorep = 0;
02708 } else
02709 result = 0;
02710 data_string_forget (&ds, MDL);
02711 return result;
02712 }
02713
02714
02715
02716
02717
02718 int evaluate_boolean_expression_result (ignorep, packet, lease, client_state,
02719 in_options, cfg_options, scope, expr)
02720 int *ignorep;
02721 struct packet *packet;
02722 struct lease *lease;
02723 struct client_state *client_state;
02724 struct option_state *in_options;
02725 struct option_state *cfg_options;
02726 struct binding_scope **scope;
02727 struct expression *expr;
02728 {
02729 int result;
02730
02731
02732 if (!expr)
02733 return 0;
02734
02735 if (!evaluate_boolean_expression (&result, packet, lease, client_state,
02736 in_options, cfg_options,
02737 scope, expr))
02738 return 0;
02739
02740 if (result == 2) {
02741 *ignorep = 1;
02742 result = 0;
02743 } else
02744 *ignorep = 0;
02745 return result;
02746 }
02747
02748
02749
02750
02751 void expression_dereference (eptr, file, line)
02752 struct expression **eptr;
02753 const char *file;
02754 int line;
02755 {
02756 struct expression *expr = *eptr;
02757
02758
02759 *eptr = (struct expression *)0;
02760
02761
02762
02763 --(expr -> refcnt);
02764 rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC);
02765 if (expr -> refcnt > 0)
02766 return;
02767 if (expr -> refcnt < 0) {
02768 log_error ("%s(%d): negative refcnt!", file, line);
02769 #if defined (DEBUG_RC_HISTORY)
02770 dump_rc_history (expr);
02771 #endif
02772 #if defined (POINTER_DEBUG)
02773 abort ();
02774 #else
02775 return;
02776 #endif
02777 }
02778
02779
02780 switch (expr -> op) {
02781
02782 case expr_equal:
02783 case expr_not_equal:
02784 case expr_regex_match:
02785 case expr_iregex_match:
02786 case expr_concat:
02787 case expr_and:
02788 case expr_or:
02789 case expr_add:
02790 case expr_subtract:
02791 case expr_multiply:
02792 case expr_divide:
02793 case expr_remainder:
02794 case expr_binary_and:
02795 case expr_binary_or:
02796 case expr_binary_xor:
02797 case expr_client_state:
02798 if (expr -> data.equal [0])
02799 expression_dereference (&expr -> data.equal [0],
02800 file, line);
02801 if (expr -> data.equal [1])
02802 expression_dereference (&expr -> data.equal [1],
02803 file, line);
02804 break;
02805
02806 case expr_substring:
02807 if (expr -> data.substring.expr)
02808 expression_dereference (&expr -> data.substring.expr,
02809 file, line);
02810 if (expr -> data.substring.offset)
02811 expression_dereference (&expr -> data.substring.offset,
02812 file, line);
02813 if (expr -> data.substring.len)
02814 expression_dereference (&expr -> data.substring.len,
02815 file, line);
02816 break;
02817
02818 case expr_suffix:
02819 if (expr -> data.suffix.expr)
02820 expression_dereference (&expr -> data.suffix.expr,
02821 file, line);
02822 if (expr -> data.suffix.len)
02823 expression_dereference (&expr -> data.suffix.len,
02824 file, line);
02825 break;
02826
02827 case expr_lcase:
02828 if (expr->data.lcase)
02829 expression_dereference(&expr->data.lcase, MDL);
02830 break;
02831
02832 case expr_ucase:
02833 if (expr->data.ucase)
02834 expression_dereference(&expr->data.ucase, MDL);
02835 break;
02836
02837 case expr_not:
02838 if (expr -> data.not)
02839 expression_dereference (&expr -> data.not, file, line);
02840 break;
02841
02842 case expr_packet:
02843 if (expr -> data.packet.offset)
02844 expression_dereference (&expr -> data.packet.offset,
02845 file, line);
02846 if (expr -> data.packet.len)
02847 expression_dereference (&expr -> data.packet.len,
02848 file, line);
02849 break;
02850
02851 case expr_extract_int8:
02852 case expr_extract_int16:
02853 case expr_extract_int32:
02854 if (expr -> data.extract_int)
02855 expression_dereference (&expr -> data.extract_int,
02856 file, line);
02857 break;
02858
02859 case expr_encode_int8:
02860 case expr_encode_int16:
02861 case expr_encode_int32:
02862 if (expr -> data.encode_int)
02863 expression_dereference (&expr -> data.encode_int,
02864 file, line);
02865 break;
02866
02867 case expr_encapsulate:
02868 case expr_const_data:
02869 data_string_forget (&expr -> data.const_data, file, line);
02870 break;
02871
02872 case expr_host_lookup:
02873 if (expr -> data.host_lookup)
02874 dns_host_entry_dereference (&expr -> data.host_lookup,
02875 file, line);
02876 break;
02877
02878 case expr_binary_to_ascii:
02879 if (expr -> data.b2a.base)
02880 expression_dereference (&expr -> data.b2a.base,
02881 file, line);
02882 if (expr -> data.b2a.width)
02883 expression_dereference (&expr -> data.b2a.width,
02884 file, line);
02885 if (expr -> data.b2a.separator)
02886 expression_dereference (&expr -> data.b2a.separator,
02887 file, line);
02888 if (expr -> data.b2a.buffer)
02889 expression_dereference (&expr -> data.b2a.buffer,
02890 file, line);
02891 break;
02892
02893 case expr_pick_first_value:
02894 if (expr -> data.pick_first_value.car)
02895 expression_dereference (&expr -> data.pick_first_value.car,
02896 file, line);
02897 if (expr -> data.pick_first_value.cdr)
02898 expression_dereference (&expr -> data.pick_first_value.cdr,
02899 file, line);
02900 break;
02901
02902 case expr_reverse:
02903 if (expr -> data.reverse.width)
02904 expression_dereference (&expr -> data.reverse.width,
02905 file, line);
02906 if (expr -> data.reverse.buffer)
02907 expression_dereference
02908 (&expr -> data.reverse.buffer, file, line);
02909 break;
02910
02911 case expr_variable_reference:
02912 case expr_variable_exists:
02913 if (expr -> data.variable)
02914 dfree (expr -> data.variable, file, line);
02915 break;
02916
02917 case expr_funcall:
02918 if (expr -> data.funcall.name)
02919 dfree (expr -> data.funcall.name, file, line);
02920 if (expr -> data.funcall.arglist)
02921 expression_dereference (&expr -> data.funcall.arglist,
02922 file, line);
02923 break;
02924
02925 case expr_arg:
02926 if (expr -> data.arg.val)
02927 expression_dereference (&expr -> data.arg.val,
02928 file, line);
02929 if (expr -> data.arg.next)
02930 expression_dereference (&expr -> data.arg.next,
02931 file, line);
02932 break;
02933
02934 case expr_function:
02935 fundef_dereference (&expr -> data.func, file, line);
02936 break;
02937
02938 case expr_v6relay:
02939 if (expr->data.v6relay.relay)
02940 expression_dereference(&expr->data.v6relay.relay,
02941 file, line);
02942
02943 if (expr->data.v6relay.roption)
02944 expression_dereference(&expr->data.v6relay.roption,
02945 file, line);
02946 break;
02947
02948
02949 case expr_leased_address:
02950 case expr_lease_time:
02951 case expr_filename:
02952 case expr_sname:
02953 case expr_const_int:
02954 case expr_check:
02955 case expr_option:
02956 case expr_hardware:
02957 case expr_exists:
02958 case expr_known:
02959 case expr_null:
02960 case expr_gethostname:
02961 break;
02962
02963 default:
02964 break;
02965 }
02966 free_expression (expr, MDL);
02967 }
02968
02969 int is_boolean_expression (expr)
02970 struct expression *expr;
02971 {
02972 return (expr -> op == expr_check ||
02973 expr -> op == expr_exists ||
02974 expr -> op == expr_variable_exists ||
02975 expr -> op == expr_equal ||
02976 expr -> op == expr_not_equal ||
02977 expr->op == expr_regex_match ||
02978 expr->op == expr_iregex_match ||
02979 expr -> op == expr_and ||
02980 expr -> op == expr_or ||
02981 expr -> op == expr_not ||
02982 expr -> op == expr_known ||
02983 expr -> op == expr_static);
02984 }
02985
02986 int is_data_expression (expr)
02987 struct expression *expr;
02988 {
02989 return (expr->op == expr_substring ||
02990 expr->op == expr_suffix ||
02991 expr->op == expr_lcase ||
02992 expr->op == expr_ucase ||
02993 expr->op == expr_option ||
02994 expr->op == expr_hardware ||
02995 expr->op == expr_const_data ||
02996 expr->op == expr_packet ||
02997 expr->op == expr_concat ||
02998 expr->op == expr_encapsulate ||
02999 expr->op == expr_encode_int8 ||
03000 expr->op == expr_encode_int16 ||
03001 expr->op == expr_encode_int32 ||
03002 expr->op == expr_host_lookup ||
03003 expr->op == expr_binary_to_ascii ||
03004 expr->op == expr_filename ||
03005 expr->op == expr_sname ||
03006 expr->op == expr_reverse ||
03007 expr->op == expr_pick_first_value ||
03008 expr->op == expr_host_decl_name ||
03009 expr->op == expr_leased_address ||
03010 expr->op == expr_config_option ||
03011 expr->op == expr_null ||
03012 expr->op == expr_gethostname ||
03013 expr->op == expr_v6relay);
03014 }
03015
03016 int is_numeric_expression (expr)
03017 struct expression *expr;
03018 {
03019 return (expr -> op == expr_extract_int8 ||
03020 expr -> op == expr_extract_int16 ||
03021 expr -> op == expr_extract_int32 ||
03022 expr -> op == expr_const_int ||
03023 expr -> op == expr_lease_time ||
03024 expr -> op == expr_add ||
03025 expr -> op == expr_subtract ||
03026 expr -> op == expr_multiply ||
03027 expr -> op == expr_divide ||
03028 expr -> op == expr_remainder ||
03029 expr -> op == expr_binary_and ||
03030 expr -> op == expr_binary_or ||
03031 expr -> op == expr_binary_xor ||
03032 expr -> op == expr_client_state);
03033 }
03034
03035 int is_compound_expression (expr)
03036 struct expression *expr;
03037 {
03038 return (expr -> op == expr_substring ||
03039 expr -> op == expr_suffix ||
03040 expr -> op == expr_option ||
03041 expr -> op == expr_concat ||
03042 expr -> op == expr_encode_int8 ||
03043 expr -> op == expr_encode_int16 ||
03044 expr -> op == expr_encode_int32 ||
03045 expr -> op == expr_binary_to_ascii ||
03046 expr -> op == expr_reverse ||
03047 expr -> op == expr_pick_first_value ||
03048 expr -> op == expr_config_option ||
03049 expr -> op == expr_extract_int8 ||
03050 expr -> op == expr_extract_int16 ||
03051 expr -> op == expr_extract_int32 ||
03052 expr -> op == expr_v6relay);
03053 }
03054
03055 static int op_val (enum expr_op);
03056
03057 static int op_val (op)
03058 enum expr_op op;
03059 {
03060 switch (op) {
03061 case expr_none:
03062 case expr_match:
03063 case expr_static:
03064 case expr_check:
03065 case expr_substring:
03066 case expr_suffix:
03067 case expr_lcase:
03068 case expr_ucase:
03069 case expr_concat:
03070 case expr_encapsulate:
03071 case expr_host_lookup:
03072 case expr_not:
03073 case expr_option:
03074 case expr_hardware:
03075 case expr_packet:
03076 case expr_const_data:
03077 case expr_extract_int8:
03078 case expr_extract_int16:
03079 case expr_extract_int32:
03080 case expr_encode_int8:
03081 case expr_encode_int16:
03082 case expr_encode_int32:
03083 case expr_const_int:
03084 case expr_exists:
03085 case expr_variable_exists:
03086 case expr_known:
03087 case expr_binary_to_ascii:
03088 case expr_reverse:
03089 case expr_filename:
03090 case expr_sname:
03091 case expr_pick_first_value:
03092 case expr_host_decl_name:
03093 case expr_config_option:
03094 case expr_leased_address:
03095 case expr_lease_time:
03096 case expr_dns_transaction:
03097 case expr_null:
03098 case expr_variable_reference:
03099 case expr_ns_add:
03100 case expr_ns_delete:
03101 case expr_ns_exists:
03102 case expr_ns_not_exists:
03103 case expr_arg:
03104 case expr_funcall:
03105 case expr_function:
03106
03107 case expr_binary_and:
03108 case expr_binary_or:
03109 case expr_binary_xor:
03110 case expr_client_state:
03111 case expr_gethostname:
03112 case expr_v6relay:
03113 return 100;
03114
03115 case expr_equal:
03116 case expr_not_equal:
03117 case expr_regex_match:
03118 case expr_iregex_match:
03119 return 4;
03120
03121 case expr_or:
03122 case expr_and:
03123 return 3;
03124
03125 case expr_add:
03126 case expr_subtract:
03127 return 2;
03128
03129 case expr_multiply:
03130 case expr_divide:
03131 case expr_remainder:
03132 return 1;
03133 }
03134 return 100;
03135 }
03136
03137 int op_precedence (op1, op2)
03138 enum expr_op op1, op2;
03139 {
03140 return op_val (op1) - op_val (op2);
03141 }
03142
03143 enum expression_context expression_context (struct expression *expr)
03144 {
03145 if (is_data_expression (expr))
03146 return context_data;
03147 if (is_numeric_expression (expr))
03148 return context_numeric;
03149 if (is_boolean_expression (expr))
03150 return context_boolean;
03151 return context_any;
03152 }
03153
03154 enum expression_context op_context (op)
03155 enum expr_op op;
03156 {
03157 switch (op) {
03158
03159 case expr_none:
03160 case expr_match:
03161 case expr_static:
03162 case expr_check:
03163 case expr_substring:
03164 case expr_suffix:
03165 case expr_lcase:
03166 case expr_ucase:
03167 case expr_concat:
03168 case expr_encapsulate:
03169 case expr_host_lookup:
03170 case expr_not:
03171 case expr_option:
03172 case expr_hardware:
03173 case expr_packet:
03174 case expr_const_data:
03175 case expr_extract_int8:
03176 case expr_extract_int16:
03177 case expr_extract_int32:
03178 case expr_encode_int8:
03179 case expr_encode_int16:
03180 case expr_encode_int32:
03181 case expr_const_int:
03182 case expr_exists:
03183 case expr_variable_exists:
03184 case expr_known:
03185 case expr_binary_to_ascii:
03186 case expr_reverse:
03187 case expr_filename:
03188 case expr_sname:
03189 case expr_pick_first_value:
03190 case expr_host_decl_name:
03191 case expr_config_option:
03192 case expr_leased_address:
03193 case expr_lease_time:
03194 case expr_null:
03195 case expr_variable_reference:
03196 case expr_ns_add:
03197 case expr_ns_delete:
03198 case expr_ns_exists:
03199 case expr_ns_not_exists:
03200 case expr_dns_transaction:
03201 case expr_arg:
03202 case expr_funcall:
03203 case expr_function:
03204 case expr_gethostname:
03205 case expr_v6relay:
03206 return context_any;
03207
03208 case expr_equal:
03209 case expr_not_equal:
03210 case expr_regex_match:
03211 case expr_iregex_match:
03212 return context_data;
03213
03214 case expr_and:
03215 return context_boolean;
03216
03217 case expr_or:
03218 return context_boolean;
03219
03220 case expr_add:
03221 case expr_subtract:
03222 case expr_multiply:
03223 case expr_divide:
03224 case expr_remainder:
03225 case expr_binary_and:
03226 case expr_binary_or:
03227 case expr_binary_xor:
03228 case expr_client_state:
03229 return context_numeric;
03230 }
03231 return context_any;
03232 }
03233
03234 int write_expression (file, expr, col, indent, firstp)
03235 FILE *file;
03236 struct expression *expr;
03237 int col;
03238 int indent;
03239 int firstp;
03240 {
03241 struct expression *e;
03242 const char *s;
03243 char obuf [65];
03244 int scol;
03245 int width;
03246
03247
03248 if (!firstp && is_compound_expression (expr)) {
03249 indent_spaces (file, indent);
03250 col = indent;
03251 }
03252
03253 switch (expr -> op) {
03254 case expr_none:
03255 col = token_print_indent (file, col, indent, "", "", "null");
03256 break;
03257
03258 case expr_check:
03259 col = token_print_indent (file, col, indent, "", "", "check");
03260 col = token_print_indent_concat (file, col, indent,
03261 " ", "", "\"",
03262 expr -> data.check -> name,
03263 "\"", (char *)0);
03264 break;
03265
03266 case expr_regex_match:
03267 s = "~=";
03268 goto binary;
03269
03270 case expr_iregex_match:
03271 s = "~~";
03272 goto binary;
03273
03274 case expr_not_equal:
03275 s = "!=";
03276 goto binary;
03277
03278 case expr_equal:
03279 s = "=";
03280 binary:
03281 col = write_expression (file, expr -> data.equal [0],
03282 col, indent, 1);
03283 col = token_print_indent (file, col, indent, " ", " ", s);
03284 col = write_expression (file, expr -> data.equal [1],
03285 col, indent + 2, 0);
03286 break;
03287
03288 case expr_substring:
03289 col = token_print_indent (file, col, indent, "", "",
03290 "substring");
03291 col = token_print_indent (file, col, indent, " ", "", "(");
03292 scol = col;
03293 col = write_expression (file, expr -> data.substring.expr,
03294 col, scol, 1);
03295 col = token_print_indent (file, col, indent, "", " ", ",");
03296 col = write_expression (file, expr -> data.substring.offset,
03297 col, indent, 0);
03298 col = token_print_indent (file, col, scol, "", " ", ",");
03299 col = write_expression (file, expr -> data.substring.len,
03300 col, scol, 0);
03301 col = token_print_indent (file, col, indent, "", "", ")");
03302 break;
03303
03304 case expr_suffix:
03305 col = token_print_indent (file, col, indent, "", "", "suffix");
03306 col = token_print_indent (file, col, indent, " ", "", "(");
03307 scol = col;
03308 col = write_expression (file, expr -> data.suffix.expr,
03309 col, scol, 1);
03310 col = token_print_indent (file, col, scol, "", " ", ",");
03311 col = write_expression (file, expr -> data.suffix.len,
03312 col, scol, 0);
03313 col = token_print_indent (file, col, indent, "", "", ")");
03314 break;
03315
03316 case expr_lcase:
03317 col = token_print_indent(file, col, indent, "", "", "lcase");
03318 col = token_print_indent(file, col, indent, " ", "", "(");
03319 scol = col;
03320 col = write_expression(file, expr->data.lcase, col, scol, 1);
03321 col = token_print_indent(file, col, indent, "", "", ")");
03322 break;
03323
03324 case expr_ucase:
03325 col = token_print_indent(file, col, indent, "", "", "ucase");
03326 col = token_print_indent(file, col, indent, " ", "", "(");
03327 scol = col;
03328 col = write_expression(file, expr->data.ucase, col, scol, 1);
03329 col = token_print_indent(file, col, indent, "", "", ")");
03330 break;
03331
03332 case expr_concat:
03333 e = expr;
03334 col = token_print_indent (file, col, indent, "", "",
03335 "concat");
03336 col = token_print_indent (file, col, indent, " ", "", "(");
03337 scol = col;
03338 firstp = 1;
03339 concat_again:
03340 col = write_expression (file, e -> data.concat [0],
03341 col, scol, firstp);
03342 firstp = 0;
03343 if (!e -> data.concat [1])
03344 goto no_concat_cdr;
03345 col = token_print_indent (file, col, scol, "", " ", ",");
03346 if (e -> data.concat [1] -> op == expr_concat) {
03347 e = e -> data.concat [1];
03348 goto concat_again;
03349 }
03350 col = write_expression (file, e -> data.concat [1],
03351 col, scol, 0);
03352 no_concat_cdr:
03353 col = token_print_indent (file, col, indent, "", "", ")");
03354 break;
03355
03356 case expr_host_lookup:
03357 col = token_print_indent (file, col, indent, "", "",
03358 "gethostbyname");
03359 col = token_print_indent (file, col, indent, " ", "", "(");
03360 col = token_print_indent_concat
03361 (file, col, indent, "", "",
03362 "\"", expr -> data.host_lookup -> hostname, "\"",
03363 (char *)0);
03364 col = token_print_indent (file, col, indent, "", "", ")");
03365 break;
03366
03367 case expr_add:
03368 s = "+";
03369 goto binary;
03370
03371 case expr_subtract:
03372 s = "-";
03373 goto binary;
03374
03375 case expr_multiply:
03376 s = "*";
03377 goto binary;
03378
03379 case expr_divide:
03380 s = "/";
03381 goto binary;
03382
03383 case expr_remainder:
03384 s = "%";
03385 goto binary;
03386
03387 case expr_binary_and:
03388 s = "&";
03389 goto binary;
03390
03391 case expr_binary_or:
03392 s = "|";
03393 goto binary;
03394
03395 case expr_binary_xor:
03396 s = "^";
03397 goto binary;
03398
03399 case expr_and:
03400 s = "and";
03401 goto binary;
03402
03403 case expr_or:
03404 s = "or";
03405 goto binary;
03406
03407 case expr_not:
03408 col = token_print_indent (file, col, indent, "", " ", "not");
03409 col = write_expression (file,
03410 expr -> data.not, col, indent + 2, 1);
03411 break;
03412
03413 case expr_option:
03414 s = "option";
03415
03416 print_option_name:
03417 col = token_print_indent (file, col, indent, "", "", s);
03418
03419 if (expr -> data.option -> universe != &dhcp_universe) {
03420 col = token_print_indent (file, col, indent,
03421 " ", "",
03422 (expr -> data.option ->
03423 universe -> name));
03424 col = token_print_indent (file, col, indent, "", "",
03425 ".");
03426 col = token_print_indent (file, col, indent, "", "",
03427 expr -> data.option -> name);
03428 } else {
03429 col = token_print_indent (file, col, indent, " ", "",
03430 expr -> data.option -> name);
03431 }
03432 break;
03433
03434 case expr_hardware:
03435 col = token_print_indent (file, col, indent, "", "",
03436 "hardware");
03437 break;
03438
03439 case expr_packet:
03440 col = token_print_indent (file, col, indent, "", "",
03441 "packet");
03442 col = token_print_indent (file, col, indent, " ", "", "(");
03443 scol = col;
03444 col = write_expression (file, expr -> data.packet.offset,
03445 col, indent, 1);
03446 col = token_print_indent (file, col, scol, "", " ", ",");
03447 col = write_expression (file, expr -> data.packet.len,
03448 col, scol, 0);
03449 col = token_print_indent (file, col, indent, "", "", ")");
03450 break;
03451
03452 case expr_const_data:
03453 col = token_indent_data_string (file, col, indent, "", "",
03454 &expr -> data.const_data);
03455 break;
03456
03457 case expr_extract_int8:
03458 width = 8;
03459 extract_int:
03460 col = token_print_indent (file, col, indent, "", "",
03461 "extract-int");
03462 col = token_print_indent (file, col, indent, " ", "", "(");
03463 scol = col;
03464 col = write_expression (file, expr -> data.extract_int,
03465 col, indent, 1);
03466 col = token_print_indent (file, col, scol, "", " ", ",");
03467 sprintf (obuf, "%d", width);
03468 col = token_print_indent (file, col, scol, " ", "", obuf);
03469 col = token_print_indent (file, col, indent, "", "", ")");
03470 break;
03471
03472 case expr_extract_int16:
03473 width = 16;
03474 goto extract_int;
03475
03476 case expr_extract_int32:
03477 width = 32;
03478 goto extract_int;
03479
03480 case expr_encode_int8:
03481 width = 8;
03482 encode_int:
03483 col = token_print_indent (file, col, indent, "", "",
03484 "encode-int");
03485 col = token_print_indent (file, col, indent, " ", "", "(");
03486 scol = col;
03487 col = write_expression (file, expr -> data.extract_int,
03488 col, indent, 1);
03489 col = token_print_indent (file, col, scol, "", " ", ",");
03490 sprintf (obuf, "%d", width);
03491 col = token_print_indent (file, col, scol, " ", "", obuf);
03492 col = token_print_indent (file, col, indent, "", "",
03493 ")");
03494 break;
03495
03496 case expr_encode_int16:
03497 width = 16;
03498 goto encode_int;
03499
03500 case expr_encode_int32:
03501 width = 32;
03502 goto encode_int;
03503
03504 case expr_const_int:
03505 sprintf (obuf, "%lu", expr -> data.const_int);
03506 col = token_print_indent (file, col, indent, "", "", obuf);
03507 break;
03508
03509 case expr_exists:
03510 s = "exists";
03511 goto print_option_name;
03512
03513 case expr_encapsulate:
03514 col = token_print_indent (file, col, indent, "", "",
03515 "encapsulate");
03516 col = token_indent_data_string (file, col, indent, " ", "",
03517 &expr -> data.encapsulate);
03518 break;
03519
03520 case expr_known:
03521 col = token_print_indent (file, col, indent, "", "", "known");
03522 break;
03523
03524 case expr_reverse:
03525 col = token_print_indent (file, col, indent, "", "",
03526 "reverse");
03527 col = token_print_indent (file, col, indent, " ", "", "(");
03528 scol = col;
03529 col = write_expression (file, expr -> data.reverse.width,
03530 col, scol, 1);
03531 col = token_print_indent (file, col, scol, "", " ", ",");
03532 col = write_expression (file, expr -> data.reverse.buffer,
03533 col, scol, 0);
03534 col = token_print_indent (file, col, indent, "", "",
03535 ")");
03536 break;
03537
03538 case expr_leased_address:
03539 col = token_print_indent (file, col, indent, "", "",
03540 "leased-address");
03541 break;
03542
03543 case expr_client_state:
03544 col = token_print_indent (file, col, indent, "", "",
03545 "client-state");
03546 break;
03547
03548 case expr_binary_to_ascii:
03549 col = token_print_indent (file, col, indent, "", "",
03550 "binary-to-ascii");
03551 col = token_print_indent (file, col, indent, " ", "",
03552 "(");
03553 scol = col;
03554 col = write_expression (file, expr -> data.b2a.base,
03555 col, scol, 1);
03556 col = token_print_indent (file, col, scol, "", " ",
03557 ",");
03558 col = write_expression (file, expr -> data.b2a.width,
03559 col, scol, 0);
03560 col = token_print_indent (file, col, scol, "", " ",
03561 ",");
03562 col = write_expression (file, expr -> data.b2a.separator,
03563 col, scol, 0);
03564 col = token_print_indent (file, col, scol, "", " ",
03565 ",");
03566 col = write_expression (file, expr -> data.b2a.buffer,
03567 col, scol, 0);
03568 col = token_print_indent (file, col, indent, "", "",
03569 ")");
03570 break;
03571
03572 case expr_config_option:
03573 s = "config-option";
03574 goto print_option_name;
03575
03576 case expr_host_decl_name:
03577 col = token_print_indent (file, col, indent, "", "",
03578 "host-decl-name");
03579 break;
03580
03581 case expr_pick_first_value:
03582 e = expr;
03583 col = token_print_indent (file, col, indent, "", "",
03584 "concat");
03585 col = token_print_indent (file, col, indent, " ", "",
03586 "(");
03587 scol = col;
03588 firstp = 1;
03589 pick_again:
03590 col = write_expression (file,
03591 e -> data.pick_first_value.car,
03592 col, scol, firstp);
03593 firstp = 0;
03594
03595
03596
03597
03598
03599
03600 if (!e -> data.pick_first_value.cdr)
03601 goto no_pick_cdr;
03602 col = token_print_indent (file, col, scol, "", " ",
03603 ",");
03604 if (e -> data.pick_first_value.cdr -> op ==
03605 expr_pick_first_value) {
03606 e = e -> data.pick_first_value.cdr;
03607 goto pick_again;
03608 }
03609 col = write_expression (file,
03610 e -> data.pick_first_value.cdr,
03611 col, scol, 0);
03612 no_pick_cdr:
03613 col = token_print_indent (file, col, indent, "", "",
03614 ")");
03615 break;
03616
03617 case expr_lease_time:
03618 col = token_print_indent (file, col, indent, "", "",
03619 "lease-time");
03620 break;
03621
03622 case expr_static:
03623 col = token_print_indent (file, col, indent, "", "",
03624 "static");
03625 break;
03626
03627 case expr_null:
03628 col = token_print_indent (file, col, indent, "", "", "null");
03629 break;
03630
03631 case expr_variable_reference:
03632 col = token_print_indent (file, indent, indent, "", "",
03633 expr -> data.variable);
03634 break;
03635
03636 case expr_variable_exists:
03637 col = token_print_indent (file, indent, indent, "", "",
03638 "defined");
03639 col = token_print_indent (file, col, indent, " ", "", "(");
03640 col = token_print_indent (file, col, indent, "", "",
03641 expr -> data.variable);
03642 col = token_print_indent (file, col, indent, "", "", ")");
03643 break;
03644
03645 case expr_gethostname:
03646 col = token_print_indent(file, col, indent, "", "",
03647 "gethostname()");
03648 break;
03649
03650 case expr_funcall:
03651 col = token_print_indent(file, indent, indent, "", "",
03652 expr->data.funcall.name);
03653 col = token_print_indent(file, col, indent, " ", "", "(");
03654
03655 firstp = 1;
03656 e = expr->data.funcall.arglist;
03657 while (e != NULL) {
03658 if (!firstp)
03659 col = token_print_indent(file, col, indent,
03660 "", " ", ",");
03661
03662 col = write_expression(file, e->data.arg.val, col,
03663 indent, firstp);
03664 firstp = 0;
03665 e = e->data.arg.next;
03666 }
03667
03668 col = token_print_indent(file, col, indent, "", "", ")");
03669 break;
03670
03671 case expr_v6relay:
03672 col = token_print_indent(file, col, indent, "", "",
03673 "v6relay");
03674 col = token_print_indent(file, col, indent, " ", "", "(");
03675 scol = col;
03676 col = write_expression(file, expr->data.v6relay.relay,
03677 col, scol, 1);
03678 col = token_print_indent (file, col, scol, "", " ", ",");
03679 col = write_expression(file, expr->data.v6relay.roption,
03680 col, scol, 0);
03681 col = token_print_indent(file, col, indent, "", "", ")");
03682 break;
03683
03684 default:
03685 log_fatal ("invalid expression type in print_expression: %d",
03686 expr -> op);
03687 }
03688 return col;
03689 }
03690
03691 struct binding *find_binding (struct binding_scope *scope, const char *name)
03692 {
03693 struct binding *bp;
03694 struct binding_scope *s;
03695
03696 for (s = scope; s; s = s -> outer) {
03697 for (bp = s -> bindings; bp; bp = bp -> next) {
03698 if (!strcasecmp (name, bp -> name)) {
03699 return bp;
03700 }
03701 }
03702 }
03703 return (struct binding *)0;
03704 }
03705
03706 int free_bindings (struct binding_scope *scope, const char *file, int line)
03707 {
03708 struct binding *bp, *next;
03709
03710 for (bp = scope -> bindings; bp; bp = next) {
03711 next = bp -> next;
03712 if (bp -> name)
03713 dfree (bp -> name, file, line);
03714 if (bp -> value)
03715 binding_value_dereference (&bp -> value, file, line);
03716 dfree (bp, file, line);
03717 }
03718 scope -> bindings = (struct binding *)0;
03719 return 1;
03720 }
03721
03722 int binding_scope_dereference (ptr, file, line)
03723 struct binding_scope **ptr;
03724 const char *file;
03725 int line;
03726 {
03727 struct binding_scope *binding_scope;
03728
03729 if (!ptr || !*ptr) {
03730 log_error ("%s(%d): null pointer", file, line);
03731 #if defined (POINTER_DEBUG)
03732 abort ();
03733 #else
03734 return 0;
03735 #endif
03736 }
03737
03738 binding_scope = *ptr;
03739 *ptr = (struct binding_scope *)0;
03740 --binding_scope -> refcnt;
03741 rc_register (file, line, ptr,
03742 binding_scope, binding_scope -> refcnt, 1, RC_MISC);
03743 if (binding_scope -> refcnt > 0)
03744 return 1;
03745
03746 if (binding_scope -> refcnt < 0) {
03747 log_error ("%s(%d): negative refcnt!", file, line);
03748 #if defined (DEBUG_RC_HISTORY)
03749 dump_rc_history (binding_scope);
03750 #endif
03751 #if defined (POINTER_DEBUG)
03752 abort ();
03753 #else
03754 return 0;
03755 #endif
03756 }
03757
03758 free_bindings (binding_scope, file, line);
03759 if (binding_scope -> outer)
03760 binding_scope_dereference (&binding_scope -> outer, MDL);
03761 dfree (binding_scope, file, line);
03762 return 1;
03763 }
03764
03765 int fundef_dereference (ptr, file, line)
03766 struct fundef **ptr;
03767 const char *file;
03768 int line;
03769 {
03770 struct fundef *bp;
03771 struct string_list *sp, *next;
03772
03773 if ((ptr == NULL) || (*ptr == NULL)) {
03774 log_error ("%s(%d): null pointer", file, line);
03775 #if defined (POINTER_DEBUG)
03776 abort ();
03777 #else
03778 return 0;
03779 #endif
03780 }
03781
03782 bp = *ptr;
03783 bp -> refcnt--;
03784 rc_register (file, line, ptr, bp, bp -> refcnt, 1, RC_MISC);
03785 if (bp -> refcnt < 0) {
03786 log_error ("%s(%d): negative refcnt!", file, line);
03787 #if defined (DEBUG_RC_HISTORY)
03788 dump_rc_history (bp);
03789 #endif
03790 #if defined (POINTER_DEBUG)
03791 abort ();
03792 #else
03793 return 0;
03794 #endif
03795 }
03796 if (!bp -> refcnt) {
03797 for (sp = bp -> args; sp; sp = next) {
03798 next = sp -> next;
03799 dfree (sp, file, line);
03800 }
03801 if (bp -> statements)
03802 executable_statement_dereference (&bp -> statements,
03803 file, line);
03804 dfree (bp, file, line);
03805 }
03806 *ptr = (struct fundef *)0;
03807 return 1;
03808 }
03809
03810 #if defined (NOTYET)
03811 int data_subexpression_length (int *rv,
03812 struct expression *expr)
03813 {
03814 int crhs, clhs, llhs, lrhs;
03815 switch (expr -> op) {
03816 case expr_substring:
03817 if (expr -> data.substring.len &&
03818 expr -> data.substring.len -> op == expr_const_int) {
03819 (*rv =
03820 (int)expr -> data.substring.len -> data.const_int);
03821 return 1;
03822 }
03823 return 0;
03824
03825 case expr_packet:
03826 case expr_suffix:
03827 if (expr -> data.suffix.len &&
03828 expr -> data.suffix.len -> op == expr_const_int) {
03829 (*rv =
03830 (int)expr -> data.suffix.len -> data.const_int);
03831 return 1;
03832 }
03833 return 0;
03834
03835 case expr_lcase:
03836 return data_subexpression_length(rv, expr->data.lcase);
03837
03838 case expr_ucase:
03839 return data_subexpression_length(rv, expr->data.ucase);
03840
03841 case expr_concat:
03842 clhs = data_subexpression_length (&llhs,
03843 expr -> data.concat [0]);
03844 crhs = data_subexpression_length (&lrhs,
03845 expr -> data.concat [1]);
03846 if (crhs == 0 || clhs == 0)
03847 return 0;
03848 *rv = llhs + lrhs;
03849 return 1;
03850 break;
03851
03852 case expr_hardware:
03853 return 0;
03854
03855 case expr_const_data:
03856 *rv = expr -> data.const_data.len;
03857 return 2;
03858
03859 case expr_reverse:
03860 return data_subexpression_length (rv,
03861 expr -> data.reverse.buffer);
03862
03863 case expr_leased_address:
03864 case expr_lease_time:
03865 *rv = 4;
03866 return 2;
03867
03868 case expr_pick_first_value:
03869 clhs = data_subexpression_length (&llhs,
03870 expr -> data.concat [0]);
03871 crhs = data_subexpression_length (&lrhs,
03872 expr -> data.concat [1]);
03873 if (crhs == 0 || clhs == 0)
03874 return 0;
03875 if (llhs > lrhs)
03876 *rv = llhs;
03877 else
03878 *rv = lrhs;
03879 return 1;
03880
03881 case expr_v6relay:
03882 clhs = data_subexpression_length (&llhs,
03883 expr -> data.v6relay.relay);
03884 crhs = data_subexpression_length (&lrhs,
03885 expr -> data.v6relay.roption);
03886 if (crhs == 0 || clhs == 0)
03887 return 0;
03888 *rv = llhs + lrhs;
03889 return 1;
03890 break;
03891
03892 case expr_binary_to_ascii:
03893 case expr_config_option:
03894 case expr_host_decl_name:
03895 case expr_encapsulate:
03896 case expr_filename:
03897 case expr_sname:
03898 case expr_host_lookup:
03899 case expr_option:
03900 case expr_none:
03901 case expr_match:
03902 case expr_check:
03903 case expr_equal:
03904 case expr_regex_match:
03905 case expr_iregex_match:
03906 case expr_and:
03907 case expr_or:
03908 case expr_not:
03909 case expr_extract_int8:
03910 case expr_extract_int16:
03911 case expr_extract_int32:
03912 case expr_encode_int8:
03913 case expr_encode_int16:
03914 case expr_encode_int32:
03915 case expr_const_int:
03916 case expr_exists:
03917 case expr_known:
03918 case expr_static:
03919 case expr_not_equal:
03920 case expr_null:
03921 case expr_variable_exists:
03922 case expr_variable_reference:
03923 case expr_arg:
03924 case expr_funcall:
03925 case expr_function:
03926 case expr_add:
03927 case expr_subtract:
03928 case expr_multiply:
03929 case expr_divide:
03930 case expr_remainder:
03931 case expr_binary_and:
03932 case expr_binary_or:
03933 case expr_binary_xor:
03934 case expr_client_state:
03935 case expr_gethostname:
03936 return 0;
03937 }
03938 return 0;
03939 }
03940
03941 int expr_valid_for_context (struct expression *expr,
03942 enum expression_context context)
03943 {
03944
03945
03946 if (expr -> op == expr_funcall ||
03947 expr -> op == expr_variable_reference)
03948 return 1;
03949
03950 switch (context) {
03951 case context_any:
03952 return 1;
03953
03954 case context_boolean:
03955 if (is_boolean_expression (expr))
03956 return 1;
03957 return 0;
03958
03959 case context_data:
03960 if (is_data_expression (expr))
03961 return 1;
03962 return 0;
03963
03964 case context_numeric:
03965 if (is_numeric_expression (expr))
03966 return 1;
03967 return 0;
03968
03969 case context_data_or_numeric:
03970 if (is_numeric_expression (expr) ||
03971 is_data_expression (expr)) {
03972 return 1;
03973 }
03974 return 0;
03975
03976 case context_function:
03977 if (expr -> op == expr_function)
03978 return 1;
03979 return 0;
03980 }
03981 return 0;
03982 }
03983 #endif
03984
03985 struct binding *create_binding (struct binding_scope **scope, const char *name)
03986 {
03987 struct binding *binding;
03988
03989 if (!*scope) {
03990 if (!binding_scope_allocate (scope, MDL))
03991 return (struct binding *)0;
03992 }
03993
03994 binding = find_binding (*scope, name);
03995 if (!binding) {
03996 binding = dmalloc (sizeof *binding, MDL);
03997 if (!binding)
03998 return (struct binding *)0;
03999
04000 memset (binding, 0, sizeof *binding);
04001 binding -> name = dmalloc (strlen (name) + 1, MDL);
04002 if (!binding -> name) {
04003 dfree (binding, MDL);
04004 return (struct binding *)0;
04005 }
04006 strcpy (binding -> name, name);
04007
04008 binding -> next = (*scope) -> bindings;
04009 (*scope) -> bindings = binding;
04010 }
04011
04012 return binding;
04013 }
04014
04015
04016 int bind_ds_value (struct binding_scope **scope,
04017 const char *name,
04018 struct data_string *value)
04019 {
04020 struct binding *binding;
04021
04022 binding = create_binding (scope, name);
04023 if (!binding)
04024 return 0;
04025
04026 if (binding -> value)
04027 binding_value_dereference (&binding -> value, MDL);
04028
04029 if (!binding_value_allocate (&binding -> value, MDL))
04030 return 0;
04031
04032 data_string_copy (&binding -> value -> value.data, value, MDL);
04033 binding -> value -> type = binding_data;
04034
04035 return 1;
04036 }
04037
04038
04039 int find_bound_string (struct data_string *value,
04040 struct binding_scope *scope,
04041 const char *name)
04042 {
04043 struct binding *binding;
04044
04045 binding = find_binding (scope, name);
04046 if (!binding ||
04047 !binding -> value ||
04048 binding -> value -> type != binding_data)
04049 return 0;
04050
04051 if (binding -> value -> value.data.terminated) {
04052 data_string_copy (value, &binding -> value -> value.data, MDL);
04053 } else {
04054 if (buffer_allocate (&value->buffer,
04055 binding->value->value.data.len,
04056 MDL) == 0) {
04057 return 0;
04058 }
04059
04060 memcpy (value -> buffer -> data,
04061 binding -> value -> value.data.data,
04062 binding -> value -> value.data.len);
04063 value -> data = value -> buffer -> data;
04064 value -> len = binding -> value -> value.data.len;
04065 }
04066
04067 return 1;
04068 }
04069
04070 int unset (struct binding_scope *scope, const char *name)
04071 {
04072 struct binding *binding;
04073
04074 binding = find_binding (scope, name);
04075 if (binding) {
04076 if (binding -> value)
04077 binding_value_dereference
04078 (&binding -> value, MDL);
04079 return 1;
04080 }
04081 return 0;
04082 }
04083
04084