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