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