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