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