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