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