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