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