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