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