]> git.ipfire.org Git - thirdparty/dhcp.git/blame - common/print.c
- Silence benign static analysis warnings.
[thirdparty/dhcp.git] / common / print.c
CommitLineData
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
38int db_time_format = DEFAULT_TIME_FORMAT;
39
0efc1180
TL
40char *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
78char *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
116char *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 166char *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
189void 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
216void 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
246void 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
288void 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
29801234567890123456789012345678901234567890123456789012345678901234567890123
299280: 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
339void 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 */
375void 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 */
402void 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
439char *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
476char *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
507char *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
515char *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 523static unsigned print_subexpression (struct expression *, char *, unsigned);
2d0eb019 524
b1b7b521 525static 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
1154void 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
1164int 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
1202int 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
1245int 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
1283void 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
1310void
1311print_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 */
1479const char *
1480print_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}