141c99275SPeter Avalos /*
241c99275SPeter Avalos * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
341c99275SPeter Avalos * The Regents of the University of California. All rights reserved.
441c99275SPeter Avalos *
541c99275SPeter Avalos * Redistribution and use in source and binary forms, with or without
641c99275SPeter Avalos * modification, are permitted provided that: (1) source code distributions
741c99275SPeter Avalos * retain the above copyright notice and this paragraph in its entirety, (2)
841c99275SPeter Avalos * distributions including binary code include the above copyright notice and
941c99275SPeter Avalos * this paragraph in its entirety in the documentation or other materials
1041c99275SPeter Avalos * provided with the distribution, and (3) all advertising materials mentioning
1141c99275SPeter Avalos * features or use of this software display the following acknowledgement:
1241c99275SPeter Avalos * ``This product includes software developed by the University of California,
1341c99275SPeter Avalos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1441c99275SPeter Avalos * the University nor the names of its contributors may be used to endorse
1541c99275SPeter Avalos * or promote products derived from this software without specific prior
1641c99275SPeter Avalos * written permission.
1741c99275SPeter Avalos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1841c99275SPeter Avalos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1941c99275SPeter Avalos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2041c99275SPeter Avalos *
2141c99275SPeter Avalos * Support for splitting captures into multiple files with a maximum
2241c99275SPeter Avalos * file size:
2341c99275SPeter Avalos *
2441c99275SPeter Avalos * Copyright (c) 2001
2541c99275SPeter Avalos * Seth Webster <swebster@sst.ll.mit.edu>
2641c99275SPeter Avalos */
2741c99275SPeter Avalos
2841c99275SPeter Avalos /*
29411677aeSAaron LI * tcpdump - dump traffic on a network
3041c99275SPeter Avalos *
3141c99275SPeter Avalos * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory.
3241c99275SPeter Avalos * Mercilessly hacked and occasionally improved since then via the
3341c99275SPeter Avalos * combined efforts of Van, Steve McCanne and Craig Leres of LBL.
3441c99275SPeter Avalos */
3541c99275SPeter Avalos
3641c99275SPeter Avalos #ifdef HAVE_CONFIG_H
37*ed775ee7SAntonio Huete Jimenez #include <config.h>
3841c99275SPeter Avalos #endif
3941c99275SPeter Avalos
40411677aeSAaron LI /*
41*ed775ee7SAntonio Huete Jimenez * Some older versions of Mac OS X may ship pcap.h from libpcap 0.6 with a
42*ed775ee7SAntonio Huete Jimenez * libpcap based on 0.8. That means it has pcap_findalldevs() but the
43*ed775ee7SAntonio Huete Jimenez * header doesn't define pcap_if_t, meaning that we can't actually *use*
44*ed775ee7SAntonio Huete Jimenez * pcap_findalldevs().
45411677aeSAaron LI */
46411677aeSAaron LI #ifdef HAVE_PCAP_FINDALLDEVS
47411677aeSAaron LI #ifndef HAVE_PCAP_IF_T
48411677aeSAaron LI #undef HAVE_PCAP_FINDALLDEVS
49411677aeSAaron LI #endif
5041c99275SPeter Avalos #endif
5141c99275SPeter Avalos
52*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
53*ed775ee7SAntonio Huete Jimenez
54*ed775ee7SAntonio Huete Jimenez /*
55*ed775ee7SAntonio Huete Jimenez * This must appear after including netdissect-stdinc.h, so that _U_ is
56*ed775ee7SAntonio Huete Jimenez * defined.
57*ed775ee7SAntonio Huete Jimenez */
58*ed775ee7SAntonio Huete Jimenez #ifndef lint
59*ed775ee7SAntonio Huete Jimenez static const char copyright[] _U_ =
60*ed775ee7SAntonio Huete Jimenez "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
61*ed775ee7SAntonio Huete Jimenez The Regents of the University of California. All rights reserved.\n";
62*ed775ee7SAntonio Huete Jimenez #endif
63411677aeSAaron LI
64411677aeSAaron LI #include <sys/stat.h>
65411677aeSAaron LI
66411677aeSAaron LI #ifdef HAVE_FCNTL_H
67411677aeSAaron LI #include <fcntl.h>
68411677aeSAaron LI #endif
69411677aeSAaron LI
70411677aeSAaron LI #ifdef HAVE_LIBCRYPTO
71411677aeSAaron LI #include <openssl/crypto.h>
72411677aeSAaron LI #endif
73411677aeSAaron LI
74411677aeSAaron LI #ifdef HAVE_GETOPT_LONG
75411677aeSAaron LI #include <getopt.h>
76411677aeSAaron LI #else
77*ed775ee7SAntonio Huete Jimenez #include "missing/getopt_long.h"
78411677aeSAaron LI #endif
79411677aeSAaron LI /* Capsicum-specific code requires macros from <net/bpf.h>, which will fail
80411677aeSAaron LI * to compile if <pcap.h> has already been included; including the headers
81411677aeSAaron LI * in the opposite order works fine.
82411677aeSAaron LI */
83411677aeSAaron LI #ifdef HAVE_CAPSICUM
84*ed775ee7SAntonio Huete Jimenez #include <sys/capsicum.h>
85411677aeSAaron LI #include <sys/ioccom.h>
86411677aeSAaron LI #include <net/bpf.h>
87411677aeSAaron LI #include <libgen.h>
88*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_CASPER
89*ed775ee7SAntonio Huete Jimenez #include <libcasper.h>
90*ed775ee7SAntonio Huete Jimenez #include <casper/cap_dns.h>
91*ed775ee7SAntonio Huete Jimenez #include <sys/nv.h>
92*ed775ee7SAntonio Huete Jimenez #endif /* HAVE_CASPER */
93411677aeSAaron LI #endif /* HAVE_CAPSICUM */
94*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_OPEN
95*ed775ee7SAntonio Huete Jimenez /*
96*ed775ee7SAntonio Huete Jimenez * We found pcap_open() in the capture library, so we'll be using
97*ed775ee7SAntonio Huete Jimenez * the remote capture APIs; define PCAP_REMOTE before we include pcap.h,
98*ed775ee7SAntonio Huete Jimenez * so we get those APIs declared, and the types and #defines that they
99*ed775ee7SAntonio Huete Jimenez * use defined.
100*ed775ee7SAntonio Huete Jimenez *
101*ed775ee7SAntonio Huete Jimenez * WinPcap's headers require that PCAP_REMOTE be defined in order to get
102*ed775ee7SAntonio Huete Jimenez * remote-capture APIs declared and types and #defines that they use
103*ed775ee7SAntonio Huete Jimenez * defined.
104*ed775ee7SAntonio Huete Jimenez *
105*ed775ee7SAntonio Huete Jimenez * (Versions of libpcap with those APIs, and thus Npcap, which is based on
106*ed775ee7SAntonio Huete Jimenez * those versions of libpcap, don't require it.)
107*ed775ee7SAntonio Huete Jimenez */
108*ed775ee7SAntonio Huete Jimenez #define HAVE_REMOTE
109*ed775ee7SAntonio Huete Jimenez #endif
11041c99275SPeter Avalos #include <pcap.h>
11141c99275SPeter Avalos #include <signal.h>
11241c99275SPeter Avalos #include <stdio.h>
113411677aeSAaron LI #include <stdarg.h>
11441c99275SPeter Avalos #include <stdlib.h>
11541c99275SPeter Avalos #include <string.h>
116ea7b4bf5SPeter Avalos #include <limits.h>
117*ed775ee7SAntonio Huete Jimenez #ifdef _WIN32
118*ed775ee7SAntonio Huete Jimenez #include <windows.h>
119*ed775ee7SAntonio Huete Jimenez #else
120*ed775ee7SAntonio Huete Jimenez #include <sys/time.h>
121ea7b4bf5SPeter Avalos #include <sys/wait.h>
122ea7b4bf5SPeter Avalos #include <sys/resource.h>
12341c99275SPeter Avalos #include <pwd.h>
12441c99275SPeter Avalos #include <grp.h>
125411677aeSAaron LI #endif /* _WIN32 */
12641c99275SPeter Avalos
127*ed775ee7SAntonio Huete Jimenez /*
128*ed775ee7SAntonio Huete Jimenez * Pathname separator.
129*ed775ee7SAntonio Huete Jimenez * Use this in pathnames, but do *not* use it in URLs.
130*ed775ee7SAntonio Huete Jimenez */
131*ed775ee7SAntonio Huete Jimenez #ifdef _WIN32
132*ed775ee7SAntonio Huete Jimenez #define PATH_SEPARATOR '\\'
133*ed775ee7SAntonio Huete Jimenez #else
134*ed775ee7SAntonio Huete Jimenez #define PATH_SEPARATOR '/'
135*ed775ee7SAntonio Huete Jimenez #endif
136*ed775ee7SAntonio Huete Jimenez
137411677aeSAaron LI /* capabilities convenience library */
138411677aeSAaron LI /* If a code depends on HAVE_LIBCAP_NG, it depends also on HAVE_CAP_NG_H.
139411677aeSAaron LI * If HAVE_CAP_NG_H is not defined, undefine HAVE_LIBCAP_NG.
140411677aeSAaron LI * Thus, the later tests are done only on HAVE_LIBCAP_NG.
141411677aeSAaron LI */
142411677aeSAaron LI #ifdef HAVE_LIBCAP_NG
143411677aeSAaron LI #ifdef HAVE_CAP_NG_H
144411677aeSAaron LI #include <cap-ng.h>
145411677aeSAaron LI #else
146411677aeSAaron LI #undef HAVE_LIBCAP_NG
147411677aeSAaron LI #endif /* HAVE_CAP_NG_H */
148411677aeSAaron LI #endif /* HAVE_LIBCAP_NG */
149ea7b4bf5SPeter Avalos
150*ed775ee7SAntonio Huete Jimenez #ifdef __FreeBSD__
151*ed775ee7SAntonio Huete Jimenez #include <sys/sysctl.h>
152*ed775ee7SAntonio Huete Jimenez #endif /* __FreeBSD__ */
153*ed775ee7SAntonio Huete Jimenez
154*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
15541c99275SPeter Avalos #include "netdissect.h"
15641c99275SPeter Avalos #include "interface.h"
15741c99275SPeter Avalos #include "addrtoname.h"
15841c99275SPeter Avalos #include "machdep.h"
15941c99275SPeter Avalos #include "pcap-missing.h"
160411677aeSAaron LI #include "ascii_strcasecmp.h"
16141c99275SPeter Avalos
162411677aeSAaron LI #include "print.h"
163411677aeSAaron LI
164*ed775ee7SAntonio Huete Jimenez #include "fptype.h"
165*ed775ee7SAntonio Huete Jimenez
166411677aeSAaron LI #ifndef PATH_MAX
167411677aeSAaron LI #define PATH_MAX 1024
168ea7b4bf5SPeter Avalos #endif
169ea7b4bf5SPeter Avalos
170*ed775ee7SAntonio Huete Jimenez #if defined(SIGINFO)
1716263709fSPeter Avalos #define SIGNAL_REQ_INFO SIGINFO
172*ed775ee7SAntonio Huete Jimenez #elif defined(SIGUSR1)
1736263709fSPeter Avalos #define SIGNAL_REQ_INFO SIGUSR1
1746263709fSPeter Avalos #endif
1756263709fSPeter Avalos
176*ed775ee7SAntonio Huete Jimenez #if defined(HAVE_PCAP_DUMP_FLUSH) && defined(SIGUSR2)
177*ed775ee7SAntonio Huete Jimenez #define SIGNAL_FLUSH_PCAP SIGUSR2
178*ed775ee7SAntonio Huete Jimenez #endif
179*ed775ee7SAntonio Huete Jimenez
180*ed775ee7SAntonio Huete Jimenez #if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
181411677aeSAaron LI static int Bflag; /* buffer size */
182*ed775ee7SAntonio Huete Jimenez #endif
183*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_DUMP_FTELL64
184*ed775ee7SAntonio Huete Jimenez static int64_t Cflag; /* rotate dump files after this many bytes */
185*ed775ee7SAntonio Huete Jimenez #else
186411677aeSAaron LI static long Cflag; /* rotate dump files after this many bytes */
187*ed775ee7SAntonio Huete Jimenez #endif
188411677aeSAaron LI static int Cflag_count; /* Keep track of which file number we're writing */
189*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS
190411677aeSAaron LI static int Dflag; /* list available devices and exit */
191*ed775ee7SAntonio Huete Jimenez #endif
192*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS_EX
193*ed775ee7SAntonio Huete Jimenez static char *remote_interfaces_source; /* list available devices from this source and exit */
194*ed775ee7SAntonio Huete Jimenez #endif
195*ed775ee7SAntonio Huete Jimenez
196411677aeSAaron LI /*
197411677aeSAaron LI * This is exported because, in some versions of libpcap, if libpcap
198411677aeSAaron LI * is built with optimizer debugging code (which is *NOT* the default
199411677aeSAaron LI * configuration!), the library *imports*(!) a variable named dflag,
200411677aeSAaron LI * under the expectation that tcpdump is exporting it, to govern
201411677aeSAaron LI * how much debugging information to print when optimizing
202411677aeSAaron LI * the generated BPF code.
203411677aeSAaron LI *
204411677aeSAaron LI * This is a horrible hack; newer versions of libpcap don't import
205411677aeSAaron LI * dflag but, instead, *if* built with optimizer debugging code,
206411677aeSAaron LI * *export* a routine to set that flag.
207411677aeSAaron LI */
208*ed775ee7SAntonio Huete Jimenez extern int dflag;
209411677aeSAaron LI int dflag; /* print filter code */
210411677aeSAaron LI static int Gflag; /* rotate dump files after this many seconds */
211411677aeSAaron LI static int Gflag_count; /* number of files created with Gflag rotation */
212411677aeSAaron LI static time_t Gflag_time; /* The last time_t the dump file was rotated. */
21327bfbee1SPeter Avalos static int Lflag; /* list available data link types and exit */
214411677aeSAaron LI static int Iflag; /* rfmon (monitor) mode */
21527bfbee1SPeter Avalos #ifdef HAVE_PCAP_SET_TSTAMP_TYPE
21627bfbee1SPeter Avalos static int Jflag; /* list available time stamp types */
217411677aeSAaron LI static int jflag = -1; /* packet time stamp source */
218*ed775ee7SAntonio Huete Jimenez #endif
219*ed775ee7SAntonio Huete Jimenez static int lflag; /* line-buffered output */
220411677aeSAaron LI static int pflag; /* don't go promiscuous */
221411677aeSAaron LI #ifdef HAVE_PCAP_SETDIRECTION
222411677aeSAaron LI static int Qflag = -1; /* restrict captured packet by send/receive direction */
223411677aeSAaron LI #endif
224*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_DUMP_FLUSH
225411677aeSAaron LI static int Uflag; /* "unbuffered" output of dump files */
226*ed775ee7SAntonio Huete Jimenez #endif
227411677aeSAaron LI static int Wflag; /* recycle output files after this number of files */
228411677aeSAaron LI static int WflagChars;
22927bfbee1SPeter Avalos static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */
230*ed775ee7SAntonio Huete Jimenez static int timeout = 1000; /* default timeout = 1000 ms = 1 s */
231*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
232411677aeSAaron LI static int immediate_mode;
233*ed775ee7SAntonio Huete Jimenez #endif
234*ed775ee7SAntonio Huete Jimenez static int count_mode;
23541c99275SPeter Avalos
23641c99275SPeter Avalos static int infodelay;
23741c99275SPeter Avalos static int infoprint;
23841c99275SPeter Avalos
23941c99275SPeter Avalos char *program_name;
24041c99275SPeter Avalos
241*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_CASPER
242*ed775ee7SAntonio Huete Jimenez cap_channel_t *capdns;
243*ed775ee7SAntonio Huete Jimenez #endif
244*ed775ee7SAntonio Huete Jimenez
24541c99275SPeter Avalos /* Forwards */
246*ed775ee7SAntonio Huete Jimenez static NORETURN void error(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2);
247411677aeSAaron LI static void warning(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2);
248*ed775ee7SAntonio Huete Jimenez static NORETURN void exit_tcpdump(int);
249*ed775ee7SAntonio Huete Jimenez static void (*setsignal (int sig, void (*func)(int)))(int);
250*ed775ee7SAntonio Huete Jimenez static void cleanup(int);
251*ed775ee7SAntonio Huete Jimenez static void child_cleanup(int);
252*ed775ee7SAntonio Huete Jimenez static void print_version(FILE *);
253*ed775ee7SAntonio Huete Jimenez static void print_usage(FILE *);
254*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_SET_TSTAMP_TYPE
255*ed775ee7SAntonio Huete Jimenez static NORETURN void show_tstamp_types_and_exit(pcap_t *, const char *device);
256*ed775ee7SAntonio Huete Jimenez #endif
257*ed775ee7SAntonio Huete Jimenez static NORETURN void show_dlts_and_exit(pcap_t *, const char *device);
258411677aeSAaron LI #ifdef HAVE_PCAP_FINDALLDEVS
259*ed775ee7SAntonio Huete Jimenez static NORETURN void show_devices_and_exit(void);
260*ed775ee7SAntonio Huete Jimenez #endif
261*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS_EX
262*ed775ee7SAntonio Huete Jimenez static NORETURN void show_remote_devices_and_exit(void);
263411677aeSAaron LI #endif
26441c99275SPeter Avalos
26541c99275SPeter Avalos static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
26641c99275SPeter Avalos static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *);
26741c99275SPeter Avalos static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
26841c99275SPeter Avalos static void droproot(const char *, const char *);
26941c99275SPeter Avalos
2706263709fSPeter Avalos #ifdef SIGNAL_REQ_INFO
271*ed775ee7SAntonio Huete Jimenez static void requestinfo(int);
27241c99275SPeter Avalos #endif
27341c99275SPeter Avalos
274*ed775ee7SAntonio Huete Jimenez #ifdef SIGNAL_FLUSH_PCAP
275*ed775ee7SAntonio Huete Jimenez static void flushpcap(int);
27641c99275SPeter Avalos #endif
27741c99275SPeter Avalos
278*ed775ee7SAntonio Huete Jimenez #ifdef _WIN32
279*ed775ee7SAntonio Huete Jimenez static HANDLE timer_handle = INVALID_HANDLE_VALUE;
280*ed775ee7SAntonio Huete Jimenez static void CALLBACK verbose_stats_dump(PVOID param, BOOLEAN timer_fired);
281*ed775ee7SAntonio Huete Jimenez #else /* _WIN32 */
282*ed775ee7SAntonio Huete Jimenez static void verbose_stats_dump(int sig);
283*ed775ee7SAntonio Huete Jimenez #endif /* _WIN32 */
284*ed775ee7SAntonio Huete Jimenez
28541c99275SPeter Avalos static void info(int);
28641c99275SPeter Avalos static u_int packets_captured;
28741c99275SPeter Avalos
288411677aeSAaron LI #ifdef HAVE_PCAP_FINDALLDEVS
289411677aeSAaron LI static const struct tok status_flags[] = {
290411677aeSAaron LI #ifdef PCAP_IF_UP
291411677aeSAaron LI { PCAP_IF_UP, "Up" },
292411677aeSAaron LI #endif
293411677aeSAaron LI #ifdef PCAP_IF_RUNNING
294411677aeSAaron LI { PCAP_IF_RUNNING, "Running" },
295411677aeSAaron LI #endif
296411677aeSAaron LI { PCAP_IF_LOOPBACK, "Loopback" },
297*ed775ee7SAntonio Huete Jimenez #ifdef PCAP_IF_WIRELESS
298*ed775ee7SAntonio Huete Jimenez { PCAP_IF_WIRELESS, "Wireless" },
299*ed775ee7SAntonio Huete Jimenez #endif
300411677aeSAaron LI { 0, NULL }
30141c99275SPeter Avalos };
30241c99275SPeter Avalos #endif
30327bfbee1SPeter Avalos
30441c99275SPeter Avalos static pcap_t *pd;
305*ed775ee7SAntonio Huete Jimenez static pcap_dumper_t *pdd = NULL;
30641c99275SPeter Avalos
30727bfbee1SPeter Avalos static int supports_monitor_mode;
30827bfbee1SPeter Avalos
30941c99275SPeter Avalos extern int optind;
31041c99275SPeter Avalos extern int opterr;
31141c99275SPeter Avalos extern char *optarg;
31241c99275SPeter Avalos
31341c99275SPeter Avalos struct dump_info {
31441c99275SPeter Avalos char *WFileName;
315ea7b4bf5SPeter Avalos char *CurrentFileName;
31641c99275SPeter Avalos pcap_t *pd;
317*ed775ee7SAntonio Huete Jimenez pcap_dumper_t *pdd;
318*ed775ee7SAntonio Huete Jimenez netdissect_options *ndo;
319411677aeSAaron LI #ifdef HAVE_CAPSICUM
320411677aeSAaron LI int dirfd;
321411677aeSAaron LI #endif
32241c99275SPeter Avalos };
32341c99275SPeter Avalos
324411677aeSAaron LI #if defined(HAVE_PCAP_SET_PARSER_DEBUG)
325411677aeSAaron LI /*
326411677aeSAaron LI * We have pcap_set_parser_debug() in libpcap; declare it (it's not declared
327411677aeSAaron LI * by any libpcap header, because it's a special hack, only available if
328411677aeSAaron LI * libpcap was configured to include it, and only intended for use by
329411677aeSAaron LI * libpcap developers trying to debug the parser for filter expressions).
330411677aeSAaron LI */
331411677aeSAaron LI #ifdef _WIN32
332411677aeSAaron LI __declspec(dllimport)
333411677aeSAaron LI #else /* _WIN32 */
334411677aeSAaron LI extern
335411677aeSAaron LI #endif /* _WIN32 */
336411677aeSAaron LI void pcap_set_parser_debug(int);
337411677aeSAaron LI #elif defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG)
338411677aeSAaron LI /*
339411677aeSAaron LI * We don't have pcap_set_parser_debug() in libpcap, but we do have
340411677aeSAaron LI * pcap_debug or yydebug. Make a local version of pcap_set_parser_debug()
341411677aeSAaron LI * to set the flag, and define HAVE_PCAP_SET_PARSER_DEBUG.
342411677aeSAaron LI */
343411677aeSAaron LI static void
pcap_set_parser_debug(int value)344411677aeSAaron LI pcap_set_parser_debug(int value)
345411677aeSAaron LI {
346411677aeSAaron LI #ifdef HAVE_PCAP_DEBUG
347411677aeSAaron LI extern int pcap_debug;
348411677aeSAaron LI
349411677aeSAaron LI pcap_debug = value;
350411677aeSAaron LI #else /* HAVE_PCAP_DEBUG */
351411677aeSAaron LI extern int yydebug;
352411677aeSAaron LI
353411677aeSAaron LI yydebug = value;
354411677aeSAaron LI #endif /* HAVE_PCAP_DEBUG */
355411677aeSAaron LI }
356411677aeSAaron LI
357411677aeSAaron LI #define HAVE_PCAP_SET_PARSER_DEBUG
358411677aeSAaron LI #endif
359411677aeSAaron LI
360411677aeSAaron LI #if defined(HAVE_PCAP_SET_OPTIMIZER_DEBUG)
361411677aeSAaron LI /*
362411677aeSAaron LI * We have pcap_set_optimizer_debug() in libpcap; declare it (it's not declared
363411677aeSAaron LI * by any libpcap header, because it's a special hack, only available if
364411677aeSAaron LI * libpcap was configured to include it, and only intended for use by
365411677aeSAaron LI * libpcap developers trying to debug the optimizer for filter expressions).
366411677aeSAaron LI */
367411677aeSAaron LI #ifdef _WIN32
368411677aeSAaron LI __declspec(dllimport)
369411677aeSAaron LI #else /* _WIN32 */
370411677aeSAaron LI extern
371411677aeSAaron LI #endif /* _WIN32 */
372411677aeSAaron LI void pcap_set_optimizer_debug(int);
373411677aeSAaron LI #endif
374411677aeSAaron LI
375411677aeSAaron LI /* VARARGS */
376411677aeSAaron LI static void
error(const char * fmt,...)377411677aeSAaron LI error(const char *fmt, ...)
378411677aeSAaron LI {
379411677aeSAaron LI va_list ap;
380411677aeSAaron LI
381411677aeSAaron LI (void)fprintf(stderr, "%s: ", program_name);
382411677aeSAaron LI va_start(ap, fmt);
383411677aeSAaron LI (void)vfprintf(stderr, fmt, ap);
384411677aeSAaron LI va_end(ap);
385411677aeSAaron LI if (*fmt) {
386411677aeSAaron LI fmt += strlen(fmt);
387411677aeSAaron LI if (fmt[-1] != '\n')
388411677aeSAaron LI (void)fputc('\n', stderr);
389411677aeSAaron LI }
390*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_ERR_HOST_PROGRAM);
391411677aeSAaron LI /* NOTREACHED */
392411677aeSAaron LI }
393411677aeSAaron LI
394411677aeSAaron LI /* VARARGS */
395411677aeSAaron LI static void
warning(const char * fmt,...)396411677aeSAaron LI warning(const char *fmt, ...)
397411677aeSAaron LI {
398411677aeSAaron LI va_list ap;
399411677aeSAaron LI
400411677aeSAaron LI (void)fprintf(stderr, "%s: WARNING: ", program_name);
401411677aeSAaron LI va_start(ap, fmt);
402411677aeSAaron LI (void)vfprintf(stderr, fmt, ap);
403411677aeSAaron LI va_end(ap);
404411677aeSAaron LI if (*fmt) {
405411677aeSAaron LI fmt += strlen(fmt);
406411677aeSAaron LI if (fmt[-1] != '\n')
407411677aeSAaron LI (void)fputc('\n', stderr);
408411677aeSAaron LI }
409411677aeSAaron LI }
410411677aeSAaron LI
411411677aeSAaron LI static void
exit_tcpdump(int status)412411677aeSAaron LI exit_tcpdump(int status)
413411677aeSAaron LI {
414411677aeSAaron LI nd_cleanup();
415411677aeSAaron LI exit(status);
416411677aeSAaron LI }
417411677aeSAaron LI
41827bfbee1SPeter Avalos #ifdef HAVE_PCAP_SET_TSTAMP_TYPE
41941c99275SPeter Avalos static void
show_tstamp_types_and_exit(pcap_t * pc,const char * device)420411677aeSAaron LI show_tstamp_types_and_exit(pcap_t *pc, const char *device)
42127bfbee1SPeter Avalos {
42227bfbee1SPeter Avalos int n_tstamp_types;
42327bfbee1SPeter Avalos int *tstamp_types = 0;
42427bfbee1SPeter Avalos const char *tstamp_type_name;
42527bfbee1SPeter Avalos int i;
42627bfbee1SPeter Avalos
427411677aeSAaron LI n_tstamp_types = pcap_list_tstamp_types(pc, &tstamp_types);
42827bfbee1SPeter Avalos if (n_tstamp_types < 0)
429411677aeSAaron LI error("%s", pcap_geterr(pc));
43027bfbee1SPeter Avalos
43127bfbee1SPeter Avalos if (n_tstamp_types == 0) {
43227bfbee1SPeter Avalos fprintf(stderr, "Time stamp type cannot be set for %s\n",
43327bfbee1SPeter Avalos device);
434*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_SUCCESS);
43527bfbee1SPeter Avalos }
43627bfbee1SPeter Avalos fprintf(stderr, "Time stamp types for %s (use option -j to set):\n",
43727bfbee1SPeter Avalos device);
43827bfbee1SPeter Avalos for (i = 0; i < n_tstamp_types; i++) {
43927bfbee1SPeter Avalos tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]);
44027bfbee1SPeter Avalos if (tstamp_type_name != NULL) {
44127bfbee1SPeter Avalos (void) fprintf(stderr, " %s (%s)\n", tstamp_type_name,
44227bfbee1SPeter Avalos pcap_tstamp_type_val_to_description(tstamp_types[i]));
44327bfbee1SPeter Avalos } else {
44427bfbee1SPeter Avalos (void) fprintf(stderr, " %d\n", tstamp_types[i]);
44527bfbee1SPeter Avalos }
44627bfbee1SPeter Avalos }
44727bfbee1SPeter Avalos pcap_free_tstamp_types(tstamp_types);
448*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_SUCCESS);
44927bfbee1SPeter Avalos }
45027bfbee1SPeter Avalos #endif
45127bfbee1SPeter Avalos
45227bfbee1SPeter Avalos static void
show_dlts_and_exit(pcap_t * pc,const char * device)453411677aeSAaron LI show_dlts_and_exit(pcap_t *pc, const char *device)
45441c99275SPeter Avalos {
455411677aeSAaron LI int n_dlts, i;
45641c99275SPeter Avalos int *dlts = 0;
45741c99275SPeter Avalos const char *dlt_name;
45841c99275SPeter Avalos
459411677aeSAaron LI n_dlts = pcap_list_datalinks(pc, &dlts);
46041c99275SPeter Avalos if (n_dlts < 0)
461411677aeSAaron LI error("%s", pcap_geterr(pc));
46241c99275SPeter Avalos else if (n_dlts == 0 || !dlts)
46341c99275SPeter Avalos error("No data link types.");
46441c99275SPeter Avalos
46527bfbee1SPeter Avalos /*
46627bfbee1SPeter Avalos * If the interface is known to support monitor mode, indicate
46727bfbee1SPeter Avalos * whether these are the data link types available when not in
46827bfbee1SPeter Avalos * monitor mode, if -I wasn't specified, or when in monitor mode,
46927bfbee1SPeter Avalos * when -I was specified (the link-layer types available in
47027bfbee1SPeter Avalos * monitor mode might be different from the ones available when
47127bfbee1SPeter Avalos * not in monitor mode).
47227bfbee1SPeter Avalos */
47327bfbee1SPeter Avalos if (supports_monitor_mode)
47427bfbee1SPeter Avalos (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n",
47527bfbee1SPeter Avalos device,
47627bfbee1SPeter Avalos Iflag ? "when in monitor mode" : "when not in monitor mode");
47727bfbee1SPeter Avalos else
47827bfbee1SPeter Avalos (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n",
47927bfbee1SPeter Avalos device);
48041c99275SPeter Avalos
481411677aeSAaron LI for (i = 0; i < n_dlts; i++) {
482411677aeSAaron LI dlt_name = pcap_datalink_val_to_name(dlts[i]);
48341c99275SPeter Avalos if (dlt_name != NULL) {
48441c99275SPeter Avalos (void) fprintf(stderr, " %s (%s)", dlt_name,
485411677aeSAaron LI pcap_datalink_val_to_description(dlts[i]));
48641c99275SPeter Avalos
48741c99275SPeter Avalos /*
48841c99275SPeter Avalos * OK, does tcpdump handle that type?
48941c99275SPeter Avalos */
490411677aeSAaron LI if (!has_printer(dlts[i]))
491ea7b4bf5SPeter Avalos (void) fprintf(stderr, " (printing not supported)");
49227bfbee1SPeter Avalos fprintf(stderr, "\n");
49341c99275SPeter Avalos } else {
494ea7b4bf5SPeter Avalos (void) fprintf(stderr, " DLT %d (printing not supported)\n",
495411677aeSAaron LI dlts[i]);
49641c99275SPeter Avalos }
49741c99275SPeter Avalos }
498411677aeSAaron LI #ifdef HAVE_PCAP_FREE_DATALINKS
49927bfbee1SPeter Avalos pcap_free_datalinks(dlts);
500411677aeSAaron LI #endif
501*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_SUCCESS);
50241c99275SPeter Avalos }
50341c99275SPeter Avalos
504411677aeSAaron LI #ifdef HAVE_PCAP_FINDALLDEVS
505411677aeSAaron LI static void
show_devices_and_exit(void)506411677aeSAaron LI show_devices_and_exit(void)
507411677aeSAaron LI {
508411677aeSAaron LI pcap_if_t *dev, *devlist;
509411677aeSAaron LI char ebuf[PCAP_ERRBUF_SIZE];
510411677aeSAaron LI int i;
511411677aeSAaron LI
512411677aeSAaron LI if (pcap_findalldevs(&devlist, ebuf) < 0)
513411677aeSAaron LI error("%s", ebuf);
514411677aeSAaron LI for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) {
515411677aeSAaron LI printf("%d.%s", i+1, dev->name);
516411677aeSAaron LI if (dev->description != NULL)
517411677aeSAaron LI printf(" (%s)", dev->description);
518*ed775ee7SAntonio Huete Jimenez if (dev->flags != 0) {
519*ed775ee7SAntonio Huete Jimenez printf(" [");
520*ed775ee7SAntonio Huete Jimenez printf("%s", bittok2str(status_flags, "none", dev->flags));
521*ed775ee7SAntonio Huete Jimenez #ifdef PCAP_IF_WIRELESS
522*ed775ee7SAntonio Huete Jimenez if (dev->flags & PCAP_IF_WIRELESS) {
523*ed775ee7SAntonio Huete Jimenez switch (dev->flags & PCAP_IF_CONNECTION_STATUS) {
524*ed775ee7SAntonio Huete Jimenez
525*ed775ee7SAntonio Huete Jimenez case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
526*ed775ee7SAntonio Huete Jimenez printf(", Association status unknown");
527*ed775ee7SAntonio Huete Jimenez break;
528*ed775ee7SAntonio Huete Jimenez
529*ed775ee7SAntonio Huete Jimenez case PCAP_IF_CONNECTION_STATUS_CONNECTED:
530*ed775ee7SAntonio Huete Jimenez printf(", Associated");
531*ed775ee7SAntonio Huete Jimenez break;
532*ed775ee7SAntonio Huete Jimenez
533*ed775ee7SAntonio Huete Jimenez case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
534*ed775ee7SAntonio Huete Jimenez printf(", Not associated");
535*ed775ee7SAntonio Huete Jimenez break;
536*ed775ee7SAntonio Huete Jimenez
537*ed775ee7SAntonio Huete Jimenez case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
538*ed775ee7SAntonio Huete Jimenez break;
539*ed775ee7SAntonio Huete Jimenez }
540*ed775ee7SAntonio Huete Jimenez } else {
541*ed775ee7SAntonio Huete Jimenez switch (dev->flags & PCAP_IF_CONNECTION_STATUS) {
542*ed775ee7SAntonio Huete Jimenez
543*ed775ee7SAntonio Huete Jimenez case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
544*ed775ee7SAntonio Huete Jimenez printf(", Connection status unknown");
545*ed775ee7SAntonio Huete Jimenez break;
546*ed775ee7SAntonio Huete Jimenez
547*ed775ee7SAntonio Huete Jimenez case PCAP_IF_CONNECTION_STATUS_CONNECTED:
548*ed775ee7SAntonio Huete Jimenez printf(", Connected");
549*ed775ee7SAntonio Huete Jimenez break;
550*ed775ee7SAntonio Huete Jimenez
551*ed775ee7SAntonio Huete Jimenez case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
552*ed775ee7SAntonio Huete Jimenez printf(", Disconnected");
553*ed775ee7SAntonio Huete Jimenez break;
554*ed775ee7SAntonio Huete Jimenez
555*ed775ee7SAntonio Huete Jimenez case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
556*ed775ee7SAntonio Huete Jimenez break;
557*ed775ee7SAntonio Huete Jimenez }
558*ed775ee7SAntonio Huete Jimenez }
559*ed775ee7SAntonio Huete Jimenez #endif
560*ed775ee7SAntonio Huete Jimenez printf("]");
561*ed775ee7SAntonio Huete Jimenez }
562*ed775ee7SAntonio Huete Jimenez printf("\n");
563*ed775ee7SAntonio Huete Jimenez }
564*ed775ee7SAntonio Huete Jimenez pcap_freealldevs(devlist);
565*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_SUCCESS);
566*ed775ee7SAntonio Huete Jimenez }
567*ed775ee7SAntonio Huete Jimenez #endif /* HAVE_PCAP_FINDALLDEVS */
568*ed775ee7SAntonio Huete Jimenez
569*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS_EX
570*ed775ee7SAntonio Huete Jimenez static void
show_remote_devices_and_exit(void)571*ed775ee7SAntonio Huete Jimenez show_remote_devices_and_exit(void)
572*ed775ee7SAntonio Huete Jimenez {
573*ed775ee7SAntonio Huete Jimenez pcap_if_t *dev, *devlist;
574*ed775ee7SAntonio Huete Jimenez char ebuf[PCAP_ERRBUF_SIZE];
575*ed775ee7SAntonio Huete Jimenez int i;
576*ed775ee7SAntonio Huete Jimenez
577*ed775ee7SAntonio Huete Jimenez if (pcap_findalldevs_ex(remote_interfaces_source, NULL, &devlist,
578*ed775ee7SAntonio Huete Jimenez ebuf) < 0)
579*ed775ee7SAntonio Huete Jimenez error("%s", ebuf);
580*ed775ee7SAntonio Huete Jimenez for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) {
581*ed775ee7SAntonio Huete Jimenez printf("%d.%s", i+1, dev->name);
582*ed775ee7SAntonio Huete Jimenez if (dev->description != NULL)
583*ed775ee7SAntonio Huete Jimenez printf(" (%s)", dev->description);
584411677aeSAaron LI if (dev->flags != 0)
585411677aeSAaron LI printf(" [%s]", bittok2str(status_flags, "none", dev->flags));
586411677aeSAaron LI printf("\n");
587411677aeSAaron LI }
588411677aeSAaron LI pcap_freealldevs(devlist);
589*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_SUCCESS);
590411677aeSAaron LI }
591411677aeSAaron LI #endif /* HAVE_PCAP_FINDALLDEVS */
592411677aeSAaron LI
593411677aeSAaron LI /*
594411677aeSAaron LI * Short options.
595411677aeSAaron LI *
596411677aeSAaron LI * Note that there we use all letters for short options except for g, k,
597411677aeSAaron LI * o, and P, and those are used by other versions of tcpdump, and we should
598411677aeSAaron LI * only use them for the same purposes that the other versions of tcpdump
599411677aeSAaron LI * use them:
600411677aeSAaron LI *
601*ed775ee7SAntonio Huete Jimenez * macOS tcpdump uses -g to force non--v output for IP to be on one
602411677aeSAaron LI * line, making it more "g"repable;
603411677aeSAaron LI *
604*ed775ee7SAntonio Huete Jimenez * macOS tcpdump uses -k to specify that packet comments in pcapng files
605411677aeSAaron LI * should be printed;
606411677aeSAaron LI *
607411677aeSAaron LI * OpenBSD tcpdump uses -o to indicate that OS fingerprinting should be done
608411677aeSAaron LI * for hosts sending TCP SYN packets;
609411677aeSAaron LI *
610*ed775ee7SAntonio Huete Jimenez * macOS tcpdump uses -P to indicate that -w should write pcapng rather
611411677aeSAaron LI * than pcap files.
612411677aeSAaron LI *
613*ed775ee7SAntonio Huete Jimenez * macOS tcpdump also uses -Q to specify expressions that match packet
614411677aeSAaron LI * metadata, including but not limited to the packet direction.
615411677aeSAaron LI * The expression syntax is different from a simple "in|out|inout",
616*ed775ee7SAntonio Huete Jimenez * and those expressions aren't accepted by macOS tcpdump, but the
617411677aeSAaron LI * equivalents would be "in" = "dir=in", "out" = "dir=out", and
618411677aeSAaron LI * "inout" = "dir=in or dir=out", and the parser could conceivably
619411677aeSAaron LI * special-case "in", "out", and "inout" as expressions for backwards
620411677aeSAaron LI * compatibility, so all is not (yet) lost.
621411677aeSAaron LI */
622411677aeSAaron LI
62341c99275SPeter Avalos /*
62441c99275SPeter Avalos * Set up flags that might or might not be supported depending on the
62541c99275SPeter Avalos * version of libpcap we're using.
62641c99275SPeter Avalos */
627411677aeSAaron LI #if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
62841c99275SPeter Avalos #define B_FLAG "B:"
62941c99275SPeter Avalos #define B_FLAG_USAGE " [ -B size ]"
630411677aeSAaron LI #else /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */
63141c99275SPeter Avalos #define B_FLAG
63241c99275SPeter Avalos #define B_FLAG_USAGE
633411677aeSAaron LI #endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */
634ea7b4bf5SPeter Avalos
635*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS
636*ed775ee7SAntonio Huete Jimenez #define D_FLAG "D"
637*ed775ee7SAntonio Huete Jimenez #else
638*ed775ee7SAntonio Huete Jimenez #define D_FLAG
639*ed775ee7SAntonio Huete Jimenez #endif
640*ed775ee7SAntonio Huete Jimenez
641ea7b4bf5SPeter Avalos #ifdef HAVE_PCAP_CREATE
642ea7b4bf5SPeter Avalos #define I_FLAG "I"
643ea7b4bf5SPeter Avalos #else /* HAVE_PCAP_CREATE */
644ea7b4bf5SPeter Avalos #define I_FLAG
645ea7b4bf5SPeter Avalos #endif /* HAVE_PCAP_CREATE */
64641c99275SPeter Avalos
64727bfbee1SPeter Avalos #ifdef HAVE_PCAP_SET_TSTAMP_TYPE
64827bfbee1SPeter Avalos #define j_FLAG "j:"
64927bfbee1SPeter Avalos #define j_FLAG_USAGE " [ -j tstamptype ]"
65027bfbee1SPeter Avalos #define J_FLAG "J"
65127bfbee1SPeter Avalos #else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */
65227bfbee1SPeter Avalos #define j_FLAG
65327bfbee1SPeter Avalos #define j_FLAG_USAGE
65427bfbee1SPeter Avalos #define J_FLAG
65527bfbee1SPeter Avalos #endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */
65627bfbee1SPeter Avalos
657*ed775ee7SAntonio Huete Jimenez #ifdef USE_LIBSMI
658*ed775ee7SAntonio Huete Jimenez #define m_FLAG_USAGE "[ -m module ] ..."
659*ed775ee7SAntonio Huete Jimenez #endif
660*ed775ee7SAntonio Huete Jimenez
661*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_SETDIRECTION
662*ed775ee7SAntonio Huete Jimenez #define Q_FLAG "Q:"
663*ed775ee7SAntonio Huete Jimenez #define Q_FLAG_USAGE " [ -Q in|out|inout ]"
66441c99275SPeter Avalos #else
665*ed775ee7SAntonio Huete Jimenez #define Q_FLAG
666*ed775ee7SAntonio Huete Jimenez #define Q_FLAG_USAGE
66741c99275SPeter Avalos #endif
66841c99275SPeter Avalos
66941c99275SPeter Avalos #ifdef HAVE_PCAP_DUMP_FLUSH
67041c99275SPeter Avalos #define U_FLAG "U"
67141c99275SPeter Avalos #else
67241c99275SPeter Avalos #define U_FLAG
67341c99275SPeter Avalos #endif
67441c99275SPeter Avalos
675411677aeSAaron LI #define SHORTOPTS "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:s:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#"
676411677aeSAaron LI
677411677aeSAaron LI /*
678411677aeSAaron LI * Long options.
679411677aeSAaron LI *
680411677aeSAaron LI * We do not currently have long options corresponding to all short
681411677aeSAaron LI * options; we should probably pick appropriate option names for them.
682411677aeSAaron LI *
683411677aeSAaron LI * However, the short options where the number of times the option is
684411677aeSAaron LI * specified matters, such as -v and -d and -t, should probably not
685411677aeSAaron LI * just map to a long option, as saying
686411677aeSAaron LI *
687411677aeSAaron LI * tcpdump --verbose --verbose
688411677aeSAaron LI *
689411677aeSAaron LI * doesn't make sense; it should be --verbosity={N} or something such
690411677aeSAaron LI * as that.
691411677aeSAaron LI *
692411677aeSAaron LI * For long options with no corresponding short options, we define values
693411677aeSAaron LI * outside the range of ASCII graphic characters, make that the last
694411677aeSAaron LI * component of the entry for the long option, and have a case for that
695411677aeSAaron LI * option in the switch statement.
696411677aeSAaron LI */
697411677aeSAaron LI #define OPTION_VERSION 128
698411677aeSAaron LI #define OPTION_TSTAMP_PRECISION 129
699411677aeSAaron LI #define OPTION_IMMEDIATE_MODE 130
700*ed775ee7SAntonio Huete Jimenez #define OPTION_PRINT 131
701*ed775ee7SAntonio Huete Jimenez #define OPTION_LIST_REMOTE_INTERFACES 132
702*ed775ee7SAntonio Huete Jimenez #define OPTION_TSTAMP_MICRO 133
703*ed775ee7SAntonio Huete Jimenez #define OPTION_TSTAMP_NANO 134
704*ed775ee7SAntonio Huete Jimenez #define OPTION_FP_TYPE 135
705*ed775ee7SAntonio Huete Jimenez #define OPTION_COUNT 136
706411677aeSAaron LI
707411677aeSAaron LI static const struct option longopts[] = {
708411677aeSAaron LI #if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
709411677aeSAaron LI { "buffer-size", required_argument, NULL, 'B' },
710411677aeSAaron LI #endif
711411677aeSAaron LI { "list-interfaces", no_argument, NULL, 'D' },
712*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS_EX
713*ed775ee7SAntonio Huete Jimenez { "list-remote-interfaces", required_argument, NULL, OPTION_LIST_REMOTE_INTERFACES },
714*ed775ee7SAntonio Huete Jimenez #endif
715411677aeSAaron LI { "help", no_argument, NULL, 'h' },
716411677aeSAaron LI { "interface", required_argument, NULL, 'i' },
717411677aeSAaron LI #ifdef HAVE_PCAP_CREATE
718411677aeSAaron LI { "monitor-mode", no_argument, NULL, 'I' },
719411677aeSAaron LI #endif
720411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_TYPE
721411677aeSAaron LI { "time-stamp-type", required_argument, NULL, 'j' },
722411677aeSAaron LI { "list-time-stamp-types", no_argument, NULL, 'J' },
723411677aeSAaron LI #endif
724411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
725*ed775ee7SAntonio Huete Jimenez { "micro", no_argument, NULL, OPTION_TSTAMP_MICRO},
726*ed775ee7SAntonio Huete Jimenez { "nano", no_argument, NULL, OPTION_TSTAMP_NANO},
727411677aeSAaron LI { "time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION},
728411677aeSAaron LI #endif
729411677aeSAaron LI { "dont-verify-checksums", no_argument, NULL, 'K' },
730411677aeSAaron LI { "list-data-link-types", no_argument, NULL, 'L' },
731411677aeSAaron LI { "no-optimize", no_argument, NULL, 'O' },
732411677aeSAaron LI { "no-promiscuous-mode", no_argument, NULL, 'p' },
733411677aeSAaron LI #ifdef HAVE_PCAP_SETDIRECTION
734411677aeSAaron LI { "direction", required_argument, NULL, 'Q' },
735411677aeSAaron LI #endif
736411677aeSAaron LI { "snapshot-length", required_argument, NULL, 's' },
737411677aeSAaron LI { "absolute-tcp-sequence-numbers", no_argument, NULL, 'S' },
738411677aeSAaron LI #ifdef HAVE_PCAP_DUMP_FLUSH
739411677aeSAaron LI { "packet-buffered", no_argument, NULL, 'U' },
740411677aeSAaron LI #endif
741411677aeSAaron LI { "linktype", required_argument, NULL, 'y' },
742411677aeSAaron LI #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
743411677aeSAaron LI { "immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE },
744411677aeSAaron LI #endif
745411677aeSAaron LI #ifdef HAVE_PCAP_SET_PARSER_DEBUG
746411677aeSAaron LI { "debug-filter-parser", no_argument, NULL, 'Y' },
747411677aeSAaron LI #endif
748411677aeSAaron LI { "relinquish-privileges", required_argument, NULL, 'Z' },
749*ed775ee7SAntonio Huete Jimenez { "count", no_argument, NULL, OPTION_COUNT },
750*ed775ee7SAntonio Huete Jimenez { "fp-type", no_argument, NULL, OPTION_FP_TYPE },
751411677aeSAaron LI { "number", no_argument, NULL, '#' },
752*ed775ee7SAntonio Huete Jimenez { "print", no_argument, NULL, OPTION_PRINT },
753411677aeSAaron LI { "version", no_argument, NULL, OPTION_VERSION },
754411677aeSAaron LI { NULL, 0, NULL, 0 }
755411677aeSAaron LI };
756411677aeSAaron LI
757*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS_EX
758*ed775ee7SAntonio Huete Jimenez #define LIST_REMOTE_INTERFACES_USAGE "[ --list-remote-interfaces remote-source ]"
759*ed775ee7SAntonio Huete Jimenez #else
760*ed775ee7SAntonio Huete Jimenez #define LIST_REMOTE_INTERFACES_USAGE
761*ed775ee7SAntonio Huete Jimenez #endif
762*ed775ee7SAntonio Huete Jimenez
763*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
764*ed775ee7SAntonio Huete Jimenez #define IMMEDIATE_MODE_USAGE " [ --immediate-mode ]"
765*ed775ee7SAntonio Huete Jimenez #else
766*ed775ee7SAntonio Huete Jimenez #define IMMEDIATE_MODE_USAGE ""
767*ed775ee7SAntonio Huete Jimenez #endif
768*ed775ee7SAntonio Huete Jimenez
769411677aeSAaron LI #ifndef _WIN32
77041c99275SPeter Avalos /* Drop root privileges and chroot if necessary */
77141c99275SPeter Avalos static void
droproot(const char * username,const char * chroot_dir)77241c99275SPeter Avalos droproot(const char *username, const char *chroot_dir)
77341c99275SPeter Avalos {
77441c99275SPeter Avalos struct passwd *pw = NULL;
77541c99275SPeter Avalos
776*ed775ee7SAntonio Huete Jimenez if (chroot_dir && !username)
777*ed775ee7SAntonio Huete Jimenez error("Chroot without dropping root is insecure");
77841c99275SPeter Avalos
77941c99275SPeter Avalos pw = getpwnam(username);
78041c99275SPeter Avalos if (pw) {
78141c99275SPeter Avalos if (chroot_dir) {
782*ed775ee7SAntonio Huete Jimenez if (chroot(chroot_dir) != 0 || chdir ("/") != 0)
783*ed775ee7SAntonio Huete Jimenez error("Couldn't chroot/chdir to '%.64s': %s",
784*ed775ee7SAntonio Huete Jimenez chroot_dir, pcap_strerror(errno));
78541c99275SPeter Avalos }
786411677aeSAaron LI #ifdef HAVE_LIBCAP_NG
787411677aeSAaron LI {
788411677aeSAaron LI int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG);
789411677aeSAaron LI if (ret < 0)
790411677aeSAaron LI error("capng_change_id(): return %d\n", ret);
791411677aeSAaron LI else
792411677aeSAaron LI fprintf(stderr, "dropped privs to %s\n", username);
793411677aeSAaron LI }
794411677aeSAaron LI #else
79541c99275SPeter Avalos if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
796*ed775ee7SAntonio Huete Jimenez setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0)
797*ed775ee7SAntonio Huete Jimenez error("Couldn't change to '%.32s' uid=%lu gid=%lu: %s",
798*ed775ee7SAntonio Huete Jimenez username,
79941c99275SPeter Avalos (unsigned long)pw->pw_uid,
80041c99275SPeter Avalos (unsigned long)pw->pw_gid,
80141c99275SPeter Avalos pcap_strerror(errno));
80241c99275SPeter Avalos else {
803411677aeSAaron LI fprintf(stderr, "dropped privs to %s\n", username);
80441c99275SPeter Avalos }
805411677aeSAaron LI #endif /* HAVE_LIBCAP_NG */
806*ed775ee7SAntonio Huete Jimenez } else
807*ed775ee7SAntonio Huete Jimenez error("Couldn't find user '%.32s'", username);
808411677aeSAaron LI #ifdef HAVE_LIBCAP_NG
809411677aeSAaron LI /* We don't need CAP_SETUID, CAP_SETGID and CAP_SYS_CHROOT any more. */
810*ed775ee7SAntonio Huete Jimenez DIAG_OFF_CLANG(assign-enum)
811411677aeSAaron LI capng_updatev(
812411677aeSAaron LI CAPNG_DROP,
813411677aeSAaron LI CAPNG_EFFECTIVE | CAPNG_PERMITTED,
814411677aeSAaron LI CAP_SETUID,
815411677aeSAaron LI CAP_SETGID,
816411677aeSAaron LI CAP_SYS_CHROOT,
817411677aeSAaron LI -1);
818*ed775ee7SAntonio Huete Jimenez DIAG_ON_CLANG(assign-enum)
819411677aeSAaron LI capng_apply(CAPNG_SELECT_BOTH);
820411677aeSAaron LI #endif /* HAVE_LIBCAP_NG */
821411677aeSAaron LI
822411677aeSAaron LI }
823411677aeSAaron LI #endif /* _WIN32 */
82441c99275SPeter Avalos
82541c99275SPeter Avalos static int
getWflagChars(int x)82641c99275SPeter Avalos getWflagChars(int x)
82741c99275SPeter Avalos {
82841c99275SPeter Avalos int c = 0;
82941c99275SPeter Avalos
83041c99275SPeter Avalos x -= 1;
83141c99275SPeter Avalos while (x > 0) {
83241c99275SPeter Avalos c += 1;
83341c99275SPeter Avalos x /= 10;
83441c99275SPeter Avalos }
83541c99275SPeter Avalos
83641c99275SPeter Avalos return c;
83741c99275SPeter Avalos }
83841c99275SPeter Avalos
83941c99275SPeter Avalos
84041c99275SPeter Avalos static void
MakeFilename(char * buffer,char * orig_name,int cnt,int max_chars)84141c99275SPeter Avalos MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
84241c99275SPeter Avalos {
843411677aeSAaron LI char *filename = malloc(PATH_MAX + 1);
844411677aeSAaron LI if (filename == NULL)
845*ed775ee7SAntonio Huete Jimenez error("%s: malloc", __func__);
846ea7b4bf5SPeter Avalos
847ea7b4bf5SPeter Avalos /* Process with strftime if Gflag is set. */
848ea7b4bf5SPeter Avalos if (Gflag != 0) {
849ea7b4bf5SPeter Avalos struct tm *local_tm;
850ea7b4bf5SPeter Avalos
851ea7b4bf5SPeter Avalos /* Convert Gflag_time to a usable format */
852ea7b4bf5SPeter Avalos if ((local_tm = localtime(&Gflag_time)) == NULL) {
853*ed775ee7SAntonio Huete Jimenez error("%s: localtime", __func__);
854ea7b4bf5SPeter Avalos }
855ea7b4bf5SPeter Avalos
856ea7b4bf5SPeter Avalos /* There's no good way to detect an error in strftime since a return
857ea7b4bf5SPeter Avalos * value of 0 isn't necessarily failure.
858ea7b4bf5SPeter Avalos */
859411677aeSAaron LI strftime(filename, PATH_MAX, orig_name, local_tm);
860ea7b4bf5SPeter Avalos } else {
861411677aeSAaron LI strncpy(filename, orig_name, PATH_MAX);
862ea7b4bf5SPeter Avalos }
863ea7b4bf5SPeter Avalos
86441c99275SPeter Avalos if (cnt == 0 && max_chars == 0)
865411677aeSAaron LI strncpy(buffer, filename, PATH_MAX + 1);
86641c99275SPeter Avalos else
867411677aeSAaron LI if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX)
868ea7b4bf5SPeter Avalos /* Report an error if the filename is too large */
869411677aeSAaron LI error("too many output files or filename is too long (> %d)", PATH_MAX);
870ea7b4bf5SPeter Avalos free(filename);
87141c99275SPeter Avalos }
87241c99275SPeter Avalos
873411677aeSAaron LI static char *
get_next_file(FILE * VFile,char * ptr)874411677aeSAaron LI get_next_file(FILE *VFile, char *ptr)
87541c99275SPeter Avalos {
876411677aeSAaron LI char *ret;
877411677aeSAaron LI size_t len;
87841c99275SPeter Avalos
879411677aeSAaron LI ret = fgets(ptr, PATH_MAX, VFile);
880411677aeSAaron LI if (!ret)
881411677aeSAaron LI return NULL;
88241c99275SPeter Avalos
883411677aeSAaron LI len = strlen (ptr);
884411677aeSAaron LI if (len > 0 && ptr[len - 1] == '\n')
885411677aeSAaron LI ptr[len - 1] = '\0';
88641c99275SPeter Avalos
88741c99275SPeter Avalos return ret;
88841c99275SPeter Avalos }
88941c99275SPeter Avalos
890*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_CASPER
891*ed775ee7SAntonio Huete Jimenez static cap_channel_t *
capdns_setup(void)892*ed775ee7SAntonio Huete Jimenez capdns_setup(void)
893*ed775ee7SAntonio Huete Jimenez {
894*ed775ee7SAntonio Huete Jimenez cap_channel_t *capcas, *capdnsloc;
895*ed775ee7SAntonio Huete Jimenez const char *types[1];
896*ed775ee7SAntonio Huete Jimenez int families[2];
897*ed775ee7SAntonio Huete Jimenez
898*ed775ee7SAntonio Huete Jimenez capcas = cap_init();
899*ed775ee7SAntonio Huete Jimenez if (capcas == NULL)
900*ed775ee7SAntonio Huete Jimenez error("unable to create casper process");
901*ed775ee7SAntonio Huete Jimenez capdnsloc = cap_service_open(capcas, "system.dns");
902*ed775ee7SAntonio Huete Jimenez /* Casper capability no longer needed. */
903*ed775ee7SAntonio Huete Jimenez cap_close(capcas);
904*ed775ee7SAntonio Huete Jimenez if (capdnsloc == NULL)
905*ed775ee7SAntonio Huete Jimenez error("unable to open system.dns service");
906*ed775ee7SAntonio Huete Jimenez /* Limit system.dns to reverse DNS lookups. */
907*ed775ee7SAntonio Huete Jimenez types[0] = "ADDR";
908*ed775ee7SAntonio Huete Jimenez if (cap_dns_type_limit(capdnsloc, types, 1) < 0)
909*ed775ee7SAntonio Huete Jimenez error("unable to limit access to system.dns service");
910*ed775ee7SAntonio Huete Jimenez families[0] = AF_INET;
911*ed775ee7SAntonio Huete Jimenez families[1] = AF_INET6;
912*ed775ee7SAntonio Huete Jimenez if (cap_dns_family_limit(capdnsloc, families, 2) < 0)
913*ed775ee7SAntonio Huete Jimenez error("unable to limit access to system.dns service");
914*ed775ee7SAntonio Huete Jimenez
915*ed775ee7SAntonio Huete Jimenez return (capdnsloc);
916*ed775ee7SAntonio Huete Jimenez }
917*ed775ee7SAntonio Huete Jimenez #endif /* HAVE_CASPER */
918*ed775ee7SAntonio Huete Jimenez
919411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
920411677aeSAaron LI static int
tstamp_precision_from_string(const char * precision)921411677aeSAaron LI tstamp_precision_from_string(const char *precision)
922411677aeSAaron LI {
923411677aeSAaron LI if (strncmp(precision, "nano", strlen("nano")) == 0)
924411677aeSAaron LI return PCAP_TSTAMP_PRECISION_NANO;
925411677aeSAaron LI
926411677aeSAaron LI if (strncmp(precision, "micro", strlen("micro")) == 0)
927411677aeSAaron LI return PCAP_TSTAMP_PRECISION_MICRO;
928411677aeSAaron LI
929411677aeSAaron LI return -EINVAL;
930411677aeSAaron LI }
931411677aeSAaron LI
932411677aeSAaron LI static const char *
tstamp_precision_to_string(int precision)933411677aeSAaron LI tstamp_precision_to_string(int precision)
934411677aeSAaron LI {
935411677aeSAaron LI switch (precision) {
936411677aeSAaron LI
937411677aeSAaron LI case PCAP_TSTAMP_PRECISION_MICRO:
938411677aeSAaron LI return "micro";
939411677aeSAaron LI
940411677aeSAaron LI case PCAP_TSTAMP_PRECISION_NANO:
941411677aeSAaron LI return "nano";
942411677aeSAaron LI
943411677aeSAaron LI default:
944411677aeSAaron LI return "unknown";
945411677aeSAaron LI }
946411677aeSAaron LI }
947411677aeSAaron LI #endif
948411677aeSAaron LI
949411677aeSAaron LI #ifdef HAVE_CAPSICUM
950411677aeSAaron LI /*
951411677aeSAaron LI * Ensure that, on a dump file's descriptor, we have all the rights
952411677aeSAaron LI * necessary to make the standard I/O library work with an fdopen()ed
953411677aeSAaron LI * FILE * from that descriptor.
954411677aeSAaron LI *
955*ed775ee7SAntonio Huete Jimenez * A long time ago in a galaxy far, far away, AT&T decided that, instead
956411677aeSAaron LI * of providing separate APIs for getting and setting the FD_ flags on a
957411677aeSAaron LI * descriptor, getting and setting the O_ flags on a descriptor, and
958411677aeSAaron LI * locking files, they'd throw them all into a kitchen-sink fcntl() call
959411677aeSAaron LI * along the lines of ioctl(), the fact that ioctl() operations are
960411677aeSAaron LI * largely specific to particular character devices but fcntl() operations
961411677aeSAaron LI * are either generic to all descriptors or generic to all descriptors for
962411677aeSAaron LI * regular files nonwithstanding.
963411677aeSAaron LI *
964411677aeSAaron LI * The Capsicum people decided that fine-grained control of descriptor
965411677aeSAaron LI * operations was required, so that you need to grant permission for
966411677aeSAaron LI * reading, writing, seeking, and fcntl-ing. The latter, courtesy of
967411677aeSAaron LI * AT&T's decision, means that "fcntl-ing" isn't a thing, but a motley
968411677aeSAaron LI * collection of things, so there are *individual* fcntls for which
969411677aeSAaron LI * permission needs to be granted.
970411677aeSAaron LI *
971411677aeSAaron LI * The FreeBSD standard I/O people implemented some optimizations that
972411677aeSAaron LI * requires that the standard I/O routines be able to determine whether
973411677aeSAaron LI * the descriptor for the FILE * is open append-only or not; as that
974411677aeSAaron LI * descriptor could have come from an open() rather than an fopen(),
975411677aeSAaron LI * that requires that it be able to do an F_GETFL fcntl() to read
976411677aeSAaron LI * the O_ flags.
977411677aeSAaron LI *
978411677aeSAaron LI * Tcpdump uses ftell() to determine how much data has been written
979411677aeSAaron LI * to a file in order to, when used with -C, determine when it's time
980411677aeSAaron LI * to rotate capture files. ftell() therefore needs to do an lseek()
981411677aeSAaron LI * to find out the file offset and must, thanks to the aforementioned
982411677aeSAaron LI * optimization, also know whether the descriptor is open append-only
983411677aeSAaron LI * or not.
984411677aeSAaron LI *
985411677aeSAaron LI * The net result of all the above is that we need to grant CAP_SEEK,
986411677aeSAaron LI * CAP_WRITE, and CAP_FCNTL with the CAP_FCNTL_GETFL subcapability.
987411677aeSAaron LI *
988411677aeSAaron LI * Perhaps this is the universe's way of saying that either
989411677aeSAaron LI *
990411677aeSAaron LI * 1) there needs to be an fopenat() call and a pcap_dump_openat() call
991411677aeSAaron LI * using it, so that Capsicum-capable tcpdump wouldn't need to do
992411677aeSAaron LI * an fdopen()
993411677aeSAaron LI *
994411677aeSAaron LI * or
995411677aeSAaron LI *
996411677aeSAaron LI * 2) there needs to be a cap_fdopen() call in the FreeBSD standard
997411677aeSAaron LI * I/O library that knows what rights are needed by the standard
998411677aeSAaron LI * I/O library, based on the open mode, and assigns them, perhaps
999411677aeSAaron LI * with an additional argument indicating, for example, whether
1000411677aeSAaron LI * seeking should be allowed, so that tcpdump doesn't need to know
1001411677aeSAaron LI * what the standard I/O library happens to require this week.
1002411677aeSAaron LI */
1003411677aeSAaron LI static void
set_dumper_capsicum_rights(pcap_dumper_t * p)1004411677aeSAaron LI set_dumper_capsicum_rights(pcap_dumper_t *p)
1005411677aeSAaron LI {
1006411677aeSAaron LI int fd = fileno(pcap_dump_file(p));
1007411677aeSAaron LI cap_rights_t rights;
1008411677aeSAaron LI
1009411677aeSAaron LI cap_rights_init(&rights, CAP_SEEK, CAP_WRITE, CAP_FCNTL);
1010411677aeSAaron LI if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) {
1011411677aeSAaron LI error("unable to limit dump descriptor");
1012411677aeSAaron LI }
1013411677aeSAaron LI if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS) {
1014411677aeSAaron LI error("unable to limit dump descriptor fcntls");
1015411677aeSAaron LI }
1016411677aeSAaron LI }
1017411677aeSAaron LI #endif
1018411677aeSAaron LI
1019411677aeSAaron LI /*
1020411677aeSAaron LI * Copy arg vector into a new buffer, concatenating arguments with spaces.
1021411677aeSAaron LI */
1022411677aeSAaron LI static char *
copy_argv(char ** argv)1023*ed775ee7SAntonio Huete Jimenez copy_argv(char **argv)
1024411677aeSAaron LI {
1025*ed775ee7SAntonio Huete Jimenez char **p;
1026*ed775ee7SAntonio Huete Jimenez size_t len = 0;
1027411677aeSAaron LI char *buf;
1028411677aeSAaron LI char *src, *dst;
1029411677aeSAaron LI
1030411677aeSAaron LI p = argv;
1031411677aeSAaron LI if (*p == NULL)
1032411677aeSAaron LI return 0;
1033411677aeSAaron LI
1034411677aeSAaron LI while (*p)
1035411677aeSAaron LI len += strlen(*p++) + 1;
1036411677aeSAaron LI
1037411677aeSAaron LI buf = (char *)malloc(len);
1038411677aeSAaron LI if (buf == NULL)
1039*ed775ee7SAntonio Huete Jimenez error("%s: malloc", __func__);
1040411677aeSAaron LI
1041411677aeSAaron LI p = argv;
1042411677aeSAaron LI dst = buf;
1043411677aeSAaron LI while ((src = *p++) != NULL) {
1044411677aeSAaron LI while ((*dst++ = *src++) != '\0')
1045411677aeSAaron LI ;
1046411677aeSAaron LI dst[-1] = ' ';
1047411677aeSAaron LI }
1048411677aeSAaron LI dst[-1] = '\0';
1049411677aeSAaron LI
1050411677aeSAaron LI return buf;
1051411677aeSAaron LI }
1052411677aeSAaron LI
1053411677aeSAaron LI /*
1054411677aeSAaron LI * On Windows, we need to open the file in binary mode, so that
1055411677aeSAaron LI * we get all the bytes specified by the size we get from "fstat()".
1056411677aeSAaron LI * On UNIX, that's not necessary. O_BINARY is defined on Windows;
1057411677aeSAaron LI * we define it as 0 if it's not defined, so it does nothing.
1058411677aeSAaron LI */
1059411677aeSAaron LI #ifndef O_BINARY
1060411677aeSAaron LI #define O_BINARY 0
1061411677aeSAaron LI #endif
1062411677aeSAaron LI
1063411677aeSAaron LI static char *
read_infile(char * fname)1064411677aeSAaron LI read_infile(char *fname)
1065411677aeSAaron LI {
1066*ed775ee7SAntonio Huete Jimenez int i, fd;
1067*ed775ee7SAntonio Huete Jimenez ssize_t cc;
1068*ed775ee7SAntonio Huete Jimenez char *cp;
1069*ed775ee7SAntonio Huete Jimenez our_statb buf;
1070411677aeSAaron LI
1071411677aeSAaron LI fd = open(fname, O_RDONLY|O_BINARY);
1072411677aeSAaron LI if (fd < 0)
1073411677aeSAaron LI error("can't open %s: %s", fname, pcap_strerror(errno));
1074411677aeSAaron LI
1075*ed775ee7SAntonio Huete Jimenez if (our_fstat(fd, &buf) < 0)
1076411677aeSAaron LI error("can't stat %s: %s", fname, pcap_strerror(errno));
1077411677aeSAaron LI
1078*ed775ee7SAntonio Huete Jimenez /*
1079*ed775ee7SAntonio Huete Jimenez * Reject files whose size doesn't fit into an int; a filter
1080*ed775ee7SAntonio Huete Jimenez * *that* large will probably be too big.
1081*ed775ee7SAntonio Huete Jimenez */
1082*ed775ee7SAntonio Huete Jimenez if (buf.st_size > INT_MAX)
1083*ed775ee7SAntonio Huete Jimenez error("%s is too large", fname);
1084*ed775ee7SAntonio Huete Jimenez
1085411677aeSAaron LI cp = malloc((u_int)buf.st_size + 1);
1086411677aeSAaron LI if (cp == NULL)
1087411677aeSAaron LI error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
1088411677aeSAaron LI fname, pcap_strerror(errno));
1089411677aeSAaron LI cc = read(fd, cp, (u_int)buf.st_size);
1090411677aeSAaron LI if (cc < 0)
1091411677aeSAaron LI error("read %s: %s", fname, pcap_strerror(errno));
1092411677aeSAaron LI if (cc != buf.st_size)
1093*ed775ee7SAntonio Huete Jimenez error("short read %s (%d != %d)", fname, (int) cc,
1094*ed775ee7SAntonio Huete Jimenez (int)buf.st_size);
1095411677aeSAaron LI
1096411677aeSAaron LI close(fd);
1097411677aeSAaron LI /* replace "# comment" with spaces */
1098411677aeSAaron LI for (i = 0; i < cc; i++) {
1099411677aeSAaron LI if (cp[i] == '#')
1100411677aeSAaron LI while (i < cc && cp[i] != '\n')
1101411677aeSAaron LI cp[i++] = ' ';
1102411677aeSAaron LI }
1103411677aeSAaron LI cp[cc] = '\0';
1104411677aeSAaron LI return (cp);
1105411677aeSAaron LI }
1106411677aeSAaron LI
1107411677aeSAaron LI #ifdef HAVE_PCAP_FINDALLDEVS
1108411677aeSAaron LI static long
parse_interface_number(const char * device)1109411677aeSAaron LI parse_interface_number(const char *device)
1110411677aeSAaron LI {
1111*ed775ee7SAntonio Huete Jimenez const char *p;
1112411677aeSAaron LI long devnum;
1113411677aeSAaron LI char *end;
1114411677aeSAaron LI
1115*ed775ee7SAntonio Huete Jimenez /*
1116*ed775ee7SAntonio Huete Jimenez * Search for a colon, terminating any scheme at the beginning
1117*ed775ee7SAntonio Huete Jimenez * of the device.
1118*ed775ee7SAntonio Huete Jimenez */
1119*ed775ee7SAntonio Huete Jimenez p = strchr(device, ':');
1120*ed775ee7SAntonio Huete Jimenez if (p != NULL) {
1121*ed775ee7SAntonio Huete Jimenez /*
1122*ed775ee7SAntonio Huete Jimenez * We found it. Is it followed by "//"?
1123*ed775ee7SAntonio Huete Jimenez */
1124*ed775ee7SAntonio Huete Jimenez p++; /* skip the : */
1125*ed775ee7SAntonio Huete Jimenez if (strncmp(p, "//", 2) == 0) {
1126*ed775ee7SAntonio Huete Jimenez /*
1127*ed775ee7SAntonio Huete Jimenez * Yes. Search for the next /, at the end of the
1128*ed775ee7SAntonio Huete Jimenez * authority part of the URL.
1129*ed775ee7SAntonio Huete Jimenez */
1130*ed775ee7SAntonio Huete Jimenez p += 2; /* skip the // */
1131*ed775ee7SAntonio Huete Jimenez p = strchr(p, '/');
1132*ed775ee7SAntonio Huete Jimenez if (p != NULL) {
1133*ed775ee7SAntonio Huete Jimenez /*
1134*ed775ee7SAntonio Huete Jimenez * OK, past the / is the path.
1135*ed775ee7SAntonio Huete Jimenez */
1136*ed775ee7SAntonio Huete Jimenez device = p + 1;
1137*ed775ee7SAntonio Huete Jimenez }
1138*ed775ee7SAntonio Huete Jimenez }
1139*ed775ee7SAntonio Huete Jimenez }
1140411677aeSAaron LI devnum = strtol(device, &end, 10);
1141411677aeSAaron LI if (device != end && *end == '\0') {
1142411677aeSAaron LI /*
1143411677aeSAaron LI * It's all-numeric, but is it a valid number?
1144411677aeSAaron LI */
1145411677aeSAaron LI if (devnum <= 0) {
1146411677aeSAaron LI /*
1147411677aeSAaron LI * No, it's not an ordinal.
1148411677aeSAaron LI */
1149411677aeSAaron LI error("Invalid adapter index");
1150411677aeSAaron LI }
1151411677aeSAaron LI return (devnum);
1152411677aeSAaron LI } else {
1153411677aeSAaron LI /*
1154411677aeSAaron LI * It's not all-numeric; return -1, so our caller
1155411677aeSAaron LI * knows that.
1156411677aeSAaron LI */
1157411677aeSAaron LI return (-1);
1158411677aeSAaron LI }
1159411677aeSAaron LI }
1160411677aeSAaron LI
1161411677aeSAaron LI static char *
find_interface_by_number(const char * url _U_,long devnum)1162*ed775ee7SAntonio Huete Jimenez find_interface_by_number(const char *url
1163*ed775ee7SAntonio Huete Jimenez #ifndef HAVE_PCAP_FINDALLDEVS_EX
1164*ed775ee7SAntonio Huete Jimenez _U_
1165*ed775ee7SAntonio Huete Jimenez #endif
1166*ed775ee7SAntonio Huete Jimenez , long devnum)
1167411677aeSAaron LI {
1168411677aeSAaron LI pcap_if_t *dev, *devlist;
1169411677aeSAaron LI long i;
1170411677aeSAaron LI char ebuf[PCAP_ERRBUF_SIZE];
1171411677aeSAaron LI char *device;
1172*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS_EX
1173*ed775ee7SAntonio Huete Jimenez const char *endp;
1174*ed775ee7SAntonio Huete Jimenez char *host_url;
1175*ed775ee7SAntonio Huete Jimenez #endif
1176*ed775ee7SAntonio Huete Jimenez int status;
1177411677aeSAaron LI
1178*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS_EX
1179*ed775ee7SAntonio Huete Jimenez /*
1180*ed775ee7SAntonio Huete Jimenez * Search for a colon, terminating any scheme at the beginning
1181*ed775ee7SAntonio Huete Jimenez * of the URL.
1182*ed775ee7SAntonio Huete Jimenez */
1183*ed775ee7SAntonio Huete Jimenez endp = strchr(url, ':');
1184*ed775ee7SAntonio Huete Jimenez if (endp != NULL) {
1185*ed775ee7SAntonio Huete Jimenez /*
1186*ed775ee7SAntonio Huete Jimenez * We found it. Is it followed by "//"?
1187*ed775ee7SAntonio Huete Jimenez */
1188*ed775ee7SAntonio Huete Jimenez endp++; /* skip the : */
1189*ed775ee7SAntonio Huete Jimenez if (strncmp(endp, "//", 2) == 0) {
1190*ed775ee7SAntonio Huete Jimenez /*
1191*ed775ee7SAntonio Huete Jimenez * Yes. Search for the next /, at the end of the
1192*ed775ee7SAntonio Huete Jimenez * authority part of the URL.
1193*ed775ee7SAntonio Huete Jimenez */
1194*ed775ee7SAntonio Huete Jimenez endp += 2; /* skip the // */
1195*ed775ee7SAntonio Huete Jimenez endp = strchr(endp, '/');
1196*ed775ee7SAntonio Huete Jimenez } else
1197*ed775ee7SAntonio Huete Jimenez endp = NULL;
1198*ed775ee7SAntonio Huete Jimenez }
1199*ed775ee7SAntonio Huete Jimenez if (endp != NULL) {
1200*ed775ee7SAntonio Huete Jimenez /*
1201*ed775ee7SAntonio Huete Jimenez * OK, everything from device to endp is a URL to hand
1202*ed775ee7SAntonio Huete Jimenez * to pcap_findalldevs_ex().
1203*ed775ee7SAntonio Huete Jimenez */
1204*ed775ee7SAntonio Huete Jimenez endp++; /* Include the trailing / in the URL; pcap_findalldevs_ex() requires it */
1205*ed775ee7SAntonio Huete Jimenez host_url = malloc(endp - url + 1);
1206*ed775ee7SAntonio Huete Jimenez if (host_url == NULL && (endp - url + 1) > 0)
1207*ed775ee7SAntonio Huete Jimenez error("Invalid allocation for host");
1208*ed775ee7SAntonio Huete Jimenez
1209*ed775ee7SAntonio Huete Jimenez memcpy(host_url, url, endp - url);
1210*ed775ee7SAntonio Huete Jimenez host_url[endp - url] = '\0';
1211*ed775ee7SAntonio Huete Jimenez status = pcap_findalldevs_ex(host_url, NULL, &devlist, ebuf);
1212*ed775ee7SAntonio Huete Jimenez free(host_url);
1213*ed775ee7SAntonio Huete Jimenez } else
1214*ed775ee7SAntonio Huete Jimenez #endif
1215*ed775ee7SAntonio Huete Jimenez status = pcap_findalldevs(&devlist, ebuf);
1216*ed775ee7SAntonio Huete Jimenez if (status < 0)
1217411677aeSAaron LI error("%s", ebuf);
1218411677aeSAaron LI /*
1219411677aeSAaron LI * Look for the devnum-th entry in the list of devices (1-based).
1220411677aeSAaron LI */
1221411677aeSAaron LI for (i = 0, dev = devlist; i < devnum-1 && dev != NULL;
1222411677aeSAaron LI i++, dev = dev->next)
1223411677aeSAaron LI ;
1224411677aeSAaron LI if (dev == NULL)
1225411677aeSAaron LI error("Invalid adapter index");
1226411677aeSAaron LI device = strdup(dev->name);
1227411677aeSAaron LI pcap_freealldevs(devlist);
1228411677aeSAaron LI return (device);
1229411677aeSAaron LI }
1230411677aeSAaron LI #endif
1231411677aeSAaron LI
1232*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_OPEN
1233*ed775ee7SAntonio Huete Jimenez /*
1234*ed775ee7SAntonio Huete Jimenez * Prefixes for rpcap URLs.
1235*ed775ee7SAntonio Huete Jimenez */
1236*ed775ee7SAntonio Huete Jimenez static char rpcap_prefix[] = "rpcap://";
1237*ed775ee7SAntonio Huete Jimenez static char rpcap_ssl_prefix[] = "rpcaps://";
1238*ed775ee7SAntonio Huete Jimenez #endif
1239*ed775ee7SAntonio Huete Jimenez
1240411677aeSAaron LI static pcap_t *
open_interface(const char * device,netdissect_options * ndo,char * ebuf)1241411677aeSAaron LI open_interface(const char *device, netdissect_options *ndo, char *ebuf)
1242411677aeSAaron LI {
1243411677aeSAaron LI pcap_t *pc;
1244411677aeSAaron LI #ifdef HAVE_PCAP_CREATE
1245411677aeSAaron LI int status;
1246411677aeSAaron LI char *cp;
1247411677aeSAaron LI #endif
1248411677aeSAaron LI
1249*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_OPEN
1250*ed775ee7SAntonio Huete Jimenez /*
1251*ed775ee7SAntonio Huete Jimenez * Is this an rpcap URL?
1252*ed775ee7SAntonio Huete Jimenez */
1253*ed775ee7SAntonio Huete Jimenez if (strncmp(device, rpcap_prefix, sizeof(rpcap_prefix) - 1) == 0 ||
1254*ed775ee7SAntonio Huete Jimenez strncmp(device, rpcap_ssl_prefix, sizeof(rpcap_ssl_prefix) - 1) == 0) {
1255*ed775ee7SAntonio Huete Jimenez /*
1256*ed775ee7SAntonio Huete Jimenez * Yes. Open it with pcap_open().
1257*ed775ee7SAntonio Huete Jimenez */
1258*ed775ee7SAntonio Huete Jimenez *ebuf = '\0';
1259*ed775ee7SAntonio Huete Jimenez pc = pcap_open(device, ndo->ndo_snaplen,
1260*ed775ee7SAntonio Huete Jimenez pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, timeout, NULL,
1261*ed775ee7SAntonio Huete Jimenez ebuf);
1262*ed775ee7SAntonio Huete Jimenez if (pc == NULL) {
1263*ed775ee7SAntonio Huete Jimenez /*
1264*ed775ee7SAntonio Huete Jimenez * If this failed with "No such device" or "The system
1265*ed775ee7SAntonio Huete Jimenez * cannot find the device specified", that means
1266*ed775ee7SAntonio Huete Jimenez * the interface doesn't exist; return NULL, so that
1267*ed775ee7SAntonio Huete Jimenez * the caller can see whether the device name is
1268*ed775ee7SAntonio Huete Jimenez * actually an interface index.
1269*ed775ee7SAntonio Huete Jimenez */
1270*ed775ee7SAntonio Huete Jimenez if (strstr(ebuf, "No such device") != NULL ||
1271*ed775ee7SAntonio Huete Jimenez strstr(ebuf, "The system cannot find the device specified") != NULL)
1272*ed775ee7SAntonio Huete Jimenez return (NULL);
1273*ed775ee7SAntonio Huete Jimenez error("%s", ebuf);
1274*ed775ee7SAntonio Huete Jimenez }
1275*ed775ee7SAntonio Huete Jimenez if (*ebuf)
1276*ed775ee7SAntonio Huete Jimenez warning("%s", ebuf);
1277*ed775ee7SAntonio Huete Jimenez return (pc);
1278*ed775ee7SAntonio Huete Jimenez }
1279*ed775ee7SAntonio Huete Jimenez #endif /* HAVE_PCAP_OPEN */
1280*ed775ee7SAntonio Huete Jimenez
1281411677aeSAaron LI #ifdef HAVE_PCAP_CREATE
1282411677aeSAaron LI pc = pcap_create(device, ebuf);
1283411677aeSAaron LI if (pc == NULL) {
1284411677aeSAaron LI /*
1285411677aeSAaron LI * If this failed with "No such device", that means
1286411677aeSAaron LI * the interface doesn't exist; return NULL, so that
1287411677aeSAaron LI * the caller can see whether the device name is
1288411677aeSAaron LI * actually an interface index.
1289411677aeSAaron LI */
1290411677aeSAaron LI if (strstr(ebuf, "No such device") != NULL)
1291411677aeSAaron LI return (NULL);
1292411677aeSAaron LI error("%s", ebuf);
1293411677aeSAaron LI }
1294411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_TYPE
1295411677aeSAaron LI if (Jflag)
1296411677aeSAaron LI show_tstamp_types_and_exit(pc, device);
1297411677aeSAaron LI #endif
1298411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
1299411677aeSAaron LI status = pcap_set_tstamp_precision(pc, ndo->ndo_tstamp_precision);
1300411677aeSAaron LI if (status != 0)
1301411677aeSAaron LI error("%s: Can't set %ssecond time stamp precision: %s",
1302411677aeSAaron LI device,
1303411677aeSAaron LI tstamp_precision_to_string(ndo->ndo_tstamp_precision),
1304411677aeSAaron LI pcap_statustostr(status));
1305411677aeSAaron LI #endif
1306411677aeSAaron LI
1307411677aeSAaron LI #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
1308411677aeSAaron LI if (immediate_mode) {
1309411677aeSAaron LI status = pcap_set_immediate_mode(pc, 1);
1310411677aeSAaron LI if (status != 0)
1311411677aeSAaron LI error("%s: Can't set immediate mode: %s",
1312*ed775ee7SAntonio Huete Jimenez device, pcap_statustostr(status));
1313411677aeSAaron LI }
1314411677aeSAaron LI #endif
1315411677aeSAaron LI /*
1316411677aeSAaron LI * Is this an interface that supports monitor mode?
1317411677aeSAaron LI */
1318411677aeSAaron LI if (pcap_can_set_rfmon(pc) == 1)
1319411677aeSAaron LI supports_monitor_mode = 1;
1320411677aeSAaron LI else
1321411677aeSAaron LI supports_monitor_mode = 0;
1322*ed775ee7SAntonio Huete Jimenez if (ndo->ndo_snaplen != 0) {
1323*ed775ee7SAntonio Huete Jimenez /*
1324*ed775ee7SAntonio Huete Jimenez * A snapshot length was explicitly specified;
1325*ed775ee7SAntonio Huete Jimenez * use it.
1326*ed775ee7SAntonio Huete Jimenez */
1327411677aeSAaron LI status = pcap_set_snaplen(pc, ndo->ndo_snaplen);
1328411677aeSAaron LI if (status != 0)
1329411677aeSAaron LI error("%s: Can't set snapshot length: %s",
1330411677aeSAaron LI device, pcap_statustostr(status));
1331*ed775ee7SAntonio Huete Jimenez }
1332411677aeSAaron LI status = pcap_set_promisc(pc, !pflag);
1333411677aeSAaron LI if (status != 0)
1334411677aeSAaron LI error("%s: Can't set promiscuous mode: %s",
1335411677aeSAaron LI device, pcap_statustostr(status));
1336411677aeSAaron LI if (Iflag) {
1337411677aeSAaron LI status = pcap_set_rfmon(pc, 1);
1338411677aeSAaron LI if (status != 0)
1339411677aeSAaron LI error("%s: Can't set monitor mode: %s",
1340411677aeSAaron LI device, pcap_statustostr(status));
1341411677aeSAaron LI }
1342*ed775ee7SAntonio Huete Jimenez status = pcap_set_timeout(pc, timeout);
1343411677aeSAaron LI if (status != 0)
1344411677aeSAaron LI error("%s: pcap_set_timeout failed: %s",
1345411677aeSAaron LI device, pcap_statustostr(status));
1346411677aeSAaron LI if (Bflag != 0) {
1347411677aeSAaron LI status = pcap_set_buffer_size(pc, Bflag);
1348411677aeSAaron LI if (status != 0)
1349411677aeSAaron LI error("%s: Can't set buffer size: %s",
1350411677aeSAaron LI device, pcap_statustostr(status));
1351411677aeSAaron LI }
1352411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_TYPE
1353411677aeSAaron LI if (jflag != -1) {
1354411677aeSAaron LI status = pcap_set_tstamp_type(pc, jflag);
1355411677aeSAaron LI if (status < 0)
1356411677aeSAaron LI error("%s: Can't set time stamp type: %s",
1357411677aeSAaron LI device, pcap_statustostr(status));
1358411677aeSAaron LI else if (status > 0)
1359411677aeSAaron LI warning("When trying to set timestamp type '%s' on %s: %s",
1360411677aeSAaron LI pcap_tstamp_type_val_to_name(jflag), device,
1361411677aeSAaron LI pcap_statustostr(status));
1362411677aeSAaron LI }
1363411677aeSAaron LI #endif
1364411677aeSAaron LI status = pcap_activate(pc);
1365411677aeSAaron LI if (status < 0) {
1366411677aeSAaron LI /*
1367411677aeSAaron LI * pcap_activate() failed.
1368411677aeSAaron LI */
1369411677aeSAaron LI cp = pcap_geterr(pc);
1370411677aeSAaron LI if (status == PCAP_ERROR)
1371411677aeSAaron LI error("%s", cp);
1372411677aeSAaron LI else if (status == PCAP_ERROR_NO_SUCH_DEVICE) {
1373411677aeSAaron LI /*
1374411677aeSAaron LI * Return an error for our caller to handle.
1375411677aeSAaron LI */
1376411677aeSAaron LI snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s\n(%s)",
1377411677aeSAaron LI device, pcap_statustostr(status), cp);
1378411677aeSAaron LI } else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0')
1379411677aeSAaron LI error("%s: %s\n(%s)", device,
1380411677aeSAaron LI pcap_statustostr(status), cp);
1381*ed775ee7SAntonio Huete Jimenez #ifdef __FreeBSD__
1382*ed775ee7SAntonio Huete Jimenez else if (status == PCAP_ERROR_RFMON_NOTSUP &&
1383*ed775ee7SAntonio Huete Jimenez strncmp(device, "wlan", 4) == 0) {
1384*ed775ee7SAntonio Huete Jimenez char parent[8], newdev[8];
1385*ed775ee7SAntonio Huete Jimenez char sysctl[32];
1386*ed775ee7SAntonio Huete Jimenez size_t s = sizeof(parent);
1387*ed775ee7SAntonio Huete Jimenez
1388*ed775ee7SAntonio Huete Jimenez snprintf(sysctl, sizeof(sysctl),
1389*ed775ee7SAntonio Huete Jimenez "net.wlan.%d.%%parent", atoi(device + 4));
1390*ed775ee7SAntonio Huete Jimenez sysctlbyname(sysctl, parent, &s, NULL, 0);
1391*ed775ee7SAntonio Huete Jimenez strlcpy(newdev, device, sizeof(newdev));
1392*ed775ee7SAntonio Huete Jimenez /* Suggest a new wlan device. */
1393*ed775ee7SAntonio Huete Jimenez /* FIXME: incrementing the index this way is not going to work well
1394*ed775ee7SAntonio Huete Jimenez * when the index is 9 or greater but the only consequence in this
1395*ed775ee7SAntonio Huete Jimenez * specific case would be an error message that looks a bit odd.
1396*ed775ee7SAntonio Huete Jimenez */
1397*ed775ee7SAntonio Huete Jimenez newdev[strlen(newdev)-1]++;
1398*ed775ee7SAntonio Huete Jimenez error("%s is not a monitor mode VAP\n"
1399*ed775ee7SAntonio Huete Jimenez "To create a new monitor mode VAP use:\n"
1400*ed775ee7SAntonio Huete Jimenez " ifconfig %s create wlandev %s wlanmode monitor\n"
1401*ed775ee7SAntonio Huete Jimenez "and use %s as the tcpdump interface",
1402*ed775ee7SAntonio Huete Jimenez device, newdev, parent, newdev);
1403*ed775ee7SAntonio Huete Jimenez }
1404*ed775ee7SAntonio Huete Jimenez #endif
1405411677aeSAaron LI else
1406411677aeSAaron LI error("%s: %s", device,
1407411677aeSAaron LI pcap_statustostr(status));
1408*ed775ee7SAntonio Huete Jimenez pcap_close(pc);
1409*ed775ee7SAntonio Huete Jimenez return (NULL);
1410411677aeSAaron LI } else if (status > 0) {
1411411677aeSAaron LI /*
1412411677aeSAaron LI * pcap_activate() succeeded, but it's warning us
1413411677aeSAaron LI * of a problem it had.
1414411677aeSAaron LI */
1415411677aeSAaron LI cp = pcap_geterr(pc);
1416411677aeSAaron LI if (status == PCAP_WARNING)
1417411677aeSAaron LI warning("%s", cp);
1418411677aeSAaron LI else if (status == PCAP_WARNING_PROMISC_NOTSUP &&
1419411677aeSAaron LI *cp != '\0')
1420411677aeSAaron LI warning("%s: %s\n(%s)", device,
1421411677aeSAaron LI pcap_statustostr(status), cp);
1422411677aeSAaron LI else
1423411677aeSAaron LI warning("%s: %s", device,
1424411677aeSAaron LI pcap_statustostr(status));
1425411677aeSAaron LI }
1426411677aeSAaron LI #ifdef HAVE_PCAP_SETDIRECTION
1427411677aeSAaron LI if (Qflag != -1) {
1428411677aeSAaron LI status = pcap_setdirection(pc, Qflag);
1429411677aeSAaron LI if (status != 0)
1430411677aeSAaron LI error("%s: pcap_setdirection() failed: %s",
1431411677aeSAaron LI device, pcap_geterr(pc));
1432411677aeSAaron LI }
1433411677aeSAaron LI #endif /* HAVE_PCAP_SETDIRECTION */
1434411677aeSAaron LI #else /* HAVE_PCAP_CREATE */
1435411677aeSAaron LI *ebuf = '\0';
1436*ed775ee7SAntonio Huete Jimenez /*
1437*ed775ee7SAntonio Huete Jimenez * If no snapshot length was specified, or a length of 0 was
1438*ed775ee7SAntonio Huete Jimenez * specified, default to 256KB.
1439*ed775ee7SAntonio Huete Jimenez */
1440*ed775ee7SAntonio Huete Jimenez if (ndo->ndo_snaplen == 0)
1441*ed775ee7SAntonio Huete Jimenez ndo->ndo_snaplen = MAXIMUM_SNAPLEN;
1442*ed775ee7SAntonio Huete Jimenez pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, timeout, ebuf);
1443411677aeSAaron LI if (pc == NULL) {
1444411677aeSAaron LI /*
1445411677aeSAaron LI * If this failed with "No such device", that means
1446411677aeSAaron LI * the interface doesn't exist; return NULL, so that
1447411677aeSAaron LI * the caller can see whether the device name is
1448411677aeSAaron LI * actually an interface index.
1449411677aeSAaron LI */
1450411677aeSAaron LI if (strstr(ebuf, "No such device") != NULL)
1451411677aeSAaron LI return (NULL);
1452411677aeSAaron LI error("%s", ebuf);
1453411677aeSAaron LI }
1454411677aeSAaron LI if (*ebuf)
1455411677aeSAaron LI warning("%s", ebuf);
1456411677aeSAaron LI #endif /* HAVE_PCAP_CREATE */
1457411677aeSAaron LI
1458411677aeSAaron LI return (pc);
1459411677aeSAaron LI }
1460411677aeSAaron LI
146141c99275SPeter Avalos int
main(int argc,char ** argv)146241c99275SPeter Avalos main(int argc, char **argv)
146341c99275SPeter Avalos {
1464*ed775ee7SAntonio Huete Jimenez int cnt, op, i;
1465411677aeSAaron LI bpf_u_int32 localnet = 0, netmask = 0;
1466*ed775ee7SAntonio Huete Jimenez char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName;
1467*ed775ee7SAntonio Huete Jimenez char *endp;
146841c99275SPeter Avalos pcap_handler callback;
1469411677aeSAaron LI int dlt;
1470411677aeSAaron LI const char *dlt_name;
147141c99275SPeter Avalos struct bpf_program fcode;
1472411677aeSAaron LI #ifndef _WIN32
1473*ed775ee7SAntonio Huete Jimenez void (*oldhandler)(int);
147441c99275SPeter Avalos #endif
147541c99275SPeter Avalos struct dump_info dumpinfo;
147641c99275SPeter Avalos u_char *pcap_userdata;
147741c99275SPeter Avalos char ebuf[PCAP_ERRBUF_SIZE];
1478411677aeSAaron LI char VFileLine[PATH_MAX + 1];
1479*ed775ee7SAntonio Huete Jimenez const char *username = NULL;
1480*ed775ee7SAntonio Huete Jimenez #ifndef _WIN32
1481*ed775ee7SAntonio Huete Jimenez const char *chroot_dir = NULL;
1482*ed775ee7SAntonio Huete Jimenez #endif
1483411677aeSAaron LI char *ret = NULL;
1484411677aeSAaron LI char *end;
148541c99275SPeter Avalos #ifdef HAVE_PCAP_FINDALLDEVS
1486411677aeSAaron LI pcap_if_t *devlist;
1487411677aeSAaron LI long devnum;
148841c99275SPeter Avalos #endif
148941c99275SPeter Avalos int status;
1490411677aeSAaron LI FILE *VFile;
1491411677aeSAaron LI #ifdef HAVE_CAPSICUM
1492411677aeSAaron LI cap_rights_t rights;
1493411677aeSAaron LI int cansandbox;
1494411677aeSAaron LI #endif /* HAVE_CAPSICUM */
1495411677aeSAaron LI int Oflag = 1; /* run filter code optimizer */
1496411677aeSAaron LI int yflag_dlt = -1;
1497411677aeSAaron LI const char *yflag_dlt_name = NULL;
1498*ed775ee7SAntonio Huete Jimenez int print = 0;
149941c99275SPeter Avalos
1500411677aeSAaron LI netdissect_options Ndo;
1501411677aeSAaron LI netdissect_options *ndo = &Ndo;
1502411677aeSAaron LI
1503411677aeSAaron LI /*
1504411677aeSAaron LI * Initialize the netdissect code.
1505411677aeSAaron LI */
1506*ed775ee7SAntonio Huete Jimenez if (nd_init(ebuf, sizeof(ebuf)) == -1)
1507411677aeSAaron LI error("%s", ebuf);
1508411677aeSAaron LI
1509411677aeSAaron LI memset(ndo, 0, sizeof(*ndo));
1510411677aeSAaron LI ndo_set_function_pointers(ndo);
151141c99275SPeter Avalos
151241c99275SPeter Avalos cnt = -1;
151341c99275SPeter Avalos device = NULL;
151441c99275SPeter Avalos infile = NULL;
151541c99275SPeter Avalos RFileName = NULL;
1516411677aeSAaron LI VFileName = NULL;
1517411677aeSAaron LI VFile = NULL;
151841c99275SPeter Avalos WFileName = NULL;
1519411677aeSAaron LI dlt = -1;
1520*ed775ee7SAntonio Huete Jimenez if ((cp = strrchr(argv[0], PATH_SEPARATOR)) != NULL)
1521411677aeSAaron LI ndo->program_name = program_name = cp + 1;
152241c99275SPeter Avalos else
1523411677aeSAaron LI ndo->program_name = program_name = argv[0];
152441c99275SPeter Avalos
1525*ed775ee7SAntonio Huete Jimenez #if defined(HAVE_PCAP_WSOCKINIT)
1526411677aeSAaron LI if (pcap_wsockinit() != 0)
1527411677aeSAaron LI error("Attempting to initialize Winsock failed");
1528*ed775ee7SAntonio Huete Jimenez #elif defined(HAVE_WSOCKINIT)
1529*ed775ee7SAntonio Huete Jimenez if (wsockinit() != 0)
1530*ed775ee7SAntonio Huete Jimenez error("Attempting to initialize Winsock failed");
1531*ed775ee7SAntonio Huete Jimenez #endif
1532411677aeSAaron LI
1533411677aeSAaron LI /*
1534411677aeSAaron LI * On platforms where the CPU doesn't support unaligned loads,
1535411677aeSAaron LI * force unaligned accesses to abort with SIGBUS, rather than
1536411677aeSAaron LI * being fixed up (slowly) by the OS kernel; on those platforms,
1537411677aeSAaron LI * misaligned accesses are bugs, and we want tcpdump to crash so
1538411677aeSAaron LI * that the bugs are reported.
1539411677aeSAaron LI */
154041c99275SPeter Avalos if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0)
154141c99275SPeter Avalos error("%s", ebuf);
154241c99275SPeter Avalos
154341c99275SPeter Avalos while (
1544411677aeSAaron LI (op = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != -1)
154541c99275SPeter Avalos switch (op) {
154641c99275SPeter Avalos
154741c99275SPeter Avalos case 'a':
154841c99275SPeter Avalos /* compatibility for old -a */
154941c99275SPeter Avalos break;
155041c99275SPeter Avalos
155141c99275SPeter Avalos case 'A':
1552411677aeSAaron LI ++ndo->ndo_Aflag;
155341c99275SPeter Avalos break;
155441c99275SPeter Avalos
155527bfbee1SPeter Avalos case 'b':
1556411677aeSAaron LI ++ndo->ndo_bflag;
155727bfbee1SPeter Avalos break;
155827bfbee1SPeter Avalos
1559411677aeSAaron LI #if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
156041c99275SPeter Avalos case 'B':
1561ea7b4bf5SPeter Avalos Bflag = atoi(optarg)*1024;
1562ea7b4bf5SPeter Avalos if (Bflag <= 0)
156341c99275SPeter Avalos error("invalid packet buffer size %s", optarg);
156441c99275SPeter Avalos break;
1565411677aeSAaron LI #endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */
156641c99275SPeter Avalos
156741c99275SPeter Avalos case 'c':
156841c99275SPeter Avalos cnt = atoi(optarg);
156941c99275SPeter Avalos if (cnt <= 0)
157041c99275SPeter Avalos error("invalid packet count %s", optarg);
157141c99275SPeter Avalos break;
157241c99275SPeter Avalos
157341c99275SPeter Avalos case 'C':
1574*ed775ee7SAntonio Huete Jimenez errno = 0;
1575*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_DUMP_FTELL64
1576*ed775ee7SAntonio Huete Jimenez Cflag = strtoint64_t(optarg, &endp, 10);
1577*ed775ee7SAntonio Huete Jimenez #else
1578*ed775ee7SAntonio Huete Jimenez Cflag = strtol(optarg, &endp, 10);
1579*ed775ee7SAntonio Huete Jimenez #endif
1580*ed775ee7SAntonio Huete Jimenez if (endp == optarg || *endp != '\0' || errno != 0
1581*ed775ee7SAntonio Huete Jimenez || Cflag <= 0)
158241c99275SPeter Avalos error("invalid file size %s", optarg);
1583*ed775ee7SAntonio Huete Jimenez /*
1584*ed775ee7SAntonio Huete Jimenez * Will multiplying it by 1000000 overflow?
1585*ed775ee7SAntonio Huete Jimenez */
1586*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_DUMP_FTELL64
1587*ed775ee7SAntonio Huete Jimenez if (Cflag > INT64_T_CONSTANT(0x7fffffffffffffff) / 1000000)
1588*ed775ee7SAntonio Huete Jimenez #else
1589*ed775ee7SAntonio Huete Jimenez if (Cflag > LONG_MAX / 1000000)
1590*ed775ee7SAntonio Huete Jimenez #endif
1591*ed775ee7SAntonio Huete Jimenez error("file size %s is too large", optarg);
1592*ed775ee7SAntonio Huete Jimenez Cflag *= 1000000;
159341c99275SPeter Avalos break;
159441c99275SPeter Avalos
159541c99275SPeter Avalos case 'd':
159641c99275SPeter Avalos ++dflag;
159741c99275SPeter Avalos break;
159841c99275SPeter Avalos
1599*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS
160041c99275SPeter Avalos case 'D':
1601411677aeSAaron LI Dflag++;
1602411677aeSAaron LI break;
1603*ed775ee7SAntonio Huete Jimenez #endif
1604*ed775ee7SAntonio Huete Jimenez
1605*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS_EX
1606*ed775ee7SAntonio Huete Jimenez case OPTION_LIST_REMOTE_INTERFACES:
1607*ed775ee7SAntonio Huete Jimenez remote_interfaces_source = optarg;
1608*ed775ee7SAntonio Huete Jimenez break;
1609*ed775ee7SAntonio Huete Jimenez #endif
161041c99275SPeter Avalos
161141c99275SPeter Avalos case 'L':
161241c99275SPeter Avalos Lflag++;
161341c99275SPeter Avalos break;
161441c99275SPeter Avalos
161541c99275SPeter Avalos case 'e':
1616411677aeSAaron LI ++ndo->ndo_eflag;
161741c99275SPeter Avalos break;
161841c99275SPeter Avalos
161941c99275SPeter Avalos case 'E':
162041c99275SPeter Avalos #ifndef HAVE_LIBCRYPTO
162141c99275SPeter Avalos warning("crypto code not compiled in");
162241c99275SPeter Avalos #endif
1623411677aeSAaron LI ndo->ndo_espsecret = optarg;
162441c99275SPeter Avalos break;
162541c99275SPeter Avalos
162641c99275SPeter Avalos case 'f':
1627411677aeSAaron LI ++ndo->ndo_fflag;
162841c99275SPeter Avalos break;
162941c99275SPeter Avalos
163041c99275SPeter Avalos case 'F':
163141c99275SPeter Avalos infile = optarg;
163241c99275SPeter Avalos break;
163341c99275SPeter Avalos
1634ea7b4bf5SPeter Avalos case 'G':
1635ea7b4bf5SPeter Avalos Gflag = atoi(optarg);
1636ea7b4bf5SPeter Avalos if (Gflag < 0)
1637ea7b4bf5SPeter Avalos error("invalid number of seconds %s", optarg);
1638ea7b4bf5SPeter Avalos
1639ea7b4bf5SPeter Avalos /* We will create one file initially. */
1640ea7b4bf5SPeter Avalos Gflag_count = 0;
1641ea7b4bf5SPeter Avalos
1642ea7b4bf5SPeter Avalos /* Grab the current time for rotation use. */
1643ea7b4bf5SPeter Avalos if ((Gflag_time = time(NULL)) == (time_t)-1) {
1644*ed775ee7SAntonio Huete Jimenez error("%s: can't get current time: %s",
1645*ed775ee7SAntonio Huete Jimenez __func__, pcap_strerror(errno));
1646ea7b4bf5SPeter Avalos }
1647ea7b4bf5SPeter Avalos break;
1648ea7b4bf5SPeter Avalos
164927bfbee1SPeter Avalos case 'h':
1650*ed775ee7SAntonio Huete Jimenez print_usage(stdout);
1651*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_SUCCESS);
165227bfbee1SPeter Avalos break;
165327bfbee1SPeter Avalos
165427bfbee1SPeter Avalos case 'H':
1655411677aeSAaron LI ++ndo->ndo_Hflag;
165627bfbee1SPeter Avalos break;
165727bfbee1SPeter Avalos
165841c99275SPeter Avalos case 'i':
165941c99275SPeter Avalos device = optarg;
166041c99275SPeter Avalos break;
166141c99275SPeter Avalos
1662ea7b4bf5SPeter Avalos #ifdef HAVE_PCAP_CREATE
1663ea7b4bf5SPeter Avalos case 'I':
1664ea7b4bf5SPeter Avalos ++Iflag;
1665ea7b4bf5SPeter Avalos break;
1666ea7b4bf5SPeter Avalos #endif /* HAVE_PCAP_CREATE */
1667ea7b4bf5SPeter Avalos
166827bfbee1SPeter Avalos #ifdef HAVE_PCAP_SET_TSTAMP_TYPE
166927bfbee1SPeter Avalos case 'j':
167027bfbee1SPeter Avalos jflag = pcap_tstamp_type_name_to_val(optarg);
167127bfbee1SPeter Avalos if (jflag < 0)
167227bfbee1SPeter Avalos error("invalid time stamp type %s", optarg);
167327bfbee1SPeter Avalos break;
167427bfbee1SPeter Avalos
167527bfbee1SPeter Avalos case 'J':
167627bfbee1SPeter Avalos Jflag++;
167727bfbee1SPeter Avalos break;
167827bfbee1SPeter Avalos #endif
167927bfbee1SPeter Avalos
168041c99275SPeter Avalos case 'l':
1681411677aeSAaron LI #ifdef _WIN32
168241c99275SPeter Avalos /*
168341c99275SPeter Avalos * _IOLBF is the same as _IOFBF in Microsoft's C
168441c99275SPeter Avalos * libraries; the only alternative they offer
168541c99275SPeter Avalos * is _IONBF.
168641c99275SPeter Avalos *
168741c99275SPeter Avalos * XXX - this should really be checking for MSVC++,
1688411677aeSAaron LI * not _WIN32, if, for example, MinGW has its own
168941c99275SPeter Avalos * C library that is more UNIX-compatible.
169041c99275SPeter Avalos */
169141c99275SPeter Avalos setvbuf(stdout, NULL, _IONBF, 0);
1692411677aeSAaron LI #else /* _WIN32 */
169341c99275SPeter Avalos #ifdef HAVE_SETLINEBUF
169441c99275SPeter Avalos setlinebuf(stdout);
169541c99275SPeter Avalos #else
169641c99275SPeter Avalos setvbuf(stdout, NULL, _IOLBF, 0);
169741c99275SPeter Avalos #endif
1698411677aeSAaron LI #endif /* _WIN32 */
1699*ed775ee7SAntonio Huete Jimenez lflag = 1;
170041c99275SPeter Avalos break;
170141c99275SPeter Avalos
1702ea7b4bf5SPeter Avalos case 'K':
1703411677aeSAaron LI ++ndo->ndo_Kflag;
170441c99275SPeter Avalos break;
170541c99275SPeter Avalos
170641c99275SPeter Avalos case 'm':
1707411677aeSAaron LI if (nd_have_smi_support()) {
1708*ed775ee7SAntonio Huete Jimenez if (nd_load_smi_module(optarg, ebuf, sizeof(ebuf)) == -1)
1709411677aeSAaron LI error("%s", ebuf);
1710411677aeSAaron LI } else {
171141c99275SPeter Avalos (void)fprintf(stderr, "%s: ignoring option `-m %s' ",
171241c99275SPeter Avalos program_name, optarg);
171341c99275SPeter Avalos (void)fprintf(stderr, "(no libsmi support)\n");
1714411677aeSAaron LI }
171541c99275SPeter Avalos break;
171641c99275SPeter Avalos
171741c99275SPeter Avalos case 'M':
171841c99275SPeter Avalos /* TCP-MD5 shared secret */
171941c99275SPeter Avalos #ifndef HAVE_LIBCRYPTO
172041c99275SPeter Avalos warning("crypto code not compiled in");
172141c99275SPeter Avalos #endif
1722411677aeSAaron LI ndo->ndo_sigsecret = optarg;
172341c99275SPeter Avalos break;
172441c99275SPeter Avalos
1725ea7b4bf5SPeter Avalos case 'n':
1726411677aeSAaron LI ++ndo->ndo_nflag;
1727ea7b4bf5SPeter Avalos break;
1728ea7b4bf5SPeter Avalos
1729ea7b4bf5SPeter Avalos case 'N':
1730411677aeSAaron LI ++ndo->ndo_Nflag;
1731ea7b4bf5SPeter Avalos break;
1732ea7b4bf5SPeter Avalos
173341c99275SPeter Avalos case 'O':
173441c99275SPeter Avalos Oflag = 0;
173541c99275SPeter Avalos break;
173641c99275SPeter Avalos
173741c99275SPeter Avalos case 'p':
173841c99275SPeter Avalos ++pflag;
173941c99275SPeter Avalos break;
174041c99275SPeter Avalos
174141c99275SPeter Avalos case 'q':
1742411677aeSAaron LI ++ndo->ndo_qflag;
1743411677aeSAaron LI ++ndo->ndo_suppress_default_print;
174441c99275SPeter Avalos break;
174541c99275SPeter Avalos
1746411677aeSAaron LI #ifdef HAVE_PCAP_SETDIRECTION
1747411677aeSAaron LI case 'Q':
1748411677aeSAaron LI if (ascii_strcasecmp(optarg, "in") == 0)
1749411677aeSAaron LI Qflag = PCAP_D_IN;
1750411677aeSAaron LI else if (ascii_strcasecmp(optarg, "out") == 0)
1751411677aeSAaron LI Qflag = PCAP_D_OUT;
1752411677aeSAaron LI else if (ascii_strcasecmp(optarg, "inout") == 0)
1753411677aeSAaron LI Qflag = PCAP_D_INOUT;
1754411677aeSAaron LI else
1755411677aeSAaron LI error("unknown capture direction `%s'", optarg);
1756411677aeSAaron LI break;
1757411677aeSAaron LI #endif /* HAVE_PCAP_SETDIRECTION */
1758411677aeSAaron LI
175941c99275SPeter Avalos case 'r':
176041c99275SPeter Avalos RFileName = optarg;
176141c99275SPeter Avalos break;
176241c99275SPeter Avalos
1763411677aeSAaron LI case 's':
1764*ed775ee7SAntonio Huete Jimenez ndo->ndo_snaplen = (int)strtol(optarg, &end, 0);
176541c99275SPeter Avalos if (optarg == end || *end != '\0'
1766411677aeSAaron LI || ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN)
1767*ed775ee7SAntonio Huete Jimenez error("invalid snaplen %s (must be >= 0 and <= %d)",
1768*ed775ee7SAntonio Huete Jimenez optarg, MAXIMUM_SNAPLEN);
176941c99275SPeter Avalos break;
177041c99275SPeter Avalos
177141c99275SPeter Avalos case 'S':
1772411677aeSAaron LI ++ndo->ndo_Sflag;
177341c99275SPeter Avalos break;
177441c99275SPeter Avalos
177541c99275SPeter Avalos case 't':
1776411677aeSAaron LI ++ndo->ndo_tflag;
177741c99275SPeter Avalos break;
177841c99275SPeter Avalos
177941c99275SPeter Avalos case 'T':
1780411677aeSAaron LI if (ascii_strcasecmp(optarg, "vat") == 0)
1781411677aeSAaron LI ndo->ndo_packettype = PT_VAT;
1782411677aeSAaron LI else if (ascii_strcasecmp(optarg, "wb") == 0)
1783411677aeSAaron LI ndo->ndo_packettype = PT_WB;
1784411677aeSAaron LI else if (ascii_strcasecmp(optarg, "rpc") == 0)
1785411677aeSAaron LI ndo->ndo_packettype = PT_RPC;
1786411677aeSAaron LI else if (ascii_strcasecmp(optarg, "rtp") == 0)
1787411677aeSAaron LI ndo->ndo_packettype = PT_RTP;
1788411677aeSAaron LI else if (ascii_strcasecmp(optarg, "rtcp") == 0)
1789411677aeSAaron LI ndo->ndo_packettype = PT_RTCP;
1790411677aeSAaron LI else if (ascii_strcasecmp(optarg, "snmp") == 0)
1791411677aeSAaron LI ndo->ndo_packettype = PT_SNMP;
1792411677aeSAaron LI else if (ascii_strcasecmp(optarg, "cnfp") == 0)
1793411677aeSAaron LI ndo->ndo_packettype = PT_CNFP;
1794411677aeSAaron LI else if (ascii_strcasecmp(optarg, "tftp") == 0)
1795411677aeSAaron LI ndo->ndo_packettype = PT_TFTP;
1796411677aeSAaron LI else if (ascii_strcasecmp(optarg, "aodv") == 0)
1797411677aeSAaron LI ndo->ndo_packettype = PT_AODV;
1798411677aeSAaron LI else if (ascii_strcasecmp(optarg, "carp") == 0)
1799411677aeSAaron LI ndo->ndo_packettype = PT_CARP;
1800411677aeSAaron LI else if (ascii_strcasecmp(optarg, "radius") == 0)
1801411677aeSAaron LI ndo->ndo_packettype = PT_RADIUS;
1802411677aeSAaron LI else if (ascii_strcasecmp(optarg, "zmtp1") == 0)
1803411677aeSAaron LI ndo->ndo_packettype = PT_ZMTP1;
1804411677aeSAaron LI else if (ascii_strcasecmp(optarg, "vxlan") == 0)
1805411677aeSAaron LI ndo->ndo_packettype = PT_VXLAN;
1806411677aeSAaron LI else if (ascii_strcasecmp(optarg, "pgm") == 0)
1807411677aeSAaron LI ndo->ndo_packettype = PT_PGM;
1808411677aeSAaron LI else if (ascii_strcasecmp(optarg, "pgm_zmtp1") == 0)
1809411677aeSAaron LI ndo->ndo_packettype = PT_PGM_ZMTP1;
1810411677aeSAaron LI else if (ascii_strcasecmp(optarg, "lmp") == 0)
1811411677aeSAaron LI ndo->ndo_packettype = PT_LMP;
1812411677aeSAaron LI else if (ascii_strcasecmp(optarg, "resp") == 0)
1813411677aeSAaron LI ndo->ndo_packettype = PT_RESP;
1814*ed775ee7SAntonio Huete Jimenez else if (ascii_strcasecmp(optarg, "ptp") == 0)
1815*ed775ee7SAntonio Huete Jimenez ndo->ndo_packettype = PT_PTP;
1816*ed775ee7SAntonio Huete Jimenez else if (ascii_strcasecmp(optarg, "someip") == 0)
1817*ed775ee7SAntonio Huete Jimenez ndo->ndo_packettype = PT_SOMEIP;
1818*ed775ee7SAntonio Huete Jimenez else if (ascii_strcasecmp(optarg, "domain") == 0)
1819*ed775ee7SAntonio Huete Jimenez ndo->ndo_packettype = PT_DOMAIN;
182041c99275SPeter Avalos else
182141c99275SPeter Avalos error("unknown packet type `%s'", optarg);
182241c99275SPeter Avalos break;
182341c99275SPeter Avalos
182441c99275SPeter Avalos case 'u':
1825411677aeSAaron LI ++ndo->ndo_uflag;
182641c99275SPeter Avalos break;
182741c99275SPeter Avalos
182841c99275SPeter Avalos #ifdef HAVE_PCAP_DUMP_FLUSH
182941c99275SPeter Avalos case 'U':
183041c99275SPeter Avalos ++Uflag;
183141c99275SPeter Avalos break;
183241c99275SPeter Avalos #endif
183341c99275SPeter Avalos
183441c99275SPeter Avalos case 'v':
1835411677aeSAaron LI ++ndo->ndo_vflag;
1836411677aeSAaron LI break;
1837411677aeSAaron LI
1838411677aeSAaron LI case 'V':
1839411677aeSAaron LI VFileName = optarg;
184041c99275SPeter Avalos break;
184141c99275SPeter Avalos
184241c99275SPeter Avalos case 'w':
184341c99275SPeter Avalos WFileName = optarg;
184441c99275SPeter Avalos break;
184541c99275SPeter Avalos
184641c99275SPeter Avalos case 'W':
184741c99275SPeter Avalos Wflag = atoi(optarg);
1848411677aeSAaron LI if (Wflag <= 0)
184941c99275SPeter Avalos error("invalid number of output files %s", optarg);
185041c99275SPeter Avalos WflagChars = getWflagChars(Wflag);
185141c99275SPeter Avalos break;
185241c99275SPeter Avalos
185341c99275SPeter Avalos case 'x':
1854411677aeSAaron LI ++ndo->ndo_xflag;
1855411677aeSAaron LI ++ndo->ndo_suppress_default_print;
185641c99275SPeter Avalos break;
185741c99275SPeter Avalos
185841c99275SPeter Avalos case 'X':
1859411677aeSAaron LI ++ndo->ndo_Xflag;
1860411677aeSAaron LI ++ndo->ndo_suppress_default_print;
186141c99275SPeter Avalos break;
186241c99275SPeter Avalos
186341c99275SPeter Avalos case 'y':
1864411677aeSAaron LI yflag_dlt_name = optarg;
1865411677aeSAaron LI yflag_dlt =
1866411677aeSAaron LI pcap_datalink_name_to_val(yflag_dlt_name);
1867411677aeSAaron LI if (yflag_dlt < 0)
1868411677aeSAaron LI error("invalid data link type %s", yflag_dlt_name);
186941c99275SPeter Avalos break;
187041c99275SPeter Avalos
1871411677aeSAaron LI #ifdef HAVE_PCAP_SET_PARSER_DEBUG
187241c99275SPeter Avalos case 'Y':
187341c99275SPeter Avalos {
187441c99275SPeter Avalos /* Undocumented flag */
1875411677aeSAaron LI pcap_set_parser_debug(1);
187641c99275SPeter Avalos }
187741c99275SPeter Avalos break;
187841c99275SPeter Avalos #endif
1879ea7b4bf5SPeter Avalos case 'z':
1880411677aeSAaron LI zflag = optarg;
1881ea7b4bf5SPeter Avalos break;
1882ea7b4bf5SPeter Avalos
188341c99275SPeter Avalos case 'Z':
1884411677aeSAaron LI username = optarg;
188541c99275SPeter Avalos break;
188641c99275SPeter Avalos
1887411677aeSAaron LI case '#':
1888411677aeSAaron LI ndo->ndo_packet_number = 1;
1889411677aeSAaron LI break;
1890411677aeSAaron LI
1891411677aeSAaron LI case OPTION_VERSION:
1892*ed775ee7SAntonio Huete Jimenez print_version(stdout);
1893*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_SUCCESS);
1894411677aeSAaron LI break;
1895411677aeSAaron LI
1896411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
1897411677aeSAaron LI case OPTION_TSTAMP_PRECISION:
1898411677aeSAaron LI ndo->ndo_tstamp_precision = tstamp_precision_from_string(optarg);
1899411677aeSAaron LI if (ndo->ndo_tstamp_precision < 0)
1900411677aeSAaron LI error("unsupported time stamp precision");
1901411677aeSAaron LI break;
1902411677aeSAaron LI #endif
1903411677aeSAaron LI
1904411677aeSAaron LI #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
1905411677aeSAaron LI case OPTION_IMMEDIATE_MODE:
1906411677aeSAaron LI immediate_mode = 1;
1907411677aeSAaron LI break;
1908411677aeSAaron LI #endif
1909411677aeSAaron LI
1910*ed775ee7SAntonio Huete Jimenez case OPTION_PRINT:
1911*ed775ee7SAntonio Huete Jimenez print = 1;
1912*ed775ee7SAntonio Huete Jimenez break;
1913*ed775ee7SAntonio Huete Jimenez
1914*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
1915*ed775ee7SAntonio Huete Jimenez case OPTION_TSTAMP_MICRO:
1916*ed775ee7SAntonio Huete Jimenez ndo->ndo_tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
1917*ed775ee7SAntonio Huete Jimenez break;
1918*ed775ee7SAntonio Huete Jimenez
1919*ed775ee7SAntonio Huete Jimenez case OPTION_TSTAMP_NANO:
1920*ed775ee7SAntonio Huete Jimenez ndo->ndo_tstamp_precision = PCAP_TSTAMP_PRECISION_NANO;
1921*ed775ee7SAntonio Huete Jimenez break;
1922*ed775ee7SAntonio Huete Jimenez #endif
1923*ed775ee7SAntonio Huete Jimenez
1924*ed775ee7SAntonio Huete Jimenez case OPTION_FP_TYPE:
1925*ed775ee7SAntonio Huete Jimenez /*
1926*ed775ee7SAntonio Huete Jimenez * Print out the type of floating-point arithmetic
1927*ed775ee7SAntonio Huete Jimenez * we're doing; it's probably IEEE, unless somebody
1928*ed775ee7SAntonio Huete Jimenez * tries to run this on a VAX, but the precision
1929*ed775ee7SAntonio Huete Jimenez * may differ (e.g., it might be 32-bit, 64-bit,
1930*ed775ee7SAntonio Huete Jimenez * or 80-bit).
1931*ed775ee7SAntonio Huete Jimenez */
1932*ed775ee7SAntonio Huete Jimenez float_type_check(0x4e93312d);
1933*ed775ee7SAntonio Huete Jimenez return 0;
1934*ed775ee7SAntonio Huete Jimenez
1935*ed775ee7SAntonio Huete Jimenez case OPTION_COUNT:
1936*ed775ee7SAntonio Huete Jimenez count_mode = 1;
1937*ed775ee7SAntonio Huete Jimenez break;
1938*ed775ee7SAntonio Huete Jimenez
193941c99275SPeter Avalos default:
1940*ed775ee7SAntonio Huete Jimenez print_usage(stderr);
1941*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_ERR_HOST_PROGRAM);
194241c99275SPeter Avalos /* NOTREACHED */
194341c99275SPeter Avalos }
194441c99275SPeter Avalos
1945411677aeSAaron LI #ifdef HAVE_PCAP_FINDALLDEVS
1946411677aeSAaron LI if (Dflag)
1947411677aeSAaron LI show_devices_and_exit();
1948411677aeSAaron LI #endif
1949*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS_EX
1950*ed775ee7SAntonio Huete Jimenez if (remote_interfaces_source != NULL)
1951*ed775ee7SAntonio Huete Jimenez show_remote_devices_and_exit();
1952*ed775ee7SAntonio Huete Jimenez #endif
1953*ed775ee7SAntonio Huete Jimenez
1954*ed775ee7SAntonio Huete Jimenez #if defined(DLT_LINUX_SLL2) && defined(HAVE_PCAP_SET_DATALINK)
1955*ed775ee7SAntonio Huete Jimenez /* Set default linktype DLT_LINUX_SLL2 when capturing on the "any" device */
1956*ed775ee7SAntonio Huete Jimenez if (device != NULL &&
1957*ed775ee7SAntonio Huete Jimenez strncmp (device, "any", strlen("any")) == 0
1958*ed775ee7SAntonio Huete Jimenez && yflag_dlt == -1)
1959*ed775ee7SAntonio Huete Jimenez yflag_dlt = DLT_LINUX_SLL2;
1960*ed775ee7SAntonio Huete Jimenez #endif
1961411677aeSAaron LI
1962411677aeSAaron LI switch (ndo->ndo_tflag) {
196341c99275SPeter Avalos
196441c99275SPeter Avalos case 0: /* Default */
196541c99275SPeter Avalos case 1: /* No time stamp */
196641c99275SPeter Avalos case 2: /* Unix timeval style */
1967*ed775ee7SAntonio Huete Jimenez case 3: /* Microseconds/nanoseconds since previous packet */
1968*ed775ee7SAntonio Huete Jimenez case 4: /* Date + Default */
1969*ed775ee7SAntonio Huete Jimenez case 5: /* Microseconds/nanoseconds since first packet */
197041c99275SPeter Avalos break;
197141c99275SPeter Avalos
197241c99275SPeter Avalos default: /* Not supported */
1973ea7b4bf5SPeter Avalos error("only -t, -tt, -ttt, -tttt and -ttttt are supported");
197441c99275SPeter Avalos break;
197541c99275SPeter Avalos }
197641c99275SPeter Avalos
1977411677aeSAaron LI if (ndo->ndo_fflag != 0 && (VFileName != NULL || RFileName != NULL))
1978411677aeSAaron LI error("-f can not be used with -V or -r");
1979411677aeSAaron LI
1980411677aeSAaron LI if (VFileName != NULL && RFileName != NULL)
1981411677aeSAaron LI error("-V and -r are mutually exclusive.");
1982411677aeSAaron LI
1983411677aeSAaron LI /*
1984*ed775ee7SAntonio Huete Jimenez * If we're printing dissected packets to the standard output,
1985*ed775ee7SAntonio Huete Jimenez * and either the standard output is a terminal or we're doing
1986*ed775ee7SAntonio Huete Jimenez * "line" buffering, set the capture timeout to .1 second rather
1987*ed775ee7SAntonio Huete Jimenez * than 1 second, as the user's probably expecting to see packets
1988*ed775ee7SAntonio Huete Jimenez * pop up immediately shortly after they arrive.
1989*ed775ee7SAntonio Huete Jimenez *
1990*ed775ee7SAntonio Huete Jimenez * XXX - would there be some value appropriate for all cases,
1991*ed775ee7SAntonio Huete Jimenez * based on, say, the buffer size and packet input rate?
1992411677aeSAaron LI */
1993*ed775ee7SAntonio Huete Jimenez if ((WFileName == NULL || print) && (isatty(1) || lflag))
1994*ed775ee7SAntonio Huete Jimenez timeout = 100;
1995411677aeSAaron LI
199641c99275SPeter Avalos #ifdef WITH_CHROOT
199741c99275SPeter Avalos /* if run as root, prepare for chrooting */
199841c99275SPeter Avalos if (getuid() == 0 || geteuid() == 0) {
199941c99275SPeter Avalos /* future extensibility for cmd-line arguments */
200041c99275SPeter Avalos if (!chroot_dir)
200141c99275SPeter Avalos chroot_dir = WITH_CHROOT;
200241c99275SPeter Avalos }
200341c99275SPeter Avalos #endif
200441c99275SPeter Avalos
200541c99275SPeter Avalos #ifdef WITH_USER
200641c99275SPeter Avalos /* if run as root, prepare for dropping root privileges */
200741c99275SPeter Avalos if (getuid() == 0 || geteuid() == 0) {
200841c99275SPeter Avalos /* Run with '-Z root' to restore old behaviour */
200941c99275SPeter Avalos if (!username)
201041c99275SPeter Avalos username = WITH_USER;
201141c99275SPeter Avalos }
201241c99275SPeter Avalos #endif
201341c99275SPeter Avalos
2014411677aeSAaron LI if (RFileName != NULL || VFileName != NULL) {
2015411677aeSAaron LI /*
2016411677aeSAaron LI * If RFileName is non-null, it's the pathname of a
2017411677aeSAaron LI * savefile to read. If VFileName is non-null, it's
2018411677aeSAaron LI * the pathname of a file containing a list of pathnames
2019411677aeSAaron LI * (one per line) of savefiles to read.
2020411677aeSAaron LI *
2021411677aeSAaron LI * In either case, we're reading a savefile, not doing
2022411677aeSAaron LI * a live capture.
2023411677aeSAaron LI */
2024411677aeSAaron LI #ifndef _WIN32
202541c99275SPeter Avalos /*
202641c99275SPeter Avalos * We don't need network access, so relinquish any set-UID
202741c99275SPeter Avalos * or set-GID privileges we have (if any).
202841c99275SPeter Avalos *
202941c99275SPeter Avalos * We do *not* want set-UID privileges when opening a
203041c99275SPeter Avalos * trace file, as that might let the user read other
203141c99275SPeter Avalos * people's trace files (especially if we're set-UID
203241c99275SPeter Avalos * root).
203341c99275SPeter Avalos */
203441c99275SPeter Avalos if (setgid(getgid()) != 0 || setuid(getuid()) != 0 )
203541c99275SPeter Avalos fprintf(stderr, "Warning: setgid/setuid failed !\n");
2036411677aeSAaron LI #endif /* _WIN32 */
2037411677aeSAaron LI if (VFileName != NULL) {
2038411677aeSAaron LI if (VFileName[0] == '-' && VFileName[1] == '\0')
2039411677aeSAaron LI VFile = stdin;
2040411677aeSAaron LI else
2041411677aeSAaron LI VFile = fopen(VFileName, "r");
2042411677aeSAaron LI
2043411677aeSAaron LI if (VFile == NULL)
2044411677aeSAaron LI error("Unable to open file: %s\n", pcap_strerror(errno));
2045411677aeSAaron LI
2046411677aeSAaron LI ret = get_next_file(VFile, VFileLine);
2047411677aeSAaron LI if (!ret)
2048411677aeSAaron LI error("Nothing in %s\n", VFileName);
2049411677aeSAaron LI RFileName = VFileLine;
2050411677aeSAaron LI }
2051411677aeSAaron LI
2052411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
2053411677aeSAaron LI pd = pcap_open_offline_with_tstamp_precision(RFileName,
2054411677aeSAaron LI ndo->ndo_tstamp_precision, ebuf);
2055411677aeSAaron LI #else
205641c99275SPeter Avalos pd = pcap_open_offline(RFileName, ebuf);
2057411677aeSAaron LI #endif
2058411677aeSAaron LI
205941c99275SPeter Avalos if (pd == NULL)
206041c99275SPeter Avalos error("%s", ebuf);
2061411677aeSAaron LI #ifdef HAVE_CAPSICUM
2062411677aeSAaron LI cap_rights_init(&rights, CAP_READ);
2063411677aeSAaron LI if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 &&
2064411677aeSAaron LI errno != ENOSYS) {
2065411677aeSAaron LI error("unable to limit pcap descriptor");
2066411677aeSAaron LI }
2067411677aeSAaron LI #endif
206841c99275SPeter Avalos dlt = pcap_datalink(pd);
206941c99275SPeter Avalos dlt_name = pcap_datalink_val_to_name(dlt);
2070*ed775ee7SAntonio Huete Jimenez fprintf(stderr, "reading from file %s", RFileName);
207141c99275SPeter Avalos if (dlt_name == NULL) {
2072*ed775ee7SAntonio Huete Jimenez fprintf(stderr, ", link-type %u", dlt);
207341c99275SPeter Avalos } else {
2074*ed775ee7SAntonio Huete Jimenez fprintf(stderr, ", link-type %s (%s)", dlt_name,
207541c99275SPeter Avalos pcap_datalink_val_to_description(dlt));
207641c99275SPeter Avalos }
2077*ed775ee7SAntonio Huete Jimenez fprintf(stderr, ", snapshot length %d\n", pcap_snapshot(pd));
2078*ed775ee7SAntonio Huete Jimenez #ifdef DLT_LINUX_SLL2
2079*ed775ee7SAntonio Huete Jimenez if (dlt == DLT_LINUX_SLL2)
2080*ed775ee7SAntonio Huete Jimenez fprintf(stderr, "Warning: interface names might be incorrect\n");
2081*ed775ee7SAntonio Huete Jimenez #endif
2082*ed775ee7SAntonio Huete Jimenez } else if (dflag && !device) {
2083*ed775ee7SAntonio Huete Jimenez int dump_dlt = DLT_EN10MB;
2084*ed775ee7SAntonio Huete Jimenez /*
2085*ed775ee7SAntonio Huete Jimenez * We're dumping the compiled code without an explicit
2086*ed775ee7SAntonio Huete Jimenez * device specification. (If a device is specified, we
2087*ed775ee7SAntonio Huete Jimenez * definitely want to open it to use the DLT of that device.)
2088*ed775ee7SAntonio Huete Jimenez * Either default to DLT_EN10MB with a warning, or use
2089*ed775ee7SAntonio Huete Jimenez * the user-specified value if supplied.
2090*ed775ee7SAntonio Huete Jimenez */
2091*ed775ee7SAntonio Huete Jimenez /*
2092*ed775ee7SAntonio Huete Jimenez * If no snapshot length was specified, or a length of 0 was
2093*ed775ee7SAntonio Huete Jimenez * specified, default to 256KB.
2094*ed775ee7SAntonio Huete Jimenez */
2095*ed775ee7SAntonio Huete Jimenez if (ndo->ndo_snaplen == 0)
2096*ed775ee7SAntonio Huete Jimenez ndo->ndo_snaplen = MAXIMUM_SNAPLEN;
2097*ed775ee7SAntonio Huete Jimenez /*
2098*ed775ee7SAntonio Huete Jimenez * If a DLT was specified with the -y flag, use that instead.
2099*ed775ee7SAntonio Huete Jimenez */
2100*ed775ee7SAntonio Huete Jimenez if (yflag_dlt != -1)
2101*ed775ee7SAntonio Huete Jimenez dump_dlt = yflag_dlt;
2102*ed775ee7SAntonio Huete Jimenez else
2103*ed775ee7SAntonio Huete Jimenez fprintf(stderr, "Warning: assuming Ethernet\n");
2104*ed775ee7SAntonio Huete Jimenez pd = pcap_open_dead(dump_dlt, ndo->ndo_snaplen);
210541c99275SPeter Avalos } else {
2106411677aeSAaron LI /*
2107411677aeSAaron LI * We're doing a live capture.
2108411677aeSAaron LI */
210941c99275SPeter Avalos if (device == NULL) {
2110411677aeSAaron LI /*
2111411677aeSAaron LI * No interface was specified. Pick one.
2112411677aeSAaron LI */
2113411677aeSAaron LI #ifdef HAVE_PCAP_FINDALLDEVS
2114411677aeSAaron LI /*
2115411677aeSAaron LI * Find the list of interfaces, and pick
2116411677aeSAaron LI * the first interface.
2117411677aeSAaron LI */
2118*ed775ee7SAntonio Huete Jimenez if (pcap_findalldevs(&devlist, ebuf) == -1)
2119*ed775ee7SAntonio Huete Jimenez error("%s", ebuf);
2120*ed775ee7SAntonio Huete Jimenez if (devlist == NULL)
2121*ed775ee7SAntonio Huete Jimenez error("no interfaces available for capture");
2122411677aeSAaron LI device = strdup(devlist->name);
2123411677aeSAaron LI pcap_freealldevs(devlist);
2124411677aeSAaron LI #else /* HAVE_PCAP_FINDALLDEVS */
2125411677aeSAaron LI /*
2126411677aeSAaron LI * Use whatever interface pcap_lookupdev()
2127411677aeSAaron LI * chooses.
2128411677aeSAaron LI */
212941c99275SPeter Avalos device = pcap_lookupdev(ebuf);
213041c99275SPeter Avalos if (device == NULL)
213141c99275SPeter Avalos error("%s", ebuf);
2132*ed775ee7SAntonio Huete Jimenez #endif
213341c99275SPeter Avalos }
2134411677aeSAaron LI
2135411677aeSAaron LI /*
2136411677aeSAaron LI * Try to open the interface with the specified name.
2137411677aeSAaron LI */
2138411677aeSAaron LI pd = open_interface(device, ndo, ebuf);
2139411677aeSAaron LI if (pd == NULL) {
2140411677aeSAaron LI /*
2141411677aeSAaron LI * That failed. If we can get a list of
2142411677aeSAaron LI * interfaces, and the interface name
2143411677aeSAaron LI * is purely numeric, try to use it as
2144411677aeSAaron LI * a 1-based index in the list of
2145411677aeSAaron LI * interfaces.
2146411677aeSAaron LI */
2147411677aeSAaron LI #ifdef HAVE_PCAP_FINDALLDEVS
2148411677aeSAaron LI devnum = parse_interface_number(device);
2149411677aeSAaron LI if (devnum == -1) {
2150411677aeSAaron LI /*
2151411677aeSAaron LI * It's not a number; just report
2152411677aeSAaron LI * the open error and fail.
2153411677aeSAaron LI */
2154411677aeSAaron LI error("%s", ebuf);
215541c99275SPeter Avalos }
215641c99275SPeter Avalos
2157411677aeSAaron LI /*
2158411677aeSAaron LI * OK, it's a number; try to find the
2159411677aeSAaron LI * interface with that index, and try
2160411677aeSAaron LI * to open it.
2161411677aeSAaron LI *
2162411677aeSAaron LI * find_interface_by_number() exits if it
2163411677aeSAaron LI * couldn't be found.
2164411677aeSAaron LI */
2165*ed775ee7SAntonio Huete Jimenez device = find_interface_by_number(device, devnum);
2166411677aeSAaron LI pd = open_interface(device, ndo, ebuf);
2167ea7b4bf5SPeter Avalos if (pd == NULL)
2168ea7b4bf5SPeter Avalos error("%s", ebuf);
2169411677aeSAaron LI #else /* HAVE_PCAP_FINDALLDEVS */
217027bfbee1SPeter Avalos /*
2171411677aeSAaron LI * We can't get a list of interfaces; just
2172411677aeSAaron LI * fail.
217327bfbee1SPeter Avalos */
217441c99275SPeter Avalos error("%s", ebuf);
2175411677aeSAaron LI #endif /* HAVE_PCAP_FINDALLDEVS */
2176411677aeSAaron LI }
2177411677aeSAaron LI
217841c99275SPeter Avalos /*
2179*ed775ee7SAntonio Huete Jimenez * Let user own process after capture device has
2180*ed775ee7SAntonio Huete Jimenez * been opened.
218141c99275SPeter Avalos */
2182411677aeSAaron LI #ifndef _WIN32
218341c99275SPeter Avalos if (setgid(getgid()) != 0 || setuid(getuid()) != 0)
218441c99275SPeter Avalos fprintf(stderr, "Warning: setgid/setuid failed !\n");
2185411677aeSAaron LI #endif /* _WIN32 */
2186411677aeSAaron LI #if !defined(HAVE_PCAP_CREATE) && defined(_WIN32)
2187ea7b4bf5SPeter Avalos if(Bflag != 0)
2188ea7b4bf5SPeter Avalos if(pcap_setbuff(pd, Bflag)==-1){
218941c99275SPeter Avalos error("%s", pcap_geterr(pd));
219041c99275SPeter Avalos }
2191411677aeSAaron LI #endif /* !defined(HAVE_PCAP_CREATE) && defined(_WIN32) */
219241c99275SPeter Avalos if (Lflag)
2193411677aeSAaron LI show_dlts_and_exit(pd, device);
2194411677aeSAaron LI if (yflag_dlt >= 0) {
219541c99275SPeter Avalos #ifdef HAVE_PCAP_SET_DATALINK
2196411677aeSAaron LI if (pcap_set_datalink(pd, yflag_dlt) < 0)
219741c99275SPeter Avalos error("%s", pcap_geterr(pd));
219841c99275SPeter Avalos #else
219941c99275SPeter Avalos /*
220041c99275SPeter Avalos * We don't actually support changing the
220141c99275SPeter Avalos * data link type, so we only let them
220241c99275SPeter Avalos * set it to what it already is.
220341c99275SPeter Avalos */
2204411677aeSAaron LI if (yflag_dlt != pcap_datalink(pd)) {
220541c99275SPeter Avalos error("%s is not one of the DLTs supported by this device\n",
2206411677aeSAaron LI yflag_dlt_name);
220741c99275SPeter Avalos }
220841c99275SPeter Avalos #endif
220941c99275SPeter Avalos (void)fprintf(stderr, "%s: data link type %s\n",
2210*ed775ee7SAntonio Huete Jimenez program_name,
2211*ed775ee7SAntonio Huete Jimenez pcap_datalink_val_to_name(yflag_dlt));
221241c99275SPeter Avalos (void)fflush(stderr);
221341c99275SPeter Avalos }
221441c99275SPeter Avalos i = pcap_snapshot(pd);
2215411677aeSAaron LI if (ndo->ndo_snaplen < i) {
2216*ed775ee7SAntonio Huete Jimenez if (ndo->ndo_snaplen != 0)
2217411677aeSAaron LI warning("snaplen raised from %d to %d", ndo->ndo_snaplen, i);
2218411677aeSAaron LI ndo->ndo_snaplen = i;
2219*ed775ee7SAntonio Huete Jimenez } else if (ndo->ndo_snaplen > i) {
2220*ed775ee7SAntonio Huete Jimenez warning("snaplen lowered from %d to %d", ndo->ndo_snaplen, i);
2221*ed775ee7SAntonio Huete Jimenez ndo->ndo_snaplen = i;
222241c99275SPeter Avalos }
2223411677aeSAaron LI if(ndo->ndo_fflag != 0) {
222441c99275SPeter Avalos if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
2225411677aeSAaron LI warning("foreign (-f) flag used but: %s", ebuf);
222641c99275SPeter Avalos }
222741c99275SPeter Avalos }
2228411677aeSAaron LI
2229411677aeSAaron LI }
223041c99275SPeter Avalos if (infile)
223141c99275SPeter Avalos cmdbuf = read_infile(infile);
223241c99275SPeter Avalos else
223341c99275SPeter Avalos cmdbuf = copy_argv(&argv[optind]);
223441c99275SPeter Avalos
2235411677aeSAaron LI #ifdef HAVE_PCAP_SET_OPTIMIZER_DEBUG
2236411677aeSAaron LI pcap_set_optimizer_debug(dflag);
2237411677aeSAaron LI #endif
223841c99275SPeter Avalos if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
223941c99275SPeter Avalos error("%s", pcap_geterr(pd));
224041c99275SPeter Avalos if (dflag) {
224141c99275SPeter Avalos bpf_dump(&fcode, dflag);
224241c99275SPeter Avalos pcap_close(pd);
2243411677aeSAaron LI free(cmdbuf);
2244411677aeSAaron LI pcap_freecode(&fcode);
2245*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_SUCCESS);
224641c99275SPeter Avalos }
2247*ed775ee7SAntonio Huete Jimenez
2248*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_CASPER
2249*ed775ee7SAntonio Huete Jimenez if (!ndo->ndo_nflag)
2250*ed775ee7SAntonio Huete Jimenez capdns = capdns_setup();
2251*ed775ee7SAntonio Huete Jimenez #endif /* HAVE_CASPER */
2252*ed775ee7SAntonio Huete Jimenez
2253*ed775ee7SAntonio Huete Jimenez init_print(ndo, localnet, netmask);
225441c99275SPeter Avalos
2255411677aeSAaron LI #ifndef _WIN32
225641c99275SPeter Avalos (void)setsignal(SIGPIPE, cleanup);
225741c99275SPeter Avalos (void)setsignal(SIGTERM, cleanup);
2258411677aeSAaron LI #endif /* _WIN32 */
2259*ed775ee7SAntonio Huete Jimenez (void)setsignal(SIGINT, cleanup);
226027bfbee1SPeter Avalos #if defined(HAVE_FORK) || defined(HAVE_VFORK)
226127bfbee1SPeter Avalos (void)setsignal(SIGCHLD, child_cleanup);
226227bfbee1SPeter Avalos #endif
226341c99275SPeter Avalos /* Cooperate with nohup(1) */
2264411677aeSAaron LI #ifndef _WIN32
226541c99275SPeter Avalos if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
226641c99275SPeter Avalos (void)setsignal(SIGHUP, oldhandler);
2267411677aeSAaron LI #endif /* _WIN32 */
226841c99275SPeter Avalos
2269411677aeSAaron LI #ifndef _WIN32
227027bfbee1SPeter Avalos /*
227127bfbee1SPeter Avalos * If a user name was specified with "-Z", attempt to switch to
227227bfbee1SPeter Avalos * that user's UID. This would probably be used with sudo,
227327bfbee1SPeter Avalos * to allow tcpdump to be run in a special restricted
227427bfbee1SPeter Avalos * account (if you just want to allow users to open capture
227527bfbee1SPeter Avalos * devices, and can't just give users that permission,
227627bfbee1SPeter Avalos * you'd make tcpdump set-UID or set-GID).
227727bfbee1SPeter Avalos *
227827bfbee1SPeter Avalos * Tcpdump doesn't necessarily write only to one savefile;
227927bfbee1SPeter Avalos * the general only way to allow a -Z instance to write to
228027bfbee1SPeter Avalos * savefiles as the user under whose UID it's run, rather
228127bfbee1SPeter Avalos * than as the user specified with -Z, would thus be to switch
228227bfbee1SPeter Avalos * to the original user ID before opening a capture file and
228327bfbee1SPeter Avalos * then switch back to the -Z user ID after opening the savefile.
228427bfbee1SPeter Avalos * Switching to the -Z user ID only after opening the first
228527bfbee1SPeter Avalos * savefile doesn't handle the general case.
228627bfbee1SPeter Avalos */
2287411677aeSAaron LI
228827bfbee1SPeter Avalos if (getuid() == 0 || geteuid() == 0) {
2289411677aeSAaron LI #ifdef HAVE_LIBCAP_NG
2290411677aeSAaron LI /* Initialize capng */
2291411677aeSAaron LI capng_clear(CAPNG_SELECT_BOTH);
2292411677aeSAaron LI if (username) {
2293*ed775ee7SAntonio Huete Jimenez DIAG_OFF_CLANG(assign-enum)
2294411677aeSAaron LI capng_updatev(
2295411677aeSAaron LI CAPNG_ADD,
2296411677aeSAaron LI CAPNG_PERMITTED | CAPNG_EFFECTIVE,
2297411677aeSAaron LI CAP_SETUID,
2298411677aeSAaron LI CAP_SETGID,
2299411677aeSAaron LI -1);
2300*ed775ee7SAntonio Huete Jimenez DIAG_ON_CLANG(assign-enum)
2301411677aeSAaron LI }
2302411677aeSAaron LI if (chroot_dir) {
2303*ed775ee7SAntonio Huete Jimenez DIAG_OFF_CLANG(assign-enum)
2304411677aeSAaron LI capng_update(
2305411677aeSAaron LI CAPNG_ADD,
2306411677aeSAaron LI CAPNG_PERMITTED | CAPNG_EFFECTIVE,
2307411677aeSAaron LI CAP_SYS_CHROOT
2308411677aeSAaron LI );
2309*ed775ee7SAntonio Huete Jimenez DIAG_ON_CLANG(assign-enum)
2310411677aeSAaron LI }
2311411677aeSAaron LI
2312411677aeSAaron LI if (WFileName) {
2313*ed775ee7SAntonio Huete Jimenez DIAG_OFF_CLANG(assign-enum)
2314411677aeSAaron LI capng_update(
2315411677aeSAaron LI CAPNG_ADD,
2316411677aeSAaron LI CAPNG_PERMITTED | CAPNG_EFFECTIVE,
2317411677aeSAaron LI CAP_DAC_OVERRIDE
2318411677aeSAaron LI );
2319*ed775ee7SAntonio Huete Jimenez DIAG_ON_CLANG(assign-enum)
2320411677aeSAaron LI }
2321411677aeSAaron LI capng_apply(CAPNG_SELECT_BOTH);
2322411677aeSAaron LI #endif /* HAVE_LIBCAP_NG */
232327bfbee1SPeter Avalos if (username || chroot_dir)
232427bfbee1SPeter Avalos droproot(username, chroot_dir);
2325411677aeSAaron LI
232627bfbee1SPeter Avalos }
2327411677aeSAaron LI #endif /* _WIN32 */
232827bfbee1SPeter Avalos
232941c99275SPeter Avalos if (pcap_setfilter(pd, &fcode) < 0)
233041c99275SPeter Avalos error("%s", pcap_geterr(pd));
2331411677aeSAaron LI #ifdef HAVE_CAPSICUM
2332*ed775ee7SAntonio Huete Jimenez if (RFileName == NULL && VFileName == NULL && pcap_fileno(pd) != -1) {
2333411677aeSAaron LI static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
2334411677aeSAaron LI
2335411677aeSAaron LI /*
2336411677aeSAaron LI * The various libpcap devices use a combination of
2337411677aeSAaron LI * read (bpf), ioctl (bpf, netmap), poll (netmap)
2338411677aeSAaron LI * so we add the relevant access rights.
2339411677aeSAaron LI */
2340411677aeSAaron LI cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_EVENT);
2341411677aeSAaron LI if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 &&
2342411677aeSAaron LI errno != ENOSYS) {
2343411677aeSAaron LI error("unable to limit pcap descriptor");
2344411677aeSAaron LI }
2345411677aeSAaron LI if (cap_ioctls_limit(pcap_fileno(pd), cmds,
2346411677aeSAaron LI sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) {
2347411677aeSAaron LI error("unable to limit ioctls on pcap descriptor");
2348411677aeSAaron LI }
2349411677aeSAaron LI }
2350411677aeSAaron LI #endif
235141c99275SPeter Avalos if (WFileName) {
2352411677aeSAaron LI /* Do not exceed the default PATH_MAX for files. */
2353411677aeSAaron LI dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1);
235441c99275SPeter Avalos
2355ea7b4bf5SPeter Avalos if (dumpinfo.CurrentFileName == NULL)
2356ea7b4bf5SPeter Avalos error("malloc of dumpinfo.CurrentFileName");
2357ea7b4bf5SPeter Avalos
2358ea7b4bf5SPeter Avalos /* We do not need numbering for dumpfiles if Cflag isn't set. */
2359ea7b4bf5SPeter Avalos if (Cflag != 0)
2360ea7b4bf5SPeter Avalos MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars);
2361ea7b4bf5SPeter Avalos else
2362ea7b4bf5SPeter Avalos MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0);
2363ea7b4bf5SPeter Avalos
2364*ed775ee7SAntonio Huete Jimenez pdd = pcap_dump_open(pd, dumpinfo.CurrentFileName);
2365411677aeSAaron LI #ifdef HAVE_LIBCAP_NG
2366411677aeSAaron LI /* Give up CAP_DAC_OVERRIDE capability.
2367411677aeSAaron LI * Only allow it to be restored if the -C or -G flag have been
2368411677aeSAaron LI * set since we may need to create more files later on.
2369411677aeSAaron LI */
2370411677aeSAaron LI capng_update(
2371411677aeSAaron LI CAPNG_DROP,
2372411677aeSAaron LI (Cflag || Gflag ? 0 : CAPNG_PERMITTED)
2373411677aeSAaron LI | CAPNG_EFFECTIVE,
2374411677aeSAaron LI CAP_DAC_OVERRIDE
2375411677aeSAaron LI );
2376411677aeSAaron LI capng_apply(CAPNG_SELECT_BOTH);
2377411677aeSAaron LI #endif /* HAVE_LIBCAP_NG */
2378*ed775ee7SAntonio Huete Jimenez if (pdd == NULL)
237941c99275SPeter Avalos error("%s", pcap_geterr(pd));
2380411677aeSAaron LI #ifdef HAVE_CAPSICUM
2381*ed775ee7SAntonio Huete Jimenez set_dumper_capsicum_rights(pdd);
2382411677aeSAaron LI #endif
2383ea7b4bf5SPeter Avalos if (Cflag != 0 || Gflag != 0) {
2384411677aeSAaron LI #ifdef HAVE_CAPSICUM
2385411677aeSAaron LI dumpinfo.WFileName = strdup(basename(WFileName));
2386411677aeSAaron LI if (dumpinfo.WFileName == NULL) {
2387411677aeSAaron LI error("Unable to allocate memory for file %s",
2388411677aeSAaron LI WFileName);
2389411677aeSAaron LI }
2390411677aeSAaron LI dumpinfo.dirfd = open(dirname(WFileName),
2391411677aeSAaron LI O_DIRECTORY | O_RDONLY);
2392411677aeSAaron LI if (dumpinfo.dirfd < 0) {
2393411677aeSAaron LI error("unable to open directory %s",
2394411677aeSAaron LI dirname(WFileName));
2395411677aeSAaron LI }
2396411677aeSAaron LI cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL,
2397411677aeSAaron LI CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE);
2398411677aeSAaron LI if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 &&
2399411677aeSAaron LI errno != ENOSYS) {
2400411677aeSAaron LI error("unable to limit directory rights");
2401411677aeSAaron LI }
2402411677aeSAaron LI if (cap_fcntls_limit(dumpinfo.dirfd, CAP_FCNTL_GETFL) < 0 &&
2403411677aeSAaron LI errno != ENOSYS) {
2404411677aeSAaron LI error("unable to limit dump descriptor fcntls");
2405411677aeSAaron LI }
2406411677aeSAaron LI #else /* !HAVE_CAPSICUM */
240741c99275SPeter Avalos dumpinfo.WFileName = WFileName;
2408411677aeSAaron LI #endif
2409411677aeSAaron LI callback = dump_packet_and_trunc;
241041c99275SPeter Avalos dumpinfo.pd = pd;
2411*ed775ee7SAntonio Huete Jimenez dumpinfo.pdd = pdd;
241241c99275SPeter Avalos pcap_userdata = (u_char *)&dumpinfo;
241341c99275SPeter Avalos } else {
241441c99275SPeter Avalos callback = dump_packet;
2415*ed775ee7SAntonio Huete Jimenez dumpinfo.WFileName = WFileName;
2416*ed775ee7SAntonio Huete Jimenez dumpinfo.pd = pd;
2417*ed775ee7SAntonio Huete Jimenez dumpinfo.pdd = pdd;
2418*ed775ee7SAntonio Huete Jimenez pcap_userdata = (u_char *)&dumpinfo;
241941c99275SPeter Avalos }
2420*ed775ee7SAntonio Huete Jimenez if (print) {
2421*ed775ee7SAntonio Huete Jimenez dlt = pcap_datalink(pd);
2422*ed775ee7SAntonio Huete Jimenez ndo->ndo_if_printer = get_if_printer(dlt);
2423*ed775ee7SAntonio Huete Jimenez dumpinfo.ndo = ndo;
2424*ed775ee7SAntonio Huete Jimenez } else
2425*ed775ee7SAntonio Huete Jimenez dumpinfo.ndo = NULL;
2426*ed775ee7SAntonio Huete Jimenez
242727bfbee1SPeter Avalos #ifdef HAVE_PCAP_DUMP_FLUSH
242827bfbee1SPeter Avalos if (Uflag)
2429*ed775ee7SAntonio Huete Jimenez pcap_dump_flush(pdd);
243027bfbee1SPeter Avalos #endif
243141c99275SPeter Avalos } else {
2432411677aeSAaron LI dlt = pcap_datalink(pd);
2433*ed775ee7SAntonio Huete Jimenez ndo->ndo_if_printer = get_if_printer(dlt);
243441c99275SPeter Avalos callback = print_packet;
2435411677aeSAaron LI pcap_userdata = (u_char *)ndo;
243641c99275SPeter Avalos }
243727bfbee1SPeter Avalos
24386263709fSPeter Avalos #ifdef SIGNAL_REQ_INFO
2439ea7b4bf5SPeter Avalos /*
2440ea7b4bf5SPeter Avalos * We can't get statistics when reading from a file rather
2441ea7b4bf5SPeter Avalos * than capturing from a device.
2442ea7b4bf5SPeter Avalos */
2443ea7b4bf5SPeter Avalos if (RFileName == NULL)
24446263709fSPeter Avalos (void)setsignal(SIGNAL_REQ_INFO, requestinfo);
244541c99275SPeter Avalos #endif
2446*ed775ee7SAntonio Huete Jimenez #ifdef SIGNAL_FLUSH_PCAP
2447*ed775ee7SAntonio Huete Jimenez (void)setsignal(SIGNAL_FLUSH_PCAP, flushpcap);
244841c99275SPeter Avalos #endif
2449*ed775ee7SAntonio Huete Jimenez
2450*ed775ee7SAntonio Huete Jimenez if (ndo->ndo_vflag > 0 && WFileName && RFileName == NULL && !print) {
2451*ed775ee7SAntonio Huete Jimenez /*
2452*ed775ee7SAntonio Huete Jimenez * When capturing to a file, if "--print" wasn't specified,
2453*ed775ee7SAntonio Huete Jimenez *"-v" means tcpdump should, once per second,
2454*ed775ee7SAntonio Huete Jimenez * "v"erbosely report the number of packets captured.
2455*ed775ee7SAntonio Huete Jimenez * Except when reading from a file, because -r, -w and -v
2456*ed775ee7SAntonio Huete Jimenez * together used to make a corner case, in which pcap_loop()
2457*ed775ee7SAntonio Huete Jimenez * errored due to EINTR (see GH #155 for details).
2458*ed775ee7SAntonio Huete Jimenez */
2459*ed775ee7SAntonio Huete Jimenez #ifdef _WIN32
2460*ed775ee7SAntonio Huete Jimenez /*
2461*ed775ee7SAntonio Huete Jimenez * https://blogs.msdn.microsoft.com/oldnewthing/20151230-00/?p=92741
2462*ed775ee7SAntonio Huete Jimenez *
2463*ed775ee7SAntonio Huete Jimenez * suggests that this dates back to W2K.
2464*ed775ee7SAntonio Huete Jimenez *
2465*ed775ee7SAntonio Huete Jimenez * I don't know what a "long wait" is, but we'll assume
2466*ed775ee7SAntonio Huete Jimenez * that printing the stats could be a "long wait".
2467*ed775ee7SAntonio Huete Jimenez */
2468*ed775ee7SAntonio Huete Jimenez CreateTimerQueueTimer(&timer_handle, NULL,
2469*ed775ee7SAntonio Huete Jimenez verbose_stats_dump, NULL, 1000, 1000,
2470*ed775ee7SAntonio Huete Jimenez WT_EXECUTEDEFAULT|WT_EXECUTELONGFUNCTION);
2471*ed775ee7SAntonio Huete Jimenez setvbuf(stderr, NULL, _IONBF, 0);
2472*ed775ee7SAntonio Huete Jimenez #else /* _WIN32 */
2473*ed775ee7SAntonio Huete Jimenez /*
2474*ed775ee7SAntonio Huete Jimenez * Assume this is UN*X, and that it has setitimer(); that
2475*ed775ee7SAntonio Huete Jimenez * dates back to UNIX 95.
2476*ed775ee7SAntonio Huete Jimenez */
2477*ed775ee7SAntonio Huete Jimenez struct itimerval timer;
2478*ed775ee7SAntonio Huete Jimenez (void)setsignal(SIGALRM, verbose_stats_dump);
2479*ed775ee7SAntonio Huete Jimenez timer.it_interval.tv_sec = 1;
2480*ed775ee7SAntonio Huete Jimenez timer.it_interval.tv_usec = 0;
2481*ed775ee7SAntonio Huete Jimenez timer.it_value.tv_sec = 1;
2482*ed775ee7SAntonio Huete Jimenez timer.it_value.tv_usec = 1;
2483*ed775ee7SAntonio Huete Jimenez setitimer(ITIMER_REAL, &timer, NULL);
2484*ed775ee7SAntonio Huete Jimenez #endif /* _WIN32 */
248541c99275SPeter Avalos }
248641c99275SPeter Avalos
248741c99275SPeter Avalos if (RFileName == NULL) {
2488411677aeSAaron LI /*
2489411677aeSAaron LI * Live capture (if -V was specified, we set RFileName
2490411677aeSAaron LI * to a file from the -V file). Print a message to
2491411677aeSAaron LI * the standard error on UN*X.
2492411677aeSAaron LI */
2493411677aeSAaron LI if (!ndo->ndo_vflag && !WFileName) {
249441c99275SPeter Avalos (void)fprintf(stderr,
2495*ed775ee7SAntonio Huete Jimenez "%s: verbose output suppressed, use -v[v]... for full protocol decode\n",
249641c99275SPeter Avalos program_name);
249741c99275SPeter Avalos } else
249841c99275SPeter Avalos (void)fprintf(stderr, "%s: ", program_name);
249941c99275SPeter Avalos dlt = pcap_datalink(pd);
250041c99275SPeter Avalos dlt_name = pcap_datalink_val_to_name(dlt);
2501*ed775ee7SAntonio Huete Jimenez (void)fprintf(stderr, "listening on %s", device);
250241c99275SPeter Avalos if (dlt_name == NULL) {
2503*ed775ee7SAntonio Huete Jimenez (void)fprintf(stderr, ", link-type %u", dlt);
250441c99275SPeter Avalos } else {
2505*ed775ee7SAntonio Huete Jimenez (void)fprintf(stderr, ", link-type %s (%s)", dlt_name,
2506*ed775ee7SAntonio Huete Jimenez pcap_datalink_val_to_description(dlt));
250741c99275SPeter Avalos }
2508*ed775ee7SAntonio Huete Jimenez (void)fprintf(stderr, ", snapshot length %d bytes\n", ndo->ndo_snaplen);
250941c99275SPeter Avalos (void)fflush(stderr);
251041c99275SPeter Avalos }
2511411677aeSAaron LI
2512411677aeSAaron LI #ifdef HAVE_CAPSICUM
2513*ed775ee7SAntonio Huete Jimenez cansandbox = (VFileName == NULL && zflag == NULL);
2514*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_CASPER
2515*ed775ee7SAntonio Huete Jimenez cansandbox = (cansandbox && (ndo->ndo_nflag || capdns != NULL));
2516*ed775ee7SAntonio Huete Jimenez #else
2517*ed775ee7SAntonio Huete Jimenez cansandbox = (cansandbox && ndo->ndo_nflag);
2518*ed775ee7SAntonio Huete Jimenez #endif /* HAVE_CASPER */
2519411677aeSAaron LI if (cansandbox && cap_enter() < 0 && errno != ENOSYS)
2520411677aeSAaron LI error("unable to enter the capability mode");
2521411677aeSAaron LI #endif /* HAVE_CAPSICUM */
2522411677aeSAaron LI
2523411677aeSAaron LI do {
252441c99275SPeter Avalos status = pcap_loop(pd, cnt, callback, pcap_userdata);
252541c99275SPeter Avalos if (WFileName == NULL) {
252641c99275SPeter Avalos /*
252741c99275SPeter Avalos * We're printing packets. Flush the printed output,
252841c99275SPeter Avalos * so it doesn't get intermingled with error output.
252941c99275SPeter Avalos */
253041c99275SPeter Avalos if (status == -2) {
253141c99275SPeter Avalos /*
253241c99275SPeter Avalos * We got interrupted, so perhaps we didn't
253341c99275SPeter Avalos * manage to finish a line we were printing.
253441c99275SPeter Avalos * Print an extra newline, just in case.
253541c99275SPeter Avalos */
253641c99275SPeter Avalos putchar('\n');
253741c99275SPeter Avalos }
253841c99275SPeter Avalos (void)fflush(stdout);
253941c99275SPeter Avalos }
2540411677aeSAaron LI if (status == -2) {
2541411677aeSAaron LI /*
2542411677aeSAaron LI * We got interrupted. If we are reading multiple
2543411677aeSAaron LI * files (via -V) set these so that we stop.
2544411677aeSAaron LI */
2545411677aeSAaron LI VFileName = NULL;
2546411677aeSAaron LI ret = NULL;
2547411677aeSAaron LI }
254841c99275SPeter Avalos if (status == -1) {
254941c99275SPeter Avalos /*
255041c99275SPeter Avalos * Error. Report it.
255141c99275SPeter Avalos */
255241c99275SPeter Avalos (void)fprintf(stderr, "%s: pcap_loop: %s\n",
255341c99275SPeter Avalos program_name, pcap_geterr(pd));
255441c99275SPeter Avalos }
255541c99275SPeter Avalos if (RFileName == NULL) {
255641c99275SPeter Avalos /*
255741c99275SPeter Avalos * We're doing a live capture. Report the capture
255841c99275SPeter Avalos * statistics.
255941c99275SPeter Avalos */
256041c99275SPeter Avalos info(1);
256141c99275SPeter Avalos }
256241c99275SPeter Avalos pcap_close(pd);
2563411677aeSAaron LI if (VFileName != NULL) {
2564411677aeSAaron LI ret = get_next_file(VFile, VFileLine);
2565411677aeSAaron LI if (ret) {
2566411677aeSAaron LI int new_dlt;
2567411677aeSAaron LI
2568411677aeSAaron LI RFileName = VFileLine;
2569411677aeSAaron LI pd = pcap_open_offline(RFileName, ebuf);
2570411677aeSAaron LI if (pd == NULL)
2571411677aeSAaron LI error("%s", ebuf);
2572411677aeSAaron LI #ifdef HAVE_CAPSICUM
2573411677aeSAaron LI cap_rights_init(&rights, CAP_READ);
2574411677aeSAaron LI if (cap_rights_limit(fileno(pcap_file(pd)),
2575411677aeSAaron LI &rights) < 0 && errno != ENOSYS) {
2576411677aeSAaron LI error("unable to limit pcap descriptor");
2577411677aeSAaron LI }
2578411677aeSAaron LI #endif
2579411677aeSAaron LI new_dlt = pcap_datalink(pd);
2580411677aeSAaron LI if (new_dlt != dlt) {
2581411677aeSAaron LI /*
2582411677aeSAaron LI * The new file has a different
2583411677aeSAaron LI * link-layer header type from the
2584411677aeSAaron LI * previous one.
2585411677aeSAaron LI */
2586411677aeSAaron LI if (WFileName != NULL) {
2587411677aeSAaron LI /*
2588411677aeSAaron LI * We're writing raw packets
2589411677aeSAaron LI * that match the filter to
2590411677aeSAaron LI * a pcap file. pcap files
2591411677aeSAaron LI * don't support multiple
2592411677aeSAaron LI * different link-layer
2593411677aeSAaron LI * header types, so we fail
2594411677aeSAaron LI * here.
2595411677aeSAaron LI */
2596411677aeSAaron LI error("%s: new dlt does not match original", RFileName);
2597411677aeSAaron LI }
2598411677aeSAaron LI
2599411677aeSAaron LI /*
2600411677aeSAaron LI * We're printing the decoded packets;
2601411677aeSAaron LI * switch to the new DLT.
2602411677aeSAaron LI *
2603411677aeSAaron LI * To do that, we need to change
2604411677aeSAaron LI * the printer, change the DLT name,
2605411677aeSAaron LI * and recompile the filter with
2606411677aeSAaron LI * the new DLT.
2607411677aeSAaron LI */
2608411677aeSAaron LI dlt = new_dlt;
2609*ed775ee7SAntonio Huete Jimenez ndo->ndo_if_printer = get_if_printer(dlt);
2610411677aeSAaron LI if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
2611411677aeSAaron LI error("%s", pcap_geterr(pd));
2612411677aeSAaron LI }
2613411677aeSAaron LI
2614411677aeSAaron LI /*
2615411677aeSAaron LI * Set the filter on the new file.
2616411677aeSAaron LI */
2617411677aeSAaron LI if (pcap_setfilter(pd, &fcode) < 0)
2618411677aeSAaron LI error("%s", pcap_geterr(pd));
2619411677aeSAaron LI
2620411677aeSAaron LI /*
2621411677aeSAaron LI * Report the new file.
2622411677aeSAaron LI */
2623411677aeSAaron LI dlt_name = pcap_datalink_val_to_name(dlt);
2624*ed775ee7SAntonio Huete Jimenez fprintf(stderr, "reading from file %s", RFileName);
2625411677aeSAaron LI if (dlt_name == NULL) {
2626*ed775ee7SAntonio Huete Jimenez fprintf(stderr, ", link-type %u", dlt);
2627411677aeSAaron LI } else {
2628*ed775ee7SAntonio Huete Jimenez fprintf(stderr, ", link-type %s (%s)",
2629*ed775ee7SAntonio Huete Jimenez dlt_name,
2630411677aeSAaron LI pcap_datalink_val_to_description(dlt));
2631411677aeSAaron LI }
2632*ed775ee7SAntonio Huete Jimenez fprintf(stderr, ", snapshot length %d\n", pcap_snapshot(pd));
2633411677aeSAaron LI }
2634411677aeSAaron LI }
2635411677aeSAaron LI }
2636411677aeSAaron LI while (ret != NULL);
2637411677aeSAaron LI
2638*ed775ee7SAntonio Huete Jimenez if (count_mode && RFileName != NULL)
2639*ed775ee7SAntonio Huete Jimenez fprintf(stdout, "%u packet%s\n", packets_captured,
2640*ed775ee7SAntonio Huete Jimenez PLURAL_SUFFIX(packets_captured));
2641*ed775ee7SAntonio Huete Jimenez
2642411677aeSAaron LI free(cmdbuf);
2643411677aeSAaron LI pcap_freecode(&fcode);
2644411677aeSAaron LI exit_tcpdump(status == -1 ? 1 : 0);
264541c99275SPeter Avalos }
264641c99275SPeter Avalos
2647*ed775ee7SAntonio Huete Jimenez /*
2648*ed775ee7SAntonio Huete Jimenez * Catch a signal.
2649*ed775ee7SAntonio Huete Jimenez */
2650*ed775ee7SAntonio Huete Jimenez static void
setsignal(int sig,void (* func)(int))2651*ed775ee7SAntonio Huete Jimenez (*setsignal (int sig, void (*func)(int)))(int)
2652*ed775ee7SAntonio Huete Jimenez {
2653*ed775ee7SAntonio Huete Jimenez #ifdef _WIN32
2654*ed775ee7SAntonio Huete Jimenez return (signal(sig, func));
2655*ed775ee7SAntonio Huete Jimenez #else
2656*ed775ee7SAntonio Huete Jimenez struct sigaction old, new;
2657*ed775ee7SAntonio Huete Jimenez
2658*ed775ee7SAntonio Huete Jimenez memset(&new, 0, sizeof(new));
2659*ed775ee7SAntonio Huete Jimenez new.sa_handler = func;
2660*ed775ee7SAntonio Huete Jimenez if (sig == SIGCHLD)
2661*ed775ee7SAntonio Huete Jimenez new.sa_flags = SA_RESTART;
2662*ed775ee7SAntonio Huete Jimenez if (sigaction(sig, &new, &old) < 0)
2663*ed775ee7SAntonio Huete Jimenez return (SIG_ERR);
2664*ed775ee7SAntonio Huete Jimenez return (old.sa_handler);
2665*ed775ee7SAntonio Huete Jimenez #endif
2666*ed775ee7SAntonio Huete Jimenez }
2667*ed775ee7SAntonio Huete Jimenez
266841c99275SPeter Avalos /* make a clean exit on interrupts */
2669*ed775ee7SAntonio Huete Jimenez static void
cleanup(int signo _U_)267041c99275SPeter Avalos cleanup(int signo _U_)
267141c99275SPeter Avalos {
2672*ed775ee7SAntonio Huete Jimenez #ifdef _WIN32
2673*ed775ee7SAntonio Huete Jimenez if (timer_handle != INVALID_HANDLE_VALUE) {
2674*ed775ee7SAntonio Huete Jimenez DeleteTimerQueueTimer(NULL, timer_handle, NULL);
2675*ed775ee7SAntonio Huete Jimenez CloseHandle(timer_handle);
2676*ed775ee7SAntonio Huete Jimenez timer_handle = INVALID_HANDLE_VALUE;
2677*ed775ee7SAntonio Huete Jimenez }
2678*ed775ee7SAntonio Huete Jimenez #else /* _WIN32 */
2679*ed775ee7SAntonio Huete Jimenez struct itimerval timer;
2680*ed775ee7SAntonio Huete Jimenez
2681*ed775ee7SAntonio Huete Jimenez timer.it_interval.tv_sec = 0;
2682*ed775ee7SAntonio Huete Jimenez timer.it_interval.tv_usec = 0;
2683*ed775ee7SAntonio Huete Jimenez timer.it_value.tv_sec = 0;
2684*ed775ee7SAntonio Huete Jimenez timer.it_value.tv_usec = 0;
2685*ed775ee7SAntonio Huete Jimenez setitimer(ITIMER_REAL, &timer, NULL);
2686*ed775ee7SAntonio Huete Jimenez #endif /* _WIN32 */
268741c99275SPeter Avalos
268841c99275SPeter Avalos #ifdef HAVE_PCAP_BREAKLOOP
268941c99275SPeter Avalos /*
269041c99275SPeter Avalos * We have "pcap_breakloop()"; use it, so that we do as little
269141c99275SPeter Avalos * as possible in the signal handler (it's probably not safe
269241c99275SPeter Avalos * to do anything with standard I/O streams in a signal handler -
269341c99275SPeter Avalos * the ANSI C standard doesn't say it is).
269441c99275SPeter Avalos */
269541c99275SPeter Avalos pcap_breakloop(pd);
269641c99275SPeter Avalos #else
269741c99275SPeter Avalos /*
269841c99275SPeter Avalos * We don't have "pcap_breakloop()"; this isn't safe, but
269941c99275SPeter Avalos * it's the best we can do. Print the summary if we're
270041c99275SPeter Avalos * not reading from a savefile - i.e., if we're doing a
270141c99275SPeter Avalos * live capture - and exit.
270241c99275SPeter Avalos */
270341c99275SPeter Avalos if (pd != NULL && pcap_file(pd) == NULL) {
270441c99275SPeter Avalos /*
270541c99275SPeter Avalos * We got interrupted, so perhaps we didn't
270641c99275SPeter Avalos * manage to finish a line we were printing.
270741c99275SPeter Avalos * Print an extra newline, just in case.
270841c99275SPeter Avalos */
270941c99275SPeter Avalos putchar('\n');
271041c99275SPeter Avalos (void)fflush(stdout);
271141c99275SPeter Avalos info(1);
271241c99275SPeter Avalos }
2713*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_SUCCESS);
271441c99275SPeter Avalos #endif
271541c99275SPeter Avalos }
271641c99275SPeter Avalos
2717ea7b4bf5SPeter Avalos /*
2718ea7b4bf5SPeter Avalos On windows, we do not use a fork, so we do not care less about
2719ea7b4bf5SPeter Avalos waiting a child processes to die
2720ea7b4bf5SPeter Avalos */
272127bfbee1SPeter Avalos #if defined(HAVE_FORK) || defined(HAVE_VFORK)
2722*ed775ee7SAntonio Huete Jimenez static void
child_cleanup(int signo _U_)2723ea7b4bf5SPeter Avalos child_cleanup(int signo _U_)
2724ea7b4bf5SPeter Avalos {
2725ea7b4bf5SPeter Avalos wait(NULL);
2726ea7b4bf5SPeter Avalos }
272727bfbee1SPeter Avalos #endif /* HAVE_FORK && HAVE_VFORK */
2728ea7b4bf5SPeter Avalos
272941c99275SPeter Avalos static void
info(int verbose)2730*ed775ee7SAntonio Huete Jimenez info(int verbose)
273141c99275SPeter Avalos {
2732411677aeSAaron LI struct pcap_stat stats;
273341c99275SPeter Avalos
273427bfbee1SPeter Avalos /*
273527bfbee1SPeter Avalos * Older versions of libpcap didn't set ps_ifdrop on some
273627bfbee1SPeter Avalos * platforms; initialize it to 0 to handle that.
273727bfbee1SPeter Avalos */
2738411677aeSAaron LI stats.ps_ifdrop = 0;
2739411677aeSAaron LI if (pcap_stats(pd, &stats) < 0) {
274041c99275SPeter Avalos (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd));
2741ea7b4bf5SPeter Avalos infoprint = 0;
274241c99275SPeter Avalos return;
274341c99275SPeter Avalos }
274441c99275SPeter Avalos
274541c99275SPeter Avalos if (!verbose)
274641c99275SPeter Avalos fprintf(stderr, "%s: ", program_name);
274741c99275SPeter Avalos
274827bfbee1SPeter Avalos (void)fprintf(stderr, "%u packet%s captured", packets_captured,
274927bfbee1SPeter Avalos PLURAL_SUFFIX(packets_captured));
275041c99275SPeter Avalos if (!verbose)
275141c99275SPeter Avalos fputs(", ", stderr);
275241c99275SPeter Avalos else
275341c99275SPeter Avalos putc('\n', stderr);
2754411677aeSAaron LI (void)fprintf(stderr, "%u packet%s received by filter", stats.ps_recv,
2755411677aeSAaron LI PLURAL_SUFFIX(stats.ps_recv));
275641c99275SPeter Avalos if (!verbose)
275741c99275SPeter Avalos fputs(", ", stderr);
275841c99275SPeter Avalos else
275941c99275SPeter Avalos putc('\n', stderr);
2760411677aeSAaron LI (void)fprintf(stderr, "%u packet%s dropped by kernel", stats.ps_drop,
2761411677aeSAaron LI PLURAL_SUFFIX(stats.ps_drop));
2762411677aeSAaron LI if (stats.ps_ifdrop != 0) {
276327bfbee1SPeter Avalos if (!verbose)
276427bfbee1SPeter Avalos fputs(", ", stderr);
276527bfbee1SPeter Avalos else
276627bfbee1SPeter Avalos putc('\n', stderr);
276727bfbee1SPeter Avalos (void)fprintf(stderr, "%u packet%s dropped by interface\n",
2768411677aeSAaron LI stats.ps_ifdrop, PLURAL_SUFFIX(stats.ps_ifdrop));
276927bfbee1SPeter Avalos } else
277027bfbee1SPeter Avalos putc('\n', stderr);
277141c99275SPeter Avalos infoprint = 0;
277241c99275SPeter Avalos }
277341c99275SPeter Avalos
277427bfbee1SPeter Avalos #if defined(HAVE_FORK) || defined(HAVE_VFORK)
2775411677aeSAaron LI #ifdef HAVE_FORK
2776411677aeSAaron LI #define fork_subprocess() fork()
2777411677aeSAaron LI #else
2778411677aeSAaron LI #define fork_subprocess() vfork()
2779411677aeSAaron LI #endif
2780ea7b4bf5SPeter Avalos static void
compress_savefile(const char * filename)2781ea7b4bf5SPeter Avalos compress_savefile(const char *filename)
2782ea7b4bf5SPeter Avalos {
2783411677aeSAaron LI pid_t child;
2784411677aeSAaron LI
2785411677aeSAaron LI child = fork_subprocess();
2786411677aeSAaron LI if (child == -1) {
2787411677aeSAaron LI fprintf(stderr,
2788411677aeSAaron LI "compress_savefile: fork failed: %s\n",
2789411677aeSAaron LI pcap_strerror(errno));
2790ea7b4bf5SPeter Avalos return;
2791411677aeSAaron LI }
2792411677aeSAaron LI if (child != 0) {
2793411677aeSAaron LI /* Parent process. */
2794411677aeSAaron LI return;
2795411677aeSAaron LI }
2796411677aeSAaron LI
2797ea7b4bf5SPeter Avalos /*
2798411677aeSAaron LI * Child process.
2799411677aeSAaron LI * Set to lowest priority so that this doesn't disturb the capture.
2800ea7b4bf5SPeter Avalos */
2801ea7b4bf5SPeter Avalos #ifdef NZERO
2802ea7b4bf5SPeter Avalos setpriority(PRIO_PROCESS, 0, NZERO - 1);
2803ea7b4bf5SPeter Avalos #else
2804ea7b4bf5SPeter Avalos setpriority(PRIO_PROCESS, 0, 19);
2805ea7b4bf5SPeter Avalos #endif
280627bfbee1SPeter Avalos if (execlp(zflag, zflag, filename, (char *)NULL) == -1)
2807ea7b4bf5SPeter Avalos fprintf(stderr,
2808411677aeSAaron LI "compress_savefile: execlp(%s, %s) failed: %s\n",
2809ea7b4bf5SPeter Avalos zflag,
2810ea7b4bf5SPeter Avalos filename,
2811411677aeSAaron LI pcap_strerror(errno));
281227bfbee1SPeter Avalos #ifdef HAVE_FORK
2813*ed775ee7SAntonio Huete Jimenez exit(S_ERR_HOST_PROGRAM);
281427bfbee1SPeter Avalos #else
2815*ed775ee7SAntonio Huete Jimenez _exit(S_ERR_HOST_PROGRAM);
281627bfbee1SPeter Avalos #endif
2817ea7b4bf5SPeter Avalos }
281827bfbee1SPeter Avalos #else /* HAVE_FORK && HAVE_VFORK */
2819ea7b4bf5SPeter Avalos static void
compress_savefile(const char * filename)2820ea7b4bf5SPeter Avalos compress_savefile(const char *filename)
2821ea7b4bf5SPeter Avalos {
2822ea7b4bf5SPeter Avalos fprintf(stderr,
282327bfbee1SPeter Avalos "compress_savefile failed. Functionality not implemented under your system\n");
2824ea7b4bf5SPeter Avalos }
282527bfbee1SPeter Avalos #endif /* HAVE_FORK && HAVE_VFORK */
2826ea7b4bf5SPeter Avalos
282741c99275SPeter Avalos static void
dump_packet_and_trunc(u_char * user,const struct pcap_pkthdr * h,const u_char * sp)282841c99275SPeter Avalos dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
282941c99275SPeter Avalos {
283041c99275SPeter Avalos struct dump_info *dump_info;
283141c99275SPeter Avalos
283241c99275SPeter Avalos ++packets_captured;
283341c99275SPeter Avalos
283441c99275SPeter Avalos ++infodelay;
283541c99275SPeter Avalos
283641c99275SPeter Avalos dump_info = (struct dump_info *)user;
283741c99275SPeter Avalos
283841c99275SPeter Avalos /*
2839ea7b4bf5SPeter Avalos * XXX - this won't force the file to rotate on the specified time
2840ea7b4bf5SPeter Avalos * boundary, but it will rotate on the first packet received after the
2841ea7b4bf5SPeter Avalos * specified Gflag number of seconds. Note: if a Gflag time boundary
2842ea7b4bf5SPeter Avalos * and a Cflag size boundary coincide, the time rotation will occur
2843ea7b4bf5SPeter Avalos * first thereby cancelling the Cflag boundary (since the file should
2844ea7b4bf5SPeter Avalos * be 0).
284541c99275SPeter Avalos */
2846ea7b4bf5SPeter Avalos if (Gflag != 0) {
2847ea7b4bf5SPeter Avalos /* Check if it is time to rotate */
2848ea7b4bf5SPeter Avalos time_t t;
2849ea7b4bf5SPeter Avalos
2850ea7b4bf5SPeter Avalos /* Get the current time */
2851ea7b4bf5SPeter Avalos if ((t = time(NULL)) == (time_t)-1) {
2852*ed775ee7SAntonio Huete Jimenez error("%s: can't get current_time: %s",
2853*ed775ee7SAntonio Huete Jimenez __func__, pcap_strerror(errno));
2854ea7b4bf5SPeter Avalos }
2855ea7b4bf5SPeter Avalos
2856ea7b4bf5SPeter Avalos
2857ea7b4bf5SPeter Avalos /* If the time is greater than the specified window, rotate */
2858ea7b4bf5SPeter Avalos if (t - Gflag_time >= Gflag) {
2859411677aeSAaron LI #ifdef HAVE_CAPSICUM
2860411677aeSAaron LI FILE *fp;
2861411677aeSAaron LI int fd;
2862411677aeSAaron LI #endif
2863411677aeSAaron LI
2864ea7b4bf5SPeter Avalos /* Update the Gflag_time */
2865ea7b4bf5SPeter Avalos Gflag_time = t;
2866ea7b4bf5SPeter Avalos /* Update Gflag_count */
2867ea7b4bf5SPeter Avalos Gflag_count++;
286841c99275SPeter Avalos /*
286941c99275SPeter Avalos * Close the current file and open a new one.
287041c99275SPeter Avalos */
2871*ed775ee7SAntonio Huete Jimenez pcap_dump_close(dump_info->pdd);
2872ea7b4bf5SPeter Avalos
2873ea7b4bf5SPeter Avalos /*
2874ea7b4bf5SPeter Avalos * Compress the file we just closed, if the user asked for it
2875ea7b4bf5SPeter Avalos */
2876ea7b4bf5SPeter Avalos if (zflag != NULL)
2877ea7b4bf5SPeter Avalos compress_savefile(dump_info->CurrentFileName);
2878ea7b4bf5SPeter Avalos
2879ea7b4bf5SPeter Avalos /*
2880ea7b4bf5SPeter Avalos * Check to see if we've exceeded the Wflag (when
2881ea7b4bf5SPeter Avalos * not using Cflag).
2882ea7b4bf5SPeter Avalos */
2883ea7b4bf5SPeter Avalos if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) {
2884ea7b4bf5SPeter Avalos (void)fprintf(stderr, "Maximum file limit reached: %d\n",
2885ea7b4bf5SPeter Avalos Wflag);
2886411677aeSAaron LI info(1);
2887*ed775ee7SAntonio Huete Jimenez exit_tcpdump(S_SUCCESS);
2888ea7b4bf5SPeter Avalos /* NOTREACHED */
2889ea7b4bf5SPeter Avalos }
2890ea7b4bf5SPeter Avalos if (dump_info->CurrentFileName != NULL)
2891ea7b4bf5SPeter Avalos free(dump_info->CurrentFileName);
2892ea7b4bf5SPeter Avalos /* Allocate space for max filename + \0. */
2893411677aeSAaron LI dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1);
2894ea7b4bf5SPeter Avalos if (dump_info->CurrentFileName == NULL)
2895ea7b4bf5SPeter Avalos error("dump_packet_and_trunc: malloc");
2896ea7b4bf5SPeter Avalos /*
2897411677aeSAaron LI * Gflag was set otherwise we wouldn't be here. Reset the count
2898411677aeSAaron LI * so multiple files would end with 1,2,3 in the filename.
2899411677aeSAaron LI * The counting is handled with the -C flow after this.
2900411677aeSAaron LI */
2901411677aeSAaron LI Cflag_count = 0;
2902411677aeSAaron LI
2903411677aeSAaron LI /*
2904ea7b4bf5SPeter Avalos * This is always the first file in the Cflag
2905ea7b4bf5SPeter Avalos * rotation: e.g. 0
2906ea7b4bf5SPeter Avalos * We also don't need numbering if Cflag is not set.
2907ea7b4bf5SPeter Avalos */
2908ea7b4bf5SPeter Avalos if (Cflag != 0)
2909ea7b4bf5SPeter Avalos MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0,
2910ea7b4bf5SPeter Avalos WflagChars);
2911ea7b4bf5SPeter Avalos else
2912ea7b4bf5SPeter Avalos MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0);
2913ea7b4bf5SPeter Avalos
2914411677aeSAaron LI #ifdef HAVE_LIBCAP_NG
2915411677aeSAaron LI capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
2916411677aeSAaron LI capng_apply(CAPNG_SELECT_BOTH);
2917411677aeSAaron LI #endif /* HAVE_LIBCAP_NG */
2918411677aeSAaron LI #ifdef HAVE_CAPSICUM
2919411677aeSAaron LI fd = openat(dump_info->dirfd,
2920411677aeSAaron LI dump_info->CurrentFileName,
2921411677aeSAaron LI O_CREAT | O_WRONLY | O_TRUNC, 0644);
2922411677aeSAaron LI if (fd < 0) {
2923411677aeSAaron LI error("unable to open file %s",
2924411677aeSAaron LI dump_info->CurrentFileName);
2925411677aeSAaron LI }
2926411677aeSAaron LI fp = fdopen(fd, "w");
2927411677aeSAaron LI if (fp == NULL) {
2928411677aeSAaron LI error("unable to fdopen file %s",
2929411677aeSAaron LI dump_info->CurrentFileName);
2930411677aeSAaron LI }
2931*ed775ee7SAntonio Huete Jimenez dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp);
2932411677aeSAaron LI #else /* !HAVE_CAPSICUM */
2933*ed775ee7SAntonio Huete Jimenez dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
2934411677aeSAaron LI #endif
2935411677aeSAaron LI #ifdef HAVE_LIBCAP_NG
2936411677aeSAaron LI capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
2937411677aeSAaron LI capng_apply(CAPNG_SELECT_BOTH);
2938411677aeSAaron LI #endif /* HAVE_LIBCAP_NG */
2939*ed775ee7SAntonio Huete Jimenez if (dump_info->pdd == NULL)
2940ea7b4bf5SPeter Avalos error("%s", pcap_geterr(pd));
2941411677aeSAaron LI #ifdef HAVE_CAPSICUM
2942*ed775ee7SAntonio Huete Jimenez set_dumper_capsicum_rights(dump_info->pdd);
2943411677aeSAaron LI #endif
2944ea7b4bf5SPeter Avalos }
2945ea7b4bf5SPeter Avalos }
2946ea7b4bf5SPeter Avalos
2947ea7b4bf5SPeter Avalos /*
2948ea7b4bf5SPeter Avalos * XXX - this won't prevent capture files from getting
2949ea7b4bf5SPeter Avalos * larger than Cflag - the last packet written to the
2950ea7b4bf5SPeter Avalos * file could put it over Cflag.
2951ea7b4bf5SPeter Avalos */
2952411677aeSAaron LI if (Cflag != 0) {
2953*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_DUMP_FTELL64
2954*ed775ee7SAntonio Huete Jimenez int64_t size = pcap_dump_ftell64(dump_info->pdd);
2955*ed775ee7SAntonio Huete Jimenez #else
2956*ed775ee7SAntonio Huete Jimenez /*
2957*ed775ee7SAntonio Huete Jimenez * XXX - this only handles a Cflag value > 2^31-1 on
2958*ed775ee7SAntonio Huete Jimenez * LP64 platforms; to handle ILP32 (32-bit UN*X and
2959*ed775ee7SAntonio Huete Jimenez * Windows) or LLP64 (64-bit Windows) would require
2960*ed775ee7SAntonio Huete Jimenez * a version of libpcap with pcap_dump_ftell64().
2961*ed775ee7SAntonio Huete Jimenez */
2962*ed775ee7SAntonio Huete Jimenez long size = pcap_dump_ftell(dump_info->pdd);
2963*ed775ee7SAntonio Huete Jimenez #endif
2964411677aeSAaron LI
2965411677aeSAaron LI if (size == -1)
2966411677aeSAaron LI error("ftell fails on output file");
2967411677aeSAaron LI if (size > Cflag) {
2968411677aeSAaron LI #ifdef HAVE_CAPSICUM
2969411677aeSAaron LI FILE *fp;
2970411677aeSAaron LI int fd;
2971411677aeSAaron LI #endif
2972411677aeSAaron LI
2973ea7b4bf5SPeter Avalos /*
2974ea7b4bf5SPeter Avalos * Close the current file and open a new one.
2975ea7b4bf5SPeter Avalos */
2976*ed775ee7SAntonio Huete Jimenez pcap_dump_close(dump_info->pdd);
2977ea7b4bf5SPeter Avalos
2978ea7b4bf5SPeter Avalos /*
2979411677aeSAaron LI * Compress the file we just closed, if the user
2980411677aeSAaron LI * asked for it.
2981ea7b4bf5SPeter Avalos */
2982ea7b4bf5SPeter Avalos if (zflag != NULL)
2983ea7b4bf5SPeter Avalos compress_savefile(dump_info->CurrentFileName);
2984ea7b4bf5SPeter Avalos
298541c99275SPeter Avalos Cflag_count++;
298641c99275SPeter Avalos if (Wflag > 0) {
298741c99275SPeter Avalos if (Cflag_count >= Wflag)
298841c99275SPeter Avalos Cflag_count = 0;
298941c99275SPeter Avalos }
2990ea7b4bf5SPeter Avalos if (dump_info->CurrentFileName != NULL)
2991ea7b4bf5SPeter Avalos free(dump_info->CurrentFileName);
2992411677aeSAaron LI dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1);
2993ea7b4bf5SPeter Avalos if (dump_info->CurrentFileName == NULL)
2994*ed775ee7SAntonio Huete Jimenez error("%s: malloc", __func__);
2995ea7b4bf5SPeter Avalos MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars);
2996411677aeSAaron LI #ifdef HAVE_LIBCAP_NG
2997411677aeSAaron LI capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
2998411677aeSAaron LI capng_apply(CAPNG_SELECT_BOTH);
2999411677aeSAaron LI #endif /* HAVE_LIBCAP_NG */
3000411677aeSAaron LI #ifdef HAVE_CAPSICUM
3001411677aeSAaron LI fd = openat(dump_info->dirfd, dump_info->CurrentFileName,
3002411677aeSAaron LI O_CREAT | O_WRONLY | O_TRUNC, 0644);
3003411677aeSAaron LI if (fd < 0) {
3004411677aeSAaron LI error("unable to open file %s",
3005411677aeSAaron LI dump_info->CurrentFileName);
3006411677aeSAaron LI }
3007411677aeSAaron LI fp = fdopen(fd, "w");
3008411677aeSAaron LI if (fp == NULL) {
3009411677aeSAaron LI error("unable to fdopen file %s",
3010411677aeSAaron LI dump_info->CurrentFileName);
3011411677aeSAaron LI }
3012*ed775ee7SAntonio Huete Jimenez dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp);
3013411677aeSAaron LI #else /* !HAVE_CAPSICUM */
3014*ed775ee7SAntonio Huete Jimenez dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
3015411677aeSAaron LI #endif
3016411677aeSAaron LI #ifdef HAVE_LIBCAP_NG
3017411677aeSAaron LI capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
3018411677aeSAaron LI capng_apply(CAPNG_SELECT_BOTH);
3019411677aeSAaron LI #endif /* HAVE_LIBCAP_NG */
3020*ed775ee7SAntonio Huete Jimenez if (dump_info->pdd == NULL)
302141c99275SPeter Avalos error("%s", pcap_geterr(pd));
3022411677aeSAaron LI #ifdef HAVE_CAPSICUM
3023*ed775ee7SAntonio Huete Jimenez set_dumper_capsicum_rights(dump_info->pdd);
3024411677aeSAaron LI #endif
3025411677aeSAaron LI }
302641c99275SPeter Avalos }
302741c99275SPeter Avalos
3028*ed775ee7SAntonio Huete Jimenez pcap_dump((u_char *)dump_info->pdd, h, sp);
302941c99275SPeter Avalos #ifdef HAVE_PCAP_DUMP_FLUSH
303041c99275SPeter Avalos if (Uflag)
3031*ed775ee7SAntonio Huete Jimenez pcap_dump_flush(dump_info->pdd);
303241c99275SPeter Avalos #endif
303341c99275SPeter Avalos
3034*ed775ee7SAntonio Huete Jimenez if (dump_info->ndo != NULL)
3035*ed775ee7SAntonio Huete Jimenez pretty_print_packet(dump_info->ndo, h, sp, packets_captured);
3036*ed775ee7SAntonio Huete Jimenez
303741c99275SPeter Avalos --infodelay;
303841c99275SPeter Avalos if (infoprint)
303941c99275SPeter Avalos info(0);
304041c99275SPeter Avalos }
304141c99275SPeter Avalos
304241c99275SPeter Avalos static void
dump_packet(u_char * user,const struct pcap_pkthdr * h,const u_char * sp)304341c99275SPeter Avalos dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
304441c99275SPeter Avalos {
3045*ed775ee7SAntonio Huete Jimenez struct dump_info *dump_info;
3046*ed775ee7SAntonio Huete Jimenez
304741c99275SPeter Avalos ++packets_captured;
304841c99275SPeter Avalos
304941c99275SPeter Avalos ++infodelay;
305041c99275SPeter Avalos
3051*ed775ee7SAntonio Huete Jimenez dump_info = (struct dump_info *)user;
3052*ed775ee7SAntonio Huete Jimenez
3053*ed775ee7SAntonio Huete Jimenez pcap_dump((u_char *)dump_info->pdd, h, sp);
305441c99275SPeter Avalos #ifdef HAVE_PCAP_DUMP_FLUSH
305541c99275SPeter Avalos if (Uflag)
3056*ed775ee7SAntonio Huete Jimenez pcap_dump_flush(dump_info->pdd);
305741c99275SPeter Avalos #endif
305841c99275SPeter Avalos
3059*ed775ee7SAntonio Huete Jimenez if (dump_info->ndo != NULL)
3060*ed775ee7SAntonio Huete Jimenez pretty_print_packet(dump_info->ndo, h, sp, packets_captured);
3061*ed775ee7SAntonio Huete Jimenez
306241c99275SPeter Avalos --infodelay;
306341c99275SPeter Avalos if (infoprint)
306441c99275SPeter Avalos info(0);
306541c99275SPeter Avalos }
306641c99275SPeter Avalos
306741c99275SPeter Avalos static void
print_packet(u_char * user,const struct pcap_pkthdr * h,const u_char * sp)306841c99275SPeter Avalos print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
306941c99275SPeter Avalos {
307041c99275SPeter Avalos ++packets_captured;
307141c99275SPeter Avalos
307241c99275SPeter Avalos ++infodelay;
307341c99275SPeter Avalos
3074*ed775ee7SAntonio Huete Jimenez if (!count_mode)
3075411677aeSAaron LI pretty_print_packet((netdissect_options *)user, h, sp, packets_captured);
307641c99275SPeter Avalos
307741c99275SPeter Avalos --infodelay;
307841c99275SPeter Avalos if (infoprint)
307941c99275SPeter Avalos info(0);
308041c99275SPeter Avalos }
308141c99275SPeter Avalos
30826263709fSPeter Avalos #ifdef SIGNAL_REQ_INFO
3083*ed775ee7SAntonio Huete Jimenez static void
requestinfo(int signo _U_)3084*ed775ee7SAntonio Huete Jimenez requestinfo(int signo _U_)
308541c99275SPeter Avalos {
308641c99275SPeter Avalos if (infodelay)
308741c99275SPeter Avalos ++infoprint;
308841c99275SPeter Avalos else
308941c99275SPeter Avalos info(0);
309041c99275SPeter Avalos }
309141c99275SPeter Avalos #endif
309241c99275SPeter Avalos
3093*ed775ee7SAntonio Huete Jimenez #ifdef SIGNAL_FLUSH_PCAP
3094*ed775ee7SAntonio Huete Jimenez static void
flushpcap(int signo _U_)3095*ed775ee7SAntonio Huete Jimenez flushpcap(int signo _U_)
309641c99275SPeter Avalos {
3097*ed775ee7SAntonio Huete Jimenez if (pdd != NULL)
3098*ed775ee7SAntonio Huete Jimenez pcap_dump_flush(pdd);
309941c99275SPeter Avalos }
310041c99275SPeter Avalos #endif
310141c99275SPeter Avalos
3102*ed775ee7SAntonio Huete Jimenez static void
print_packets_captured(void)3103*ed775ee7SAntonio Huete Jimenez print_packets_captured (void)
3104*ed775ee7SAntonio Huete Jimenez {
3105*ed775ee7SAntonio Huete Jimenez static u_int prev_packets_captured, first = 1;
3106*ed775ee7SAntonio Huete Jimenez
3107*ed775ee7SAntonio Huete Jimenez if (infodelay == 0 && (first || packets_captured != prev_packets_captured)) {
3108*ed775ee7SAntonio Huete Jimenez fprintf(stderr, "Got %u\r", packets_captured);
3109*ed775ee7SAntonio Huete Jimenez first = 0;
3110*ed775ee7SAntonio Huete Jimenez prev_packets_captured = packets_captured;
3111*ed775ee7SAntonio Huete Jimenez }
3112*ed775ee7SAntonio Huete Jimenez }
3113*ed775ee7SAntonio Huete Jimenez
3114*ed775ee7SAntonio Huete Jimenez /*
3115*ed775ee7SAntonio Huete Jimenez * Called once each second in verbose mode while dumping to file
3116*ed775ee7SAntonio Huete Jimenez */
3117*ed775ee7SAntonio Huete Jimenez #ifdef _WIN32
verbose_stats_dump(PVOID param _U_,BOOLEAN timer_fired _U_)3118*ed775ee7SAntonio Huete Jimenez static void CALLBACK verbose_stats_dump(PVOID param _U_,
3119*ed775ee7SAntonio Huete Jimenez BOOLEAN timer_fired _U_)
3120*ed775ee7SAntonio Huete Jimenez {
3121*ed775ee7SAntonio Huete Jimenez print_packets_captured();
3122*ed775ee7SAntonio Huete Jimenez }
3123*ed775ee7SAntonio Huete Jimenez #else /* _WIN32 */
verbose_stats_dump(int sig _U_)3124*ed775ee7SAntonio Huete Jimenez static void verbose_stats_dump(int sig _U_)
3125*ed775ee7SAntonio Huete Jimenez {
3126*ed775ee7SAntonio Huete Jimenez print_packets_captured();
3127*ed775ee7SAntonio Huete Jimenez }
3128*ed775ee7SAntonio Huete Jimenez #endif /* _WIN32 */
3129*ed775ee7SAntonio Huete Jimenez
3130411677aeSAaron LI USES_APPLE_DEPRECATED_API
313141c99275SPeter Avalos static void
print_version(FILE * f)3132*ed775ee7SAntonio Huete Jimenez print_version(FILE *f)
313341c99275SPeter Avalos {
313441c99275SPeter Avalos #ifndef HAVE_PCAP_LIB_VERSION
3135*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_VERSION
313641c99275SPeter Avalos extern char pcap_version[];
3137*ed775ee7SAntonio Huete Jimenez #else /* HAVE_PCAP_VERSION */
313841c99275SPeter Avalos static char pcap_version[] = "unknown";
3139*ed775ee7SAntonio Huete Jimenez #endif /* HAVE_PCAP_VERSION */
314041c99275SPeter Avalos #endif /* HAVE_PCAP_LIB_VERSION */
3141411677aeSAaron LI const char *smi_version_string;
314241c99275SPeter Avalos
3143*ed775ee7SAntonio Huete Jimenez (void)fprintf(f, "%s version " PACKAGE_VERSION "\n", program_name);
314441c99275SPeter Avalos #ifdef HAVE_PCAP_LIB_VERSION
3145*ed775ee7SAntonio Huete Jimenez (void)fprintf(f, "%s\n", pcap_lib_version());
314641c99275SPeter Avalos #else /* HAVE_PCAP_LIB_VERSION */
3147*ed775ee7SAntonio Huete Jimenez (void)fprintf(f, "libpcap version %s\n", pcap_version);
314841c99275SPeter Avalos #endif /* HAVE_PCAP_LIB_VERSION */
3149411677aeSAaron LI
3150411677aeSAaron LI #if defined(HAVE_LIBCRYPTO) && defined(SSLEAY_VERSION)
3151*ed775ee7SAntonio Huete Jimenez (void)fprintf (f, "%s\n", SSLeay_version(SSLEAY_VERSION));
3152411677aeSAaron LI #endif
3153411677aeSAaron LI
3154411677aeSAaron LI smi_version_string = nd_smi_version_string();
3155411677aeSAaron LI if (smi_version_string != NULL)
3156*ed775ee7SAntonio Huete Jimenez (void)fprintf (f, "SMI-library: %s\n", smi_version_string);
3157411677aeSAaron LI
3158411677aeSAaron LI #if defined(__SANITIZE_ADDRESS__)
3159*ed775ee7SAntonio Huete Jimenez (void)fprintf (f, "Compiled with AddressSanitizer/GCC.\n");
3160411677aeSAaron LI #elif defined(__has_feature)
3161411677aeSAaron LI # if __has_feature(address_sanitizer)
3162*ed775ee7SAntonio Huete Jimenez (void)fprintf (f, "Compiled with AddressSanitizer/Clang.\n");
3163*ed775ee7SAntonio Huete Jimenez # elif __has_feature(memory_sanitizer)
3164*ed775ee7SAntonio Huete Jimenez (void)fprintf (f, "Compiled with MemorySanitizer/Clang.\n");
3165411677aeSAaron LI # endif
3166411677aeSAaron LI #endif /* __SANITIZE_ADDRESS__ or __has_feature */
3167411677aeSAaron LI }
3168411677aeSAaron LI USES_APPLE_RST
3169411677aeSAaron LI
3170411677aeSAaron LI static void
print_usage(FILE * f)3171*ed775ee7SAntonio Huete Jimenez print_usage(FILE *f)
3172411677aeSAaron LI {
3173*ed775ee7SAntonio Huete Jimenez print_version(f);
3174*ed775ee7SAntonio Huete Jimenez (void)fprintf(f,
3175*ed775ee7SAntonio Huete Jimenez "Usage: %s [-Abd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ] [--count]\n", program_name);
3176*ed775ee7SAntonio Huete Jimenez (void)fprintf(f,
3177ea7b4bf5SPeter Avalos "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n");
3178*ed775ee7SAntonio Huete Jimenez (void)fprintf(f,
3179*ed775ee7SAntonio Huete Jimenez "\t\t[ -i interface ]" IMMEDIATE_MODE_USAGE j_FLAG_USAGE "\n");
3180*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_PCAP_FINDALLDEVS_EX
3181*ed775ee7SAntonio Huete Jimenez (void)fprintf(f,
3182*ed775ee7SAntonio Huete Jimenez "\t\t" LIST_REMOTE_INTERFACES_USAGE "\n");
3183411677aeSAaron LI #endif
3184*ed775ee7SAntonio Huete Jimenez #ifdef USE_LIBSMI
3185*ed775ee7SAntonio Huete Jimenez (void)fprintf(f,
3186*ed775ee7SAntonio Huete Jimenez "\t\t" m_FLAG_USAGE "\n");
3187*ed775ee7SAntonio Huete Jimenez #endif
3188*ed775ee7SAntonio Huete Jimenez (void)fprintf(f,
3189*ed775ee7SAntonio Huete Jimenez "\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n");
3190*ed775ee7SAntonio Huete Jimenez (void)fprintf(f,
3191*ed775ee7SAntonio Huete Jimenez "\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]\n");
3192*ed775ee7SAntonio Huete Jimenez (void)fprintf(f,
3193*ed775ee7SAntonio Huete Jimenez "\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n");
3194411677aeSAaron LI #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
3195*ed775ee7SAntonio Huete Jimenez (void)fprintf(f,
3196*ed775ee7SAntonio Huete Jimenez "\t\t[ --time-stamp-precision precision ] [ --micro ] [ --nano ]\n");
3197411677aeSAaron LI #endif
3198*ed775ee7SAntonio Huete Jimenez (void)fprintf(f,
3199*ed775ee7SAntonio Huete Jimenez "\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n");
320041c99275SPeter Avalos }
3201