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 36int db_time_format = DEFAULT_TIME_FORMAT; 37 38char *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 76char *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 126char *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 176char *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 199void 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) 226void 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 256void 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 298void 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 30801234567890123456789012345678901234567890123456789012345678901234567890123 309280: 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 349void 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 */ 385void 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 */ 424void 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 461char *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 498char *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 529char *print_dec_1 (val) 530 unsigned long val; 531{ 532 static char vbuf [32]; 533 sprintf (vbuf, "%lu", val); 534 return vbuf; 535} 536 537char *print_dec_2 (val) 538 unsigned long val; 539{ 540 static char vbuf [32]; 541 sprintf (vbuf, "%lu", val); 542 return vbuf; 543} 544 545static unsigned print_subexpression (struct expression *, char *, unsigned); 546 547static 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 1176void 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 1186int 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 1224int 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 1267int 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 1305void 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 */ 1316const char * 1317print_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*/ 1377char *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*/ 1432char *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 */ 1458char *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