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