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