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