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

1.1     ! misho       1: /* tree.c
        !             2: 
        !             3:    Routines for manipulating parse trees... */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2011 by Internet Systems Consortium, Inc. ("ISC")
        !             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;
        !          2382: 
        !          2383:        switch (expr -> op) {
        !          2384:              case expr_check:
        !          2385:              case expr_equal:
        !          2386:              case expr_not_equal:
        !          2387:              case expr_regex_match:
        !          2388:              case expr_iregex_match:
        !          2389:              case expr_and:
        !          2390:              case expr_or:
        !          2391:              case expr_not:
        !          2392:              case expr_match:
        !          2393:              case expr_static:
        !          2394:              case expr_known:
        !          2395:              case expr_none:
        !          2396:              case expr_exists:
        !          2397:              case expr_variable_exists:
        !          2398:                log_error ("Boolean opcode in evaluate_numeric_expression: %d",
        !          2399:                      expr -> op);
        !          2400:                return 0;
        !          2401: 
        !          2402:              case expr_substring:
        !          2403:              case expr_suffix:
        !          2404:              case expr_lcase:
        !          2405:              case expr_ucase:
        !          2406:              case expr_option:
        !          2407:              case expr_hardware:
        !          2408:              case expr_const_data:
        !          2409:              case expr_packet:
        !          2410:              case expr_concat:
        !          2411:              case expr_encapsulate:
        !          2412:              case expr_host_lookup:
        !          2413:              case expr_encode_int8:
        !          2414:              case expr_encode_int16:
        !          2415:              case expr_encode_int32:
        !          2416:              case expr_binary_to_ascii:
        !          2417:              case expr_reverse:
        !          2418:              case expr_filename:
        !          2419:              case expr_sname:
        !          2420:              case expr_pick_first_value:
        !          2421:              case expr_host_decl_name:
        !          2422:              case expr_config_option:
        !          2423:              case expr_leased_address:
        !          2424:              case expr_null:
        !          2425:                log_error ("Data opcode in evaluate_numeric_expression: %d",
        !          2426:                      expr -> op);
        !          2427:                return 0;
        !          2428: 
        !          2429:              case expr_extract_int8:
        !          2430:                memset (&data, 0, sizeof data);
        !          2431:                status = evaluate_data_expression
        !          2432:                        (&data, packet, lease, client_state, in_options,
        !          2433:                         cfg_options, scope, expr -> data.extract_int, MDL);
        !          2434:                if (status)
        !          2435:                        *result = data.data [0];
        !          2436: #if defined (DEBUG_EXPRESSIONS)
        !          2437:                log_debug ("num: extract_int8 (%s) = %s",
        !          2438:                      status ? print_hex_1 (data.len, data.data, 60) : "NULL",
        !          2439:                      status ? print_dec_1 (*result) : "NULL" );
        !          2440: #endif
        !          2441:                if (status) data_string_forget (&data, MDL);
        !          2442:                return status;
        !          2443: 
        !          2444:              case expr_extract_int16:
        !          2445:                memset (&data, 0, sizeof data);
        !          2446:                status = (evaluate_data_expression
        !          2447:                          (&data, packet, lease, client_state, in_options,
        !          2448:                           cfg_options, scope, expr -> data.extract_int, MDL));
        !          2449:                if (status && data.len >= 2)
        !          2450:                        *result = getUShort (data.data);
        !          2451: #if defined (DEBUG_EXPRESSIONS)
        !          2452:                log_debug ("num: extract_int16 (%s) = %ld",
        !          2453:                      ((status && data.len >= 2) ?
        !          2454:                       print_hex_1 (data.len, data.data, 60) : "NULL"),
        !          2455:                      *result);
        !          2456: #endif
        !          2457:                if (status) data_string_forget (&data, MDL);
        !          2458:                return (status && data.len >= 2);
        !          2459: 
        !          2460:              case expr_extract_int32:
        !          2461:                memset (&data, 0, sizeof data);
        !          2462:                status = (evaluate_data_expression
        !          2463:                          (&data, packet, lease, client_state, in_options,
        !          2464:                           cfg_options, scope, expr -> data.extract_int, MDL));
        !          2465:                if (status && data.len >= 4)
        !          2466:                        *result = getULong (data.data);
        !          2467: #if defined (DEBUG_EXPRESSIONS)
        !          2468:                log_debug ("num: extract_int32 (%s) = %ld",
        !          2469:                      ((status && data.len >= 4) ?
        !          2470:                       print_hex_1 (data.len, data.data, 60) : "NULL"),
        !          2471:                      *result);
        !          2472: #endif
        !          2473:                if (status) data_string_forget (&data, MDL);
        !          2474:                return (status && data.len >= 4);
        !          2475: 
        !          2476:              case expr_const_int:
        !          2477:                *result = expr -> data.const_int;
        !          2478: #if defined (DEBUG_EXPRESSIONS)
        !          2479:                log_debug ("number: CONSTANT = %ld", *result);
        !          2480: #endif
        !          2481:                return 1;
        !          2482: 
        !          2483:              case expr_lease_time:
        !          2484:                if (!lease) {
        !          2485:                        log_error ("data: leased_lease: not available");
        !          2486:                        return 0;
        !          2487:                }
        !          2488:                if (lease -> ends < cur_time) {
        !          2489:                        log_error ("%s %lu when it is now %lu",
        !          2490:                                   "data: lease_time: lease ends at",
        !          2491:                                   (long)(lease -> ends), (long)cur_time);
        !          2492:                        return 0;
        !          2493:                }
        !          2494:                *result = lease -> ends - cur_time;
        !          2495: #if defined (DEBUG_EXPRESSIONS)
        !          2496:                log_debug ("number: lease-time = (%lu - %lu) = %ld",
        !          2497:                           lease -> ends,
        !          2498:                           cur_time, *result);
        !          2499: #endif
        !          2500:                return 1;
        !          2501:  
        !          2502:              case expr_dns_transaction:
        !          2503: #if !defined (NSUPDATE)
        !          2504:                return 0;
        !          2505: #else
        !          2506:                if (!resolver_inited) {
        !          2507:                        minires_ninit (&resolver_state);
        !          2508:                        resolver_inited = 1;
        !          2509:                        resolver_state.retrans = 1;
        !          2510:                        resolver_state.retry = 1;
        !          2511:                }
        !          2512:                ISC_LIST_INIT (uq);
        !          2513:                cur = expr;
        !          2514:                do {
        !          2515:                    next = cur -> data.dns_transaction.cdr;
        !          2516:                    nut = 0;
        !          2517:                    status = (evaluate_dns_expression
        !          2518:                              (&nut, packet,
        !          2519:                               lease, client_state, in_options, cfg_options,
        !          2520:                               scope, cur -> data.dns_transaction.car));
        !          2521:                    if (!status)
        !          2522:                            goto dns_bad;
        !          2523:                    ISC_LIST_APPEND (uq, nut, r_link);
        !          2524:                    cur = next;
        !          2525:                } while (next);
        !          2526: 
        !          2527:                /* Do the update and record the error code, if there was
        !          2528:                   an error; otherwise set it to NOERROR. */
        !          2529:                *result = minires_nupdate (&resolver_state,
        !          2530:                                           ISC_LIST_HEAD (uq));
        !          2531:                status = 1;
        !          2532: 
        !          2533:                print_dns_status ((int)*result, &uq);
        !          2534: 
        !          2535:              dns_bad:
        !          2536:                while (!ISC_LIST_EMPTY (uq)) {
        !          2537:                        ns_updrec *tmp = ISC_LIST_HEAD (uq);
        !          2538:                        ISC_LIST_UNLINK (uq, tmp, r_link);
        !          2539:                        if (tmp -> r_data_ephem) {
        !          2540:                                dfree (tmp -> r_data_ephem, MDL);
        !          2541:                                tmp -> r_data = (unsigned char *)0;
        !          2542:                                tmp -> r_data_ephem = (unsigned char *)0;
        !          2543:                        }
        !          2544:                        minires_freeupdrec (tmp);
        !          2545:                }
        !          2546:                return status;
        !          2547: #endif /* NSUPDATE */
        !          2548: 
        !          2549:              case expr_variable_reference:
        !          2550:                if (scope && *scope) {
        !          2551:                    binding = find_binding (*scope, expr -> data.variable);
        !          2552: 
        !          2553:                    if (binding && binding -> value) {
        !          2554:                        if (binding -> value -> type == binding_numeric) {
        !          2555:                                *result = binding -> value -> value.intval;
        !          2556:                            status = 1;
        !          2557:                        } else {
        !          2558:                                log_error ("binding type %d in %s.",
        !          2559:                                           binding -> value -> type,
        !          2560:                                           "evaluate_numeric_expression");
        !          2561:                                status = 0;
        !          2562:                        }
        !          2563:                    } else
        !          2564:                        status = 0;
        !          2565:                } else
        !          2566:                    status = 0;
        !          2567: #if defined (DEBUG_EXPRESSIONS)
        !          2568:                if (status)
        !          2569:                        log_debug ("numeric: %s = %ld",
        !          2570:                                   expr -> data.variable, *result);
        !          2571:                else
        !          2572:                        log_debug ("numeric: %s = NULL",
        !          2573:                                   expr -> data.variable);
        !          2574: #endif
        !          2575:                return status;
        !          2576: 
        !          2577:              case expr_funcall:
        !          2578:                bv = (struct binding_value *)0;
        !          2579:                status = evaluate_expression (&bv, packet, lease,
        !          2580:                                              client_state,
        !          2581:                                              in_options, cfg_options,
        !          2582:                                              scope, expr, MDL);
        !          2583:                if (status) {
        !          2584:                        if (bv -> type != binding_numeric)
        !          2585:                                log_error ("%s() returned type %d in %s.",
        !          2586:                                           expr -> data.funcall.name,
        !          2587:                                           bv -> type,
        !          2588:                                           "evaluate_numeric_expression");
        !          2589:                        else
        !          2590:                                *result = bv -> value.intval;
        !          2591:                        binding_value_dereference (&bv, MDL);
        !          2592:                }
        !          2593: #if defined (DEBUG_EXPRESSIONS)
        !          2594:                log_debug ("data: %s = %ld", expr -> data.funcall.name,
        !          2595:                           status ? *result : 0);
        !          2596: #endif
        !          2597:                break;
        !          2598: 
        !          2599:              case expr_add:
        !          2600:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
        !          2601:                                                     client_state,
        !          2602:                                                     in_options, cfg_options,
        !          2603:                                                     scope,
        !          2604:                                                     expr -> data.and [0]);
        !          2605:                sright = evaluate_numeric_expression (&iright, packet, lease,
        !          2606:                                                      client_state,
        !          2607:                                                      in_options, cfg_options,
        !          2608:                                                      scope,
        !          2609:                                                      expr -> data.and [1]);
        !          2610: 
        !          2611: #if defined (DEBUG_EXPRESSIONS)
        !          2612:                if (sleft && sright)
        !          2613:                        log_debug ("num: %ld + %ld = %ld",
        !          2614:                                   ileft, iright, ileft + iright);
        !          2615:                else if (sleft)
        !          2616:                        log_debug ("num: %ld + NULL = NULL", ileft);
        !          2617:                else
        !          2618:                        log_debug ("num: NULL + %ld = NULL", iright);
        !          2619: #endif
        !          2620:                if (sleft && sright) {
        !          2621:                        *result = ileft + iright;
        !          2622:                        return 1;
        !          2623:                }
        !          2624:                return 0;
        !          2625: 
        !          2626:              case expr_subtract:
        !          2627:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
        !          2628:                                                     client_state,
        !          2629:                                                     in_options, cfg_options,
        !          2630:                                                     scope,
        !          2631:                                                     expr -> data.and [0]);
        !          2632:                sright = evaluate_numeric_expression (&iright, packet, lease,
        !          2633:                                                      client_state,
        !          2634:                                                      in_options, cfg_options,
        !          2635:                                                      scope,
        !          2636:                                                      expr -> data.and [1]);
        !          2637: 
        !          2638: #if defined (DEBUG_EXPRESSIONS)
        !          2639:                if (sleft && sright)
        !          2640:                        log_debug ("num: %ld - %ld = %ld",
        !          2641:                                   ileft, iright, ileft - iright);
        !          2642:                else if (sleft)
        !          2643:                        log_debug ("num: %ld - NULL = NULL", ileft);
        !          2644:                else
        !          2645:                        log_debug ("num: NULL - %ld = NULL", iright);
        !          2646: #endif
        !          2647:                if (sleft && sright) {
        !          2648:                        *result = ileft - iright;
        !          2649:                        return 1;
        !          2650:                }
        !          2651:                return 0;
        !          2652: 
        !          2653:              case expr_multiply:
        !          2654:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
        !          2655:                                                     client_state,
        !          2656:                                                     in_options, cfg_options,
        !          2657:                                                     scope,
        !          2658:                                                     expr -> data.and [0]);
        !          2659:                sright = evaluate_numeric_expression (&iright, packet, lease,
        !          2660:                                                      client_state,
        !          2661:                                                      in_options, cfg_options,
        !          2662:                                                      scope,
        !          2663:                                                      expr -> data.and [1]);
        !          2664: 
        !          2665: #if defined (DEBUG_EXPRESSIONS)
        !          2666:                if (sleft && sright)
        !          2667:                        log_debug ("num: %ld * %ld = %ld",
        !          2668:                                   ileft, iright, ileft * iright);
        !          2669:                else if (sleft)
        !          2670:                        log_debug ("num: %ld * NULL = NULL", ileft);
        !          2671:                else
        !          2672:                        log_debug ("num: NULL * %ld = NULL", iright);
        !          2673: #endif
        !          2674:                if (sleft && sright) {
        !          2675:                        *result = ileft * iright;
        !          2676:                        return 1;
        !          2677:                }
        !          2678:                return 0;
        !          2679: 
        !          2680:              case expr_divide:
        !          2681:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
        !          2682:                                                     client_state,
        !          2683:                                                     in_options, cfg_options,
        !          2684:                                                     scope,
        !          2685:                                                     expr -> data.and [0]);
        !          2686:                sright = evaluate_numeric_expression (&iright, packet, lease,
        !          2687:                                                      client_state,
        !          2688:                                                      in_options, cfg_options,
        !          2689:                                                      scope,
        !          2690:                                                      expr -> data.and [1]);
        !          2691: 
        !          2692: #if defined (DEBUG_EXPRESSIONS)
        !          2693:                if (sleft && sright) {
        !          2694:                        if (iright != 0)
        !          2695:                                log_debug ("num: %ld / %ld = %ld",
        !          2696:                                           ileft, iright, ileft / iright);
        !          2697:                        else
        !          2698:                                log_debug ("num: %ld / %ld = NULL",
        !          2699:                                           ileft, iright);
        !          2700:                } else if (sleft)
        !          2701:                        log_debug ("num: %ld / NULL = NULL", ileft);
        !          2702:                else
        !          2703:                        log_debug ("num: NULL / %ld = NULL", iright);
        !          2704: #endif
        !          2705:                if (sleft && sright && iright) {
        !          2706:                        *result = ileft / iright;
        !          2707:                        return 1;
        !          2708:                }
        !          2709:                return 0;
        !          2710: 
        !          2711:              case expr_remainder:
        !          2712:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
        !          2713:                                                     client_state,
        !          2714:                                                     in_options, cfg_options,
        !          2715:                                                     scope,
        !          2716:                                                     expr -> data.and [0]);
        !          2717:                sright = evaluate_numeric_expression (&iright, packet, lease,
        !          2718:                                                      client_state,
        !          2719:                                                      in_options, cfg_options,
        !          2720:                                                      scope,
        !          2721:                                                      expr -> data.and [1]);
        !          2722: 
        !          2723: #if defined (DEBUG_EXPRESSIONS)
        !          2724:                if (sleft && sright) {
        !          2725:                        if (iright != 0)
        !          2726:                                log_debug ("num: %ld %% %ld = %ld",
        !          2727:                                           ileft, iright, ileft % iright);
        !          2728:                        else
        !          2729:                                log_debug ("num: %ld %% %ld = NULL",
        !          2730:                                           ileft, iright);
        !          2731:                } else if (sleft)
        !          2732:                        log_debug ("num: %ld %% NULL = NULL", ileft);
        !          2733:                else
        !          2734:                        log_debug ("num: NULL %% %ld = NULL", iright);
        !          2735: #endif
        !          2736:                if (sleft && sright && iright) {
        !          2737:                        *result = ileft % iright;
        !          2738:                        return 1;
        !          2739:                }
        !          2740:                return 0;
        !          2741: 
        !          2742:              case expr_binary_and:
        !          2743:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
        !          2744:                                                     client_state,
        !          2745:                                                     in_options, cfg_options,
        !          2746:                                                     scope,
        !          2747:                                                     expr -> data.and [0]);
        !          2748:                sright = evaluate_numeric_expression (&iright, packet, lease,
        !          2749:                                                      client_state,
        !          2750:                                                      in_options, cfg_options,
        !          2751:                                                      scope,
        !          2752:                                                      expr -> data.and [1]);
        !          2753: 
        !          2754: #if defined (DEBUG_EXPRESSIONS)
        !          2755:                if (sleft && sright)
        !          2756:                        log_debug ("num: %ld | %ld = %ld",
        !          2757:                                   ileft, iright, ileft & iright);
        !          2758:                else if (sleft)
        !          2759:                        log_debug ("num: %ld & NULL = NULL", ileft);
        !          2760:                else
        !          2761:                        log_debug ("num: NULL & %ld = NULL", iright);
        !          2762: #endif
        !          2763:                if (sleft && sright) {
        !          2764:                        *result = ileft & iright;
        !          2765:                        return 1;
        !          2766:                }
        !          2767:                return 0;
        !          2768: 
        !          2769:              case expr_binary_or:
        !          2770:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
        !          2771:                                                     client_state,
        !          2772:                                                     in_options, cfg_options,
        !          2773:                                                     scope,
        !          2774:                                                     expr -> data.and [0]);
        !          2775:                sright = evaluate_numeric_expression (&iright, packet, lease,
        !          2776:                                                      client_state,
        !          2777:                                                      in_options, cfg_options,
        !          2778:                                                      scope,
        !          2779:                                                      expr -> data.and [1]);
        !          2780: 
        !          2781: #if defined (DEBUG_EXPRESSIONS)
        !          2782:                if (sleft && sright)
        !          2783:                        log_debug ("num: %ld | %ld = %ld",
        !          2784:                                   ileft, iright, ileft | iright);
        !          2785:                else if (sleft)
        !          2786:                        log_debug ("num: %ld | NULL = NULL", ileft);
        !          2787:                else
        !          2788:                        log_debug ("num: NULL | %ld = NULL", iright);
        !          2789: #endif
        !          2790:                if (sleft && sright) {
        !          2791:                        *result = ileft | iright;
        !          2792:                        return 1;
        !          2793:                }
        !          2794:                return 0;
        !          2795: 
        !          2796:              case expr_binary_xor:
        !          2797:                sleft = evaluate_numeric_expression (&ileft, packet, lease,
        !          2798:                                                     client_state,
        !          2799:                                                     in_options, cfg_options,
        !          2800:                                                     scope,
        !          2801:                                                     expr -> data.and [0]);
        !          2802:                sright = evaluate_numeric_expression (&iright, packet, lease,
        !          2803:                                                      client_state,
        !          2804:                                                      in_options, cfg_options,
        !          2805:                                                      scope,
        !          2806:                                                      expr -> data.and [1]);
        !          2807: 
        !          2808: #if defined (DEBUG_EXPRESSIONS)
        !          2809:                if (sleft && sright)
        !          2810:                        log_debug ("num: %ld ^ %ld = %ld",
        !          2811:                                   ileft, iright, ileft ^ iright);
        !          2812:                else if (sleft)
        !          2813:                        log_debug ("num: %ld ^ NULL = NULL", ileft);
        !          2814:                else
        !          2815:                        log_debug ("num: NULL ^ %ld = NULL", iright);
        !          2816: #endif
        !          2817:                if (sleft && sright) {
        !          2818:                        *result = ileft ^ iright;
        !          2819:                        return 1;
        !          2820:                }
        !          2821:                return 0;
        !          2822: 
        !          2823:              case expr_client_state:
        !          2824:                if (client_state) {
        !          2825: #if defined (DEBUG_EXPRESSIONS)
        !          2826:                        log_debug ("num: client-state = %d",
        !          2827:                                   client_state -> state);
        !          2828: #endif
        !          2829:                        *result = client_state -> state;
        !          2830:                        return 1;
        !          2831:                } else {
        !          2832: #if defined (DEBUG_EXPRESSIONS)
        !          2833:                        log_debug ("num: client-state = NULL");
        !          2834: #endif
        !          2835:                        return 0;
        !          2836:                }
        !          2837: 
        !          2838:              case expr_ns_add:
        !          2839:              case expr_ns_delete:
        !          2840:              case expr_ns_exists:
        !          2841:              case expr_ns_not_exists:
        !          2842:                log_error ("dns opcode in evaluate_numeric_expression: %d",
        !          2843:                      expr -> op);
        !          2844:                return 0;
        !          2845: 
        !          2846:              case expr_function:
        !          2847:                log_error ("function definition in evaluate_numeric_expr");
        !          2848:                return 0;
        !          2849: 
        !          2850:              case expr_arg:
        !          2851:                break;
        !          2852: 
        !          2853:              default:
        !          2854:                log_fatal("Impossible case at %s:%d.  Undefined operator "
        !          2855:                          "%d.", MDL, expr->op);
        !          2856:                break;
        !          2857:        }
        !          2858: 
        !          2859:        log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op);
        !          2860:        return 0;
        !          2861: }
        !          2862: 
        !          2863: /* Return data hanging off of an option cache structure, or if there
        !          2864:    isn't any, evaluate the expression hanging off of it and return the
        !          2865:    result of that evaluation.   There should never be both an expression
        !          2866:    and a valid data_string. */
        !          2867: 
        !          2868: int evaluate_option_cache (result, packet, lease, client_state,
        !          2869:                           in_options, cfg_options, scope, oc, file, line)
        !          2870:        struct data_string *result;
        !          2871:        struct packet *packet;
        !          2872:        struct lease *lease;
        !          2873:        struct client_state *client_state;
        !          2874:        struct option_state *in_options;
        !          2875:        struct option_state *cfg_options;
        !          2876:        struct binding_scope **scope;
        !          2877:        struct option_cache *oc;
        !          2878:        const char *file;
        !          2879:        int line;
        !          2880: {
        !          2881:        if (oc->data.data != NULL) {
        !          2882:                data_string_copy (result, &oc -> data, file, line);
        !          2883:                return 1;
        !          2884:        }
        !          2885:        if (!oc -> expression)
        !          2886:                return 0;
        !          2887:        return evaluate_data_expression (result, packet, lease, client_state,
        !          2888:                                         in_options, cfg_options, scope,
        !          2889:                                         oc -> expression, file, line);
        !          2890: }
        !          2891: 
        !          2892: /* Evaluate an option cache and extract a boolean from the result,
        !          2893:    returning the boolean.   Return false if there is no data. */
        !          2894: 
        !          2895: int evaluate_boolean_option_cache (ignorep, packet,
        !          2896:                                   lease, client_state, in_options,
        !          2897:                                   cfg_options, scope, oc, file, line)
        !          2898:        int *ignorep;
        !          2899:        struct packet *packet;
        !          2900:        struct lease *lease;
        !          2901:        struct client_state *client_state;
        !          2902:        struct option_state *in_options;
        !          2903:        struct option_state *cfg_options;
        !          2904:        struct binding_scope **scope;
        !          2905:        struct option_cache *oc;
        !          2906:        const char *file;
        !          2907:        int line;
        !          2908: {
        !          2909:        struct data_string ds;
        !          2910:        int result;
        !          2911: 
        !          2912:        /* So that we can be called with option_lookup as an argument. */
        !          2913:        if (!oc || !in_options)
        !          2914:                return 0;
        !          2915:        
        !          2916:        memset (&ds, 0, sizeof ds);
        !          2917:        if (!evaluate_option_cache (&ds, packet,
        !          2918:                                    lease, client_state, in_options,
        !          2919:                                    cfg_options, scope, oc, file, line))
        !          2920:                return 0;
        !          2921: 
        !          2922:        /* The boolean option cache is actually a trinary value.  Zero is
        !          2923:         * off, one is on, and 2 is 'ignore'.
        !          2924:         */
        !          2925:        if (ds.len) {
        !          2926:                result = ds.data [0];
        !          2927:                if (result == 2) {
        !          2928:                        result = 0;
        !          2929:                        if (ignorep != NULL)
        !          2930:                                *ignorep = 1;
        !          2931:                } else if (ignorep != NULL)
        !          2932:                        *ignorep = 0;
        !          2933:        } else
        !          2934:                result = 0;
        !          2935:        data_string_forget (&ds, MDL);
        !          2936:        return result;
        !          2937: }
        !          2938:                
        !          2939: 
        !          2940: /* Evaluate a boolean expression and return the result of the evaluation,
        !          2941:    or FALSE if it failed. */
        !          2942: 
        !          2943: int evaluate_boolean_expression_result (ignorep, packet, lease, client_state,
        !          2944:                                        in_options, cfg_options, scope, expr)
        !          2945:        int *ignorep;
        !          2946:        struct packet *packet;
        !          2947:        struct lease *lease;
        !          2948:        struct client_state *client_state;
        !          2949:        struct option_state *in_options;
        !          2950:        struct option_state *cfg_options;
        !          2951:        struct binding_scope **scope;
        !          2952:        struct expression *expr;
        !          2953: {
        !          2954:        int result;
        !          2955: 
        !          2956:        /* So that we can be called with option_lookup as an argument. */
        !          2957:        if (!expr)
        !          2958:                return 0;
        !          2959:        
        !          2960:        if (!evaluate_boolean_expression (&result, packet, lease, client_state,
        !          2961:                                          in_options, cfg_options,
        !          2962:                                          scope, expr))
        !          2963:                return 0;
        !          2964: 
        !          2965:        if (result == 2) {
        !          2966:                *ignorep = 1;
        !          2967:                result = 0;
        !          2968:        } else
        !          2969:                *ignorep = 0;
        !          2970:        return result;
        !          2971: }
        !          2972:                
        !          2973: 
        !          2974: /* Dereference an expression node, and if the reference count goes to zero,
        !          2975:    dereference any data it refers to, and then free it. */
        !          2976: void expression_dereference (eptr, file, line)
        !          2977:        struct expression **eptr;
        !          2978:        const char *file;
        !          2979:        int line;
        !          2980: {
        !          2981:        struct expression *expr = *eptr;
        !          2982: 
        !          2983:        /* Zero the pointer. */
        !          2984:        *eptr = (struct expression *)0;
        !          2985: 
        !          2986:        /* Decrement the reference count.   If it's nonzero, we're
        !          2987:           done. */
        !          2988:        --(expr -> refcnt);
        !          2989:        rc_register (file, line, eptr, expr, expr -> refcnt, 1, RC_MISC);
        !          2990:        if (expr -> refcnt > 0)
        !          2991:                return;
        !          2992:        if (expr -> refcnt < 0) {
        !          2993:                log_error ("%s(%d): negative refcnt!", file, line);
        !          2994: #if defined (DEBUG_RC_HISTORY)
        !          2995:                dump_rc_history (expr);
        !          2996: #endif
        !          2997: #if defined (POINTER_DEBUG)
        !          2998:                abort ();
        !          2999: #else
        !          3000:                return;
        !          3001: #endif
        !          3002:        }
        !          3003: 
        !          3004:        /* Dereference subexpressions. */
        !          3005:        switch (expr -> op) {
        !          3006:                /* All the binary operators can be handled the same way. */
        !          3007:              case expr_equal:
        !          3008:              case expr_not_equal:
        !          3009:              case expr_regex_match:
        !          3010:              case expr_iregex_match:
        !          3011:              case expr_concat:
        !          3012:              case expr_and:
        !          3013:              case expr_or:
        !          3014:              case expr_add:
        !          3015:              case expr_subtract:
        !          3016:              case expr_multiply:
        !          3017:              case expr_divide:
        !          3018:              case expr_remainder:
        !          3019:              case expr_binary_and:
        !          3020:              case expr_binary_or:
        !          3021:              case expr_binary_xor:
        !          3022:              case expr_client_state:
        !          3023:                if (expr -> data.equal [0])
        !          3024:                        expression_dereference (&expr -> data.equal [0],
        !          3025:                                                file, line);
        !          3026:                if (expr -> data.equal [1])
        !          3027:                        expression_dereference (&expr -> data.equal [1],
        !          3028:                                                file, line);
        !          3029:                break;
        !          3030: 
        !          3031:              case expr_substring:
        !          3032:                if (expr -> data.substring.expr)
        !          3033:                        expression_dereference (&expr -> data.substring.expr,
        !          3034:                                                file, line);
        !          3035:                if (expr -> data.substring.offset)
        !          3036:                        expression_dereference (&expr -> data.substring.offset,
        !          3037:                                                file, line);
        !          3038:                if (expr -> data.substring.len)
        !          3039:                        expression_dereference (&expr -> data.substring.len,
        !          3040:                                                file, line);
        !          3041:                break;
        !          3042: 
        !          3043:              case expr_suffix:
        !          3044:                if (expr -> data.suffix.expr)
        !          3045:                        expression_dereference (&expr -> data.suffix.expr,
        !          3046:                                                file, line);
        !          3047:                if (expr -> data.suffix.len)
        !          3048:                        expression_dereference (&expr -> data.suffix.len,
        !          3049:                                                file, line);
        !          3050:                break;
        !          3051: 
        !          3052:              case expr_lcase:
        !          3053:                if (expr->data.lcase)
        !          3054:                        expression_dereference(&expr->data.lcase, MDL);
        !          3055:                break;
        !          3056: 
        !          3057:              case expr_ucase:
        !          3058:                if (expr->data.ucase)
        !          3059:                        expression_dereference(&expr->data.ucase, MDL);
        !          3060:                break;
        !          3061: 
        !          3062:              case expr_not:
        !          3063:                if (expr -> data.not)
        !          3064:                        expression_dereference (&expr -> data.not, file, line);
        !          3065:                break;
        !          3066: 
        !          3067:              case expr_packet:
        !          3068:                if (expr -> data.packet.offset)
        !          3069:                        expression_dereference (&expr -> data.packet.offset,
        !          3070:                                                file, line);
        !          3071:                if (expr -> data.packet.len)
        !          3072:                        expression_dereference (&expr -> data.packet.len,
        !          3073:                                                file, line);
        !          3074:                break;
        !          3075: 
        !          3076:              case expr_extract_int8:
        !          3077:              case expr_extract_int16:
        !          3078:              case expr_extract_int32:
        !          3079:                if (expr -> data.extract_int)
        !          3080:                        expression_dereference (&expr -> data.extract_int,
        !          3081:                                                file, line);
        !          3082:                break;
        !          3083: 
        !          3084:              case expr_encode_int8:
        !          3085:              case expr_encode_int16:
        !          3086:              case expr_encode_int32:
        !          3087:                if (expr -> data.encode_int)
        !          3088:                        expression_dereference (&expr -> data.encode_int,
        !          3089:                                                file, line);
        !          3090:                break;
        !          3091: 
        !          3092:              case expr_encapsulate:
        !          3093:              case expr_const_data:
        !          3094:                data_string_forget (&expr -> data.const_data, file, line);
        !          3095:                break;
        !          3096: 
        !          3097:              case expr_host_lookup:
        !          3098:                if (expr -> data.host_lookup)
        !          3099:                        dns_host_entry_dereference (&expr -> data.host_lookup,
        !          3100:                                                    file, line);
        !          3101:                break;
        !          3102: 
        !          3103:              case expr_binary_to_ascii:
        !          3104:                if (expr -> data.b2a.base)
        !          3105:                        expression_dereference (&expr -> data.b2a.base,
        !          3106:                                                file, line);
        !          3107:                if (expr -> data.b2a.width)
        !          3108:                        expression_dereference (&expr -> data.b2a.width,
        !          3109:                                                file, line);
        !          3110:                if (expr -> data.b2a.separator)
        !          3111:                        expression_dereference (&expr -> data.b2a.separator,
        !          3112:                                                file, line);
        !          3113:                if (expr -> data.b2a.buffer)
        !          3114:                        expression_dereference (&expr -> data.b2a.buffer,
        !          3115:                                                file, line);
        !          3116:                break;
        !          3117: 
        !          3118:              case expr_pick_first_value:
        !          3119:                if (expr -> data.pick_first_value.car)
        !          3120:                    expression_dereference (&expr -> data.pick_first_value.car,
        !          3121:                                            file, line);
        !          3122:                if (expr -> data.pick_first_value.cdr)
        !          3123:                    expression_dereference (&expr -> data.pick_first_value.cdr,
        !          3124:                                            file, line);
        !          3125:                break;
        !          3126: 
        !          3127:              case expr_reverse:
        !          3128:                if (expr -> data.reverse.width)
        !          3129:                        expression_dereference (&expr -> data.reverse.width,
        !          3130:                                                file, line);
        !          3131:                if (expr -> data.reverse.buffer)
        !          3132:                        expression_dereference
        !          3133:                                (&expr -> data.reverse.buffer, file, line);
        !          3134:                break;
        !          3135: 
        !          3136:              case expr_dns_transaction:
        !          3137:                if (expr -> data.dns_transaction.car)
        !          3138:                    expression_dereference (&expr -> data.dns_transaction.car,
        !          3139:                                            file, line);
        !          3140:                if (expr -> data.dns_transaction.cdr)
        !          3141:                    expression_dereference (&expr -> data.dns_transaction.cdr,
        !          3142:                                            file, line);
        !          3143:                break;
        !          3144: 
        !          3145:              case expr_ns_add:
        !          3146:                if (expr -> data.ns_add.rrname)
        !          3147:                    expression_dereference (&expr -> data.ns_add.rrname,
        !          3148:                                            file, line);
        !          3149:                if (expr -> data.ns_add.rrdata)
        !          3150:                    expression_dereference (&expr -> data.ns_add.rrdata,
        !          3151:                                            file, line);
        !          3152:                if (expr -> data.ns_add.ttl)
        !          3153:                    expression_dereference (&expr -> data.ns_add.ttl,
        !          3154:                                            file, line);
        !          3155:                break;
        !          3156: 
        !          3157:              case expr_ns_delete:
        !          3158:              case expr_ns_exists:
        !          3159:              case expr_ns_not_exists:
        !          3160:                if (expr -> data.ns_delete.rrname)
        !          3161:                    expression_dereference (&expr -> data.ns_delete.rrname,
        !          3162:                                            file, line);
        !          3163:                if (expr -> data.ns_delete.rrdata)
        !          3164:                    expression_dereference (&expr -> data.ns_delete.rrdata,
        !          3165:                                            file, line);
        !          3166:                break;
        !          3167: 
        !          3168:              case expr_variable_reference:
        !          3169:              case expr_variable_exists:
        !          3170:                if (expr -> data.variable)
        !          3171:                        dfree (expr -> data.variable, file, line);
        !          3172:                break;
        !          3173: 
        !          3174:              case expr_funcall:
        !          3175:                if (expr -> data.funcall.name)
        !          3176:                        dfree (expr -> data.funcall.name, file, line);
        !          3177:                if (expr -> data.funcall.arglist)
        !          3178:                        expression_dereference (&expr -> data.funcall.arglist,
        !          3179:                                                file, line);
        !          3180:                break;
        !          3181: 
        !          3182:              case expr_arg:
        !          3183:                if (expr -> data.arg.val)
        !          3184:                        expression_dereference (&expr -> data.arg.val,
        !          3185:                                                file, line);
        !          3186:                if (expr -> data.arg.next)
        !          3187:                        expression_dereference (&expr -> data.arg.next,
        !          3188:                                                file, line);
        !          3189:                break;
        !          3190: 
        !          3191:              case expr_function:
        !          3192:                fundef_dereference (&expr -> data.func, file, line);
        !          3193:                break;
        !          3194: 
        !          3195:                /* No subexpressions. */
        !          3196:              case expr_leased_address:
        !          3197:              case expr_lease_time:
        !          3198:              case expr_filename:
        !          3199:              case expr_sname:
        !          3200:              case expr_const_int:
        !          3201:              case expr_check:
        !          3202:              case expr_option:
        !          3203:              case expr_hardware:
        !          3204:              case expr_exists:
        !          3205:              case expr_known:
        !          3206:              case expr_null:
        !          3207:                break;
        !          3208: 
        !          3209:              default:
        !          3210:                break;
        !          3211:        }
        !          3212:        free_expression (expr, MDL);
        !          3213: }
        !          3214: 
        !          3215: int is_dns_expression (expr)
        !          3216:        struct expression *expr;
        !          3217: {
        !          3218:       return (expr -> op == expr_ns_add ||
        !          3219:              expr -> op == expr_ns_delete ||
        !          3220:              expr -> op == expr_ns_exists ||
        !          3221:              expr -> op == expr_ns_not_exists);
        !          3222: }
        !          3223: 
        !          3224: int is_boolean_expression (expr)
        !          3225:        struct expression *expr;
        !          3226: {
        !          3227:        return (expr -> op == expr_check ||
        !          3228:                expr -> op == expr_exists ||
        !          3229:                expr -> op == expr_variable_exists ||
        !          3230:                expr -> op == expr_equal ||
        !          3231:                expr -> op == expr_not_equal ||
        !          3232:                expr->op == expr_regex_match ||
        !          3233:                expr->op == expr_iregex_match ||
        !          3234:                expr -> op == expr_and ||
        !          3235:                expr -> op == expr_or ||
        !          3236:                expr -> op == expr_not ||
        !          3237:                expr -> op == expr_known ||
        !          3238:                expr -> op == expr_static);
        !          3239: }
        !          3240: 
        !          3241: int is_data_expression (expr)
        !          3242:        struct expression *expr;
        !          3243: {
        !          3244:        return (expr->op == expr_substring ||
        !          3245:                expr->op == expr_suffix ||
        !          3246:                expr->op == expr_lcase ||
        !          3247:                expr->op == expr_ucase ||
        !          3248:                expr->op == expr_option ||
        !          3249:                expr->op == expr_hardware ||
        !          3250:                expr->op == expr_const_data ||
        !          3251:                expr->op == expr_packet ||
        !          3252:                expr->op == expr_concat ||
        !          3253:                expr->op == expr_encapsulate ||
        !          3254:                expr->op == expr_encode_int8 ||
        !          3255:                expr->op == expr_encode_int16 ||
        !          3256:                expr->op == expr_encode_int32 ||
        !          3257:                expr->op == expr_host_lookup ||
        !          3258:                expr->op == expr_binary_to_ascii ||
        !          3259:                expr->op == expr_filename ||
        !          3260:                expr->op == expr_sname ||
        !          3261:                expr->op == expr_reverse ||
        !          3262:                expr->op == expr_pick_first_value ||
        !          3263:                expr->op == expr_host_decl_name ||
        !          3264:                expr->op == expr_leased_address ||
        !          3265:                expr->op == expr_config_option ||
        !          3266:                expr->op == expr_null);
        !          3267: }
        !          3268: 
        !          3269: int is_numeric_expression (expr)
        !          3270:        struct expression *expr;
        !          3271: {
        !          3272:        return (expr -> op == expr_extract_int8 ||
        !          3273:                expr -> op == expr_extract_int16 ||
        !          3274:                expr -> op == expr_extract_int32 ||
        !          3275:                expr -> op == expr_const_int ||
        !          3276:                expr -> op == expr_lease_time ||
        !          3277:                expr -> op == expr_dns_transaction ||
        !          3278:                expr -> op == expr_add ||
        !          3279:                expr -> op == expr_subtract ||
        !          3280:                expr -> op == expr_multiply ||
        !          3281:                expr -> op == expr_divide ||
        !          3282:                expr -> op == expr_remainder ||
        !          3283:                expr -> op == expr_binary_and ||
        !          3284:                expr -> op == expr_binary_or ||
        !          3285:                expr -> op == expr_binary_xor ||
        !          3286:                expr -> op == expr_client_state);
        !          3287: }
        !          3288: 
        !          3289: int is_compound_expression (expr)
        !          3290:        struct expression *expr;
        !          3291: {
        !          3292:        return (expr -> op == expr_ns_add ||
        !          3293:                expr -> op == expr_ns_delete ||
        !          3294:                expr -> op == expr_ns_exists ||
        !          3295:                expr -> op == expr_ns_not_exists ||
        !          3296:                expr -> op == expr_substring ||
        !          3297:                expr -> op == expr_suffix ||
        !          3298:                expr -> op == expr_option ||
        !          3299:                expr -> op == expr_concat ||
        !          3300:                expr -> op == expr_encode_int8 ||
        !          3301:                expr -> op == expr_encode_int16 ||
        !          3302:                expr -> op == expr_encode_int32 ||
        !          3303:                expr -> op == expr_binary_to_ascii ||
        !          3304:                expr -> op == expr_reverse ||
        !          3305:                expr -> op == expr_pick_first_value ||
        !          3306:                expr -> op == expr_config_option ||
        !          3307:                expr -> op == expr_extract_int8 ||
        !          3308:                expr -> op == expr_extract_int16 ||
        !          3309:                expr -> op == expr_extract_int32 ||
        !          3310:                expr -> op == expr_dns_transaction);
        !          3311: }
        !          3312: 
        !          3313: static int op_val (enum expr_op);
        !          3314: 
        !          3315: static int op_val (op)
        !          3316:        enum expr_op op;
        !          3317: {
        !          3318:        switch (op) {
        !          3319:              case expr_none:
        !          3320:              case expr_match:
        !          3321:              case expr_static:
        !          3322:              case expr_check:
        !          3323:              case expr_substring:
        !          3324:              case expr_suffix:
        !          3325:              case expr_lcase:
        !          3326:              case expr_ucase:
        !          3327:              case expr_concat:
        !          3328:              case expr_encapsulate:
        !          3329:              case expr_host_lookup:
        !          3330:              case expr_not:
        !          3331:              case expr_option:
        !          3332:              case expr_hardware:
        !          3333:              case expr_packet:
        !          3334:              case expr_const_data:
        !          3335:              case expr_extract_int8:
        !          3336:              case expr_extract_int16:
        !          3337:              case expr_extract_int32:
        !          3338:              case expr_encode_int8:
        !          3339:              case expr_encode_int16:
        !          3340:              case expr_encode_int32:
        !          3341:              case expr_const_int:
        !          3342:              case expr_exists:
        !          3343:              case expr_variable_exists:
        !          3344:              case expr_known:
        !          3345:              case expr_binary_to_ascii:
        !          3346:              case expr_reverse:
        !          3347:              case expr_filename:
        !          3348:              case expr_sname:
        !          3349:              case expr_pick_first_value:
        !          3350:              case expr_host_decl_name:
        !          3351:              case expr_config_option:
        !          3352:              case expr_leased_address:
        !          3353:              case expr_lease_time:
        !          3354:              case expr_dns_transaction:
        !          3355:              case expr_null:
        !          3356:              case expr_variable_reference:
        !          3357:              case expr_ns_add:
        !          3358:              case expr_ns_delete:
        !          3359:              case expr_ns_exists:
        !          3360:              case expr_ns_not_exists:
        !          3361:              case expr_arg:
        !          3362:              case expr_funcall:
        !          3363:              case expr_function:
        !          3364:                /* XXXDPN: Need to assign sane precedences to these. */
        !          3365:              case expr_binary_and:
        !          3366:              case expr_binary_or:
        !          3367:              case expr_binary_xor:
        !          3368:              case expr_client_state:
        !          3369:                return 100;
        !          3370: 
        !          3371:              case expr_equal:
        !          3372:              case expr_not_equal:
        !          3373:              case expr_regex_match:
        !          3374:              case expr_iregex_match:
        !          3375:                return 4;
        !          3376: 
        !          3377:              case expr_or:
        !          3378:              case expr_and:
        !          3379:                return 3;
        !          3380: 
        !          3381:              case expr_add:
        !          3382:              case expr_subtract:
        !          3383:                return 2;
        !          3384: 
        !          3385:              case expr_multiply:
        !          3386:              case expr_divide:
        !          3387:              case expr_remainder:
        !          3388:                return 1;
        !          3389:        }
        !          3390:        return 100;
        !          3391: }
        !          3392: 
        !          3393: int op_precedence (op1, op2)
        !          3394:        enum expr_op op1, op2;
        !          3395: {
        !          3396:        return op_val (op1) - op_val (op2);
        !          3397: }
        !          3398: 
        !          3399: enum expression_context expression_context (struct expression *expr)
        !          3400: {
        !          3401:        if (is_data_expression (expr))
        !          3402:                return context_data;
        !          3403:        if (is_numeric_expression (expr))
        !          3404:                return context_numeric;
        !          3405:        if (is_boolean_expression (expr))
        !          3406:                return context_boolean;
        !          3407:        if (is_dns_expression (expr))
        !          3408:                return context_dns;
        !          3409:        return context_any;
        !          3410: }
        !          3411: 
        !          3412: enum expression_context op_context (op)
        !          3413:        enum expr_op op;
        !          3414: {
        !          3415:        switch (op) {
        !          3416: /* XXX Why aren't these specific? */
        !          3417:              case expr_none:
        !          3418:              case expr_match:
        !          3419:              case expr_static:
        !          3420:              case expr_check:
        !          3421:              case expr_substring:
        !          3422:              case expr_suffix:
        !          3423:              case expr_lcase:
        !          3424:              case expr_ucase:
        !          3425:              case expr_concat:
        !          3426:              case expr_encapsulate:
        !          3427:              case expr_host_lookup:
        !          3428:              case expr_not:
        !          3429:              case expr_option:
        !          3430:              case expr_hardware:
        !          3431:              case expr_packet:
        !          3432:              case expr_const_data:
        !          3433:              case expr_extract_int8:
        !          3434:              case expr_extract_int16:
        !          3435:              case expr_extract_int32:
        !          3436:              case expr_encode_int8:
        !          3437:              case expr_encode_int16:
        !          3438:              case expr_encode_int32:
        !          3439:              case expr_const_int:
        !          3440:              case expr_exists:
        !          3441:              case expr_variable_exists:
        !          3442:              case expr_known:
        !          3443:              case expr_binary_to_ascii:
        !          3444:              case expr_reverse:
        !          3445:              case expr_filename:
        !          3446:              case expr_sname:
        !          3447:              case expr_pick_first_value:
        !          3448:              case expr_host_decl_name:
        !          3449:              case expr_config_option:
        !          3450:              case expr_leased_address:
        !          3451:              case expr_lease_time:
        !          3452:              case expr_null:
        !          3453:              case expr_variable_reference:
        !          3454:              case expr_ns_add:
        !          3455:              case expr_ns_delete:
        !          3456:              case expr_ns_exists:
        !          3457:              case expr_ns_not_exists:
        !          3458:              case expr_dns_transaction:
        !          3459:              case expr_arg:
        !          3460:              case expr_funcall:
        !          3461:              case expr_function:
        !          3462:                return context_any;
        !          3463: 
        !          3464:              case expr_equal:
        !          3465:              case expr_not_equal:
        !          3466:              case expr_regex_match:
        !          3467:              case expr_iregex_match:
        !          3468:                return context_data;
        !          3469: 
        !          3470:              case expr_and:
        !          3471:                return context_boolean;
        !          3472: 
        !          3473:              case expr_or:
        !          3474:                return context_boolean;
        !          3475: 
        !          3476:              case expr_add:
        !          3477:              case expr_subtract:
        !          3478:              case expr_multiply:
        !          3479:              case expr_divide:
        !          3480:              case expr_remainder:
        !          3481:              case expr_binary_and:
        !          3482:              case expr_binary_or:
        !          3483:              case expr_binary_xor:
        !          3484:              case expr_client_state:
        !          3485:                return context_numeric;
        !          3486:        }
        !          3487:        return context_any;
        !          3488: }
        !          3489: 
        !          3490: int write_expression (file, expr, col, indent, firstp)
        !          3491:        FILE *file;
        !          3492:        struct expression *expr;
        !          3493:        int col;
        !          3494:        int indent;
        !          3495:        int firstp;
        !          3496: {
        !          3497:        struct expression *e;
        !          3498:        const char *s;
        !          3499:        char obuf [65];
        !          3500:        int scol;
        !          3501:        int width;
        !          3502: 
        !          3503:        /* If this promises to be a fat expression, start a new line. */
        !          3504:        if (!firstp && is_compound_expression (expr)) {
        !          3505:                indent_spaces (file, indent);
        !          3506:                col = indent;
        !          3507:        }
        !          3508: 
        !          3509:        switch (expr -> op) {
        !          3510:              case expr_none:
        !          3511:                col = token_print_indent (file, col, indent, "", "", "null");
        !          3512:                break;
        !          3513:                
        !          3514:              case expr_check:
        !          3515:                col = token_print_indent (file, col, indent, "", "", "check");
        !          3516:                col = token_print_indent_concat (file, col, indent,
        !          3517:                                                 " ", "", "\"",
        !          3518:                                                 expr -> data.check -> name,
        !          3519:                                                 "\"", (char *)0);
        !          3520:                break;
        !          3521: 
        !          3522:              case expr_regex_match:
        !          3523:                s = "~=";
        !          3524:                goto binary;
        !          3525: 
        !          3526:              case expr_iregex_match:
        !          3527:                s = "~~";
        !          3528:                goto binary;
        !          3529: 
        !          3530:              case expr_not_equal:
        !          3531:                s = "!=";
        !          3532:                goto binary;
        !          3533: 
        !          3534:              case expr_equal:
        !          3535:                s = "=";
        !          3536:              binary:
        !          3537:                col = write_expression (file, expr -> data.equal [0],
        !          3538:                                        col, indent, 1);
        !          3539:                col = token_print_indent (file, col, indent, " ", " ", s);
        !          3540:                col = write_expression (file, expr -> data.equal [1],
        !          3541:                                        col, indent + 2, 0);
        !          3542:                break;
        !          3543: 
        !          3544:              case expr_substring:
        !          3545:                col = token_print_indent (file, col, indent, "", "",
        !          3546:                                          "substring");
        !          3547:                col = token_print_indent (file, col, indent, " ", "", "(");
        !          3548:                scol = col;
        !          3549:                col = write_expression (file, expr -> data.substring.expr,
        !          3550:                                        col, scol, 1);
        !          3551:                col = token_print_indent (file, col, indent, "", " ", ",");
        !          3552:                col = write_expression (file, expr -> data.substring.offset,
        !          3553:                                        col, indent, 0);
        !          3554:                col = token_print_indent (file, col, scol, "", " ", ",");
        !          3555:                col = write_expression (file, expr -> data.substring.len,
        !          3556:                                        col, scol, 0);
        !          3557:                col = token_print_indent (file, col, indent, "", "", ")");
        !          3558:                break;
        !          3559: 
        !          3560:              case expr_suffix:
        !          3561:                col = token_print_indent (file, col, indent, "", "", "suffix");
        !          3562:                col = token_print_indent (file, col, indent, " ", "", "(");
        !          3563:                scol = col;
        !          3564:                col = write_expression (file, expr -> data.suffix.expr,
        !          3565:                                        col, scol, 1);
        !          3566:                col = token_print_indent (file, col, scol, "", " ", ",");
        !          3567:                col = write_expression (file, expr -> data.suffix.len,
        !          3568:                                        col, scol, 0);
        !          3569:                col = token_print_indent (file, col, indent, "", "", ")");
        !          3570: 
        !          3571:              case expr_lcase:
        !          3572:                col = token_print_indent(file, col, indent, "", "", "lcase");
        !          3573:                col = token_print_indent(file, col, indent, " ", "", "(");
        !          3574:                scol = col;
        !          3575:                col = write_expression(file, expr->data.lcase, col, scol, 1);
        !          3576:                col = token_print_indent(file, col, indent, "", "", ")");
        !          3577:                break;
        !          3578: 
        !          3579:              case expr_ucase:
        !          3580:                col = token_print_indent(file, col, indent, "", "", "ucase");
        !          3581:                col = token_print_indent(file, col, indent, " ", "", "(");
        !          3582:                scol = col;
        !          3583:                col = write_expression(file, expr->data.ucase, col, scol, 1);
        !          3584:                col = token_print_indent(file, col, indent, "", "", ")");
        !          3585:                break;
        !          3586: 
        !          3587:              case expr_concat:
        !          3588:                e = expr;
        !          3589:                col = token_print_indent (file, col, indent, "", "",
        !          3590:                                          "concat");
        !          3591:                col = token_print_indent (file, col, indent, " ", "", "(");
        !          3592:                scol = col;
        !          3593:                firstp = 1;
        !          3594:              concat_again:
        !          3595:                col = write_expression (file, e -> data.concat [0],
        !          3596:                                        col, scol, firstp);
        !          3597:                firstp = 0;
        !          3598:                if (!e -> data.concat [1])
        !          3599:                        goto no_concat_cdr;
        !          3600:                col = token_print_indent (file, col, scol, "", " ", ",");
        !          3601:                if (e -> data.concat [1] -> op == expr_concat) {
        !          3602:                        e = e -> data.concat [1];
        !          3603:                        goto concat_again;
        !          3604:                }
        !          3605:                col = write_expression (file, e -> data.concat [1],
        !          3606:                                        col, scol, 0);
        !          3607:              no_concat_cdr:
        !          3608:                col = token_print_indent (file, col, indent, "", "", ")");
        !          3609:                break;
        !          3610: 
        !          3611:              case expr_host_lookup:
        !          3612:                col = token_print_indent (file, col, indent, "", "",
        !          3613:                                          "gethostbyname");
        !          3614:                col = token_print_indent (file, col, indent, " ", "", "(");
        !          3615:                col = token_print_indent_concat
        !          3616:                        (file, col, indent, "", "",
        !          3617:                         "\"", expr -> data.host_lookup -> hostname, "\"",
        !          3618:                         (char *)0);
        !          3619:                col = token_print_indent (file, col, indent, "", "", ")");
        !          3620:                break;
        !          3621: 
        !          3622:              case expr_add:
        !          3623:                s = "+";
        !          3624:                goto binary;
        !          3625: 
        !          3626:              case expr_subtract:
        !          3627:                s = "-";
        !          3628:                goto binary;
        !          3629: 
        !          3630:              case expr_multiply:
        !          3631:                s = "*";
        !          3632:                goto binary;
        !          3633: 
        !          3634:              case expr_divide:
        !          3635:                s = "/";
        !          3636:                goto binary;
        !          3637: 
        !          3638:              case expr_remainder:
        !          3639:                s = "%";
        !          3640:                goto binary;
        !          3641: 
        !          3642:              case expr_binary_and:
        !          3643:                s = "&";
        !          3644:                goto binary;
        !          3645: 
        !          3646:              case expr_binary_or:
        !          3647:                s = "|";
        !          3648:                goto binary;
        !          3649: 
        !          3650:              case expr_binary_xor:
        !          3651:                s = "^";
        !          3652:                goto binary;
        !          3653: 
        !          3654:              case expr_and:
        !          3655:                s = "and";
        !          3656:                goto binary;
        !          3657: 
        !          3658:              case expr_or:
        !          3659:                s = "or";
        !          3660:                goto binary;
        !          3661: 
        !          3662:              case expr_not:
        !          3663:                col = token_print_indent (file, col, indent, "", " ", "not");
        !          3664:                col = write_expression (file,
        !          3665:                                        expr -> data.not, col, indent + 2, 1);
        !          3666:                break;
        !          3667: 
        !          3668:              case expr_option:
        !          3669:                s = "option";
        !          3670: 
        !          3671:              print_option_name:
        !          3672:                col = token_print_indent (file, col, indent, "", "", s);
        !          3673: 
        !          3674:                if (expr -> data.option -> universe != &dhcp_universe) {
        !          3675:                        col = token_print_indent (file, col, indent,
        !          3676:                                                  " ", "",
        !          3677:                                                  (expr -> data.option -> 
        !          3678:                                                   universe -> name));
        !          3679:                        col = token_print_indent (file, col, indent, "", "",
        !          3680:                                                  ".");
        !          3681:                        col = token_print_indent (file, col, indent, "", "",
        !          3682:                                                  expr -> data.option -> name);
        !          3683:                } else {
        !          3684:                        col = token_print_indent (file, col, indent, " ", "",
        !          3685:                                                  expr -> data.option -> name);
        !          3686:                }
        !          3687:                break;
        !          3688: 
        !          3689:              case expr_hardware:       
        !          3690:                col = token_print_indent (file, col, indent, "", "",
        !          3691:                                          "hardware");
        !          3692:                break;
        !          3693: 
        !          3694:              case expr_packet:
        !          3695:                col = token_print_indent (file, col, indent, "", "",
        !          3696:                                          "packet");
        !          3697:                col = token_print_indent (file, col, indent, " ", "", "(");
        !          3698:                scol = col;
        !          3699:                col = write_expression (file, expr -> data.packet.offset,
        !          3700:                                        col, indent, 1);
        !          3701:                col = token_print_indent (file, col, scol, "", " ", ",");
        !          3702:                col = write_expression (file, expr -> data.packet.len,
        !          3703:                                        col, scol, 0);
        !          3704:                col = token_print_indent (file, col, indent, "", "", ")");
        !          3705:                break;
        !          3706: 
        !          3707:              case expr_const_data:
        !          3708:                col = token_indent_data_string (file, col, indent, "", "",
        !          3709:                                                &expr -> data.const_data);
        !          3710:                break;
        !          3711: 
        !          3712:              case expr_extract_int8:
        !          3713:                width = 8;
        !          3714:              extract_int:
        !          3715:                col = token_print_indent (file, col, indent, "", "",
        !          3716:                                          "extract-int");
        !          3717:                col = token_print_indent (file, col, indent, " ", "", "(");
        !          3718:                scol = col;
        !          3719:                col = write_expression (file, expr -> data.extract_int,
        !          3720:                                        col, indent, 1);
        !          3721:                col = token_print_indent (file, col, scol, "", " ", ",");
        !          3722:                sprintf (obuf, "%d", width);
        !          3723:                col = token_print_indent (file, col, scol, " ", "", obuf);
        !          3724:                col = token_print_indent (file, col, indent, "", "", ")");
        !          3725:                break;
        !          3726: 
        !          3727:              case expr_extract_int16:
        !          3728:                width = 16;
        !          3729:                goto extract_int;
        !          3730: 
        !          3731:              case expr_extract_int32:
        !          3732:                width = 32;
        !          3733:                goto extract_int;
        !          3734: 
        !          3735:              case expr_encode_int8:
        !          3736:                width = 8;
        !          3737:              encode_int:
        !          3738:                col = token_print_indent (file, col, indent, "", "",
        !          3739:                                          "encode-int");
        !          3740:                col = token_print_indent (file, col, indent, " ", "", "(");
        !          3741:                scol = col;
        !          3742:                col = write_expression (file, expr -> data.extract_int,
        !          3743:                                        col, indent, 1);
        !          3744:                col = token_print_indent (file, col, scol, "", " ", ",");
        !          3745:                sprintf (obuf, "%d", width);
        !          3746:                col = token_print_indent (file, col, scol, " ", "", obuf);
        !          3747:                col = token_print_indent (file, col, indent, "", "",
        !          3748:                                          ")");
        !          3749:                break;
        !          3750: 
        !          3751:              case expr_encode_int16:
        !          3752:                width = 16;
        !          3753:                goto encode_int;
        !          3754: 
        !          3755:              case expr_encode_int32:
        !          3756:                width = 32;
        !          3757:                goto encode_int;
        !          3758: 
        !          3759:              case expr_const_int:
        !          3760:                sprintf (obuf, "%lu", expr -> data.const_int);
        !          3761:                col = token_print_indent (file, col, indent, "", "", obuf);
        !          3762:                break;
        !          3763: 
        !          3764:              case expr_exists:
        !          3765:                s = "exists";
        !          3766:                goto print_option_name;
        !          3767: 
        !          3768:              case expr_encapsulate:
        !          3769:                col = token_print_indent (file, col, indent, "", "",
        !          3770:                                          "encapsulate");
        !          3771:                col = token_indent_data_string (file, col, indent, " ", "",
        !          3772:                                                &expr -> data.encapsulate);
        !          3773:                break;
        !          3774: 
        !          3775:              case expr_known:
        !          3776:                col = token_print_indent (file, col, indent, "", "", "known");
        !          3777:                break;
        !          3778: 
        !          3779:              case expr_reverse:
        !          3780:                col = token_print_indent (file, col, indent, "", "",
        !          3781:                                          "reverse");
        !          3782:                col = token_print_indent (file, col, indent, " ", "", "(");
        !          3783:                scol = col;
        !          3784:                col = write_expression (file, expr -> data.reverse.width,
        !          3785:                                        col, scol, 1);
        !          3786:                col = token_print_indent (file, col, scol, "", " ", ",");
        !          3787:                col = write_expression (file, expr -> data.reverse.buffer,
        !          3788:                                        col, scol, 0);
        !          3789:                col = token_print_indent (file, col, indent, "", "",
        !          3790:                                          ")");
        !          3791:                break;
        !          3792: 
        !          3793:              case expr_leased_address:
        !          3794:                col = token_print_indent (file, col, indent, "", "",
        !          3795:                                          "leased-address");
        !          3796:                break;
        !          3797: 
        !          3798:              case expr_client_state:
        !          3799:                col = token_print_indent (file, col, indent, "", "",
        !          3800:                                          "client-state");
        !          3801:                break;
        !          3802: 
        !          3803:              case expr_binary_to_ascii:
        !          3804:                col = token_print_indent (file, col, indent, "", "",
        !          3805:                                          "binary-to-ascii");
        !          3806:                col = token_print_indent (file, col, indent, " ", "",
        !          3807:                                          "(");
        !          3808:                scol = col;
        !          3809:                col = write_expression (file, expr -> data.b2a.base,
        !          3810:                                        col, scol, 1);
        !          3811:                col = token_print_indent (file, col, scol, "", " ",
        !          3812:                                          ",");
        !          3813:                col = write_expression (file, expr -> data.b2a.width,
        !          3814:                                        col, scol, 0);
        !          3815:                col = token_print_indent (file, col, scol, "", " ",
        !          3816:                                          ",");
        !          3817:                col = write_expression (file, expr -> data.b2a.separator,
        !          3818:                                        col, scol, 0);
        !          3819:                col = token_print_indent (file, col, scol, "", " ",
        !          3820:                                          ",");
        !          3821:                col = write_expression (file, expr -> data.b2a.buffer,
        !          3822:                                        col, scol, 0);
        !          3823:                col = token_print_indent (file, col, indent, "", "",
        !          3824:                                          ")");
        !          3825:                break;
        !          3826: 
        !          3827:              case expr_config_option:
        !          3828:                s = "config-option";
        !          3829:                goto print_option_name;
        !          3830: 
        !          3831:              case expr_host_decl_name:
        !          3832:                col = token_print_indent (file, col, indent, "", "",
        !          3833:                                          "host-decl-name");
        !          3834:                break;
        !          3835: 
        !          3836:              case expr_pick_first_value:
        !          3837:                e = expr;
        !          3838:                col = token_print_indent (file, col, indent, "", "",
        !          3839:                                          "concat");
        !          3840:                col = token_print_indent (file, col, indent, " ", "",
        !          3841:                                          "(");
        !          3842:                scol = col;
        !          3843:                firstp = 1;
        !          3844:              pick_again:
        !          3845:                col = write_expression (file,
        !          3846:                                        e -> data.pick_first_value.car,
        !          3847:                                        col, scol, firstp);
        !          3848:                firstp = 0;
        !          3849:                /* We're being very lisp-like right now - instead of
        !          3850:                    representing this expression as (first middle . last) we're
        !          3851:                    representing it as (first middle last), which means that the
        !          3852:                    tail cdr is always nil.  Apologies to non-wisp-lizards - may
        !          3853:                    this obscure way of describing the problem motivate you to
        !          3854:                    learn more about the one true computing language. */
        !          3855:                if (!e -> data.pick_first_value.cdr)
        !          3856:                        goto no_pick_cdr;
        !          3857:                col = token_print_indent (file, col, scol, "", " ",
        !          3858:                                          ",");
        !          3859:                if (e -> data.pick_first_value.cdr -> op ==
        !          3860:                    expr_pick_first_value) {
        !          3861:                        e = e -> data.pick_first_value.cdr;
        !          3862:                        goto pick_again;
        !          3863:                }
        !          3864:                col = write_expression (file,
        !          3865:                                        e -> data.pick_first_value.cdr,
        !          3866:                                        col, scol, 0);
        !          3867:              no_pick_cdr:
        !          3868:                col = token_print_indent (file, col, indent, "", "",
        !          3869:                                          ")");
        !          3870:                break;
        !          3871: 
        !          3872:              case expr_lease_time:
        !          3873:                col = token_print_indent (file, col, indent, "", "",
        !          3874:                                          "lease-time");
        !          3875:                break;
        !          3876: 
        !          3877:              case expr_dns_transaction:
        !          3878:                col = token_print_indent (file, col, indent, "", "",
        !          3879:                                          "ns-update");
        !          3880:                col = token_print_indent (file, col, indent, " ", "",
        !          3881:                                          "(");
        !          3882:                scol = 0;
        !          3883:                for (e = expr;
        !          3884:                     e && e -> op == expr_dns_transaction;
        !          3885:                     e = e -> data.dns_transaction.cdr) {
        !          3886:                        if (!scol) {
        !          3887:                                scol = col;
        !          3888:                                firstp = 1;
        !          3889:                        } else
        !          3890:                                firstp = 0;
        !          3891:                        col = write_expression (file,
        !          3892:                                                e -> data.dns_transaction.car,
        !          3893:                                                col, scol, firstp);
        !          3894:                        if (e -> data.dns_transaction.cdr)
        !          3895:                                col = token_print_indent (file, col, scol,
        !          3896:                                                          "", " ", ",");
        !          3897:                }
        !          3898:                if (e)
        !          3899:                        col = write_expression (file, e, col, scol, 0);
        !          3900:                col = token_print_indent (file, col, indent, "", "", ")");
        !          3901:                break;
        !          3902: 
        !          3903:              case expr_ns_add:
        !          3904:                col = token_print_indent (file, col, indent, "", "",
        !          3905:                                          "update");
        !          3906:                col = token_print_indent (file, col, indent, " ", "",
        !          3907:                                          "(");
        !          3908:                scol = col;
        !          3909:                sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
        !          3910:                col = token_print_indent (file, col, scol, "", "", obuf);
        !          3911:                col = token_print_indent (file, col, scol, "", " ",
        !          3912:                                          ",");
        !          3913:                sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
        !          3914:                col = token_print_indent (file, col, scol, "", "", obuf);
        !          3915:                col = token_print_indent (file, col, scol, "", " ",
        !          3916:                                          ",");
        !          3917:                col = write_expression (file, expr -> data.ns_add.rrname,
        !          3918:                                        col, scol, 0);
        !          3919:                col = token_print_indent (file, col, scol, "", " ",
        !          3920:                                          ",");
        !          3921:                col = write_expression (file, expr -> data.ns_add.rrdata,
        !          3922:                                        col, scol, 0);
        !          3923:                col = token_print_indent (file, col, scol, "", " ",
        !          3924:                                          ",");
        !          3925:                col = write_expression (file, expr -> data.ns_add.ttl,
        !          3926:                                        col, scol, 0);
        !          3927:                col = token_print_indent (file, col, indent, "", "",
        !          3928:                                          ")");
        !          3929:                break;
        !          3930: 
        !          3931:              case expr_ns_delete:
        !          3932:                col = token_print_indent (file, col, indent, "", "",
        !          3933:                                          "delete");
        !          3934:                col = token_print_indent (file, col, indent, " ", "",
        !          3935:                                          "(");
        !          3936:              finish_ns_small:
        !          3937:                scol = col;
        !          3938:                sprintf (obuf, "%d", expr -> data.ns_add.rrclass);
        !          3939:                col = token_print_indent (file, col, scol, "", "", obuf);
        !          3940:                col = token_print_indent (file, col, scol, "", " ",
        !          3941:                                          ",");
        !          3942:                sprintf (obuf, "%d", expr -> data.ns_add.rrtype);
        !          3943:                col = token_print_indent (file, col, scol, "", "", obuf);
        !          3944:                col = token_print_indent (file, col, scol, "", " ",
        !          3945:                                          ",");
        !          3946:                col = write_expression (file, expr -> data.ns_add.rrname,
        !          3947:                                        col, scol, 0);
        !          3948:                col = token_print_indent (file, col, scol, "", " ",
        !          3949:                                          ",");
        !          3950:                col = write_expression (file, expr -> data.ns_add.rrdata,
        !          3951:                                        col, scol, 0);
        !          3952:                col = token_print_indent (file, col, indent, "", "",
        !          3953:                                          ")");
        !          3954:                break;
        !          3955: 
        !          3956:              case expr_ns_exists:
        !          3957:                col = token_print_indent (file, col, indent, "", "",
        !          3958:                                          "exists");
        !          3959:                col = token_print_indent (file, col, indent, " ", "",
        !          3960:                                          "(");
        !          3961:                goto finish_ns_small;
        !          3962: 
        !          3963:              case expr_ns_not_exists:
        !          3964:                col = token_print_indent (file, col, indent, "", "",
        !          3965:                                          "not exists");
        !          3966:                col = token_print_indent (file, col, indent, " ", "",
        !          3967:                                          "(");
        !          3968:                goto finish_ns_small;
        !          3969: 
        !          3970:              case expr_static:
        !          3971:                col = token_print_indent (file, col, indent, "", "",
        !          3972:                                          "static");
        !          3973:                break;
        !          3974: 
        !          3975:              case expr_null:
        !          3976:                col = token_print_indent (file, col, indent, "", "", "null");
        !          3977:                break;
        !          3978: 
        !          3979:              case expr_variable_reference:
        !          3980:                col = token_print_indent (file, indent, indent, "", "",
        !          3981:                                          expr -> data.variable);
        !          3982:                break;
        !          3983: 
        !          3984:              case expr_variable_exists:
        !          3985:                col = token_print_indent (file, indent, indent, "", "",
        !          3986:                                          "defined");
        !          3987:                col = token_print_indent (file, col, indent, " ", "", "(");
        !          3988:                col = token_print_indent (file, col, indent, "", "",
        !          3989:                                          expr -> data.variable);
        !          3990:                col = token_print_indent (file, col, indent, "", "", ")");
        !          3991:                break;
        !          3992: 
        !          3993:              case expr_funcall:
        !          3994:                col = token_print_indent(file, indent, indent, "", "",
        !          3995:                                         expr->data.funcall.name);
        !          3996:                col = token_print_indent(file, col, indent, " ", "", "(");
        !          3997: 
        !          3998:                firstp = 1;
        !          3999:                e = expr->data.funcall.arglist;
        !          4000:                while (e != NULL) {
        !          4001:                        if (!firstp)
        !          4002:                                col = token_print_indent(file, col, indent,
        !          4003:                                                         "", " ", ",");
        !          4004: 
        !          4005:                        col = write_expression(file, e->data.arg.val, col,
        !          4006:                                               indent, firstp);
        !          4007:                        firstp = 0;
        !          4008:                        e = e->data.arg.next;
        !          4009:                }
        !          4010: 
        !          4011:                col = token_print_indent(file, col, indent, "", "", ")");
        !          4012:                break;
        !          4013: 
        !          4014:              default:
        !          4015:                log_fatal ("invalid expression type in print_expression: %d",
        !          4016:                           expr -> op);
        !          4017:        }
        !          4018:        return col;
        !          4019: }
        !          4020: 
        !          4021: struct binding *find_binding (struct binding_scope *scope, const char *name)
        !          4022: {
        !          4023:        struct binding *bp;
        !          4024:        struct binding_scope *s;
        !          4025: 
        !          4026:        for (s = scope; s; s = s -> outer) {
        !          4027:                for (bp = s -> bindings; bp; bp = bp -> next) {
        !          4028:                        if (!strcasecmp (name, bp -> name)) {
        !          4029:                                return bp;
        !          4030:                        }
        !          4031:                }
        !          4032:        }
        !          4033:        return (struct binding *)0;
        !          4034: }
        !          4035: 
        !          4036: int free_bindings (struct binding_scope *scope, const char *file, int line)
        !          4037: {
        !          4038:        struct binding *bp, *next;
        !          4039: 
        !          4040:        for (bp = scope -> bindings; bp; bp = next) {
        !          4041:                next = bp -> next;
        !          4042:                if (bp -> name)
        !          4043:                        dfree (bp -> name, file, line);
        !          4044:                if (bp -> value)
        !          4045:                        binding_value_dereference (&bp -> value, file, line);
        !          4046:                dfree (bp, file, line);
        !          4047:        }
        !          4048:        scope -> bindings = (struct binding *)0;
        !          4049:        return 1;
        !          4050: }
        !          4051: 
        !          4052: int binding_scope_dereference (ptr, file, line)
        !          4053:        struct binding_scope **ptr;
        !          4054:        const char *file;
        !          4055:        int line;
        !          4056: {
        !          4057:        struct binding_scope *binding_scope;
        !          4058: 
        !          4059:        if (!ptr || !*ptr) {
        !          4060:                log_error ("%s(%d): null pointer", file, line);
        !          4061: #if defined (POINTER_DEBUG)
        !          4062:                abort ();
        !          4063: #else
        !          4064:                return 0;
        !          4065: #endif
        !          4066:        }
        !          4067: 
        !          4068:        binding_scope = *ptr;
        !          4069:        *ptr = (struct binding_scope *)0;
        !          4070:        --binding_scope -> refcnt;
        !          4071:        rc_register (file, line, ptr,
        !          4072:                     binding_scope, binding_scope -> refcnt, 1, RC_MISC);
        !          4073:        if (binding_scope -> refcnt > 0)
        !          4074:                return 1;
        !          4075: 
        !          4076:        if (binding_scope -> refcnt < 0) {
        !          4077:                log_error ("%s(%d): negative refcnt!", file, line);
        !          4078: #if defined (DEBUG_RC_HISTORY)
        !          4079:                dump_rc_history (binding_scope);
        !          4080: #endif
        !          4081: #if defined (POINTER_DEBUG)
        !          4082:                abort ();
        !          4083: #else
        !          4084:                return 0;
        !          4085: #endif
        !          4086:        }
        !          4087: 
        !          4088:        free_bindings (binding_scope, file, line);
        !          4089:        if (binding_scope -> outer)
        !          4090:                binding_scope_dereference (&binding_scope -> outer, MDL);
        !          4091:        dfree (binding_scope, file, line);
        !          4092:        return 1;
        !          4093: }
        !          4094: 
        !          4095: int fundef_dereference (ptr, file, line)
        !          4096:        struct fundef **ptr;
        !          4097:        const char *file;
        !          4098:        int line;
        !          4099: {
        !          4100:        struct fundef *bp = *ptr;
        !          4101:        struct string_list *sp, *next;
        !          4102: 
        !          4103:        if (!ptr) {
        !          4104:                log_error ("%s(%d): null pointer", file, line);
        !          4105: #if defined (POINTER_DEBUG)
        !          4106:                abort ();
        !          4107: #else
        !          4108:                return 0;
        !          4109: #endif
        !          4110:        }
        !          4111: 
        !          4112:        if (!bp) {
        !          4113:                log_error ("%s(%d): null pointer", file, line);
        !          4114: #if defined (POINTER_DEBUG)
        !          4115:                abort ();
        !          4116: #else
        !          4117:                return 0;
        !          4118: #endif
        !          4119:        }
        !          4120: 
        !          4121:        bp -> refcnt--;
        !          4122:        rc_register (file, line, ptr, bp, bp -> refcnt, 1, RC_MISC);
        !          4123:        if (bp -> refcnt < 0) {
        !          4124:                log_error ("%s(%d): negative refcnt!", file, line);
        !          4125: #if defined (DEBUG_RC_HISTORY)
        !          4126:                dump_rc_history (bp);
        !          4127: #endif
        !          4128: #if defined (POINTER_DEBUG)
        !          4129:                abort ();
        !          4130: #else
        !          4131:                return 0;
        !          4132: #endif
        !          4133:        }
        !          4134:        if (!bp -> refcnt) {
        !          4135:                for (sp = bp -> args; sp; sp = next) {
        !          4136:                        next = sp -> next;
        !          4137:                        dfree (sp, file, line);
        !          4138:                }
        !          4139:                if (bp -> statements)
        !          4140:                        executable_statement_dereference (&bp -> statements,
        !          4141:                                                          file, line);
        !          4142:                dfree (bp, file, line);
        !          4143:        }
        !          4144:        *ptr = (struct fundef *)0;
        !          4145:        return 1;
        !          4146: }
        !          4147: 
        !          4148: #if defined (NOTYET)           /* Post 3.0 final. */
        !          4149: int data_subexpression_length (int *rv,
        !          4150:                               struct expression *expr)
        !          4151: {
        !          4152:        int crhs, clhs, llhs, lrhs;
        !          4153:        switch (expr -> op) {
        !          4154:              case expr_substring:
        !          4155:                if (expr -> data.substring.len &&
        !          4156:                    expr -> data.substring.len -> op == expr_const_int) {
        !          4157:                        (*rv =
        !          4158:                         (int)expr -> data.substring.len -> data.const_int);
        !          4159:                        return 1;
        !          4160:                }
        !          4161:                return 0;
        !          4162: 
        !          4163:              case expr_packet:
        !          4164:              case expr_suffix:
        !          4165:                if (expr -> data.suffix.len &&
        !          4166:                    expr -> data.suffix.len -> op == expr_const_int) {
        !          4167:                        (*rv =
        !          4168:                         (int)expr -> data.suffix.len -> data.const_int);
        !          4169:                        return 1;
        !          4170:                }
        !          4171:                return 0;
        !          4172: 
        !          4173:              case expr_lcase:
        !          4174:                return data_subexpression_length(rv, expr->data.lcase);
        !          4175: 
        !          4176:              case expr_ucase:
        !          4177:                return data_subexpression_length(rv, expr->data.ucase);
        !          4178: 
        !          4179:              case expr_concat:
        !          4180:                clhs = data_subexpression_length (&llhs,
        !          4181:                                                  expr -> data.concat [0]);
        !          4182:                crhs = data_subexpression_length (&lrhs,
        !          4183:                                                  expr -> data.concat [1]);
        !          4184:                if (crhs == 0 || clhs == 0)
        !          4185:                        return 0;
        !          4186:                *rv = llhs + lrhs;
        !          4187:                return 1;
        !          4188:                break;
        !          4189: 
        !          4190:              case expr_hardware:
        !          4191:                return 0;
        !          4192: 
        !          4193:              case expr_const_data:
        !          4194:                *rv = expr -> data.const_data.len;
        !          4195:                return 2;
        !          4196: 
        !          4197:              case expr_reverse:
        !          4198:                return data_subexpression_length (rv,
        !          4199:                                                  expr -> data.reverse.buffer);
        !          4200: 
        !          4201:              case expr_leased_address:
        !          4202:              case expr_lease_time:
        !          4203:                *rv = 4;
        !          4204:                return 2;
        !          4205: 
        !          4206:              case expr_pick_first_value:
        !          4207:                clhs = data_subexpression_length (&llhs,
        !          4208:                                                  expr -> data.concat [0]);
        !          4209:                crhs = data_subexpression_length (&lrhs,
        !          4210:                                                  expr -> data.concat [1]);
        !          4211:                if (crhs == 0 || clhs == 0)
        !          4212:                        return 0;
        !          4213:                if (llhs > lrhs)
        !          4214:                        *rv = llhs;
        !          4215:                else
        !          4216:                        *rv = lrhs;
        !          4217:                return 1;
        !          4218:                        
        !          4219:              case expr_binary_to_ascii:
        !          4220:              case expr_config_option:
        !          4221:              case expr_host_decl_name:
        !          4222:              case expr_encapsulate:
        !          4223:              case expr_filename:
        !          4224:              case expr_sname:
        !          4225:              case expr_host_lookup:
        !          4226:              case expr_option:
        !          4227:              case expr_none:
        !          4228:              case expr_match:
        !          4229:              case expr_check:
        !          4230:              case expr_equal:
        !          4231:              case expr_regex_match:
        !          4232:              case expr_iregex_match:
        !          4233:              case expr_and:
        !          4234:              case expr_or:
        !          4235:              case expr_not:
        !          4236:              case expr_extract_int8:
        !          4237:              case expr_extract_int16:
        !          4238:              case expr_extract_int32:
        !          4239:              case expr_encode_int8:
        !          4240:              case expr_encode_int16:
        !          4241:              case expr_encode_int32:
        !          4242:              case expr_const_int:
        !          4243:              case expr_exists:
        !          4244:              case expr_known:
        !          4245:              case expr_dns_transaction:
        !          4246:              case expr_static:
        !          4247:              case expr_ns_add:
        !          4248:              case expr_ns_delete:
        !          4249:              case expr_ns_exists:
        !          4250:              case expr_ns_not_exists:
        !          4251:              case expr_not_equal:
        !          4252:              case expr_null:
        !          4253:              case expr_variable_exists:
        !          4254:              case expr_variable_reference:
        !          4255:              case expr_arg:
        !          4256:              case expr_funcall:
        !          4257:              case expr_function:
        !          4258:              case expr_add:
        !          4259:              case expr_subtract:
        !          4260:              case expr_multiply:
        !          4261:              case expr_divide:
        !          4262:              case expr_remainder:
        !          4263:              case expr_binary_and:
        !          4264:              case expr_binary_or:
        !          4265:              case expr_binary_xor:
        !          4266:              case expr_client_state:
        !          4267:                return 0;
        !          4268:        }
        !          4269:        return 0;
        !          4270: }
        !          4271: 
        !          4272: int expr_valid_for_context (struct expression *expr,
        !          4273:                            enum expression_context context)
        !          4274: {
        !          4275:        /* We don't know at parse time what type of value a function may
        !          4276:           return, so we can't flag an error on it. */
        !          4277:        if (expr -> op == expr_funcall ||
        !          4278:            expr -> op == expr_variable_reference)
        !          4279:                return 1;
        !          4280: 
        !          4281:        switch (context) {
        !          4282:              case context_any:
        !          4283:                return 1;
        !          4284: 
        !          4285:              case context_boolean:
        !          4286:                if (is_boolean_expression (expr))
        !          4287:                        return 1;
        !          4288:                return 0;
        !          4289: 
        !          4290:              case context_data:
        !          4291:                if (is_data_expression (expr))
        !          4292:                        return 1;
        !          4293:                return 0;
        !          4294: 
        !          4295:              case context_numeric:
        !          4296:                if (is_numeric_expression (expr))
        !          4297:                        return 1;
        !          4298:                return 0;
        !          4299: 
        !          4300:              case context_dns:
        !          4301:                if (is_dns_expression (expr)) {
        !          4302:                        return 1;
        !          4303:                }
        !          4304:                return 0;
        !          4305: 
        !          4306:              case context_data_or_numeric:
        !          4307:                if (is_numeric_expression (expr) ||
        !          4308:                    is_data_expression (expr)) {
        !          4309:                        return 1;
        !          4310:                }
        !          4311:                return 0;
        !          4312: 
        !          4313:              case context_function:
        !          4314:                if (expr -> op == expr_function)
        !          4315:                        return 1;
        !          4316:                return 0;
        !          4317:        }
        !          4318:        return 0;
        !          4319: }
        !          4320: #endif /* NOTYET */
        !          4321: 
        !          4322: struct binding *create_binding (struct binding_scope **scope, const char *name)
        !          4323: {
        !          4324:        struct binding *binding;
        !          4325: 
        !          4326:        if (!*scope) {
        !          4327:                if (!binding_scope_allocate (scope, MDL))
        !          4328:                        return (struct binding *)0;
        !          4329:        }
        !          4330: 
        !          4331:        binding = find_binding (*scope, name);
        !          4332:        if (!binding) {
        !          4333:                binding = dmalloc (sizeof *binding, MDL);
        !          4334:                if (!binding)
        !          4335:                        return (struct binding *)0;
        !          4336: 
        !          4337:                memset (binding, 0, sizeof *binding);
        !          4338:                binding -> name = dmalloc (strlen (name) + 1, MDL);
        !          4339:                if (!binding -> name) {
        !          4340:                        dfree (binding, MDL);
        !          4341:                        return (struct binding *)0;
        !          4342:                }
        !          4343:                strcpy (binding -> name, name);
        !          4344: 
        !          4345:                binding -> next = (*scope) -> bindings;
        !          4346:                (*scope) -> bindings = binding;
        !          4347:        }
        !          4348: 
        !          4349:        return binding;
        !          4350: }
        !          4351: 
        !          4352: 
        !          4353: int bind_ds_value (struct binding_scope **scope,
        !          4354:                   const char *name,
        !          4355:                   struct data_string *value)
        !          4356: {
        !          4357:        struct binding *binding;
        !          4358: 
        !          4359:        binding = create_binding (scope, name);
        !          4360:        if (!binding)
        !          4361:                return 0;
        !          4362: 
        !          4363:        if (binding -> value)
        !          4364:                binding_value_dereference (&binding -> value, MDL);
        !          4365: 
        !          4366:        if (!binding_value_allocate (&binding -> value, MDL))
        !          4367:                return 0;
        !          4368: 
        !          4369:        data_string_copy (&binding -> value -> value.data, value, MDL);
        !          4370:        binding -> value -> type = binding_data;
        !          4371: 
        !          4372:        return 1;
        !          4373: }
        !          4374: 
        !          4375: 
        !          4376: int find_bound_string (struct data_string *value,
        !          4377:                       struct binding_scope *scope,
        !          4378:                       const char *name)
        !          4379: {
        !          4380:        struct binding *binding;
        !          4381: 
        !          4382:        binding = find_binding (scope, name);
        !          4383:        if (!binding ||
        !          4384:            !binding -> value ||
        !          4385:            binding -> value -> type != binding_data)
        !          4386:                return 0;
        !          4387: 
        !          4388:        if (binding -> value -> value.data.terminated) {
        !          4389:                data_string_copy (value, &binding -> value -> value.data, MDL);
        !          4390:        } else {
        !          4391:                buffer_allocate (&value -> buffer,
        !          4392:                                 binding -> value -> value.data.len,
        !          4393:                                 MDL);
        !          4394:                if (!value -> buffer)
        !          4395:                        return 0;
        !          4396: 
        !          4397:                memcpy (value -> buffer -> data,
        !          4398:                        binding -> value -> value.data.data,
        !          4399:                        binding -> value -> value.data.len);
        !          4400:                value -> data = value -> buffer -> data;
        !          4401:                value -> len = binding -> value -> value.data.len;
        !          4402:        }
        !          4403: 
        !          4404:        return 1;
        !          4405: }
        !          4406: 
        !          4407: int unset (struct binding_scope *scope, const char *name)
        !          4408: {
        !          4409:        struct binding *binding;
        !          4410: 
        !          4411:        binding = find_binding (scope, name);
        !          4412:        if (binding) {
        !          4413:                if (binding -> value)
        !          4414:                        binding_value_dereference
        !          4415:                                (&binding -> value, MDL);
        !          4416:                return 1;
        !          4417:        }
        !          4418:        return 0;
        !          4419: }
        !          4420: 
        !          4421: /* vim: set tabstop=8: */

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