1/* 2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * Format and print bootp packets. 22 */ 23#include <sys/cdefs.h> 24#ifndef lint 25#if 0 26static const char rcsid[] _U_ = 27 "@(#) Header: /tcpdump/master/tcpdump/print-bootp.c,v 1.89 2008-04-22 09:45:08 hannes Exp (LBL)"; 28#else 29__RCSID("$NetBSD: print-bootp.c,v 1.2 2010/12/05 05:11:30 christos Exp $"); 30#endif 31#endif 32 33#ifdef HAVE_CONFIG_H 34#include "config.h" 35#endif 36 37#include <tcpdump-stdinc.h> 38 39#include <stdio.h> 40#include <string.h> 41 42#include "interface.h" 43#include "addrtoname.h" 44#include "extract.h" 45#include "ether.h" 46#include "bootp.h" 47 48static void rfc1048_print(const u_char *); 49static void cmu_print(const u_char *); 50static char *client_fqdn_flags(u_int flags); 51 52static char tstr[] = " [|bootp]"; 53 54static const struct tok bootp_flag_values[] = { 55 { 0x8000, "Broadcast" }, 56 { 0, NULL} 57}; 58 59static const struct tok bootp_op_values[] = { 60 { BOOTPREQUEST, "Request" }, 61 { BOOTPREPLY, "Reply" }, 62 { 0, NULL} 63}; 64 65/* 66 * Print bootp requests 67 */ 68void 69bootp_print(register const u_char *cp, u_int length) 70{ 71 register const struct bootp *bp; 72 static const u_char vm_cmu[4] = VM_CMU; 73 static const u_char vm_rfc1048[4] = VM_RFC1048; 74 75 bp = (const struct bootp *)cp; 76 TCHECK(bp->bp_op); 77 78 printf("BOOTP/DHCP, %s", 79 tok2str(bootp_op_values, "unknown (0x%02x)", bp->bp_op)); 80 81 if (bp->bp_htype == 1 && bp->bp_hlen == 6 && bp->bp_op == BOOTPREQUEST) { 82 TCHECK2(bp->bp_chaddr[0], 6); 83 printf(" from %s", etheraddr_string(bp->bp_chaddr)); 84 } 85 86 printf(", length %u", length); 87 88 if (!vflag) 89 return; 90 91 TCHECK(bp->bp_secs); 92 93 /* The usual hardware address type is 1 (10Mb Ethernet) */ 94 if (bp->bp_htype != 1) 95 printf(", htype %d", bp->bp_htype); 96 97 /* The usual length for 10Mb Ethernet address is 6 bytes */ 98 if (bp->bp_htype != 1 || bp->bp_hlen != 6) 99 printf(", hlen %d", bp->bp_hlen); 100 101 /* Only print interesting fields */ 102 if (bp->bp_hops) 103 printf(", hops %d", bp->bp_hops); 104 if (bp->bp_xid) 105 printf(", xid 0x%x", EXTRACT_32BITS(&bp->bp_xid)); 106 if (bp->bp_secs) 107 printf(", secs %d", EXTRACT_16BITS(&bp->bp_secs)); 108 109 printf(", Flags [%s]", 110 bittok2str(bootp_flag_values, "none", EXTRACT_16BITS(&bp->bp_flags))); 111 if (vflag > 1) 112 printf(" (0x%04x)", EXTRACT_16BITS(&bp->bp_flags)); 113 114 /* Client's ip address */ 115 TCHECK(bp->bp_ciaddr); 116 if (bp->bp_ciaddr.s_addr) 117 printf("\n\t Client-IP %s", ipaddr_string(&bp->bp_ciaddr)); 118 119 /* 'your' ip address (bootp client) */ 120 TCHECK(bp->bp_yiaddr); 121 if (bp->bp_yiaddr.s_addr) 122 printf("\n\t Your-IP %s", ipaddr_string(&bp->bp_yiaddr)); 123 124 /* Server's ip address */ 125 TCHECK(bp->bp_siaddr); 126 if (bp->bp_siaddr.s_addr) 127 printf("\n\t Server-IP %s", ipaddr_string(&bp->bp_siaddr)); 128 129 /* Gateway's ip address */ 130 TCHECK(bp->bp_giaddr); 131 if (bp->bp_giaddr.s_addr) 132 printf("\n\t Gateway-IP %s", ipaddr_string(&bp->bp_giaddr)); 133 134 /* Client's Ethernet address */ 135 if (bp->bp_htype == 1 && bp->bp_hlen == 6) { 136 TCHECK2(bp->bp_chaddr[0], 6); 137 printf("\n\t Client-Ethernet-Address %s", etheraddr_string(bp->bp_chaddr)); 138 } 139 140 TCHECK2(bp->bp_sname[0], 1); /* check first char only */ 141 if (*bp->bp_sname) { 142 printf("\n\t sname \""); 143 if (fn_print(bp->bp_sname, snapend)) { 144 putchar('"'); 145 fputs(tstr + 1, stdout); 146 return; 147 } 148 putchar('"'); 149 } 150 TCHECK2(bp->bp_file[0], 1); /* check first char only */ 151 if (*bp->bp_file) { 152 printf("\n\t file \""); 153 if (fn_print(bp->bp_file, snapend)) { 154 putchar('"'); 155 fputs(tstr + 1, stdout); 156 return; 157 } 158 putchar('"'); 159 } 160 161 /* Decode the vendor buffer */ 162 TCHECK(bp->bp_vend[0]); 163 if (memcmp((const char *)bp->bp_vend, vm_rfc1048, 164 sizeof(u_int32_t)) == 0) 165 rfc1048_print(bp->bp_vend); 166 else if (memcmp((const char *)bp->bp_vend, vm_cmu, 167 sizeof(u_int32_t)) == 0) 168 cmu_print(bp->bp_vend); 169 else { 170 u_int32_t ul; 171 172 ul = EXTRACT_32BITS(&bp->bp_vend); 173 if (ul != 0) 174 printf("\n\t Vendor-#0x%x", ul); 175 } 176 177 return; 178trunc: 179 fputs(tstr, stdout); 180} 181 182/* 183 * The first character specifies the format to print: 184 * i - ip address (32 bits) 185 * p - ip address pairs (32 bits + 32 bits) 186 * l - long (32 bits) 187 * L - unsigned long (32 bits) 188 * s - short (16 bits) 189 * b - period-seperated decimal bytes (variable length) 190 * x - colon-seperated hex bytes (variable length) 191 * a - ascii string (variable length) 192 * B - on/off (8 bits) 193 * $ - special (explicit code to handle) 194 */ 195static struct tok tag2str[] = { 196/* RFC1048 tags */ 197 { TAG_PAD, " PAD" }, 198 { TAG_SUBNET_MASK, "iSubnet-Mask" }, /* subnet mask (RFC950) */ 199 { TAG_TIME_OFFSET, "LTime-Zone" }, /* seconds from UTC */ 200 { TAG_GATEWAY, "iDefault-Gateway" }, /* default gateway */ 201 { TAG_TIME_SERVER, "iTime-Server" }, /* time servers (RFC868) */ 202 { TAG_NAME_SERVER, "iIEN-Name-Server" }, /* IEN name servers (IEN116) */ 203 { TAG_DOMAIN_SERVER, "iDomain-Name-Server" }, /* domain name (RFC1035) */ 204 { TAG_LOG_SERVER, "iLOG" }, /* MIT log servers */ 205 { TAG_COOKIE_SERVER, "iCS" }, /* cookie servers (RFC865) */ 206 { TAG_LPR_SERVER, "iLPR-Server" }, /* lpr server (RFC1179) */ 207 { TAG_IMPRESS_SERVER, "iIM" }, /* impress servers (Imagen) */ 208 { TAG_RLP_SERVER, "iRL" }, /* resource location (RFC887) */ 209 { TAG_HOSTNAME, "aHostname" }, /* ascii hostname */ 210 { TAG_BOOTSIZE, "sBS" }, /* 512 byte blocks */ 211 { TAG_END, " END" }, 212/* RFC1497 tags */ 213 { TAG_DUMPPATH, "aDP" }, 214 { TAG_DOMAINNAME, "aDomain-Name" }, 215 { TAG_SWAP_SERVER, "iSS" }, 216 { TAG_ROOTPATH, "aRP" }, 217 { TAG_EXTPATH, "aEP" }, 218/* RFC2132 tags */ 219 { TAG_IP_FORWARD, "BIPF" }, 220 { TAG_NL_SRCRT, "BSRT" }, 221 { TAG_PFILTERS, "pPF" }, 222 { TAG_REASS_SIZE, "sRSZ" }, 223 { TAG_DEF_TTL, "bTTL" }, 224 { TAG_MTU_TIMEOUT, "lMTU-Timeout" }, 225 { TAG_MTU_TABLE, "sMTU-Table" }, 226 { TAG_INT_MTU, "sMTU" }, 227 { TAG_LOCAL_SUBNETS, "BLSN" }, 228 { TAG_BROAD_ADDR, "iBR" }, 229 { TAG_DO_MASK_DISC, "BMD" }, 230 { TAG_SUPPLY_MASK, "BMS" }, 231 { TAG_DO_RDISC, "BRouter-Discovery" }, 232 { TAG_RTR_SOL_ADDR, "iRSA" }, 233 { TAG_STATIC_ROUTE, "pStatic-Route" }, 234 { TAG_USE_TRAILERS, "BUT" }, 235 { TAG_ARP_TIMEOUT, "lAT" }, 236 { TAG_ETH_ENCAP, "BIE" }, 237 { TAG_TCP_TTL, "bTT" }, 238 { TAG_TCP_KEEPALIVE, "lKI" }, 239 { TAG_KEEPALIVE_GO, "BKG" }, 240 { TAG_NIS_DOMAIN, "aYD" }, 241 { TAG_NIS_SERVERS, "iYS" }, 242 { TAG_NTP_SERVERS, "iNTP" }, 243 { TAG_VENDOR_OPTS, "bVendor-Option" }, 244 { TAG_NETBIOS_NS, "iNetbios-Name-Server" }, 245 { TAG_NETBIOS_DDS, "iWDD" }, 246 { TAG_NETBIOS_NODE, "$Netbios-Node" }, 247 { TAG_NETBIOS_SCOPE, "aNetbios-Scope" }, 248 { TAG_XWIN_FS, "iXFS" }, 249 { TAG_XWIN_DM, "iXDM" }, 250 { TAG_NIS_P_DOMAIN, "sN+D" }, 251 { TAG_NIS_P_SERVERS, "iN+S" }, 252 { TAG_MOBILE_HOME, "iMH" }, 253 { TAG_SMPT_SERVER, "iSMTP" }, 254 { TAG_POP3_SERVER, "iPOP3" }, 255 { TAG_NNTP_SERVER, "iNNTP" }, 256 { TAG_WWW_SERVER, "iWWW" }, 257 { TAG_FINGER_SERVER, "iFG" }, 258 { TAG_IRC_SERVER, "iIRC" }, 259 { TAG_STREETTALK_SRVR, "iSTS" }, 260 { TAG_STREETTALK_STDA, "iSTDA" }, 261 { TAG_REQUESTED_IP, "iRequested-IP" }, 262 { TAG_IP_LEASE, "lLease-Time" }, 263 { TAG_OPT_OVERLOAD, "$OO" }, 264 { TAG_TFTP_SERVER, "aTFTP" }, 265 { TAG_BOOTFILENAME, "aBF" }, 266 { TAG_DHCP_MESSAGE, " DHCP-Message" }, 267 { TAG_SERVER_ID, "iServer-ID" }, 268 { TAG_PARM_REQUEST, "bParameter-Request" }, 269 { TAG_MESSAGE, "aMSG" }, 270 { TAG_MAX_MSG_SIZE, "sMSZ" }, 271 { TAG_RENEWAL_TIME, "lRN" }, 272 { TAG_REBIND_TIME, "lRB" }, 273 { TAG_VENDOR_CLASS, "aVendor-Class" }, 274 { TAG_CLIENT_ID, "$Client-ID" }, 275/* RFC 2485 */ 276 { TAG_OPEN_GROUP_UAP, "aUAP" }, 277/* RFC 2563 */ 278 { TAG_DISABLE_AUTOCONF, "BNOAUTO" }, 279/* RFC 2610 */ 280 { TAG_SLP_DA, "bSLP-DA" }, /*"b" is a little wrong */ 281 { TAG_SLP_SCOPE, "bSLP-SCOPE" }, /*"b" is a little wrong */ 282/* RFC 2937 */ 283 { TAG_NS_SEARCH, "sNSSEARCH" }, /* XXX 's' */ 284/* RFC 3011 */ 285 { TAG_IP4_SUBNET_SELECT, "iSUBNET" }, 286/* RFC 3442 */ 287 { TAG_CLASSLESS_STATIC_RT, "$Classless-Static-Route" }, 288 { TAG_CLASSLESS_STA_RT_MS, "$Classless-Static-Route-Microsoft" }, 289/* http://www.iana.org/assignments/bootp-dhcp-extensions/index.htm */ 290 { TAG_USER_CLASS, "aCLASS" }, 291 { TAG_SLP_NAMING_AUTH, "aSLP-NA" }, 292 { TAG_CLIENT_FQDN, "$FQDN" }, 293 { TAG_AGENT_CIRCUIT, "$Agent-Information" }, 294 { TAG_AGENT_REMOTE, "bARMT" }, 295 { TAG_AGENT_MASK, "bAMSK" }, 296 { TAG_TZ_STRING, "aTZSTR" }, 297 { TAG_FQDN_OPTION, "bFQDNS" }, /* XXX 'b' */ 298 { TAG_AUTH, "bAUTH" }, /* XXX 'b' */ 299 { TAG_VINES_SERVERS, "iVINES" }, 300 { TAG_SERVER_RANK, "sRANK" }, 301 { TAG_CLIENT_ARCH, "sARCH" }, 302 { TAG_CLIENT_NDI, "bNDI" }, /* XXX 'b' */ 303 { TAG_CLIENT_GUID, "bGUID" }, /* XXX 'b' */ 304 { TAG_LDAP_URL, "aLDAP" }, 305 { TAG_6OVER4, "i6o4" }, 306 { TAG_PRINTER_NAME, "aPRTR" }, 307 { TAG_MDHCP_SERVER, "bMDHCP" }, /* XXX 'b' */ 308 { TAG_IPX_COMPAT, "bIPX" }, /* XXX 'b' */ 309 { TAG_NETINFO_PARENT, "iNI" }, 310 { TAG_NETINFO_PARENT_TAG, "aNITAG" }, 311 { TAG_URL, "aURL" }, 312 { TAG_FAILOVER, "bFAIL" }, /* XXX 'b' */ 313 { 0, NULL } 314}; 315/* 2-byte extended tags */ 316static struct tok xtag2str[] = { 317 { 0, NULL } 318}; 319 320/* DHCP "options overload" types */ 321static struct tok oo2str[] = { 322 { 1, "file" }, 323 { 2, "sname" }, 324 { 3, "file+sname" }, 325 { 0, NULL } 326}; 327 328/* NETBIOS over TCP/IP node type options */ 329static struct tok nbo2str[] = { 330 { 0x1, "b-node" }, 331 { 0x2, "p-node" }, 332 { 0x4, "m-node" }, 333 { 0x8, "h-node" }, 334 { 0, NULL } 335}; 336 337/* ARP Hardware types, for Client-ID option */ 338static struct tok arp2str[] = { 339 { 0x1, "ether" }, 340 { 0x6, "ieee802" }, 341 { 0x7, "arcnet" }, 342 { 0xf, "frelay" }, 343 { 0x17, "strip" }, 344 { 0x18, "ieee1394" }, 345 { 0, NULL } 346}; 347 348static struct tok dhcp_msg_values[] = { 349 { DHCPDISCOVER, "Discover" }, 350 { DHCPOFFER, "Offer" }, 351 { DHCPREQUEST, "Request" }, 352 { DHCPDECLINE, "Decline" }, 353 { DHCPACK, "ACK" }, 354 { DHCPNAK, "NACK" }, 355 { DHCPRELEASE, "Release" }, 356 { DHCPINFORM, "Inform" }, 357 { 0, NULL } 358}; 359 360#define AGENT_SUBOPTION_CIRCUIT_ID 1 /* RFC 3046 */ 361#define AGENT_SUBOPTION_REMOTE_ID 2 /* RFC 3046 */ 362#define AGENT_SUBOPTION_SUBSCRIBER_ID 6 /* RFC 3993 */ 363static struct tok agent_suboption_values[] = { 364 { AGENT_SUBOPTION_CIRCUIT_ID, "Circuit-ID" }, 365 { AGENT_SUBOPTION_REMOTE_ID, "Remote-ID" }, 366 { AGENT_SUBOPTION_SUBSCRIBER_ID, "Subscriber-ID" }, 367 { 0, NULL } 368}; 369 370 371static void 372rfc1048_print(register const u_char *bp) 373{ 374 register u_int16_t tag; 375 register u_int len; 376 register const char *cp; 377 register char c; 378 int first, idx; 379 u_int32_t ul; 380 u_int16_t us; 381 u_int8_t uc, subopt, suboptlen; 382 383 printf("\n\t Vendor-rfc1048 Extensions"); 384 385 /* Step over magic cookie */ 386 printf("\n\t Magic Cookie 0x%08x", EXTRACT_32BITS(bp)); 387 bp += sizeof(int32_t); 388 389 /* Loop while we there is a tag left in the buffer */ 390 while (TTEST2(*bp, 1)) { 391 tag = *bp++; 392 if (tag == TAG_PAD && vflag < 3) 393 continue; 394 if (tag == TAG_END && vflag < 3) 395 return; 396 if (tag == TAG_EXTENDED_OPTION) { 397 TCHECK2(*(bp + 1), 2); 398 tag = EXTRACT_16BITS(bp + 1); 399 /* XXX we don't know yet if the IANA will 400 * preclude overlap of 1-byte and 2-byte spaces. 401 * If not, we need to offset tag after this step. 402 */ 403 cp = tok2str(xtag2str, "?xT%u", tag); 404 } else 405 cp = tok2str(tag2str, "?T%u", tag); 406 c = *cp++; 407 408 if (tag == TAG_PAD || tag == TAG_END) 409 len = 0; 410 else { 411 /* Get the length; check for truncation */ 412 TCHECK2(*bp, 1); 413 len = *bp++; 414 } 415 416 printf("\n\t %s Option %u, length %u%s", cp, tag, len, 417 len > 0 ? ": " : ""); 418 419 if (tag == TAG_PAD && vflag > 2) { 420 u_int ntag = 1; 421 while (TTEST2(*bp, 1) && *bp == TAG_PAD) { 422 bp++; 423 ntag++; 424 } 425 if (ntag > 1) 426 printf(", occurs %u", ntag); 427 } 428 429 if (!TTEST2(*bp, len)) { 430 printf("[|rfc1048 %u]", len); 431 return; 432 } 433 434 if (tag == TAG_DHCP_MESSAGE && len == 1) { 435 uc = *bp++; 436 printf("%s", tok2str(dhcp_msg_values, "Unknown (%u)", uc)); 437 continue; 438 } 439 440 if (tag == TAG_PARM_REQUEST) { 441 idx = 0; 442 while (len-- > 0) { 443 uc = *bp++; 444 cp = tok2str(tag2str, "?Option %u", uc); 445 if (idx % 4 == 0) 446 printf("\n\t "); 447 else 448 printf(", "); 449 printf("%s", cp + 1); 450 idx++; 451 } 452 continue; 453 } 454 455 if (tag == TAG_EXTENDED_REQUEST) { 456 first = 1; 457 while (len > 1) { 458 len -= 2; 459 us = EXTRACT_16BITS(bp); 460 bp += 2; 461 cp = tok2str(xtag2str, "?xT%u", us); 462 if (!first) 463 putchar('+'); 464 printf("%s", cp + 1); 465 first = 0; 466 } 467 continue; 468 } 469 470 /* Print data */ 471 if (c == '?') { 472 /* Base default formats for unknown tags on data size */ 473 if (len & 1) 474 c = 'b'; 475 else if (len & 2) 476 c = 's'; 477 else 478 c = 'l'; 479 } 480 first = 1; 481 switch (c) { 482 483 case 'a': 484 /* ascii strings */ 485 putchar('"'); 486 if (fn_printn(bp, len, snapend)) { 487 putchar('"'); 488 goto trunc; 489 } 490 putchar('"'); 491 bp += len; 492 len = 0; 493 break; 494 495 case 'i': 496 case 'l': 497 case 'L': 498 /* ip addresses/32-bit words */ 499 while (len >= sizeof(ul)) { 500 if (!first) 501 putchar(','); 502 ul = EXTRACT_32BITS(bp); 503 if (c == 'i') { 504 ul = htonl(ul); 505 printf("%s", ipaddr_string(&ul)); 506 } else if (c == 'L') 507 printf("%d", ul); 508 else 509 printf("%u", ul); 510 bp += sizeof(ul); 511 len -= sizeof(ul); 512 first = 0; 513 } 514 break; 515 516 case 'p': 517 /* IP address pairs */ 518 while (len >= 2*sizeof(ul)) { 519 if (!first) 520 putchar(','); 521 memcpy((char *)&ul, (const char *)bp, sizeof(ul)); 522 printf("(%s:", ipaddr_string(&ul)); 523 bp += sizeof(ul); 524 memcpy((char *)&ul, (const char *)bp, sizeof(ul)); 525 printf("%s)", ipaddr_string(&ul)); 526 bp += sizeof(ul); 527 len -= 2*sizeof(ul); 528 first = 0; 529 } 530 break; 531 532 case 's': 533 /* shorts */ 534 while (len >= sizeof(us)) { 535 if (!first) 536 putchar(','); 537 us = EXTRACT_16BITS(bp); 538 printf("%u", us); 539 bp += sizeof(us); 540 len -= sizeof(us); 541 first = 0; 542 } 543 break; 544 545 case 'B': 546 /* boolean */ 547 while (len > 0) { 548 if (!first) 549 putchar(','); 550 switch (*bp) { 551 case 0: 552 putchar('N'); 553 break; 554 case 1: 555 putchar('Y'); 556 break; 557 default: 558 printf("%u?", *bp); 559 break; 560 } 561 ++bp; 562 --len; 563 first = 0; 564 } 565 break; 566 567 case 'b': 568 case 'x': 569 default: 570 /* Bytes */ 571 while (len > 0) { 572 if (!first) 573 putchar(c == 'x' ? ':' : '.'); 574 if (c == 'x') 575 printf("%02x", *bp); 576 else 577 printf("%u", *bp); 578 ++bp; 579 --len; 580 first = 0; 581 } 582 break; 583 584 case '$': 585 /* Guys we can't handle with one of the usual cases */ 586 switch (tag) { 587 588 case TAG_NETBIOS_NODE: 589 /* this option should be at least 1 byte long */ 590 if (len < 1) { 591 printf("ERROR: option %u len %u < 1 bytes", 592 TAG_NETBIOS_NODE, len); 593 break; 594 } 595 tag = *bp++; 596 --len; 597 fputs(tok2str(nbo2str, NULL, tag), stdout); 598 break; 599 600 case TAG_OPT_OVERLOAD: 601 /* this option should be at least 1 byte long */ 602 if (len < 1) { 603 printf("ERROR: option %u len %u < 1 bytes", 604 TAG_OPT_OVERLOAD, len); 605 break; 606 } 607 tag = *bp++; 608 --len; 609 fputs(tok2str(oo2str, NULL, tag), stdout); 610 break; 611 612 case TAG_CLIENT_FQDN: 613 /* this option should be at least 3 bytes long */ 614 if (len < 3) { 615 printf("ERROR: option %u len %u < 3 bytes", 616 TAG_CLIENT_FQDN, len); 617 bp += len; 618 len = 0; 619 break; 620 } 621 if (*bp) 622 printf("[%s] ", client_fqdn_flags(*bp)); 623 bp++; 624 if (*bp || *(bp+1)) 625 printf("%u/%u ", *bp, *(bp+1)); 626 bp += 2; 627 putchar('"'); 628 if (fn_printn(bp, len - 3, snapend)) { 629 putchar('"'); 630 goto trunc; 631 } 632 putchar('"'); 633 bp += len - 3; 634 len = 0; 635 break; 636 637 case TAG_CLIENT_ID: 638 { int type; 639 640 /* this option should be at least 1 byte long */ 641 if (len < 1) { 642 printf("ERROR: option %u len %u < 1 bytes", 643 TAG_CLIENT_ID, len); 644 break; 645 } 646 type = *bp++; 647 len--; 648 if (type == 0) { 649 putchar('"'); 650 if (fn_printn(bp, len, snapend)) { 651 putchar('"'); 652 goto trunc; 653 } 654 putchar('"'); 655 bp += len; 656 len = 0; 657 break; 658 } else { 659 printf("%s ", tok2str(arp2str, "hardware-type %u,", type)); 660 while (len > 0) { 661 if (!first) 662 putchar(':'); 663 printf("%02x", *bp); 664 ++bp; 665 --len; 666 first = 0; 667 } 668 } 669 break; 670 } 671 672 case TAG_AGENT_CIRCUIT: 673 while (len >= 2) { 674 subopt = *bp++; 675 suboptlen = *bp++; 676 len -= 2; 677 if (suboptlen > len) { 678 printf("\n\t %s SubOption %u, length %u: length goes past end of option", 679 tok2str(agent_suboption_values, "Unknown", subopt), 680 subopt, 681 suboptlen); 682 bp += len; 683 len = 0; 684 break; 685 } 686 printf("\n\t %s SubOption %u, length %u: ", 687 tok2str(agent_suboption_values, "Unknown", subopt), 688 subopt, 689 suboptlen); 690 switch (subopt) { 691 692 case AGENT_SUBOPTION_CIRCUIT_ID: /* fall through */ 693 case AGENT_SUBOPTION_REMOTE_ID: 694 case AGENT_SUBOPTION_SUBSCRIBER_ID: 695 fn_printn(bp, suboptlen, NULL); 696 break; 697 698 default: 699 print_unknown_data(bp, "\n\t\t", suboptlen); 700 } 701 702 len -= suboptlen; 703 bp += suboptlen; 704 } 705 break; 706 707 case TAG_CLASSLESS_STATIC_RT: 708 case TAG_CLASSLESS_STA_RT_MS: 709 { 710 u_int mask_width, significant_octets, i; 711 712 /* this option should be at least 5 bytes long */ 713 if (len < 5) { 714 printf("ERROR: option %u len %u < 5 bytes", 715 TAG_CLASSLESS_STATIC_RT, len); 716 bp += len; 717 len = 0; 718 break; 719 } 720 while (len > 0) { 721 if (!first) 722 putchar(','); 723 mask_width = *bp++; 724 len--; 725 /* mask_width <= 32 */ 726 if (mask_width > 32) { 727 printf("[ERROR: Mask width (%d) > 32]", mask_width); 728 bp += len; 729 len = 0; 730 break; 731 } 732 significant_octets = (mask_width + 7) / 8; 733 /* significant octets + router(4) */ 734 if (len < significant_octets + 4) { 735 printf("[ERROR: Remaining length (%u) < %u bytes]", len, significant_octets + 4); 736 bp += len; 737 len = 0; 738 break; 739 } 740 putchar('('); 741 if (mask_width == 0) 742 printf("default"); 743 else { 744 for (i = 0; i < significant_octets ; i++) { 745 if (i > 0) 746 putchar('.'); 747 printf("%d", *bp++); 748 } 749 for (i = significant_octets ; i < 4 ; i++) 750 printf(".0"); 751 printf("/%d", mask_width); 752 } 753 memcpy((char *)&ul, (const char *)bp, sizeof(ul)); 754 printf(":%s)", ipaddr_string(&ul)); 755 bp += sizeof(ul); 756 len -= (significant_octets + 4); 757 first = 0; 758 } 759 } 760 break; 761 762 default: 763 printf("[unknown special tag %u, size %u]", 764 tag, len); 765 bp += len; 766 len = 0; 767 break; 768 } 769 break; 770 } 771 /* Data left over? */ 772 if (len) { 773 printf("\n\t trailing data length %u", len); 774 bp += len; 775 } 776 } 777 return; 778trunc: 779 printf("|[rfc1048]"); 780} 781 782static void 783cmu_print(register const u_char *bp) 784{ 785 register const struct cmu_vend *cmu; 786 787#define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \ 788 if (cmu->m.s_addr != 0) \ 789 printf(" %s:%s", s, ipaddr_string(&cmu->m.s_addr)); } 790 791 printf(" vend-cmu"); 792 cmu = (const struct cmu_vend *)bp; 793 794 /* Only print if there are unknown bits */ 795 TCHECK(cmu->v_flags); 796 if ((cmu->v_flags & ~(VF_SMASK)) != 0) 797 printf(" F:0x%x", cmu->v_flags); 798 PRINTCMUADDR(v_dgate, "DG"); 799 PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*"); 800 PRINTCMUADDR(v_dns1, "NS1"); 801 PRINTCMUADDR(v_dns2, "NS2"); 802 PRINTCMUADDR(v_ins1, "IEN1"); 803 PRINTCMUADDR(v_ins2, "IEN2"); 804 PRINTCMUADDR(v_ts1, "TS1"); 805 PRINTCMUADDR(v_ts2, "TS2"); 806 return; 807 808trunc: 809 fputs(tstr, stdout); 810#undef PRINTCMUADDR 811} 812 813static char * 814client_fqdn_flags(u_int flags) 815{ 816 static char buf[8+1]; 817 int i = 0; 818 819 if (flags & CLIENT_FQDN_FLAGS_S) 820 buf[i++] = 'S'; 821 if (flags & CLIENT_FQDN_FLAGS_O) 822 buf[i++] = 'O'; 823 if (flags & CLIENT_FQDN_FLAGS_E) 824 buf[i++] = 'E'; 825 if (flags & CLIENT_FQDN_FLAGS_N) 826 buf[i++] = 'N'; 827 buf[i] = '\0'; 828 829 return buf; 830} 831