]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/tcpdump.c
This commit was generated by cvs2svn to compensate for changes in r97952,
[FreeBSD/FreeBSD.git] / contrib / 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.158 2000/12/21 10:43:24 guy Exp $ (LBL)";
28 #endif
29
30 /* $FreeBSD$ */
31
32 /*
33  * tcpdump - monitor tcp/ip traffic on an ethernet.
34  *
35  * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
36  * Mercilessly hacked and occasionally improved since then via the
37  * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
38  */
39
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43
44 #include <sys/types.h>
45 #include <sys/time.h>
46
47 #include <netinet/in.h>
48
49 #include <pcap.h>
50 #include <signal.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55 #include <ctype.h>
56
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 /* Forwards */
92 static RETSIGTYPE cleanup(int);
93 static void usage(void) __attribute__((noreturn));
94
95 /* Length of saved portion of packet. */
96 int snaplen = DEFAULT_SNAPLEN;
97
98 struct printer {
99         pcap_handler f;
100         int type;
101 };
102
103 static struct printer printers[] = {
104         { ether_if_print,       DLT_EN10MB },
105         { token_if_print,       DLT_IEEE802 },
106 #ifdef DLT_LANE8023
107         { lane_if_print,        DLT_LANE8023 },
108 #endif
109 #ifdef DLT_CIP
110         { cip_if_print,         DLT_CIP },
111 #endif
112 #ifdef DLT_ATM_CLIP
113         { cip_if_print,         DLT_ATM_CLIP },
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 #ifdef DLT_LOOP
122         { null_if_print,        DLT_LOOP },
123 #endif
124         { raw_if_print,         DLT_RAW },
125         { atm_if_print,         DLT_ATM_RFC1483 },
126 #ifdef DLT_C_HDLC
127         { chdlc_if_print,       DLT_C_HDLC },
128 #endif
129 #ifdef DLT_PPP_SERIAL
130         { ppp_hdlc_if_print,    DLT_PPP_SERIAL },
131 #endif
132 #ifdef DLT_LINUX_SLL
133         { sll_if_print,         DLT_LINUX_SLL },
134 #endif
135         { NULL,                 0 },
136 };
137
138 static pcap_handler
139 lookup_printer(int type)
140 {
141         struct printer *p;
142
143         for (p = printers; p->f; ++p)
144                 if (type == p->type)
145                         return p->f;
146
147         error("unknown data link type %d", type);
148         /* NOTREACHED */
149 }
150
151 static pcap_t *pd;
152
153 extern int optind;
154 extern int opterr;
155 extern char *optarg;
156
157 int
158 main(int argc, char **argv)
159 {
160         register int cnt, op, i;
161         bpf_u_int32 localnet, netmask;
162         register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName;
163         pcap_handler printer;
164         struct bpf_program fcode;
165         RETSIGTYPE (*oldhandler)(int);
166         u_char *pcap_userdata;
167         char ebuf[PCAP_ERRBUF_SIZE];
168
169         cnt = -1;
170         device = NULL;
171         infile = NULL;
172         RFileName = NULL;
173         WFileName = NULL;
174         if ((cp = strrchr(argv[0], '/')) != NULL)
175                 program_name = cp + 1;
176         else
177                 program_name = argv[0];
178
179         if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0)
180                 error("%s", ebuf);
181
182 #ifdef LIBSMI
183         smiInit("tcpdump");
184 #endif
185         
186         opterr = 0;
187         while (
188             (op = getopt(argc, argv, "ac:deE:fF:i:lm:nNOpqr:Rs:StT:uvw:xXY")) != -1)
189                 switch (op) {
190
191                 case 'a':
192                         ++aflag;
193                         break;
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                         char *end;
278
279                         snaplen = strtol(optarg, &end, 0);
280                         if (optarg == end || *end != '\0'
281                             || snaplen < 0 || snaplen > 65535)
282                                 error("invalid snaplen %s", optarg);
283                         else if (snaplen == 0)
284                                 snaplen = 65535;
285                         break;
286                 }
287
288                 case 'S':
289                         ++Sflag;
290                         break;
291
292                 case 't':
293                         --tflag;
294                         break;
295
296                 case 'T':
297                         if (strcasecmp(optarg, "vat") == 0)
298                                 packettype = PT_VAT;
299                         else if (strcasecmp(optarg, "wb") == 0)
300                                 packettype = PT_WB;
301                         else if (strcasecmp(optarg, "rpc") == 0)
302                                 packettype = PT_RPC;
303                         else if (strcasecmp(optarg, "rtp") == 0)
304                                 packettype = PT_RTP;
305                         else if (strcasecmp(optarg, "rtcp") == 0)
306                                 packettype = PT_RTCP;
307                         else if (strcasecmp(optarg, "snmp") == 0)
308                                 packettype = PT_SNMP;
309                         else if (strcasecmp(optarg, "cnfp") == 0)
310                                 packettype = PT_CNFP;
311                         else
312                                 error("unknown packet type `%s'", optarg);
313                         break;
314
315                 case 'u':
316                         ++uflag;
317                         break;
318                         
319                 case 'v':
320                         ++vflag;
321                         break;
322
323                 case 'w':
324                         WFileName = optarg;
325                         break;
326
327                 case 'x':
328                         ++xflag;
329                         break;
330
331                 case 'X':
332                         ++xflag;
333                         ++Xflag;
334                         break;
335
336 #ifdef YYDEBUG
337                 case 'Y':
338                         {
339                         /* Undocumented flag */
340                         extern int yydebug;
341                         yydebug = 1;
342                         }
343                         break;
344 #endif
345                 default:
346                         usage();
347                         /* NOTREACHED */
348                 }
349
350         if (aflag && nflag)
351                 error("-a and -n options are incompatible");
352
353         if (tflag > 0)
354                 thiszone = gmt2local(0);
355
356         if (RFileName != NULL) {
357                 /*
358                  * We don't need network access, so set it back to the user id.
359                  * Also, this prevents the user from reading anyone's
360                  * trace file.
361                  */
362                 setuid(getuid());
363
364                 pd = pcap_open_offline(RFileName, ebuf);
365                 if (pd == NULL)
366                         error("%s", ebuf);
367                 localnet = 0;
368                 netmask = 0;
369                 if (fflag != 0)
370                         error("-f and -r options are incompatible");
371         } else {
372                 if (device == NULL) {
373                         device = pcap_lookupdev(ebuf);
374                         if (device == NULL)
375                                 error("%s", ebuf);
376                 }
377                 pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf);
378                 if (pd == NULL)
379                         error("%s", ebuf);
380                 i = pcap_snapshot(pd);
381                 if (snaplen < i) {
382                         warning("snaplen raised from %d to %d", snaplen, i);
383                         snaplen = i;
384                 }
385                 if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
386                         localnet = 0;
387                         netmask = 0;
388                         warning("%s", ebuf);
389                 }
390                 /*
391                  * Let user own process after socket has been opened.
392                  */
393                 setuid(getuid());
394         }
395         if (infile)
396                 cmdbuf = read_infile(infile);
397         else
398                 cmdbuf = copy_argv(&argv[optind]);
399
400         if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
401                 error("%s", pcap_geterr(pd));
402         if (dflag) {
403                 bpf_dump(&fcode, dflag);
404                 exit(0);
405         }
406         init_addrtoname(localnet, netmask);
407
408         (void)setsignal(SIGTERM, cleanup);
409         (void)setsignal(SIGINT, cleanup);
410         /* Cooperate with nohup(1) */
411         if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
412                 (void)setsignal(SIGHUP, oldhandler);
413
414         if (pcap_setfilter(pd, &fcode) < 0)
415                 error("%s", pcap_geterr(pd));
416         if (WFileName) {
417                 pcap_dumper_t *p = pcap_dump_open(pd, WFileName);
418                 if (p == NULL)
419                         error("%s", pcap_geterr(pd));
420                 printer = pcap_dump;
421                 pcap_userdata = (u_char *)p;
422         } else {
423                 printer = lookup_printer(pcap_datalink(pd));
424                 pcap_userdata = 0;
425         }
426         if (RFileName == NULL) {
427                 (void)fprintf(stderr, "%s: listening on %s\n",
428                     program_name, device);
429                 (void)fflush(stderr);
430         }
431         if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) {
432                 (void)fprintf(stderr, "%s: pcap_loop: %s\n",
433                     program_name, pcap_geterr(pd));
434                 exit(1);
435         }
436         pcap_close(pd);
437         exit(0);
438 }
439
440 /* make a clean exit on interrupts */
441 static RETSIGTYPE
442 cleanup(int signo)
443 {
444         struct pcap_stat stat;
445
446         /* Can't print the summary if reading from a savefile */
447         if (pd != NULL && pcap_file(pd) == NULL) {
448                 (void)fflush(stdout);
449                 putc('\n', stderr);
450                 if (pcap_stats(pd, &stat) < 0)
451                         (void)fprintf(stderr, "pcap_stats: %s\n",
452                             pcap_geterr(pd));
453                 else {
454                         (void)fprintf(stderr, "%d packets received by filter\n",
455                             stat.ps_recv);
456                         (void)fprintf(stderr, "%d packets dropped by kernel\n",
457                             stat.ps_drop);
458                 }
459         }
460         exit(0);
461 }
462
463 /* Like default_print() but data need not be aligned */
464 void
465 default_print_unaligned(register const u_char *cp, register u_int length)
466 {
467         register u_int i, s;
468         register int nshorts;
469
470         if (Xflag) {
471                 ascii_print(cp, length);
472                 return;
473         }
474         nshorts = (u_int) length / sizeof(u_short);
475         i = 0;
476         while (--nshorts >= 0) {
477                 if ((i++ % 8) == 0)
478                         (void)printf("\n\t\t\t");
479                 s = *cp++;
480                 (void)printf(" %02x%02x", s, *cp++);
481         }
482         if (length & 1) {
483                 if ((i % 8) == 0)
484                         (void)printf("\n\t\t\t");
485                 (void)printf(" %02x", *cp);
486         }
487 }
488
489 /*
490  * By default, print the packet out in hex.
491  */
492 void
493 default_print(register const u_char *bp, register u_int length)
494 {
495         default_print_unaligned(bp, length);
496 }
497
498 static void
499 usage(void)
500 {
501         extern char version[];
502         extern char pcap_version[];
503
504         (void)fprintf(stderr, "%s version %s\n", program_name, version);
505         (void)fprintf(stderr, "libpcap version %s\n", pcap_version);
506         (void)fprintf(stderr,
507 "Usage: %s [-adeflnNOpqStuvxX] [-c count] [ -F file ]\n", program_name);
508         (void)fprintf(stderr,
509 "\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n");
510         (void)fprintf(stderr,
511 "\t\t[ -T type ] [ -w file ] [ expression ]\n");
512         exit(-1);
513 }