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