1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 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 22 #ifndef lint 23 static const char copyright[] = 24 "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997\n\ 25 The Regents of the University of California. All rights reserved.\n"; 26 static const char rcsid[] = 27 "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.138.2.1 2000/01/11 07:34:00 fenner Exp $ (LBL)"; 28 #endif 29 30 /* $FreeBSD$ */ 31 32 /* 33 * tcpdump - monitor tcp/ip traffic on an ethernet. 34 * 35 * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. 36 * Mercilessly hacked and occasionally improved since then via the 37 * combined efforts of Van, Steve McCanne and Craig Leres of LBL. 38 */ 39 40 #ifdef HAVE_CONFIG_H 41 #include "config.h" 42 #endif 43 44 #include <sys/types.h> 45 #include <sys/time.h> 46 47 #include <netinet/in.h> 48 49 #include <pcap.h> 50 #include <signal.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <unistd.h> 55 #include <ctype.h> 56 57 #include <netinet/in_systm.h> 58 #include <netinet/ip.h> 59 60 #include "interface.h" 61 #include "addrtoname.h" 62 #include "machdep.h" 63 #include "setsignal.h" 64 #include "gmt2local.h" 65 66 int aflag; /* translate network and broadcast addresses */ 67 int dflag; /* print filter code */ 68 int eflag; /* print ethernet header */ 69 int fflag; /* don't translate "foreign" IP address */ 70 int nflag; /* leave addresses as numbers */ 71 int Nflag; /* remove domains from printed host names */ 72 int Oflag = 1; /* run filter code optimizer */ 73 int pflag; /* don't go promiscuous */ 74 int qflag; /* quick (shorter) output */ 75 int Rflag = 1; /* print sequence # field in AH/ESP*/ 76 int sflag = 0; /* use the libsmi to translate OIDs */ 77 int Sflag; /* print raw TCP sequence numbers */ 78 int tflag = 1; /* print packet arrival time */ 79 int vflag; /* verbose */ 80 int xflag; /* print packet in hex */ 81 int Xflag; /* print packet in ascii as well as hex */ 82 83 char *ahsecret = NULL; /* AH secret key */ 84 char *espsecret = NULL; /* ESP secret key */ 85 86 int packettype; 87 88 89 char *program_name; 90 91 int32_t thiszone; /* seconds offset from gmt to local time */ 92 93 /* Externs */ 94 extern void bpf_dump(struct bpf_program *, int); 95 96 /* Forwards */ 97 RETSIGTYPE cleanup(int); 98 extern __dead void usage(void) __attribute__((volatile)); 99 100 /* Length of saved portion of packet. */ 101 int snaplen = DEFAULT_SNAPLEN; 102 103 struct printer { 104 pcap_handler f; 105 int type; 106 }; 107 108 static struct printer printers[] = { 109 { ether_if_print, DLT_EN10MB }, 110 { token_if_print, DLT_IEEE802 }, 111 #ifdef DLT_LANE8023 112 { lane_if_print, DLT_LANE8023 }, 113 #endif 114 #ifdef DLT_CIP 115 { cip_if_print, DLT_CIP }, 116 #endif 117 { sl_if_print, DLT_SLIP }, 118 { sl_bsdos_if_print, DLT_SLIP_BSDOS }, 119 { ppp_if_print, DLT_PPP }, 120 { ppp_bsdos_if_print, DLT_PPP_BSDOS }, 121 { fddi_if_print, DLT_FDDI }, 122 { null_if_print, DLT_NULL }, 123 { raw_if_print, DLT_RAW }, 124 { atm_if_print, DLT_ATM_RFC1483 }, 125 #ifdef DLT_CHDLC 126 { chdlc_if_print, DLT_CHDLC }, 127 #endif 128 { NULL, 0 }, 129 }; 130 131 static pcap_handler 132 lookup_printer(int type) 133 { 134 struct printer *p; 135 136 for (p = printers; p->f; ++p) 137 if (type == p->type) 138 return p->f; 139 140 error("unknown data link type 0x%x", type); 141 /* NOTREACHED */ 142 } 143 144 static pcap_t *pd; 145 146 extern int optind; 147 extern int opterr; 148 extern char *optarg; 149 150 int 151 main(int argc, char **argv) 152 { 153 register int cnt, op, i; 154 bpf_u_int32 localnet, netmask; 155 register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName; 156 pcap_handler printer; 157 struct bpf_program fcode; 158 RETSIGTYPE (*oldhandler)(int); 159 u_char *pcap_userdata; 160 char ebuf[PCAP_ERRBUF_SIZE]; 161 162 cnt = -1; 163 device = NULL; 164 infile = NULL; 165 RFileName = NULL; 166 WFileName = NULL; 167 if ((cp = strrchr(argv[0], '/')) != NULL) 168 program_name = cp + 1; 169 else 170 program_name = argv[0]; 171 172 if (abort_on_misalignment(ebuf) < 0) 173 error("%s", ebuf); 174 175 #ifdef LIBSMI 176 smiInit("tcpdump"); 177 #endif 178 179 opterr = 0; 180 while ( 181 (op = getopt(argc, argv, "ac:deE:fF:i:lnNm:Opqr:Rs:StT:vw:xXY")) != EOF) 182 switch (op) { 183 184 case 'a': 185 ++aflag; 186 break; 187 188 #if 0 189 case 'A': 190 #ifndef CRYPTO 191 warning("crypto code not compiled in"); 192 #endif 193 ahsecret = optarg; 194 break; 195 #endif 196 197 case 'c': 198 cnt = atoi(optarg); 199 if (cnt <= 0) 200 error("invalid packet count %s", optarg); 201 break; 202 203 case 'd': 204 ++dflag; 205 break; 206 207 case 'e': 208 ++eflag; 209 break; 210 211 case 'E': 212 #ifndef CRYPTO 213 warning("crypto code not compiled in"); 214 #endif 215 espsecret = optarg; 216 break; 217 218 case 'f': 219 ++fflag; 220 break; 221 222 case 'F': 223 infile = optarg; 224 break; 225 226 case 'i': 227 device = optarg; 228 break; 229 230 case 'l': 231 #ifdef HAVE_SETLINEBUF 232 setlinebuf(stdout); 233 #else 234 setvbuf(stdout, NULL, _IOLBF, 0); 235 #endif 236 break; 237 238 case 'n': 239 ++nflag; 240 break; 241 242 case 'N': 243 ++Nflag; 244 break; 245 246 case 'm': 247 #ifdef LIBSMI 248 if (smiLoadModule(optarg) == 0) { 249 error("could not load MIB module %s", optarg); 250 } 251 sflag = 1; 252 #else 253 (void)fprintf(stderr, "%s: ignoring option `-m %s' ", 254 program_name, optarg); 255 (void)fprintf(stderr, "(no libsmi support)\n"); 256 #endif 257 258 case 'O': 259 Oflag = 0; 260 break; 261 262 case 'p': 263 ++pflag; 264 break; 265 266 case 'q': 267 ++qflag; 268 break; 269 270 case 'r': 271 RFileName = optarg; 272 break; 273 274 case 'R': 275 Rflag = 0; 276 break; 277 278 case 's': 279 snaplen = atoi(optarg); 280 if (snaplen <= 0) 281 error("invalid snaplen %s", optarg); 282 break; 283 284 case 'S': 285 ++Sflag; 286 break; 287 288 case 't': 289 --tflag; 290 break; 291 292 case 'T': 293 if (strcasecmp(optarg, "vat") == 0) 294 packettype = PT_VAT; 295 else if (strcasecmp(optarg, "wb") == 0) 296 packettype = PT_WB; 297 else if (strcasecmp(optarg, "rpc") == 0) 298 packettype = PT_RPC; 299 else if (strcasecmp(optarg, "rtp") == 0) 300 packettype = PT_RTP; 301 else if (strcasecmp(optarg, "rtcp") == 0) 302 packettype = PT_RTCP; 303 else if (strcasecmp(optarg, "snmp") == 0) 304 packettype = PT_SNMP; 305 else 306 error("unknown packet type `%s'", optarg); 307 break; 308 309 case 'v': 310 ++vflag; 311 break; 312 313 case 'w': 314 WFileName = optarg; 315 break; 316 317 case 'x': 318 ++xflag; 319 break; 320 321 case 'X': 322 ++xflag; 323 ++Xflag; 324 break; 325 326 #ifdef YYDEBUG 327 case 'Y': 328 { 329 /* Undocumented flag */ 330 extern int yydebug; 331 yydebug = 1; 332 } 333 break; 334 #endif 335 default: 336 usage(); 337 /* NOTREACHED */ 338 } 339 340 if (aflag && nflag) 341 error("-a and -n options are incompatible"); 342 343 if (tflag > 0) 344 thiszone = gmt2local(0); 345 346 if (RFileName != NULL) { 347 /* 348 * We don't need network access, so set it back to the user id. 349 * Also, this prevents the user from reading anyone's 350 * trace file. 351 */ 352 setuid(getuid()); 353 354 pd = pcap_open_offline(RFileName, ebuf); 355 if (pd == NULL) 356 error("%s", ebuf); 357 localnet = 0; 358 netmask = 0; 359 if (fflag != 0) 360 error("-f and -r options are incompatible"); 361 } else { 362 if (device == NULL) { 363 device = pcap_lookupdev(ebuf); 364 if (device == NULL) 365 error("%s", ebuf); 366 } 367 pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); 368 if (pd == NULL) 369 error("%s", ebuf); 370 i = pcap_snapshot(pd); 371 if (snaplen < i) { 372 warning("snaplen raised from %d to %d", snaplen, i); 373 snaplen = i; 374 } 375 if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 376 localnet = 0; 377 netmask = 0; 378 warning("%s", ebuf); 379 } 380 /* 381 * Let user own process after socket has been opened. 382 */ 383 setuid(getuid()); 384 } 385 if (infile) 386 cmdbuf = read_infile(infile); 387 else 388 cmdbuf = copy_argv(&argv[optind]); 389 390 if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 391 error("%s", pcap_geterr(pd)); 392 if (dflag) { 393 bpf_dump(&fcode, dflag); 394 exit(0); 395 } 396 init_addrtoname(localnet, netmask); 397 398 (void)setsignal(SIGTERM, cleanup); 399 (void)setsignal(SIGINT, cleanup); 400 /* Cooperate with nohup(1) */ 401 if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) 402 (void)setsignal(SIGHUP, oldhandler); 403 404 if (pcap_setfilter(pd, &fcode) < 0) 405 error("%s", pcap_geterr(pd)); 406 if (WFileName) { 407 pcap_dumper_t *p = pcap_dump_open(pd, WFileName); 408 if (p == NULL) 409 error("%s", pcap_geterr(pd)); 410 printer = pcap_dump; 411 pcap_userdata = (u_char *)p; 412 } else { 413 printer = lookup_printer(pcap_datalink(pd)); 414 pcap_userdata = 0; 415 } 416 if (RFileName == NULL) { 417 (void)fprintf(stderr, "%s: listening on %s\n", 418 program_name, device); 419 (void)fflush(stderr); 420 } 421 if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) { 422 (void)fprintf(stderr, "%s: pcap_loop: %s\n", 423 program_name, pcap_geterr(pd)); 424 exit(1); 425 } 426 pcap_close(pd); 427 exit(0); 428 } 429 430 /* make a clean exit on interrupts */ 431 RETSIGTYPE 432 cleanup(int signo) 433 { 434 struct pcap_stat stat; 435 436 /* Can't print the summary if reading from a savefile */ 437 if (pd != NULL && pcap_file(pd) == NULL) { 438 (void)fflush(stdout); 439 putc('\n', stderr); 440 if (pcap_stats(pd, &stat) < 0) 441 (void)fprintf(stderr, "pcap_stats: %s\n", 442 pcap_geterr(pd)); 443 else { 444 (void)fprintf(stderr, "%d packets received by filter\n", 445 stat.ps_recv); 446 (void)fprintf(stderr, "%d packets dropped by kernel\n", 447 stat.ps_drop); 448 } 449 } 450 exit(0); 451 } 452 453 /* dump the buffer in `emacs-hexl' style */ 454 void 455 default_print_hexl(const u_char *cp, unsigned int length, unsigned int offset) 456 { 457 unsigned int i, j, jm; 458 int c; 459 char ln[128]; 460 461 printf("\n"); 462 for (i = 0; i < length; i += 0x10) { 463 snprintf(ln, 464 sizeof(ln), 465 " %04x: ", (unsigned int)(i + offset)); 466 jm = length - i; 467 jm = jm > 16 ? 16 : jm; 468 469 for (j = 0; j < jm; j++) { 470 if ((j % 2) == 1) 471 snprintf(ln + strlen(ln), 472 sizeof(ln) - strlen(ln), 473 "%02x ", (unsigned int)cp[i+j]); 474 else 475 snprintf(ln + strlen(ln), 476 sizeof(ln) - strlen(ln), 477 "%02x", (unsigned int)cp[i+j]); 478 } 479 for (; j < 16; j++) { 480 if ((j % 2) == 1) 481 snprintf(ln + strlen(ln), 482 sizeof(ln) - strlen(ln), 483 " "); 484 else 485 snprintf(ln + strlen(ln), 486 sizeof(ln) - strlen(ln), 487 " "); 488 } 489 490 snprintf(ln + strlen(ln), sizeof(ln) - strlen(ln), " "); 491 for (j = 0; j < jm; j++) { 492 c = cp[i+j]; 493 c = isprint(c) ? c : '.'; 494 snprintf(ln + strlen(ln), 495 sizeof(ln) - strlen(ln), 496 "%c", c); 497 } 498 printf("%s\n", ln); 499 } 500 } 501 502 /* Like default_print() but data need not be aligned */ 503 void 504 default_print_unaligned(register const u_char *cp, register u_int length) 505 { 506 register u_int i, s; 507 register int nshorts; 508 509 if (Xflag) { 510 ascii_print(cp, length); 511 return; 512 } 513 nshorts = (u_int) length / sizeof(u_short); 514 i = 0; 515 while (--nshorts >= 0) { 516 if ((i++ % 8) == 0) 517 (void)printf("\n\t\t\t"); 518 s = *cp++; 519 (void)printf(" %02x%02x", s, *cp++); 520 } 521 if (length & 1) { 522 if ((i % 8) == 0) 523 (void)printf("\n\t\t\t"); 524 (void)printf(" %02x", *cp); 525 } 526 } 527 528 /* 529 * By default, print the packet out in hex. 530 */ 531 void 532 default_print(register const u_char *bp, register u_int length) 533 { 534 default_print_unaligned(bp, length); 535 } 536 537 __dead void 538 usage(void) 539 { 540 extern char version[]; 541 extern char pcap_version[]; 542 543 (void)fprintf(stderr, "%s version %s\n", program_name, version); 544 (void)fprintf(stderr, "libpcap version %s\n", pcap_version); 545 (void)fprintf(stderr, 546 "Usage: %s [-adeflnNOpqStvxX] [-c count] [ -F file ]\n", program_name); 547 (void)fprintf(stderr, 548 "\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n"); 549 (void)fprintf(stderr, 550 "\t\t[ -T type ] [ -w file ] [ expression ]\n"); 551 exit(-1); 552 } 553