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