xref: /minix3/external/bsd/dhcp/dist/common/print.c (revision 83ee113ee0d94f3844d44065af2311604e9a30ad)
1*83ee113eSDavid van Moolenbroek /*	$NetBSD: print.c,v 1.1.1.3 2014/07/12 11:57:46 spz Exp $	*/
2*83ee113eSDavid van Moolenbroek /* print.c
3*83ee113eSDavid van Moolenbroek 
4*83ee113eSDavid van Moolenbroek    Turn data structures into printable text. */
5*83ee113eSDavid van Moolenbroek 
6*83ee113eSDavid van Moolenbroek /*
7*83ee113eSDavid van Moolenbroek  * Copyright (c) 2009-2014 by Internet Systems Consortium, Inc. ("ISC")
8*83ee113eSDavid van Moolenbroek  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
9*83ee113eSDavid van Moolenbroek  * Copyright (c) 1995-2003 by Internet Software Consortium
10*83ee113eSDavid van Moolenbroek  *
11*83ee113eSDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
12*83ee113eSDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
13*83ee113eSDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
14*83ee113eSDavid van Moolenbroek  *
15*83ee113eSDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16*83ee113eSDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17*83ee113eSDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
18*83ee113eSDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19*83ee113eSDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20*83ee113eSDavid van Moolenbroek  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21*83ee113eSDavid van Moolenbroek  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22*83ee113eSDavid van Moolenbroek  *
23*83ee113eSDavid van Moolenbroek  *   Internet Systems Consortium, Inc.
24*83ee113eSDavid van Moolenbroek  *   950 Charter Street
25*83ee113eSDavid van Moolenbroek  *   Redwood City, CA 94063
26*83ee113eSDavid van Moolenbroek  *   <info@isc.org>
27*83ee113eSDavid van Moolenbroek  *   https://www.isc.org/
28*83ee113eSDavid van Moolenbroek  *
29*83ee113eSDavid van Moolenbroek  */
30*83ee113eSDavid van Moolenbroek 
31*83ee113eSDavid van Moolenbroek #include <sys/cdefs.h>
32*83ee113eSDavid van Moolenbroek __RCSID("$NetBSD: print.c,v 1.1.1.3 2014/07/12 11:57:46 spz Exp $");
33*83ee113eSDavid van Moolenbroek 
34*83ee113eSDavid van Moolenbroek #include "dhcpd.h"
35*83ee113eSDavid van Moolenbroek 
36*83ee113eSDavid van Moolenbroek int db_time_format = DEFAULT_TIME_FORMAT;
37*83ee113eSDavid van Moolenbroek 
quotify_string(const char * s,const char * file,int line)38*83ee113eSDavid van Moolenbroek char *quotify_string (const char *s, const char *file, int line)
39*83ee113eSDavid van Moolenbroek {
40*83ee113eSDavid van Moolenbroek 	unsigned len = 0;
41*83ee113eSDavid van Moolenbroek 	const char *sp;
42*83ee113eSDavid van Moolenbroek 	char *buf, *nsp;
43*83ee113eSDavid van Moolenbroek 
44*83ee113eSDavid van Moolenbroek 	for (sp = s; sp && *sp; sp++) {
45*83ee113eSDavid van Moolenbroek 		if (*sp == ' ')
46*83ee113eSDavid van Moolenbroek 			len++;
47*83ee113eSDavid van Moolenbroek 		else if (!isascii ((int)*sp) || !isprint ((int)*sp))
48*83ee113eSDavid van Moolenbroek 			len += 4;
49*83ee113eSDavid van Moolenbroek 		else if (*sp == '"' || *sp == '\\')
50*83ee113eSDavid van Moolenbroek 			len += 2;
51*83ee113eSDavid van Moolenbroek 		else
52*83ee113eSDavid van Moolenbroek 			len++;
53*83ee113eSDavid van Moolenbroek 	}
54*83ee113eSDavid van Moolenbroek 
55*83ee113eSDavid van Moolenbroek 	buf = dmalloc (len + 1, file, line);
56*83ee113eSDavid van Moolenbroek 	if (buf) {
57*83ee113eSDavid van Moolenbroek 		nsp = buf;
58*83ee113eSDavid van Moolenbroek 		for (sp = s; sp && *sp; sp++) {
59*83ee113eSDavid van Moolenbroek 			if (*sp == ' ')
60*83ee113eSDavid van Moolenbroek 				*nsp++ = ' ';
61*83ee113eSDavid van Moolenbroek 			else if (!isascii ((int)*sp) || !isprint ((int)*sp)) {
62*83ee113eSDavid van Moolenbroek 				sprintf (nsp, "\\%03o",
63*83ee113eSDavid van Moolenbroek 					 *(const unsigned char *)sp);
64*83ee113eSDavid van Moolenbroek 				nsp += 4;
65*83ee113eSDavid van Moolenbroek 			} else if (*sp == '"' || *sp == '\\') {
66*83ee113eSDavid van Moolenbroek 				*nsp++ = '\\';
67*83ee113eSDavid van Moolenbroek 				*nsp++ = *sp;
68*83ee113eSDavid van Moolenbroek 			} else
69*83ee113eSDavid van Moolenbroek 				*nsp++ = *sp;
70*83ee113eSDavid van Moolenbroek 		}
71*83ee113eSDavid van Moolenbroek 		*nsp++ = 0;
72*83ee113eSDavid van Moolenbroek 	}
73*83ee113eSDavid van Moolenbroek 	return buf;
74*83ee113eSDavid van Moolenbroek }
75*83ee113eSDavid van Moolenbroek 
quotify_buf(const unsigned char * s,unsigned len,const char * file,int line)76*83ee113eSDavid van Moolenbroek char *quotify_buf (const unsigned char *s, unsigned len,
77*83ee113eSDavid van Moolenbroek 		   const char *file, int line)
78*83ee113eSDavid van Moolenbroek {
79*83ee113eSDavid van Moolenbroek 	unsigned nulen = 0;
80*83ee113eSDavid van Moolenbroek 	char *buf, *nsp;
81*83ee113eSDavid van Moolenbroek 	int i;
82*83ee113eSDavid van Moolenbroek 
83*83ee113eSDavid van Moolenbroek 	for (i = 0; i < len; i++) {
84*83ee113eSDavid van Moolenbroek 		if (s [i] == ' ')
85*83ee113eSDavid van Moolenbroek 			nulen++;
86*83ee113eSDavid van Moolenbroek 		else if (!isascii (s [i]) || !isprint (s [i]))
87*83ee113eSDavid van Moolenbroek 			nulen += 4;
88*83ee113eSDavid van Moolenbroek 		else if (s [i] == '"' || s [i] == '\\')
89*83ee113eSDavid van Moolenbroek 			nulen += 2;
90*83ee113eSDavid van Moolenbroek 		else
91*83ee113eSDavid van Moolenbroek 			nulen++;
92*83ee113eSDavid van Moolenbroek 	}
93*83ee113eSDavid van Moolenbroek 
94*83ee113eSDavid van Moolenbroek 	buf = dmalloc (nulen + 1, MDL);
95*83ee113eSDavid van Moolenbroek 	if (buf) {
96*83ee113eSDavid van Moolenbroek 		nsp = buf;
97*83ee113eSDavid van Moolenbroek 		for (i = 0; i < len; i++) {
98*83ee113eSDavid van Moolenbroek 			if (s [i] == ' ')
99*83ee113eSDavid van Moolenbroek 				*nsp++ = ' ';
100*83ee113eSDavid van Moolenbroek 			else if (!isascii (s [i]) || !isprint (s [i])) {
101*83ee113eSDavid van Moolenbroek 				sprintf (nsp, "\\%03o", s [i]);
102*83ee113eSDavid van Moolenbroek 				nsp += 4;
103*83ee113eSDavid van Moolenbroek 			} else if (s [i] == '"' || s [i] == '\\') {
104*83ee113eSDavid van Moolenbroek 				*nsp++ = '\\';
105*83ee113eSDavid van Moolenbroek 				*nsp++ = s [i];
106*83ee113eSDavid van Moolenbroek 			} else
107*83ee113eSDavid van Moolenbroek 				*nsp++ = s [i];
108*83ee113eSDavid van Moolenbroek 		}
109*83ee113eSDavid van Moolenbroek 		*nsp++ = 0;
110*83ee113eSDavid van Moolenbroek 	}
111*83ee113eSDavid van Moolenbroek 	return buf;
112*83ee113eSDavid van Moolenbroek }
113*83ee113eSDavid van Moolenbroek 
print_base64(const unsigned char * buf,unsigned len,const char * file,int line)114*83ee113eSDavid van Moolenbroek char *print_base64 (const unsigned char *buf, unsigned len,
115*83ee113eSDavid van Moolenbroek 		    const char *file, int line)
116*83ee113eSDavid van Moolenbroek {
117*83ee113eSDavid van Moolenbroek 	char *s, *b;
118*83ee113eSDavid van Moolenbroek 	unsigned bl;
119*83ee113eSDavid van Moolenbroek 	int i;
120*83ee113eSDavid van Moolenbroek 	unsigned val, extra;
121*83ee113eSDavid van Moolenbroek 	static char to64 [] =
122*83ee113eSDavid van Moolenbroek 	   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
123*83ee113eSDavid van Moolenbroek 
124*83ee113eSDavid van Moolenbroek 	bl = ((len * 4 + 2) / 3) + 1;
125*83ee113eSDavid van Moolenbroek 	b = dmalloc (bl + 1, file, line);
126*83ee113eSDavid van Moolenbroek 	if (!b)
127*83ee113eSDavid van Moolenbroek 		return (char *)0;
128*83ee113eSDavid van Moolenbroek 
129*83ee113eSDavid van Moolenbroek 	i = 0;
130*83ee113eSDavid van Moolenbroek 	s = b;
131*83ee113eSDavid van Moolenbroek 	while (i != len) {
132*83ee113eSDavid van Moolenbroek 		val = buf [i++];
133*83ee113eSDavid van Moolenbroek 		extra = val & 3;
134*83ee113eSDavid van Moolenbroek 		val = val >> 2;
135*83ee113eSDavid van Moolenbroek 		*s++ = to64 [val];
136*83ee113eSDavid van Moolenbroek 		if (i == len) {
137*83ee113eSDavid van Moolenbroek 			*s++ = to64 [extra << 4];
138*83ee113eSDavid van Moolenbroek 			*s++ = '=';
139*83ee113eSDavid van Moolenbroek 			break;
140*83ee113eSDavid van Moolenbroek 		}
141*83ee113eSDavid van Moolenbroek 		val = (extra << 8) + buf [i++];
142*83ee113eSDavid van Moolenbroek 		extra = val & 15;
143*83ee113eSDavid van Moolenbroek 		val = val >> 4;
144*83ee113eSDavid van Moolenbroek 		*s++ = to64 [val];
145*83ee113eSDavid van Moolenbroek 		if (i == len) {
146*83ee113eSDavid van Moolenbroek 			*s++ = to64 [extra << 2];
147*83ee113eSDavid van Moolenbroek 			*s++ = '=';
148*83ee113eSDavid van Moolenbroek 			break;
149*83ee113eSDavid van Moolenbroek 		}
150*83ee113eSDavid van Moolenbroek 		val = (extra << 8) + buf [i++];
151*83ee113eSDavid van Moolenbroek 		extra = val & 0x3f;
152*83ee113eSDavid van Moolenbroek 		val = val >> 6;
153*83ee113eSDavid van Moolenbroek 		*s++ = to64 [val];
154*83ee113eSDavid van Moolenbroek 		*s++ = to64 [extra];
155*83ee113eSDavid van Moolenbroek 	}
156*83ee113eSDavid van Moolenbroek 	if (!len)
157*83ee113eSDavid van Moolenbroek 		*s++ = '=';
158*83ee113eSDavid van Moolenbroek 	*s++ = 0;
159*83ee113eSDavid van Moolenbroek 	if (s > b + bl + 1)
160*83ee113eSDavid van Moolenbroek 		abort ();
161*83ee113eSDavid van Moolenbroek 	return b;
162*83ee113eSDavid van Moolenbroek }
163*83ee113eSDavid van Moolenbroek 
print_hw_addr(htype,hlen,data)164*83ee113eSDavid van Moolenbroek char *print_hw_addr (htype, hlen, data)
165*83ee113eSDavid van Moolenbroek 	const int htype;
166*83ee113eSDavid van Moolenbroek 	const int hlen;
167*83ee113eSDavid van Moolenbroek 	const unsigned char *data;
168*83ee113eSDavid van Moolenbroek {
169*83ee113eSDavid van Moolenbroek 	static char habuf [49];
170*83ee113eSDavid van Moolenbroek 	char *s;
171*83ee113eSDavid van Moolenbroek 	int i;
172*83ee113eSDavid van Moolenbroek 
173*83ee113eSDavid van Moolenbroek 	if (hlen <= 0)
174*83ee113eSDavid van Moolenbroek 		habuf [0] = 0;
175*83ee113eSDavid van Moolenbroek 	else {
176*83ee113eSDavid van Moolenbroek 		s = habuf;
177*83ee113eSDavid van Moolenbroek 		for (i = 0; i < hlen; i++) {
178*83ee113eSDavid van Moolenbroek 			sprintf (s, "%02x", data [i]);
179*83ee113eSDavid van Moolenbroek 			s += strlen (s);
180*83ee113eSDavid van Moolenbroek 			*s++ = ':';
181*83ee113eSDavid van Moolenbroek 		}
182*83ee113eSDavid van Moolenbroek 		*--s = 0;
183*83ee113eSDavid van Moolenbroek 	}
184*83ee113eSDavid van Moolenbroek 	return habuf;
185*83ee113eSDavid van Moolenbroek }
186*83ee113eSDavid van Moolenbroek 
print_lease(lease)187*83ee113eSDavid van Moolenbroek void print_lease (lease)
188*83ee113eSDavid van Moolenbroek 	struct lease *lease;
189*83ee113eSDavid van Moolenbroek {
190*83ee113eSDavid van Moolenbroek 	struct tm *t;
191*83ee113eSDavid van Moolenbroek 	char tbuf [32];
192*83ee113eSDavid van Moolenbroek 
193*83ee113eSDavid van Moolenbroek 	log_debug ("  Lease %s",
194*83ee113eSDavid van Moolenbroek 	       piaddr (lease -> ip_addr));
195*83ee113eSDavid van Moolenbroek 
196*83ee113eSDavid van Moolenbroek 	t = gmtime (&lease -> starts);
197*83ee113eSDavid van Moolenbroek 	strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
198*83ee113eSDavid van Moolenbroek 	log_debug ("  start %s", tbuf);
199*83ee113eSDavid van Moolenbroek 
200*83ee113eSDavid van Moolenbroek 	t = gmtime (&lease -> ends);
201*83ee113eSDavid van Moolenbroek 	strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t);
202*83ee113eSDavid van Moolenbroek 	log_debug ("  end %s", tbuf);
203*83ee113eSDavid van Moolenbroek 
204*83ee113eSDavid van Moolenbroek 	if (lease -> hardware_addr.hlen)
205*83ee113eSDavid van Moolenbroek 		log_debug ("    hardware addr = %s",
206*83ee113eSDavid van Moolenbroek 			   print_hw_addr (lease -> hardware_addr.hbuf [0],
207*83ee113eSDavid van Moolenbroek 					  lease -> hardware_addr.hlen - 1,
208*83ee113eSDavid van Moolenbroek 					  &lease -> hardware_addr.hbuf [1]));
209*83ee113eSDavid van Moolenbroek 	log_debug ("  host %s  ",
210*83ee113eSDavid van Moolenbroek 	       lease -> host ? lease -> host -> name : "<none>");
211*83ee113eSDavid van Moolenbroek }
212*83ee113eSDavid van Moolenbroek 
213*83ee113eSDavid van Moolenbroek #if defined (DEBUG_PACKET)
dump_packet_option(struct option_cache * oc,struct packet * packet,struct lease * lease,struct client_state * client,struct option_state * in_options,struct option_state * cfg_options,struct binding_scope ** scope,struct universe * u,void * foo)214*83ee113eSDavid van Moolenbroek void dump_packet_option (struct option_cache *oc,
215*83ee113eSDavid van Moolenbroek 			 struct packet *packet,
216*83ee113eSDavid van Moolenbroek 			 struct lease *lease,
217*83ee113eSDavid van Moolenbroek 			 struct client_state *client,
218*83ee113eSDavid van Moolenbroek 			 struct option_state *in_options,
219*83ee113eSDavid van Moolenbroek 			 struct option_state *cfg_options,
220*83ee113eSDavid van Moolenbroek 			 struct binding_scope **scope,
221*83ee113eSDavid van Moolenbroek 			 struct universe *u, void *foo)
222*83ee113eSDavid van Moolenbroek {
223*83ee113eSDavid van Moolenbroek 	const char *name, *dot;
224*83ee113eSDavid van Moolenbroek 	struct data_string ds;
225*83ee113eSDavid van Moolenbroek 	memset (&ds, 0, sizeof ds);
226*83ee113eSDavid van Moolenbroek 
227*83ee113eSDavid van Moolenbroek 	if (u != &dhcp_universe) {
228*83ee113eSDavid van Moolenbroek 		name = u -> name;
229*83ee113eSDavid van Moolenbroek 		dot = ".";
230*83ee113eSDavid van Moolenbroek 	} else {
231*83ee113eSDavid van Moolenbroek 		name = "";
232*83ee113eSDavid van Moolenbroek 		dot = "";
233*83ee113eSDavid van Moolenbroek 	}
234*83ee113eSDavid van Moolenbroek 	if (evaluate_option_cache (&ds, packet, lease, client,
235*83ee113eSDavid van Moolenbroek 				   in_options, cfg_options, scope, oc, MDL)) {
236*83ee113eSDavid van Moolenbroek 		log_debug ("  option %s%s%s %s;\n",
237*83ee113eSDavid van Moolenbroek 			   name, dot, oc -> option -> name,
238*83ee113eSDavid van Moolenbroek 			   pretty_print_option (oc -> option,
239*83ee113eSDavid van Moolenbroek 						ds.data, ds.len, 1, 1));
240*83ee113eSDavid van Moolenbroek 		data_string_forget (&ds, MDL);
241*83ee113eSDavid van Moolenbroek 	}
242*83ee113eSDavid van Moolenbroek }
243*83ee113eSDavid van Moolenbroek 
dump_packet(tp)244*83ee113eSDavid van Moolenbroek void dump_packet (tp)
245*83ee113eSDavid van Moolenbroek 	struct packet *tp;
246*83ee113eSDavid van Moolenbroek {
247*83ee113eSDavid van Moolenbroek 	struct dhcp_packet *tdp = tp -> raw;
248*83ee113eSDavid van Moolenbroek 
249*83ee113eSDavid van Moolenbroek 	log_debug ("packet length %d", tp -> packet_length);
250*83ee113eSDavid van Moolenbroek 	log_debug ("op = %d  htype = %d  hlen = %d  hops = %d",
251*83ee113eSDavid van Moolenbroek 	       tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops);
252*83ee113eSDavid van Moolenbroek 	log_debug ("xid = %x  secs = %ld  flags = %x",
253*83ee113eSDavid van Moolenbroek 	       tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags);
254*83ee113eSDavid van Moolenbroek 	log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr));
255*83ee113eSDavid van Moolenbroek 	log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr));
256*83ee113eSDavid van Moolenbroek 	log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr));
257*83ee113eSDavid van Moolenbroek 	log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr));
258*83ee113eSDavid van Moolenbroek 	log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
259*83ee113eSDavid van Moolenbroek 	       ((unsigned char *)(tdp -> chaddr)) [0],
260*83ee113eSDavid van Moolenbroek 	       ((unsigned char *)(tdp -> chaddr)) [1],
261*83ee113eSDavid van Moolenbroek 	       ((unsigned char *)(tdp -> chaddr)) [2],
262*83ee113eSDavid van Moolenbroek 	       ((unsigned char *)(tdp -> chaddr)) [3],
263*83ee113eSDavid van Moolenbroek 	       ((unsigned char *)(tdp -> chaddr)) [4],
264*83ee113eSDavid van Moolenbroek 	       ((unsigned char *)(tdp -> chaddr)) [5]);
265*83ee113eSDavid van Moolenbroek 	log_debug ("filename = %s", tdp -> file);
266*83ee113eSDavid van Moolenbroek 	log_debug ("server_name = %s", tdp -> sname);
267*83ee113eSDavid van Moolenbroek 	if (tp -> options_valid) {
268*83ee113eSDavid van Moolenbroek 		int i;
269*83ee113eSDavid van Moolenbroek 
270*83ee113eSDavid van Moolenbroek 		for (i = 0; i < tp -> options -> universe_count; i++) {
271*83ee113eSDavid van Moolenbroek 			if (tp -> options -> universes [i]) {
272*83ee113eSDavid van Moolenbroek 				option_space_foreach (tp, (struct lease *)0,
273*83ee113eSDavid van Moolenbroek 						      (struct client_state *)0,
274*83ee113eSDavid van Moolenbroek 						      (struct option_state *)0,
275*83ee113eSDavid van Moolenbroek 						      tp -> options,
276*83ee113eSDavid van Moolenbroek 						      &global_scope,
277*83ee113eSDavid van Moolenbroek 						      universes [i], 0,
278*83ee113eSDavid van Moolenbroek 						      dump_packet_option);
279*83ee113eSDavid van Moolenbroek 			}
280*83ee113eSDavid van Moolenbroek 		}
281*83ee113eSDavid van Moolenbroek 	}
282*83ee113eSDavid van Moolenbroek 	log_debug ("%s", "");
283*83ee113eSDavid van Moolenbroek }
284*83ee113eSDavid van Moolenbroek #endif
285*83ee113eSDavid van Moolenbroek 
dump_raw(buf,len)286*83ee113eSDavid van Moolenbroek void dump_raw (buf, len)
287*83ee113eSDavid van Moolenbroek 	const unsigned char *buf;
288*83ee113eSDavid van Moolenbroek 	unsigned len;
289*83ee113eSDavid van Moolenbroek {
290*83ee113eSDavid van Moolenbroek 	int i;
291*83ee113eSDavid van Moolenbroek 	char lbuf [80];
292*83ee113eSDavid van Moolenbroek 	int lbix = 0;
293*83ee113eSDavid van Moolenbroek 
294*83ee113eSDavid van Moolenbroek /*
295*83ee113eSDavid van Moolenbroek           1         2         3         4         5         6         7
296*83ee113eSDavid van Moolenbroek 01234567890123456789012345678901234567890123456789012345678901234567890123
297*83ee113eSDavid van Moolenbroek 280: 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   .................
298*83ee113eSDavid van Moolenbroek */
299*83ee113eSDavid van Moolenbroek 
300*83ee113eSDavid van Moolenbroek 	memset(lbuf, ' ', 79);
301*83ee113eSDavid van Moolenbroek 	lbuf [79] = 0;
302*83ee113eSDavid van Moolenbroek 
303*83ee113eSDavid van Moolenbroek 	for (i = 0; i < len; i++) {
304*83ee113eSDavid van Moolenbroek 		if ((i & 15) == 0) {
305*83ee113eSDavid van Moolenbroek 		  if (lbix) {
306*83ee113eSDavid van Moolenbroek 		    	lbuf[53]=' ';
307*83ee113eSDavid van Moolenbroek 			lbuf[54]=' ';
308*83ee113eSDavid van Moolenbroek 			lbuf[55]=' ';
309*83ee113eSDavid van Moolenbroek 			lbuf[73]='\0';
310*83ee113eSDavid van Moolenbroek 			log_info ("%s", lbuf);
311*83ee113eSDavid van Moolenbroek 		  }
312*83ee113eSDavid van Moolenbroek 		  memset(lbuf, ' ', 79);
313*83ee113eSDavid van Moolenbroek 		  lbuf [79] = 0;
314*83ee113eSDavid van Moolenbroek 		  sprintf (lbuf, "%03x:", i);
315*83ee113eSDavid van Moolenbroek 		  lbix = 4;
316*83ee113eSDavid van Moolenbroek 		} else if ((i & 7) == 0)
317*83ee113eSDavid van Moolenbroek 			lbuf [lbix++] = ' ';
318*83ee113eSDavid van Moolenbroek 
319*83ee113eSDavid van Moolenbroek 		if(isprint(buf[i])) {
320*83ee113eSDavid van Moolenbroek 		  lbuf[56+(i%16)]=buf[i];
321*83ee113eSDavid van Moolenbroek 		} else {
322*83ee113eSDavid van Moolenbroek 		  lbuf[56+(i%16)]='.';
323*83ee113eSDavid van Moolenbroek 		}
324*83ee113eSDavid van Moolenbroek 
325*83ee113eSDavid van Moolenbroek 		sprintf (&lbuf [lbix], " %02x", buf [i]);
326*83ee113eSDavid van Moolenbroek 		lbix += 3;
327*83ee113eSDavid van Moolenbroek 		lbuf[lbix]=' ';
328*83ee113eSDavid van Moolenbroek 
329*83ee113eSDavid van Moolenbroek 	}
330*83ee113eSDavid van Moolenbroek 	lbuf[53]=' ';
331*83ee113eSDavid van Moolenbroek 	lbuf[54]=' ';
332*83ee113eSDavid van Moolenbroek 	lbuf[55]=' ';
333*83ee113eSDavid van Moolenbroek 	lbuf[73]='\0';
334*83ee113eSDavid van Moolenbroek 	log_info ("%s", lbuf);
335*83ee113eSDavid van Moolenbroek }
336*83ee113eSDavid van Moolenbroek 
hash_dump(table)337*83ee113eSDavid van Moolenbroek void hash_dump (table)
338*83ee113eSDavid van Moolenbroek 	struct hash_table *table;
339*83ee113eSDavid van Moolenbroek {
340*83ee113eSDavid van Moolenbroek 	int i;
341*83ee113eSDavid van Moolenbroek 	struct hash_bucket *bp;
342*83ee113eSDavid van Moolenbroek 
343*83ee113eSDavid van Moolenbroek 	if (!table)
344*83ee113eSDavid van Moolenbroek 		return;
345*83ee113eSDavid van Moolenbroek 
346*83ee113eSDavid van Moolenbroek 	for (i = 0; i < table -> hash_count; i++) {
347*83ee113eSDavid van Moolenbroek 		if (!table -> buckets [i])
348*83ee113eSDavid van Moolenbroek 			continue;
349*83ee113eSDavid van Moolenbroek 		log_info ("hash bucket %d:", i);
350*83ee113eSDavid van Moolenbroek 		for (bp = table -> buckets [i]; bp; bp = bp -> next) {
351*83ee113eSDavid van Moolenbroek 			if (bp -> len)
352*83ee113eSDavid van Moolenbroek 				dump_raw (bp -> name, bp -> len);
353*83ee113eSDavid van Moolenbroek 			else
354*83ee113eSDavid van Moolenbroek 				log_info ("%s", (const char *)bp -> name);
355*83ee113eSDavid van Moolenbroek 		}
356*83ee113eSDavid van Moolenbroek 	}
357*83ee113eSDavid van Moolenbroek }
358*83ee113eSDavid van Moolenbroek 
359*83ee113eSDavid van Moolenbroek /*
360*83ee113eSDavid van Moolenbroek  * print a string as hex.  This only outputs
361*83ee113eSDavid van Moolenbroek  * colon separated hex list no matter what
362*83ee113eSDavid van Moolenbroek  * the input looks like.  See print_hex
363*83ee113eSDavid van Moolenbroek  * for a function that prints either cshl
364*83ee113eSDavid van Moolenbroek  * or a string if all bytes are printible
365*83ee113eSDavid van Moolenbroek  * It only uses limit characters from buf
366*83ee113eSDavid van Moolenbroek  * and doesn't do anything if buf == NULL
367*83ee113eSDavid van Moolenbroek  *
368*83ee113eSDavid van Moolenbroek  * len - length of data
369*83ee113eSDavid van Moolenbroek  * data - input data
370*83ee113eSDavid van Moolenbroek  * limit - length of buf to use
371*83ee113eSDavid van Moolenbroek  * buf - output buffer
372*83ee113eSDavid van Moolenbroek  */
print_hex_only(len,data,limit,buf)373*83ee113eSDavid van Moolenbroek void print_hex_only (len, data, limit, buf)
374*83ee113eSDavid van Moolenbroek 	unsigned len;
375*83ee113eSDavid van Moolenbroek 	const u_int8_t *data;
376*83ee113eSDavid van Moolenbroek 	unsigned limit;
377*83ee113eSDavid van Moolenbroek 	char *buf;
378*83ee113eSDavid van Moolenbroek {
379*83ee113eSDavid van Moolenbroek 	unsigned i;
380*83ee113eSDavid van Moolenbroek 
381*83ee113eSDavid van Moolenbroek 	if ((buf == NULL) || (limit < 3))
382*83ee113eSDavid van Moolenbroek 		return;
383*83ee113eSDavid van Moolenbroek 
384*83ee113eSDavid van Moolenbroek 	for (i = 0; (i < limit / 3) && (i < len); i++) {
385*83ee113eSDavid van Moolenbroek 		sprintf(&buf[i*3], "%02x:", data[i]);
386*83ee113eSDavid van Moolenbroek 	}
387*83ee113eSDavid van Moolenbroek 	buf[(i * 3) - 1] = 0;
388*83ee113eSDavid van Moolenbroek 	return;
389*83ee113eSDavid van Moolenbroek }
390*83ee113eSDavid van Moolenbroek 
391*83ee113eSDavid van Moolenbroek /*
392*83ee113eSDavid van Moolenbroek  * print a string as either text if all the characters
393*83ee113eSDavid van Moolenbroek  * are printable or colon separated hex if they aren't
394*83ee113eSDavid van Moolenbroek  *
395*83ee113eSDavid van Moolenbroek  * len - length of data
396*83ee113eSDavid van Moolenbroek  * data - input data
397*83ee113eSDavid van Moolenbroek  * limit - length of buf to use
398*83ee113eSDavid van Moolenbroek  * buf - output buffer
399*83ee113eSDavid van Moolenbroek  */
print_hex_or_string(len,data,limit,buf)400*83ee113eSDavid van Moolenbroek void print_hex_or_string (len, data, limit, buf)
401*83ee113eSDavid van Moolenbroek 	unsigned len;
402*83ee113eSDavid van Moolenbroek 	const u_int8_t *data;
403*83ee113eSDavid van Moolenbroek 	unsigned limit;
404*83ee113eSDavid van Moolenbroek 	char *buf;
405*83ee113eSDavid van Moolenbroek {
406*83ee113eSDavid van Moolenbroek 	unsigned i;
407*83ee113eSDavid van Moolenbroek 	if ((buf == NULL) || (limit < 3))
408*83ee113eSDavid van Moolenbroek 		return;
409*83ee113eSDavid van Moolenbroek 
410*83ee113eSDavid van Moolenbroek 	for (i = 0; (i < (limit - 3)) && (i < len); i++) {
411*83ee113eSDavid van Moolenbroek 		if (!isascii(data[i]) || !isprint(data[i])) {
412*83ee113eSDavid van Moolenbroek 			print_hex_only(len, data, limit, buf);
413*83ee113eSDavid van Moolenbroek 			return;
414*83ee113eSDavid van Moolenbroek 		}
415*83ee113eSDavid van Moolenbroek 	}
416*83ee113eSDavid van Moolenbroek 
417*83ee113eSDavid van Moolenbroek 	buf[0] = '"';
418*83ee113eSDavid van Moolenbroek 	i = len;
419*83ee113eSDavid van Moolenbroek 	if (i > (limit - 3))
420*83ee113eSDavid van Moolenbroek 		i = limit - 3;
421*83ee113eSDavid van Moolenbroek 	memcpy(&buf[1], data, i);
422*83ee113eSDavid van Moolenbroek 	buf[i + 1] = '"';
423*83ee113eSDavid van Moolenbroek 	buf[i + 2] = 0;
424*83ee113eSDavid van Moolenbroek 	return;
425*83ee113eSDavid van Moolenbroek }
426*83ee113eSDavid van Moolenbroek 
427*83ee113eSDavid van Moolenbroek /*
428*83ee113eSDavid van Moolenbroek  * print a string as either hex or text
429*83ee113eSDavid van Moolenbroek  * using static buffers to hold the output
430*83ee113eSDavid van Moolenbroek  *
431*83ee113eSDavid van Moolenbroek  * len - length of data
432*83ee113eSDavid van Moolenbroek  * data - input data
433*83ee113eSDavid van Moolenbroek  * limit - length of buf
434*83ee113eSDavid van Moolenbroek  * buf_num - the output buffer to use
435*83ee113eSDavid van Moolenbroek  */
436*83ee113eSDavid van Moolenbroek #define HBLEN 1024
print_hex(len,data,limit,buf_num)437*83ee113eSDavid van Moolenbroek char *print_hex(len, data, limit, buf_num)
438*83ee113eSDavid van Moolenbroek 	unsigned len;
439*83ee113eSDavid van Moolenbroek 	const u_int8_t *data;
440*83ee113eSDavid van Moolenbroek 	unsigned limit;
441*83ee113eSDavid van Moolenbroek 	unsigned buf_num;
442*83ee113eSDavid van Moolenbroek {
443*83ee113eSDavid van Moolenbroek 	static char hex_buf_1[HBLEN + 1];
444*83ee113eSDavid van Moolenbroek 	static char hex_buf_2[HBLEN + 1];
445*83ee113eSDavid van Moolenbroek 	static char hex_buf_3[HBLEN + 1];
446*83ee113eSDavid van Moolenbroek 	char *hex_buf;
447*83ee113eSDavid van Moolenbroek 
448*83ee113eSDavid van Moolenbroek 	switch(buf_num) {
449*83ee113eSDavid van Moolenbroek 	  case 0:
450*83ee113eSDavid van Moolenbroek 		hex_buf = hex_buf_1;
451*83ee113eSDavid van Moolenbroek 		if (limit >= sizeof(hex_buf_1))
452*83ee113eSDavid van Moolenbroek 			limit = sizeof(hex_buf_1);
453*83ee113eSDavid van Moolenbroek 		break;
454*83ee113eSDavid van Moolenbroek 	  case 1:
455*83ee113eSDavid van Moolenbroek 		hex_buf = hex_buf_2;
456*83ee113eSDavid van Moolenbroek 		if (limit >= sizeof(hex_buf_2))
457*83ee113eSDavid van Moolenbroek 			limit = sizeof(hex_buf_2);
458*83ee113eSDavid van Moolenbroek 		break;
459*83ee113eSDavid van Moolenbroek 	  case 2:
460*83ee113eSDavid van Moolenbroek 		hex_buf = hex_buf_3;
461*83ee113eSDavid van Moolenbroek 		if (limit >= sizeof(hex_buf_3))
462*83ee113eSDavid van Moolenbroek 			limit = sizeof(hex_buf_3);
463*83ee113eSDavid van Moolenbroek 		break;
464*83ee113eSDavid van Moolenbroek 	  default:
465*83ee113eSDavid van Moolenbroek 		return(NULL);
466*83ee113eSDavid van Moolenbroek 	}
467*83ee113eSDavid van Moolenbroek 
468*83ee113eSDavid van Moolenbroek 	print_hex_or_string(len, data, limit, hex_buf);
469*83ee113eSDavid van Moolenbroek 	return(hex_buf);
470*83ee113eSDavid van Moolenbroek }
471*83ee113eSDavid van Moolenbroek 
472*83ee113eSDavid van Moolenbroek #define DQLEN	80
473*83ee113eSDavid van Moolenbroek 
print_dotted_quads(len,data)474*83ee113eSDavid van Moolenbroek char *print_dotted_quads (len, data)
475*83ee113eSDavid van Moolenbroek 	unsigned len;
476*83ee113eSDavid van Moolenbroek 	const u_int8_t *data;
477*83ee113eSDavid van Moolenbroek {
478*83ee113eSDavid van Moolenbroek 	static char dq_buf [DQLEN + 1];
479*83ee113eSDavid van Moolenbroek 	int i;
480*83ee113eSDavid van Moolenbroek 	char *s;
481*83ee113eSDavid van Moolenbroek 
482*83ee113eSDavid van Moolenbroek 	s = &dq_buf [0];
483*83ee113eSDavid van Moolenbroek 
484*83ee113eSDavid van Moolenbroek 	i = 0;
485*83ee113eSDavid van Moolenbroek 
486*83ee113eSDavid van Moolenbroek 	/* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe%
487*83ee113eSDavid van Moolenbroek 	 * The sprintf can't exceed 18 bytes, and since the loop enforces
488*83ee113eSDavid van Moolenbroek 	 * 21 bytes of space per iteration at no time can we exit the
489*83ee113eSDavid van Moolenbroek 	 * loop without at least 3 bytes spare.
490*83ee113eSDavid van Moolenbroek 	 */
491*83ee113eSDavid van Moolenbroek 	do {
492*83ee113eSDavid van Moolenbroek 		sprintf (s, "%u.%u.%u.%u, ",
493*83ee113eSDavid van Moolenbroek 			 data [i], data [i + 1], data [i + 2], data [i + 3]);
494*83ee113eSDavid van Moolenbroek 		s += strlen (s);
495*83ee113eSDavid van Moolenbroek 		i += 4;
496*83ee113eSDavid van Moolenbroek 	} while ((s - &dq_buf [0] > DQLEN - 21) &&
497*83ee113eSDavid van Moolenbroek 		 i + 3 < len);
498*83ee113eSDavid van Moolenbroek 	if (i == len)
499*83ee113eSDavid van Moolenbroek 		s [-2] = 0;
500*83ee113eSDavid van Moolenbroek 	else
501*83ee113eSDavid van Moolenbroek 		strcpy (s, "...");
502*83ee113eSDavid van Moolenbroek 	return dq_buf;
503*83ee113eSDavid van Moolenbroek }
504*83ee113eSDavid van Moolenbroek 
print_dec_1(val)505*83ee113eSDavid van Moolenbroek char *print_dec_1 (val)
506*83ee113eSDavid van Moolenbroek 	unsigned long val;
507*83ee113eSDavid van Moolenbroek {
508*83ee113eSDavid van Moolenbroek 	static char vbuf [32];
509*83ee113eSDavid van Moolenbroek 	sprintf (vbuf, "%lu", val);
510*83ee113eSDavid van Moolenbroek 	return vbuf;
511*83ee113eSDavid van Moolenbroek }
512*83ee113eSDavid van Moolenbroek 
print_dec_2(val)513*83ee113eSDavid van Moolenbroek char *print_dec_2 (val)
514*83ee113eSDavid van Moolenbroek 	unsigned long val;
515*83ee113eSDavid van Moolenbroek {
516*83ee113eSDavid van Moolenbroek 	static char vbuf [32];
517*83ee113eSDavid van Moolenbroek 	sprintf (vbuf, "%lu", val);
518*83ee113eSDavid van Moolenbroek 	return vbuf;
519*83ee113eSDavid van Moolenbroek }
520*83ee113eSDavid van Moolenbroek 
521*83ee113eSDavid van Moolenbroek static unsigned print_subexpression (struct expression *, char *, unsigned);
522*83ee113eSDavid van Moolenbroek 
print_subexpression(expr,buf,len)523*83ee113eSDavid van Moolenbroek static unsigned print_subexpression (expr, buf, len)
524*83ee113eSDavid van Moolenbroek 	struct expression *expr;
525*83ee113eSDavid van Moolenbroek 	char *buf;
526*83ee113eSDavid van Moolenbroek 	unsigned len;
527*83ee113eSDavid van Moolenbroek {
528*83ee113eSDavid van Moolenbroek 	unsigned rv, left;
529*83ee113eSDavid van Moolenbroek 	const char *s;
530*83ee113eSDavid van Moolenbroek 
531*83ee113eSDavid van Moolenbroek 	switch (expr -> op) {
532*83ee113eSDavid van Moolenbroek 	      case expr_none:
533*83ee113eSDavid van Moolenbroek 		if (len > 3) {
534*83ee113eSDavid van Moolenbroek 			strcpy (buf, "nil");
535*83ee113eSDavid van Moolenbroek 			return 3;
536*83ee113eSDavid van Moolenbroek 		}
537*83ee113eSDavid van Moolenbroek 		break;
538*83ee113eSDavid van Moolenbroek 
539*83ee113eSDavid van Moolenbroek 	      case expr_match:
540*83ee113eSDavid van Moolenbroek 		if (len > 7) {
541*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(match)");
542*83ee113eSDavid van Moolenbroek 			return 7;
543*83ee113eSDavid van Moolenbroek 		}
544*83ee113eSDavid van Moolenbroek 		break;
545*83ee113eSDavid van Moolenbroek 
546*83ee113eSDavid van Moolenbroek 	      case expr_check:
547*83ee113eSDavid van Moolenbroek 		rv = 10 + strlen (expr -> data.check -> name);
548*83ee113eSDavid van Moolenbroek 		if (len > rv) {
549*83ee113eSDavid van Moolenbroek 			sprintf (buf, "(check %s)",
550*83ee113eSDavid van Moolenbroek 				 expr -> data.check -> name);
551*83ee113eSDavid van Moolenbroek 			return rv;
552*83ee113eSDavid van Moolenbroek 		}
553*83ee113eSDavid van Moolenbroek 		break;
554*83ee113eSDavid van Moolenbroek 
555*83ee113eSDavid van Moolenbroek 	      case expr_equal:
556*83ee113eSDavid van Moolenbroek 		if (len > 6) {
557*83ee113eSDavid van Moolenbroek 			rv = 4;
558*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(eq ");
559*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.equal [0],
560*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 2);
561*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
562*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.equal [1],
563*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
564*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
565*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
566*83ee113eSDavid van Moolenbroek 			return rv;
567*83ee113eSDavid van Moolenbroek 		}
568*83ee113eSDavid van Moolenbroek 		break;
569*83ee113eSDavid van Moolenbroek 
570*83ee113eSDavid van Moolenbroek 	      case expr_not_equal:
571*83ee113eSDavid van Moolenbroek 		if (len > 7) {
572*83ee113eSDavid van Moolenbroek 			rv = 5;
573*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(neq ");
574*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.equal [0],
575*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 2);
576*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
577*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.equal [1],
578*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
579*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
580*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
581*83ee113eSDavid van Moolenbroek 			return rv;
582*83ee113eSDavid van Moolenbroek 		}
583*83ee113eSDavid van Moolenbroek 		break;
584*83ee113eSDavid van Moolenbroek 
585*83ee113eSDavid van Moolenbroek 	      case expr_regex_match:
586*83ee113eSDavid van Moolenbroek 		if (len > 10) {
587*83ee113eSDavid van Moolenbroek 			rv = 4;
588*83ee113eSDavid van Moolenbroek 			strcpy(buf, "(regex ");
589*83ee113eSDavid van Moolenbroek 			rv += print_subexpression(expr->data.equal[0],
590*83ee113eSDavid van Moolenbroek 						  buf + rv, len - rv - 2);
591*83ee113eSDavid van Moolenbroek 			buf[rv++] = ' ';
592*83ee113eSDavid van Moolenbroek 			rv += print_subexpression(expr->data.equal[1],
593*83ee113eSDavid van Moolenbroek 						  buf + rv, len - rv - 1);
594*83ee113eSDavid van Moolenbroek 			buf[rv++] = ')';
595*83ee113eSDavid van Moolenbroek 			buf[rv] = 0;
596*83ee113eSDavid van Moolenbroek 			return rv;
597*83ee113eSDavid van Moolenbroek 		}
598*83ee113eSDavid van Moolenbroek 		break;
599*83ee113eSDavid van Moolenbroek 
600*83ee113eSDavid van Moolenbroek 	      case expr_substring:
601*83ee113eSDavid van Moolenbroek 		if (len > 11) {
602*83ee113eSDavid van Moolenbroek 			rv = 8;
603*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(substr ");
604*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.substring.expr,
605*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 3);
606*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
607*83ee113eSDavid van Moolenbroek 			rv += print_subexpression
608*83ee113eSDavid van Moolenbroek 				(expr -> data.substring.offset,
609*83ee113eSDavid van Moolenbroek 				 buf + rv, len - rv - 2);
610*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
611*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.substring.len,
612*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
613*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
614*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
615*83ee113eSDavid van Moolenbroek 			return rv;
616*83ee113eSDavid van Moolenbroek 		}
617*83ee113eSDavid van Moolenbroek 		break;
618*83ee113eSDavid van Moolenbroek 
619*83ee113eSDavid van Moolenbroek 	      case expr_suffix:
620*83ee113eSDavid van Moolenbroek 		if (len > 10) {
621*83ee113eSDavid van Moolenbroek 			rv = 8;
622*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(suffix ");
623*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.suffix.expr,
624*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 2);
625*83ee113eSDavid van Moolenbroek 			if (len > rv)
626*83ee113eSDavid van Moolenbroek 				buf [rv++] = ' ';
627*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.suffix.len,
628*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
629*83ee113eSDavid van Moolenbroek 			if (len > rv)
630*83ee113eSDavid van Moolenbroek 				buf [rv++] = ')';
631*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
632*83ee113eSDavid van Moolenbroek 			return rv;
633*83ee113eSDavid van Moolenbroek 		}
634*83ee113eSDavid van Moolenbroek 		break;
635*83ee113eSDavid van Moolenbroek 
636*83ee113eSDavid van Moolenbroek 	      case expr_lcase:
637*83ee113eSDavid van Moolenbroek 		if (len > 9) {
638*83ee113eSDavid van Moolenbroek 			rv = 7;
639*83ee113eSDavid van Moolenbroek 			strcpy(buf, "(lcase ");
640*83ee113eSDavid van Moolenbroek 			rv += print_subexpression(expr->data.lcase,
641*83ee113eSDavid van Moolenbroek 						  buf + rv, len - rv - 1);
642*83ee113eSDavid van Moolenbroek 			buf[rv++] = ')';
643*83ee113eSDavid van Moolenbroek 			buf[rv] = 0;
644*83ee113eSDavid van Moolenbroek 			return rv;
645*83ee113eSDavid van Moolenbroek 		}
646*83ee113eSDavid van Moolenbroek 		break;
647*83ee113eSDavid van Moolenbroek 
648*83ee113eSDavid van Moolenbroek 	      case expr_ucase:
649*83ee113eSDavid van Moolenbroek 		if (len > 9) {
650*83ee113eSDavid van Moolenbroek 			rv = 7;
651*83ee113eSDavid van Moolenbroek 			strcpy(buf, "(ucase ");
652*83ee113eSDavid van Moolenbroek 			rv += print_subexpression(expr->data.ucase,
653*83ee113eSDavid van Moolenbroek 						  buf + rv, len - rv - 1);
654*83ee113eSDavid van Moolenbroek 			buf[rv++] = ')';
655*83ee113eSDavid van Moolenbroek 			buf[rv] = 0;
656*83ee113eSDavid van Moolenbroek 			return rv;
657*83ee113eSDavid van Moolenbroek 		}
658*83ee113eSDavid van Moolenbroek 		break;
659*83ee113eSDavid van Moolenbroek 
660*83ee113eSDavid van Moolenbroek 	      case expr_concat:
661*83ee113eSDavid van Moolenbroek 		if (len > 10) {
662*83ee113eSDavid van Moolenbroek 			rv = 8;
663*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(concat ");
664*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.concat [0],
665*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 2);
666*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
667*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.concat [1],
668*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
669*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
670*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
671*83ee113eSDavid van Moolenbroek 			return rv;
672*83ee113eSDavid van Moolenbroek 		}
673*83ee113eSDavid van Moolenbroek 		break;
674*83ee113eSDavid van Moolenbroek 
675*83ee113eSDavid van Moolenbroek 	      case expr_pick_first_value:
676*83ee113eSDavid van Moolenbroek 		if (len > 8) {
677*83ee113eSDavid van Moolenbroek 			rv = 6;
678*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(pick1st ");
679*83ee113eSDavid van Moolenbroek 			rv += print_subexpression
680*83ee113eSDavid van Moolenbroek 				(expr -> data.pick_first_value.car,
681*83ee113eSDavid van Moolenbroek 				 buf + rv, len - rv - 2);
682*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
683*83ee113eSDavid van Moolenbroek 			rv += print_subexpression
684*83ee113eSDavid van Moolenbroek 				(expr -> data.pick_first_value.cdr,
685*83ee113eSDavid van Moolenbroek 				 buf + rv, len - rv - 1);
686*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
687*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
688*83ee113eSDavid van Moolenbroek 			return rv;
689*83ee113eSDavid van Moolenbroek 		}
690*83ee113eSDavid van Moolenbroek 		break;
691*83ee113eSDavid van Moolenbroek 
692*83ee113eSDavid van Moolenbroek 	      case expr_host_lookup:
693*83ee113eSDavid van Moolenbroek 		rv = 15 + strlen (expr -> data.host_lookup -> hostname);
694*83ee113eSDavid van Moolenbroek 		if (len > rv) {
695*83ee113eSDavid van Moolenbroek 			sprintf (buf, "(dns-lookup %s)",
696*83ee113eSDavid van Moolenbroek 				 expr -> data.host_lookup -> hostname);
697*83ee113eSDavid van Moolenbroek 			return rv;
698*83ee113eSDavid van Moolenbroek 		}
699*83ee113eSDavid van Moolenbroek 		break;
700*83ee113eSDavid van Moolenbroek 
701*83ee113eSDavid van Moolenbroek 	      case expr_and:
702*83ee113eSDavid van Moolenbroek 		s = "and";
703*83ee113eSDavid van Moolenbroek 	      binop:
704*83ee113eSDavid van Moolenbroek 		rv = strlen (s);
705*83ee113eSDavid van Moolenbroek 		if (len > rv + 4) {
706*83ee113eSDavid van Moolenbroek 			buf [0] = '(';
707*83ee113eSDavid van Moolenbroek 			strcpy (&buf [1], s);
708*83ee113eSDavid van Moolenbroek 			rv += 1;
709*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
710*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.and [0],
711*83ee113eSDavid van Moolenbroek 						buf + rv, len - rv - 2);
712*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
713*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.and [1],
714*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
715*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
716*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
717*83ee113eSDavid van Moolenbroek 			return rv;
718*83ee113eSDavid van Moolenbroek 		}
719*83ee113eSDavid van Moolenbroek 		break;
720*83ee113eSDavid van Moolenbroek 
721*83ee113eSDavid van Moolenbroek 	      case expr_or:
722*83ee113eSDavid van Moolenbroek 		s = "or";
723*83ee113eSDavid van Moolenbroek 		goto binop;
724*83ee113eSDavid van Moolenbroek 
725*83ee113eSDavid van Moolenbroek 	      case expr_add:
726*83ee113eSDavid van Moolenbroek 		s = "+";
727*83ee113eSDavid van Moolenbroek 		goto binop;
728*83ee113eSDavid van Moolenbroek 
729*83ee113eSDavid van Moolenbroek 	      case expr_subtract:
730*83ee113eSDavid van Moolenbroek 		s = "-";
731*83ee113eSDavid van Moolenbroek 		goto binop;
732*83ee113eSDavid van Moolenbroek 
733*83ee113eSDavid van Moolenbroek 	      case expr_multiply:
734*83ee113eSDavid van Moolenbroek 		s = "*";
735*83ee113eSDavid van Moolenbroek 		goto binop;
736*83ee113eSDavid van Moolenbroek 
737*83ee113eSDavid van Moolenbroek 	      case expr_divide:
738*83ee113eSDavid van Moolenbroek 		s = "/";
739*83ee113eSDavid van Moolenbroek 		goto binop;
740*83ee113eSDavid van Moolenbroek 
741*83ee113eSDavid van Moolenbroek 	      case expr_remainder:
742*83ee113eSDavid van Moolenbroek 		s = "%";
743*83ee113eSDavid van Moolenbroek 		goto binop;
744*83ee113eSDavid van Moolenbroek 
745*83ee113eSDavid van Moolenbroek 	      case expr_binary_and:
746*83ee113eSDavid van Moolenbroek 		s = "&";
747*83ee113eSDavid van Moolenbroek 		goto binop;
748*83ee113eSDavid van Moolenbroek 
749*83ee113eSDavid van Moolenbroek 	      case expr_binary_or:
750*83ee113eSDavid van Moolenbroek 		s = "|";
751*83ee113eSDavid van Moolenbroek 		goto binop;
752*83ee113eSDavid van Moolenbroek 
753*83ee113eSDavid van Moolenbroek 	      case expr_binary_xor:
754*83ee113eSDavid van Moolenbroek 		s = "^";
755*83ee113eSDavid van Moolenbroek 		goto binop;
756*83ee113eSDavid van Moolenbroek 
757*83ee113eSDavid van Moolenbroek 	      case expr_not:
758*83ee113eSDavid van Moolenbroek 		if (len > 6) {
759*83ee113eSDavid van Moolenbroek 			rv = 5;
760*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(not ");
761*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.not,
762*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
763*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
764*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
765*83ee113eSDavid van Moolenbroek 			return rv;
766*83ee113eSDavid van Moolenbroek 		}
767*83ee113eSDavid van Moolenbroek 		break;
768*83ee113eSDavid van Moolenbroek 
769*83ee113eSDavid van Moolenbroek 	      case expr_config_option:
770*83ee113eSDavid van Moolenbroek 		s = "cfg-option";
771*83ee113eSDavid van Moolenbroek 		goto dooption;
772*83ee113eSDavid van Moolenbroek 
773*83ee113eSDavid van Moolenbroek 	      case expr_option:
774*83ee113eSDavid van Moolenbroek 		s = "option";
775*83ee113eSDavid van Moolenbroek 	      dooption:
776*83ee113eSDavid van Moolenbroek 		rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) +
777*83ee113eSDavid van Moolenbroek 			   strlen (expr -> data.option -> universe -> name));
778*83ee113eSDavid van Moolenbroek 		if (len > rv) {
779*83ee113eSDavid van Moolenbroek 			sprintf (buf, "(option %s.%s)",
780*83ee113eSDavid van Moolenbroek 				 expr -> data.option -> universe -> name,
781*83ee113eSDavid van Moolenbroek 				 expr -> data.option -> name);
782*83ee113eSDavid van Moolenbroek 			return rv;
783*83ee113eSDavid van Moolenbroek 		}
784*83ee113eSDavid van Moolenbroek 		break;
785*83ee113eSDavid van Moolenbroek 
786*83ee113eSDavid van Moolenbroek 	      case expr_hardware:
787*83ee113eSDavid van Moolenbroek 		if (len > 10) {
788*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(hardware)");
789*83ee113eSDavid van Moolenbroek 			return 10;
790*83ee113eSDavid van Moolenbroek 		}
791*83ee113eSDavid van Moolenbroek 		break;
792*83ee113eSDavid van Moolenbroek 
793*83ee113eSDavid van Moolenbroek 	      case expr_packet:
794*83ee113eSDavid van Moolenbroek 		if (len > 10) {
795*83ee113eSDavid van Moolenbroek 			rv = 8;
796*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(substr ");
797*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.packet.offset,
798*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 2);
799*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
800*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.packet.len,
801*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
802*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
803*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
804*83ee113eSDavid van Moolenbroek 			return rv;
805*83ee113eSDavid van Moolenbroek 		}
806*83ee113eSDavid van Moolenbroek 		break;
807*83ee113eSDavid van Moolenbroek 
808*83ee113eSDavid van Moolenbroek 	      case expr_const_data:
809*83ee113eSDavid van Moolenbroek 		s = print_hex_1 (expr -> data.const_data.len,
810*83ee113eSDavid van Moolenbroek 				 expr -> data.const_data.data, len);
811*83ee113eSDavid van Moolenbroek 		rv = strlen (s);
812*83ee113eSDavid van Moolenbroek 		if (rv >= len)
813*83ee113eSDavid van Moolenbroek 			rv = len - 1;
814*83ee113eSDavid van Moolenbroek 		strncpy (buf, s, rv);
815*83ee113eSDavid van Moolenbroek 		buf [rv] = 0;
816*83ee113eSDavid van Moolenbroek 		return rv;
817*83ee113eSDavid van Moolenbroek 
818*83ee113eSDavid van Moolenbroek 	      case expr_encapsulate:
819*83ee113eSDavid van Moolenbroek 		rv = 13;
820*83ee113eSDavid van Moolenbroek 		strcpy (buf, "(encapsulate ");
821*83ee113eSDavid van Moolenbroek 		rv += expr -> data.encapsulate.len;
822*83ee113eSDavid van Moolenbroek 		if (rv + 2 > len)
823*83ee113eSDavid van Moolenbroek 			rv = len - 2;
824*83ee113eSDavid van Moolenbroek 		strncpy (buf,
825*83ee113eSDavid van Moolenbroek 			 (const char *)expr -> data.encapsulate.data, rv - 13);
826*83ee113eSDavid van Moolenbroek 		buf [rv++] = ')';
827*83ee113eSDavid van Moolenbroek 		buf [rv++] = 0;
828*83ee113eSDavid van Moolenbroek 		break;
829*83ee113eSDavid van Moolenbroek 
830*83ee113eSDavid van Moolenbroek 	      case expr_extract_int8:
831*83ee113eSDavid van Moolenbroek 		if (len > 7) {
832*83ee113eSDavid van Moolenbroek 			rv = 6;
833*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(int8 ");
834*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.extract_int,
835*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
836*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
837*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
838*83ee113eSDavid van Moolenbroek 			return rv;
839*83ee113eSDavid van Moolenbroek 		}
840*83ee113eSDavid van Moolenbroek 		break;
841*83ee113eSDavid van Moolenbroek 
842*83ee113eSDavid van Moolenbroek 	      case expr_extract_int16:
843*83ee113eSDavid van Moolenbroek 		if (len > 8) {
844*83ee113eSDavid van Moolenbroek 			rv = 7;
845*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(int16 ");
846*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.extract_int,
847*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
848*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
849*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
850*83ee113eSDavid van Moolenbroek 			return rv;
851*83ee113eSDavid van Moolenbroek 		}
852*83ee113eSDavid van Moolenbroek 		break;
853*83ee113eSDavid van Moolenbroek 
854*83ee113eSDavid van Moolenbroek 	      case expr_extract_int32:
855*83ee113eSDavid van Moolenbroek 		if (len > 8) {
856*83ee113eSDavid van Moolenbroek 			rv = 7;
857*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(int32 ");
858*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.extract_int,
859*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
860*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
861*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
862*83ee113eSDavid van Moolenbroek 			return rv;
863*83ee113eSDavid van Moolenbroek 		}
864*83ee113eSDavid van Moolenbroek 		break;
865*83ee113eSDavid van Moolenbroek 
866*83ee113eSDavid van Moolenbroek 	      case expr_encode_int8:
867*83ee113eSDavid van Moolenbroek 		if (len > 7) {
868*83ee113eSDavid van Moolenbroek 			rv = 6;
869*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(to-int8 ");
870*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.encode_int,
871*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
872*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
873*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
874*83ee113eSDavid van Moolenbroek 			return rv;
875*83ee113eSDavid van Moolenbroek 		}
876*83ee113eSDavid van Moolenbroek 		break;
877*83ee113eSDavid van Moolenbroek 
878*83ee113eSDavid van Moolenbroek 	      case expr_encode_int16:
879*83ee113eSDavid van Moolenbroek 		if (len > 8) {
880*83ee113eSDavid van Moolenbroek 			rv = 7;
881*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(to-int16 ");
882*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.encode_int,
883*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
884*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
885*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
886*83ee113eSDavid van Moolenbroek 			return rv;
887*83ee113eSDavid van Moolenbroek 		}
888*83ee113eSDavid van Moolenbroek 		break;
889*83ee113eSDavid van Moolenbroek 
890*83ee113eSDavid van Moolenbroek 	      case expr_encode_int32:
891*83ee113eSDavid van Moolenbroek 		if (len > 8) {
892*83ee113eSDavid van Moolenbroek 			rv = 7;
893*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(to-int32 ");
894*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.encode_int,
895*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
896*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
897*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
898*83ee113eSDavid van Moolenbroek 			return rv;
899*83ee113eSDavid van Moolenbroek 		}
900*83ee113eSDavid van Moolenbroek 		break;
901*83ee113eSDavid van Moolenbroek 
902*83ee113eSDavid van Moolenbroek 	      case expr_const_int:
903*83ee113eSDavid van Moolenbroek 		s = print_dec_1 (expr -> data.const_int);
904*83ee113eSDavid van Moolenbroek 		rv = strlen (s);
905*83ee113eSDavid van Moolenbroek 		if (len > rv) {
906*83ee113eSDavid van Moolenbroek 			strcpy (buf, s);
907*83ee113eSDavid van Moolenbroek 			return rv;
908*83ee113eSDavid van Moolenbroek 		}
909*83ee113eSDavid van Moolenbroek 		break;
910*83ee113eSDavid van Moolenbroek 
911*83ee113eSDavid van Moolenbroek 	      case expr_exists:
912*83ee113eSDavid van Moolenbroek 		rv = 10 + (strlen (expr -> data.option -> name) +
913*83ee113eSDavid van Moolenbroek 			   strlen (expr -> data.option -> universe -> name));
914*83ee113eSDavid van Moolenbroek 		if (len > rv) {
915*83ee113eSDavid van Moolenbroek 			sprintf (buf, "(exists %s.%s)",
916*83ee113eSDavid van Moolenbroek 				 expr -> data.option -> universe -> name,
917*83ee113eSDavid van Moolenbroek 				 expr -> data.option -> name);
918*83ee113eSDavid van Moolenbroek 			return rv;
919*83ee113eSDavid van Moolenbroek 		}
920*83ee113eSDavid van Moolenbroek 		break;
921*83ee113eSDavid van Moolenbroek 
922*83ee113eSDavid van Moolenbroek 	      case expr_variable_exists:
923*83ee113eSDavid van Moolenbroek 		rv = 10 + strlen (expr -> data.variable);
924*83ee113eSDavid van Moolenbroek 		if (len > rv) {
925*83ee113eSDavid van Moolenbroek 			sprintf (buf, "(defined %s)", expr -> data.variable);
926*83ee113eSDavid van Moolenbroek 			return rv;
927*83ee113eSDavid van Moolenbroek 		}
928*83ee113eSDavid van Moolenbroek 		break;
929*83ee113eSDavid van Moolenbroek 
930*83ee113eSDavid van Moolenbroek 	      case expr_variable_reference:
931*83ee113eSDavid van Moolenbroek 		rv = strlen (expr -> data.variable);
932*83ee113eSDavid van Moolenbroek 		if (len > rv) {
933*83ee113eSDavid van Moolenbroek 			sprintf (buf, "%s", expr -> data.variable);
934*83ee113eSDavid van Moolenbroek 			return rv;
935*83ee113eSDavid van Moolenbroek 		}
936*83ee113eSDavid van Moolenbroek 		break;
937*83ee113eSDavid van Moolenbroek 
938*83ee113eSDavid van Moolenbroek 	      case expr_known:
939*83ee113eSDavid van Moolenbroek 		s = "known";
940*83ee113eSDavid van Moolenbroek 	      astring:
941*83ee113eSDavid van Moolenbroek 		rv = strlen (s);
942*83ee113eSDavid van Moolenbroek 		if (len > rv) {
943*83ee113eSDavid van Moolenbroek 			strcpy (buf, s);
944*83ee113eSDavid van Moolenbroek 			return rv;
945*83ee113eSDavid van Moolenbroek 		}
946*83ee113eSDavid van Moolenbroek 		break;
947*83ee113eSDavid van Moolenbroek 
948*83ee113eSDavid van Moolenbroek 	      case expr_leased_address:
949*83ee113eSDavid van Moolenbroek 		s = "leased-address";
950*83ee113eSDavid van Moolenbroek 		goto astring;
951*83ee113eSDavid van Moolenbroek 
952*83ee113eSDavid van Moolenbroek 	      case expr_client_state:
953*83ee113eSDavid van Moolenbroek 		s = "client-state";
954*83ee113eSDavid van Moolenbroek 		goto astring;
955*83ee113eSDavid van Moolenbroek 
956*83ee113eSDavid van Moolenbroek 	      case expr_host_decl_name:
957*83ee113eSDavid van Moolenbroek 		s = "host-decl-name";
958*83ee113eSDavid van Moolenbroek 		goto astring;
959*83ee113eSDavid van Moolenbroek 
960*83ee113eSDavid van Moolenbroek 	      case expr_lease_time:
961*83ee113eSDavid van Moolenbroek 		s = "lease-time";
962*83ee113eSDavid van Moolenbroek 		goto astring;
963*83ee113eSDavid van Moolenbroek 
964*83ee113eSDavid van Moolenbroek 	      case expr_static:
965*83ee113eSDavid van Moolenbroek 		s = "static";
966*83ee113eSDavid van Moolenbroek 		goto astring;
967*83ee113eSDavid van Moolenbroek 
968*83ee113eSDavid van Moolenbroek 	      case expr_filename:
969*83ee113eSDavid van Moolenbroek 		s = "filename";
970*83ee113eSDavid van Moolenbroek 		goto astring;
971*83ee113eSDavid van Moolenbroek 
972*83ee113eSDavid van Moolenbroek 	      case expr_sname:
973*83ee113eSDavid van Moolenbroek 		s = "server-name";
974*83ee113eSDavid van Moolenbroek 		goto astring;
975*83ee113eSDavid van Moolenbroek 
976*83ee113eSDavid van Moolenbroek 	      case expr_reverse:
977*83ee113eSDavid van Moolenbroek 		if (len > 11) {
978*83ee113eSDavid van Moolenbroek 			rv = 13;
979*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(reverse ");
980*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.reverse.width,
981*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 2);
982*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
983*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.reverse.buffer,
984*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
985*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
986*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
987*83ee113eSDavid van Moolenbroek 			return rv;
988*83ee113eSDavid van Moolenbroek 		}
989*83ee113eSDavid van Moolenbroek 		break;
990*83ee113eSDavid van Moolenbroek 
991*83ee113eSDavid van Moolenbroek 	      case expr_binary_to_ascii:
992*83ee113eSDavid van Moolenbroek 		if (len > 5) {
993*83ee113eSDavid van Moolenbroek 			rv = 9;
994*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(b2a ");
995*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.b2a.base,
996*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 4);
997*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
998*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.b2a.width,
999*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 3);
1000*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
1001*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.b2a.separator,
1002*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 2);
1003*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
1004*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.b2a.buffer,
1005*83ee113eSDavid van Moolenbroek 						   buf + rv, len - rv - 1);
1006*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
1007*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
1008*83ee113eSDavid van Moolenbroek 			return rv;
1009*83ee113eSDavid van Moolenbroek 		}
1010*83ee113eSDavid van Moolenbroek 		break;
1011*83ee113eSDavid van Moolenbroek 
1012*83ee113eSDavid van Moolenbroek 	      case expr_dns_transaction:
1013*83ee113eSDavid van Moolenbroek 		rv = 10;
1014*83ee113eSDavid van Moolenbroek 		if (len < rv + 2) {
1015*83ee113eSDavid van Moolenbroek 			buf [0] = '(';
1016*83ee113eSDavid van Moolenbroek 			strcpy (&buf [1], "ns-update ");
1017*83ee113eSDavid van Moolenbroek 			while (len < rv + 2) {
1018*83ee113eSDavid van Moolenbroek 				rv += print_subexpression
1019*83ee113eSDavid van Moolenbroek 					(expr -> data.dns_transaction.car,
1020*83ee113eSDavid van Moolenbroek 					 buf + rv, len - rv - 2);
1021*83ee113eSDavid van Moolenbroek 				buf [rv++] = ' ';
1022*83ee113eSDavid van Moolenbroek 				expr = expr -> data.dns_transaction.cdr;
1023*83ee113eSDavid van Moolenbroek 			}
1024*83ee113eSDavid van Moolenbroek 			buf [rv - 1] = ')';
1025*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
1026*83ee113eSDavid van Moolenbroek 			return rv;
1027*83ee113eSDavid van Moolenbroek 		}
1028*83ee113eSDavid van Moolenbroek 		return 0;
1029*83ee113eSDavid van Moolenbroek 
1030*83ee113eSDavid van Moolenbroek 	      case expr_ns_delete:
1031*83ee113eSDavid van Moolenbroek 		s = "delete";
1032*83ee113eSDavid van Moolenbroek 		left = 4;
1033*83ee113eSDavid van Moolenbroek 		goto dodnsupd;
1034*83ee113eSDavid van Moolenbroek 	      case expr_ns_exists:
1035*83ee113eSDavid van Moolenbroek 		s = "exists";
1036*83ee113eSDavid van Moolenbroek 		left = 4;
1037*83ee113eSDavid van Moolenbroek 		goto dodnsupd;
1038*83ee113eSDavid van Moolenbroek 	      case expr_ns_not_exists:
1039*83ee113eSDavid van Moolenbroek 		s = "not_exists";
1040*83ee113eSDavid van Moolenbroek 		left = 4;
1041*83ee113eSDavid van Moolenbroek 		goto dodnsupd;
1042*83ee113eSDavid van Moolenbroek 	      case expr_ns_add:
1043*83ee113eSDavid van Moolenbroek 		s = "update";
1044*83ee113eSDavid van Moolenbroek 		left = 5;
1045*83ee113eSDavid van Moolenbroek 	      dodnsupd:
1046*83ee113eSDavid van Moolenbroek 		rv = strlen (s);
1047*83ee113eSDavid van Moolenbroek 		if (len > strlen (s) + 1) {
1048*83ee113eSDavid van Moolenbroek 			buf [0] = '(';
1049*83ee113eSDavid van Moolenbroek 			strcpy (buf + 1, s);
1050*83ee113eSDavid van Moolenbroek 			rv++;
1051*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
1052*83ee113eSDavid van Moolenbroek 			s = print_dec_1 (expr -> data.ns_add.rrclass);
1053*83ee113eSDavid van Moolenbroek 			if (len > rv + strlen (s) + left) {
1054*83ee113eSDavid van Moolenbroek 				strcpy (&buf [rv], s);
1055*83ee113eSDavid van Moolenbroek 				rv += strlen (&buf [rv]);
1056*83ee113eSDavid van Moolenbroek 			}
1057*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
1058*83ee113eSDavid van Moolenbroek 			left--;
1059*83ee113eSDavid van Moolenbroek 			s = print_dec_1 (expr -> data.ns_add.rrtype);
1060*83ee113eSDavid van Moolenbroek 			if (len > rv + strlen (s) + left) {
1061*83ee113eSDavid van Moolenbroek 				strcpy (&buf [rv], s);
1062*83ee113eSDavid van Moolenbroek 				rv += strlen (&buf [rv]);
1063*83ee113eSDavid van Moolenbroek 			}
1064*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
1065*83ee113eSDavid van Moolenbroek 			left--;
1066*83ee113eSDavid van Moolenbroek 			rv += print_subexpression
1067*83ee113eSDavid van Moolenbroek 				(expr -> data.ns_add.rrname,
1068*83ee113eSDavid van Moolenbroek 				 buf + rv, len - rv - left);
1069*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
1070*83ee113eSDavid van Moolenbroek 			left--;
1071*83ee113eSDavid van Moolenbroek 			rv += print_subexpression
1072*83ee113eSDavid van Moolenbroek 				(expr -> data.ns_add.rrdata,
1073*83ee113eSDavid van Moolenbroek 				 buf + rv, len - rv - left);
1074*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
1075*83ee113eSDavid van Moolenbroek 			left--;
1076*83ee113eSDavid van Moolenbroek 			rv += print_subexpression
1077*83ee113eSDavid van Moolenbroek 				(expr -> data.ns_add.ttl,
1078*83ee113eSDavid van Moolenbroek 				 buf + rv, len - rv - left);
1079*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
1080*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
1081*83ee113eSDavid van Moolenbroek 			return rv;
1082*83ee113eSDavid van Moolenbroek 		}
1083*83ee113eSDavid van Moolenbroek 		break;
1084*83ee113eSDavid van Moolenbroek 
1085*83ee113eSDavid van Moolenbroek 	      case expr_null:
1086*83ee113eSDavid van Moolenbroek 		if (len > 6) {
1087*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(null)");
1088*83ee113eSDavid van Moolenbroek 			return 6;
1089*83ee113eSDavid van Moolenbroek 		}
1090*83ee113eSDavid van Moolenbroek 		break;
1091*83ee113eSDavid van Moolenbroek 	      case expr_funcall:
1092*83ee113eSDavid van Moolenbroek 		rv = 12 + strlen (expr -> data.funcall.name);
1093*83ee113eSDavid van Moolenbroek 		if (len > rv + 1) {
1094*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(funcall  ");
1095*83ee113eSDavid van Moolenbroek 			strcpy (buf + 9, expr -> data.funcall.name);
1096*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
1097*83ee113eSDavid van Moolenbroek 			rv += print_subexpression
1098*83ee113eSDavid van Moolenbroek 				(expr -> data.funcall.arglist, buf + rv,
1099*83ee113eSDavid van Moolenbroek 				 len - rv - 1);
1100*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
1101*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
1102*83ee113eSDavid van Moolenbroek 			return rv;
1103*83ee113eSDavid van Moolenbroek 		}
1104*83ee113eSDavid van Moolenbroek 		break;
1105*83ee113eSDavid van Moolenbroek 
1106*83ee113eSDavid van Moolenbroek 	      case expr_arg:
1107*83ee113eSDavid van Moolenbroek 		rv = print_subexpression (expr -> data.arg.val, buf, len);
1108*83ee113eSDavid van Moolenbroek 		if (expr -> data.arg.next && rv + 2 < len) {
1109*83ee113eSDavid van Moolenbroek 			buf [rv++] = ' ';
1110*83ee113eSDavid van Moolenbroek 			rv += print_subexpression (expr -> data.arg.next,
1111*83ee113eSDavid van Moolenbroek 						   buf, len);
1112*83ee113eSDavid van Moolenbroek 			if (rv + 1 < len)
1113*83ee113eSDavid van Moolenbroek 				buf [rv++] = 0;
1114*83ee113eSDavid van Moolenbroek 			return rv;
1115*83ee113eSDavid van Moolenbroek 		}
1116*83ee113eSDavid van Moolenbroek 		break;
1117*83ee113eSDavid van Moolenbroek 
1118*83ee113eSDavid van Moolenbroek 	      case expr_function:
1119*83ee113eSDavid van Moolenbroek 		rv = 9;
1120*83ee113eSDavid van Moolenbroek 		if (len > rv + 1) {
1121*83ee113eSDavid van Moolenbroek 			struct string_list *foo;
1122*83ee113eSDavid van Moolenbroek 			strcpy (buf, "(function");
1123*83ee113eSDavid van Moolenbroek 			for (foo = expr -> data.func -> args;
1124*83ee113eSDavid van Moolenbroek 			     foo; foo = foo -> next) {
1125*83ee113eSDavid van Moolenbroek 				if (len > rv + 2 + strlen (foo -> string)) {
1126*83ee113eSDavid van Moolenbroek 					buf [rv - 1] = ' ';
1127*83ee113eSDavid van Moolenbroek 					strcpy (&buf [rv], foo -> string);
1128*83ee113eSDavid van Moolenbroek 					rv += strlen (foo -> string);
1129*83ee113eSDavid van Moolenbroek 				}
1130*83ee113eSDavid van Moolenbroek 			}
1131*83ee113eSDavid van Moolenbroek 			buf [rv++] = ')';
1132*83ee113eSDavid van Moolenbroek 			buf [rv] = 0;
1133*83ee113eSDavid van Moolenbroek 			return rv;
1134*83ee113eSDavid van Moolenbroek 		}
1135*83ee113eSDavid van Moolenbroek 		break;
1136*83ee113eSDavid van Moolenbroek 
1137*83ee113eSDavid van Moolenbroek 	      case expr_gethostname:
1138*83ee113eSDavid van Moolenbroek 		if (len > 13) {
1139*83ee113eSDavid van Moolenbroek 			strcpy(buf, "(gethostname)");
1140*83ee113eSDavid van Moolenbroek 			return 13;
1141*83ee113eSDavid van Moolenbroek 		}
1142*83ee113eSDavid van Moolenbroek 		break;
1143*83ee113eSDavid van Moolenbroek 
1144*83ee113eSDavid van Moolenbroek 	      default:
1145*83ee113eSDavid van Moolenbroek 		log_fatal("Impossible case at %s:%d (undefined expression "
1146*83ee113eSDavid van Moolenbroek 			  "%d).", MDL, expr->op);
1147*83ee113eSDavid van Moolenbroek 		break;
1148*83ee113eSDavid van Moolenbroek 	}
1149*83ee113eSDavid van Moolenbroek 	return 0;
1150*83ee113eSDavid van Moolenbroek }
1151*83ee113eSDavid van Moolenbroek 
print_expression(name,expr)1152*83ee113eSDavid van Moolenbroek void print_expression (name, expr)
1153*83ee113eSDavid van Moolenbroek 	const char *name;
1154*83ee113eSDavid van Moolenbroek 	struct expression *expr;
1155*83ee113eSDavid van Moolenbroek {
1156*83ee113eSDavid van Moolenbroek 	char buf [1024];
1157*83ee113eSDavid van Moolenbroek 
1158*83ee113eSDavid van Moolenbroek 	print_subexpression (expr, buf, sizeof buf);
1159*83ee113eSDavid van Moolenbroek 	log_info ("%s: %s", name, buf);
1160*83ee113eSDavid van Moolenbroek }
1161*83ee113eSDavid van Moolenbroek 
token_print_indent_concat(FILE * file,int col,int indent,const char * prefix,const char * suffix,...)1162*83ee113eSDavid van Moolenbroek int token_print_indent_concat (FILE *file, int col,  int indent,
1163*83ee113eSDavid van Moolenbroek 			       const char *prefix,
1164*83ee113eSDavid van Moolenbroek 			       const char *suffix, ...)
1165*83ee113eSDavid van Moolenbroek {
1166*83ee113eSDavid van Moolenbroek 	va_list list;
1167*83ee113eSDavid van Moolenbroek 	unsigned len;
1168*83ee113eSDavid van Moolenbroek 	char *s, *t, *u;
1169*83ee113eSDavid van Moolenbroek 
1170*83ee113eSDavid van Moolenbroek 	va_start (list, suffix);
1171*83ee113eSDavid van Moolenbroek 	s = va_arg (list, char *);
1172*83ee113eSDavid van Moolenbroek 	len = 0;
1173*83ee113eSDavid van Moolenbroek 	while (s) {
1174*83ee113eSDavid van Moolenbroek 		len += strlen (s);
1175*83ee113eSDavid van Moolenbroek 		s = va_arg (list, char *);
1176*83ee113eSDavid van Moolenbroek 	}
1177*83ee113eSDavid van Moolenbroek 	va_end (list);
1178*83ee113eSDavid van Moolenbroek 
1179*83ee113eSDavid van Moolenbroek 	t = dmalloc (len + 1, MDL);
1180*83ee113eSDavid van Moolenbroek 	if (!t)
1181*83ee113eSDavid van Moolenbroek 		log_fatal ("token_print_indent: no memory for copy buffer");
1182*83ee113eSDavid van Moolenbroek 
1183*83ee113eSDavid van Moolenbroek 	va_start (list, suffix);
1184*83ee113eSDavid van Moolenbroek 	s = va_arg (list, char *);
1185*83ee113eSDavid van Moolenbroek 	u = t;
1186*83ee113eSDavid van Moolenbroek 	while (s) {
1187*83ee113eSDavid van Moolenbroek 		len = strlen (s);
1188*83ee113eSDavid van Moolenbroek 		strcpy (u, s);
1189*83ee113eSDavid van Moolenbroek 		u += len;
1190*83ee113eSDavid van Moolenbroek 		s = va_arg (list, char *);
1191*83ee113eSDavid van Moolenbroek 	}
1192*83ee113eSDavid van Moolenbroek 	va_end (list);
1193*83ee113eSDavid van Moolenbroek 
1194*83ee113eSDavid van Moolenbroek 	col = token_print_indent (file, col, indent,
1195*83ee113eSDavid van Moolenbroek 				  prefix, suffix, t);
1196*83ee113eSDavid van Moolenbroek 	dfree (t, MDL);
1197*83ee113eSDavid van Moolenbroek 	return col;
1198*83ee113eSDavid van Moolenbroek }
1199*83ee113eSDavid van Moolenbroek 
token_indent_data_string(FILE * file,int col,int indent,const char * prefix,const char * suffix,struct data_string * data)1200*83ee113eSDavid van Moolenbroek int token_indent_data_string (FILE *file, int col, int indent,
1201*83ee113eSDavid van Moolenbroek 			      const char *prefix, const char *suffix,
1202*83ee113eSDavid van Moolenbroek 			      struct data_string *data)
1203*83ee113eSDavid van Moolenbroek {
1204*83ee113eSDavid van Moolenbroek 	int i;
1205*83ee113eSDavid van Moolenbroek 	char *buf;
1206*83ee113eSDavid van Moolenbroek 	char obuf [3];
1207*83ee113eSDavid van Moolenbroek 
1208*83ee113eSDavid van Moolenbroek 	/* See if this is just ASCII. */
1209*83ee113eSDavid van Moolenbroek 	for (i = 0; i < data -> len; i++)
1210*83ee113eSDavid van Moolenbroek 		if (!isascii (data -> data [i]) ||
1211*83ee113eSDavid van Moolenbroek 		    !isprint (data -> data [i]))
1212*83ee113eSDavid van Moolenbroek 			break;
1213*83ee113eSDavid van Moolenbroek 
1214*83ee113eSDavid van Moolenbroek 	/* If we have a purely ASCII string, output it as text. */
1215*83ee113eSDavid van Moolenbroek 	if (i == data -> len) {
1216*83ee113eSDavid van Moolenbroek 		buf = dmalloc (data -> len + 3, MDL);
1217*83ee113eSDavid van Moolenbroek 		if (buf) {
1218*83ee113eSDavid van Moolenbroek 			buf [0] = '"';
1219*83ee113eSDavid van Moolenbroek 			memcpy (buf + 1, data -> data, data -> len);
1220*83ee113eSDavid van Moolenbroek 			buf [data -> len + 1] = '"';
1221*83ee113eSDavid van Moolenbroek 			buf [data -> len + 2] = 0;
1222*83ee113eSDavid van Moolenbroek 			i = token_print_indent (file, col, indent,
1223*83ee113eSDavid van Moolenbroek 						prefix, suffix, buf);
1224*83ee113eSDavid van Moolenbroek 			dfree (buf, MDL);
1225*83ee113eSDavid van Moolenbroek 			return i;
1226*83ee113eSDavid van Moolenbroek 		}
1227*83ee113eSDavid van Moolenbroek 	}
1228*83ee113eSDavid van Moolenbroek 
1229*83ee113eSDavid van Moolenbroek 	for (i = 0; i < data -> len; i++) {
1230*83ee113eSDavid van Moolenbroek 		sprintf (obuf, "%2.2x", data -> data [i]);
1231*83ee113eSDavid van Moolenbroek 		col = token_print_indent (file, col, indent,
1232*83ee113eSDavid van Moolenbroek 					  i == 0 ? prefix : "",
1233*83ee113eSDavid van Moolenbroek 					  (i + 1 == data -> len
1234*83ee113eSDavid van Moolenbroek 					   ? suffix
1235*83ee113eSDavid van Moolenbroek 					   : ""), obuf);
1236*83ee113eSDavid van Moolenbroek 		if (i + 1 != data -> len)
1237*83ee113eSDavid van Moolenbroek 			col = token_print_indent (file, col, indent,
1238*83ee113eSDavid van Moolenbroek 						  prefix, suffix, ":");
1239*83ee113eSDavid van Moolenbroek 	}
1240*83ee113eSDavid van Moolenbroek 	return col;
1241*83ee113eSDavid van Moolenbroek }
1242*83ee113eSDavid van Moolenbroek 
token_print_indent(FILE * file,int col,int indent,const char * prefix,const char * suffix,const char * buf)1243*83ee113eSDavid van Moolenbroek int token_print_indent (FILE *file, int col, int indent,
1244*83ee113eSDavid van Moolenbroek 			const char *prefix,
1245*83ee113eSDavid van Moolenbroek 			const char *suffix, const char *buf)
1246*83ee113eSDavid van Moolenbroek {
1247*83ee113eSDavid van Moolenbroek 	int len = 0;
1248*83ee113eSDavid van Moolenbroek 	if (prefix != NULL)
1249*83ee113eSDavid van Moolenbroek 		len += strlen (prefix);
1250*83ee113eSDavid van Moolenbroek 	if (buf != NULL)
1251*83ee113eSDavid van Moolenbroek 		len += strlen (buf);
1252*83ee113eSDavid van Moolenbroek 
1253*83ee113eSDavid van Moolenbroek 	if (col + len > 79) {
1254*83ee113eSDavid van Moolenbroek 		if (indent + len < 79) {
1255*83ee113eSDavid van Moolenbroek 			indent_spaces (file, indent);
1256*83ee113eSDavid van Moolenbroek 			col = indent;
1257*83ee113eSDavid van Moolenbroek 		} else {
1258*83ee113eSDavid van Moolenbroek 			indent_spaces (file, col);
1259*83ee113eSDavid van Moolenbroek 			col = len > 79 ? 0 : 79 - len - 1;
1260*83ee113eSDavid van Moolenbroek 		}
1261*83ee113eSDavid van Moolenbroek 	} else if (prefix && *prefix) {
1262*83ee113eSDavid van Moolenbroek 		fputs (prefix, file);
1263*83ee113eSDavid van Moolenbroek 		col += strlen (prefix);
1264*83ee113eSDavid van Moolenbroek 	}
1265*83ee113eSDavid van Moolenbroek 	if ((buf != NULL) && (*buf != 0)) {
1266*83ee113eSDavid van Moolenbroek 		fputs (buf, file);
1267*83ee113eSDavid van Moolenbroek 		col += strlen(buf);
1268*83ee113eSDavid van Moolenbroek 	}
1269*83ee113eSDavid van Moolenbroek 	if (suffix && *suffix) {
1270*83ee113eSDavid van Moolenbroek 		if (col + strlen (suffix) > 79) {
1271*83ee113eSDavid van Moolenbroek 			indent_spaces (file, indent);
1272*83ee113eSDavid van Moolenbroek 			col = indent;
1273*83ee113eSDavid van Moolenbroek 		} else {
1274*83ee113eSDavid van Moolenbroek 			fputs (suffix, file);
1275*83ee113eSDavid van Moolenbroek 			col += strlen (suffix);
1276*83ee113eSDavid van Moolenbroek 		}
1277*83ee113eSDavid van Moolenbroek 	}
1278*83ee113eSDavid van Moolenbroek 	return col;
1279*83ee113eSDavid van Moolenbroek }
1280*83ee113eSDavid van Moolenbroek 
indent_spaces(FILE * file,int indent)1281*83ee113eSDavid van Moolenbroek void indent_spaces (FILE *file, int indent)
1282*83ee113eSDavid van Moolenbroek {
1283*83ee113eSDavid van Moolenbroek 	int i;
1284*83ee113eSDavid van Moolenbroek 	fputc ('\n', file);
1285*83ee113eSDavid van Moolenbroek 	for (i = 0; i < indent; i++)
1286*83ee113eSDavid van Moolenbroek 		fputc (' ', file);
1287*83ee113eSDavid van Moolenbroek }
1288*83ee113eSDavid van Moolenbroek 
1289*83ee113eSDavid van Moolenbroek #if defined (NSUPDATE)
1290*83ee113eSDavid van Moolenbroek #if defined (DEBUG_DNS_UPDATES)
1291*83ee113eSDavid van Moolenbroek /*
1292*83ee113eSDavid van Moolenbroek  * direction outbound (messages to the dns server)
1293*83ee113eSDavid van Moolenbroek  *           inbound  (messages from the dns server)
1294*83ee113eSDavid van Moolenbroek  * ddns_cb is the control block associated with the message
1295*83ee113eSDavid van Moolenbroek  * result is the result from the dns code.  For outbound calls
1296*83ee113eSDavid van Moolenbroek  * it is from the call to pass the message to the dns library.
1297*83ee113eSDavid van Moolenbroek  * For inbound calls it is from the event returned by the library.
1298*83ee113eSDavid van Moolenbroek  *
1299*83ee113eSDavid van Moolenbroek  * For outbound messages we print whatever we think is interesting
1300*83ee113eSDavid van Moolenbroek  * from the control block.
1301*83ee113eSDavid van Moolenbroek  * For inbound messages we only print the transaction id pointer
1302*83ee113eSDavid van Moolenbroek  * and the result and expect that the user will match them up as
1303*83ee113eSDavid van Moolenbroek  * necessary.  Note well: the transaction information is opaque to
1304*83ee113eSDavid van Moolenbroek  * us so we simply print the pointer to it.  This should be sufficient
1305*83ee113eSDavid van Moolenbroek  * to match requests and replys in a short sequence but is awkward
1306*83ee113eSDavid van Moolenbroek  * when trying to use it for longer sequences.
1307*83ee113eSDavid van Moolenbroek  */
1308*83ee113eSDavid van Moolenbroek void
print_dns_status(int direction,struct dhcp_ddns_cb * ddns_cb,isc_result_t result)1309*83ee113eSDavid van Moolenbroek print_dns_status (int direction,
1310*83ee113eSDavid van Moolenbroek 		  struct dhcp_ddns_cb *ddns_cb,
1311*83ee113eSDavid van Moolenbroek 		  isc_result_t result)
1312*83ee113eSDavid van Moolenbroek {
1313*83ee113eSDavid van Moolenbroek 	char obuf[1024];
1314*83ee113eSDavid van Moolenbroek 	char *s = obuf, *end = &obuf[sizeof(obuf)-2];
1315*83ee113eSDavid van Moolenbroek 	char *en;
1316*83ee113eSDavid van Moolenbroek 	const char *result_str;
1317*83ee113eSDavid van Moolenbroek 	char ddns_address[
1318*83ee113eSDavid van Moolenbroek 		sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
1319*83ee113eSDavid van Moolenbroek 
1320*83ee113eSDavid van Moolenbroek 	if (direction == DDNS_PRINT_INBOUND) {
1321*83ee113eSDavid van Moolenbroek 		log_info("DDNS reply: id ptr %p, result: %s",
1322*83ee113eSDavid van Moolenbroek 			 ddns_cb->transaction, isc_result_totext(result));
1323*83ee113eSDavid van Moolenbroek 		return;
1324*83ee113eSDavid van Moolenbroek 	}
1325*83ee113eSDavid van Moolenbroek 
1326*83ee113eSDavid van Moolenbroek 	/*
1327*83ee113eSDavid van Moolenbroek 	 * To avoid having to figure out if any of the strings
1328*83ee113eSDavid van Moolenbroek 	 * aren't NULL terminated, just 0 the whole string
1329*83ee113eSDavid van Moolenbroek 	 */
1330*83ee113eSDavid van Moolenbroek 	memset(obuf, 0, 1024);
1331*83ee113eSDavid van Moolenbroek 
1332*83ee113eSDavid van Moolenbroek 	en = "DDNS request: id ptr ";
1333*83ee113eSDavid van Moolenbroek 	if (s + strlen(en) + 16 < end) {
1334*83ee113eSDavid van Moolenbroek 		sprintf(s, "%s%p", en, ddns_cb->transaction);
1335*83ee113eSDavid van Moolenbroek 		s += strlen(s);
1336*83ee113eSDavid van Moolenbroek 	} else {
1337*83ee113eSDavid van Moolenbroek 		goto bailout;
1338*83ee113eSDavid van Moolenbroek 	}
1339*83ee113eSDavid van Moolenbroek 
1340*83ee113eSDavid van Moolenbroek 	switch (ddns_cb->state) {
1341*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_ADD_FW_NXDOMAIN:
1342*83ee113eSDavid van Moolenbroek 		en = " add forward ";
1343*83ee113eSDavid van Moolenbroek 		break;
1344*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_ADD_FW_YXDHCID:
1345*83ee113eSDavid van Moolenbroek 		en = " modify forward ";
1346*83ee113eSDavid van Moolenbroek 		break;
1347*83ee113eSDavid van Moolenbroek 
1348*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_ADD_PTR:
1349*83ee113eSDavid van Moolenbroek 		en = " add reverse ";
1350*83ee113eSDavid van Moolenbroek 		break;
1351*83ee113eSDavid van Moolenbroek 
1352*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_REM_FW_YXDHCID:
1353*83ee113eSDavid van Moolenbroek 		en = " remove forward ";
1354*83ee113eSDavid van Moolenbroek 		break;
1355*83ee113eSDavid van Moolenbroek 
1356*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_REM_FW_NXRR:
1357*83ee113eSDavid van Moolenbroek 		en = " remove rrset ";
1358*83ee113eSDavid van Moolenbroek 		break;
1359*83ee113eSDavid van Moolenbroek 
1360*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_REM_PTR:
1361*83ee113eSDavid van Moolenbroek 		en = " remove reverse ";
1362*83ee113eSDavid van Moolenbroek 		break;
1363*83ee113eSDavid van Moolenbroek 
1364*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_CLEANUP:
1365*83ee113eSDavid van Moolenbroek 		en = " cleanup ";
1366*83ee113eSDavid van Moolenbroek 		break;
1367*83ee113eSDavid van Moolenbroek 
1368*83ee113eSDavid van Moolenbroek 	default:
1369*83ee113eSDavid van Moolenbroek 		en = " unknown state ";
1370*83ee113eSDavid van Moolenbroek 		break;
1371*83ee113eSDavid van Moolenbroek 	}
1372*83ee113eSDavid van Moolenbroek 
1373*83ee113eSDavid van Moolenbroek 	switch (ddns_cb->state) {
1374*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_ADD_FW_NXDOMAIN:
1375*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_ADD_FW_YXDHCID:
1376*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_REM_FW_YXDHCID:
1377*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_REM_FW_NXRR:
1378*83ee113eSDavid van Moolenbroek 		strcpy(ddns_address, piaddr(ddns_cb->address));
1379*83ee113eSDavid van Moolenbroek 		if (s + strlen(en) + strlen(ddns_address) +
1380*83ee113eSDavid van Moolenbroek 		    ddns_cb->fwd_name.len + 5 < end) {
1381*83ee113eSDavid van Moolenbroek 			sprintf(s, "%s%s for %.*s", en, ddns_address,
1382*83ee113eSDavid van Moolenbroek 				ddns_cb->fwd_name.len,
1383*83ee113eSDavid van Moolenbroek 				ddns_cb->fwd_name.data);
1384*83ee113eSDavid van Moolenbroek 			s += strlen(s);
1385*83ee113eSDavid van Moolenbroek 		} else {
1386*83ee113eSDavid van Moolenbroek 			goto bailout;
1387*83ee113eSDavid van Moolenbroek 		}
1388*83ee113eSDavid van Moolenbroek 		break;
1389*83ee113eSDavid van Moolenbroek 
1390*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_ADD_PTR:
1391*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_REM_PTR:
1392*83ee113eSDavid van Moolenbroek 		if (s + strlen(en) + ddns_cb->fwd_name.len +
1393*83ee113eSDavid van Moolenbroek 		    ddns_cb->rev_name.len + 5 < end) {
1394*83ee113eSDavid van Moolenbroek 			sprintf(s, "%s%.*s for %.*s", en,
1395*83ee113eSDavid van Moolenbroek 				ddns_cb->fwd_name.len,
1396*83ee113eSDavid van Moolenbroek 				ddns_cb->fwd_name.data,
1397*83ee113eSDavid van Moolenbroek 				ddns_cb->rev_name.len,
1398*83ee113eSDavid van Moolenbroek 				ddns_cb->rev_name.data);
1399*83ee113eSDavid van Moolenbroek 			s += strlen(s);
1400*83ee113eSDavid van Moolenbroek 		} else {
1401*83ee113eSDavid van Moolenbroek 			goto bailout;
1402*83ee113eSDavid van Moolenbroek 		}
1403*83ee113eSDavid van Moolenbroek 		break;
1404*83ee113eSDavid van Moolenbroek 
1405*83ee113eSDavid van Moolenbroek 	case DDNS_STATE_CLEANUP:
1406*83ee113eSDavid van Moolenbroek 	default:
1407*83ee113eSDavid van Moolenbroek 		if (s + strlen(en) < end) {
1408*83ee113eSDavid van Moolenbroek 			sprintf(s, "%s", en);
1409*83ee113eSDavid van Moolenbroek 			s += strlen(s);
1410*83ee113eSDavid van Moolenbroek 		} else {
1411*83ee113eSDavid van Moolenbroek 			goto bailout;
1412*83ee113eSDavid van Moolenbroek 		}
1413*83ee113eSDavid van Moolenbroek 		break;
1414*83ee113eSDavid van Moolenbroek 	}
1415*83ee113eSDavid van Moolenbroek 
1416*83ee113eSDavid van Moolenbroek 	en = " zone: ";
1417*83ee113eSDavid van Moolenbroek 	if (s + strlen(en) + strlen((char *)ddns_cb->zone_name) < end) {
1418*83ee113eSDavid van Moolenbroek 		sprintf(s, "%s%s", en, ddns_cb->zone_name);
1419*83ee113eSDavid van Moolenbroek 		s += strlen(s);
1420*83ee113eSDavid van Moolenbroek 	} else {
1421*83ee113eSDavid van Moolenbroek 		goto bailout;
1422*83ee113eSDavid van Moolenbroek 	}
1423*83ee113eSDavid van Moolenbroek 
1424*83ee113eSDavid van Moolenbroek 	en = " dhcid: ";
1425*83ee113eSDavid van Moolenbroek 	if (ddns_cb->dhcid.len > 0) {
1426*83ee113eSDavid van Moolenbroek 		if (s + strlen(en) + ddns_cb->dhcid.len-1 < end) {
1427*83ee113eSDavid van Moolenbroek 			strcpy(s, en);
1428*83ee113eSDavid van Moolenbroek 			s += strlen(s);
1429*83ee113eSDavid van Moolenbroek 			strncpy(s, (char *)ddns_cb->dhcid.data+1,
1430*83ee113eSDavid van Moolenbroek 				ddns_cb->dhcid.len-1);
1431*83ee113eSDavid van Moolenbroek 			s += strlen(s);
1432*83ee113eSDavid van Moolenbroek 		} else {
1433*83ee113eSDavid van Moolenbroek 			goto bailout;
1434*83ee113eSDavid van Moolenbroek 		}
1435*83ee113eSDavid van Moolenbroek 	} else {
1436*83ee113eSDavid van Moolenbroek 		en = " dhcid: <empty>";
1437*83ee113eSDavid van Moolenbroek 		if (s + strlen(en) < end) {
1438*83ee113eSDavid van Moolenbroek 			strcpy(s, en);
1439*83ee113eSDavid van Moolenbroek 			s += strlen(s);
1440*83ee113eSDavid van Moolenbroek 		} else {
1441*83ee113eSDavid van Moolenbroek 			goto bailout;
1442*83ee113eSDavid van Moolenbroek 		}
1443*83ee113eSDavid van Moolenbroek 	}
1444*83ee113eSDavid van Moolenbroek 
1445*83ee113eSDavid van Moolenbroek 	en = " ttl: ";
1446*83ee113eSDavid van Moolenbroek 	if (s + strlen(en) + 10 < end) {
1447*83ee113eSDavid van Moolenbroek 		sprintf(s, "%s%ld", en, ddns_cb->ttl);
1448*83ee113eSDavid van Moolenbroek 		s += strlen(s);
1449*83ee113eSDavid van Moolenbroek 	} else {
1450*83ee113eSDavid van Moolenbroek 		goto bailout;
1451*83ee113eSDavid van Moolenbroek 	}
1452*83ee113eSDavid van Moolenbroek 
1453*83ee113eSDavid van Moolenbroek 	en = " result: ";
1454*83ee113eSDavid van Moolenbroek 	result_str = isc_result_totext(result);
1455*83ee113eSDavid van Moolenbroek 	if (s + strlen(en) + strlen(result_str) < end) {
1456*83ee113eSDavid van Moolenbroek 		sprintf(s, "%s%s", en, result_str);
1457*83ee113eSDavid van Moolenbroek 		s += strlen(s);
1458*83ee113eSDavid van Moolenbroek 	} else {
1459*83ee113eSDavid van Moolenbroek 		goto bailout;
1460*83ee113eSDavid van Moolenbroek 	}
1461*83ee113eSDavid van Moolenbroek 
1462*83ee113eSDavid van Moolenbroek  bailout:
1463*83ee113eSDavid van Moolenbroek 	/*
1464*83ee113eSDavid van Moolenbroek 	 * We either finished building the string or ran out
1465*83ee113eSDavid van Moolenbroek 	 * of space, print whatever we have in case it is useful
1466*83ee113eSDavid van Moolenbroek 	 */
1467*83ee113eSDavid van Moolenbroek 	log_info("%s", obuf);
1468*83ee113eSDavid van Moolenbroek 
1469*83ee113eSDavid van Moolenbroek 	return;
1470*83ee113eSDavid van Moolenbroek }
1471*83ee113eSDavid van Moolenbroek #endif
1472*83ee113eSDavid van Moolenbroek #endif /* NSUPDATE */
1473*83ee113eSDavid van Moolenbroek 
1474*83ee113eSDavid van Moolenbroek /* Format the given time as "A; # B", where A is the format
1475*83ee113eSDavid van Moolenbroek  * used by the parser, and B is the local time, for humans.
1476*83ee113eSDavid van Moolenbroek  */
1477*83ee113eSDavid van Moolenbroek const char *
print_time(TIME t)1478*83ee113eSDavid van Moolenbroek print_time(TIME t)
1479*83ee113eSDavid van Moolenbroek {
1480*83ee113eSDavid van Moolenbroek 	static char buf[sizeof("epoch 9223372036854775807; "
1481*83ee113eSDavid van Moolenbroek 			       "# Wed Jun 30 21:49:08 2147483647")];
1482*83ee113eSDavid van Moolenbroek 	static char buf1[sizeof("# Wed Jun 30 21:49:08 2147483647")];
1483*83ee113eSDavid van Moolenbroek 	time_t since_epoch;
1484*83ee113eSDavid van Moolenbroek 	/* The string: 	       "6 2147483647/12/31 23:59:60;"
1485*83ee113eSDavid van Moolenbroek 	 * is smaller than the other, used to declare the buffer size, so
1486*83ee113eSDavid van Moolenbroek 	 * we can use one buffer for both.
1487*83ee113eSDavid van Moolenbroek 	 */
1488*83ee113eSDavid van Moolenbroek 
1489*83ee113eSDavid van Moolenbroek 	if (t == MAX_TIME)
1490*83ee113eSDavid van Moolenbroek 		return "never;";
1491*83ee113eSDavid van Moolenbroek 
1492*83ee113eSDavid van Moolenbroek 	if (t < 0)
1493*83ee113eSDavid van Moolenbroek 		return NULL;
1494*83ee113eSDavid van Moolenbroek 
1495*83ee113eSDavid van Moolenbroek 	/* For those lucky enough to have a 128-bit time_t, ensure that
1496*83ee113eSDavid van Moolenbroek 	 * whatever (corrupt) value we're given doesn't exceed the static
1497*83ee113eSDavid van Moolenbroek 	 * buffer.
1498*83ee113eSDavid van Moolenbroek 	 */
1499*83ee113eSDavid van Moolenbroek #if (MAX_TIME > 0x7fffffffffffffff)
1500*83ee113eSDavid van Moolenbroek 	if (t > 0x7fffffffffffffff)
1501*83ee113eSDavid van Moolenbroek 		return NULL;
1502*83ee113eSDavid van Moolenbroek #endif
1503*83ee113eSDavid van Moolenbroek 
1504*83ee113eSDavid van Moolenbroek 	if (db_time_format == LOCAL_TIME_FORMAT) {
1505*83ee113eSDavid van Moolenbroek 		since_epoch = mktime(localtime(&t));
1506*83ee113eSDavid van Moolenbroek 		if ((strftime(buf1, sizeof(buf1),
1507*83ee113eSDavid van Moolenbroek 			      "# %a %b %d %H:%M:%S %Y",
1508*83ee113eSDavid van Moolenbroek 			      localtime(&t)) == 0) ||
1509*83ee113eSDavid van Moolenbroek 		    (snprintf(buf, sizeof(buf), "epoch %lu; %s",
1510*83ee113eSDavid van Moolenbroek 			      (unsigned long)since_epoch, buf1) >= sizeof(buf)))
1511*83ee113eSDavid van Moolenbroek 			return NULL;
1512*83ee113eSDavid van Moolenbroek 
1513*83ee113eSDavid van Moolenbroek 	} else {
1514*83ee113eSDavid van Moolenbroek 		/* No bounds check for the year is necessary - in this case,
1515*83ee113eSDavid van Moolenbroek 		 * strftime() will run out of space and assert an error.
1516*83ee113eSDavid van Moolenbroek 		 */
1517*83ee113eSDavid van Moolenbroek 		if (strftime(buf, sizeof(buf), "%w %Y/%m/%d %H:%M:%S;",
1518*83ee113eSDavid van Moolenbroek 			     gmtime(&t)) == 0)
1519*83ee113eSDavid van Moolenbroek 			return NULL;
1520*83ee113eSDavid van Moolenbroek 	}
1521*83ee113eSDavid van Moolenbroek 
1522*83ee113eSDavid van Moolenbroek 	return buf;
1523*83ee113eSDavid van Moolenbroek }
1524