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