]> The Tcpdump Group git mirrors - tcpdump/blob - tcpdump.c
print pppOE. From <[email protected]>
[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.134 1999-11-21 03:50:26 assar 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 #include <sys/types.h>
39 #include <sys/time.h>
40
41 #include <netinet/in.h>
42
43 #include <pcap.h>
44 #include <signal.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49
50 #include <netinet/in_systm.h>
51 #include <netinet/ip.h>
52
53 #include "interface.h"
54 #include "addrtoname.h"
55 #include "machdep.h"
56 #include "setsignal.h"
57 #include "gmt2local.h"
58
59 int aflag; /* translate network and broadcast addresses */
60 int dflag; /* print filter code */
61 int eflag; /* print ethernet header */
62 int fflag; /* don't translate "foreign" IP address */
63 int nflag; /* leave addresses as numbers */
64 int Nflag; /* remove domains from printed host names */
65 int Oflag = 1; /* run filter code optimizer */
66 int pflag; /* don't go promiscuous */
67 int qflag; /* quick (shorter) output */
68 int Rflag = 1; /* print sequence # field in AH/ESP*/
69 int Sflag; /* print raw TCP sequence numbers */
70 int tflag = 1; /* print packet arrival time */
71 int vflag; /* verbose */
72 int xflag; /* print packet in hex */
73
74 char *ahsecret = NULL; /* AH secret key */
75 char *espsecret = NULL; /* ESP secret key */
76
77 int packettype;
78
79
80 char *program_name;
81
82 int32_t thiszone; /* seconds offset from gmt to local time */
83
84 /* Externs */
85 extern void bpf_dump(struct bpf_program *, int);
86
87 /* Forwards */
88 RETSIGTYPE cleanup(int);
89 extern __dead void usage(void) __attribute__((volatile));
90
91 /* Length of saved portion of packet. */
92 int snaplen = DEFAULT_SNAPLEN;
93
94 struct printer {
95 pcap_handler f;
96 int type;
97 };
98
99 static struct printer printers[] = {
100 { ether_if_print, DLT_EN10MB },
101 { ether_if_print, DLT_IEEE802 },
102 #ifdef DLT_LANE8023
103 { lane_if_print, DLT_LANE8023 },
104 #endif
105 #ifdef DLT_CIP
106 { cip_if_print, DLT_CIP },
107 #endif
108 { sl_if_print, DLT_SLIP },
109 { sl_bsdos_if_print, DLT_SLIP_BSDOS },
110 { ppp_if_print, DLT_PPP },
111 { ppp_bsdos_if_print, DLT_PPP_BSDOS },
112 { fddi_if_print, DLT_FDDI },
113 { null_if_print, DLT_NULL },
114 { raw_if_print, DLT_RAW },
115 { atm_if_print, DLT_ATM_RFC1483 },
116 #ifdef DLT_CHDLC
117 { chdlc_if_print, DLT_CHDLC },
118 #endif
119 { NULL, 0 },
120 };
121
122 static pcap_handler
123 lookup_printer(int type)
124 {
125 struct printer *p;
126
127 for (p = printers; p->f; ++p)
128 if (type == p->type)
129 return p->f;
130
131 error("unknown data link type 0x%x", type);
132 /* NOTREACHED */
133 }
134
135 static pcap_t *pd;
136
137 extern int optind;
138 extern int opterr;
139 extern char *optarg;
140
141 int
142 main(int argc, char **argv)
143 {
144 register int cnt, op, i;
145 bpf_u_int32 localnet, netmask;
146 register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName;
147 pcap_handler printer;
148 struct bpf_program fcode;
149 RETSIGTYPE (*oldhandler)(int);
150 u_char *pcap_userdata;
151 char ebuf[PCAP_ERRBUF_SIZE];
152
153 cnt = -1;
154 device = NULL;
155 infile = NULL;
156 RFileName = NULL;
157 WFileName = NULL;
158 if ((cp = strrchr(argv[0], '/')) != NULL)
159 program_name = cp + 1;
160 else
161 program_name = argv[0];
162
163 if (abort_on_misalignment(ebuf) < 0)
164 error("%s", ebuf);
165
166 opterr = 0;
167 while (
168 (op = getopt(argc, argv, "ac:deE:fF:i:lnNOpqr:Rs:StT:vw:xY")) != EOF)
169 switch (op) {
170
171 case 'a':
172 ++aflag;
173 break;
174
175 #if 0
176 case 'A':
177 #ifndef CRYPTO
178 warning("crypto code not compiled in");
179 #endif
180 ahsecret = optarg;
181 break;
182 #endif
183
184 case 'c':
185 cnt = atoi(optarg);
186 if (cnt <= 0)
187 error("invalid packet count %s", optarg);
188 break;
189
190 case 'd':
191 ++dflag;
192 break;
193
194 case 'e':
195 ++eflag;
196 break;
197
198 case 'E':
199 #ifndef CRYPTO
200 warning("crypto code not compiled in");
201 #endif
202 espsecret = optarg;
203 break;
204
205 case 'f':
206 ++fflag;
207 break;
208
209 case 'F':
210 infile = optarg;
211 break;
212
213 case 'i':
214 device = optarg;
215 break;
216
217 case 'l':
218 #ifdef HAVE_SETLINEBUF
219 setlinebuf(stdout);
220 #else
221 setvbuf(stdout, NULL, _IOLBF, 0);
222 #endif
223 break;
224
225 case 'n':
226 ++nflag;
227 break;
228
229 case 'N':
230 ++Nflag;
231 break;
232
233 case 'O':
234 Oflag = 0;
235 break;
236
237 case 'p':
238 ++pflag;
239 break;
240
241 case 'q':
242 ++qflag;
243 break;
244
245 case 'r':
246 RFileName = optarg;
247 break;
248
249 case 'R':
250 Rflag = 0;
251 break;
252
253 case 's':
254 snaplen = atoi(optarg);
255 if (snaplen <= 0)
256 error("invalid snaplen %s", optarg);
257 break;
258
259 case 'S':
260 ++Sflag;
261 break;
262
263 case 't':
264 --tflag;
265 break;
266
267 case 'T':
268 if (strcasecmp(optarg, "vat") == 0)
269 packettype = PT_VAT;
270 else if (strcasecmp(optarg, "wb") == 0)
271 packettype = PT_WB;
272 else if (strcasecmp(optarg, "rpc") == 0)
273 packettype = PT_RPC;
274 else if (strcasecmp(optarg, "rtp") == 0)
275 packettype = PT_RTP;
276 else if (strcasecmp(optarg, "rtcp") == 0)
277 packettype = PT_RTCP;
278 else if (strcasecmp(optarg, "snmp") == 0)
279 packettype = PT_SNMP;
280 else
281 error("unknown packet type `%s'", optarg);
282 break;
283
284 case 'v':
285 ++vflag;
286 break;
287
288 case 'w':
289 WFileName = optarg;
290 break;
291 #ifdef YYDEBUG
292 case 'Y':
293 {
294 /* Undocumented flag */
295 extern int yydebug;
296 yydebug = 1;
297 }
298 break;
299 #endif
300 case 'x':
301 ++xflag;
302 break;
303
304 default:
305 usage();
306 /* NOTREACHED */
307 }
308
309 if (aflag && nflag)
310 error("-a and -n options are incompatible");
311
312 if (tflag > 0)
313 thiszone = gmt2local(0);
314
315 if (RFileName != NULL) {
316 /*
317 * We don't need network access, so set it back to the user id.
318 * Also, this prevents the user from reading anyone's
319 * trace file.
320 */
321 setuid(getuid());
322
323 pd = pcap_open_offline(RFileName, ebuf);
324 if (pd == NULL)
325 error("%s", ebuf);
326 localnet = 0;
327 netmask = 0;
328 if (fflag != 0)
329 error("-f and -r options are incompatible");
330 } else {
331 if (device == NULL) {
332 device = pcap_lookupdev(ebuf);
333 if (device == NULL)
334 error("%s", ebuf);
335 }
336 pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf);
337 if (pd == NULL)
338 error("%s", ebuf);
339 i = pcap_snapshot(pd);
340 if (snaplen < i) {
341 warning("snaplen raised from %d to %d", snaplen, i);
342 snaplen = i;
343 }
344 if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
345 localnet = 0;
346 netmask = 0;
347 warning("%s", ebuf);
348 }
349 /*
350 * Let user own process after socket has been opened.
351 */
352 setuid(getuid());
353 }
354 if (infile)
355 cmdbuf = read_infile(infile);
356 else
357 cmdbuf = copy_argv(&argv[optind]);
358
359 if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
360 error("%s", pcap_geterr(pd));
361 if (dflag) {
362 bpf_dump(&fcode, dflag);
363 exit(0);
364 }
365 init_addrtoname(localnet, netmask);
366
367 (void)setsignal(SIGTERM, cleanup);
368 (void)setsignal(SIGINT, cleanup);
369 /* Cooperate with nohup(1) */
370 if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
371 (void)setsignal(SIGHUP, oldhandler);
372
373 if (pcap_setfilter(pd, &fcode) < 0)
374 error("%s", pcap_geterr(pd));
375 if (WFileName) {
376 pcap_dumper_t *p = pcap_dump_open(pd, WFileName);
377 if (p == NULL)
378 error("%s", pcap_geterr(pd));
379 printer = pcap_dump;
380 pcap_userdata = (u_char *)p;
381 } else {
382 printer = lookup_printer(pcap_datalink(pd));
383 pcap_userdata = 0;
384 }
385 if (RFileName == NULL) {
386 (void)fprintf(stderr, "%s: listening on %s\n",
387 program_name, device);
388 (void)fflush(stderr);
389 }
390 if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) {
391 (void)fprintf(stderr, "%s: pcap_loop: %s\n",
392 program_name, pcap_geterr(pd));
393 exit(1);
394 }
395 pcap_close(pd);
396 exit(0);
397 }
398
399 /* make a clean exit on interrupts */
400 RETSIGTYPE
401 cleanup(int signo)
402 {
403 struct pcap_stat stat;
404
405 /* Can't print the summary if reading from a savefile */
406 if (pd != NULL && pcap_file(pd) == NULL) {
407 (void)fflush(stdout);
408 putc('\n', stderr);
409 if (pcap_stats(pd, &stat) < 0)
410 (void)fprintf(stderr, "pcap_stats: %s\n",
411 pcap_geterr(pd));
412 else {
413 (void)fprintf(stderr, "%d packets received by filter\n",
414 stat.ps_recv);
415 (void)fprintf(stderr, "%d packets dropped by kernel\n",
416 stat.ps_drop);
417 }
418 }
419 exit(0);
420 }
421
422 /* Like default_print() but data need not be aligned */
423 void
424 default_print_unaligned(register const u_char *cp, register u_int length)
425 {
426 register u_int i, s;
427 register int nshorts;
428
429 char line[81];
430
431 nshorts = (u_int) length / sizeof(u_short);
432 i = 0;
433 memset(line, ' ', 80);
434 line[81]='\0';
435
436 putchar('\n');
437 while (nshorts >= 0) {
438
439 sprintf(line+20+i*5, "%02x%02x ", cp[0], cp[1]);
440
441 if(isprint(cp[0])) {
442 line[62+i*2]=cp[0];
443 } else {
444 line[62+i*2]='.';
445 }
446 if(isprint(cp[1])) {
447 line[62+i*2+1]=cp[1];
448 } else {
449 line[62+i*2+1]='.';
450 }
451 i++;
452 if (i == 8) {
453 line[60]=' ';
454 line[61]=' ';
455 line[62+16]='\0';
456 puts(line);
457 i=0;
458 }
459 cp += 2;
460 nshorts--;
461 }
462 }
463
464 /*
465 * By default, print the packet out in hex.
466 *
467 * (BTW, please don't send us patches to print the packet out in ascii)
468 */
469 void
470 default_print(register const u_char *bp, register u_int length)
471 {
472 register const u_short *sp;
473 register u_int i;
474 register int nshorts;
475
476 default_print_unaligned(bp, length);
477 }
478
479 __dead void
480 usage(void)
481 {
482 extern char version[];
483 extern char pcap_version[];
484
485 (void)fprintf(stderr, "%s version %s\n", program_name, version);
486 (void)fprintf(stderr, "libpcap version %s\n", pcap_version);
487 (void)fprintf(stderr,
488 "Usage: %s [-adeflnNOpqStvx] [-c count] [ -F file ]\n", program_name);
489 (void)fprintf(stderr,
490 "\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n");
491 (void)fprintf(stderr,
492 "\t\t[ -T type ] [ -w file ] [ expression ]\n");
493 exit(-1);
494 }