1 |
|
|
/* $OpenBSD: tcpdump.c,v 1.80 2017/09/08 19:10:57 brynet Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 |
5 |
|
|
* The Regents of the University of California. All rights reserved. |
6 |
|
|
* |
7 |
|
|
* Redistribution and use in source and binary forms, with or without |
8 |
|
|
* modification, are permitted provided that: (1) source code distributions |
9 |
|
|
* retain the above copyright notice and this paragraph in its entirety, (2) |
10 |
|
|
* distributions including binary code include the above copyright notice and |
11 |
|
|
* this paragraph in its entirety in the documentation or other materials |
12 |
|
|
* provided with the distribution, and (3) all advertising materials mentioning |
13 |
|
|
* features or use of this software display the following acknowledgement: |
14 |
|
|
* ``This product includes software developed by the University of California, |
15 |
|
|
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of |
16 |
|
|
* the University nor the names of its contributors may be used to endorse |
17 |
|
|
* or promote products derived from this software without specific prior |
18 |
|
|
* written permission. |
19 |
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED |
20 |
|
|
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF |
21 |
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
/* |
25 |
|
|
* tcpdump - monitor tcp/ip traffic on an ethernet. |
26 |
|
|
* |
27 |
|
|
* First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. |
28 |
|
|
* Mercilessly hacked and occasionally improved since then via the |
29 |
|
|
* combined efforts of Van, Steve McCanne and Craig Leres of LBL. |
30 |
|
|
*/ |
31 |
|
|
|
32 |
|
|
#include <sys/types.h> |
33 |
|
|
#include <sys/time.h> |
34 |
|
|
#include <sys/ioctl.h> |
35 |
|
|
#include <sys/wait.h> |
36 |
|
|
|
37 |
|
|
#include <netinet/in.h> |
38 |
|
|
|
39 |
|
|
#include <pcap.h> |
40 |
|
|
#include <signal.h> |
41 |
|
|
#include <stdio.h> |
42 |
|
|
#include <stdlib.h> |
43 |
|
|
#include <string.h> |
44 |
|
|
#include <unistd.h> |
45 |
|
|
#include <limits.h> |
46 |
|
|
#include <ctype.h> |
47 |
|
|
#include <err.h> |
48 |
|
|
#include <errno.h> |
49 |
|
|
|
50 |
|
|
#include "interface.h" |
51 |
|
|
#include "addrtoname.h" |
52 |
|
|
#include "setsignal.h" |
53 |
|
|
#include "gmt2local.h" |
54 |
|
|
|
55 |
|
|
#include <sys/socket.h> |
56 |
|
|
#include <net/if.h> |
57 |
|
|
#include <net/pfvar.h> |
58 |
|
|
#include "pfctl.h" |
59 |
|
|
#include "pfctl_parser.h" |
60 |
|
|
#include "privsep.h" |
61 |
|
|
|
62 |
|
|
int Aflag; /* dump ascii */ |
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 Iflag; /* include interface in output */ |
68 |
|
|
int Lflag; /* List available link types */ |
69 |
|
|
int nflag; /* leave addresses as numbers */ |
70 |
|
|
int Nflag; /* remove domains from printed host names */ |
71 |
|
|
int Oflag = 1; /* run filter code optimizer */ |
72 |
|
|
int oflag; /* print passive OS fingerprints */ |
73 |
|
|
int pflag; /* don't go promiscuous */ |
74 |
|
|
int qflag; /* quick (shorter) output */ |
75 |
|
|
int Sflag; /* print raw TCP sequence numbers */ |
76 |
|
|
int tflag = 1; /* print packet arrival time */ |
77 |
|
|
int vflag; /* verbose */ |
78 |
|
|
int xflag; /* print packet in hex */ |
79 |
|
|
int Xflag; /* print packet in emacs-hexl style */ |
80 |
|
|
|
81 |
|
|
int packettype; |
82 |
|
|
|
83 |
|
|
char *program_name; |
84 |
|
|
char *device = NULL; |
85 |
|
|
|
86 |
|
|
int32_t thiszone; /* seconds offset from gmt to local time */ |
87 |
|
|
|
88 |
|
|
extern volatile pid_t child_pid; |
89 |
|
|
|
90 |
|
|
/* Externs */ |
91 |
|
|
extern void bpf_dump(struct bpf_program *, int); |
92 |
|
|
extern int esp_init(char *); |
93 |
|
|
|
94 |
|
|
/* Forwards */ |
95 |
|
|
void cleanup(int); |
96 |
|
|
void gotchld(int); |
97 |
|
|
extern __dead void usage(void); |
98 |
|
|
|
99 |
|
|
/* Length of saved portion of packet. */ |
100 |
|
|
int snaplen = 0; |
101 |
|
|
|
102 |
|
|
struct printer { |
103 |
|
|
pcap_handler f; |
104 |
|
|
int type; |
105 |
|
|
}; |
106 |
|
|
|
107 |
|
|
/* XXX needed if using old bpf.h */ |
108 |
|
|
#ifndef DLT_ATM_RFC1483 |
109 |
|
|
#define DLT_ATM_RFC1483 11 |
110 |
|
|
#endif |
111 |
|
|
|
112 |
|
|
static struct printer printers[] = { |
113 |
|
|
{ ether_if_print, DLT_EN10MB }, |
114 |
|
|
{ ether_if_print, DLT_IEEE802 }, |
115 |
|
|
{ sl_if_print, DLT_SLIP }, |
116 |
|
|
{ sl_bsdos_if_print, DLT_SLIP_BSDOS }, |
117 |
|
|
{ ppp_if_print, DLT_PPP }, |
118 |
|
|
{ fddi_if_print, DLT_FDDI }, |
119 |
|
|
{ null_if_print, DLT_NULL }, |
120 |
|
|
{ raw_if_print, DLT_RAW }, |
121 |
|
|
{ atm_if_print, DLT_ATM_RFC1483 }, |
122 |
|
|
{ loop_if_print, DLT_LOOP }, |
123 |
|
|
{ enc_if_print, DLT_ENC }, |
124 |
|
|
{ pflog_if_print, DLT_PFLOG }, |
125 |
|
|
{ pfsync_if_print, DLT_PFSYNC }, |
126 |
|
|
{ ppp_ether_if_print, DLT_PPP_ETHER }, |
127 |
|
|
{ ieee802_11_if_print, DLT_IEEE802_11 }, |
128 |
|
|
{ ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, |
129 |
|
|
{ ofp_if_print, DLT_OPENFLOW }, |
130 |
|
|
{ NULL, 0 }, |
131 |
|
|
}; |
132 |
|
|
|
133 |
|
|
static pcap_handler |
134 |
|
|
lookup_printer(int type) |
135 |
|
|
{ |
136 |
|
|
struct printer *p; |
137 |
|
|
|
138 |
|
|
for (p = printers; p->f; ++p) { |
139 |
|
|
if (type == p->type) |
140 |
|
|
return p->f; |
141 |
|
|
} |
142 |
|
|
|
143 |
|
|
error("unknown data link type 0x%x", type); |
144 |
|
|
/* NOTREACHED */ |
145 |
|
|
} |
146 |
|
|
|
147 |
|
|
static int |
148 |
|
|
init_pfosfp(void) |
149 |
|
|
{ |
150 |
|
|
pf_osfp_initialize(); |
151 |
|
|
if (pfctl_file_fingerprints(-1, |
152 |
|
|
PF_OPT_QUIET|PF_OPT_NOACTION, PF_OSFP_FILE) == 0) |
153 |
|
|
return 1; |
154 |
|
|
return 0; |
155 |
|
|
} |
156 |
|
|
|
157 |
|
|
static pcap_t *pd; |
158 |
|
|
|
159 |
|
|
/* Multiple DLT support */ |
160 |
|
|
void pcap_list_linktypes(pcap_t *); |
161 |
|
|
void pcap_print_linktype(u_int); |
162 |
|
|
|
163 |
|
|
void |
164 |
|
|
pcap_print_linktype(u_int dlt) |
165 |
|
|
{ |
166 |
|
|
const char *name; |
167 |
|
|
|
168 |
|
|
if ((name = pcap_datalink_val_to_name(dlt)) != NULL) |
169 |
|
|
fprintf(stderr, "%s\n", name); |
170 |
|
|
else |
171 |
|
|
fprintf(stderr, "<unknown: %u>\n", dlt); |
172 |
|
|
} |
173 |
|
|
|
174 |
|
|
void |
175 |
|
|
pcap_list_linktypes(pcap_t *p) |
176 |
|
|
{ |
177 |
|
|
int fd = p->fd; |
178 |
|
|
u_int n; |
179 |
|
|
|
180 |
|
|
#define MAXDLT 100 |
181 |
|
|
|
182 |
|
|
u_int dltlist[MAXDLT]; |
183 |
|
|
struct bpf_dltlist dl = {MAXDLT, dltlist}; |
184 |
|
|
|
185 |
|
|
if (fd < 0) |
186 |
|
|
error("Invalid bpf descriptor"); |
187 |
|
|
|
188 |
|
|
if (ioctl(fd, BIOCGDLTLIST, &dl) < 0) |
189 |
|
|
err(1, "BIOCGDLTLIST"); |
190 |
|
|
|
191 |
|
|
if (dl.bfl_len > MAXDLT) |
192 |
|
|
error("Invalid number of linktypes: %u", dl.bfl_len); |
193 |
|
|
|
194 |
|
|
fprintf(stderr, "%d link type%s supported:\n", dl.bfl_len, |
195 |
|
|
dl.bfl_len == 1 ? "" : "s"); |
196 |
|
|
|
197 |
|
|
for (n = 0; n < dl.bfl_len; n++) { |
198 |
|
|
fprintf(stderr, "\t"); |
199 |
|
|
pcap_print_linktype(dltlist[n]); |
200 |
|
|
} |
201 |
|
|
} |
202 |
|
|
|
203 |
|
|
int |
204 |
|
|
main(int argc, char **argv) |
205 |
|
|
{ |
206 |
|
|
int cnt = -1, op, i; |
207 |
|
|
bpf_u_int32 localnet, netmask; |
208 |
|
|
char *cp, *infile = NULL, *RFileName = NULL; |
209 |
|
|
char ebuf[PCAP_ERRBUF_SIZE], *WFileName = NULL; |
210 |
|
|
pcap_handler printer; |
211 |
|
|
struct bpf_program *fcode; |
212 |
|
|
u_char *pcap_userdata; |
213 |
|
|
u_int dirfilt = 0, dlt = (u_int) -1; |
214 |
|
|
const char *errstr; |
215 |
|
|
|
216 |
|
|
if ((cp = strrchr(argv[0], '/')) != NULL) |
217 |
|
|
program_name = cp + 1; |
218 |
|
|
else |
219 |
|
|
program_name = argv[0]; |
220 |
|
|
|
221 |
|
|
/* '-P' used internally, exec privileged portion */ |
222 |
|
|
if (argc >= 2 && strcmp("-P", argv[1]) == 0) |
223 |
|
|
priv_exec(argc, argv); |
224 |
|
|
|
225 |
|
|
if (priv_init(argc, argv)) |
226 |
|
|
error("Failed to setup privsep"); |
227 |
|
|
|
228 |
|
|
/* state: STATE_INIT */ |
229 |
|
|
|
230 |
|
|
opterr = 0; |
231 |
|
|
while ((op = getopt(argc, argv, |
232 |
|
|
"Aac:D:deE:fF:i:IlLnNOopqr:s:StT:vw:xXy:Y")) != -1) |
233 |
|
|
switch (op) { |
234 |
|
|
|
235 |
|
|
case 'A': |
236 |
|
|
xflag = 1; |
237 |
|
|
Aflag = 1; |
238 |
|
|
break; |
239 |
|
|
|
240 |
|
|
case 'a': |
241 |
|
|
aflag = 1; |
242 |
|
|
break; |
243 |
|
|
|
244 |
|
|
case 'c': |
245 |
|
|
cnt = strtonum(optarg, 1, INT_MAX, &errstr); |
246 |
|
|
if (errstr) |
247 |
|
|
error("invalid packet count %s: %s", |
248 |
|
|
optarg, errstr); |
249 |
|
|
break; |
250 |
|
|
|
251 |
|
|
case 'D': |
252 |
|
|
if (strcasecmp(optarg, "in") == 0) |
253 |
|
|
dirfilt = BPF_DIRECTION_OUT; |
254 |
|
|
else if (strcasecmp(optarg, "out") == 0) |
255 |
|
|
dirfilt = BPF_DIRECTION_IN; |
256 |
|
|
else |
257 |
|
|
error("invalid traffic direction %s", optarg); |
258 |
|
|
break; |
259 |
|
|
|
260 |
|
|
case 'd': |
261 |
|
|
++dflag; |
262 |
|
|
break; |
263 |
|
|
case 'e': |
264 |
|
|
eflag = 1; |
265 |
|
|
break; |
266 |
|
|
|
267 |
|
|
case 'f': |
268 |
|
|
fflag = 1; |
269 |
|
|
break; |
270 |
|
|
|
271 |
|
|
case 'F': |
272 |
|
|
infile = optarg; |
273 |
|
|
break; |
274 |
|
|
|
275 |
|
|
case 'i': |
276 |
|
|
device = optarg; |
277 |
|
|
break; |
278 |
|
|
|
279 |
|
|
case 'I': |
280 |
|
|
Iflag = 1; |
281 |
|
|
break; |
282 |
|
|
|
283 |
|
|
case 'l': |
284 |
|
|
setvbuf(stdout, NULL, _IOLBF, 0); |
285 |
|
|
break; |
286 |
|
|
case 'L': |
287 |
|
|
Lflag = 1; |
288 |
|
|
break; |
289 |
|
|
case 'n': |
290 |
|
|
nflag = 1; |
291 |
|
|
break; |
292 |
|
|
|
293 |
|
|
case 'N': |
294 |
|
|
Nflag = 1; |
295 |
|
|
break; |
296 |
|
|
|
297 |
|
|
case 'O': |
298 |
|
|
Oflag = 0; |
299 |
|
|
break; |
300 |
|
|
|
301 |
|
|
case 'o': |
302 |
|
|
oflag = 1; |
303 |
|
|
break; |
304 |
|
|
|
305 |
|
|
case 'p': |
306 |
|
|
pflag = 1; |
307 |
|
|
break; |
308 |
|
|
|
309 |
|
|
case 'q': |
310 |
|
|
qflag = 1; |
311 |
|
|
break; |
312 |
|
|
|
313 |
|
|
case 'r': |
314 |
|
|
RFileName = optarg; |
315 |
|
|
break; |
316 |
|
|
|
317 |
|
|
case 's': |
318 |
|
|
snaplen = strtonum(optarg, 1, INT_MAX, &errstr); |
319 |
|
|
if (errstr) |
320 |
|
|
error("invalid snaplen %s: %s", optarg, errstr); |
321 |
|
|
break; |
322 |
|
|
|
323 |
|
|
case 'S': |
324 |
|
|
Sflag = 1; |
325 |
|
|
break; |
326 |
|
|
|
327 |
|
|
case 't': |
328 |
|
|
--tflag; |
329 |
|
|
break; |
330 |
|
|
|
331 |
|
|
case 'T': |
332 |
|
|
if (strcasecmp(optarg, "vat") == 0) |
333 |
|
|
packettype = PT_VAT; |
334 |
|
|
else if (strcasecmp(optarg, "wb") == 0) |
335 |
|
|
packettype = PT_WB; |
336 |
|
|
else if (strcasecmp(optarg, "rpc") == 0) |
337 |
|
|
packettype = PT_RPC; |
338 |
|
|
else if (strcasecmp(optarg, "rtp") == 0) |
339 |
|
|
packettype = PT_RTP; |
340 |
|
|
else if (strcasecmp(optarg, "rtcp") == 0) |
341 |
|
|
packettype = PT_RTCP; |
342 |
|
|
else if (strcasecmp(optarg, "cnfp") == 0) |
343 |
|
|
packettype = PT_CNFP; |
344 |
|
|
else if (strcasecmp(optarg, "vrrp") == 0) |
345 |
|
|
packettype = PT_VRRP; |
346 |
|
|
else if (strcasecmp(optarg, "tcp") == 0) |
347 |
|
|
packettype = PT_TCP; |
348 |
|
|
else if (strcasecmp(optarg, "sack") == 0) |
349 |
|
|
/* |
350 |
|
|
* kept for compatibility; DEFAULT_SNAPLEN |
351 |
|
|
* used to be too short to capture SACK. |
352 |
|
|
*/ |
353 |
|
|
; |
354 |
|
|
else |
355 |
|
|
error("unknown packet type `%s'", optarg); |
356 |
|
|
break; |
357 |
|
|
|
358 |
|
|
case 'v': |
359 |
|
|
++vflag; |
360 |
|
|
break; |
361 |
|
|
|
362 |
|
|
case 'w': |
363 |
|
|
WFileName = optarg; |
364 |
|
|
break; |
365 |
|
|
#ifdef YYDEBUG |
366 |
|
|
case 'Y': |
367 |
|
|
{ |
368 |
|
|
/* Undocumented flag */ |
369 |
|
|
extern int yydebug; |
370 |
|
|
yydebug = 1; |
371 |
|
|
} |
372 |
|
|
break; |
373 |
|
|
#endif |
374 |
|
|
case 'y': |
375 |
|
|
i = pcap_datalink_name_to_val(optarg); |
376 |
|
|
if (i < 0) |
377 |
|
|
error("invalid data link type: %s", optarg); |
378 |
|
|
dlt = (u_int)i; |
379 |
|
|
break; |
380 |
|
|
|
381 |
|
|
case 'x': |
382 |
|
|
xflag = 1; |
383 |
|
|
break; |
384 |
|
|
|
385 |
|
|
case 'X': |
386 |
|
|
Xflag = 1; |
387 |
|
|
xflag = 1; |
388 |
|
|
break; |
389 |
|
|
|
390 |
|
|
case 'E': |
391 |
|
|
if (esp_init(optarg) < 0) |
392 |
|
|
error("bad esp specification `%s'", optarg); |
393 |
|
|
break; |
394 |
|
|
|
395 |
|
|
default: |
396 |
|
|
usage(); |
397 |
|
|
/* NOTREACHED */ |
398 |
|
|
} |
399 |
|
|
|
400 |
|
|
if (snaplen == 0) { |
401 |
|
|
switch (dlt) { |
402 |
|
|
case DLT_IEEE802_11: |
403 |
|
|
snaplen = IEEE802_11_SNAPLEN; |
404 |
|
|
break; |
405 |
|
|
case DLT_IEEE802_11_RADIO: |
406 |
|
|
snaplen = IEEE802_11_RADIO_SNAPLEN; |
407 |
|
|
break; |
408 |
|
|
default: |
409 |
|
|
snaplen = DEFAULT_SNAPLEN; |
410 |
|
|
break; |
411 |
|
|
} |
412 |
|
|
} |
413 |
|
|
|
414 |
|
|
if (aflag && nflag) |
415 |
|
|
error("-a and -n options are incompatible"); |
416 |
|
|
|
417 |
|
|
if (RFileName != NULL) { |
418 |
|
|
pd = priv_pcap_offline(RFileName, ebuf); |
419 |
|
|
if (pd == NULL) |
420 |
|
|
error("%s", ebuf); |
421 |
|
|
/* state: STATE_BPF */ |
422 |
|
|
localnet = 0; |
423 |
|
|
netmask = 0; |
424 |
|
|
if (fflag != 0) |
425 |
|
|
error("-f and -r options are incompatible"); |
426 |
|
|
} else { |
427 |
|
|
if (device == NULL) { |
428 |
|
|
device = pcap_lookupdev(ebuf); |
429 |
|
|
if (device == NULL) |
430 |
|
|
error("%s", ebuf); |
431 |
|
|
} |
432 |
|
|
pd = priv_pcap_live(device, snaplen, !pflag, 1000, ebuf, |
433 |
|
|
dlt, dirfilt); |
434 |
|
|
if (pd == NULL) |
435 |
|
|
error("%s", ebuf); |
436 |
|
|
|
437 |
|
|
/* state: STATE_BPF */ |
438 |
|
|
if (pcap_lookupnet(device, &localnet, &netmask, ebuf)) { |
439 |
|
|
if (fflag) |
440 |
|
|
warning("%s", ebuf); |
441 |
|
|
localnet = 0; |
442 |
|
|
netmask = 0; |
443 |
|
|
} |
444 |
|
|
} |
445 |
|
|
i = pcap_snapshot(pd); |
446 |
|
|
if (snaplen < i) { |
447 |
|
|
warning("snaplen raised from %d to %d", snaplen, i); |
448 |
|
|
snaplen = i; |
449 |
|
|
} |
450 |
|
|
|
451 |
|
|
if (Lflag) { |
452 |
|
|
pcap_list_linktypes(pd); |
453 |
|
|
exit(0); |
454 |
|
|
} |
455 |
|
|
|
456 |
|
|
fcode = priv_pcap_setfilter(pd, Oflag, netmask); |
457 |
|
|
/* state: STATE_FILTER */ |
458 |
|
|
if (fcode == NULL) |
459 |
|
|
error("%s", pcap_geterr(pd)); |
460 |
|
|
if (dflag) { |
461 |
|
|
bpf_dump(fcode, dflag); |
462 |
|
|
exit(0); |
463 |
|
|
} |
464 |
|
|
init_addrtoname(localnet, netmask); |
465 |
|
|
|
466 |
|
|
if (WFileName) { |
467 |
|
|
pcap_dumper_t *p; |
468 |
|
|
|
469 |
|
|
p = priv_pcap_dump_open(pd, WFileName); |
470 |
|
|
/* state: STATE_RUN */ |
471 |
|
|
if (p == NULL) |
472 |
|
|
error("%s", pcap_geterr(pd)); |
473 |
|
|
{ |
474 |
|
|
FILE *fp = (FILE *)p; /* XXX touching pcap guts! */ |
475 |
|
|
fflush(fp); |
476 |
|
|
setvbuf(fp, NULL, _IONBF, 0); |
477 |
|
|
} |
478 |
|
|
printer = pcap_dump; |
479 |
|
|
pcap_userdata = (u_char *)p; |
480 |
|
|
} else { |
481 |
|
|
printer = lookup_printer(pcap_datalink(pd)); |
482 |
|
|
pcap_userdata = NULL; |
483 |
|
|
priv_init_done(); |
484 |
|
|
/* state: STATE_RUN */ |
485 |
|
|
} |
486 |
|
|
if (RFileName == NULL) { |
487 |
|
|
(void)fprintf(stderr, "%s: listening on %s, link-type ", |
488 |
|
|
program_name, device); |
489 |
|
|
pcap_print_linktype(pd->linktype); |
490 |
|
|
(void)fflush(stderr); |
491 |
|
|
} |
492 |
|
|
|
493 |
|
|
if (oflag) |
494 |
|
|
oflag = init_pfosfp(); |
495 |
|
|
if (tflag > 0) |
496 |
|
|
thiszone = gmt2local(0); |
497 |
|
|
|
498 |
|
|
if (pledge("stdio flock rpath cpath wpath", NULL) == -1) |
499 |
|
|
err(1, "pledge"); |
500 |
|
|
|
501 |
|
|
if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) { |
502 |
|
|
(void)fprintf(stderr, "%s: pcap_loop: %s\n", |
503 |
|
|
program_name, pcap_geterr(pd)); |
504 |
|
|
exit(1); |
505 |
|
|
} |
506 |
|
|
pcap_close(pd); |
507 |
|
|
exit(0); |
508 |
|
|
} |
509 |
|
|
|
510 |
|
|
/* make a clean exit on interrupts */ |
511 |
|
|
void |
512 |
|
|
cleanup(int signo) |
513 |
|
|
{ |
514 |
|
|
struct pcap_stat stat; |
515 |
|
|
sigset_t allsigs; |
516 |
|
|
char buf[1024]; |
517 |
|
|
|
518 |
|
|
sigfillset(&allsigs); |
519 |
|
|
sigprocmask(SIG_BLOCK, &allsigs, NULL); |
520 |
|
|
|
521 |
|
|
/* Can't print the summary if reading from a savefile */ |
522 |
|
|
(void)write(STDERR_FILENO, "\n", 1); |
523 |
|
|
if (pd != NULL && pcap_file(pd) == NULL) { |
524 |
|
|
if (priv_pcap_stats(&stat) < 0) { |
525 |
|
|
(void)snprintf(buf, sizeof buf, |
526 |
|
|
"pcap_stats: %s\n", pcap_geterr(pd)); |
527 |
|
|
write(STDERR_FILENO, buf, strlen(buf)); |
528 |
|
|
} else { |
529 |
|
|
(void)snprintf(buf, sizeof buf, |
530 |
|
|
"%u packets received by filter\n", stat.ps_recv); |
531 |
|
|
write(STDERR_FILENO, buf, strlen(buf)); |
532 |
|
|
(void)snprintf(buf, sizeof buf, |
533 |
|
|
"%u packets dropped by kernel\n", stat.ps_drop); |
534 |
|
|
write(STDERR_FILENO, buf, strlen(buf)); |
535 |
|
|
} |
536 |
|
|
} |
537 |
|
|
_exit(0); |
538 |
|
|
} |
539 |
|
|
|
540 |
|
|
void |
541 |
|
|
gotchld(int signo) |
542 |
|
|
{ |
543 |
|
|
pid_t pid; |
544 |
|
|
int status; |
545 |
|
|
int save_err = errno; |
546 |
|
|
|
547 |
|
|
do { |
548 |
|
|
pid = waitpid(child_pid, &status, WNOHANG); |
549 |
|
|
if (pid > 0 && (WIFEXITED(status) || WIFSIGNALED(status))) |
550 |
|
|
cleanup(0); |
551 |
|
|
} while (pid == -1 && errno == EINTR); |
552 |
|
|
|
553 |
|
|
if (pid == -1) |
554 |
|
|
_exit(1); |
555 |
|
|
|
556 |
|
|
errno = save_err; |
557 |
|
|
} |
558 |
|
|
|
559 |
|
|
/* dump the buffer in `emacs-hexl' style */ |
560 |
|
|
void |
561 |
|
|
default_print_hexl(const u_char *cp, unsigned int length) |
562 |
|
|
{ |
563 |
|
|
unsigned int i, j, jm; |
564 |
|
|
int c; |
565 |
|
|
char ln[128], buf[128]; |
566 |
|
|
|
567 |
|
|
printf("\n"); |
568 |
|
|
for (i = 0; i < length; i += 0x10) { |
569 |
|
|
snprintf(ln, sizeof(ln), " %04x: ", (unsigned int)i); |
570 |
|
|
jm = length - i; |
571 |
|
|
jm = jm > 16 ? 16 : jm; |
572 |
|
|
|
573 |
|
|
for (j = 0; j < jm; j++) { |
574 |
|
|
if ((j % 2) == 1) |
575 |
|
|
snprintf(buf, sizeof(buf), "%02x ", |
576 |
|
|
(unsigned int)cp[i+j]); |
577 |
|
|
else |
578 |
|
|
snprintf(buf, sizeof(buf), "%02x", |
579 |
|
|
(unsigned int)cp[i+j]); |
580 |
|
|
strlcat(ln, buf, sizeof ln); |
581 |
|
|
} |
582 |
|
|
for (; j < 16; j++) { |
583 |
|
|
if ((j % 2) == 1) |
584 |
|
|
snprintf(buf, sizeof buf, " "); |
585 |
|
|
else |
586 |
|
|
snprintf(buf, sizeof buf, " "); |
587 |
|
|
strlcat(ln, buf, sizeof ln); |
588 |
|
|
} |
589 |
|
|
|
590 |
|
|
strlcat(ln, " ", sizeof ln); |
591 |
|
|
for (j = 0; j < jm; j++) { |
592 |
|
|
c = cp[i+j]; |
593 |
|
|
c = isprint(c) ? c : '.'; |
594 |
|
|
buf[0] = c; |
595 |
|
|
buf[1] = '\0'; |
596 |
|
|
strlcat(ln, buf, sizeof ln); |
597 |
|
|
} |
598 |
|
|
printf("%s\n", ln); |
599 |
|
|
} |
600 |
|
|
} |
601 |
|
|
|
602 |
|
|
/* dump the text from the buffer */ |
603 |
|
|
void |
604 |
|
|
default_print_ascii(const u_char *cp, unsigned int length) |
605 |
|
|
{ |
606 |
|
|
int c, i; |
607 |
|
|
|
608 |
|
|
printf("\n"); |
609 |
|
|
for (i = 0; i < length; i++) { |
610 |
|
|
c = cp[i]; |
611 |
|
|
if (isprint(c) || c == '\t' || c == '\n' || c == '\r') |
612 |
|
|
putchar(c); |
613 |
|
|
else |
614 |
|
|
putchar('.'); |
615 |
|
|
} |
616 |
|
|
} |
617 |
|
|
|
618 |
|
|
/* Like default_print() but data need not be aligned */ |
619 |
|
|
void |
620 |
|
|
default_print_unaligned(const u_char *cp, u_int length) |
621 |
|
|
{ |
622 |
|
|
u_int i, s; |
623 |
|
|
int nshorts; |
624 |
|
|
|
625 |
|
|
if (Xflag) { |
626 |
|
|
/* dump the buffer in `emacs-hexl' style */ |
627 |
|
|
default_print_hexl(cp, length); |
628 |
|
|
} else if (Aflag) { |
629 |
|
|
/* dump the text in the buffer */ |
630 |
|
|
default_print_ascii(cp, length); |
631 |
|
|
} else { |
632 |
|
|
/* dump the buffer in old tcpdump style */ |
633 |
|
|
nshorts = (u_int) length / sizeof(u_short); |
634 |
|
|
i = 0; |
635 |
|
|
while (--nshorts >= 0) { |
636 |
|
|
if ((i++ % 8) == 0) |
637 |
|
|
(void)printf("\n\t\t\t"); |
638 |
|
|
s = *cp++; |
639 |
|
|
(void)printf(" %02x%02x", s, *cp++); |
640 |
|
|
} |
641 |
|
|
if (length & 1) { |
642 |
|
|
if ((i % 8) == 0) |
643 |
|
|
(void)printf("\n\t\t\t"); |
644 |
|
|
(void)printf(" %02x", *cp); |
645 |
|
|
} |
646 |
|
|
} |
647 |
|
|
} |
648 |
|
|
|
649 |
|
|
void |
650 |
|
|
default_print(const u_char *bp, u_int length) |
651 |
|
|
{ |
652 |
|
|
const u_short *sp; |
653 |
|
|
u_int i; |
654 |
|
|
int nshorts; |
655 |
|
|
|
656 |
|
|
if (Xflag) { |
657 |
|
|
/* dump the buffer in `emacs-hexl' style */ |
658 |
|
|
default_print_hexl(bp, length); |
659 |
|
|
} else if (Aflag) { |
660 |
|
|
/* dump the text in the buffer */ |
661 |
|
|
default_print_ascii(bp, length); |
662 |
|
|
} else { |
663 |
|
|
/* dump the buffer in old tcpdump style */ |
664 |
|
|
if ((long)bp & 1) { |
665 |
|
|
default_print_unaligned(bp, length); |
666 |
|
|
return; |
667 |
|
|
} |
668 |
|
|
sp = (u_short *)bp; |
669 |
|
|
nshorts = (u_int) length / sizeof(u_short); |
670 |
|
|
i = 0; |
671 |
|
|
while (--nshorts >= 0) { |
672 |
|
|
if ((i++ % 8) == 0) |
673 |
|
|
(void)printf("\n\t\t\t"); |
674 |
|
|
(void)printf(" %04x", ntohs(*sp++)); |
675 |
|
|
} |
676 |
|
|
if (length & 1) { |
677 |
|
|
if ((i % 8) == 0) |
678 |
|
|
(void)printf("\n\t\t\t"); |
679 |
|
|
(void)printf(" %02x", *(u_char *)sp); |
680 |
|
|
} |
681 |
|
|
} |
682 |
|
|
} |
683 |
|
|
|
684 |
|
|
void |
685 |
|
|
set_slave_signals(void) |
686 |
|
|
{ |
687 |
|
|
setsignal(SIGTERM, cleanup); |
688 |
|
|
setsignal(SIGINT, cleanup); |
689 |
|
|
setsignal(SIGCHLD, gotchld); |
690 |
|
|
setsignal(SIGHUP, cleanup); |
691 |
|
|
} |
692 |
|
|
|
693 |
|
|
__dead void |
694 |
|
|
usage(void) |
695 |
|
|
{ |
696 |
|
|
(void)fprintf(stderr, |
697 |
|
|
"Usage: %s [-AadefILlNnOopqStvXx] [-c count] [-D direction]\n", |
698 |
|
|
program_name); |
699 |
|
|
(void)fprintf(stderr, |
700 |
|
|
"\t [-E [espalg:]espkey] [-F file] [-i interface] [-r file]\n"); |
701 |
|
|
(void)fprintf(stderr, |
702 |
|
|
"\t [-s snaplen] [-T type] [-w file] [-y datalinktype] [expression]\n"); |
703 |
|
|
exit(1); |
704 |
|
|
} |