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