~ubuntu-branches/ubuntu/oneiric/isc-dhcp/oneiric-security

« back to all changes in this revision

Viewing changes to common/tree.c

  • Committer: Bazaar Package Importer
  • Author(s): Andrew Pollock
  • Date: 2009-09-02 22:34:25 UTC
  • Revision ID: james.westby@ubuntu.com-20090902223425-nypo7bkftxffq41m
Tags: upstream-4.1.0
ImportĀ upstreamĀ versionĀ 4.1.0

Show diffs side-by-side

added added

removed removed

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