1/* print.c 2 3 Turn data structures into printable text. */ 4 5/* 6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 7 * Copyright (c) 1995-2003 by Internet Software Consortium 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 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 * http://www.isc.org/ 26 * 27 * This software has been written for Internet Systems Consortium 28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. 29 * To learn more about Internet Systems Consortium, see 30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises, 31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see 32 * ``http://www.nominum.com''. 33 */ 34 35#ifndef lint 36static char copyright[] = 37"$Id: print.c,v 1.7 2005/08/11 17:13:21 drochner Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n"; 38#endif /* not lint */ 39 40#include "dhcpd.h" 41 42char *quotify_string (const char *s, const char *file, int line) 43{ 44 unsigned len = 0; 45 const char *sp; 46 char *buf, *nsp; 47 48 for (sp = s; sp && *sp; sp++) { 49 if (*sp == ' ') 50 len++; 51 else if (!isascii (*sp) || !isprint ((unsigned char)*sp)) 52 len += 4; 53 else if (*sp == '"' || *sp == '\\') 54 len += 2; 55 else 56 len++; 57 } 58 59 buf = dmalloc (len + 1, file, line); 60 if (buf) { 61 nsp = buf; 62 for (sp = s; sp && *sp; sp++) { 63 if (*sp == ' ') 64 *nsp++ = ' '; 65 else if (!isascii (*sp) || !isprint ((unsigned char)*sp)) { 66 sprintf (nsp, "\\%03o", 67 *(const unsigned char *)sp); 68 nsp += 4; 69 } else if (*sp == '"' || *sp == '\\') { 70 *nsp++ = '\\'; 71 *nsp++ = *sp; 72 } else 73 *nsp++ = *sp; 74 } 75 *nsp++ = 0; 76 } 77 return buf; 78} 79 80char *quotify_buf (const unsigned char *s, unsigned len, 81 const char *file, int line) 82{ 83 unsigned nulen = 0; 84 char *buf, *nsp; 85 int i; 86 87 for (i = 0; i < len; i++) { 88 if (s [i] == ' ') 89 nulen++; 90 else if (!isascii (s [i]) || !isprint (s [i])) 91 nulen += 4; 92 else if (s [i] == '"' || s [i] == '\\') 93 nulen += 2; 94 else 95 nulen++; 96 } 97 98 buf = dmalloc (nulen + 1, MDL); 99 if (buf) { 100 nsp = buf; 101 for (i = 0; i < len; i++) { 102 if (s [i] == ' ') 103 *nsp++ = ' '; 104 else if (!isascii (s [i]) || !isprint (s [i])) { 105 sprintf (nsp, "\\%03o", s [i]); 106 nsp += 4; 107 } else if (s [i] == '"' || s [i] == '\\') { 108 *nsp++ = '\\'; 109 *nsp++ = s [i]; 110 } else 111 *nsp++ = s [i]; 112 } 113 *nsp++ = 0; 114 } 115 return buf; 116} 117 118char *print_base64 (const unsigned char *buf, unsigned len, 119 const char *file, int line) 120{ 121 char *s, *b; 122 unsigned bl; 123 int i; 124 unsigned val, extra; 125 static char to64 [] = 126 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 127 128 bl = ((len * 4 + 2) / 3) + 1; 129 b = dmalloc (bl + 1, file, line); 130 if (!b) 131 return (char *)0; 132 133 i = 0; 134 s = b; 135 while (i != len) { 136 val = buf [i++]; 137 extra = val & 3; 138 val = val >> 2; 139 *s++ = to64 [val]; 140 if (i == len) { 141 *s++ = to64 [extra << 4]; 142 *s++ = '='; 143 break; 144 } 145 val = (extra << 8) + buf [i++]; 146 extra = val & 15; 147 val = val >> 4; 148 *s++ = to64 [val]; 149 if (i == len) { 150 *s++ = to64 [extra << 2]; 151 *s++ = '='; 152 break; 153 } 154 val = (extra << 8) + buf [i++]; 155 extra = val & 0x3f; 156 val = val >> 6; 157 *s++ = to64 [val]; 158 *s++ = to64 [extra]; 159 } 160 if (!len) 161 *s++ = '='; 162 *s++ = 0; 163 if (s > b + bl + 1) 164 abort (); 165 return b; 166} 167 168char *print_hw_addr (htype, hlen, data) 169 int htype; 170 int hlen; 171 unsigned char *data; 172{ 173 static char habuf [49]; 174 char *s; 175 int i; 176 177 if (hlen <= 0) 178 habuf [0] = 0; 179 else { 180 s = habuf; 181 for (i = 0; i < hlen; i++) { 182 sprintf (s, "%02x", data [i]); 183 s += strlen (s); 184 *s++ = ':'; 185 } 186 *--s = 0; 187 } 188 return habuf; 189} 190 191void print_lease (lease) 192 struct lease *lease; 193{ 194 struct tm *t; 195 char tbuf [32]; 196 197 log_debug (" Lease %s", 198 piaddr (lease -> ip_addr)); 199 200 t = gmtime (&lease -> starts); 201 strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); 202 log_debug (" start %s", tbuf); 203 204 t = gmtime (&lease -> ends); 205 strftime (tbuf, sizeof tbuf, "%Y/%m/%d %H:%M:%S", t); 206 log_debug (" end %s", tbuf); 207 208 if (lease -> hardware_addr.hlen) 209 log_debug (" hardware addr = %s", 210 print_hw_addr (lease -> hardware_addr.hbuf [0], 211 lease -> hardware_addr.hlen - 1, 212 &lease -> hardware_addr.hbuf [1])); 213 log_debug (" host %s ", 214 lease -> host ? lease -> host -> name : "<none>"); 215} 216 217#if defined (DEBUG_PACKET) 218void dump_packet_option (struct option_cache *oc, 219 struct packet *packet, 220 struct lease *lease, 221 struct client_state *client, 222 struct option_state *in_options, 223 struct option_state *cfg_options, 224 struct binding_scope **scope, 225 struct universe *u, void *foo) 226{ 227 const char *name, *dot; 228 struct data_string ds; 229 memset (&ds, 0, sizeof ds); 230 231 if (u != &dhcp_universe) { 232 name = u -> name; 233 dot = "."; 234 } else { 235 name = ""; 236 dot = ""; 237 } 238 if (evaluate_option_cache (&ds, packet, lease, client, 239 in_options, cfg_options, scope, oc, MDL)) { 240 log_debug (" option %s%s%s %s;\n", 241 name, dot, oc -> option -> name, 242 pretty_print_option (oc -> option, 243 ds.data, ds.len, 1, 1)); 244 data_string_forget (&ds, MDL); 245 } 246} 247 248void dump_packet (tp) 249 struct packet *tp; 250{ 251 struct dhcp_packet *tdp = tp -> raw; 252 253 log_debug ("packet length %d", tp -> packet_length); 254 log_debug ("op = %d htype = %d hlen = %d hops = %d", 255 tdp -> op, tdp -> htype, tdp -> hlen, tdp -> hops); 256 log_debug ("xid = %x secs = %ld flags = %x", 257 tdp -> xid, (unsigned long)tdp -> secs, tdp -> flags); 258 log_debug ("ciaddr = %s", inet_ntoa (tdp -> ciaddr)); 259 log_debug ("yiaddr = %s", inet_ntoa (tdp -> yiaddr)); 260 log_debug ("siaddr = %s", inet_ntoa (tdp -> siaddr)); 261 log_debug ("giaddr = %s", inet_ntoa (tdp -> giaddr)); 262 log_debug ("chaddr = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", 263 ((unsigned char *)(tdp -> chaddr)) [0], 264 ((unsigned char *)(tdp -> chaddr)) [1], 265 ((unsigned char *)(tdp -> chaddr)) [2], 266 ((unsigned char *)(tdp -> chaddr)) [3], 267 ((unsigned char *)(tdp -> chaddr)) [4], 268 ((unsigned char *)(tdp -> chaddr)) [5]); 269 log_debug ("filename = %s", tdp -> file); 270 log_debug ("server_name = %s", tdp -> sname); 271 if (tp -> options_valid) { 272 int i; 273 274 for (i = 0; i < tp -> options -> universe_count; i++) { 275 if (tp -> options -> universes [i]) { 276 option_space_foreach (tp, (struct lease *)0, 277 (struct client_state *)0, 278 (struct option_state *)0, 279 tp -> options, 280 &global_scope, 281 universes [i], 0, 282 dump_packet_option); 283 } 284 } 285 } 286 log_debug ("%s", ""); 287} 288#endif 289 290void dump_raw (buf, len) 291 const unsigned char *buf; 292 unsigned len; 293{ 294 int i; 295 char lbuf [80]; 296 int lbix = 0; 297 298/* 299 1 2 3 4 5 6 7 30001234567890123456789012345678901234567890123456789012345678901234567890123 301280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................. 302*/ 303 304 memset(lbuf, ' ', 79); 305 lbuf [79] = 0; 306 307 for (i = 0; i < len; i++) { 308 if ((i & 15) == 0) { 309 if (lbix) { 310 lbuf[53]=' '; 311 lbuf[54]=' '; 312 lbuf[55]=' '; 313 lbuf[73]='\0'; 314 log_info ("%s", lbuf); 315 } 316 memset(lbuf, ' ', 79); 317 lbuf [79] = 0; 318 sprintf (lbuf, "%03x:", i); 319 lbix = 4; 320 } else if ((i & 7) == 0) 321 lbuf [lbix++] = ' '; 322 323 if(isprint(buf[i])) { 324 lbuf[56+(i%16)]=buf[i]; 325 } else { 326 lbuf[56+(i%16)]='.'; 327 } 328 329 sprintf (&lbuf [lbix], " %02x", buf [i]); 330 lbix += 3; 331 lbuf[lbix]=' '; 332 333 } 334 lbuf[53]=' '; 335 lbuf[54]=' '; 336 lbuf[55]=' '; 337 lbuf[73]='\0'; 338 log_info ("%s", lbuf); 339} 340 341void hash_dump (table) 342 struct hash_table *table; 343{ 344 int i; 345 struct hash_bucket *bp; 346 347 if (!table) 348 return; 349 350 for (i = 0; i < table -> hash_count; i++) { 351 if (!table -> buckets [i]) 352 continue; 353 log_info ("hash bucket %d:", i); 354 for (bp = table -> buckets [i]; bp; bp = bp -> next) { 355 if (bp -> len) 356 dump_raw (bp -> name, bp -> len); 357 else 358 log_info ("%s", (const char *)bp -> name); 359 } 360 } 361} 362 363#define HBLEN 60 364 365#define DECLARE_HEX_PRINTER(x) \ 366char *print_hex##x (len, data, limit) \ 367 unsigned len; \ 368 const u_int8_t *data; \ 369 unsigned limit; \ 370{ \ 371 \ 372 static char hex_buf##x [HBLEN + 1]; \ 373 unsigned i; \ 374 \ 375 if (limit > HBLEN) \ 376 limit = HBLEN; \ 377 \ 378 for (i = 0; i < (limit - 2) && i < len; i++) { \ 379 if (!isascii (data [i]) || !isprint (data [i])) { \ 380 for (i = 0; i < limit / 3 && i < len; i++) { \ 381 sprintf (&hex_buf##x [i * 3], \ 382 "%02x:", data [i]); \ 383 } \ 384 hex_buf##x [i * 3 - 1] = 0; \ 385 return hex_buf##x; \ 386 } \ 387 } \ 388 hex_buf##x [0] = '"'; \ 389 i = len; \ 390 if (i > limit - 2) \ 391 i = limit - 2; \ 392 memcpy (&hex_buf##x [1], data, i); \ 393 hex_buf##x [i + 1] = '"'; \ 394 hex_buf##x [i + 2] = 0; \ 395 return hex_buf##x; \ 396} 397 398DECLARE_HEX_PRINTER (_1) 399DECLARE_HEX_PRINTER (_2) 400DECLARE_HEX_PRINTER (_3) 401 402#define DQLEN 80 403 404char *print_dotted_quads (len, data) 405 unsigned len; 406 const u_int8_t *data; 407{ 408 static char dq_buf [DQLEN + 1]; 409 int i; 410 char *s, *last; 411 412 s = &dq_buf [0]; 413 last = s; 414 415 i = 0; 416 417 /* %Audit% Loop bounds checks to 21 bytes. %2004.06.17,Safe% 418 * The sprintf can't exceed 18 bytes, and since the loop enforces 419 * 21 bytes of space per iteration at no time can we exit the 420 * loop without at least 3 bytes spare. 421 */ 422 do { 423 sprintf (s, "%u.%u.%u.%u, ", 424 data [i], data [i + 1], data [i + 2], data [i + 3]); 425 s += strlen (s); 426 i += 4; 427 } while ((s - &dq_buf [0] > DQLEN - 21) && 428 i + 3 < len); 429 if (i == len) 430 s [-2] = 0; 431 else 432 strcpy (s, "..."); 433 return dq_buf; 434} 435 436char *print_dec_1 (val) 437 unsigned long val; 438{ 439 static char vbuf [32]; 440 sprintf (vbuf, "%lu", val); 441 return vbuf; 442} 443 444char *print_dec_2 (val) 445 unsigned long val; 446{ 447 static char vbuf [32]; 448 sprintf (vbuf, "%lu", val); 449 return vbuf; 450} 451 452static unsigned print_subexpression PROTO ((struct expression *, 453 char *, unsigned)); 454 455static unsigned print_subexpression (expr, buf, len) 456 struct expression *expr; 457 char *buf; 458 unsigned len; 459{ 460 unsigned rv, left; 461 const char *s; 462 463 switch (expr -> op) { 464 case expr_none: 465 if (len > 3) { 466 strcpy (buf, "nil"); 467 return 3; 468 } 469 break; 470 471 case expr_match: 472 if (len > 7) { 473 strcpy (buf, "(match)"); 474 return 7; 475 } 476 break; 477 478 case expr_check: 479 rv = 10 + strlen (expr -> data.check -> name); 480 if (len > rv) { 481 sprintf (buf, "(check %s)", 482 expr -> data.check -> name); 483 return rv; 484 } 485 break; 486 487 case expr_equal: 488 if (len > 6) { 489 rv = 4; 490 strcpy (buf, "(eq "); 491 rv += print_subexpression (expr -> data.equal [0], 492 buf + rv, len - rv - 2); 493 buf [rv++] = ' '; 494 rv += print_subexpression (expr -> data.equal [1], 495 buf + rv, len - rv - 1); 496 buf [rv++] = ')'; 497 buf [rv] = 0; 498 return rv; 499 } 500 break; 501 502 case expr_not_equal: 503 if (len > 7) { 504 rv = 5; 505 strcpy (buf, "(neq "); 506 rv += print_subexpression (expr -> data.equal [0], 507 buf + rv, len - rv - 2); 508 buf [rv++] = ' '; 509 rv += print_subexpression (expr -> data.equal [1], 510 buf + rv, len - rv - 1); 511 buf [rv++] = ')'; 512 buf [rv] = 0; 513 return rv; 514 } 515 break; 516 517 case expr_substring: 518 if (len > 11) { 519 rv = 8; 520 strcpy (buf, "(substr "); 521 rv += print_subexpression (expr -> data.substring.expr, 522 buf + rv, len - rv - 3); 523 buf [rv++] = ' '; 524 rv += print_subexpression 525 (expr -> data.substring.offset, 526 buf + rv, len - rv - 2); 527 buf [rv++] = ' '; 528 rv += print_subexpression (expr -> data.substring.len, 529 buf + rv, len - rv - 1); 530 buf [rv++] = ')'; 531 buf [rv] = 0; 532 return rv; 533 } 534 break; 535 536 case expr_suffix: 537 if (len > 10) { 538 rv = 8; 539 strcpy (buf, "(suffix "); 540 rv += print_subexpression (expr -> data.suffix.expr, 541 buf + rv, len - rv - 2); 542 if (len > rv) 543 buf [rv++] = ' '; 544 rv += print_subexpression (expr -> data.suffix.len, 545 buf + rv, len - rv - 1); 546 if (len > rv) 547 buf [rv++] = ')'; 548 buf [rv] = 0; 549 return rv; 550 } 551 break; 552 553 case expr_concat: 554 if (len > 10) { 555 rv = 8; 556 strcpy (buf, "(concat "); 557 rv += print_subexpression (expr -> data.concat [0], 558 buf + rv, len - rv - 2); 559 buf [rv++] = ' '; 560 rv += print_subexpression (expr -> data.concat [1], 561 buf + rv, len - rv - 1); 562 buf [rv++] = ')'; 563 buf [rv] = 0; 564 return rv; 565 } 566 break; 567 568 case expr_pick_first_value: 569 if (len > 8) { 570 rv = 6; 571 strcpy (buf, "(pick1st "); 572 rv += print_subexpression 573 (expr -> data.pick_first_value.car, 574 buf + rv, len - rv - 2); 575 buf [rv++] = ' '; 576 rv += print_subexpression 577 (expr -> data.pick_first_value.cdr, 578 buf + rv, len - rv - 1); 579 buf [rv++] = ')'; 580 buf [rv] = 0; 581 return rv; 582 } 583 break; 584 585 case expr_host_lookup: 586 rv = 15 + strlen (expr -> data.host_lookup -> hostname); 587 if (len > rv) { 588 sprintf (buf, "(dns-lookup %s)", 589 expr -> data.host_lookup -> hostname); 590 return rv; 591 } 592 break; 593 594 case expr_and: 595 s = "and"; 596 binop: 597 rv = strlen (s); 598 if (len > rv + 4) { 599 buf [0] = '('; 600 strcpy (&buf [1], s); 601 rv += 1; 602 buf [rv++] = ' '; 603 rv += print_subexpression (expr -> data.and [0], 604 buf + rv, len - rv - 2); 605 buf [rv++] = ' '; 606 rv += print_subexpression (expr -> data.and [1], 607 buf + rv, len - rv - 1); 608 buf [rv++] = ')'; 609 buf [rv] = 0; 610 return rv; 611 } 612 break; 613 614 case expr_or: 615 s = "or"; 616 goto binop; 617 618 case expr_add: 619 s = "+"; 620 goto binop; 621 622 case expr_subtract: 623 s = "-"; 624 goto binop; 625 626 case expr_multiply: 627 s = "*"; 628 goto binop; 629 630 case expr_divide: 631 s = "/"; 632 goto binop; 633 634 case expr_remainder: 635 s = "%"; 636 goto binop; 637 638 case expr_binary_and: 639 s = "&"; 640 goto binop; 641 642 case expr_binary_or: 643 s = "|"; 644 goto binop; 645 646 case expr_binary_xor: 647 s = "^"; 648 goto binop; 649 650 case expr_not: 651 if (len > 6) { 652 rv = 5; 653 strcpy (buf, "(not "); 654 rv += print_subexpression (expr -> data.not, 655 buf + rv, len - rv - 1); 656 buf [rv++] = ')'; 657 buf [rv] = 0; 658 return rv; 659 } 660 break; 661 662 case expr_config_option: 663 s = "cfg-option"; 664 goto dooption; 665 666 case expr_option: 667 s = "option"; 668 dooption: 669 rv = strlen (s) + 2 + (strlen (expr -> data.option -> name) + 670 strlen (expr -> data.option -> universe -> name)); 671 if (len > rv) { 672 sprintf (buf, "(option %s.%s)", 673 expr -> data.option -> universe -> name, 674 expr -> data.option -> name); 675 return rv; 676 } 677 break; 678 679 case expr_hardware: 680 if (len > 10) { 681 strcpy (buf, "(hardware)"); 682 return 10; 683 } 684 break; 685 686 case expr_packet: 687 if (len > 10) { 688 rv = 8; 689 strcpy (buf, "(substr "); 690 rv += print_subexpression (expr -> data.packet.offset, 691 buf + rv, len - rv - 2); 692 buf [rv++] = ' '; 693 rv += print_subexpression (expr -> data.packet.len, 694 buf + rv, len - rv - 1); 695 buf [rv++] = ')'; 696 buf [rv] = 0; 697 return rv; 698 } 699 break; 700 701 case expr_const_data: 702 s = print_hex_1 (expr -> data.const_data.len, 703 expr -> data.const_data.data, len); 704 rv = strlen (s); 705 if (rv >= len) 706 rv = len - 1; 707 strncpy (buf, s, rv); 708 buf [rv] = 0; 709 return rv; 710 711 case expr_encapsulate: 712 rv = 13; 713 strcpy (buf, "(encapsulate "); 714 rv += expr -> data.encapsulate.len; 715 if (rv + 2 > len) 716 rv = len - 2; 717 strncpy (buf, 718 (const char *)expr -> data.encapsulate.data, rv - 13); 719 buf [rv++] = ')'; 720 buf [rv++] = 0; 721 break; 722 723 case expr_extract_int8: 724 if (len > 7) { 725 rv = 6; 726 strcpy (buf, "(int8 "); 727 rv += print_subexpression (expr -> data.extract_int, 728 buf + rv, len - rv - 1); 729 buf [rv++] = ')'; 730 buf [rv] = 0; 731 return rv; 732 } 733 break; 734 735 case expr_extract_int16: 736 if (len > 8) { 737 rv = 7; 738 strcpy (buf, "(int16 "); 739 rv += print_subexpression (expr -> data.extract_int, 740 buf + rv, len - rv - 1); 741 buf [rv++] = ')'; 742 buf [rv] = 0; 743 return rv; 744 } 745 break; 746 747 case expr_extract_int32: 748 if (len > 8) { 749 rv = 7; 750 strcpy (buf, "(int32 "); 751 rv += print_subexpression (expr -> data.extract_int, 752 buf + rv, len - rv - 1); 753 buf [rv++] = ')'; 754 buf [rv] = 0; 755 return rv; 756 } 757 break; 758 759 case expr_encode_int8: 760 if (len > 7) { 761 rv = 6; 762 strcpy (buf, "(to-int8 "); 763 rv += print_subexpression (expr -> data.encode_int, 764 buf + rv, len - rv - 1); 765 buf [rv++] = ')'; 766 buf [rv] = 0; 767 return rv; 768 } 769 break; 770 771 case expr_encode_int16: 772 if (len > 8) { 773 rv = 7; 774 strcpy (buf, "(to-int16 "); 775 rv += print_subexpression (expr -> data.encode_int, 776 buf + rv, len - rv - 1); 777 buf [rv++] = ')'; 778 buf [rv] = 0; 779 return rv; 780 } 781 break; 782 783 case expr_encode_int32: 784 if (len > 8) { 785 rv = 7; 786 strcpy (buf, "(to-int32 "); 787 rv += print_subexpression (expr -> data.encode_int, 788 buf + rv, len - rv - 1); 789 buf [rv++] = ')'; 790 buf [rv] = 0; 791 return rv; 792 } 793 break; 794 795 case expr_const_int: 796 s = print_dec_1 (expr -> data.const_int); 797 rv = strlen (s); 798 if (len > rv) { 799 strcpy (buf, s); 800 return rv; 801 } 802 break; 803 804 case expr_exists: 805 rv = 10 + (strlen (expr -> data.option -> name) + 806 strlen (expr -> data.option -> universe -> name)); 807 if (len > rv) { 808 sprintf (buf, "(exists %s.%s)", 809 expr -> data.option -> universe -> name, 810 expr -> data.option -> name); 811 return rv; 812 } 813 break; 814 815 case expr_variable_exists: 816 rv = 10 + strlen (expr -> data.variable); 817 if (len > rv) { 818 sprintf (buf, "(defined %s)", expr -> data.variable); 819 return rv; 820 } 821 break; 822 823 case expr_variable_reference: 824 rv = strlen (expr -> data.variable); 825 if (len > rv) { 826 sprintf (buf, "%s", expr -> data.variable); 827 return rv; 828 } 829 break; 830 831 case expr_known: 832 s = "known"; 833 astring: 834 rv = strlen (s); 835 if (len > rv) { 836 strcpy (buf, s); 837 return rv; 838 } 839 break; 840 841 case expr_leased_address: 842 s = "leased-address"; 843 goto astring; 844 845 case expr_client_state: 846 s = "client-state"; 847 goto astring; 848 849 case expr_host_decl_name: 850 s = "host-decl-name"; 851 goto astring; 852 853 case expr_lease_time: 854 s = "lease-time"; 855 goto astring; 856 857 case expr_static: 858 s = "static"; 859 goto astring; 860 861 case expr_filename: 862 s = "filename"; 863 goto astring; 864 865 case expr_sname: 866 s = "server-name"; 867 goto astring; 868 869 case expr_reverse: 870 if (len > 11) { 871 rv = 13; 872 strcpy (buf, "(reverse "); 873 rv += print_subexpression (expr -> data.reverse.width, 874 buf + rv, len - rv - 2); 875 buf [rv++] = ' '; 876 rv += print_subexpression (expr -> data.reverse.buffer, 877 buf + rv, len - rv - 1); 878 buf [rv++] = ')'; 879 buf [rv] = 0; 880 return rv; 881 } 882 break; 883 884 case expr_binary_to_ascii: 885 if (len > 5) { 886 rv = 9; 887 strcpy (buf, "(b2a "); 888 rv += print_subexpression (expr -> data.b2a.base, 889 buf + rv, len - rv - 4); 890 buf [rv++] = ' '; 891 rv += print_subexpression (expr -> data.b2a.width, 892 buf + rv, len - rv - 3); 893 buf [rv++] = ' '; 894 rv += print_subexpression (expr -> data.b2a.seperator, 895 buf + rv, len - rv - 2); 896 buf [rv++] = ' '; 897 rv += print_subexpression (expr -> data.b2a.buffer, 898 buf + rv, len - rv - 1); 899 buf [rv++] = ')'; 900 buf [rv] = 0; 901 return rv; 902 } 903 break; 904 905 case expr_dns_transaction: 906 rv = 10; 907 if (len < rv + 2) { 908 buf [0] = '('; 909 strcpy (&buf [1], "ns-update "); 910 while (len < rv + 2) { 911 rv += print_subexpression 912 (expr -> data.dns_transaction.car, 913 buf + rv, len - rv - 2); 914 buf [rv++] = ' '; 915 expr = expr -> data.dns_transaction.cdr; 916 } 917 buf [rv - 1] = ')'; 918 buf [rv] = 0; 919 return rv; 920 } 921 return 0; 922 923 case expr_ns_delete: 924 s = "delete"; 925 left = 4; 926 goto dodnsupd; 927 case expr_ns_exists: 928 s = "exists"; 929 left = 4; 930 goto dodnsupd; 931 case expr_ns_not_exists: 932 s = "not_exists"; 933 left = 4; 934 goto dodnsupd; 935 case expr_ns_add: 936 s = "update"; 937 left = 5; 938 dodnsupd: 939 rv = strlen (s); 940 if (len > strlen (s) + 1) { 941 buf [0] = '('; 942 strcpy (buf + 1, s); 943 rv++; 944 buf [rv++] = ' '; 945 s = print_dec_1 (expr -> data.ns_add.rrclass); 946 if (len > rv + strlen (s) + left) { 947 strcpy (&buf [rv], s); 948 rv += strlen (&buf [rv]); 949 } 950 buf [rv++] = ' '; 951 left--; 952 s = print_dec_1 (expr -> data.ns_add.rrtype); 953 if (len > rv + strlen (s) + left) { 954 strcpy (&buf [rv], s); 955 rv += strlen (&buf [rv]); 956 } 957 buf [rv++] = ' '; 958 left--; 959 rv += print_subexpression 960 (expr -> data.ns_add.rrname, 961 buf + rv, len - rv - left); 962 buf [rv++] = ' '; 963 left--; 964 rv += print_subexpression 965 (expr -> data.ns_add.rrdata, 966 buf + rv, len - rv - left); 967 buf [rv++] = ' '; 968 left--; 969 rv += print_subexpression 970 (expr -> data.ns_add.ttl, 971 buf + rv, len - rv - left); 972 buf [rv++] = ')'; 973 buf [rv] = 0; 974 return rv; 975 } 976 break; 977 978 case expr_null: 979 if (len > 6) { 980 strcpy (buf, "(null)"); 981 return 6; 982 } 983 break; 984 case expr_funcall: 985 rv = 12 + strlen (expr -> data.funcall.name); 986 if (len > rv + 1) { 987 strcpy (buf, "(funcall "); 988 strcpy (buf + 9, expr -> data.funcall.name); 989 buf [rv++] = ' '; 990 rv += print_subexpression 991 (expr -> data.funcall.arglist, buf + rv, 992 len - rv - 1); 993 buf [rv++] = ')'; 994 buf [rv] = 0; 995 return rv; 996 } 997 break; 998 999 case expr_arg: 1000 rv = print_subexpression (expr -> data.arg.val, buf, len); 1001 if (expr -> data.arg.next && rv + 2 < len) { 1002 buf [rv++] = ' '; 1003 rv += print_subexpression (expr -> data.arg.next, 1004 buf, len); 1005 if (rv + 1 < len) 1006 buf [rv++] = 0; 1007 return rv; 1008 } 1009 break; 1010 case expr_function: 1011 rv = 9; 1012 if (len > rv + 1) { 1013 struct string_list *foo; 1014 strcpy (buf, "(function"); 1015 for (foo = expr -> data.func -> args; 1016 foo; foo = foo -> next) { 1017 if (len > rv + 2 + strlen (foo -> string)) { 1018 buf [rv - 1] = ' '; 1019 strcpy (&buf [rv], foo -> string); 1020 rv += strlen (foo -> string); 1021 } 1022 } 1023 buf [rv] = ')'; 1024 buf [rv++] = 0; 1025 return rv; 1026 } 1027 } 1028 return 0; 1029} 1030 1031void print_expression (name, expr) 1032 const char *name; 1033 struct expression *expr; 1034{ 1035 char buf [1024]; 1036 1037 print_subexpression (expr, buf, sizeof buf); 1038 log_info ("%s: %s", name, buf); 1039} 1040 1041int token_print_indent_concat (FILE *file, int col, int indent, 1042 const char *prefix, 1043 const char *suffix, ...) 1044{ 1045 va_list list; 1046 unsigned len; 1047 char *s, *t, *u; 1048 1049 va_start (list, suffix); 1050 s = va_arg (list, char *); 1051 len = 0; 1052 while (s) { 1053 len += strlen (s); 1054 s = va_arg (list, char *); 1055 } 1056 va_end (list); 1057 1058 t = dmalloc (len + 1, MDL); 1059 if (!t) 1060 log_fatal ("token_print_indent: no memory for copy buffer"); 1061 1062 va_start (list, suffix); 1063 s = va_arg (list, char *); 1064 u = t; 1065 while (s) { 1066 len = strlen (s); 1067 strcpy (u, s); 1068 u += len; 1069 } 1070 va_end (list); 1071 1072 len = token_print_indent (file, col, indent, 1073 prefix, suffix, t); 1074 dfree (t, MDL); 1075 return col; 1076} 1077 1078int token_indent_data_string (FILE *file, int col, int indent, 1079 const char *prefix, const char *suffix, 1080 struct data_string *data) 1081{ 1082 int i; 1083 char obuf [3]; 1084 1085 /* See if this is just ASCII. */ 1086 for (i = 0; i < data -> len; i++) 1087 if (!isascii (data -> data [i]) || 1088 !isprint (data -> data [i])) 1089 break; 1090 1091 /* If we have a purely ASCII string, output it as text. */ 1092 if (i == data -> len) { 1093 char *buf = dmalloc (data -> len + 3, MDL); 1094 if (buf) { 1095 buf [0] = '"'; 1096 memcpy (buf + 1, data -> data, data -> len); 1097 buf [data -> len + 1] = '"'; 1098 buf [data -> len + 2] = 0; 1099 i = token_print_indent (file, col, indent, 1100 prefix, suffix, buf); 1101 dfree (buf, MDL); 1102 return i; 1103 } 1104 } 1105 1106 for (i = 0; i < data -> len; i++) { 1107 sprintf (obuf, "%2.2x", data -> data [i]); 1108 col = token_print_indent (file, col, indent, 1109 i == 0 ? prefix : "", 1110 (i + 1 == data -> len 1111 ? suffix 1112 : ""), obuf); 1113 if (i + 1 != data -> len) 1114 col = token_print_indent (file, col, indent, 1115 prefix, suffix, ":"); 1116 } 1117 return col; 1118} 1119 1120int token_print_indent (FILE *file, int col, int indent, 1121 const char *prefix, 1122 const char *suffix, const char *buf) 1123{ 1124 int len = strlen (buf) + strlen (prefix); 1125 if (col + len > 79) { 1126 if (indent + len < 79) { 1127 indent_spaces (file, indent); 1128 col = indent; 1129 } else { 1130 indent_spaces (file, col); 1131 col = len > 79 ? 0 : 79 - len - 1; 1132 } 1133 } else if (prefix && *prefix) { 1134 fputs (prefix, file); 1135 col += strlen (prefix); 1136 } 1137 fputs (buf, file); 1138 col += len; 1139 if (suffix && *suffix) { 1140 if (col + strlen (suffix) > 79) { 1141 indent_spaces (file, indent); 1142 col = indent; 1143 } else { 1144 fputs (suffix, file); 1145 col += strlen (suffix); 1146 } 1147 } 1148 return col; 1149} 1150 1151void indent_spaces (FILE *file, int indent) 1152{ 1153 int i; 1154 fputc ('\n', file); 1155 for (i = 0; i < indent; i++) 1156 fputc (' ', file); 1157} 1158 1159#if defined (NSUPDATE) 1160void print_dns_status (int status, ns_updque *uq) 1161{ 1162 char obuf [1024]; 1163 char *s = &obuf [0], *end = &obuf [1022]; 1164 ns_updrec *u; 1165 int position; 1166 int ttlp; 1167 const char *predicate = "if", *en, *op; 1168 int errorp; 1169 1170 for (u = ISC_LIST_HEAD (*uq); u; u = ISC_LIST_NEXT (u, r_link)) { 1171 ttlp = 0; 1172 1173 switch (u -> r_opcode) 1174 { 1175 case NXRRSET: 1176 op = "rrset doesn't exist"; 1177 position = 1; 1178 break; 1179 case YXRRSET: 1180 op = "rrset exists"; 1181 position = 1; 1182 break; 1183 case NXDOMAIN: 1184 op = "domain doesn't exist"; 1185 position = 1; 1186 break; 1187 case YXDOMAIN: 1188 op = "domain exists"; 1189 position = 1; 1190 break; 1191 case ADD: 1192 op = "add"; 1193 position = 0; 1194 ttlp = 1; 1195 break; 1196 case DELETE: 1197 op = "delete"; 1198 position = 0; 1199 break; 1200 default: 1201 op = "unknown"; 1202 position = 0; 1203 break; 1204 } 1205 if (!position) { 1206 if (s != &obuf [0] && s + 1 < end) 1207 *s++ = ' '; 1208 if (s + strlen (op) < end) { 1209 strcpy (s, op); 1210 s += strlen (s); 1211 } 1212 } else { 1213 if (s != &obuf [0] && s + 1 < end) 1214 *s++ = ' '; 1215 if (s + strlen (predicate) < end) { 1216 strcpy (s, predicate); 1217 s += strlen (s); 1218 } 1219 predicate = "and"; 1220 } 1221 if (u -> r_dname) { 1222 if (s + 1 < end) 1223 *s++ = ' '; 1224 if (s + strlen (u -> r_dname) < end) { 1225 strcpy (s, u -> r_dname); 1226 s += strlen (s); 1227 } 1228 } 1229 if (ttlp) { 1230 if (s + 1 < end) 1231 *s++ = ' '; 1232 /* 27 is as big as a ttl can get. */ 1233 if (s + 27 < end) { 1234 sprintf (s, "%lu", 1235 (unsigned long)(u -> r_ttl)); 1236 s += strlen (s); 1237 } 1238 } 1239 switch (u -> r_class) { 1240 case C_IN: 1241 en = "IN"; 1242 break; 1243 case C_CHAOS: 1244 en = "CHAOS"; 1245 break; 1246 case C_HS: 1247 en = "HS"; 1248 break; 1249 default: 1250 en = "UNKNOWN"; 1251 break; 1252 } 1253 if (s + strlen (en) < end) { 1254 if (s + 1 < end) 1255 *s++ = ' '; 1256 strcpy (s, en); 1257 s += strlen (en); 1258 } 1259 switch (u -> r_type) { 1260 case T_A: 1261 en = "A"; 1262 break; 1263 case T_PTR: 1264 en = "PTR"; 1265 break; 1266 case T_MX: 1267 en = "MX"; 1268 break; 1269 case T_TXT: 1270 en = "TXT"; 1271 break; 1272 case T_KEY: 1273 en = "KEY"; 1274 break; 1275 case T_CNAME: 1276 en = "CNAME"; 1277 break; 1278 default: 1279 en = "UNKNOWN"; 1280 break; 1281 } 1282 if (s + strlen (en) < end) { 1283 if (s + 1 < end) 1284 *s++ = ' '; 1285 strcpy (s, en); 1286 s += strlen (en); 1287 } 1288 if (u -> r_data) { 1289 if (s + 1 < end) 1290 *s++ = ' '; 1291 if (u -> r_type == T_TXT) { 1292 if (s + 1 < end) 1293 *s++ = '"'; 1294 } 1295 if(u->r_type == T_KEY) { 1296 strcat(s, "<keydata>"); 1297 s+=strlen("<keydata>"); 1298 } 1299 else { 1300 if (s + u -> r_size < end) { 1301 memcpy (s, u -> r_data, u -> r_size); 1302 s += u -> r_size; 1303 if (u -> r_type == T_TXT) { 1304 if (s + 1 < end) 1305 *s++ = '"'; 1306 } 1307 } 1308 } 1309 } 1310 if (position) { 1311 if (s + 1 < end) 1312 *s++ = ' '; 1313 if (s + strlen (op) < end) { 1314 strcpy (s, op); 1315 s += strlen (s); 1316 } 1317 } 1318 if (u == ISC_LIST_TAIL (*uq)) 1319 break; 1320 } 1321 if (s == &obuf [0]) { 1322 strcpy (s, "empty update"); 1323 s += strlen (s); 1324 } 1325 if (status == NOERROR) 1326 errorp = 0; 1327 else 1328 errorp = 1; 1329 en = isc_result_totext (status); 1330#if 0 1331 switch (status) { 1332 case -1: 1333 en = "resolver failed"; 1334 break; 1335 1336 case FORMERR: 1337 en = "format error"; 1338 break; 1339 1340 case NOERROR: 1341 en = "succeeded"; 1342 errorp = 0; 1343 break; 1344 1345 case NOTAUTH: 1346 en = "not authorized"; 1347 break; 1348 1349 case NOTIMP: 1350 en = "not implemented"; 1351 break; 1352 1353 case NOTZONE: 1354 en = "not a single valid zone"; 1355 break; 1356 1357 case NXDOMAIN: 1358 en = "no such domain"; 1359 break; 1360 1361 case NXRRSET: 1362 en = "no such record"; 1363 break; 1364 1365 case REFUSED: 1366 en = "refused"; 1367 break; 1368 1369 case SERVFAIL: 1370 en = "server failed"; 1371 break; 1372 1373 case YXDOMAIN: 1374 en = "domain exists"; 1375 break; 1376 1377 case YXRRSET: 1378 en = "record exists"; 1379 break; 1380 1381 default: 1382 en = "unknown error"; 1383 break; 1384 } 1385#endif 1386 1387 if (s + 2 < end) { 1388 *s++ = ':'; 1389 *s++ = ' '; 1390 } 1391 if (s + strlen (en) < end) { 1392 strcpy (s, en); 1393 s += strlen (en); 1394 } 1395 if (s + 1 < end) 1396 *s++ = '.'; 1397 *s++ = 0; 1398 if (errorp) 1399 log_error ("%s", obuf); 1400 else 1401 log_info ("%s", obuf); 1402} 1403#endif /* NSUPDATE */ 1404