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