Annotation of embedaddon/dhcp/common/tree.c, revision 1.1.1.1

1.1       misho       1: /* tree.c
                      2: 
                      3:    Routines for manipulating parse trees... */
                      4: 
                      5: /*
1.1.1.1 ! misho       6:  * Copyright (c) 2011-2012 by Internet Systems Consortium, Inc. ("ISC")
1.1       misho       7:  * Copyright (c) 2004-2007,2009 by Internet Systems Consortium, Inc. ("ISC")
                      8:  * Copyright (c) 1995-2003 by Internet Software Consortium
                      9:  *
                     10:  * Permission to use, copy, modify, and distribute this software for any
                     11:  * purpose with or without fee is hereby granted, provided that the above
                     12:  * copyright notice and this permission notice appear in all copies.
                     13:  *
                     14:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     15:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     16:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     17:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     18:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     19:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     20:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     21:  *
                     22:  *   Internet Systems Consortium, Inc.
                     23:  *   950 Charter Street
                     24:  *   Redwood City, CA 94063
                     25:  *   <info@isc.org>
                     26:  *   https://www.isc.org/
                     27:  *
                     28:  * This software has been written for Internet Systems Consortium
                     29:  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
                     30:  * To learn more about Internet Systems Consortium, see
                     31:  * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
                     32:  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
                     33:  * ``http://www.nominum.com''.
                     34:  */
                     35: 
                     36: #include "dhcpd.h"
                     37: #include <omapip/omapip_p.h>
                     38: #include <ctype.h>
                     39: #include <sys/wait.h>
                     40: 
                     41: #ifdef HAVE_REGEX_H
                     42: # include <regex.h>
                     43: #endif
                     44: 
                     45: struct binding_scope *global_scope;
                     46: 
                     47: static int do_host_lookup (struct data_string *,
                     48:                           struct dns_host_entry *);
                     49: 
                     50: #ifdef NSUPDATE
                     51: struct __res_state resolver_state;
                     52: int resolver_inited = 0;
                     53: #endif
                     54: 
                     55: #define DS_SPRINTF_SIZE 128
                     56: 
                     57: /* 
                     58:  * If we are using a data_string structure to hold a NUL-terminated 
                     59:  * ASCII string, this function can be used to append a printf-formatted 
                     60:  * string to the end of it. The data_string structure will be resized to
                     61:  * be big enough to hold the new string.
                     62:  *
                     63:  * If the append works, then 1 is returned.
                     64:  *
                     65:  * If it is not possible to allocate a buffer big enough to hold the 
                     66:  * new value, then the old data_string is unchanged, and 0 is returned.
                     67:  */
                     68: int
                     69: data_string_sprintfa(struct data_string *ds, const char *fmt, ...) {
                     70:        va_list args;
                     71:        int cur_strlen;
                     72:        int max;
                     73:        int vsnprintf_ret;
                     74:        int new_len;
                     75:        struct buffer *tmp_buffer;
                     76: 
                     77:        /*
                     78:         * If the data_string is empty, then initialize it.
                     79:         */
                     80:        if (ds->data == NULL) {
                     81:                /* INSIST(ds.buffer == NULL); */
                     82:                if (!buffer_allocate(&ds->buffer, DS_SPRINTF_SIZE, MDL)) {
                     83:                        return 0;
                     84:                }
                     85:                ds->data = ds->buffer->data;
                     86:                ds->len = DS_SPRINTF_SIZE;
                     87:                *((char *)ds->data) = '\0';
                     88:        }
                     89: 
                     90:        /*
                     91:         * Get the length of the string, and figure out how much space
                     92:         * is left.
                     93:         */
                     94:        cur_strlen = strlen((char *)ds->data);
                     95:        max = ds->len - cur_strlen;
                     96: 
                     97:        /* 
                     98:         * Use vsnprintf(), which won't write past our space, but will
                     99:         * tell us how much space it wants.
                    100:         */
                    101:        va_start(args, fmt);
                    102:        vsnprintf_ret = vsnprintf((char *)ds->data+cur_strlen, max, fmt, args);
                    103:        va_end(args);
                    104:        /* INSIST(vsnprintf_ret >= 0); */
                    105: 
                    106:        /*
                    107:         * If our buffer is not big enough, we need a new buffer.
                    108:         */
                    109:        if (vsnprintf_ret >= max) {
                    110:                /* 
                    111:                 * Figure out a size big enough.
                    112:                 */
                    113:                new_len = ds->len * 2;
                    114:                while (new_len <= cur_strlen + vsnprintf_ret) {
                    115:                        new_len *= 2;
                    116:                }
                    117: 
                    118:                /* 
                    119:                 * Create a new buffer and fill it.
                    120:                 */
                    121:                tmp_buffer = NULL;
                    122:                if (!buffer_allocate(&tmp_buffer, new_len, MDL)) {
                    123:                        /* 
                    124:                         * If we can't create a big enough buffer, 
                    125:                         * we should remove any truncated output that we had.
                    126:                         */
                    127:                        *((char *)ds->data+cur_strlen) = '\0';
                    128:                        va_end(args);
                    129:                        return 0;
                    130:                }
                    131:                memcpy(tmp_buffer->data, ds->data, cur_strlen);
                    132: 
                    133:                /* Rerun the vsprintf. */
                    134:                va_start(args, fmt);
                    135:                vsprintf((char *)tmp_buffer->data + cur_strlen, fmt, args);
                    136:                va_end(args);
                    137: 
                    138:                /*
                    139:                 * Replace our old buffer with the new buffer.
                    140:                 */
                    141:                buffer_dereference(&ds->buffer, MDL);
                    142:                buffer_reference(&ds->buffer, tmp_buffer, MDL);
                    143:                buffer_dereference(&tmp_buffer, MDL);
                    144:                ds->data = ds->buffer->data;
                    145:                ds->len = new_len;
                    146:        }
                    147:        return 1;
                    148: }
                    149: 
                    150: pair cons (car, cdr)
                    151:        caddr_t car;
                    152:        pair cdr;
                    153: {
                    154:        pair foo = (pair)dmalloc (sizeof *foo, MDL);
                    155:        if (!foo)
                    156:                log_fatal ("no memory for cons.");
                    157:        foo -> car = car;
                    158:        foo -> cdr = cdr;
                    159:        return foo;
                    160: }
                    161: 
                    162: int make_const_option_cache (oc, buffer, data, len, option, file, line)
                    163:        struct option_cache **oc;
                    164:        struct buffer **buffer;
                    165:        u_int8_t *data;
                    166:        unsigned len;
                    167:        struct option *option;
                    168:        const char *file;
                    169:        int line;
                    170: {
                    171:        struct buffer *bp;
                    172: 
                    173:        if (buffer) {
                    174:                bp = *buffer;
                    175:                *buffer = 0;
                    176:        } else {
                    177:                bp = (struct buffer *)0;
                    178:                if (!buffer_allocate (&bp, len, file, line)) {
                    179:                        log_error ("%s(%d): can't allocate buffer.",
                    180:                                   file, line);
                    181:                        return 0;
                    182:                }
                    183:        }
                    184: 
                    185:        if (!option_cache_allocate (oc, file, line)) {
                    186:                log_error ("%s(%d): can't allocate option cache.", file, line);
                    187:                buffer_dereference (&bp, file, line);
                    188:                return 0;
                    189:        }
                    190: 
                    191:        (*oc) -> data.len = len;
                    192:        (*oc) -> data.buffer = bp;
                    193:        (*oc) -> data.data = &bp -> data [0];
                    194:        (*oc) -> data.terminated = 0;
                    195:        if (data)
                    196:                memcpy (&bp -> data [0], data, len);
                    197:        option_reference(&((*oc)->option), option, MDL);
                    198:        return 1;
                    199: }
                    200: 
                    201: int make_host_lookup (expr, name)
                    202:        struct expression **expr;
                    203:        const char *name;
                    204: {
                    205:        if (!expression_allocate (expr, MDL)) {
                    206:                log_error ("No memory for host lookup tree node.");
                    207:                return 0;
                    208:        }
                    209:        (*expr) -> op = expr_host_lookup;
                    210:        if (!enter_dns_host (&((*expr) -> data.host_lookup), name)) {
                    211:                expression_dereference (expr, MDL);
                    212:                return 0;
                    213:        }
                    214:        return 1;
                    215: }
                    216: 
                    217: int enter_dns_host (dh, name)
                    218:        struct dns_host_entry **dh;
                    219:        const char *name;
                    220: {
                    221:        /* XXX This should really keep a hash table of hostnames
                    222:           XXX and just add a new reference to a hostname that
                    223:           XXX already exists, if possible, rather than creating
                    224:           XXX a new structure. */
                    225:        if (!dns_host_entry_allocate (dh, name, MDL)) {
                    226:                log_error ("Can't allocate space for new host.");
                    227:                return 0;
                    228:        }
                    229:        return 1;
                    230: }
                    231: 
                    232: int make_const_data (struct expression **expr, const unsigned char *data,
                    233:                     unsigned len, int terminated, int allocate,
                    234:                     const char *file, int line)
                    235: {
                    236:        struct expression *nt;
                    237: 
                    238:        if (!expression_allocate (expr, file, line)) {
                    239:                log_error ("No memory for make_const_data tree node.");
                    240:                return 0;
                    241:        }
                    242:        nt = *expr;
                    243: 
                    244:        if (len) {
                    245:                if (allocate) {
                    246:                        if (!buffer_allocate (&nt -> data.const_data.buffer,
                    247:                                              len + terminated, file, line)) {
                    248:                                log_error ("Can't allocate const_data buffer");
                    249:                                expression_dereference (expr, file, line);
                    250:                                return 0;
                    251:                        }
                    252:                        nt -> data.const_data.data =
                    253:                                &nt -> data.const_data.buffer -> data [0];
                    254:                        memcpy (nt -> data.const_data.buffer -> data,
                    255:                                data, len + terminated);
                    256:                } else 
                    257:                        nt -> data.const_data.data = data;
                    258:                nt -> data.const_data.terminated = terminated;
                    259:        } else
                    260:                nt -> data.const_data.data = 0;
                    261: 
                    262:        nt -> op = expr_const_data;
                    263:        nt -> data.const_data.len = len;
                    264:        return 1;
                    265: }
                    266: 
                    267: int make_const_int (expr, val)
                    268:        struct expression **expr;
                    269:        unsigned long val;
                    270: {
                    271:        if (!expression_allocate (expr, MDL)) {
                    272:                log_error ("No memory for make_const_int tree node.");
                    273:                return 0;
                    274:        }
                    275: 
                    276:        (*expr) -> op = expr_const_int;
                    277:        (*expr) -> data.const_int = val;
                    278:        return 1;
                    279: }
                    280: 
                    281: int make_concat (expr, left, right)
                    282:        struct expression **expr;
                    283:        struct expression *left, *right;
                    284: {
                    285:        /* If we're concatenating a null tree to a non-null tree, just
                    286:           return the non-null tree; if both trees are null, return
                    287:           a null tree. */
                    288:        if (!left) {
                    289:                if (!right)
                    290:                        return 0;
                    291:                expression_reference (expr, right, MDL);
                    292:                return 1;
                    293:        }
                    294:        if (!right) {
                    295:                expression_reference (expr, left, MDL);
                    296:                return 1;
                    297:        }
                    298:                        
                    299:        /* Otherwise, allocate a new node to concatenate the two. */
                    300:        if (!expression_allocate (expr, MDL)) {
                    301:                log_error ("No memory for concatenation expression node.");
                    302:                return 0;
                    303:        }
                    304:                
                    305:        (*expr) -> op = expr_concat;
                    306:        expression_reference (&(*expr) -> data.concat [0], left, MDL);
                    307:        expression_reference (&(*expr) -> data.concat [1], right, MDL);
                    308:        return 1;
                    309: }
                    310: 
                    311: int make_encapsulation (expr, name)
                    312:        struct expression **expr;
                    313:        struct data_string *name;
                    314: {
                    315:        /* Allocate a new node to store the encapsulation. */
                    316:        if (!expression_allocate (expr, MDL)) {
                    317:                log_error ("No memory for encapsulation expression node.");
                    318:                return 0;
                    319:        }
                    320:                
                    321:        (*expr) -> op = expr_encapsulate;
                    322:        data_string_copy (&(*expr) -> data.encapsulate, name, MDL);
                    323:        return 1;
                    324: }
                    325: 
                    326: int make_substring (new, expr, offset, length)
                    327:        struct expression **new;
                    328:        struct expression *expr;
                    329:        struct expression *offset;
                    330:        struct expression *length;
                    331: {
                    332:        /* Allocate an expression node to compute the substring. */
                    333:        if (!expression_allocate (new, MDL)) {
                    334:                log_error ("no memory for substring expression.");
                    335:                return 0;
                    336:        }
                    337:        (*new) -> op = expr_substring;
                    338:        expression_reference (&(*new) -> data.substring.expr, expr, MDL);
                    339:        expression_reference (&(*new) -> data.substring.offset, offset, MDL);
                    340:        expression_reference (&(*new) -> data.substring.len, length, MDL);
                    341:        return 1;
                    342: }
                    343: 
                    344: int make_limit (new, expr, limit)
                    345:        struct expression **new;
                    346:        struct expression *expr;
                    347:        int limit;
                    348: {
                    349:        /* Allocate a node to enforce a limit on evaluation. */
                    350:        if (!expression_allocate (new, MDL))
                    351:                log_error ("no memory for limit expression");
                    352:        (*new) -> op = expr_substring;
                    353:        expression_reference (&(*new) -> data.substring.expr, expr, MDL);
                    354: 
                    355:        /* Offset is a constant 0. */
                    356:        if (!expression_allocate (&(*new) -> data.substring.offset, MDL)) {
                    357:                log_error ("no memory for limit offset expression");
                    358:                expression_dereference (new, MDL);
                    359:                return 0;
                    360:        }
                    361:        (*new) -> data.substring.offset -> op = expr_const_int;
                    362:        (*new) -> data.substring.offset -> data.const_int = 0;
                    363: 
                    364:        /* Length is a constant: the specified limit. */
                    365:        if (!expression_allocate (&(*new) -> data.substring.len, MDL)) {
                    366:                log_error ("no memory for limit length expression");
                    367:                expression_dereference (new, MDL);
                    368:                return 0;
                    369:        }
                    370:        (*new) -> data.substring.len -> op = expr_const_int;
                    371:        (*new) -> data.substring.len -> data.const_int = limit;
                    372: 
                    373:        return 1;
                    374: }
                    375: 
                    376: int option_cache (struct option_cache **oc, struct data_string *dp,
                    377:                  struct expression *expr, struct option *option,
                    378:                  const char *file, int line)
                    379: {
                    380:        if (!option_cache_allocate (oc, file, line))
                    381:                return 0;
                    382:        if (dp)
                    383:                data_string_copy (&(*oc) -> data, dp, file, line);
                    384:        if (expr)
                    385:                expression_reference (&(*oc) -> expression, expr, file, line);
                    386:        option_reference(&(*oc)->option, option, MDL);
                    387:        return 1;
                    388: }
                    389: 
                    390: int make_let (result, name)
                    391:        struct executable_statement **result;
                    392:        const char *name;
                    393: {
                    394:        if (!(executable_statement_allocate (result, MDL)))
                    395:                return 0;
                    396:        
                    397:        (*result) -> op = let_statement;
                    398:        (*result) -> data.let.name = dmalloc (strlen (name) + 1, MDL);
                    399:        if (!(*result) -> data.let.name) {
                    400:                executable_statement_dereference (result, MDL);
                    401:                return 0;
                    402:        }
                    403:        strcpy ((*result) -> data.let.name, name);
                    404:        return 1;
                    405: }
                    406:                
                    407: static int do_host_lookup (result, dns)
                    408:        struct data_string *result;
                    409:        struct dns_host_entry *dns;
                    410: {
                    411:        struct hostent *h;
                    412:        unsigned i, count;
                    413:        unsigned new_len;
                    414: 
                    415: #ifdef DEBUG_EVAL
                    416:        log_debug ("time: now = %d  dns = %d  diff = %d",
                    417:               cur_time, dns -> timeout, cur_time - dns -> timeout);
                    418: #endif
                    419: 
                    420:        /* If the record hasn't timed out, just copy the data and return. */
                    421:        if (cur_time <= dns -> timeout) {
                    422: #ifdef DEBUG_EVAL
                    423:                log_debug ("easy copy: %d %s",
                    424:                       dns -> data.len,
                    425:                       (dns -> data.len > 4
                    426:                        ? inet_ntoa (*(struct in_addr *)(dns -> data.data))
                    427:                        : 0));
                    428: #endif
                    429:                data_string_copy (result, &dns -> data, MDL);
                    430:                return 1;
                    431:        }
                    432: #ifdef DEBUG_EVAL
                    433:        log_debug ("Looking up %s", dns -> hostname);
                    434: #endif
                    435: 
                    436:        /* Otherwise, look it up... */
                    437:        h = gethostbyname (dns -> hostname);
                    438:        if (!h) {
                    439: #ifndef NO_H_ERRNO
                    440:                switch (h_errno) {
                    441:                      case HOST_NOT_FOUND:
                    442: #endif
                    443:                        log_error ("%s: host unknown.", dns -> hostname);
                    444: #ifndef NO_H_ERRNO
                    445:                        break;
                    446:                      case TRY_AGAIN:
                    447:                        log_error ("%s: temporary name server failure",
                    448:                                   dns -> hostname);
                    449:                        break;
                    450:                      case NO_RECOVERY:
                    451:                        log_error ("%s: name server failed", dns -> hostname);
                    452:                        break;
                    453:                      case NO_DATA:
                    454:                        log_error ("%s: no A record associated with address",
                    455:                                   dns -> hostname);
                    456:                }
                    457: #endif /* !NO_H_ERRNO */
                    458: 
                    459:                /* Okay to try again after a minute. */
                    460:                dns -> timeout = cur_time + 60;
                    461:                data_string_forget (&dns -> data, MDL);
                    462:                return 0;
                    463:        }
                    464: 
                    465: #ifdef DEBUG_EVAL
                    466:        log_debug ("Lookup succeeded; first address is %s",
                    467:               inet_ntoa (h -> h_addr_list [0]));
                    468: #endif
                    469: 
                    470:        /* Count the number of addresses we got... */
                    471:        for (count = 0; h -> h_addr_list [count]; count++)
                    472:                ;
                    473:        
                    474:        /* Dereference the old data, if any. */
                    475:        data_string_forget (&dns -> data, MDL);
                    476: 
                    477:        /* Do we need to allocate more memory? */
                    478:        new_len = count * h -> h_length;
                    479:        if (!buffer_allocate (&dns -> data.buffer, new_len, MDL))
                    480:        {
                    481:                log_error ("No memory for %s.", dns -> hostname);
                    482:                return 0;
                    483:        }
                    484: 
                    485:        dns -> data.data = &dns -> data.buffer -> data [0];
                    486:        dns -> data.len = new_len;
                    487:        dns -> data.terminated = 0;
                    488: 
                    489:        /* Addresses are conveniently stored one to the buffer, so we
                    490:           have to copy them out one at a time... :'( */
                    491:        for (i = 0; i < count; i++) {
                    492:                memcpy (&dns -> data.buffer -> data [h -> h_length * i],
                    493:                        h -> h_addr_list [i], (unsigned)(h -> h_length));
                    494:        }
                    495: #ifdef DEBUG_EVAL
                    496:        log_debug ("dns -> data: %x  h -> h_addr_list [0]: %x",
                    497:                   *(int *)(dns -> buffer), h -> h_addr_list [0]);
                    498: #endif
                    499: 
                    500:        /* XXX Set the timeout for an hour from now.
                    501:           XXX This should really use the time on the DNS reply. */
                    502:        dns -> timeout = cur_time + 3600;
                    503: 
                    504: #ifdef DEBUG_EVAL
                    505:        log_debug ("hard copy: %d %s", dns -> data.len,
                    506:               (dns -> data.len > 4
                    507:                ? inet_ntoa (*(struct in_addr *)(dns -> data.data)) : 0));
                    508: #endif
                    509:        data_string_copy (result, &dns -> data, MDL);
                    510:        return 1;
                    511: }
                    512: 
                    513: int evaluate_expression (result, packet, lease, client_state,
                    514:                         in_options, cfg_options, scope, expr, file, line)
                    515:        struct binding_value **result;
                    516:        struct packet *packet;
                    517:        struct lease *lease;
                    518:        struct client_state *client_state;
                    519:        struct option_state *in_options;
                    520:        struct option_state *cfg_options;
                    521:        struct binding_scope **scope;
                    522:        struct expression *expr;
                    523:        const char *file;
                    524:        int line;
                    525: {
                    526:        struct binding_value *bv;
                    527:        int status;
                    528:        struct binding *binding;
                    529: 
                    530:        bv = (struct binding_value *)0;
                    531: 
                    532:        if (expr -> op == expr_variable_reference) {
                    533:                if (!scope || !*scope)
                    534:                        return 0;
                    535: 
                    536:                binding = find_binding (*scope, expr -> data.variable);
                    537: 
                    538:                if (binding && binding -> value) {
                    539:                        if (result)
                    540:                                binding_value_reference (result,
                    541:                                                         binding -> value,
                    542:                                                         file, line);
                    543:                        return 1;
                    544:                } else
                    545:                        return 0;
                    546:        } else if (expr -> op == expr_funcall) {
                    547:                struct string_list *s;
                    548:                struct expression *arg;
                    549:                struct binding_scope *ns;
                    550:                struct binding *nb;
                    551: 
                    552:                if (!scope || !*scope) {
                    553:                        log_error ("%s: no such function.",
                    554:                                   expr -> data.funcall.name);
                    555:                        return 0;
                    556:                }
                    557: 
                    558:                binding = find_binding (*scope, expr -> data.funcall.name);
                    559: 
                    560:                if (!binding || !binding -> value) {
                    561:                        log_error ("%s: no such function.",
                    562:                                   expr -> data.funcall.name);
                    563:                        return 0;
                    564:                }
                    565:                if (binding -> value -> type != binding_function) {
                    566:                        log_error ("%s: not a function.",
                    567:                                   expr -> data.funcall.name);
                    568:                        return 0;
                    569:                }
                    570: 
                    571:                /* Create a new binding scope in which to define
                    572:                   the arguments to the function. */
                    573:                ns = (struct binding_scope *)0;
                    574:                if (!binding_scope_allocate (&ns, MDL)) {
                    575:                        log_error ("%s: can't allocate argument scope.",
                    576:                                   expr -> data.funcall.name);
                    577:                        return 0;
                    578:                }
                    579: 
                    580:                arg = expr -> data.funcall.arglist;
                    581:                s = binding -> value -> value.fundef -> args;
                    582:                while (arg && s) {
                    583:                        nb = dmalloc (sizeof *nb, MDL);
                    584:                        if (!nb) {
                    585:                              blb:
                    586:                                binding_scope_dereference (&ns, MDL);
                    587:                                return 0;
                    588:                        } else {
                    589:                                memset (nb, 0, sizeof *nb);
                    590:                                nb -> name = dmalloc (strlen (s -> string) + 1,
                    591:                                                      MDL);
                    592:                                if (nb -> name)
                    593:                                        strcpy (nb -> name, s -> string);
                    594:                                else {
                    595:                                        dfree (nb, MDL);
                    596:                                        nb = (struct binding *)0;
                    597:                                        goto blb;
                    598:                                }
                    599:                        }
                    600:                        evaluate_expression (&nb -> value, packet, lease,
                    601:                                             client_state,
                    602:                                             in_options, cfg_options, scope,
                    603:                                             arg -> data.arg.val, file, line);
                    604:                        nb -> next = ns -> bindings;
                    605:                        ns -> bindings = nb;
                    606:                        arg = arg -> data.arg.next;
                    607:                        s = s -> next;
                    608:                }
                    609:                if (arg) {
                    610:                        log_error ("%s: too many arguments.",
                    611:                                   expr -> data.funcall.name);
                    612:                        binding_scope_dereference (&ns, MDL);
                    613:                        return 0;
                    614:                }
                    615:                if (s) {
                    616:                        log_error ("%s: too few arguments.",
                    617:                                   expr -> data.funcall.name);
                    618:                        binding_scope_dereference (&ns, MDL);
                    619:                        return 0;
                    620:                }
                    621: 
                    622:                if (scope && *scope)
                    623:                        binding_scope_reference (&ns -> outer, *scope, MDL);
                    624: 
                    625:                status = (execute_statements
                    626:                          (&bv, packet,
                    627:                           lease, client_state, in_options, cfg_options, &ns,
                    628:                           binding -> value -> value.fundef -> statements));
                    629:                binding_scope_dereference (&ns, MDL);
                    630: 
                    631:                if (!bv)
                    632:                        return 1;
                    633:         } else if (is_boolean_expression (expr)) {
                    634:                if (!binding_value_allocate (&bv, MDL))
                    635:                        return 0;
                    636:                bv -> type = binding_boolean;
                    637:                status = (evaluate_boolean_expression
                    638:                          (&bv -> value.boolean, packet, lease, client_state,
                    639:                           in_options, cfg_options, scope, expr));
                    640:        } else if (is_numeric_expression (expr)) {
                    641:                if (!binding_value_allocate (&bv, MDL))
                    642:                        return 0;
                    643:                bv -> type = binding_numeric;
                    644:                status = (evaluate_numeric_expression
                    645:                          (&bv -> value.intval, packet, lease, client_state,
                    646:                           in_options, cfg_options, scope, expr));
                    647:        } else if (is_data_expression  (expr)) {
                    648:                if (!binding_value_allocate (&bv, MDL))
                    649:                        return 0;
                    650:                bv -> type = binding_data;
                    651:                status = (evaluate_data_expression
                    652:                          (&bv -> value.data, packet, lease, client_state,
                    653:                           in_options, cfg_options, scope, expr, MDL));
                    654:        } else if (is_dns_expression (expr)) {
                    655: #if defined (NSUPDATE)
                    656:                if (!binding_value_allocate (&bv, MDL))
                    657:                        return 0;
                    658:                bv -> type = binding_dns;
                    659:                status = (evaluate_dns_expression
                    660:                          (&bv -> value.dns, packet, lease, client_state,
                    661:                           in_options, cfg_options, scope, expr));
                    662: #endif
                    663:        } else {
                    664:                log_error ("%s: invalid expression type: %d",
                    665:                           "evaluate_expression", expr -> op);
                    666:                return 0;
                    667:        }
                    668:        if (result && status)
                    669:                binding_value_reference (result, bv, file, line);
                    670:        binding_value_dereference (&bv, MDL);
                    671: 
                    672:        return status;
                    673: }
                    674: 
                    675: int binding_value_dereference (struct binding_value **v,
                    676:                               const char *file, int line)
                    677: {
                    678:        struct binding_value *bv = *v;
                    679: 
                    680:        *v = (struct binding_value *)0;
                    681: 
                    682:        /* Decrement the reference count.   If it's nonzero, we're
                    683:           done. */
                    684:        --(bv -> refcnt);
                    685:        rc_register (file, line, v, bv, bv -> refcnt, 1, RC_MISC);
                    686:        if (bv -> refcnt > 0)
                    687:                return 1;
                    688:        if (bv -> refcnt < 0) {
                    689:                log_error ("%s(%d): negative refcnt!", file, line);
                    690: #if defined (DEBUG_RC_HISTORY)
                    691:                dump_rc_history (bv);
                    692: #endif
                    693: #if defined (POINTER_DEBUG)
                    694:                abort ();
                    695: #else
                    696:                return 0;
                    697: #endif
                    698:        }
                    699: 
                    700:        switch (bv -> type) {
                    701:              case binding_boolean:
                    702:              case binding_numeric:
                    703:                break;
                    704:              case binding_data:
                    705:                if (bv -> value.data.buffer)
                    706:                        data_string_forget (&bv -> value.data, file, line);
                    707:                break;
                    708:              case binding_dns:
                    709: #if defined (NSUPDATE)
                    710:                if (bv -> value.dns) {
                    711:                        if (bv -> value.dns -> r_data) {
                    712:                                dfree (bv -> value.dns -> r_data_ephem, MDL);
                    713:                                bv -> value.dns -> r_data = (unsigned char *)0;
                    714:                                bv -> value.dns -> r_data_ephem =
                    715:                                        (unsigned char *)0;
                    716:                        }
                    717:                        minires_freeupdrec (bv -> value.dns);
                    718:                }
                    719:                break;
                    720: #endif
                    721:              default:
                    722:                log_error ("%s(%d): invalid binding type: %d",
                    723:                           file, line, bv -> type);
                    724:                return 0;
                    725:        }
                    726:        free_binding_value(bv, file, line);
                    727:        return 1;
                    728: }
                    729: 
                    730: #if defined (NSUPDATE)
                    731: int evaluate_dns_expression (result, packet, lease, client_state, in_options,
                    732:                             cfg_options, scope, expr)
                    733:        ns_updrec **result;
                    734:        struct packet *packet;
                    735:        struct lease *lease;
                    736:        struct client_state *client_state;
                    737:        struct option_state *in_options;
                    738:        struct option_state *cfg_options;
                    739:        struct binding_scope **scope;
                    740:        struct expression *expr;
                    741: {
                    742:        unsigned long ttl = 0;
                    743:        char *tname;
                    744:        struct data_string name, data;
                    745:        int r0, r1, r2;
                    746: 
                    747:        if (!result || *result) {
                    748:                log_error ("evaluate_dns_expression called with non-null %s",
                    749:                           "result pointer");
                    750: #if defined (POINTER_DEBUG)
                    751:                abort ();
                    752: #else
                    753:                return 0;
                    754: #endif
                    755:        }
                    756:                
                    757:        switch (expr -> op) {
                    758: #if defined (NSUPDATE)
                    759:              case expr_ns_add:
                    760:                r0 = evaluate_numeric_expression (&ttl, packet, lease,
                    761:                                                  client_state,
                    762:                                                  in_options, cfg_options,
                    763:                                                  scope,
                    764:                                                  expr -> data.ns_add.ttl);
                    765:                goto nsfinish;
                    766: 
                    767:              case expr_ns_exists:
                    768:                ttl = 1;
                    769: 
                    770:              case expr_ns_delete:
                    771:              case expr_ns_not_exists:
                    772:                r0 = 1;
                    773:              nsfinish:
                    774:                memset (&name, 0, sizeof name);
                    775:                r1 = evaluate_data_expression (&name, packet, lease,
                    776:                                               client_state,
                    777:                                               in_options, cfg_options, scope,
                    778:                                               expr -> data.ns_add.rrname,
                    779:                                               MDL);
                    780:                if (r1) {
                    781:                        /* The result of the evaluation may or may not
                    782:                           be NUL-terminated, but we need it
                    783:                           terminated for sure, so we have to allocate
                    784:                           a buffer and terminate it. */
                    785:                        tname = dmalloc (name.len + 1, MDL);
                    786:                        if (!tname) {
                    787:                                r2 = 0;
                    788:                                r1 = 0;
                    789:                                data_string_forget (&name, MDL);
                    790:                        } else {
                    791:                                memcpy (tname, name.data, name.len);
                    792:                                tname [name.len] = 0;
                    793:                                memset (&data, 0, sizeof data);
                    794:                                r2 = evaluate_data_expression
                    795:                                        (&data, packet, lease, client_state,
                    796:                                         in_options, cfg_options, scope,
                    797:                                         expr -> data.ns_add.rrdata, MDL);
                    798:                        }
                    799:                } else {
                    800:                        r2 = 0;
                    801:                        tname = NULL;
                    802:                }
                    803:                if (r0 && r1 && (r2 || expr -> op != expr_ns_add)) {
                    804:                    *result = minires_mkupdrec (((expr -> op == expr_ns_add ||
                    805:                                                  expr -> op == expr_ns_delete)
                    806:                                                 ? S_UPDATE : S_PREREQ),
                    807:                                                tname,
                    808:                                                expr -> data.ns_add.rrclass,
                    809:                                                expr -> data.ns_add.rrtype,
                    810:                                                ttl);
                    811:                    if (!*result) {
                    812:                          ngood:
                    813:                            if (r2) {
                    814:                                data_string_forget (&data, MDL);
                    815:                                r2 = 0;
                    816:                            }
                    817:                    } else {
                    818:                        if (data.len) {
                    819:                                /* As a special case, if we get exactly
                    820:                                   four bytes of data, it's an IP address
                    821:                                   represented as a 32-bit quantity, which
                    822:                                   is actually what we *should* be getting
                    823:                                   here.   Because res_mkupdrec is currently
                    824:                                   broken and expects a dotted quad, convert
                    825:                                   it.   This should be fixed when the new
                    826:                                   resolver is merged. */
                    827:                                if (data.len == 4) {
                    828:                                    (*result) -> r_data_ephem =
                    829:                                            dmalloc (16, MDL);
                    830:                                    if (!(*result) -> r_data_ephem)
                    831:                                        goto dpngood;
                    832:                                    (*result) -> r_data =
                    833:                                            (*result) -> r_data_ephem;
                    834:                                    /*%Audit% 16 bytes max. %2004.06.17,Safe%*/
                    835:                                    sprintf ((char *)(*result) -> r_data_ephem,
                    836:                                             "%u.%u.%u.%u",
                    837:                                             data.data [0] & 0xff,
                    838:                                             data.data [1] & 0xff,
                    839:                                             data.data [2] & 0xff,
                    840:                                             data.data [3] & 0xff);
                    841:                                    (*result) -> r_size = 
                    842:                                            strlen ((const char *)
                    843:                                                    (*result) -> r_data);
                    844:                                } else {
                    845:                                    (*result) -> r_size = data.len;
                    846:                                    (*result) -> r_data_ephem =
                    847:                                            dmalloc (data.len, MDL);
                    848:                                    if (!(*result) -> r_data_ephem) {
                    849:                                      dpngood: /* double plus ungood. */
                    850:                                        minires_freeupdrec (*result);
                    851:                                        *result = 0;
                    852:                                        goto ngood;
                    853:                                    }
                    854:                                    (*result) -> r_data =
                    855:                                            (*result) -> r_data_ephem;
                    856:                                    memcpy ((*result) -> r_data_ephem,
                    857:                                            data.data, data.len);
                    858:                                }
                    859:                        } else {
                    860:                                (*result) -> r_data = 0;
                    861:                                (*result) -> r_size = 0;
                    862:                        }
                    863:                        switch (expr -> op) {
                    864:                              case expr_ns_add:
                    865:                                (*result) -> r_opcode = ADD;
                    866:                                break;
                    867:                              case expr_ns_delete:
                    868:                                (*result) -> r_opcode = DELETE;
                    869:                                break;
                    870:                              case expr_ns_exists:
                    871:                                (*result) -> r_opcode = YXRRSET;
                    872:                                break;
                    873:                              case expr_ns_not_exists:
                    874:                                (*result) -> r_opcode = NXRRSET;
                    875:                                break;
                    876: 
                    877:                                /* Can't happen, but satisfy gcc. */
                    878:                              default:
                    879:                                break;
                    880:                        }
                    881:                    }
                    882:                }
                    883:                if (r1) {
                    884:                        data_string_forget (&name, MDL);
                    885:                        dfree (tname, MDL);
                    886:                }
                    887:                if (r2)
                    888:                        data_string_forget (&data, MDL);
                    889:                /* One flaw in the thinking here: an IP address and an
                    890:                   ASCII string both look like data expressions, but
                    891:                   for A records, we want an ASCII string, not a
                    892:                   binary IP address.  Do I need to turn binary IP
                    893:                   addresses into a separate type?  */
                    894:                return (r0 && r1 &&
                    895:                        (r2 || expr -> op != expr_ns_add) && *result);
                    896: 
                    897: #else
                    898:              case expr_ns_add:
                    899:              case expr_ns_delete:
                    900:              case expr_ns_exists:
                    901:              case expr_ns_not_exists:
                    902:                return 0;
                    903: #endif
                    904:              case expr_funcall:
                    905:                log_error ("%s: dns values for functions not supported.",
                    906:                           expr -> data.funcall.name);
                    907:                break;
                    908: 
                    909:              case expr_variable_reference:
                    910:                log_error ("%s: dns values for variables not supported.",
                    911:                           expr -> data.variable);
                    912:                break;
                    913: 
                    914:              case expr_check:
                    915:              case expr_equal:
                    916:              case expr_not_equal:
                    917:              case expr_regex_match:
                    918:              case expr_iregex_match:
                    919:              case expr_and:
                    920:              case expr_or:
                    921:              case expr_not:
                    922:              case expr_match:
                    923:              case expr_static:
                    924:              case expr_known:
                    925:              case expr_exists:
                    926:              case expr_variable_exists:
                    927:                log_error ("Boolean opcode in evaluate_dns_expression: %d",
                    928:                      expr -> op);
                    929:                return 0;
                    930: 
                    931:              case expr_none:
                    932:              case expr_substring:
                    933:              case expr_suffix:
                    934:              case expr_lcase:
                    935:              case expr_ucase:
                    936:              case expr_option:
                    937:              case expr_hardware:
                    938:              case expr_const_data:
                    939:              case expr_packet:
                    940:              case expr_concat:
                    941:              case expr_encapsulate:
                    942:              case expr_host_lookup:
                    943:              case expr_encode_int8:
                    944:              case expr_encode_int16:
                    945:              case expr_encode_int32:
                    946:              case expr_binary_to_ascii:
                    947:              case expr_reverse:
                    948:              case expr_filename:
                    949:              case expr_sname:
                    950:              case expr_pick_first_value:
                    951:              case expr_host_decl_name:
                    952:              case expr_config_option:
                    953:              case expr_leased_address:
                    954:              case expr_null:
                    955:                log_error ("Data opcode in evaluate_dns_expression: %d",
                    956:                      expr -> op);
                    957:                return 0;
                    958: 
                    959:              case expr_extract_int8:
                    960:              case expr_extract_int16:
                    961:              case expr_extract_int32:
                    962:              case expr_const_int:
                    963:              case expr_lease_time:
                    964:              case expr_dns_transaction:
                    965:              case expr_add:
                    966:              case expr_subtract:
                    967:              case expr_multiply:
                    968:              case expr_divide:
                    969:              case expr_remainder:
                    970:              case expr_binary_and:
                    971:              case expr_binary_or:
                    972:              case expr_binary_xor:
                    973:              case expr_client_state:
                    974:                log_error ("Numeric opcode in evaluate_dns_expression: %d",
                    975:                      expr -> op);
                    976:                return 0;
                    977: 
                    978:              case expr_function:
                    979:                log_error ("Function opcode in evaluate_dns_expression: %d",
                    980:                      expr -> op);
                    981:                return 0;
                    982: 
                    983:              case expr_arg:
                    984:                break;
                    985:        }
                    986: 
                    987:        log_error ("Bogus opcode in evaluate_dns_expression: %d",
                    988:                   expr -> op);
                    989:        return 0;
                    990: }
                    991: #endif /* defined (NSUPDATE) */
                    992: 
                    993: int evaluate_boolean_expression (result, packet, lease, client_state,
                    994:                                 in_options, cfg_options, scope, expr)
                    995:        int *result;
                    996:        struct packet *packet;
                    997:        struct lease *lease;
                    998:        struct client_state *client_state;
                    999:        struct option_state *in_options;
                   1000:        struct option_state *cfg_options;
                   1001:        struct binding_scope **scope;
                   1002:        struct expression *expr;
                   1003: {
                   1004:        struct data_string left, right;
                   1005:        int bleft, bright;
                   1006:        int sleft, sright;
                   1007:        struct binding *binding;
                   1008:        struct binding_value *bv, *obv;
                   1009: #ifdef HAVE_REGEX_H
                   1010:        int regflags = REG_EXTENDED | REG_NOSUB;
                   1011:        regex_t re;
                   1012: #endif
                   1013: 
                   1014:        switch (expr -> op) {
                   1015:              case expr_check:
                   1016:                *result = check_collection (packet, lease,
                   1017:                                            expr -> data.check);
                   1018: #if defined (DEBUG_EXPRESSIONS)
                   1019:                log_debug ("bool: check (%s) returns %s",
                   1020:                           expr -> data.check -> name,
                   1021:                           *result ? "true" : "false");
                   1022: #endif
                   1023:                return 1;
                   1024: 
                   1025:              case expr_equal:
                   1026:              case expr_not_equal:
                   1027:                bv = obv = (struct binding_value *)0;
                   1028:                sleft = evaluate_expression (&bv, packet, lease, client_state,
                   1029:                                             in_options, cfg_options, scope,
                   1030:                                             expr -> data.equal [0], MDL);
                   1031:                sright = evaluate_expression (&obv, packet, lease,
                   1032:                                              client_state, in_options,
                   1033:                                              cfg_options, scope,
                   1034:                                              expr -> data.equal [1], MDL);
                   1035:                if (sleft && sright) {
                   1036:                    if (bv -> type != obv -> type)
                   1037:                        *result = expr -> op == expr_not_equal;
                   1038:                    else {
                   1039:                        switch (obv -> type) {
                   1040:                          case binding_boolean:
                   1041:                            if (bv -> value.boolean == obv -> value.boolean)
                   1042:                                *result = expr -> op == expr_equal;
                   1043:                            else
                   1044:                                *result = expr -> op == expr_not_equal;
                   1045:                            break;
                   1046: 
                   1047:                          case binding_data:
                   1048:                            if ((bv -> value.data.len ==
                   1049:                                 obv -> value.data.len) &&
                   1050:                                !memcmp (bv -> value.data.data,
                   1051:                                         obv -> value.data.data,
                   1052:                                         obv -> value.data.len))
                   1053:                                *result = expr -> op == expr_equal;
                   1054:                            else
                   1055:                                *result = expr -> op == expr_not_equal;
                   1056:                            break;
                   1057: 
                   1058:                          case binding_numeric:
                   1059:                            if (bv -> value.intval == obv -> value.intval)
                   1060:                                *result = expr -> op == expr_equal;
                   1061:                            else
                   1062:                                *result = expr -> op == expr_not_equal;
                   1063:                            break;
                   1064: 
                   1065:                          case binding_dns:
                   1066: #if defined (NSUPDATE)
                   1067:                            /* XXX This should be a comparison for equal
                   1068:                               XXX values, not for identity. */
                   1069:                            if (bv -> value.dns == obv -> value.dns)
                   1070:                                *result = expr -> op == expr_equal;
                   1071:                            else
                   1072:                                *result = expr -> op == expr_not_equal;
                   1073: #else
                   1074:                                *result = expr -> op == expr_not_equal;
                   1075: #endif
                   1076:                            break;
                   1077: 
                   1078:                          case binding_function:
                   1079:                            if (bv -> value.fundef == obv -> value.fundef)
                   1080:                                *result = expr -> op == expr_equal;
                   1081:                            else
                   1082:                                *result = expr -> op == expr_not_equal;
                   1083:                            break;
                   1084:                          default:
                   1085:                            *result = expr -> op == expr_not_equal;
                   1086:                            break;
                   1087:                        }
                   1088:                    }
                   1089:                } else if (!sleft && !sright)
                   1090:                    *result = expr -> op == expr_equal;
                   1091:                else
                   1092:                    *result = expr -> op == expr_not_equal;
                   1093: 
                   1094: #if defined (DEBUG_EXPRESSIONS)
                   1095:                log_debug ("bool: %sequal = %s",
                   1096:                           expr -> op == expr_not_equal ? "not" : "",
                   1097:                           (*result ? "true" : "false"));
                   1098: #endif
                   1099:                if (sleft)
                   1100:                        binding_value_dereference (&bv, MDL);
                   1101:                if (sright)
                   1102:                        binding_value_dereference (&obv, MDL);
                   1103:                return 1;
                   1104: 
                   1105:              case expr_iregex_match:
                   1106: #ifdef HAVE_REGEX_H
                   1107:                regflags |= REG_ICASE;
                   1108: #endif
                   1109:                /* FALL THROUGH */
                   1110:              case expr_regex_match:
                   1111: #ifdef HAVE_REGEX_H
                   1112:                memset(&left, 0, sizeof left);
                   1113:                bleft = evaluate_data_expression(&left, packet, lease,
                   1114:                                                 client_state,
                   1115:                                                 in_options, cfg_options,
                   1116:                                                 scope,
                   1117:                                                 expr->data.equal[0], MDL);
                   1118:                memset(&right, 0, sizeof right);
                   1119:                bright = evaluate_data_expression(&right, packet, lease,
                   1120:                                                  client_state,
                   1121:                                                  in_options, cfg_options,
                   1122:                                                  scope,
                   1123:                                                  expr->data.equal[1], MDL);
                   1124: 
                   1125:                *result = 0;
                   1126:                memset(&re, 0, sizeof(re));
                   1127:                if (bleft && bright &&
                   1128:                    (left.data != NULL) && (right.data != NULL) &&
                   1129:                    (regcomp(&re, (char *)right.data, regflags) == 0) &&
                   1130:                    (regexec(&re, (char *)left.data, (size_t)0, NULL, 0) == 0))
                   1131:                                *result = 1;
                   1132: 
                   1133: #if defined (DEBUG_EXPRESSIONS)
                   1134:                log_debug("bool: %s ~= %s yields %s",
                   1135:                          bleft ? print_hex_1(left.len, left.data, 20)
                   1136:                                : "NULL",
                   1137:                          bright ? print_hex_2 (right.len, right.data, 20)
                   1138:                                 : "NULL",
                   1139:                          *result ? "true" : "false");
                   1140: #endif
                   1141: 
                   1142:                if (bleft)
                   1143:                        data_string_forget(&left, MDL);
                   1144:                if (bright)
                   1145:                        data_string_forget(&right, MDL);
                   1146: 
                   1147:                regfree(&re);
                   1148: 
                   1149:                /*
                   1150:                 * If we have bleft and bright then we have a good
                   1151:                 * syntax, otherwise not.
                   1152:                 *
                   1153:                 * XXX: we don't warn on invalid regular expression 
                   1154:                 *      syntax, should we?
                   1155:                 */
                   1156:                return bleft && bright;
                   1157: #else
                   1158:                /* It shouldn't be possible to configure a regex operator
                   1159:                 * when there's no support.
                   1160:                 */
                   1161:                log_fatal("Impossible condition at %s:%d.", MDL);
                   1162:                break;
                   1163: #endif
                   1164: 
                   1165:              case expr_and:
                   1166:                sleft = evaluate_boolean_expression (&bleft, packet, lease,
                   1167:                                                     client_state,
                   1168:                                                     in_options, cfg_options,
                   1169:                                                     scope,
                   1170:                                                     expr -> data.and [0]);
                   1171:                if (sleft && bleft)
                   1172:                        sright = evaluate_boolean_expression
                   1173:                                (&bright, packet, lease, client_state,
                   1174:                                 in_options, cfg_options,
                   1175:                                 scope, expr -> data.and [1]);
                   1176:                else
                   1177:                        sright = bright = 0;
                   1178: 
                   1179: #if defined (DEBUG_EXPRESSIONS)
                   1180:                log_debug ("bool: and (%s, %s) = %s",
                   1181:                      sleft ? (bleft ? "true" : "false") : "NULL",
                   1182:                      sright ? (bright ? "true" : "false") : "NULL",
                   1183:                      ((sleft && sright)
                   1184:                       ? (bleft && bright ? "true" : "false") : "NULL"));
                   1185: #endif
                   1186:                if (sleft && sright) {
                   1187:                        *result = bleft && bright;
                   1188:                        return 1;
                   1189:                }
                   1190:                return 0;
                   1191: 
                   1192:              case expr_or:
                   1193:                bleft = bright = 0;
                   1194:                sleft = evaluate_boolean_expression (&bleft, packet, lease,
                   1195:                                                     client_state,
                   1196:                                                     in_options, cfg_options,
                   1197:                                                     scope,
                   1198:                                                     expr -> data.or [0]);
                   1199:                if (!sleft || !bleft)
                   1200:                        sright = evaluate_boolean_expression
                   1201:                                (&bright, packet, lease, client_state,
                   1202:                                 in_options, cfg_options,
                   1203:                                 scope, expr -> data.or [1]);
                   1204:                else
                   1205:                        sright = 0;
                   1206: #if defined (DEBUG_EXPRESSIONS)
                   1207:                log_debug ("bool: or (%s, %s) = %s",
                   1208:                      sleft ? (bleft ? "true" : "false") : "NULL",
                   1209:                      sright ? (bright ? "true" : "false") : "NULL",
                   1210:                      ((sleft || sright)
                   1211:                       ? (bleft || bright ? "true" : "false") : "NULL"));
                   1212: #endif
                   1213:                if (sleft || sright) {
                   1214:                        *result = bleft || bright;
                   1215:                        return 1;
                   1216:                }
                   1217:                return 0;
                   1218: 
                   1219:              case expr_not:
                   1220:                sleft = evaluate_boolean_expression (&bleft, packet, lease,
                   1221:                                                     client_state,
                   1222:                                                     in_options, cfg_options,
                   1223:                                                     scope,
                   1224:                                                     expr -> data.not);
                   1225: #if defined (DEBUG_EXPRESSIONS)
                   1226:                log_debug ("bool: not (%s) = %s",
                   1227:                      sleft ? (bleft ? "true" : "false") : "NULL",
                   1228:                      ((sleft && sright)
                   1229:                       ? (!bleft ? "true" : "false") : "NULL"));
                   1230: 
                   1231: #endif
                   1232:                if (sleft) {
                   1233:                        *result = !bleft;
                   1234:                        return 1;
                   1235:                }
                   1236:                return 0;
                   1237: 
                   1238:              case expr_exists:
                   1239:                memset (&left, 0, sizeof left);
                   1240:                if (!in_options ||
                   1241:                    !get_option (&left, expr -> data.exists -> universe,
                   1242:                                 packet, lease, client_state,
                   1243:                                 in_options, cfg_options, in_options,
                   1244:                                 scope, expr -> data.exists -> code, MDL))
                   1245:                        *result = 0;
                   1246:                else {
                   1247:                        *result = 1;
                   1248:                        data_string_forget (&left, MDL);
                   1249:                }
                   1250: #if defined (DEBUG_EXPRESSIONS)
                   1251:                log_debug ("bool: exists %s.%s = %s",
                   1252:                           expr -> data.option -> universe -> name,
                   1253:                           expr -> data.option -> name,
                   1254:                           *result ? "true" : "false");
                   1255: #endif
                   1256:                return 1;
                   1257: 
                   1258:              case expr_known:
                   1259:                if (!packet) {
                   1260: #if defined (DEBUG_EXPRESSIONS)
                   1261:                        log_debug ("bool: known = NULL");
                   1262: #endif
                   1263:                        return 0;
                   1264:                }
                   1265: #if defined (DEBUG_EXPRESSIONS)
                   1266:                log_debug ("bool: known = %s",
                   1267:                          packet -> known ? "true" : "false");
                   1268: #endif
                   1269:                *result = packet -> known;
                   1270:                return 1;
                   1271: 
                   1272:              case expr_static:
                   1273:                if (!lease || !(lease -> flags & STATIC_LEASE)) {
                   1274: #if defined (DEBUG_EXPRESSIONS)
                   1275:                        log_debug ("bool: static = false (%s %s %s %d)",
                   1276:                                   lease ? "y" : "n",
                   1277:                                   (lease && (lease -> flags & STATIC_LEASE)
                   1278:                                    ? "y" : "n"),
                   1279:                                   piaddr (lease -> ip_addr),
                   1280:                                   lease ? lease -> flags : 0);
                   1281: #endif
                   1282:                        *result = 0;
                   1283:                        return 1;
                   1284:                }
                   1285: #if defined (DEBUG_EXPRESSIONS)
                   1286:                log_debug ("bool: static = true");
                   1287: #endif
                   1288:                *result = 1;
                   1289:                return 1;
                   1290: 
                   1291:              case expr_variable_exists:
                   1292:                if (scope && *scope) {
                   1293:                        binding = find_binding (*scope, expr -> data.variable);
                   1294: 
                   1295:                        if (binding) {
                   1296:                                if (binding -> value)
                   1297:                                        *result = 1;
                   1298:                                else
                   1299:                                        *result = 0;
                   1300:                        } else
                   1301:                                *result = 0;
                   1302:                } else
                   1303:                        *result = 0;
                   1304: #if defined (DEBUG_EXPRESSIONS)
                   1305:                log_debug ("boolean: %s? = %s", expr -> data.variable,
                   1306:                           *result ? "true" : "false");
                   1307: #endif
                   1308:                return 1;
                   1309: 
                   1310:              case expr_variable_reference:
                   1311:                if (scope && *scope) {
                   1312:                    binding = find_binding (*scope, expr -> data.variable);
                   1313: 
                   1314:                    if (binding && binding -> value) {
                   1315:                        if (binding -> value -> type ==
                   1316:                            binding_boolean) {
                   1317:                                *result = binding -> value -> value.boolean;
                   1318:                                sleft = 1;
                   1319:                        } else {
                   1320:                                log_error ("binding type %d in %s.",
                   1321:                                           binding -> value -> type,
                   1322:                                           "evaluate_boolean_expression");
                   1323:                                sleft = 0;
                   1324:                        }
                   1325:                    } else
                   1326:                            sleft = 0;
                   1327:                } else
                   1328:                        sleft = 0;
                   1329: #if defined (DEBUG_EXPRESSIONS)
                   1330:                log_debug ("boolean: %s = %s", expr -> data.variable,
                   1331:                           sleft ? (*result ? "true" : "false") : "NULL");
                   1332: #endif
                   1333:                return sleft;
                   1334: 
                   1335:              case expr_funcall:
                   1336:                bv = (struct binding_value *)0;
                   1337:                sleft = evaluate_expression (&bv, packet, lease, client_state,
                   1338:                                          in_options, cfg_options,
                   1339:                                          scope, expr, MDL);
                   1340:                if (sleft) {
                   1341:                        if (bv -> type != binding_boolean)
                   1342:                                log_error ("%s() returned type %d in %s.",
                   1343:                                           expr -> data.funcall.name,
                   1344:                                           bv -> type,
                   1345:                                           "evaluate_boolean_expression");
                   1346:                        else
                   1347:                                *result = bv -> value.boolean;
                   1348:                        binding_value_dereference (&bv, MDL);
                   1349:                }
                   1350: #if defined (DEBUG_EXPRESSIONS)
                   1351:                log_debug ("boolean: %s() = %s", expr -> data.funcall.name,
                   1352:                           sleft ? (*result ? "true" : "false") : "NULL");
                   1353: #endif
                   1354:                break;
                   1355: 
                   1356:              case expr_none:
                   1357:              case expr_match:
                   1358:              case expr_substring:
                   1359:              case expr_suffix:
                   1360:              case expr_lcase:
                   1361:              case expr_ucase:
                   1362:              case expr_option:
                   1363:              case expr_hardware:
                   1364:              case expr_const_data:
                   1365:              case expr_packet:
                   1366:              case expr_concat:
                   1367:              case expr_encapsulate:
                   1368:              case expr_host_lookup:
                   1369:              case expr_encode_int8:
                   1370:              case expr_encode_int16:
                   1371:              case expr_encode_int32:
                   1372:              case expr_binary_to_ascii:
                   1373:              case expr_reverse:
                   1374:              case expr_pick_first_value:
                   1375:              case expr_host_decl_name:
                   1376:              case expr_config_option:
                   1377:              case expr_leased_address:
                   1378:              case expr_null:
                   1379:              case expr_filename:
                   1380:              case expr_sname:
                   1381:                log_error ("Data opcode in evaluate_boolean_expression: %d",
                   1382:                      expr -> op);
                   1383:                return 0;
                   1384: 
                   1385:              case expr_extract_int8:
                   1386:              case expr_extract_int16:
                   1387:              case expr_extract_int32:
                   1388:              case expr_const_int:
                   1389:              case expr_lease_time:
                   1390:              case expr_dns_transaction:
                   1391:              case expr_add:
                   1392:              case expr_subtract:
                   1393:              case expr_multiply:
                   1394:              case expr_divide:
                   1395:              case expr_remainder:
                   1396:              case expr_binary_and:
                   1397:              case expr_binary_or:
                   1398:              case expr_binary_xor:
                   1399:              case expr_client_state:
                   1400:                log_error ("Numeric opcode in evaluate_boolean_expression: %d",
                   1401:                      expr -> op);
                   1402:                return 0;
                   1403: 
                   1404:              case expr_ns_add:
                   1405:              case expr_ns_delete:
                   1406:              case expr_ns_exists:
                   1407:              case expr_ns_not_exists:
                   1408:                log_error ("dns opcode in evaluate_boolean_expression: %d",
                   1409:                      expr -> op);
                   1410:                return 0;
                   1411: 
                   1412:              case expr_function:
                   1413:                log_error ("function definition in evaluate_boolean_expr");
                   1414:                return 0;
                   1415: 
                   1416:              case expr_arg:
                   1417:                break;
                   1418:        }
                   1419: 
                   1420:        log_error ("Bogus opcode in evaluate_boolean_expression: %d",
                   1421:                   expr -> op);
                   1422:        return 0;
                   1423: }
                   1424: 
                   1425: int evaluate_data_expression (result, packet, lease, client_state,
                   1426:                              in_options, cfg_options, scope, expr, file, line)
                   1427:        struct data_string *result;
                   1428:        struct packet *packet;
                   1429:        struct lease *lease;
                   1430:        struct client_state *client_state;
                   1431:        struct option_state *in_options;
                   1432:        struct option_state *cfg_options;
                   1433:        struct binding_scope **scope;
                   1434:        struct expression *expr;
                   1435:        const char *file;
                   1436:        int line;
                   1437: {
                   1438:        struct data_string data, other;
                   1439:        unsigned long offset, len, i;
                   1440:        int s0, s1, s2, s3;
                   1441:        int status;
                   1442:        struct binding *binding;
                   1443:        unsigned char *s;
                   1444:        struct binding_value *bv;
                   1445: 
                   1446:        switch (expr -> op) {
                   1447:                /* Extract N bytes starting at byte M of a data string. */
                   1448:              case expr_substring:
                   1449:                memset (&data, 0, sizeof data);
                   1450:                s0 = evaluate_data_expression (&data, packet, lease,
                   1451:                                               client_state,
                   1452:                                               in_options, cfg_options, scope,
                   1453:                                               expr -> data.substring.expr,
                   1454:                                               MDL);
                   1455: 
                   1456:                /* Evaluate the offset and length. */
                   1457:                s1 = evaluate_numeric_expression
                   1458:                        (&offset, packet, lease, client_state, in_options,
                   1459:                         cfg_options, scope, expr -> data.substring.offset);
                   1460:                s2 = evaluate_numeric_expression (&len, packet, lease,
                   1461:                                                  client_state,
                   1462:                                                  in_options, cfg_options,
                   1463:                                                  scope,
                   1464:                                                  expr -> data.substring.len);
                   1465: 
                   1466:                if (s0 && s1 && s2) {
                   1467:                        /* If the offset is after end of the string,
                   1468:                           return an empty string.  Otherwise, do the
                   1469:                           adjustments and return what's left. */
                   1470:                        if (data.len > offset) {
                   1471:                                data_string_copy (result, &data, file, line);
                   1472:                                result -> len -= offset;
                   1473:                                if (result -> len > len) {
                   1474:                                        result -> len = len;
                   1475:                                        result -> terminated = 0;
                   1476:                                }
                   1477:                                result -> data += offset;
                   1478:                        }
                   1479:                        s3 = 1;
                   1480:                } else
                   1481:                        s3 = 0;
                   1482: 
                   1483: #if defined (DEBUG_EXPRESSIONS)
                   1484:                log_debug ("data: substring (%s, %s, %s) = %s",
                   1485:                      s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
                   1486:                      s1 ? print_dec_1 (offset) : "NULL",
                   1487:                      s2 ? print_dec_2 (len) : "NULL",
                   1488:                      (s3 ? print_hex_2 (result -> len, result -> data, 30)
                   1489:                          : "NULL"));
                   1490: #endif
                   1491:                if (s0)
                   1492:                        data_string_forget (&data, MDL);
                   1493:                if (s3)
                   1494:                        return 1;
                   1495:                return 0;
                   1496: 
                   1497:                /* Extract the last N bytes of a data string. */
                   1498:              case expr_suffix:
                   1499:                memset (&data, 0, sizeof data);
                   1500:                s0 = evaluate_data_expression (&data, packet, lease,
                   1501:                                               client_state,
                   1502:                                               in_options, cfg_options, scope,
                   1503:                                               expr -> data.suffix.expr, MDL);
                   1504:                /* Evaluate the length. */
                   1505:                s1 = evaluate_numeric_expression (&len, packet, lease,
                   1506:                                                  client_state,
                   1507:                                                  in_options, cfg_options,
                   1508:                                                  scope,
                   1509:                                                  expr -> data.suffix.len);
                   1510:                if (s0 && s1) {
                   1511:                        data_string_copy (result, &data, file, line);
                   1512: 
                   1513:                        /* If we are returning the last N bytes of a
                   1514:                           string whose length is <= N, just return
                   1515:                           the string - otherwise, compute a new
                   1516:                           starting address and decrease the
                   1517:                           length. */
                   1518:                        if (data.len > len) {
                   1519:                                result -> data += data.len - len;
                   1520:                                result -> len = len;
                   1521:                        }
                   1522:                        data_string_forget (&data, MDL);
                   1523:                }
                   1524: 
                   1525: #if defined (DEBUG_EXPRESSIONS)
                   1526:                log_debug ("data: suffix (%s, %s) = %s",
                   1527:                      s0 ? print_hex_1 (data.len, data.data, 30) : "NULL",
                   1528:                      s1 ? print_dec_1 (len) : "NULL",
                   1529:                      ((s0 && s1)
                   1530:                       ? print_hex_2 (result -> len, result -> data, 30)
                   1531:                       : "NULL"));
                   1532: #endif
                   1533:                return s0 && s1;
                   1534: 
                   1535:                /* Convert string to lowercase. */
                   1536:              case expr_lcase:
                   1537:                memset(&data, 0, sizeof data);
                   1538:                s0 = evaluate_data_expression(&data, packet, lease,
                   1539:                                              client_state,
                   1540:                                              in_options, cfg_options, scope,
                   1541:                                              expr->data.lcase, MDL);
                   1542:                s1 = 0;
                   1543:                if (s0) {
                   1544:                        result->len = data.len;
                   1545:                        if (buffer_allocate(&result->buffer,
                   1546:                                            result->len + data.terminated,
                   1547:                                            MDL)) {
                   1548:                                result->data = &result->buffer->data[0];
                   1549:                                memcpy(result->buffer->data, data.data,
                   1550:                                       data.len + data.terminated);
                   1551:                                result->terminated = data.terminated;
                   1552:                                s = (unsigned char *)result->data;
                   1553:                                for (i = 0; i < result->len; i++, s++)
                   1554:                                        *s = tolower(*s);
                   1555:                                s1 = 1;
                   1556:                        } else {
                   1557:                                log_error("data: lcase: no buffer memory.");
                   1558:                        }
                   1559:                }
                   1560: 
                   1561: #if defined (DEBUG_EXPRESSIONS)
                   1562:                log_debug("data: lcase (%s) = %s",
                   1563:                          s0 ? print_hex_1(data.len, data.data, 30) : "NULL",
                   1564:                          s1 ? print_hex_2(result->len, result->data, 30)
                   1565:                             : "NULL");
                   1566: #endif
                   1567:                if (s0)
                   1568:                        data_string_forget(&data, MDL);
                   1569:                return s1;
                   1570: 
                   1571:                /* Convert string to uppercase. */
                   1572:              case expr_ucase:
                   1573:                memset(&data, 0, sizeof data);
                   1574:                s0 = evaluate_data_expression(&data, packet, lease,
                   1575:                                              client_state,
                   1576:                                              in_options, cfg_options, scope,
                   1577:                                              expr->data.lcase, MDL);
                   1578:                s1 = 0;
                   1579:                if (s0) {
                   1580:                        result->len = data.len;
                   1581:                        if (buffer_allocate(&result->buffer,
                   1582:                                            result->len + data.terminated,
                   1583:                                            file, line)) {
                   1584:                                result->data = &result->buffer->data[0];
                   1585:                                memcpy(result->buffer->data, data.data,
                   1586:                                       data.len + data.terminated);
                   1587:                                result->terminated = data.terminated;
                   1588:                                s = (unsigned char *)result->data;
                   1589:                                for (i = 0; i < result->len; i++, s++)
                   1590:                                        *s = toupper(*s);
                   1591:                                s1 = 1;
                   1592:                        } else {
                   1593:                                log_error("data: lcase: no buffer memory.");
                   1594:                        }
                   1595:                }
                   1596: 
                   1597: #if defined (DEBUG_EXPRESSIONS)
                   1598:                log_debug("data: ucase (%s) = %s",
                   1599:                          s0 ? print_hex_1(data.len, data.data, 30) : "NULL",
                   1600:                          s1 ? print_hex_2(result->len, result->data, 30)
                   1601:                             : "NULL");
                   1602: #endif
                   1603:                 if (s0)
                   1604:                        data_string_forget(&data, MDL);
                   1605:                 return s1;
                   1606: 
                   1607:                /* Extract an option. */
                   1608:              case expr_option:
                   1609:                if (in_options)
                   1610:                    s0 = get_option (result,
                   1611:                                     expr -> data.option -> universe,
                   1612:                                     packet, lease, client_state,
                   1613:                                     in_options, cfg_options, in_options,
                   1614:                                     scope, expr -> data.option -> code,
                   1615:                                     file, line);
                   1616:                else
                   1617:                        s0 = 0;
                   1618: 
                   1619: #if defined (DEBUG_EXPRESSIONS)
                   1620:                log_debug ("data: option %s.%s = %s",
                   1621:                      expr -> data.option -> universe -> name,
                   1622:                      expr -> data.option -> name,
                   1623:                      s0 ? print_hex_1 (result -> len, result -> data, 60)
                   1624:                      : "NULL");
                   1625: #endif
                   1626:                return s0;
                   1627: 
                   1628:              case expr_config_option:
                   1629:                if (cfg_options)
                   1630:                    s0 = get_option (result,
                   1631:                                     expr -> data.option -> universe,
                   1632:                                     packet, lease, client_state,
                   1633:                                     in_options, cfg_options, cfg_options,
                   1634:                                     scope, expr -> data.option -> code,
                   1635:                                     file, line);
                   1636:                else
                   1637:                        s0 = 0;
                   1638: 
                   1639: #if defined (DEBUG_EXPRESSIONS)
                   1640:                log_debug ("data: config-option %s.%s = %s",
                   1641:                      expr -> data.option -> universe -> name,
                   1642:                      expr -> data.option -> name,
                   1643:                      s0 ? print_hex_1 (result -> len, result -> data, 60)
                   1644:                      : "NULL");
                   1645: #endif
                   1646:                return s0;
                   1647: 
                   1648:                /* Combine the hardware type and address. */
                   1649:              case expr_hardware:
                   1650:                /* On the client, hardware is our hardware. */
                   1651:                if (client_state) {
                   1652:                        memset (result, 0, sizeof *result);
                   1653:                        result -> data =
                   1654:                                client_state -> interface -> hw_address.hbuf;
                   1655:                        result -> len =
                   1656:                                client_state -> interface -> hw_address.hlen;
                   1657: #if defined (DEBUG_EXPRESSIONS)
                   1658:                        log_debug ("data: hardware = %s",
                   1659:                                   print_hex_1 (result -> len,
                   1660:                                                result -> data, 60));
                   1661: #endif
                   1662:                        return 1;
                   1663:                }
                   1664: 
                   1665:                /* The server cares about the client's hardware address,
                   1666:                   so only in the case where we are examining a packet can
                   1667:                   we return anything. */
                   1668:                if (!packet || !packet -> raw) {
                   1669:                        log_error ("data: hardware: raw packet not available");
                   1670:                        return 0;
                   1671:                }
                   1672:                if (packet -> raw -> hlen > sizeof packet -> raw -> chaddr) {
                   1673:                        log_error ("data: hardware: invalid hlen (%d)\n",
                   1674:                                   packet -> raw -> hlen);
                   1675:                        return 0;
                   1676:                }
                   1677:                result -> len = packet -> raw -> hlen + 1;
                   1678:                if (buffer_allocate (&result -> buffer, result -> len,
                   1679:                                     file, line)) {
                   1680:                        result -> data = &result -> buffer -> data [0];
                   1681:                        result -> buffer -> data [0] = packet -> raw -> htype;
                   1682:                        memcpy (&result -> buffer -> data [1],
                   1683:                                packet -> raw -> chaddr,
                   1684:                                packet -> raw -> hlen);
                   1685:                        result -> terminated = 0;
                   1686:                } else {
                   1687:                        log_error ("data: hardware: no memory for buffer.");
                   1688:                        return 0;
                   1689:                }
                   1690: #if defined (DEBUG_EXPRESSIONS)
                   1691:                log_debug ("data: hardware = %s",
                   1692:                      print_hex_1 (result -> len, result -> data, 60));
                   1693: #endif
                   1694:                return 1;
                   1695: 
                   1696:                /* Extract part of the raw packet. */
                   1697:              case expr_packet:
                   1698:                if (!packet || !packet -> raw) {
                   1699:                        log_error ("data: packet: raw packet not available");
                   1700:                        return 0;
                   1701:                }
                   1702: 
                   1703:                s0 = evaluate_numeric_expression (&offset, packet, lease,
                   1704:                                                  client_state,
                   1705:                                                  in_options, cfg_options,
                   1706:                                                  scope,
                   1707:                                                  expr -> data.packet.offset);
                   1708:                s1 = evaluate_numeric_expression (&len,
                   1709:                                                  packet, lease, client_state,
                   1710:                                                  in_options, cfg_options,
                   1711:                                                  scope,
                   1712:                                                  expr -> data.packet.len);
                   1713:                if (s0 && s1 && offset < packet -> packet_length) {
                   1714:                        if (offset + len > packet -> packet_length)
                   1715:                                result -> len =
                   1716:                                        packet -> packet_length - offset;
                   1717:                        else
                   1718:                                result -> len = len;
                   1719:                        if (buffer_allocate (&result -> buffer,
                   1720:                                             result -> len, file, line)) {
                   1721:                                result -> data = &result -> buffer -> data [0];
                   1722:                                memcpy (result -> buffer -> data,
                   1723:                                        (((unsigned char *)(packet -> raw))
                   1724:                                         + offset), result -> len);
                   1725:                                result -> terminated = 0;
                   1726:                        } else {
                   1727:                                log_error ("data: packet: no buffer memory.");
                   1728:                                return 0;
                   1729:                        }
                   1730:                        s2 = 1;
                   1731:                } else
                   1732:                        s2 = 0;
                   1733: #if defined (DEBUG_EXPRESSIONS)
                   1734:                log_debug ("data: packet (%ld, %ld) = %s",
                   1735:                      offset, len,
                   1736:                      s2 ? print_hex_1 (result -> len,
                   1737:                                        result -> data, 60) : NULL);
                   1738: #endif
                   1739:                return s2;
                   1740: 
                   1741:                /* The encapsulation of all defined options in an
                   1742:                   option space... */
                   1743:              case expr_encapsulate:
                   1744:                if (cfg_options)
                   1745:                        s0 = option_space_encapsulate
                   1746:                                (result, packet, lease, client_state,
                   1747:                                 in_options, cfg_options, scope,
                   1748:                                 &expr -> data.encapsulate);
                   1749:                else
                   1750:                        s0 = 0;
                   1751: 
                   1752: #if defined (DEBUG_EXPRESSIONS)
                   1753:                log_debug ("data: encapsulate (%s) = %s",
                   1754:                          expr -> data.encapsulate.data,
                   1755:                          s0 ? print_hex_1 (result -> len,
                   1756:                                            result -> data, 60) : "NULL");
                   1757: #endif
                   1758:                return s0;
                   1759: 
                   1760:                /* Some constant data... */
                   1761:              case expr_const_data:
                   1762: #if defined (DEBUG_EXPRESSIONS)
                   1763:                log_debug ("data: const = %s",
                   1764:                      print_hex_1 (expr -> data.const_data.len,
                   1765:                                   expr -> data.const_data.data, 60));
                   1766: #endif
                   1767:                data_string_copy (result,
                   1768:                                  &expr -> data.const_data, file, line);
                   1769:                return 1;
                   1770: 
                   1771:                /* Hostname lookup... */
                   1772:              case expr_host_lookup:
                   1773:                s0 = do_host_lookup (result, expr -> data.host_lookup);
                   1774: #if defined (DEBUG_EXPRESSIONS)
                   1775:                log_debug ("data: DNS lookup (%s) = %s",
                   1776:                      expr -> data.host_lookup -> hostname,
                   1777:                      (s0
                   1778:                       ? print_dotted_quads (result -> len, result -> data)
                   1779:                       : "NULL"));
                   1780: #endif
                   1781:                return s0;
                   1782: 
                   1783:                /* Concatenation... */
                   1784:              case expr_concat:
                   1785:                memset (&data, 0, sizeof data);
                   1786:                s0 = evaluate_data_expression (&data, packet, lease,
                   1787:                                               client_state,
                   1788:                                               in_options, cfg_options, scope,
                   1789:                                               expr -> data.concat [0], MDL);
                   1790:                memset (&other, 0, sizeof other);
                   1791:                s1 = evaluate_data_expression (&other, packet, lease,
                   1792:                                               client_state,
                   1793:                                               in_options, cfg_options, scope,
                   1794:                                               expr -> data.concat [1], MDL);
                   1795: 
                   1796:                if (s0 && s1) {
                   1797:                    result -> len = data.len + other.len;
                   1798:                    if (!buffer_allocate (&result -> buffer,
                   1799:                                          (result -> len + other.terminated),
                   1800:                                          file, line)) {
                   1801:                                log_error ("data: concat: no memory");
                   1802:                                result -> len = 0;
                   1803:                                data_string_forget (&data, MDL);
                   1804:                                data_string_forget (&other, MDL);
                   1805:                                return 0;
                   1806:                        }
                   1807:                        result -> data = &result -> buffer -> data [0];
                   1808:                        memcpy (result -> buffer -> data, data.data, data.len);
                   1809:                        memcpy (&result -> buffer -> data [data.len],
                   1810:                                other.data, other.len + other.terminated);
                   1811:                }
                   1812: 
                   1813:                if (s0)
                   1814:                        data_string_forget (&data, MDL);
                   1815:                if (s1)
                   1816:                        data_string_forget (&other, MDL);
                   1817: #if defined (DEBUG_EXPRESSIONS)
                   1818:                log_debug ("data: concat (%s, %s) = %s",
                   1819:                      s0 ? print_hex_1 (data.len, data.data, 20) : "NULL",
                   1820:                      s1 ? print_hex_2 (other.len, other.data, 20) : "NULL",
                   1821:                      ((s0 && s1)
                   1822:                       ? print_hex_3 (result -> len, result -> data, 30)
                   1823:                       : "NULL"));
                   1824: #endif
                   1825:                return s0 && s1;
                   1826: 
                   1827:              case expr_encode_int8:
                   1828:                s0 = evaluate_numeric_expression (&len, packet, lease,
                   1829:                                                  client_state,
                   1830:                                                  in_options, cfg_options,
                   1831:                                                  scope,
                   1832:                                                  expr -> data.encode_int);
                   1833:                if (s0) {
                   1834:                        result -> len = 1;
                   1835:                        if (!buffer_allocate (&result -> buffer,
                   1836:                                              1, file, line)) {
                   1837:                                log_error ("data: encode_int8: no memory");
                   1838:                                result -> len = 0;
                   1839:                                s0 = 0;
                   1840:                        } else {
                   1841:                                result -> data = &result -> buffer -> data [0];
                   1842:                                result -> buffer -> data [0] = len;
                   1843:                        }
                   1844:                } else
                   1845:                        result -> len = 0;
                   1846: 
                   1847: #if defined (DEBUG_EXPRESSIONS)
                   1848:                if (!s0)
                   1849:                        log_debug ("data: encode_int8 (NULL) = NULL");
                   1850:                else
                   1851:                        log_debug ("data: encode_int8 (%ld) = %s", len,
                   1852:                                  print_hex_2 (result -> len,
                   1853:                                               result -> data, 20));
                   1854: #endif
                   1855:                return s0;
                   1856:                        
                   1857:                
                   1858:              case expr_encode_int16:
                   1859:                s0 = evaluate_numeric_expression (&len, packet, lease,
                   1860:                                                  client_state,
                   1861:                                                  in_options, cfg_options,
                   1862:                                                  scope,
                   1863:                                                  expr -> data.encode_int);
                   1864:                if (s0) {
                   1865:                        result -> len = 2;
                   1866:                        if (!buffer_allocate (&result -> buffer, 2,
                   1867:                                              file, line)) {
                   1868:                                log_error ("data: encode_int16: no memory");
                   1869:                                result -> len = 0;
                   1870:                                s0 = 0;
                   1871:                        } else {
                   1872:                                result -> data = &result -> buffer -> data [0];
                   1873:                                putUShort (result -> buffer -> data, len);
                   1874:                        }
                   1875:                } else
                   1876:                        result -> len = 0;
                   1877: 
                   1878: #if defined (DEBUG_EXPRESSIONS)
                   1879:                if (!s0)
                   1880:                        log_debug ("data: encode_int16 (NULL) = NULL");
                   1881:                else
                   1882:                        log_debug ("data: encode_int16 (%ld) = %s", len,
                   1883:                                  print_hex_2 (result -> len,
                   1884:                                               result -> data, 20));
                   1885: #endif
                   1886:                return s0;
                   1887: 
                   1888:              case expr_encode_int32:
                   1889:                s0 = evaluate_numeric_expression (&len, packet, lease,
                   1890:                                                  client_state,
                   1891:                                                  in_options, cfg_options,
                   1892:                                                  scope,
                   1893:                                                  expr -> data.encode_int);
                   1894:                if (s0) {
                   1895:                        result -> len = 4;
                   1896:                        if (!buffer_allocate (&result -> buffer, 4,
                   1897:                                              file, line)) {
                   1898:                                log_error ("data: encode_int32: no memory");
                   1899:                                result -> len = 0;
                   1900:                                s0 = 0;
                   1901:                        } else {
                   1902:                                result -> data = &result -> buffer -> data [0];
                   1903:                                putULong (result -> buffer -> data, len);
                   1904:                        }
                   1905:                } else
                   1906:                        result -> len = 0;
                   1907: 
                   1908: #if defined (DEBUG_EXPRESSIONS)
                   1909:                if (!s0)
                   1910:                        log_debug ("data: encode_int32 (NULL) = NULL");
                   1911:                else
                   1912:                        log_debug ("data: encode_int32 (%ld) = %s", len,
                   1913:                                  print_hex_2 (result -> len,
                   1914:                                               result -> data, 20));
                   1915: #endif
                   1916:                return s0;
                   1917: 
                   1918:              case expr_binary_to_ascii:
                   1919:                /* Evaluate the base (offset) and width (len): */
                   1920:                s0 = evaluate_numeric_expression
                   1921:                        (&offset, packet, lease, client_state, in_options,
                   1922:                         cfg_options, scope, expr -> data.b2a.base);
                   1923:                s1 = evaluate_numeric_expression (&len, packet, lease,
                   1924:                                                  client_state,
                   1925:                                                  in_options, cfg_options,
                   1926:                                                  scope,
                   1927:                                                  expr -> data.b2a.width);
                   1928: 
                   1929:                /* Evaluate the separator string. */
                   1930:                memset (&data, 0, sizeof data);
                   1931:                s2 = evaluate_data_expression (&data, packet, lease,
                   1932:                                               client_state,
                   1933:                                               in_options, cfg_options, scope,
                   1934:                                               expr -> data.b2a.separator,
                   1935:                                               MDL);
                   1936: 
                   1937:                /* Evaluate the data to be converted. */
                   1938:                memset (&other, 0, sizeof other);
                   1939:                s3 = evaluate_data_expression (&other, packet, lease,
                   1940:                                               client_state,
                   1941:                                               in_options, cfg_options, scope,
                   1942:                                               expr -> data.b2a.buffer, MDL);
                   1943: 
                   1944:                if (s0 && s1 && s2 && s3) {
                   1945:                        unsigned buflen, i;
                   1946: 
                   1947:                        if (len != 8 && len != 16 && len != 32) {
                   1948:                                log_info ("binary_to_ascii: %s %ld!",
                   1949:                                          "invalid width", len);
                   1950:                                status = 0;
                   1951:                                goto b2a_out;
                   1952:                        }
                   1953:                        len /= 8;
                   1954: 
                   1955:                        /* The buffer must be a multiple of the number's
                   1956:                           width. */
                   1957:                        if (other.len % len) {
                   1958:                                log_info ("binary-to-ascii: %s %d %s %ld!",
                   1959:                                          "length of buffer", other.len,
                   1960:                                          "not a multiple of width", len);
                   1961:                                status = 0;
                   1962:                                goto b2a_out;
                   1963:                        }
                   1964: 
                   1965:                        /* Count the width of the output. */
                   1966:                        buflen = 0;
                   1967:                        for (i = 0; i < other.len; i += len) {
                   1968:                                if (len == 1) {
                   1969:                                        if (offset == 8) {
                   1970:                                                if (other.data [i] < 8)
                   1971:                                                        buflen++;
                   1972:                                                else if (other.data [i] < 64)
                   1973:                                                        buflen += 2;
                   1974:                                                else
                   1975:                                                        buflen += 3;
                   1976:                                        } else if (offset == 10) {
                   1977:                                                if (other.data [i] < 10)
                   1978:                                                        buflen++;
                   1979:                                                else if (other.data [i] < 100)
                   1980:                                                        buflen += 2;
                   1981:                                                else
                   1982:                                                        buflen += 3;
                   1983:                                        } else if (offset == 16) {
                   1984:                                                if (other.data [i] < 16)
                   1985:                                                        buflen++;
                   1986:                                                else
                   1987:                                                        buflen += 2;
                   1988:                                        } else
                   1989:                                                buflen += (converted_length
                   1990:                                                           (&other.data [i],
                   1991:                                                            offset, 1));
                   1992:                                } else
                   1993:                                        buflen += (converted_length
                   1994:                                                   (&other.data [i],
                   1995:                                                    offset, len));
                   1996:                                if (i + len != other.len)
                   1997:                                        buflen += data.len;
                   1998:                        }
                   1999: 
                   2000:                        if (!buffer_allocate (&result -> buffer,
                   2001:                                              buflen + 1, file, line)) {
                   2002:                                log_error ("data: binary-to-ascii: no memory");
                   2003:                                status = 0;
                   2004:                                goto b2a_out;
                   2005:                        }
                   2006:                        result -> data = &result -> buffer -> data [0];
                   2007:                        result -> len = buflen;
                   2008:                        result -> terminated = 1;
                   2009: 
                   2010:                        buflen = 0;
                   2011:                        for (i = 0; i < other.len; i += len) {
                   2012:                                buflen += (binary_to_ascii
                   2013:                                           (&result -> buffer -> data [buflen],
                   2014:                                            &other.data [i], offset, len));
                   2015:                                if (i + len != other.len) {
                   2016:                                        memcpy (&result ->
                   2017:                                                buffer -> data [buflen],
                   2018:                                                data.data, data.len);
                   2019:                                        buflen += data.len;
                   2020:                                }
                   2021:                        }
                   2022:                        /* NUL terminate. */
                   2023:                        result -> buffer -> data [buflen] = 0;
                   2024:                        status = 1;
                   2025:                } else
                   2026:                        status = 0;
                   2027: 
                   2028:              b2a_out:
                   2029: #if defined (DEBUG_EXPRESSIONS)
                   2030:                log_debug ("data: binary-to-ascii (%s, %s, %s, %s) = %s",
                   2031:                      s0 ? print_dec_1 (offset) : "NULL",
                   2032:                      s1 ? print_dec_2 (len) : "NULL",
                   2033:                      s2 ? print_hex_1 (data.len, data.data, 30) : "NULL",
                   2034:                      s3 ? print_hex_2 (other.len, other.data, 30) : "NULL",
                   2035:                      (status ? print_hex_3 (result -> len, result -> data, 30)
                   2036:                          : "NULL"));
                   2037: #endif
                   2038:                if (s2)
                   2039:                        data_string_forget (&data, MDL);
                   2040:                if (s3)
                   2041:                        data_string_forget (&other, MDL);
                   2042:                if (status)
                   2043:                        return 1;
                   2044:                return 0;
                   2045: 
                   2046:              case expr_reverse:
                   2047:                /* Evaluate the width (len): */
                   2048:                s0 = evaluate_numeric_expression
                   2049:                        (&len, packet, lease, client_state, in_options,
                   2050:                         cfg_options, scope, expr -> data.reverse.width);
                   2051: 
                   2052:                /* Evaluate the data. */
                   2053:                memset (&data, 0, sizeof data);
                   2054:                s1 = evaluate_data_expression (&data, packet, lease,
                   2055:                                               client_state,
                   2056:                                               in_options, cfg_options, scope,
                   2057:                                               expr -> data.reverse.buffer,
                   2058:                                               MDL);
                   2059: 
                   2060:                if (s0 && s1) {
                   2061:                        int i;
                   2062: 
                   2063:                        /* The buffer must be a multiple of the number's
                   2064:                           width. */
                   2065:                        if (data.len % len) {
                   2066:                                log_info ("reverse: %s %d %s %ld!",
                   2067:                                          "length of buffer", data.len,
                   2068:                                          "not a multiple of width", len);
                   2069:                                status = 0;
                   2070:                                goto reverse_out;
                   2071:                        }
                   2072: 
                   2073:                        /* XXX reverse in place?   I don't think we can. */
                   2074:                        if (!buffer_allocate (&result -> buffer,
                   2075:                                              data.len, file, line)) {
                   2076:                                log_error ("data: reverse: no memory");
                   2077:                                status = 0;
                   2078:                                goto reverse_out;
                   2079:                        }
                   2080:                        result -> data = &result -> buffer -> data [0];
                   2081:                        result -> len = data.len;
                   2082:                        result -> terminated = 0;
                   2083: 
                   2084:                        for (i = 0; i < data.len; i += len) {
                   2085:                                memcpy (&result -> buffer -> data [i],
                   2086:                                        &data.data [data.len - i - len], len);
                   2087:                        }
                   2088:                        status = 1;
                   2089:                } else
                   2090:                        status = 0;
                   2091: 
                   2092:              reverse_out:
                   2093: #if defined (DEBUG_EXPRESSIONS)
                   2094:                log_debug ("data: reverse (%s, %s) = %s",
                   2095:                      s0 ? print_dec_1 (len) : "NULL",
                   2096:                      s1 ? print_hex_1 (data.len, data.data, 30) : "NULL",
                   2097:                      (status ? print_hex_3 (result -> len, result -> data, 30)
                   2098:                          : "NULL"));
                   2099: #endif
                   2100:                if (s0)
                   2101:                        data_string_forget (&data, MDL);
                   2102:                if (status)
                   2103:                        return 1;
                   2104:                return 0;
                   2105: 
                   2106:              case expr_leased_address:
                   2107:                if (!lease) {
                   2108:                        log_debug("data: \"leased-address\" configuration "
                   2109:                                  "directive: there is no lease associated "
                   2110:                                  "with this client.");
                   2111:                        return 0;
                   2112:                }
                   2113:                result -> len = lease -> ip_addr.len;
                   2114:                if (buffer_allocate (&result -> buffer, result -> len,
                   2115:                                     file, line)) {
                   2116:                        result -> data = &result -> buffer -> data [0];
                   2117:                        memcpy (&result -> buffer -> data [0],
                   2118:                                lease -> ip_addr.iabuf, lease -> ip_addr.len);
                   2119:                        result -> terminated = 0;
                   2120:                } else {
                   2121:                        log_error ("data: leased-address: no memory.");
                   2122:                        return 0;
                   2123:                }
                   2124: #if defined (DEBUG_EXPRESSIONS)
                   2125:                log_debug ("data: leased-address = %s",
                   2126:                      print_hex_1 (result -> len, result -> data, 60));
                   2127: #endif
                   2128:                return 1;
                   2129: 
                   2130:              case expr_pick_first_value:
                   2131:                memset (&data, 0, sizeof data);
                   2132:                if ((evaluate_data_expression
                   2133:                     (result, packet,
                   2134:                      lease, client_state, in_options, cfg_options,
                   2135:                      scope, expr -> data.pick_first_value.car, MDL))) {
                   2136: #if defined (DEBUG_EXPRESSIONS)
                   2137:                        log_debug ("data: pick_first_value (%s, xxx)",
                   2138:                                   print_hex_1 (result -> len,
                   2139:                                                result -> data, 40));
                   2140: #endif
                   2141:                        return 1;
                   2142:                }
                   2143: 
                   2144:                if (expr -> data.pick_first_value.cdr &&
                   2145:                    (evaluate_data_expression
                   2146:                     (result, packet,
                   2147:                      lease, client_state, in_options, cfg_options,
                   2148:                      scope, expr -> data.pick_first_value.cdr, MDL))) {
                   2149: #if defined (DEBUG_EXPRESSIONS)
                   2150:                        log_debug ("data: pick_first_value (NULL, %s)",
                   2151:                                   print_hex_1 (result -> len,
                   2152:                                                result -> data, 40));
                   2153: #endif
                   2154:                        return 1;
                   2155:                }
                   2156: 
                   2157: #if defined (DEBUG_EXPRESSIONS)
                   2158:                log_debug ("data: pick_first_value (NULL, NULL) = NULL");
                   2159: #endif
                   2160:                return 0;
                   2161: 
                   2162:              case expr_host_decl_name:
                   2163:                if (!lease || !lease -> host) {
                   2164:                        log_error ("data: host_decl_name: not available");
                   2165:                        return 0;
                   2166:                }
                   2167:                result -> len = strlen (lease -> host -> name);
                   2168:                if (buffer_allocate (&result -> buffer,
                   2169:                                     result -> len + 1, file, line)) {
                   2170:                        result -> data = &result -> buffer -> data [0];
                   2171:                        strcpy ((char *)&result -> buffer -> data [0],
                   2172:                                lease -> host -> name);
                   2173:                        result -> terminated = 1;
                   2174:                } else {
                   2175:                        log_error ("data: host-decl-name: no memory.");
                   2176:                        return 0;
                   2177:                }
                   2178: #if defined (DEBUG_EXPRESSIONS)
                   2179:                log_debug ("data: host-decl-name = %s", lease -> host -> name);
                   2180: #endif
                   2181:                return 1;
                   2182: 
                   2183:              case expr_null:
                   2184: #if defined (DEBUG_EXPRESSIONS)
                   2185:                log_debug ("data: null = NULL");
                   2186: #endif
                   2187:                return 0;
                   2188: 
                   2189:              case expr_variable_reference:
                   2190:                if (scope && *scope) {
                   2191:                    binding = find_binding (*scope, expr -> data.variable);
                   2192: 
                   2193:                    if (binding && binding -> value) {
                   2194:                        if (binding -> value -> type == binding_data) {
                   2195:                            data_string_copy (result,
                   2196:                                              &binding -> value -> value.data,
                   2197:                                              file, line);
                   2198:                            s0 = 1;
                   2199:                        } else if (binding -> value -> type != binding_data) {
                   2200:                            log_error ("binding type %d in %s.",
                   2201:                                       binding -> value -> type,
                   2202:                                       "evaluate_data_expression");
                   2203:                            s0 = 0;
                   2204:                        } else
                   2205:                            s0 = 0;
                   2206:                    } else
                   2207:                        s0 = 0;
                   2208:                } else
                   2209:                    s0 = 0;
                   2210: #if defined (DEBUG_EXPRESSIONS)
                   2211:                log_debug ("data: %s = %s", expr -> data.variable,
                   2212:                           s0 ? print_hex_1 (result -> len,
                   2213:                                             result -> data, 50) : "NULL");
                   2214: #endif
                   2215:                return s0;
                   2216: 
                   2217:              case expr_funcall:
                   2218:                bv = (struct binding_value *)0;
                   2219:                s0 = evaluate_expression (&bv, packet, lease, client_state,
                   2220:                                          in_options, cfg_options,
                   2221:                                          scope, expr, MDL);
                   2222:                if (s0) {
                   2223:                        if (bv -> type != binding_data)
                   2224:                                log_error ("%s() returned type %d in %s.",
                   2225:                                           expr -> data.funcall.name,
                   2226:                                           bv -> type,
                   2227:                                           "evaluate_data_expression");
                   2228:                        else
                   2229:                                data_string_copy (result, &bv -> value.data,
                   2230:                                                  file, line);
                   2231:                        binding_value_dereference (&bv, MDL);
                   2232:                }
                   2233: #if defined (DEBUG_EXPRESSIONS)
                   2234:                log_debug ("data: %s = %s", expr -> data.funcall.name,
                   2235:                           s0 ? print_hex_1 (result -> len,
                   2236:                                             result -> data, 50) : "NULL");
                   2237: #endif
                   2238:                break;
                   2239: 
                   2240:                /* Extract the filename. */
                   2241:              case expr_filename:
                   2242:                if (packet && packet -> raw -> file [0]) {
                   2243:                        char *fn =
                   2244:                                memchr (packet -> raw -> file, 0,
                   2245:                                        sizeof packet -> raw -> file);
                   2246:                        if (!fn)
                   2247:                                fn = ((char *)packet -> raw -> file +
                   2248:                                      sizeof packet -> raw -> file);
                   2249:                        result -> len = fn - &(packet -> raw -> file [0]);
                   2250:                        if (buffer_allocate (&result -> buffer,
                   2251:                                             result -> len + 1, file, line)) {
                   2252:                                result -> data = &result -> buffer -> data [0];
                   2253:                                memcpy (&result -> buffer -> data [0],
                   2254:                                        packet -> raw -> file,
                   2255:                                        result -> len);
                   2256:                                result -> buffer -> data [result -> len] = 0;
                   2257:                                result -> terminated = 1;
                   2258:                                s0 = 1;
                   2259:                        } else {
                   2260:                                log_error ("data: filename: no memory.");
                   2261:                                s0 = 0;
                   2262:                        }
                   2263:                } else
                   2264:                        s0 = 0;
                   2265: 
                   2266: #if defined (DEBUG_EXPRESSIONS)
                   2267:                log_info ("data: filename = \"%s\"",
                   2268:                          s0 ? (const char *)(result -> data) : "NULL");
                   2269: #endif
                   2270:                return s0;
                   2271: 
                   2272:                /* Extract the server name. */
                   2273:              case expr_sname:
                   2274:                if (packet && packet -> raw -> sname [0]) {
                   2275:                        char *fn =
                   2276:                                memchr (packet -> raw -> sname, 0,
                   2277:                                        sizeof packet -> raw -> sname);
                   2278:                        if (!fn)
                   2279:                                fn = ((char *)packet -> raw -> sname + 
                   2280:                                      sizeof packet -> raw -> sname);
                   2281:                        result -> len = fn - &packet -> raw -> sname [0];
                   2282:                        if (buffer_allocate (&result -> buffer,
                   2283:                                             result -> len + 1, file, line)) {
                   2284:                                result -> data = &result -> buffer -> data [0];
                   2285:                                memcpy (&result -> buffer -> data [0],
                   2286:                                        packet -> raw -> sname,
                   2287:                                        result -> len);
                   2288:                                result -> buffer -> data [result -> len] = 0;
                   2289:                                result -> terminated = 1;
                   2290:                                s0 = 1;
                   2291:                        } else {
                   2292:                                log_error ("data: sname: no memory.");
                   2293:                                s0 = 0;
                   2294:                        }
                   2295:                } else
                   2296:                        s0 = 0;
                   2297: 
                   2298: #if defined (DEBUG_EXPRESSIONS)
                   2299:                log_info ("data: sname = \"%s\"",
                   2300:                          s0 ? (const char *)(result -> data) : "NULL");
                   2301: #endif
                   2302:                return s0;
                   2303: 
                   2304:              case expr_check:
                   2305:              case expr_equal:
                   2306:              case expr_not_equal:
                   2307:              case expr_regex_match:
                   2308:              case expr_iregex_match:
                   2309:              case expr_and:
                   2310:              case expr_or:
                   2311:              case expr_not:
                   2312:              case expr_match:
                   2313:              case expr_static:
                   2314:              case expr_known:
                   2315:              case expr_none:
                   2316:              case expr_exists:
                   2317:              case expr_variable_exists:
                   2318:                log_error ("Boolean opcode in evaluate_data_expression: %d",
                   2319:                      expr -> op);
                   2320:                return 0;
                   2321: 
                   2322:              case expr_extract_int8:
                   2323:              case expr_extract_int16:
                   2324:              case expr_extract_int32:
                   2325:              case expr_const_int:
                   2326:              case expr_lease_time:
                   2327:              case expr_dns_transaction:
                   2328:              case expr_add:
                   2329:              case expr_subtract:
                   2330:              case expr_multiply:
                   2331:              case expr_divide:
                   2332:              case expr_remainder:
                   2333:              case expr_binary_and:
                   2334:              case expr_binary_or:
                   2335:              case expr_binary_xor:
                   2336:              case expr_client_state:
                   2337:                log_error ("Numeric opcode in evaluate_data_expression: %d",
                   2338:                      expr -> op);
                   2339:                return 0;
                   2340: 
                   2341:              case expr_ns_add:
                   2342:              case expr_ns_delete:
                   2343:              case expr_ns_exists:
                   2344:              case expr_ns_not_exists:
                   2345:                log_error ("dns update opcode in evaluate_data_expression: %d",
                   2346:                      expr -> op);
                   2347:                return 0;
                   2348: 
                   2349:              case expr_function:
                   2350:                log_error ("function definition in evaluate_data_expression");
                   2351:                return 0;
                   2352: 
                   2353:              case expr_arg:
                   2354:                break;
                   2355:        }
                   2356: 
                   2357:        log_error ("Bogus opcode in evaluate_data_expression: %d", expr -> op);
                   2358:        return 0;
                   2359: }      
                   2360: 
                   2361: int evaluate_numeric_expression (result, packet, lease, client_state,
                   2362:                                 in_options, cfg_options, scope, expr)
                   2363:        unsigned long *result;
                   2364:        struct packet *packet;
                   2365:        struct lease *lease;
                   2366:        struct client_state *client_state;
                   2367:        struct option_state *in_options;
                   2368:        struct option_state *cfg_options;
                   2369:        struct binding_scope **scope;
                   2370:        struct expression *expr;
                   2371: {
                   2372:        struct data_string data;
                   2373:        int status, sleft, sright;
                   2374: #if defined (NSUPDATE)
                   2375:        ns_updrec *nut;
                   2376:        ns_updque uq;
                   2377: #endif
                   2378:        struct expression *cur, *next;
                   2379:        struct binding *binding;
                   2380:        struct binding_value *bv;
                   2381:        unsigned long ileft, iright;
1.1.1.1 ! misho    2382:        int rc = 0;
1.1       misho    2383: 
                   2384:        switch (expr -> op) {
                   2385:              case expr_check:
                   2386:              case expr_equal:
                   2387:              case expr_not_equal:
                   2388:              case expr_regex_match:
                   2389:              case expr_iregex_match:
                   2390:              case expr_and:
                   2391:              case expr_or:
                   2392:              case expr_not:
                   2393:              case expr_match:
                   2394:              case expr_static:
                   2395:              case expr_known:
                   2396:              case expr_none:
                   2397:              case expr_exists:
                   2398:              case expr_variable_exists:
                   2399:                log_error ("Boolean opcode in evaluate_numeric_expression: %d",
                   2400:                      expr -> op);
                   2401:                return 0;
                   2402: 
                   2403:              case expr_substring:
                   2404:              case expr_suffix:
                   2405:              case expr_lcase:
                   2406:              case expr_ucase:
                   2407:              case expr_option:
                   2408:              case expr_hardware:
                   2409:              case expr_const_data:
                   2410:              case expr_packet:
                   2411:              case expr_concat:
                   2412:              case expr_encapsulate:
                   2413:              case expr_host_lookup:
                   2414:              case expr_encode_int8:
                   2415:              case expr_encode_int16:
                   2416:              case expr_encode_int32:
                   2417:              case expr_binary_to_ascii:
                   2418:              case expr_reverse:
                   2419:              case expr_filename:
                   2420:              case expr_sname:
                   2421:              case expr_pick_first_value:
                   2422:              case expr_host_decl_name:
                   2423:              case expr_config_option:
                   2424:              case expr_leased_address:
                   2425:              case expr_null:
                   2426:                log_error ("Data opcode in evaluate_numeric_expression: %d",
                   2427:                      expr -> op);
                   2428:                return 0;
                   2429: 
                   2430:              case expr_extract_int8:
                   2431:                memset (&data, 0, sizeof data);
                   2432:                status = evaluate_data_expression
                   2433:                        (&data, packet, lease, client_state, in_options,
                   2434:                         cfg_options, scope, expr -> data.extract_int, MDL);
                   2435:                if (status)
                   2436:                        *result = data.data [0];
                   2437: #if defined (DEBUG_EXPRESSIONS)
                   2438:                log_debug ("num: extract_int8 (%s) = %s",
                   2439:                      status ? print_hex_1 (data.len, data.data, 60) : "NULL",
                   2440:                      status ? print_dec_1 (*result) : "NULL" );
                   2441: #endif
                   2442:                if (status) data_string_forget (&data, MDL);
                   2443:                return status;
                   2444: 
                   2445:              case expr_extract_int16:
                   2446:                memset (&data, 0, sizeof data);
                   2447:                status = (evaluate_data_expression
                   2448:                          (&data, packet, lease, client_state, in_options,
                   2449:                           cfg_options, scope, expr -> data.extract_int, MDL));
1.1.1.1 ! misho    2450:                if (status && data.len >= 2) {
1.1       misho    2451:                        *result = getUShort (data.data);
1.1.1.1 ! misho    2452:                        rc = 1;
        !          2453:                }
1.1       misho    2454: #if defined (DEBUG_EXPRESSIONS)
1.1.1.1 ! misho    2455:                if (rc == 1) {
        !          2456:                        log_debug ("num: extract_int16 (%s) = %ld",
        !          2457:                                   print_hex_1(data.len, data.data, 60)
        !          2458:                                   *result);
        !          2459:                } else {
        !          2460:                        log_debug ("num: extract_int16 (NULL) = NULL");
        !          2461:                }
1.1       misho    2462: #endif
                   2463:                if (status) data_string_forget (&data, MDL);
1.1.1.1 ! misho    2464:                return (rc);
1.1       misho    2465: 
                   2466:              case expr_extract_int32:
                   2467:                memset (&data, 0, sizeof data);
                   2468:                status = (evaluate_data_expression
                   2469:                          (&data, packet, lease, client_state, in_options,
                   2470:                           cfg_options, scope, expr -> data.extract_int, MDL));
1.1.1.1 ! misho    2471:                if (status && data.len >= 4) {
1.1       misho    2472:                        *result = getULong (data.data);
1.1.1.1 ! misho    2473:                        rc = 1;
        !          2474:                }
1.1       misho    2475: #if defined (DEBUG_EXPRESSIONS)
1.1.1.1 ! misho    2476:                if (rc == 1) {
        !          2477:                        log_debug ("num: extract_int32 (%s) = %ld",
        !          2478:                                   print_hex_1 (data.len, data.data, 60),
        !          2479:                                   *result);
        !          2480:                } else {
        !          2481:                        log_debug ("num: extract_int32 (NULL) = NULL");
        !          2482:                }
1.1       misho    2483: #endif
                   2484:                if (status) data_string_forget (&data, MDL);
1.1.1.1 ! misho    2485:                return (rc);
1.1       misho    2486: 
                   2487:              case expr_const_int:
                   2488:                *result = expr -> data.const_int;
                   2489: #if defined (DEBUG_EXPRESSIONS)
                   2490:                log_debug ("number: CONSTANT = %ld", *result);
                   2491: #endif
                   2492:                return 1;
                   2493: 
                   2494:              case expr_lease_time:
                   2495:                if (!lease) {
                   2496:                        log_error ("data: leased_lease: not available");
                   2497:                        return 0;
                   2498:                }
                   2499:                if (lease -> ends < cur_time) {
                   2500:                        log_error ("%s %lu when it is now %lu",
                   2501:                                   "data: lease_time: lease ends at",
                   2502:                                   (long)(lease -> ends), (long)cur_time);
                   2503:                        return 0;
                   2504:                }
                   2505:                *result = lease -> ends - cur_time;
                   2506: #if defined (DEBUG_EXPRESSIONS)
                   2507:                log_debug ("number: lease-time = (%lu - %lu) = %ld",
                   2508:                           lease -> ends,
                   2509:                           cur_time, *result);
                   2510: #endif
                   2511:                return 1;
                   2512:  
                   2513:              case expr_dns_transaction:
                   2514: #if !defined (NSUPDATE)
                   2515:                return 0;
                   2516: #else
                   2517:                if (!resolver_inited) {
                   2518:                        minires_ninit (&resolver_state);
                   2519:                        resolver_inited = 1;
                   2520:                        resolver_state.retrans = 1;
                   2521:                        resolver_state.retry = 1;
                   2522:                }
                   2523:                ISC_LIST_INIT (uq);
                   2524:                cur = expr;
                   2525:                do {
                   2526:                    next = cur -> data.dns_transaction.cdr;
                   2527:                    nut = 0;
                   2528:                    status = (evaluate_dns_expression
                   2529:                              (&nut, packet,
                   2530:                               lease, client_state, in_options, cfg_options,
                   2531:                               scope, cur -> data.dns_transaction.car));
                   2532:                    if (!status)
                   2533:                            goto dns_bad;
                   2534:                    ISC_LIST_APPEND (uq, nut, r_link);
                   2535:                    cur = next;
                   2536:                } while (next);
                   2537: 
                   2538:                /* Do the update and record the error code, if there was
                   2539:                   an error; otherwise set it to NOERROR. */
                   2540:                *result = minires_nupdate (&resolver_state,
                   2541:                                           ISC_LIST_HEAD (uq));
                   2542:                status = 1;
                   2543: 
                   2544:                print_dns_status ((int)*result, &uq);
                   2545: 
                   2546:              dns_bad:
                   2547:                while (!ISC_LIST_EMPTY (uq)) {
                   2548:                        ns_updrec *tmp = ISC_LIST_HEAD (uq);
                   2549:                        ISC_LIST_UNLINK (uq, tmp, r_link);
                   2550:                        if (tmp -> r_data_ephem) {
                   2551:                                dfree (tmp -> r_data_ephem, MDL);
                   2552:                                tmp -> r_data = (unsigned char *)0;
                   2553:                                tmp -> r_data_ephem = (unsigned char *)0;
                   2554:                        }
                   2555:                        minires_freeupdrec (tmp);
                   2556:                }
                   2557:                return status;
                   2558: #endif /* NSUPDATE */
                   2559: 
                   2560:              case expr_variable_reference:
                   2561:                if (scope && *scope) {
                   2562:                    binding = find_binding (*scope, expr -> data.variable);
                   2563: 
                   2564:                    if (binding && binding -> value) {
                   2565:                        if (binding -> value -> type == binding_numeric) {
                   2566:                                *result = binding -> value -> value.intval;
                   2567:                            status = 1;
                   2568:                        } else {
                   2569:                                log_error ("binding type %d in %s.",
                   2570:                                           binding -> value -> type,
                   2571:                                           "evaluate_numeric_expression");
                   2572:                                status = 0;
                   2573:                        }
                   2574:                    } else
                   2575:                        status = 0;
                   2576:                } else
                   2577:                    status = 0;
                   2578: #if defined (DEBUG_EXPRESSIONS)
                   2579:                if (status)
                   2580:                        log_debug ("numeric: %s = %ld",
                   2581:                                   expr -> data.variable, *result);
                   2582:                else
                   2583:                        log_debug ("numeric: %s = NULL",
                   2584:                                   expr -> data.variable);
                   2585: #endif
                   2586:                return status;
                   2587: 
                   2588:              case expr_funcall:
                   2589:                bv = (struct binding_value *)0;
                   2590:                status = evaluate_expression (&bv, packet, lease,
                   2591:                                              client_state,
                   2592:                                              in_options, cfg_options,
                   2593:                                              scope, expr, MDL);
                   2594:                if (status) {
                   2595:                        if (bv -> type != binding_numeric)
                   2596:                                log_error ("%s() returned type %d in %s.",
                   2597:                                           expr -> data.funcall.name,
                   2598:                                           bv -> type,
                   2599:                                           "evaluate_numeric_expression");
                   2600:                        else
                   2601:                                *result = bv -> value.intval;
                   2602:                        binding_value_dereference (&bv, MDL);
                   2603:                }
                   2604: #if defined (DEBUG_EXPRESSIONS)
                   2605:                log_debug ("data: %s = %ld", expr -> data.funcall.name,
                   2606:                           status ? *result : 0);
                   2607: #endif
                   2608:                break;
                   2609: 
                   2610:              case expr_add:
                   2611:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
                   2612:                                                     client_state,
                   2613:                                                     in_options, cfg_options,
                   2614:                                                     scope,
                   2615:                                                     expr -> data.and [0]);
                   2616:                sright = evaluate_numeric_expression (&iright, packet, lease,
                   2617:                                                      client_state,
                   2618:                                                      in_options, cfg_options,
                   2619:                                                      scope,
                   2620:                                                      expr -> data.and [1]);
                   2621: 
                   2622: #if defined (DEBUG_EXPRESSIONS)
                   2623:                if (sleft && sright)
                   2624:                        log_debug ("num: %ld + %ld = %ld",
                   2625:                                   ileft, iright, ileft + iright);
                   2626:                else if (sleft)
                   2627:                        log_debug ("num: %ld + NULL = NULL", ileft);
                   2628:                else
                   2629:                        log_debug ("num: NULL + %ld = NULL", iright);
                   2630: #endif
                   2631:                if (sleft && sright) {
                   2632:                        *result = ileft + iright;
                   2633:                        return 1;
                   2634:                }
                   2635:                return 0;
                   2636: 
                   2637:              case expr_subtract:
                   2638:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
                   2639:                                                     client_state,
                   2640:                                                     in_options, cfg_options,
                   2641:                                                     scope,
                   2642:                                                     expr -> data.and [0]);
                   2643:                sright = evaluate_numeric_expression (&iright, packet, lease,
                   2644:                                                      client_state,
                   2645:                                                      in_options, cfg_options,
                   2646:                                                      scope,
                   2647:                                                      expr -> data.and [1]);
                   2648: 
                   2649: #if defined (DEBUG_EXPRESSIONS)
                   2650:                if (sleft && sright)
                   2651:                        log_debug ("num: %ld - %ld = %ld",
                   2652:                                   ileft, iright, ileft - iright);
                   2653:                else if (sleft)
                   2654:                        log_debug ("num: %ld - NULL = NULL", ileft);
                   2655:                else
                   2656:                        log_debug ("num: NULL - %ld = NULL", iright);
                   2657: #endif
                   2658:                if (sleft && sright) {
                   2659:                        *result = ileft - iright;
                   2660:                        return 1;
                   2661:                }
                   2662:                return 0;
                   2663: 
                   2664:              case expr_multiply:
                   2665:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
                   2666:                                                     client_state,
                   2667:                                                     in_options, cfg_options,
                   2668:                                                     scope,
                   2669:                                                     expr -> data.and [0]);
                   2670:                sright = evaluate_numeric_expression (&iright, packet, lease,
                   2671:                                                      client_state,
                   2672:                                                      in_options, cfg_options,
                   2673:                                                      scope,
                   2674:                                                      expr -> data.and [1]);
                   2675: 
                   2676: #if defined (DEBUG_EXPRESSIONS)
                   2677:                if (sleft && sright)
                   2678:                        log_debug ("num: %ld * %ld = %ld",
                   2679:                                   ileft, iright, ileft * iright);
                   2680:                else if (sleft)
                   2681:                        log_debug ("num: %ld * NULL = NULL", ileft);
                   2682:                else
                   2683:                        log_debug ("num: NULL * %ld = NULL", iright);
                   2684: #endif
                   2685:                if (sleft && sright) {
                   2686:                        *result = ileft * iright;
                   2687:                        return 1;
                   2688:                }
                   2689:                return 0;
                   2690: 
                   2691:              case expr_divide:
                   2692:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
                   2693:                                                     client_state,
                   2694:                                                     in_options, cfg_options,
                   2695:                                                     scope,
                   2696:                                                     expr -> data.and [0]);
                   2697:                sright = evaluate_numeric_expression (&iright, packet, lease,
                   2698:                                                      client_state,
                   2699:                                                      in_options, cfg_options,
                   2700:                                                      scope,
                   2701:                                                      expr -> data.and [1]);
                   2702: 
                   2703: #if defined (DEBUG_EXPRESSIONS)
                   2704:                if (sleft && sright) {
                   2705:                        if (iright != 0)
                   2706:                                log_debug ("num: %ld / %ld = %ld",
                   2707:                                           ileft, iright, ileft / iright);
                   2708:                        else
                   2709:                                log_debug ("num: %ld / %ld = NULL",
                   2710:                                           ileft, iright);
                   2711:                } else if (sleft)
                   2712:                        log_debug ("num: %ld / NULL = NULL", ileft);
                   2713:                else
                   2714:                        log_debug ("num: NULL / %ld = NULL", iright);
                   2715: #endif
                   2716:                if (sleft && sright && iright) {
                   2717:                        *result = ileft / iright;
                   2718:                        return 1;
                   2719:                }
                   2720:                return 0;
                   2721: 
                   2722:              case expr_remainder:
                   2723:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
                   2724:                                                     client_state,
                   2725:                                                     in_options, cfg_options,
                   2726:                                                     scope,
                   2727:                                                     expr -> data.and [0]);
                   2728:                sright = evaluate_numeric_expression (&iright, packet, lease,
                   2729:                                                      client_state,
                   2730:                                                      in_options, cfg_options,
                   2731:                                                      scope,
                   2732:                                                      expr -> data.and [1]);
                   2733: 
                   2734: #if defined (DEBUG_EXPRESSIONS)
                   2735:                if (sleft && sright) {
                   2736:                        if (iright != 0)
                   2737:                                log_debug ("num: %ld %% %ld = %ld",
                   2738:                                           ileft, iright, ileft % iright);
                   2739:                        else
                   2740:                                log_debug ("num: %ld %% %ld = NULL",
                   2741:                                           ileft, iright);
                   2742:                } else if (sleft)
                   2743:                        log_debug ("num: %ld %% NULL = NULL", ileft);
                   2744:                else
                   2745:                        log_debug ("num: NULL %% %ld = NULL", iright);
                   2746: #endif
                   2747:                if (sleft && sright && iright) {
                   2748:                        *result = ileft % iright;
                   2749:                        return 1;
                   2750:                }
                   2751:                return 0;
                   2752: 
                   2753:              case expr_binary_and:
                   2754:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
                   2755:                                                     client_state,
                   2756:                                                     in_options, cfg_options,
                   2757:                                                     scope,
                   2758:                                                     expr -> data.and [0]);
                   2759:                sright = evaluate_numeric_expression (&iright, packet, lease,
                   2760:                                                      client_state,
                   2761:                                                      in_options, cfg_options,
                   2762:                                                      scope,
                   2763:                                                      expr -> data.and [1]);
                   2764: 
                   2765: #if defined (DEBUG_EXPRESSIONS)
                   2766:                if (sleft && sright)
                   2767:                        log_debug ("num: %ld | %ld = %ld",
                   2768:                                   ileft, iright, ileft & iright);
                   2769:                else if (sleft)
                   2770:                        log_debug ("num: %ld & NULL = NULL", ileft);
                   2771:                else
                   2772:                        log_debug ("num: NULL & %ld = NULL", iright);
                   2773: #endif
                   2774:                if (sleft && sright) {
                   2775:                        *result = ileft & iright;
                   2776:                        return 1;
                   2777:                }
                   2778:                return 0;
                   2779: 
                   2780:              case expr_binary_or:
                   2781:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
                   2782:                                                     client_state,
                   2783:                                                     in_options, cfg_options,
                   2784:                                                     scope,
                   2785:                                                     expr -> data.and [0]);
                   2786:                sright = evaluate_numeric_expression (&iright, packet, lease,
                   2787:                                                      client_state,
                   2788:                                                      in_options, cfg_options,
                   2789:                                                      scope,
                   2790:                                                      expr -> data.and [1]);
                   2791: 
                   2792: #if defined (DEBUG_EXPRESSIONS)
                   2793:                if (sleft && sright)
                   2794:                        log_debug ("num: %ld | %ld = %ld",
                   2795:                                   ileft, iright, ileft | iright);
                   2796:                else if (sleft)
                   2797:                        log_debug ("num: %ld | NULL = NULL", ileft);
                   2798:                else
                   2799:                        log_debug ("num: NULL | %ld = NULL", iright);
                   2800: #endif
                   2801:                if (sleft && sright) {
                   2802:                        *result = ileft | iright;
                   2803:                        return 1;
                   2804:                }
                   2805:                return 0;
                   2806: 
                   2807:              case expr_binary_xor:
                   2808:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
                   2809:                                                     client_state,
                   2810:                                                     in_options, cfg_options,
                   2811:                                                     scope,
                   2812:                                                     expr -> data.and [0]);
                   2813:                sright = evaluate_numeric_expression (&iright, packet, lease,
                   2814:                                                      client_state,
                   2815:                                                      in_options, cfg_options,
                   2816:                                                      scope,
                   2817:                                                      expr -> data.and [1]);
                   2818: 
                   2819: #if defined (DEBUG_EXPRESSIONS)
                   2820:                if (sleft && sright)
                   2821:                        log_debug ("num: %ld ^ %ld = %ld",
                   2822:                                   ileft, iright, ileft ^ iright);
                   2823:                else if (sleft)
                   2824:                        log_debug ("num: %ld ^ NULL = NULL", ileft);
                   2825:                else
                   2826:                        log_debug ("num: NULL ^ %ld = NULL", iright);
                   2827: #endif
                   2828:                if (sleft && sright) {
                   2829:                        *result = ileft ^ iright;
                   2830:                        return 1;
                   2831:                }
                   2832:                return 0;
                   2833: 
                   2834:              case expr_client_state:
                   2835:                if (client_state) {
                   2836: #if defined (DEBUG_EXPRESSIONS)
                   2837:                        log_debug ("num: client-state = %d",
                   2838:                                   client_state -> state);
                   2839: #endif
                   2840:                        *result = client_state -> state;
                   2841:                        return 1;
                   2842:                } else {
                   2843: #if defined (DEBUG_EXPRESSIONS)
                   2844:                        log_debug ("num: client-state = NULL");
                   2845: #endif
                   2846:                        return 0;
                   2847:                }
                   2848: 
                   2849:              case expr_ns_add:
                   2850:              case expr_ns_delete:
                   2851:              case expr_ns_exists:
                   2852:              case expr_ns_not_exists:
                   2853:                log_error ("dns opcode in evaluate_numeric_expression: %d",
                   2854:                      expr -> op);
                   2855:                return 0;
                   2856: 
                   2857:              case expr_function:
                   2858:                log_error ("function definition in evaluate_numeric_expr");
                   2859:                return 0;
                   2860: 
                   2861:              case expr_arg:
                   2862:                break;
                   2863: 
                   2864:              default:
                   2865:                log_fatal("Impossible case at %s:%d.  Undefined operator "
                   2866:                          "%d.", MDL, expr->op);
                   2867:                break;
                   2868:        }
                   2869: 
                   2870:        log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op);
                   2871:        return 0;
                   2872: }
                   2873: 
                   2874: /* Return data hanging off of an option cache structure, or if there
                   2875:    isn't any, evaluate the expression hanging off of it and return the
                   2876:    result of that evaluation.   There should never be both an expression
                   2877:    and a valid data_string. */
                   2878: 
                   2879: int evaluate_option_cache (result, packet, lease, client_state,
                   2880:                           in_options, cfg_options, scope, oc, file, line)
                   2881:        struct data_string *result;
                   2882:        struct packet *packet;
                   2883:        struct lease *lease;
                   2884:        struct client_state *client_state;
                   2885:        struct option_state *in_options;
                   2886:        struct option_state *cfg_options;
                   2887:        struct binding_scope **scope;
                   2888:        struct option_cache *oc;
                   2889:        const char *file;
                   2890:        int line;
                   2891: {
                   2892:        if (oc->data.data != NULL) {
                   2893:                data_string_copy (result, &oc -> data, file, line);
                   2894:                return 1;
                   2895:        }
                   2896:        if (!oc -> expression)
                   2897:                return 0;
                   2898:        return evaluate_data_expression (result, packet, lease, client_state,
                   2899:                                         in_options, cfg_options, scope,
                   2900:                                         oc -> expression, file, line);
                   2901: }
                   2902: 
                   2903: /* Evaluate an option cache and extract a boolean from the result,
                   2904:    returning the boolean.   Return false if there is no data. */
                   2905: 
                   2906: int evaluate_boolean_option_cache (ignorep, packet,
                   2907:                                   lease, client_state, in_options,
                   2908:                                   cfg_options, scope, oc, file, line)
                   2909:        int *ignorep;
                   2910:        struct packet *packet;
                   2911:        struct lease *lease;
                   2912:        struct client_state *client_state;
                   2913:        struct option_state *in_options;
                   2914:        struct option_state *cfg_options;
                   2915:        struct binding_scope **scope;
                   2916:        struct option_cache *oc;
                   2917:        const char *file;
                   2918:        int line;
                   2919: {
                   2920:        struct data_string ds;
                   2921:        int result;
                   2922: 
                   2923:        /* So that we can be called with option_lookup as an argument. */
                   2924:        if (!oc || !in_options)
                   2925:                return 0;
                   2926:        
                   2927:        memset (&ds, 0, sizeof ds);
                   2928:        if (!evaluate_option_cache (&ds, packet,
                   2929:                                    lease, client_state, in_options,
                   2930:                                    cfg_options, scope, oc, file, line))
                   2931:                return 0;
                   2932: 
                   2933:        /* The boolean option cache is actually a trinary value.  Zero is
                   2934:         * off, one is on, and 2 is 'ignore'.
                   2935:         */
                   2936:        if (ds.len) {
                   2937:                result = ds.data [0];
                   2938:                if (result == 2) {
                   2939:                        result = 0;
                   2940:                        if (ignorep != NULL)
                   2941:                                *ignorep = 1;
                   2942:                } else if (ignorep != NULL)
                   2943:                        *ignorep = 0;
                   2944:        } else
                   2945:                result = 0;
                   2946:        data_string_forget (&ds, MDL);
                   2947:        return result;
                   2948: }
                   2949:                
                   2950: 
                   2951: /* Evaluate a boolean expression and return the result of the evaluation,
                   2952:    or FALSE if it failed. */
                   2953: 
                   2954: int evaluate_boolean_expression_result (ignorep, packet, lease, client_state,
                   2955:                                        in_options, cfg_options, scope, expr)
                   2956:        int *ignorep;
                   2957:        struct packet *packet;
                   2958:        struct lease *lease;
                   2959:        struct client_state *client_state;
                   2960:        struct option_state *in_options;
                   2961:        struct option_state *cfg_options;
                   2962:        struct binding_scope **scope;
                   2963:        struct expression *expr;
                   2964: {
                   2965:        int result;
                   2966: 
                   2967:        /* So that we can be called with option_lookup as an argument. */
                   2968:        if (!expr)
                   2969:                return 0;
                   2970:        
                   2971:        if (!evaluate_boolean_expression (&result, packet, lease, client_state,
                   2972:                                          in_options, cfg_options,
                   2973:                                          scope, expr))
                   2974:                return 0;
                   2975: 
                   2976:        if (result == 2) {
                   2977:                *ignorep = 1;
                   2978:                result = 0;
                   2979:        } else
                   2980:                *ignorep = 0;
                   2981:        return result;
                   2982: }
                   2983:                
                   2984: 
                   2985: /* Dereference an expression node, and if the reference count goes to zero,
                   2986:    dereference any data it refers to, and then free it. */
                   2987: void expression_dereference (eptr, file, line)
                   2988:        struct expression **eptr;
                   2989:        const char *file;
                   2990:        int line;
                   2991: {
                   2992:        struct expression *expr = *eptr;
                   2993: 
                   2994:        /* Zero the pointer. */
                   2995:        *eptr = (struct expression *)0;
                   2996: 
                   2997:        /* Decrement the reference count.   If it's nonzero, we're
                   2998:           done. */
                   2999:        --(expr -> refcnt);
                   3000:        rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC);
                   3001:        if (expr -> refcnt > 0)
                   3002:                return;
                   3003:        if (expr -> refcnt < 0) {
                   3004:                log_error ("%s(%d): negative refcnt!", file, line);
                   3005: #if defined (DEBUG_RC_HISTORY)
                   3006:                dump_rc_history (expr);
                   3007: #endif
                   3008: #if defined (POINTER_DEBUG)
                   3009:                abort ();
                   3010: #else
                   3011:                return;
                   3012: #endif
                   3013:        }
                   3014: 
                   3015:        /* Dereference subexpressions. */
                   3016:        switch (expr -> op) {
                   3017:                /* All the binary operators can be handled the same way. */
                   3018:              case expr_equal:
                   3019:              case expr_not_equal:
                   3020:              case expr_regex_match:
                   3021:              case expr_iregex_match:
                   3022:              case expr_concat:
                   3023:              case expr_and:
                   3024:              case expr_or:
                   3025:              case expr_add:
                   3026:              case expr_subtract:
                   3027:              case expr_multiply:
                   3028:              case expr_divide:
                   3029:              case expr_remainder:
                   3030:              case expr_binary_and:
                   3031:              case expr_binary_or:
                   3032:              case expr_binary_xor:
                   3033:              case expr_client_state:
                   3034:                if (expr -> data.equal [0])
                   3035:                        expression_dereference (&expr -> data.equal [0],
                   3036:                                                file, line);
                   3037:                if (expr -> data.equal [1])
                   3038:                        expression_dereference (&expr -> data.equal [1],
                   3039:                                                file, line);
                   3040:                break;
                   3041: 
                   3042:              case expr_substring:
                   3043:                if (expr -> data.substring.expr)
                   3044:                        expression_dereference (&expr -> data.substring.expr,
                   3045:                                                file, line);
                   3046:                if (expr -> data.substring.offset)
                   3047:                        expression_dereference (&expr -> data.substring.offset,
                   3048:                                                file, line);
                   3049:                if (expr -> data.substring.len)
                   3050:                        expression_dereference (&expr -> data.substring.len,
                   3051:                                                file, line);
                   3052:                break;
                   3053: 
                   3054:              case expr_suffix:
                   3055:                if (expr -> data.suffix.expr)
                   3056:                        expression_dereference (&expr -> data.suffix.expr,
                   3057:                                                file, line);
                   3058:                if (expr -> data.suffix.len)
                   3059:                        expression_dereference (&expr -> data.suffix.len,
                   3060:                                                file, line);
                   3061:                break;
                   3062: 
                   3063:              case expr_lcase:
                   3064:                if (expr->data.lcase)
                   3065:                        expression_dereference(&expr->data.lcase, MDL);
                   3066:                break;
                   3067: 
                   3068:              case expr_ucase:
                   3069:                if (expr->data.ucase)
                   3070:                        expression_dereference(&expr->data.ucase, MDL);
                   3071:                break;
                   3072: 
                   3073:              case expr_not:
                   3074:                if (expr -> data.not)
                   3075:                        expression_dereference (&expr -> data.not, file, line);
                   3076:                break;
                   3077: 
                   3078:              case expr_packet:
                   3079:                if (expr -> data.packet.offset)
                   3080:                        expression_dereference (&expr -> data.packet.offset,
                   3081:                                                file, line);
                   3082:                if (expr -> data.packet.len)
                   3083:                        expression_dereference (&expr -> data.packet.len,
                   3084:                                                file, line);
                   3085:                break;
                   3086: 
                   3087:              case expr_extract_int8:
                   3088:              case expr_extract_int16:
                   3089:              case expr_extract_int32:
                   3090:                if (expr -> data.extract_int)
                   3091:                        expression_dereference (&expr -> data.extract_int,
                   3092:                                                file, line);
                   3093:                break;
                   3094: 
                   3095:              case expr_encode_int8:
                   3096:              case expr_encode_int16:
                   3097:              case expr_encode_int32:
                   3098:                if (expr -> data.encode_int)
                   3099:                        expression_dereference (&expr -> data.encode_int,
                   3100:                                                file, line);
                   3101:                break;
                   3102: 
                   3103:              case expr_encapsulate:
                   3104:              case expr_const_data:
                   3105:                data_string_forget (&expr -> data.const_data, file, line);
                   3106:                break;
                   3107: 
                   3108:              case expr_host_lookup:
                   3109:                if (expr -> data.host_lookup)
                   3110:                        dns_host_entry_dereference (&expr -> data.host_lookup,
                   3111:                                                    file, line);
                   3112:                break;
                   3113: 
                   3114:              case expr_binary_to_ascii:
                   3115:                if (expr -> data.b2a.base)
                   3116:                        expression_dereference (&expr -> data.b2a.base,
                   3117:                                                file, line);
                   3118:                if (expr -> data.b2a.width)
                   3119:                        expression_dereference (&expr -> data.b2a.width,
                   3120:                                                file, line);
                   3121:                if (expr -> data.b2a.separator)
                   3122:                        expression_dereference (&expr -> data.b2a.separator,
                   3123:                                                file, line);
                   3124:                if (expr -> data.b2a.buffer)
                   3125:                        expression_dereference (&expr -> data.b2a.buffer,
                   3126:                                                file, line);
                   3127:                break;
                   3128: 
                   3129:              case expr_pick_first_value:
                   3130:                if (expr -> data.pick_first_value.car)
                   3131:                    expression_dereference (&expr -> data.pick_first_value.car,
                   3132:                                            file, line);
                   3133:                if (expr -> data.pick_first_value.cdr)
                   3134:                    expression_dereference (&expr -> data.pick_first_value.cdr,
                   3135:                                            file, line);
                   3136:                break;
                   3137: 
                   3138:              case expr_reverse:
                   3139:                if (expr -> data.reverse.width)
                   3140:                        expression_dereference (&expr -> data.reverse.width,
                   3141:                                                file, line);
                   3142:                if (expr -> data.reverse.buffer)
                   3143:                        expression_dereference
                   3144:                                (&expr -> data.reverse.buffer, file, line);
                   3145:                break;
                   3146: 
                   3147:              case expr_dns_transaction:
                   3148:                if (expr -> data.dns_transaction.car)
                   3149:                    expression_dereference (&expr -> data.dns_transaction.car,
                   3150:                                            file, line);
                   3151:                if (expr -> data.dns_transaction.cdr)
                   3152:                    expression_dereference (&expr -> data.dns_transaction.cdr,
                   3153:                                            file, line);
                   3154:                break;
                   3155: 
                   3156:              case expr_ns_add:
                   3157:                if (expr -> data.ns_add.rrname)
                   3158:                    expression_dereference (&expr -> data.ns_add.rrname,
                   3159:                                            file, line);
                   3160:                if (expr -> data.ns_add.rrdata)
                   3161:                    expression_dereference (&expr -> data.ns_add.rrdata,
                   3162:                                            file, line);
                   3163:                if (expr -> data.ns_add.ttl)
                   3164:                    expression_dereference (&expr -> data.ns_add.ttl,
                   3165:                                            file, line);
                   3166:                break;
                   3167: 
                   3168:              case expr_ns_delete:
                   3169:              case expr_ns_exists:
                   3170:              case expr_ns_not_exists:
                   3171:                if (expr -> data.ns_delete.rrname)
                   3172:                    expression_dereference (&expr -> data.ns_delete.rrname,
                   3173:                                            file, line);
                   3174:                if (expr -> data.ns_delete.rrdata)
                   3175:                    expression_dereference (&expr -> data.ns_delete.rrdata,
                   3176:                                            file, line);
                   3177:                break;
                   3178: 
                   3179:              case expr_variable_reference:
                   3180:              case expr_variable_exists:
                   3181:                if (expr -> data.variable)
                   3182:                        dfree (expr -> data.variable, file, line);
                   3183:                break;
                   3184: 
                   3185:              case expr_funcall:
                   3186:                if (expr -> data.funcall.name)
                   3187:                        dfree (expr -> data.funcall.name, file, line);
                   3188:                if (expr -> data.funcall.arglist)
                   3189:                        expression_dereference (&expr -> data.funcall.arglist,
                   3190:                                                file, line);
                   3191:                break;
                   3192: 
                   3193:              case expr_arg:
                   3194:                if (expr -> data.arg.val)
                   3195:                        expression_dereference (&expr -> data.arg.val,
                   3196:                                                file, line);
                   3197:                if (expr -> data.arg.next)
                   3198:                        expression_dereference (&expr -> data.arg.next,
                   3199:                                                file, line);
                   3200:                break;
                   3201: 
                   3202:              case expr_function:
                   3203:                fundef_dereference (&expr -> data.func, file, line);
                   3204:                break;
                   3205: 
                   3206:                /* No subexpressions. */
                   3207:              case expr_leased_address:
                   3208:              case expr_lease_time:
                   3209:              case expr_filename:
                   3210:              case expr_sname:
                   3211:              case expr_const_int:
                   3212:              case expr_check:
                   3213:              case expr_option:
                   3214:              case expr_hardware:
                   3215:              case expr_exists:
                   3216:              case expr_known:
                   3217:              case expr_null:
                   3218:                break;
                   3219: 
                   3220:              default:
                   3221:                break;
                   3222:        }
                   3223:        free_expression (expr, MDL);
                   3224: }
                   3225: 
                   3226: int is_dns_expression (expr)
                   3227:        struct expression *expr;
                   3228: {
                   3229:       return (expr -> op == expr_ns_add ||
                   3230:              expr -> op == expr_ns_delete ||
                   3231:              expr -> op == expr_ns_exists ||
                   3232:              expr -> op == expr_ns_not_exists);
                   3233: }
                   3234: 
                   3235: int is_boolean_expression (expr)
                   3236:        struct expression *expr;
                   3237: {
                   3238:        return (expr -> op == expr_check ||
                   3239:                expr -> op == expr_exists ||
                   3240:                expr -> op == expr_variable_exists ||
                   3241:                expr -> op == expr_equal ||
                   3242:                expr -> op == expr_not_equal ||
                   3243:                expr->op == expr_regex_match ||
                   3244:                expr->op == expr_iregex_match ||
                   3245:                expr -> op == expr_and ||
                   3246:                expr -> op == expr_or ||
                   3247:                expr -> op == expr_not ||
                   3248:                expr -> op == expr_known ||
                   3249:                expr -> op == expr_static);
                   3250: }
                   3251: 
                   3252: int is_data_expression (expr)
                   3253:        struct expression *expr;
                   3254: {
                   3255:        return (expr->op == expr_substring ||
                   3256:                expr->op == expr_suffix ||
                   3257:                expr->op == expr_lcase ||
                   3258:                expr->op == expr_ucase ||
                   3259:                expr->op == expr_option ||
                   3260:                expr->op == expr_hardware ||
                   3261:                expr->op == expr_const_data ||
                   3262:                expr->op == expr_packet ||
                   3263:                expr->op == expr_concat ||
                   3264:                expr->op == expr_encapsulate ||
                   3265:                expr->op == expr_encode_int8 ||
                   3266:                expr->op == expr_encode_int16 ||
                   3267:                expr->op == expr_encode_int32 ||
                   3268:                expr->op == expr_host_lookup ||
                   3269:                expr->op == expr_binary_to_ascii ||
                   3270:                expr->op == expr_filename ||
                   3271:                expr->op == expr_sname ||
                   3272:                expr->op == expr_reverse ||
                   3273:                expr->op == expr_pick_first_value ||
                   3274:                expr->op == expr_host_decl_name ||
                   3275:                expr->op == expr_leased_address ||
                   3276:                expr->op == expr_config_option ||
                   3277:                expr->op == expr_null);
                   3278: }
                   3279: 
                   3280: int is_numeric_expression (expr)
                   3281:        struct expression *expr;
                   3282: {
                   3283:        return (expr -> op == expr_extract_int8 ||
                   3284:                expr -> op == expr_extract_int16 ||
                   3285:                expr -> op == expr_extract_int32 ||
                   3286:                expr -> op == expr_const_int ||
                   3287:                expr -> op == expr_lease_time ||
                   3288:                expr -> op == expr_dns_transaction ||
                   3289:                expr -> op == expr_add ||
                   3290:                expr -> op == expr_subtract ||
                   3291:                expr -> op == expr_multiply ||
                   3292:                expr -> op == expr_divide ||
                   3293:                expr -> op == expr_remainder ||
                   3294:                expr -> op == expr_binary_and ||
                   3295:                expr -> op == expr_binary_or ||
                   3296:                expr -> op == expr_binary_xor ||
                   3297:                expr -> op == expr_client_state);
                   3298: }
                   3299: 
                   3300: int is_compound_expression (expr)
                   3301:        struct expression *expr;
                   3302: {
                   3303:        return (expr -> op == expr_ns_add ||
                   3304:                expr -> op == expr_ns_delete ||
                   3305:                expr -> op == expr_ns_exists ||
                   3306:                expr -> op == expr_ns_not_exists ||
                   3307:                expr -> op == expr_substring ||
                   3308:                expr -> op == expr_suffix ||
                   3309:                expr -> op == expr_option ||
                   3310:                expr -> op == expr_concat ||
                   3311:                expr -> op == expr_encode_int8 ||
                   3312:                expr -> op == expr_encode_int16 ||
                   3313:                expr -> op == expr_encode_int32 ||
                   3314:                expr -> op == expr_binary_to_ascii ||
                   3315:                expr -> op == expr_reverse ||
                   3316:                expr -> op == expr_pick_first_value ||
                   3317:                expr -> op == expr_config_option ||
                   3318:                expr -> op == expr_extract_int8 ||
                   3319:                expr -> op == expr_extract_int16 ||
                   3320:                expr -> op == expr_extract_int32 ||
                   3321:                expr -> op == expr_dns_transaction);
                   3322: }
                   3323: 
                   3324: static int op_val (enum expr_op);
                   3325: 
                   3326: static int op_val (op)
                   3327:        enum expr_op op;
                   3328: {
                   3329:        switch (op) {
                   3330:              case expr_none:
                   3331:              case expr_match:
                   3332:              case expr_static:
                   3333:              case expr_check:
                   3334:              case expr_substring:
                   3335:              case expr_suffix:
                   3336:              case expr_lcase:
                   3337:              case expr_ucase:
                   3338:              case expr_concat:
                   3339:              case expr_encapsulate:
                   3340:              case expr_host_lookup:
                   3341:              case expr_not:
                   3342:              case expr_option:
                   3343:              case expr_hardware:
                   3344:              case expr_packet:
                   3345:              case expr_const_data:
                   3346:              case expr_extract_int8:
                   3347:              case expr_extract_int16:
                   3348:              case expr_extract_int32:
                   3349:              case expr_encode_int8:
                   3350:              case expr_encode_int16:
                   3351:              case expr_encode_int32:
                   3352:              case expr_const_int:
                   3353:              case expr_exists:
                   3354:              case expr_variable_exists:
                   3355:              case expr_known:
                   3356:              case expr_binary_to_ascii:
                   3357:              case expr_reverse:
                   3358:              case expr_filename:
                   3359:              case expr_sname:
                   3360:              case expr_pick_first_value:
                   3361:              case expr_host_decl_name:
                   3362:              case expr_config_option:
                   3363:              case expr_leased_address:
                   3364:              case expr_lease_time:
                   3365:              case expr_dns_transaction:
                   3366:              case expr_null:
                   3367:              case expr_variable_reference:
                   3368:              case expr_ns_add:
                   3369:              case expr_ns_delete:
                   3370:              case expr_ns_exists:
                   3371:              case expr_ns_not_exists:
                   3372:              case expr_arg:
                   3373:              case expr_funcall:
                   3374:              case expr_function:
                   3375:                /* XXXDPN: Need to assign sane precedences to these. */
                   3376:              case expr_binary_and:
                   3377:              case expr_binary_or:
                   3378:              case expr_binary_xor:
                   3379:              case expr_client_state:
                   3380:                return 100;
                   3381: 
                   3382:              case expr_equal:
                   3383:              case expr_not_equal:
                   3384:              case expr_regex_match:
                   3385:              case expr_iregex_match:
                   3386:                return 4;
                   3387: 
                   3388:              case expr_or:
                   3389:              case expr_and:
                   3390:                return 3;
                   3391: 
                   3392:              case expr_add:
                   3393:              case expr_subtract:
                   3394:                return 2;
                   3395: 
                   3396:              case expr_multiply:
                   3397:              case expr_divide:
                   3398:              case expr_remainder:
                   3399:                return 1;
                   3400:        }
                   3401:        return 100;
                   3402: }
                   3403: 
                   3404: int op_precedence (op1, op2)
                   3405:        enum expr_op op1, op2;
                   3406: {
                   3407:        return op_val (op1) - op_val (op2);
                   3408: }
                   3409: 
                   3410: enum expression_context expression_context (struct expression *expr)
                   3411: {
                   3412:        if (is_data_expression (expr))
                   3413:                return context_data;
                   3414:        if (is_numeric_expression (expr))
                   3415:                return context_numeric;
                   3416:        if (is_boolean_expression (expr))
                   3417:                return context_boolean;
                   3418:        if (is_dns_expression (expr))
                   3419:                return context_dns;
                   3420:        return context_any;
                   3421: }
                   3422: 
                   3423: enum expression_context op_context (op)
                   3424:        enum expr_op op;
                   3425: {
                   3426:        switch (op) {
                   3427: /* XXX Why aren't these specific? */
                   3428:              case expr_none:
                   3429:              case expr_match:
                   3430:              case expr_static:
                   3431:              case expr_check:
                   3432:              case expr_substring:
                   3433:              case expr_suffix:
                   3434:              case expr_lcase:
                   3435:              case expr_ucase:
                   3436:              case expr_concat:
                   3437:              case expr_encapsulate:
                   3438:              case expr_host_lookup:
                   3439:              case expr_not:
                   3440:              case expr_option:
                   3441:              case expr_hardware:
                   3442:              case expr_packet:
                   3443:              case expr_const_data:
                   3444:              case expr_extract_int8:
                   3445:              case expr_extract_int16:
                   3446:              case expr_extract_int32:
                   3447:              case expr_encode_int8:
                   3448:              case expr_encode_int16:
                   3449:              case expr_encode_int32:
                   3450:              case expr_const_int:
                   3451:              case expr_exists:
                   3452:              case expr_variable_exists:
                   3453:              case expr_known:
                   3454:              case expr_binary_to_ascii:
                   3455:              case expr_reverse:
                   3456:              case expr_filename:
                   3457:              case expr_sname:
                   3458:              case expr_pick_first_value:
                   3459:              case expr_host_decl_name:
                   3460:              case expr_config_option:
                   3461:              case expr_leased_address:
                   3462:              case expr_lease_time:
                   3463:              case expr_null:
                   3464:              case expr_variable_reference:
                   3465:              case expr_ns_add:
                   3466:              case expr_ns_delete:
                   3467:              case expr_ns_exists:
                   3468:              case expr_ns_not_exists:
                   3469:              case expr_dns_transaction:
                   3470:              case expr_arg:
                   3471:              case expr_funcall:
                   3472:              case expr_function:
                   3473:                return context_any;
                   3474: 
                   3475:              case expr_equal:
                   3476:              case expr_not_equal:
                   3477:              case expr_regex_match:
                   3478:              case expr_iregex_match:
                   3479:                return context_data;
                   3480: 
                   3481:              case expr_and:
                   3482:                return context_boolean;
                   3483: 
                   3484:              case expr_or:
                   3485:                return context_boolean;
                   3486: 
                   3487:              case expr_add:
                   3488:              case expr_subtract:
                   3489:              case expr_multiply:
                   3490:              case expr_divide:
                   3491:              case expr_remainder:
                   3492:              case expr_binary_and:
                   3493:              case expr_binary_or:
                   3494:              case expr_binary_xor:
                   3495:              case expr_client_state:
                   3496:                return context_numeric;
                   3497:        }
                   3498:        return context_any;
                   3499: }
                   3500: 
                   3501: int write_expression (file, expr, col, indent, firstp)
                   3502:        FILE *file;
                   3503:        struct expression *expr;
                   3504:        int col;
                   3505:        int indent;
                   3506:        int firstp;
                   3507: {
                   3508:        struct expression *e;
                   3509:        const char *s;
                   3510:        char obuf [65];
                   3511:        int scol;
                   3512:        int width;
                   3513: 
                   3514:        /* If this promises to be a fat expression, start a new line. */
                   3515:        if (!firstp && is_compound_expression (expr)) {
                   3516:                indent_spaces (file, indent);
                   3517:                col = indent;
                   3518:        }
                   3519: 
                   3520:        switch (expr -> op) {
                   3521:              case expr_none:
                   3522:                col = token_print_indent (file, col, indent, "", "", "null");
                   3523:                break;
                   3524:                
                   3525:              case expr_check:
                   3526:                col = token_print_indent (file, col, indent, "", "", "check");
                   3527:                col = token_print_indent_concat (file, col, indent,
                   3528:                                                 " ", "", "\"",
                   3529:                                                 expr -> data.check -> name,
                   3530:                                                 "\"", (char *)0);
                   3531:                break;
                   3532: 
                   3533:              case expr_regex_match:
                   3534:                s = "~=";
                   3535:                goto binary;
                   3536: 
                   3537:              case expr_iregex_match:
                   3538:                s = "~~";
                   3539:                goto binary;
                   3540: 
                   3541:              case expr_not_equal:
                   3542:                s = "!=";
                   3543:                goto binary;
                   3544: 
                   3545:              case expr_equal:
                   3546:                s = "=";
                   3547:              binary:
                   3548:                col = write_expression (file, expr -> data.equal [0],
                   3549:                                        col, indent, 1);
                   3550:                col = token_print_indent (file, col, indent, " ", " ", s);
                   3551:                col = write_expression (file, expr -> data.equal [1],
                   3552:                                        col, indent + 2, 0);
                   3553:                break;
                   3554: 
                   3555:              case expr_substring:
                   3556:                col = token_print_indent (file, col, indent, "", "",
                   3557:                                          "substring");
                   3558:                col = token_print_indent (file, col, indent, " ", "", "(");
                   3559:                scol = col;
                   3560:                col = write_expression (file, expr -> data.substring.expr,
                   3561:                                        col, scol, 1);
                   3562:                col = token_print_indent (file, col, indent, "", " ", ",");
                   3563:                col = write_expression (file, expr -> data.substring.offset,
                   3564:                                        col, indent, 0);
                   3565:                col = token_print_indent (file, col, scol, "", " ", ",");
                   3566:                col = write_expression (file, expr -> data.substring.len,
                   3567:                                        col, scol, 0);
                   3568:                col = token_print_indent (file, col, indent, "", "", ")");
                   3569:                break;
                   3570: 
                   3571:              case expr_suffix:
                   3572:                col = token_print_indent (file, col, indent, "", "", "suffix");
                   3573:                col = token_print_indent (file, col, indent, " ", "", "(");
                   3574:                scol = col;
                   3575:                col = write_expression (file, expr -> data.suffix.expr,
                   3576:                                        col, scol, 1);
                   3577:                col = token_print_indent (file, col, scol, "", " ", ",");
                   3578:                col = write_expression (file, expr -> data.suffix.len,
                   3579:                                        col, scol, 0);
                   3580:                col = token_print_indent (file, col, indent, "", "", ")");
                   3581: 
                   3582:              case expr_lcase:
                   3583:                col = token_print_indent(file, col, indent, "", "", "lcase");
                   3584:                col = token_print_indent(file, col, indent, " ", "", "(");
                   3585:                scol = col;
                   3586:                col = write_expression(file, expr->data.lcase, col, scol, 1);
                   3587:                col = token_print_indent(file, col, indent, "", "", ")");
                   3588:                break;
                   3589: 
                   3590:              case expr_ucase:
                   3591:                col = token_print_indent(file, col, indent, "", "", "ucase");
                   3592:                col = token_print_indent(file, col, indent, " ", "", "(");
                   3593:                scol = col;
                   3594:                col = write_expression(file, expr->data.ucase, col, scol, 1);
                   3595:                col = token_print_indent(file, col, indent, "", "", ")");
                   3596:                break;
                   3597: 
                   3598:              case expr_concat:
                   3599:                e = expr;
                   3600:                col = token_print_indent (file, col, indent, "", "",
                   3601:                                          "concat");
                   3602:                col = token_print_indent (file, col, indent, " ", "", "(");
                   3603:                scol = col;
                   3604:                firstp = 1;
                   3605:              concat_again:
                   3606:                col = write_expression (file, e -> data.concat [0],
                   3607:                                        col, scol, firstp);
                   3608:                firstp = 0;
                   3609:                if (!e -> data.concat [1])
                   3610:                        goto no_concat_cdr;
                   3611:                col = token_print_indent (file, col, scol, "", " ", ",");
                   3612:                if (e -> data.concat [1] -> op == expr_concat) {
                   3613:                        e = e -> data.concat [1];
                   3614:                        goto concat_again;
                   3615:                }
                   3616:                col = write_expression (file, e -> data.concat [1],
                   3617:                                        col, scol, 0);
                   3618:              no_concat_cdr:
                   3619:                col = token_print_indent (file, col, indent, "", "", ")");
                   3620:                break;
                   3621: 
                   3622:              case expr_host_lookup:
                   3623:                col = token_print_indent (file, col, indent, "", "",
                   3624:                                          "gethostbyname");
                   3625:                col = token_print_indent (file, col, indent, " ", "", "(");
                   3626:                col = token_print_indent_concat
                   3627:                        (file, col, indent, "", "",
                   3628:                         "\"", expr -> data.host_lookup -> hostname, "\"",
                   3629:                         (char *)0);
                   3630:                col = token_print_indent (file, col, indent, "", "", ")");
                   3631:                break;
                   3632: 
                   3633:              case expr_add:
                   3634:                s = "+";
                   3635:                goto binary;
                   3636: 
                   3637:              case expr_subtract:
                   3638:                s = "-";
                   3639:                goto binary;
                   3640: 
                   3641:              case expr_multiply:
                   3642:                s = "*";
                   3643:                goto binary;
                   3644: 
                   3645:              case expr_divide:
                   3646:                s = "/";
                   3647:                goto binary;
                   3648: 
                   3649:              case expr_remainder:
                   3650:                s = "%";
                   3651:                goto binary;
                   3652: 
                   3653:              case expr_binary_and:
                   3654:                s = "&";
                   3655:                goto binary;
                   3656: 
                   3657:              case expr_binary_or:
                   3658:                s = "|";
                   3659:                goto binary;
                   3660: 
                   3661:              case expr_binary_xor:
                   3662:                s = "^";
                   3663:                goto binary;
                   3664: 
                   3665:              case expr_and:
                   3666:                s = "and";
                   3667:                goto binary;
                   3668: 
                   3669:              case expr_or:
                   3670:                s = "or";
                   3671:                goto binary;
                   3672: 
                   3673:              case expr_not:
                   3674:                col = token_print_indent (file, col, indent, "", " ", "not");
                   3675:                col = write_expression (file,
                   3676:                                        expr -> data.not, col, indent + 2, 1);
                   3677:                break;
                   3678: 
                   3679:              case expr_option:
                   3680:                s = "option";
                   3681: 
                   3682:              print_option_name:
                   3683:                col = token_print_indent (file, col, indent, "", "", s);
                   3684: 
                   3685:                if (expr -> data.option -> universe != &dhcp_universe) {
                   3686:                        col = token_print_indent (file, col, indent,
                   3687:                                                  " ", "",
                   3688:                                                  (expr -> data.option -> 
                   3689:                                                   universe -> name));
                   3690:                        col = token_print_indent (file, col, indent, "", "",
                   3691:                                                  ".");
                   3692:                        col = token_print_indent (file, col, indent, "", "",
                   3693:                                                  expr -> data.option -> name);
                   3694:                } else {
                   3695:                        col = token_print_indent (file, col, indent, " ", "",
                   3696:                                                  expr -> data.option -> name);
                   3697:                }
                   3698:                break;
                   3699: 
                   3700:              case expr_hardware:       
                   3701:                col = token_print_indent (file, col, indent, "", "",
                   3702:                                          "hardware");
                   3703:                break;
                   3704: 
                   3705:              case expr_packet:
                   3706:                col = token_print_indent (file, col, indent, "", "",
                   3707:                                          "packet");
                   3708:                col = token_print_indent (file, col, indent, " ", "", "(");
                   3709:                scol = col;
                   3710:                col = write_expression (file, expr -> data.packet.offset,
                   3711:                                        col, indent, 1);
                   3712:                col = token_print_indent (file, col, scol, "", " ", ",");
                   3713:                col = write_expression (file, expr -> data.packet.len,
                   3714:                                        col, scol, 0);
                   3715:                col = token_print_indent (file, col, indent, "", "", ")");
                   3716:                break;
                   3717: 
                   3718:              case expr_const_data:
                   3719:                col = token_indent_data_string (file, col, indent, "", "",
                   3720:                                                &expr -> data.const_data);
                   3721:                break;
                   3722: 
                   3723:              case expr_extract_int8:
                   3724:                width = 8;
                   3725:              extract_int:
                   3726:                col = token_print_indent (file, col, indent, "", "",
                   3727:                                          "extract-int");
                   3728:                col = token_print_indent (file, col, indent, " ", "", "(");
                   3729:                scol = col;
                   3730:                col = write_expression (file, expr -> data.extract_int,
                   3731:                                        col, indent, 1);
                   3732:                col = token_print_indent (file, col, scol, "", " ", ",");
                   3733:                sprintf (obuf, "%d", width);
                   3734:                col = token_print_indent (file, col, scol, " ", "", obuf);
                   3735:                col = token_print_indent (file, col, indent, "", "", ")");
                   3736:                break;
                   3737: 
                   3738:              case expr_extract_int16:
                   3739:                width = 16;
                   3740:                goto extract_int;
                   3741: 
                   3742:              case expr_extract_int32:
                   3743:                width = 32;
                   3744:                goto extract_int;
                   3745: 
                   3746:              case expr_encode_int8:
                   3747:                width = 8;
                   3748:              encode_int:
                   3749:                col = token_print_indent (file, col, indent, "", "",
                   3750:                                          "encode-int");
                   3751:                col = token_print_indent (file, col, indent, " ", "", "(");
                   3752:                scol = col;
                   3753:                col = write_expression (file, expr -> data.extract_int,
                   3754:                                        col, indent, 1);
                   3755:                col = token_print_indent (file, col, scol, "", " ", ",");
                   3756:                sprintf (obuf, "%d", width);
                   3757:                col = token_print_indent (file, col, scol, " ", "", obuf);
                   3758:                col = token_print_indent (file, col, indent, "", "",
                   3759:                                          ")");
                   3760:                break;
                   3761: 
                   3762:              case expr_encode_int16:
                   3763:                width = 16;
                   3764:                goto encode_int;
                   3765: 
                   3766:              case expr_encode_int32:
                   3767:                width = 32;
                   3768:                goto encode_int;
                   3769: 
                   3770:              case expr_const_int:
                   3771:                sprintf (obuf, "%lu", expr -> data.const_int);
                   3772:                col = token_print_indent (file, col, indent, "", "", obuf);
                   3773:                break;
                   3774: 
                   3775:              case expr_exists:
                   3776:                s = "exists";
                   3777:                goto print_option_name;
                   3778: 
                   3779:              case expr_encapsulate:
                   3780:                col = token_print_indent (file, col, indent, "", "",
                   3781:                                          "encapsulate");
                   3782:                col = token_indent_data_string (file, col, indent, " ", "",
                   3783:                                                &expr -> data.encapsulate);
                   3784:                break;
                   3785: 
                   3786:              case expr_known:
                   3787:                col = token_print_indent (file, col, indent, "", "", "known");
                   3788:                break;
                   3789: 
                   3790:              case expr_reverse:
                   3791:                col = token_print_indent (file, col, indent, "", "",
                   3792:                                          "reverse");
                   3793:                col = token_print_indent (file, col, indent, " ", "", "(");
                   3794:                scol = col;
                   3795:                col = write_expression (file, expr -> data.reverse.width,
                   3796:                                        col, scol, 1);
                   3797:                col = token_print_indent (file, col, scol, "", " ", ",");
                   3798:                col = write_expression (file, expr -> data.reverse.buffer,
                   3799:                                        col, scol, 0);
                   3800:                col = token_print_indent (file, col, indent, "", "",
                   3801:                                          ")");
                   3802:                break;
                   3803: 
                   3804:              case expr_leased_address:
                   3805:                col = token_print_indent (file, col, indent, "", "",
                   3806:                                          "leased-address");
                   3807:                break;
                   3808: 
                   3809:              case expr_client_state:
                   3810:                col = token_print_indent (file, col, indent, "", "",
                   3811:                                          "client-state");
                   3812:                break;
                   3813: 
                   3814:              case expr_binary_to_ascii:
                   3815:                col = token_print_indent (file, col, indent, "", "",
                   3816:                                          "binary-to-ascii");
                   3817:                col = token_print_indent (file, col, indent, " ", "",
                   3818:                                          "(");
                   3819:                scol = col;
                   3820:                col = write_expression (file, expr -> data.b2a.base,
                   3821:                                        col, scol, 1);
                   3822:                col = token_print_indent (file, col, scol, "", " ",
                   3823:                                          ",");
                   3824:                col = write_expression (file, expr -> data.b2a.width,
                   3825:                                        col, scol, 0);
                   3826:                col = token_print_indent (file, col, scol, "", " ",
                   3827:                                          ",");
                   3828:                col = write_expression (file, expr -> data.b2a.separator,
                   3829:                                        col, scol, 0);
                   3830:                col = token_print_indent (file, col, scol, "", " ",
                   3831:                                          ",");
                   3832:                col = write_expression (file, expr -> data.b2a.buffer,
                   3833:                                        col, scol, 0);
                   3834:                col = token_print_indent (file, col, indent, "", "",
                   3835:                                          ")");
                   3836:                break;
                   3837: 
                   3838:              case expr_config_option:
                   3839:                s = "config-option";
                   3840:                goto print_option_name;
                   3841: 
                   3842:              case expr_host_decl_name:
                   3843:                col = token_print_indent (file, col, indent, "", "",
                   3844:                                          "host-decl-name");
                   3845:                break;
                   3846: 
                   3847:              case expr_pick_first_value:
                   3848:                e = expr;
                   3849:                col = token_print_indent (file, col, indent, "", "",
                   3850:                                          "concat");
                   3851:                col = token_print_indent (file, col, indent, " ", "",
                   3852:                                          "(");
                   3853:                scol = col;
                   3854:                firstp = 1;
                   3855:              pick_again:
                   3856:                col = write_expression (file,
                   3857:                                        e -> data.pick_first_value.car,
                   3858:                                        col, scol, firstp);
                   3859:                firstp = 0;
                   3860:                /* We're being very lisp-like right now - instead of
                   3861:                    representing this expression as (first middle . last) we're
                   3862:                    representing it as (first middle last), which means that the
                   3863:                    tail cdr is always nil.  Apologies to non-wisp-lizards - may
                   3864:                    this obscure way of describing the problem motivate you to
                   3865:                    learn more about the one true computing language. */
                   3866:                if (!e -> data.pick_first_value.cdr)
                   3867:                        goto no_pick_cdr;
                   3868:                col = token_print_indent (file, col, scol, "", " ",
                   3869:                                          ",");
                   3870:                if (e -> data.pick_first_value.cdr -> op ==
                   3871:                    expr_pick_first_value) {
                   3872:                        e = e -> data.pick_first_value.cdr;
                   3873:                        goto pick_again;
                   3874:                }
                   3875:                col = write_expression (file,
                   3876:                                        e -> data.pick_first_value.cdr,
                   3877:                                        col, scol, 0);
                   3878:              no_pick_cdr:
                   3879:                col = token_print_indent (file, col, indent, "", "",
                   3880:                                          ")");
                   3881:                break;
                   3882: 
                   3883:              case expr_lease_time:
                   3884:                col = token_print_indent (file, col, indent, "", "",
                   3885:                                          "lease-time");
                   3886:                break;
                   3887: 
                   3888:              case expr_dns_transaction:
                   3889:                col = token_print_indent (file, col, indent, "", "",
                   3890:                                          "ns-update");
                   3891:                col = token_print_indent (file, col, indent, " ", "",
                   3892:                                          "(");
                   3893:                scol = 0;
                   3894:                for (e = expr;
                   3895:                     e && e -> op == expr_dns_transaction;
                   3896:                     e = e -> data.dns_transaction.cdr) {
                   3897:                        if (!scol) {
                   3898:                                scol = col;
                   3899:                                firstp = 1;
                   3900:                        } else
                   3901:                                firstp = 0;
                   3902:                        col = write_expression (file,
                   3903:                                                e -> data.dns_transaction.car,
                   3904:                                                col, scol, firstp);
                   3905:                        if (e -> data.dns_transaction.cdr)
                   3906:                                col = token_print_indent (file, col, scol,
                   3907:                                                          "", " ", ",");
                   3908:                }
                   3909:                if (e)
                   3910:                        col = write_expression (file, e, col, scol, 0);
                   3911:                col = token_print_indent (file, col, indent, "", "", ")");
                   3912:                break;
                   3913: 
                   3914:              case expr_ns_add:
                   3915:                col = token_print_indent (file, col, indent, "", "",
                   3916:                                          "update");
                   3917:                col = token_print_indent (file, col, indent, " ", "",
                   3918:                                          "(");
                   3919:                scol = col;
                   3920:                sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
                   3921:                col = token_print_indent (file, col, scol, "", "", obuf);
                   3922:                col = token_print_indent (file, col, scol, "", " ",
                   3923:                                          ",");
                   3924:                sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
                   3925:                col = token_print_indent (file, col, scol, "", "", obuf);
                   3926:                col = token_print_indent (file, col, scol, "", " ",
                   3927:                                          ",");
                   3928:                col = write_expression (file, expr -> data.ns_add.rrname,
                   3929:                                        col, scol, 0);
                   3930:                col = token_print_indent (file, col, scol, "", " ",
                   3931:                                          ",");
                   3932:                col = write_expression (file, expr -> data.ns_add.rrdata,
                   3933:                                        col, scol, 0);
                   3934:                col = token_print_indent (file, col, scol, "", " ",
                   3935:                                          ",");
                   3936:                col = write_expression (file, expr -> data.ns_add.ttl,
                   3937:                                        col, scol, 0);
                   3938:                col = token_print_indent (file, col, indent, "", "",
                   3939:                                          ")");
                   3940:                break;
                   3941: 
                   3942:              case expr_ns_delete:
                   3943:                col = token_print_indent (file, col, indent, "", "",
                   3944:                                          "delete");
                   3945:                col = token_print_indent (file, col, indent, " ", "",
                   3946:                                          "(");
                   3947:              finish_ns_small:
                   3948:                scol = col;
                   3949:                sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
                   3950:                col = token_print_indent (file, col, scol, "", "", obuf);
                   3951:                col = token_print_indent (file, col, scol, "", " ",
                   3952:                                          ",");
                   3953:                sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
                   3954:                col = token_print_indent (file, col, scol, "", "", obuf);
                   3955:                col = token_print_indent (file, col, scol, "", " ",
                   3956:                                          ",");
                   3957:                col = write_expression (file, expr -> data.ns_add.rrname,
                   3958:                                        col, scol, 0);
                   3959:                col = token_print_indent (file, col, scol, "", " ",
                   3960:                                          ",");
                   3961:                col = write_expression (file, expr -> data.ns_add.rrdata,
                   3962:                                        col, scol, 0);
                   3963:                col = token_print_indent (file, col, indent, "", "",
                   3964:                                          ")");
                   3965:                break;
                   3966: 
                   3967:              case expr_ns_exists:
                   3968:                col = token_print_indent (file, col, indent, "", "",
                   3969:                                          "exists");
                   3970:                col = token_print_indent (file, col, indent, " ", "",
                   3971:                                          "(");
                   3972:                goto finish_ns_small;
                   3973: 
                   3974:              case expr_ns_not_exists:
                   3975:                col = token_print_indent (file, col, indent, "", "",
                   3976:                                          "not exists");
                   3977:                col = token_print_indent (file, col, indent, " ", "",
                   3978:                                          "(");
                   3979:                goto finish_ns_small;
                   3980: 
                   3981:              case expr_static:
                   3982:                col = token_print_indent (file, col, indent, "", "",
                   3983:                                          "static");
                   3984:                break;
                   3985: 
                   3986:              case expr_null:
                   3987:                col = token_print_indent (file, col, indent, "", "", "null");
                   3988:                break;
                   3989: 
                   3990:              case expr_variable_reference:
                   3991:                col = token_print_indent (file, indent, indent, "", "",
                   3992:                                          expr -> data.variable);
                   3993:                break;
                   3994: 
                   3995:              case expr_variable_exists:
                   3996:                col = token_print_indent (file, indent, indent, "", "",
                   3997:                                          "defined");
                   3998:                col = token_print_indent (file, col, indent, " ", "", "(");
                   3999:                col = token_print_indent (file, col, indent, "", "",
                   4000:                                          expr -> data.variable);
                   4001:                col = token_print_indent (file, col, indent, "", "", ")");
                   4002:                break;
                   4003: 
                   4004:              case expr_funcall:
                   4005:                col = token_print_indent(file, indent, indent, "", "",
                   4006:                                         expr->data.funcall.name);
                   4007:                col = token_print_indent(file, col, indent, " ", "", "(");
                   4008: 
                   4009:                firstp = 1;
                   4010:                e = expr->data.funcall.arglist;
                   4011:                while (e != NULL) {
                   4012:                        if (!firstp)
                   4013:                                col = token_print_indent(file, col, indent,
                   4014:                                                         "", " ", ",");
                   4015: 
                   4016:                        col = write_expression(file, e->data.arg.val, col,
                   4017:                                               indent, firstp);
                   4018:                        firstp = 0;
                   4019:                        e = e->data.arg.next;
                   4020:                }
                   4021: 
                   4022:                col = token_print_indent(file, col, indent, "", "", ")");
                   4023:                break;
                   4024: 
                   4025:              default:
                   4026:                log_fatal ("invalid expression type in print_expression: %d",
                   4027:                           expr -> op);
                   4028:        }
                   4029:        return col;
                   4030: }
                   4031: 
                   4032: struct binding *find_binding (struct binding_scope *scope, const char *name)
                   4033: {
                   4034:        struct binding *bp;
                   4035:        struct binding_scope *s;
                   4036: 
                   4037:        for (s = scope; s; s = s -> outer) {
                   4038:                for (bp = s -> bindings; bp; bp = bp -> next) {
                   4039:                        if (!strcasecmp (name, bp -> name)) {
                   4040:                                return bp;
                   4041:                        }
                   4042:                }
                   4043:        }
                   4044:        return (struct binding *)0;
                   4045: }
                   4046: 
                   4047: int free_bindings (struct binding_scope *scope, const char *file, int line)
                   4048: {
                   4049:        struct binding *bp, *next;
                   4050: 
                   4051:        for (bp = scope -> bindings; bp; bp = next) {
                   4052:                next = bp -> next;
                   4053:                if (bp -> name)
                   4054:                        dfree (bp -> name, file, line);
                   4055:                if (bp -> value)
                   4056:                        binding_value_dereference (&bp -> value, file, line);
                   4057:                dfree (bp, file, line);
                   4058:        }
                   4059:        scope -> bindings = (struct binding *)0;
                   4060:        return 1;
                   4061: }
                   4062: 
                   4063: int binding_scope_dereference (ptr, file, line)
                   4064:        struct binding_scope **ptr;
                   4065:        const char *file;
                   4066:        int line;
                   4067: {
                   4068:        struct binding_scope *binding_scope;
                   4069: 
                   4070:        if (!ptr || !*ptr) {
                   4071:                log_error ("%s(%d): null pointer", file, line);
                   4072: #if defined (POINTER_DEBUG)
                   4073:                abort ();
                   4074: #else
                   4075:                return 0;
                   4076: #endif
                   4077:        }
                   4078: 
                   4079:        binding_scope = *ptr;
                   4080:        *ptr = (struct binding_scope *)0;
                   4081:        --binding_scope -> refcnt;
                   4082:        rc_register (file, line, ptr,
                   4083:                     binding_scope, binding_scope -> refcnt, 1, RC_MISC);
                   4084:        if (binding_scope -> refcnt > 0)
                   4085:                return 1;
                   4086: 
                   4087:        if (binding_scope -> refcnt < 0) {
                   4088:                log_error ("%s(%d): negative refcnt!", file, line);
                   4089: #if defined (DEBUG_RC_HISTORY)
                   4090:                dump_rc_history (binding_scope);
                   4091: #endif
                   4092: #if defined (POINTER_DEBUG)
                   4093:                abort ();
                   4094: #else
                   4095:                return 0;
                   4096: #endif
                   4097:        }
                   4098: 
                   4099:        free_bindings (binding_scope, file, line);
                   4100:        if (binding_scope -> outer)
                   4101:                binding_scope_dereference (&binding_scope -> outer, MDL);
                   4102:        dfree (binding_scope, file, line);
                   4103:        return 1;
                   4104: }
                   4105: 
                   4106: int fundef_dereference (ptr, file, line)
                   4107:        struct fundef **ptr;
                   4108:        const char *file;
                   4109:        int line;
                   4110: {
                   4111:        struct fundef *bp = *ptr;
                   4112:        struct string_list *sp, *next;
                   4113: 
                   4114:        if (!ptr) {
                   4115:                log_error ("%s(%d): null pointer", file, line);
                   4116: #if defined (POINTER_DEBUG)
                   4117:                abort ();
                   4118: #else
                   4119:                return 0;
                   4120: #endif
                   4121:        }
                   4122: 
                   4123:        if (!bp) {
                   4124:                log_error ("%s(%d): null pointer", file, line);
                   4125: #if defined (POINTER_DEBUG)
                   4126:                abort ();
                   4127: #else
                   4128:                return 0;
                   4129: #endif
                   4130:        }
                   4131: 
                   4132:        bp -> refcnt--;
                   4133:        rc_register (file, line, ptr, bp, bp -> refcnt, 1, RC_MISC);
                   4134:        if (bp -> refcnt < 0) {
                   4135:                log_error ("%s(%d): negative refcnt!", file, line);
                   4136: #if defined (DEBUG_RC_HISTORY)
                   4137:                dump_rc_history (bp);
                   4138: #endif
                   4139: #if defined (POINTER_DEBUG)
                   4140:                abort ();
                   4141: #else
                   4142:                return 0;
                   4143: #endif
                   4144:        }
                   4145:        if (!bp -> refcnt) {
                   4146:                for (sp = bp -> args; sp; sp = next) {
                   4147:                        next = sp -> next;
                   4148:                        dfree (sp, file, line);
                   4149:                }
                   4150:                if (bp -> statements)
                   4151:                        executable_statement_dereference (&bp -> statements,
                   4152:                                                          file, line);
                   4153:                dfree (bp, file, line);
                   4154:        }
                   4155:        *ptr = (struct fundef *)0;
                   4156:        return 1;
                   4157: }
                   4158: 
                   4159: #if defined (NOTYET)           /* Post 3.0 final. */
                   4160: int data_subexpression_length (int *rv,
                   4161:                               struct expression *expr)
                   4162: {
                   4163:        int crhs, clhs, llhs, lrhs;
                   4164:        switch (expr -> op) {
                   4165:              case expr_substring:
                   4166:                if (expr -> data.substring.len &&
                   4167:                    expr -> data.substring.len -> op == expr_const_int) {
                   4168:                        (*rv =
                   4169:                         (int)expr -> data.substring.len -> data.const_int);
                   4170:                        return 1;
                   4171:                }
                   4172:                return 0;
                   4173: 
                   4174:              case expr_packet:
                   4175:              case expr_suffix:
                   4176:                if (expr -> data.suffix.len &&
                   4177:                    expr -> data.suffix.len -> op == expr_const_int) {
                   4178:                        (*rv =
                   4179:                         (int)expr -> data.suffix.len -> data.const_int);
                   4180:                        return 1;
                   4181:                }
                   4182:                return 0;
                   4183: 
                   4184:              case expr_lcase:
                   4185:                return data_subexpression_length(rv, expr->data.lcase);
                   4186: 
                   4187:              case expr_ucase:
                   4188:                return data_subexpression_length(rv, expr->data.ucase);
                   4189: 
                   4190:              case expr_concat:
                   4191:                clhs = data_subexpression_length (&llhs,
                   4192:                                                  expr -> data.concat [0]);
                   4193:                crhs = data_subexpression_length (&lrhs,
                   4194:                                                  expr -> data.concat [1]);
                   4195:                if (crhs == 0 || clhs == 0)
                   4196:                        return 0;
                   4197:                *rv = llhs + lrhs;
                   4198:                return 1;
                   4199:                break;
                   4200: 
                   4201:              case expr_hardware:
                   4202:                return 0;
                   4203: 
                   4204:              case expr_const_data:
                   4205:                *rv = expr -> data.const_data.len;
                   4206:                return 2;
                   4207: 
                   4208:              case expr_reverse:
                   4209:                return data_subexpression_length (rv,
                   4210:                                                  expr -> data.reverse.buffer);
                   4211: 
                   4212:              case expr_leased_address:
                   4213:              case expr_lease_time:
                   4214:                *rv = 4;
                   4215:                return 2;
                   4216: 
                   4217:              case expr_pick_first_value:
                   4218:                clhs = data_subexpression_length (&llhs,
                   4219:                                                  expr -> data.concat [0]);
                   4220:                crhs = data_subexpression_length (&lrhs,
                   4221:                                                  expr -> data.concat [1]);
                   4222:                if (crhs == 0 || clhs == 0)
                   4223:                        return 0;
                   4224:                if (llhs > lrhs)
                   4225:                        *rv = llhs;
                   4226:                else
                   4227:                        *rv = lrhs;
                   4228:                return 1;
                   4229:                        
                   4230:              case expr_binary_to_ascii:
                   4231:              case expr_config_option:
                   4232:              case expr_host_decl_name:
                   4233:              case expr_encapsulate:
                   4234:              case expr_filename:
                   4235:              case expr_sname:
                   4236:              case expr_host_lookup:
                   4237:              case expr_option:
                   4238:              case expr_none:
                   4239:              case expr_match:
                   4240:              case expr_check:
                   4241:              case expr_equal:
                   4242:              case expr_regex_match:
                   4243:              case expr_iregex_match:
                   4244:              case expr_and:
                   4245:              case expr_or:
                   4246:              case expr_not:
                   4247:              case expr_extract_int8:
                   4248:              case expr_extract_int16:
                   4249:              case expr_extract_int32:
                   4250:              case expr_encode_int8:
                   4251:              case expr_encode_int16:
                   4252:              case expr_encode_int32:
                   4253:              case expr_const_int:
                   4254:              case expr_exists:
                   4255:              case expr_known:
                   4256:              case expr_dns_transaction:
                   4257:              case expr_static:
                   4258:              case expr_ns_add:
                   4259:              case expr_ns_delete:
                   4260:              case expr_ns_exists:
                   4261:              case expr_ns_not_exists:
                   4262:              case expr_not_equal:
                   4263:              case expr_null:
                   4264:              case expr_variable_exists:
                   4265:              case expr_variable_reference:
                   4266:              case expr_arg:
                   4267:              case expr_funcall:
                   4268:              case expr_function:
                   4269:              case expr_add:
                   4270:              case expr_subtract:
                   4271:              case expr_multiply:
                   4272:              case expr_divide:
                   4273:              case expr_remainder:
                   4274:              case expr_binary_and:
                   4275:              case expr_binary_or:
                   4276:              case expr_binary_xor:
                   4277:              case expr_client_state:
                   4278:                return 0;
                   4279:        }
                   4280:        return 0;
                   4281: }
                   4282: 
                   4283: int expr_valid_for_context (struct expression *expr,
                   4284:                            enum expression_context context)
                   4285: {
                   4286:        /* We don't know at parse time what type of value a function may
                   4287:           return, so we can't flag an error on it. */
                   4288:        if (expr -> op == expr_funcall ||
                   4289:            expr -> op == expr_variable_reference)
                   4290:                return 1;
                   4291: 
                   4292:        switch (context) {
                   4293:              case context_any:
                   4294:                return 1;
                   4295: 
                   4296:              case context_boolean:
                   4297:                if (is_boolean_expression (expr))
                   4298:                        return 1;
                   4299:                return 0;
                   4300: 
                   4301:              case context_data:
                   4302:                if (is_data_expression (expr))
                   4303:                        return 1;
                   4304:                return 0;
                   4305: 
                   4306:              case context_numeric:
                   4307:                if (is_numeric_expression (expr))
                   4308:                        return 1;
                   4309:                return 0;
                   4310: 
                   4311:              case context_dns:
                   4312:                if (is_dns_expression (expr)) {
                   4313:                        return 1;
                   4314:                }
                   4315:                return 0;
                   4316: 
                   4317:              case context_data_or_numeric:
                   4318:                if (is_numeric_expression (expr) ||
                   4319:                    is_data_expression (expr)) {
                   4320:                        return 1;
                   4321:                }
                   4322:                return 0;
                   4323: 
                   4324:              case context_function:
                   4325:                if (expr -> op == expr_function)
                   4326:                        return 1;
                   4327:                return 0;
                   4328:        }
                   4329:        return 0;
                   4330: }
                   4331: #endif /* NOTYET */
                   4332: 
                   4333: struct binding *create_binding (struct binding_scope **scope, const char *name)
                   4334: {
                   4335:        struct binding *binding;
                   4336: 
                   4337:        if (!*scope) {
                   4338:                if (!binding_scope_allocate (scope, MDL))
                   4339:                        return (struct binding *)0;
                   4340:        }
                   4341: 
                   4342:        binding = find_binding (*scope, name);
                   4343:        if (!binding) {
                   4344:                binding = dmalloc (sizeof *binding, MDL);
                   4345:                if (!binding)
                   4346:                        return (struct binding *)0;
                   4347: 
                   4348:                memset (binding, 0, sizeof *binding);
                   4349:                binding -> name = dmalloc (strlen (name) + 1, MDL);
                   4350:                if (!binding -> name) {
                   4351:                        dfree (binding, MDL);
                   4352:                        return (struct binding *)0;
                   4353:                }
                   4354:                strcpy (binding -> name, name);
                   4355: 
                   4356:                binding -> next = (*scope) -> bindings;
                   4357:                (*scope) -> bindings = binding;
                   4358:        }
                   4359: 
                   4360:        return binding;
                   4361: }
                   4362: 
                   4363: 
                   4364: int bind_ds_value (struct binding_scope **scope,
                   4365:                   const char *name,
                   4366:                   struct data_string *value)
                   4367: {
                   4368:        struct binding *binding;
                   4369: 
                   4370:        binding = create_binding (scope, name);
                   4371:        if (!binding)
                   4372:                return 0;
                   4373: 
                   4374:        if (binding -> value)
                   4375:                binding_value_dereference (&binding -> value, MDL);
                   4376: 
                   4377:        if (!binding_value_allocate (&binding -> value, MDL))
                   4378:                return 0;
                   4379: 
                   4380:        data_string_copy (&binding -> value -> value.data, value, MDL);
                   4381:        binding -> value -> type = binding_data;
                   4382: 
                   4383:        return 1;
                   4384: }
                   4385: 
                   4386: 
                   4387: int find_bound_string (struct data_string *value,
                   4388:                       struct binding_scope *scope,
                   4389:                       const char *name)
                   4390: {
                   4391:        struct binding *binding;
                   4392: 
                   4393:        binding = find_binding (scope, name);
                   4394:        if (!binding ||
                   4395:            !binding -> value ||
                   4396:            binding -> value -> type != binding_data)
                   4397:                return 0;
                   4398: 
                   4399:        if (binding -> value -> value.data.terminated) {
                   4400:                data_string_copy (value, &binding -> value -> value.data, MDL);
                   4401:        } else {
                   4402:                buffer_allocate (&value -> buffer,
                   4403:                                 binding -> value -> value.data.len,
                   4404:                                 MDL);
                   4405:                if (!value -> buffer)
                   4406:                        return 0;
                   4407: 
                   4408:                memcpy (value -> buffer -> data,
                   4409:                        binding -> value -> value.data.data,
                   4410:                        binding -> value -> value.data.len);
                   4411:                value -> data = value -> buffer -> data;
                   4412:                value -> len = binding -> value -> value.data.len;
                   4413:        }
                   4414: 
                   4415:        return 1;
                   4416: }
                   4417: 
                   4418: int unset (struct binding_scope *scope, const char *name)
                   4419: {
                   4420:        struct binding *binding;
                   4421: 
                   4422:        binding = find_binding (scope, name);
                   4423:        if (binding) {
                   4424:                if (binding -> value)
                   4425:                        binding_value_dereference
                   4426:                                (&binding -> value, MDL);
                   4427:                return 1;
                   4428:        }
                   4429:        return 0;
                   4430: }
                   4431: 
                   4432: /* vim: set tabstop=8: */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>