common/tree.c

Go to the documentation of this file.
00001 /* tree.c
00002 
00003    Routines for manipulating parse trees... */
00004 
00005 /*
00006  * Copyright (c) 2011-2014 by Internet Systems Consortium, Inc. ("ISC")
00007  * Copyright (c) 2004-2007,2009 by Internet Systems Consortium, Inc. ("ISC")
00008  * Copyright (c) 1995-2003 by Internet Software Consortium
00009  *
00010  * Permission to use, copy, modify, and distribute this software for any
00011  * purpose with or without fee is hereby granted, provided that the above
00012  * copyright notice and this permission notice appear in all copies.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00015  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00016  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00017  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00018  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00019  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00020  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00021  *
00022  *   Internet Systems Consortium, Inc.
00023  *   950 Charter Street
00024  *   Redwood City, CA 94063
00025  *   <info@isc.org>
00026  *   https://www.isc.org/
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  * If we are using a data_string structure to hold a NUL-terminated 
00047  * ASCII string, this function can be used to append a printf-formatted 
00048  * string to the end of it. The data_string structure will be resized to
00049  * be big enough to hold the new string.
00050  *
00051  * If the append works, then 1 is returned.
00052  *
00053  * If it is not possible to allocate a buffer big enough to hold the 
00054  * new value, then the old data_string is unchanged, and 0 is returned.
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          * If the data_string is empty, then initialize it.
00067          */
00068         if (ds->data == NULL) {
00069                 /* INSIST(ds.buffer == NULL); */
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          * Get the length of the string, and figure out how much space
00080          * is left.
00081          */
00082         cur_strlen = strlen((char *)ds->data);
00083         max = ds->len - cur_strlen;
00084 
00085         /* 
00086          * Use vsnprintf(), which won't write past our space, but will
00087          * tell us how much space it wants.
00088          */
00089         va_start(args, fmt);
00090         vsnprintf_ret = vsnprintf((char *)ds->data+cur_strlen, max, fmt, args);
00091         va_end(args);
00092         /* INSIST(vsnprintf_ret >= 0); */
00093 
00094         /*
00095          * If our buffer is not big enough, we need a new buffer.
00096          */
00097         if (vsnprintf_ret >= max) {
00098                 /* 
00099                  * Figure out a size big enough.
00100                  */
00101                 new_len = ds->len * 2;
00102                 while (new_len <= cur_strlen + vsnprintf_ret) {
00103                         new_len *= 2;
00104                 }
00105 
00106                 /* 
00107                  * Create a new buffer and fill it.
00108                  */
00109                 tmp_buffer = NULL;
00110                 if (!buffer_allocate(&tmp_buffer, new_len, MDL)) {
00111                         /* 
00112                          * If we can't create a big enough buffer, 
00113                          * we should remove any truncated output that we had.
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                 /* Rerun the vsprintf. */
00122                 va_start(args, fmt);
00123                 vsprintf((char *)tmp_buffer->data + cur_strlen, fmt, args);
00124                 va_end(args);
00125 
00126                 /*
00127                  * Replace our old buffer with the new buffer.
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         /* XXX This should really keep a hash table of hostnames
00210            XXX and just add a new reference to a hostname that
00211            XXX already exists, if possible, rather than creating
00212            XXX a new structure. */
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         /* If we're concatenating a null tree to a non-null tree, just
00274            return the non-null tree; if both trees are null, return
00275            a null tree. */
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         /* Otherwise, allocate a new node to concatenate the two. */
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         /* Allocate a new node to store the encapsulation. */
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         /* Allocate an expression node to compute the substring. */
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         /* Allocate a node to enforce a limit on evaluation. */
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         /* Offset is a constant 0. */
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         /* Length is a constant: the specified limit. */
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         /* If the record hasn't timed out, just copy the data and return. */
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         /* Otherwise, look it up... */
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 /* !NO_H_ERRNO */
00446 
00447                 /* Okay to try again after a minute. */
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         /* Count the number of addresses we got... */
00459         for (count = 0; h -> h_addr_list [count]; count++)
00460                 ;
00461         
00462         /* Dereference the old data, if any. */
00463         data_string_forget (&dns -> data, MDL);
00464 
00465         /* Do we need to allocate more memory? */
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         /* Addresses are conveniently stored one to the buffer, so we
00478            have to copy them out one at a time... :'( */
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         /* XXX Set the timeout for an hour from now.
00489            XXX This should really use the time on the DNS reply. */
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                 /* Create a new binding scope in which to define
00560                    the arguments to the function. */
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         /* Decrement the reference count.   If it's nonzero, we're
00661            done. */
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                 /* FALL THROUGH */
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                  * If we have bleft and bright then we have a good
00840                  * syntax, otherwise not.
00841                  *
00842                  * XXX: we don't warn on invalid regular expression 
00843                  *      syntax, should we?
00844                  */
00845                 return bleft && bright;
00846 #else
00847                 /* It shouldn't be possible to configure a regex operator
00848                  * when there's no support.
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                 /* Extract N bytes starting at byte M of a data string. */
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                 /* Evaluate the offset and length. */
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                         /* If the offset is after end of the string,
01159                            return an empty string.  Otherwise, do the
01160                            adjustments and return what's left. */
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                 /* Extract the last N bytes of a data string. */
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                 /* Evaluate the length. */
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                         /* If we are returning the last N bytes of a
01205                            string whose length is <= N, just return
01206                            the string - otherwise, compute a new
01207                            starting address and decrease the
01208                            length. */
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                 /* Convert string to lowercase. */
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                 /* Convert string to uppercase. */
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                 /* Extract an option. */
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                 /* Combine the hardware type and address. */
01343               case expr_hardware:
01344                 /* On the client, hardware is our hardware. */
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                 /* The server cares about the client's hardware address,
01357                    so only in the case where we are examining a packet or have
01358                    a lease with a hardware address can we return anything. */
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                 /* Extract part of the raw packet. */
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                 /* The encapsulation of all defined options in an
01448                    option space... */
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                 /* Some constant data... */
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                 /* Hostname lookup... */
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                 /* Concatenation... */
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                 /* Evaluate the base (offset) and width (len): */
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                 /* Evaluate the separator string. */
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                 /* Evaluate the data to be converted. */
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                         /* The buffer must be a multiple of the number's
01662                            width. */
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                         /* Count the width of the output. */
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                         /* NUL terminate. */
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                 /* Evaluate the width (len): */
01754                 s0 = evaluate_numeric_expression
01755                         (&len, packet, lease, client_state, in_options,
01756                          cfg_options, scope, expr -> data.reverse.width);
01757 
01758                 /* Evaluate the data. */
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                         /* The buffer must be a multiple of the number's
01770                            width. */
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                         /* XXX reverse in place?   I don't think we can. */
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                 /* Extract the filename. */
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                 /* Extract the server name. */
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                 /* Provide the system's local hostname as a return value. */
02011               case expr_gethostname:
02012                 /*
02013                  * Allocate a buffer to return.
02014                  *
02015                  * The largest valid hostname is maybe 64 octets at a single
02016                  * label, or 255 octets if you think a hostname is allowed
02017                  * to contain labels (plus termination).
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                  * On successful completion, gethostname() resturns 0.  It may
02028                  * not null-terminate the string if there was insufficient
02029                  * space.
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                 /* Find an option within a v6relay context
02044                  *
02045                  * The numeric expression in relay indicates which relay
02046                  * to try and use as the context.  The relays are numbered
02047                  * 1 to 32 with 1 being the one closest to the client and
02048                  * 32 closest to the server.  A value of greater than 33
02049                  * indicates using the one closest to the server whatever
02050                  * the count.  A value of 0 indicates not using the relay
02051                  * options, this is included for completeness and consistency
02052                  * with the host-identier code.
02053                  *
02054                  * The data expression in roption is evaluated in that
02055                  * context and the result returned.
02056                  */
02057               case expr_v6relay:
02058                 len = 0;
02059                 s1 = 0;
02060                 memset (&data, 0, sizeof data);
02061 
02062                 /* Evaluate the relay count */
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                 /* no number or an obviously invalid number */
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                 /* Find the correct packet for the requested relay */
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                 /* We wanted a specific relay but were unable to find it */
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  * Return data hanging off of an option cache structure, or if there
02633  * isn't any, evaluate the expression hanging off of it and return the
02634  * result of that evaluation.   There should never be both an expression
02635  * and a valid data_string.
02636  *
02637  * returns 0 if there wasn't an expression or it couldn't be evaluated
02638  * returns non-zero if there was an expression or string that was evaluated
02639  * When it returns zero the arguements, in particualr resutl,  should not
02640  * be modified
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 /* Evaluate an option cache and extract a boolean from the result,
02668    returning the boolean.   Return false if there is no data. */
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         /* So that we can be called with option_lookup as an argument. */
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         /* The boolean option cache is actually a trinary value.  Zero is
02698          * off, one is on, and 2 is 'ignore'.
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 /* Evaluate a boolean expression and return the result of the evaluation,
02716    or FALSE if it failed. */
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         /* So that we can be called with option_lookup as an argument. */
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 /* Dereference an expression node, and if the reference count goes to zero,
02750    dereference any data it refers to, and then free it. */
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         /* Zero the pointer. */
02759         *eptr = (struct expression *)0;
02760 
02761         /* Decrement the reference count.   If it's nonzero, we're
02762            done. */
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         /* Dereference subexpressions. */
02780         switch (expr -> op) {
02781                 /* All the binary operators can be handled the same way. */
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                 /* No subexpressions. */
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                 /* XXXDPN: Need to assign sane precedences to these. */
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 /* XXX Why aren't these specific? */
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         /* If this promises to be a fat expression, start a new line. */
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                 /* We're being very lisp-like right now - instead of
03595                    representing this expression as (first middle . last) we're
03596                    representing it as (first middle last), which means that the
03597                    tail cdr is always nil.  Apologies to non-wisp-lizards - may
03598                    this obscure way of describing the problem motivate you to
03599                    learn more about the one true computing language. */
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)            /* Post 3.0 final. */
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         /* We don't know at parse time what type of value a function may
03945            return, so we can't flag an error on it. */
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 /* NOTYET */
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 /* vim: set tabstop=8: */

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1