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 #ifndef lint 26 static const char rcsid[] = 27 "@(#) $Header: /tcpdump/master/tcpdump/print-bootp.c,v 1.48 1999/11/21 09:36:49 fenner Exp $ (LBL)"; 28 #endif 29 30 #ifdef HAVE_CONFIG_H 31 #include "config.h" 32 #endif 33 34 #include <sys/param.h> 35 #include <sys/time.h> 36 #include <sys/socket.h> 37 38 #if __STDC__ 39 struct mbuf; 40 struct rtentry; 41 #endif 42 #include <net/if.h> 43 44 #include <netinet/in.h> 45 #include <net/ethernet.h> 46 47 #include <ctype.h> 48 #ifdef HAVE_MEMORY_H 49 #include <memory.h> 50 #endif 51 #include <stdio.h> 52 #include <string.h> 53 54 #include "interface.h" 55 #include "addrtoname.h" 56 #include "bootp.h" 57 58 static void rfc1048_print(const u_char *, u_int); 59 static void cmu_print(const u_char *, u_int); 60 61 static char tstr[] = " [|bootp]"; 62 63 /* 64 * Print bootp requests 65 */ 66 void 67 bootp_print(register const u_char *cp, u_int length, 68 u_short sport, u_short dport) 69 { 70 register const struct bootp *bp; 71 static u_char vm_cmu[4] = VM_CMU; 72 static u_char vm_rfc1048[4] = VM_RFC1048; 73 74 bp = (struct bootp *)cp; 75 TCHECK(bp->bp_op); 76 switch (bp->bp_op) { 77 78 case BOOTREQUEST: 79 /* Usually, a request goes from a client to a server */ 80 if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS) 81 printf(" (request)"); 82 break; 83 84 case BOOTREPLY: 85 /* Usually, a reply goes from a server to a client */ 86 if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC) 87 printf(" (reply)"); 88 break; 89 90 default: 91 printf(" bootp-#%d", bp->bp_op); 92 } 93 94 TCHECK(bp->bp_secs); 95 96 /* The usual hardware address type is 1 (10Mb Ethernet) */ 97 if (bp->bp_htype != 1) 98 printf(" htype-#%d", bp->bp_htype); 99 100 /* The usual length for 10Mb Ethernet address is 6 bytes */ 101 if (bp->bp_htype != 1 || bp->bp_hlen != 6) 102 printf(" hlen:%d", bp->bp_hlen); 103 104 /* Only print interesting fields */ 105 if (bp->bp_hops) 106 printf(" hops:%d", bp->bp_hops); 107 if (bp->bp_xid) 108 printf(" xid:0x%x", (u_int32_t)ntohl(bp->bp_xid)); 109 if (bp->bp_secs) 110 printf(" secs:%d", ntohs(bp->bp_secs)); 111 if (bp->bp_flags) 112 printf(" flags:0x%x", ntohs(bp->bp_flags)); 113 114 /* Client's ip address */ 115 TCHECK(bp->bp_ciaddr); 116 if (bp->bp_ciaddr.s_addr) 117 printf(" C:%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(" Y:%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(" S:%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(" G:%s", ipaddr_string(&bp->bp_giaddr)); 133 134 /* Client's Ethernet address */ 135 if (bp->bp_htype == 1 && bp->bp_hlen == 6) { 136 register const struct ether_header *eh; 137 register const char *e; 138 139 TCHECK2(bp->bp_chaddr[0], 6); 140 eh = (struct ether_header *)packetp; 141 if (bp->bp_op == BOOTREQUEST) 142 e = (const char *)ESRC(eh); 143 else if (bp->bp_op == BOOTREPLY) 144 e = (const char *)EDST(eh); 145 else 146 e = 0; 147 if (e == 0 || memcmp((char *)bp->bp_chaddr, e, 6) != 0) 148 printf(" ether %s", etheraddr_string(bp->bp_chaddr)); 149 } 150 151 TCHECK2(bp->bp_sname[0], 1); /* check first char only */ 152 if (*bp->bp_sname) { 153 printf(" sname \""); 154 if (fn_print(bp->bp_sname, snapend)) { 155 putchar('"'); 156 fputs(tstr + 1, stdout); 157 return; 158 } 159 putchar('"'); 160 } 161 TCHECK2(bp->bp_sname[0], 1); /* check first char only */ 162 if (*bp->bp_file) { 163 printf(" file \""); 164 if (fn_print(bp->bp_file, snapend)) { 165 putchar('"'); 166 fputs(tstr + 1, stdout); 167 return; 168 } 169 putchar('"'); 170 } 171 172 /* Decode the vendor buffer */ 173 TCHECK(bp->bp_vend[0]); 174 length -= sizeof(*bp) - sizeof(bp->bp_vend); 175 if (memcmp((char *)bp->bp_vend, (char *)vm_rfc1048, 176 sizeof(u_int32_t)) == 0) 177 rfc1048_print(bp->bp_vend, length); 178 else if (memcmp((char *)bp->bp_vend, (char *)vm_cmu, 179 sizeof(u_int32_t)) == 0) 180 cmu_print(bp->bp_vend, length); 181 else { 182 u_int32_t ul; 183 184 memcpy((char *)&ul, (char *)bp->bp_vend, sizeof(ul)); 185 if (ul != 0) 186 printf("vend-#0x%x", ul); 187 } 188 189 return; 190 trunc: 191 fputs(tstr, stdout); 192 } 193 194 /* The first character specifies the format to print */ 195 static struct tok tag2str[] = { 196 /* RFC1048 tags */ 197 { TAG_PAD, " PAD" }, 198 { TAG_SUBNET_MASK, "iSM" }, /* subnet mask (RFC950) */ 199 { TAG_TIME_OFFSET, "lTZ" }, /* seconds from UTC */ 200 { TAG_GATEWAY, "iDG" }, /* default gateway */ 201 { TAG_TIME_SERVER, "iTS" }, /* time servers (RFC868) */ 202 { TAG_NAME_SERVER, "iIEN" }, /* IEN name servers (IEN116) */ 203 { TAG_DOMAIN_SERVER, "iNS" }, /* domain name (RFC1035) */ 204 { TAG_LOG_SERVER, "iLOG" }, /* MIT log servers */ 205 { TAG_COOKIE_SERVER, "iCS" }, /* cookie servers (RFC865) */ 206 { TAG_LPR_SERVER, "iLPR" }, /* lpr server (RFC1179) */ 207 { TAG_IMPRESS_SERVER, "iIM" }, /* impress servers (Imagen) */ 208 { TAG_RLP_SERVER, "iRL" }, /* resource location (RFC887) */ 209 { TAG_HOSTNAME, "aHN" }, /* ascii hostname */ 210 { TAG_BOOTSIZE, "sBS" }, /* 512 byte blocks */ 211 { TAG_END, " END" }, 212 /* RFC1497 tags */ 213 { TAG_DUMPPATH, "aDP" }, 214 { TAG_DOMAINNAME, "aDN" }, 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, "lMA" }, 225 { TAG_MTU_TABLE, "sMT" }, 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, "BRD" }, 232 { TAG_RTR_SOL_ADDR, "iRSA" }, 233 { TAG_STATIC_ROUTE, "pSR" }, 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, "bVO" }, 244 { TAG_NETBIOS_NS, "iWNS" }, 245 { TAG_NETBIOS_DDS, "iWDD" }, 246 { TAG_NETBIOS_NODE, "bWNT" }, 247 { TAG_NETBIOS_SCOPE, "aWSC" }, 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, "iRQ" }, 262 { TAG_IP_LEASE, "lLT" }, 263 { TAG_OPT_OVERLOAD, "bOO" }, 264 { TAG_TFTP_SERVER, "aTFTP" }, 265 { TAG_BOOTFILENAME, "aBF" }, 266 { TAG_DHCP_MESSAGE, " DHCP" }, 267 { TAG_SERVER_ID, "iSID" }, 268 { TAG_PARM_REQUEST, "bPR" }, 269 { TAG_MESSAGE, "aMSG" }, 270 { TAG_MAX_MSG_SIZE, "sMSZ" }, 271 { TAG_RENEWAL_TIME, "lRN" }, 272 { TAG_REBIND_TIME, "lRB" }, 273 { TAG_VENDOR_CLASS, "bVC" }, 274 { TAG_CLIENT_ID, "bCID" }, 275 { 0, NULL } 276 }; 277 278 static void 279 rfc1048_print(register const u_char *bp, register u_int length) 280 { 281 register u_char tag; 282 register u_int len, size; 283 register const char *cp; 284 register char c; 285 int first; 286 u_int32_t ul; 287 u_short us; 288 289 printf(" vend-rfc1048"); 290 291 /* Step over magic cookie */ 292 bp += sizeof(int32_t); 293 294 /* Loop while we there is a tag left in the buffer */ 295 while (bp + 1 < snapend) { 296 tag = *bp++; 297 if (tag == TAG_PAD) 298 continue; 299 if (tag == TAG_END) 300 return; 301 cp = tok2str(tag2str, "?T%d", tag); 302 c = *cp++; 303 printf(" %s:", cp); 304 305 /* Get the length; check for truncation */ 306 if (bp + 1 >= snapend) { 307 fputs(tstr, stdout); 308 return; 309 } 310 len = *bp++; 311 if (bp + len >= snapend) { 312 fputs(tstr, stdout); 313 return; 314 } 315 316 if (tag == TAG_DHCP_MESSAGE && len == 1) { 317 c = *bp++; 318 switch (c) { 319 case DHCPDISCOVER: printf("DISCOVER"); break; 320 case DHCPOFFER: printf("OFFER"); break; 321 case DHCPREQUEST: printf("REQUEST"); break; 322 case DHCPDECLINE: printf("DECLINE"); break; 323 case DHCPACK: printf("ACK"); break; 324 case DHCPNAK: printf("NACK"); break; 325 case DHCPRELEASE: printf("RELEASE"); break; 326 case DHCPINFORM: printf("INFORM"); break; 327 default: printf("%u", c); break; 328 } 329 continue; 330 } 331 332 if (tag == TAG_PARM_REQUEST) { 333 first = 1; 334 while (len-- > 0) { 335 c = *bp++; 336 cp = tok2str(tag2str, "?%d", c); 337 if (!first) 338 putchar('+'); 339 printf("%s", cp + 1); 340 first = 0; 341 } 342 continue; 343 } 344 345 /* Print data */ 346 size = len; 347 if (c == '?') { 348 /* Base default formats for unknown tags on data size */ 349 if (size & 1) 350 c = 'b'; 351 else if (size & 2) 352 c = 's'; 353 else 354 c = 'l'; 355 } 356 first = 1; 357 switch (c) { 358 359 case 'a': 360 /* ascii strings */ 361 putchar('"'); 362 (void)fn_printn(bp, size, NULL); 363 putchar('"'); 364 bp += size; 365 size = 0; 366 break; 367 368 case 'i': 369 case 'l': 370 /* ip addresses/32-bit words */ 371 while (size >= sizeof(ul)) { 372 if (!first) 373 putchar(','); 374 memcpy((char *)&ul, (char *)bp, sizeof(ul)); 375 if (c == 'i') 376 printf("%s", ipaddr_string(&ul)); 377 else 378 printf("%u", ul); 379 bp += sizeof(ul); 380 size -= sizeof(ul); 381 first = 0; 382 } 383 break; 384 385 case 'p': 386 /* IP address pairs */ 387 while (size >= 2*sizeof(ul)) { 388 if (!first) 389 putchar(','); 390 memcpy((char *)&ul, (char *)bp, sizeof(ul)); 391 printf("(%s:", ipaddr_string(&ul)); 392 bp += sizeof(ul); 393 memcpy((char *)&ul, (char *)bp, sizeof(ul)); 394 printf("%s)", ipaddr_string(&ul)); 395 bp += sizeof(ul); 396 size -= 2*sizeof(ul); 397 first = 0; 398 } 399 break; 400 401 case 's': 402 /* shorts */ 403 while (size >= sizeof(us)) { 404 if (!first) 405 putchar(','); 406 memcpy((char *)&us, (char *)bp, sizeof(us)); 407 printf("%d", us); 408 bp += sizeof(us); 409 size -= sizeof(us); 410 first = 0; 411 } 412 break; 413 414 case 'B': 415 /* boolean */ 416 while (size > 0) { 417 if (!first) 418 putchar(','); 419 switch (*bp) { 420 case 0: 421 putchar('N'); 422 break; 423 case 1: 424 putchar('Y'); 425 break; 426 default: 427 printf("%d?", *bp); 428 break; 429 } 430 ++bp; 431 --size; 432 first = 0; 433 } 434 break; 435 436 case 'b': 437 default: 438 /* Bytes */ 439 while (size > 0) { 440 if (!first) 441 putchar('.'); 442 printf("%d", *bp); 443 ++bp; 444 --size; 445 first = 0; 446 } 447 break; 448 } 449 /* Data left over? */ 450 if (size) 451 printf("[len %d]", len); 452 } 453 } 454 455 static void 456 cmu_print(register const u_char *bp, register u_int length) 457 { 458 register const struct cmu_vend *cmu; 459 char *fmt = " %s:%s"; 460 461 #define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \ 462 if (cmu->m.s_addr != 0) \ 463 printf(fmt, s, ipaddr_string(&cmu->m.s_addr)); } 464 465 printf(" vend-cmu"); 466 cmu = (struct cmu_vend *)bp; 467 468 /* Only print if there are unknown bits */ 469 TCHECK(cmu->v_flags); 470 if ((cmu->v_flags & ~(VF_SMASK)) != 0) 471 printf(" F:0x%x", cmu->v_flags); 472 PRINTCMUADDR(v_dgate, "DG"); 473 PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*"); 474 PRINTCMUADDR(v_dns1, "NS1"); 475 PRINTCMUADDR(v_dns2, "NS2"); 476 PRINTCMUADDR(v_ins1, "IEN1"); 477 PRINTCMUADDR(v_ins2, "IEN2"); 478 PRINTCMUADDR(v_ts1, "TS1"); 479 PRINTCMUADDR(v_ts2, "TS2"); 480 return; 481 482 trunc: 483 fputs(tstr, stdout); 484 #undef PRINTCMUADDR 485 } 486