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