* combined efforts of Van, Steve McCanne and Craig Leres of LBL.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
-
-/*
- * Some older versions of Mac OS X ship pcap.h from libpcap 0.6 with a
- * libpcap based on 0.8. That means it has pcap_findalldevs() but the
- * header doesn't define pcap_if_t, meaning that we can't actually *use*
- * pcap_findalldevs().
- */
-#ifdef HAVE_PCAP_FINDALLDEVS
-#ifndef HAVE_PCAP_IF_T
-#undef HAVE_PCAP_FINDALLDEVS
-#endif
+#ifndef TCPDUMP_CONFIG_H_
+#error "The included config.h header is not from the tcpdump build."
#endif
#include "netdissect-stdinc.h"
#include <sys/stat.h>
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
#ifdef HAVE_LIBCRYPTO
#include <openssl/crypto.h>
#include <sys/sysctl.h>
#endif /* __FreeBSD__ */
-#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "interface.h"
#include "addrtoname.h"
-#include "machdep.h"
-#include "pcap-missing.h"
#include "ascii_strcasecmp.h"
#include "print.h"
#define SIGNAL_REQ_INFO SIGUSR1
#endif
-#if defined(HAVE_PCAP_DUMP_FLUSH) && defined(SIGUSR2)
+#if defined(SIGUSR2)
#define SIGNAL_FLUSH_PCAP SIGUSR2
#endif
-#if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
static int Bflag; /* buffer size */
-#endif
-#ifdef HAVE_PCAP_DUMP_FTELL64
static int64_t Cflag; /* rotate dump files after this many bytes */
-#else
-static long Cflag; /* rotate dump files after this many bytes */
-#endif
static int Cflag_count; /* Keep track of which file number we're writing */
-#ifdef HAVE_PCAP_FINDALLDEVS
static int Dflag; /* list available devices and exit */
-#endif
#ifdef HAVE_PCAP_FINDALLDEVS_EX
static char *remote_interfaces_source; /* list available devices from this source and exit */
#endif
#endif
static int lflag; /* line-buffered output */
static int pflag; /* don't go promiscuous */
-#ifdef HAVE_PCAP_SETDIRECTION
static int Qflag = -1; /* restrict captured packet by send/receive direction */
-#endif
-#ifdef HAVE_PCAP_DUMP_FLUSH
static int Uflag; /* "unbuffered" output of dump files */
-#endif
static int Wflag; /* recycle output files after this number of files */
static int WflagChars;
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */
+#endif
static int timeout = 1000; /* default timeout = 1000 ms = 1 s */
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
static int immediate_mode;
#endif
static int count_mode;
+static u_int packets_to_skip;
static int infodelay;
static int infoprint;
char *program_name;
/* Forwards */
+static int parse_int(const char *argname, const char *string, char **endp,
+ int minval, int maxval, int base);
+static u_int parse_u_int(const char *argname, const char *string, char **endp,
+ u_int minval, u_int maxval, int base);
+static int64_t parse_int64(const char *argname, const char *string,
+ char **endp, int64_t minval, int64_t maxval, int base);
static void (*setsignal (int sig, void (*func)(int)))(int);
static void cleanup(int);
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
static void child_cleanup(int);
+#endif
static void print_version(FILE *);
static void print_usage(FILE *);
static void info(int);
static u_int packets_captured;
-#ifdef HAVE_PCAP_FINDALLDEVS
static const struct tok status_flags[] = {
#ifdef PCAP_IF_UP
{ PCAP_IF_UP, "Up" },
#endif
{ 0, NULL }
};
-#endif
static pcap_t *pd;
static pcap_dumper_t *pdd = NULL;
}
#define HAVE_PCAP_SET_PARSER_DEBUG
-#endif
+#endif // HAVE_PCAP_SET_PARSER_DEBUG, HAVE_PCAP_DEBUG, HAVE_YYDEBUG
#if defined(HAVE_PCAP_SET_OPTIMIZER_DEBUG)
/*
extern
#endif /* _WIN32 */
void pcap_set_optimizer_debug(int);
-#endif
+#endif // HAVE_PCAP_SET_OPTIMIZER_DEBUG
static void NORETURN
exit_tcpdump(const int status)
pcap_free_tstamp_types(tstamp_types);
exit_tcpdump(S_SUCCESS);
}
-#endif
+#endif // HAVE_PCAP_SET_TSTAMP_TYPE
static void NORETURN
show_dlts_and_exit(pcap_t *pc, const char *device)
dlts[i]);
}
}
-#ifdef HAVE_PCAP_FREE_DATALINKS
pcap_free_datalinks(dlts);
-#endif
exit_tcpdump(S_SUCCESS);
}
-#ifdef HAVE_PCAP_FINDALLDEVS
static void NORETURN
show_devices_and_exit(void)
{
break;
}
}
-#endif
+#endif // PCAP_IF_WIRELESS
printf("]");
}
printf("\n");
pcap_freealldevs(devlist);
exit_tcpdump(S_SUCCESS);
}
-#endif /* HAVE_PCAP_FINDALLDEVS */
#ifdef HAVE_PCAP_FINDALLDEVS_EX
static void NORETURN
pcap_freealldevs(devlist);
exit_tcpdump(S_SUCCESS);
}
-#endif /* HAVE_PCAP_FINDALLDEVS */
+#endif /* HAVE_PCAP_FINDALLDEVS_EX */
/*
* Short options.
* Set up flags that might or might not be supported depending on the
* version of libpcap we're using.
*/
-#if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
-#define B_FLAG "B:"
-#define B_FLAG_USAGE " [ -B size ]"
-#else /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */
-#define B_FLAG
-#define B_FLAG_USAGE
-#endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */
-
-#ifdef HAVE_PCAP_FINDALLDEVS
-#define D_FLAG "D"
-#else
-#define D_FLAG
-#endif
-
-#ifdef HAVE_PCAP_CREATE
-#define I_FLAG "I"
-#else /* HAVE_PCAP_CREATE */
-#define I_FLAG
-#endif /* HAVE_PCAP_CREATE */
-
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
#define j_FLAG "j:"
#define j_FLAG_USAGE " [ -j tstamptype ]"
#define J_FLAG "J"
-#else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */
+#else /* HAVE_PCAP_SET_TSTAMP_TYPE */
#define j_FLAG
#define j_FLAG_USAGE
#define J_FLAG
-#endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */
+#endif /* HAVE_PCAP_SET_TSTAMP_TYPE */
#ifdef USE_LIBSMI
#define m_FLAG_USAGE "[ -m module ] ..."
#endif
-#ifdef HAVE_PCAP_SETDIRECTION
-#define Q_FLAG "Q:"
-#define Q_FLAG_USAGE " [ -Q in|out|inout ]"
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
+#define z_FLAG "z:"
+#define z_FLAG_USAGE "[ -z postrotate-command ] "
#else
-#define Q_FLAG
-#define Q_FLAG_USAGE
+#define z_FLAG
+#define z_FLAG_USAGE
#endif
-#ifdef HAVE_PCAP_DUMP_FLUSH
-#define U_FLAG "U"
+#ifdef HAVE_LIBCRYPTO
+#define E_FLAG "E:"
+#define E_FLAG_USAGE "[ -E algo:secret ] "
+#define M_FLAG "M:"
+#define M_FLAG_USAGE "[ -M secret ] "
#else
-#define U_FLAG
+#define E_FLAG
+#define E_FLAG_USAGE
+#define M_FLAG
+#define M_FLAG_USAGE
#endif
-#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:#"
+#define SHORTOPTS "aAbB:c:C:dDe" E_FLAG "fF:G:hHi:I" j_FLAG J_FLAG "KlLm:" M_FLAG "nNOpqQ:r:s:StT:uUvV:w:W:xXy:Y" z_FLAG "Z:#"
/*
* Long options.
#define OPTION_FP_TYPE 135
#define OPTION_COUNT 136
#define OPTION_PRINT_SAMPLING 137
+#define OPTION_LENGTHS 138
+#define OPTION_TIME_T_SIZE 139
+#define OPTION_SKIP 140
static const struct option longopts[] = {
-#if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
{ "buffer-size", required_argument, NULL, 'B' },
-#endif
{ "list-interfaces", no_argument, NULL, 'D' },
#ifdef HAVE_PCAP_FINDALLDEVS_EX
{ "list-remote-interfaces", required_argument, NULL, OPTION_LIST_REMOTE_INTERFACES },
#endif
{ "help", no_argument, NULL, 'h' },
{ "interface", required_argument, NULL, 'i' },
-#ifdef HAVE_PCAP_CREATE
{ "monitor-mode", no_argument, NULL, 'I' },
-#endif
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
{ "time-stamp-type", required_argument, NULL, 'j' },
{ "list-time-stamp-types", no_argument, NULL, 'J' },
{ "list-data-link-types", no_argument, NULL, 'L' },
{ "no-optimize", no_argument, NULL, 'O' },
{ "no-promiscuous-mode", no_argument, NULL, 'p' },
-#ifdef HAVE_PCAP_SETDIRECTION
{ "direction", required_argument, NULL, 'Q' },
-#endif
{ "snapshot-length", required_argument, NULL, 's' },
{ "absolute-tcp-sequence-numbers", no_argument, NULL, 'S' },
-#ifdef HAVE_PCAP_DUMP_FLUSH
{ "packet-buffered", no_argument, NULL, 'U' },
-#endif
{ "linktype", required_argument, NULL, 'y' },
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
{ "immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE },
{ "number", no_argument, NULL, '#' },
{ "print", no_argument, NULL, OPTION_PRINT },
{ "print-sampling", required_argument, NULL, OPTION_PRINT_SAMPLING },
+ { "lengths", no_argument, NULL, OPTION_LENGTHS },
+ { "time-t-size", no_argument, NULL, OPTION_TIME_T_SIZE },
+ { "skip", required_argument, NULL, OPTION_SKIP },
{ "version", no_argument, NULL, OPTION_VERSION },
{ NULL, 0, NULL, 0 }
};
#ifdef HAVE_PCAP_FINDALLDEVS_EX
-#define LIST_REMOTE_INTERFACES_USAGE "[ --list-remote-interfaces remote-source ]"
+#define LIST_REMOTE_INTERFACES_USAGE " [ --list-remote-interfaces remote-source ]"
#else
#define LIST_REMOTE_INTERFACES_USAGE
#endif
{
int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG);
if (ret < 0)
- error("capng_change_id(): return %d\n", ret);
+ error("capng_change_id(): return %d", ret);
else
fprintf(stderr, "dropped privs to %s\n", username);
}
return "unknown";
}
}
-#endif
+#endif // HAVE_PCAP_SET_TSTAMP_PRECISION
#ifdef HAVE_CAPSICUM
/*
* that requires that it be able to do an F_GETFL fcntl() to read
* the O_ flags.
*
- * Tcpdump uses ftell() to determine how much data has been written
+ * tcpdump uses ftell() to determine how much data has been written
* to a file in order to, when used with -C, determine when it's time
* to rotate capture files. ftell() therefore needs to do an lseek()
* to find out the file offset and must, thanks to the aforementioned
error("unable to limit dump descriptor fcntls");
}
}
-#endif
+#endif // HAVE_CAPSICUM
/*
* Copy arg vector into a new buffer, concatenating arguments with spaces.
return (cp);
}
-#ifdef HAVE_PCAP_FINDALLDEVS
static long
parse_interface_number(const char *device)
{
/*
* No, it's not an ordinal.
*/
- error("Invalid adapter index");
+ error("Invalid adapter index %s", device);
}
return (devnum);
} else {
status = pcap_findalldevs_ex(host_url, NULL, &devlist, ebuf);
free(host_url);
} else
-#endif
+#endif // HAVE_PCAP_FINDALLDEVS_EX
status = pcap_findalldevs(&devlist, ebuf);
if (status < 0)
error("%s", ebuf);
for (i = 0, dev = devlist; i < devnum-1 && dev != NULL;
i++, dev = dev->next)
;
- if (dev == NULL)
- error("Invalid adapter index");
+ if (dev == NULL) {
+ pcap_freealldevs(devlist);
+ error("Invalid adapter index %ld: only %ld interfaces found",
+ devnum, i);
+ }
device = strdup(dev->name);
pcap_freealldevs(devlist);
return (device);
}
-#endif
#ifdef HAVE_PCAP_OPEN
/*
open_interface(const char *device, netdissect_options *ndo, char *ebuf)
{
pcap_t *pc;
-#ifdef HAVE_PCAP_CREATE
int status;
char *cp;
-#endif
#ifdef HAVE_PCAP_OPEN
/*
}
#endif /* HAVE_PCAP_OPEN */
-#ifdef HAVE_PCAP_CREATE
pc = pcap_create(device, ebuf);
if (pc == NULL) {
/*
} else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0')
error("%s: %s\n(%s)", device,
pcap_statustostr(status), cp);
+#ifdef PCAP_ERROR_CAPTURE_NOTSUP
+ else if (status == PCAP_ERROR_CAPTURE_NOTSUP && *cp != '\0')
+ error("%s: %s\n(%s)", device,
+ pcap_statustostr(status), cp);
+#endif
#ifdef __FreeBSD__
else if (status == PCAP_ERROR_RFMON_NOTSUP &&
strncmp(device, "wlan", 4) == 0) {
* specific case would be an error message that looks a bit odd.
*/
newdev[strlen(newdev)-1]++;
- error("%s is not a monitor mode VAP\n"
+ error("%s is not a monitor mode VAP"
"To create a new monitor mode VAP use:\n"
" ifconfig %s create wlandev %s wlanmode monitor\n"
"and use %s as the tcpdump interface",
device, newdev, parent, newdev);
}
-#endif
+#endif // __FreeBSD__
else
error("%s: %s", device,
pcap_statustostr(status));
warning("%s: %s", device,
pcap_statustostr(status));
}
-#ifdef HAVE_PCAP_SETDIRECTION
if (Qflag != -1) {
status = pcap_setdirection(pc, Qflag);
if (status != 0)
error("%s: pcap_setdirection() failed: %s",
device, pcap_geterr(pc));
}
-#endif /* HAVE_PCAP_SETDIRECTION */
-#else /* HAVE_PCAP_CREATE */
- *ebuf = '\0';
- /*
- * If no snapshot length was specified, or a length of 0 was
- * specified, default to 256KB.
- */
- if (ndo->ndo_snaplen == 0)
- ndo->ndo_snaplen = MAXIMUM_SNAPLEN;
- pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, timeout, ebuf);
- if (pc == NULL) {
- /*
- * If this failed with "No such device", that means
- * the interface doesn't exist; return NULL, so that
- * the caller can see whether the device name is
- * actually an interface index.
- */
- if (strstr(ebuf, "No such device") != NULL)
- return (NULL);
- error("%s", ebuf);
- }
- if (*ebuf)
- warning("%s", ebuf);
-#endif /* HAVE_PCAP_CREATE */
return (pc);
}
const char *chroot_dir = NULL;
#endif
char *ret = NULL;
- char *end;
-#ifdef HAVE_PCAP_FINDALLDEVS
pcap_if_t *devlist;
long devnum;
-#endif
int status;
FILE *VFile;
#ifdef HAVE_CAPSICUM
netdissect_options Ndo;
netdissect_options *ndo = &Ndo;
+#ifdef _WIN32
+ /*
+ * We need to look for wpcap.dll in \Windows\System32\Npcap first,
+ * as either:
+ *
+ * 1) WinPcap isn't installed and Npcap isn't installed in "WinPcap
+ * API-compatible Mode", so there's no wpcap.dll in
+ * \Windows\System32, only in \Windows\System32\Npcap;
+ *
+ * 2) WinPcap is installed and Npcap isn't installed in "WinPcap
+ * API-compatible Mode", so the wpcap.dll in \Windows\System32
+ * is a WinPcap DLL, but we'd prefer an Npcap DLL (we should
+ * work with either one if we're configured against WinPcap,
+ * and we'll probably require Npcap if we're configured against
+ * it), and that's in \Windows\System32\Npcap;
+ *
+ * 3) Npcap is installed in "WinPcap API-compatible Mode", so both
+ * \Windows\System32 and \Windows\System32\Npcap have an Npcap
+ * wpcap.dll.
+ *
+ * Unfortunately, Windows has no notion of an rpath, so we can't
+ * set the rpath to include \Windows\System32\Npcap at link time;
+ * what we need to do is to link wpcap as a delay-load DLL and
+ * add \Windows\System32\Npcap to the DLL search path early in
+ * main() with a call to SetDllDirectory().
+ *
+ * The same applies to packet.dll.
+ *
+ * We add \Windows\System32\Npcap here.
+ *
+ * See https://npcap.com/guide/npcap-devguide.html#npcap-feature-native-dll-implicitly
+ */
+ WCHAR *dll_directory = NULL;
+ size_t dll_directory_buf_len = 0; /* units of bytes */
+ UINT system_directory_buf_len = 0; /* units of WCHARs */
+ UINT system_directory_len; /* units of WCHARs */
+ static const WCHAR npcap[] = L"\\Npcap";
+
+ /*
+ * Get the system directory path, in UTF-16, into a buffer that's
+ * large enough for that directory path plus "\Npcap".
+ *
+ * String manipulation in C, plus fetching a variable-length
+ * string into a buffer whose size is fixed at the time of
+ * the call, with an oddball return value (see below), is just
+ * a huge bag of fun.
+ *
+ * And it's even more fun when dealing with UTF-16, so that the
+ * buffer sizes used in GetSystemDirectoryW() are in different
+ * units from the buffer sizes used in realloc()! We maintain
+ * all sizes/length in units of bytes, not WCHARs, so that our
+ * heads don't explode.
+ */
+ for (;;) {
+ /*
+ * Try to fetch the system directory.
+ *
+ * GetSystemDirectoryW() expects a buffer size in units
+ * of WCHARs, not bytes, and returns a directory path
+ * length in units of WCHARs, not bytes.
+ *
+ * For extra fun, if GetSystemDirectoryW() succeeds,
+ * the return value is the length of the directory
+ * path in units of WCHARs, *not* including the
+ * terminating '\0', but if it fails because the
+ * path string wouldn't fit, the return value is
+ * the length of the directory path in units of WCHARs,
+ * *including* the terminating '\0'.
+ */
+ system_directory_len = GetSystemDirectoryW(dll_directory,
+ system_directory_buf_len);
+ if (system_directory_len == 0)
+ error("GetSystemDirectoryW() failed");
+
+ /*
+ * Did the directory path fit in the buffer?
+ *
+ * As per the above, this means that the return value
+ * *plus 1*, so that the terminating '\0' is counted,
+ * is <= the buffer size.
+ *
+ * (If the directory path, complete with the terminating
+ * '\0', fits *exactly*, the return value would be the
+ * size of the buffer minus 1, as it doesn't count the
+ * terminating '\0', so the test below would succeed.
+ *
+ * If everything *but* the terminating '\0' fits,
+ * the return value would be the size of the buffer + 1,
+ * i.e., the size that the string in question would
+ * have required.
+ *
+ * The astute reader will note that returning the
+ * size of the buffer is not one of the two cases
+ * above, and should never happen.)
+ */
+ if ((system_directory_len + 1) <= system_directory_buf_len) {
+ /*
+ * No. We have a buffer that's large enough
+ * for our purposes.
+ */
+ break;
+ }
+
+ /*
+ * Yes. Grow the buffer.
+ *
+ * The space we'll need in the buffer for the system
+ * directory, in units of WCHARs, is system_directory_len,
+ * as that's the length of the system directory path
+ * including the terminating '\0'.
+ */
+ system_directory_buf_len = system_directory_len;
+
+ /*
+ * The size of the DLL directory buffer, in *bytes*, must
+ * be the number of WCHARs taken by the system directory,
+ * *minus* the terminating '\0' (as we'll overwrite that
+ * with the "\" of the "\Npcap" string), multiplied by
+ * sizeof(WCHAR) to convert it to the number of bytes,
+ * plus the size of the "\Npcap" string, in bytes (which
+ * will include the terminating '\0', as that will become
+ * the DLL path's terminating '\0').
+ */
+ dll_directory_buf_len =
+ ((system_directory_len - 1)*sizeof(WCHAR)) + sizeof npcap;
+ dll_directory = realloc(dll_directory, dll_directory_buf_len);
+ if (dll_directory == NULL)
+ error("Can't allocate string for Npcap directory");
+ }
+
+ /*
+ * OK, that worked.
+ *
+ * Now append \Npcap. We add the length of the system directory path,
+ * in WCHARs, *not* including the terminating '\0' (which, since
+ * GetSystemDirectoryW() succeeded, is the return value of
+ * GetSystemDirectoryW(), as per the above), to the pointer to the
+ * beginning of the path, to go past the end of the system directory
+ * to point to the terminating '\0'.
+ */
+ memcpy(dll_directory + system_directory_len, npcap, sizeof npcap);
+
+ /*
+ * Now add that as a system DLL directory.
+ */
+ if (!SetDllDirectoryW(dll_directory))
+ error("SetDllDirectory failed");
+
+ free(dll_directory);
+#endif // _WIN32
+
/*
* Initialize the netdissect code.
*/
error("Attempting to initialize Winsock failed");
#endif
- /*
- * On platforms where the CPU doesn't support unaligned loads,
- * force unaligned accesses to abort with SIGBUS, rather than
- * being fixed up (slowly) by the OS kernel; on those platforms,
- * misaligned accesses are bugs, and we want tcpdump to crash so
- * that the bugs are reported.
- */
- if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0)
- error("%s", ebuf);
-
/*
* An explicit tzset() call is usually not needed as it happens
* implicitly the first time we call localtime() or mktime(),
++ndo->ndo_bflag;
break;
-#if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
case 'B':
- Bflag = atoi(optarg)*1024;
- if (Bflag <= 0)
- error("invalid packet buffer size %s", optarg);
+ Bflag = parse_int("packet buffer size", optarg, NULL, 1,
+ INT_MAX, 10);
+ /*
+ * Will multiplying it by 1024 overflow?
+ */
+ if (Bflag > INT_MAX / 1024)
+ error("packet buffer size %s is too large", optarg);
+ Bflag *= 1024;
break;
-#endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */
case 'c':
- cnt = atoi(optarg);
- if (cnt <= 0)
- error("invalid packet count %s", optarg);
+ cnt = parse_int("packet count", optarg, NULL, 1,
+ INT_MAX, 10);
break;
case 'C':
- errno = 0;
-#ifdef HAVE_PCAP_DUMP_FTELL64
- Cflag = strtoint64_t(optarg, &endp, 10);
-#else
- Cflag = strtol(optarg, &endp, 10);
-#endif
- if (endp == optarg || errno != 0 || Cflag <= 0)
- error("invalid file size %s", optarg);
+ Cflag = parse_int64("file size", optarg, &endp, 1,
+ INT64_MAX, 10);
if (*endp == '\0') {
/*
break;
default:
- error("invalid file size %s", optarg);
+ error("invalid file size %s (invalid units)", optarg);
}
/*
endp++;
if (*endp != '\0') {
/* Yes - error */
- error("invalid file size %s", optarg);
+ error("invalid file size %s (invalid units)", optarg);
}
}
* Will multiplying it by multiplier overflow?
*/
#ifdef HAVE_PCAP_DUMP_FTELL64
- if (Cflag > INT64_T_CONSTANT(0x7fffffffffffffff) / Cflagmult)
+ if (Cflag > INT64_MAX / Cflagmult)
#else
if (Cflag > LONG_MAX / Cflagmult)
#endif
++dflag;
break;
-#ifdef HAVE_PCAP_FINDALLDEVS
case 'D':
Dflag++;
break;
-#endif
#ifdef HAVE_PCAP_FINDALLDEVS_EX
case OPTION_LIST_REMOTE_INTERFACES:
++ndo->ndo_eflag;
break;
+#ifdef HAVE_LIBCRYPTO
case 'E':
-#ifndef HAVE_LIBCRYPTO
- warning("crypto code not compiled in");
-#endif
ndo->ndo_espsecret = optarg;
break;
+#endif
case 'f':
++ndo->ndo_fflag;
break;
case 'G':
- Gflag = atoi(optarg);
- if (Gflag < 0)
- error("invalid number of seconds %s", optarg);
+ Gflag = parse_int("number of seconds", optarg, NULL, 0,
+ INT_MAX, 10);
/* We will create one file initially. */
Gflag_count = 0;
case 'h':
print_usage(stdout);
exit_tcpdump(S_SUCCESS);
- break;
+ /* NOTREACHED */
case 'H':
++ndo->ndo_Hflag;
device = optarg;
break;
-#ifdef HAVE_PCAP_CREATE
case 'I':
++Iflag;
break;
-#endif /* HAVE_PCAP_CREATE */
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
case 'j':
*/
setvbuf(stdout, NULL, _IONBF, 0);
#else /* _WIN32 */
-#ifdef HAVE_SETLINEBUF
- setlinebuf(stdout);
-#else
setvbuf(stdout, NULL, _IOLBF, 0);
-#endif
#endif /* _WIN32 */
lflag = 1;
break;
}
break;
+#ifdef HAVE_LIBCRYPTO
case 'M':
/* TCP-MD5 shared secret */
-#ifndef HAVE_LIBCRYPTO
- warning("crypto code not compiled in");
-#endif
ndo->ndo_sigsecret = optarg;
break;
+#endif
case 'n':
++ndo->ndo_nflag;
++ndo->ndo_suppress_default_print;
break;
-#ifdef HAVE_PCAP_SETDIRECTION
case 'Q':
if (ascii_strcasecmp(optarg, "in") == 0)
Qflag = PCAP_D_IN;
else
error("unknown capture direction '%s'", optarg);
break;
-#endif /* HAVE_PCAP_SETDIRECTION */
case 'r':
RFileName = optarg;
break;
case 's':
- ndo->ndo_snaplen = (int)strtol(optarg, &end, 0);
- if (optarg == end || *end != '\0'
- || ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN)
- error("invalid snaplen %s (must be >= 0 and <= %d)",
- optarg, MAXIMUM_SNAPLEN);
+ ndo->ndo_snaplen = parse_int("snaplen", optarg, NULL,
+ 0, MAXIMUM_SNAPLEN, 0);
break;
case 'S':
++ndo->ndo_uflag;
break;
-#ifdef HAVE_PCAP_DUMP_FLUSH
case 'U':
++Uflag;
break;
-#endif
case 'v':
++ndo->ndo_vflag;
break;
case 'W':
- Wflag = atoi(optarg);
- if (Wflag <= 0)
- error("invalid number of output files %s", optarg);
+ Wflag = parse_int("number of output files", optarg,
+ NULL, 1, INT_MAX, 10);
WflagChars = getWflagChars(Wflag);
break;
}
break;
#endif
+
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
case 'z':
zflag = optarg;
break;
+#endif
case 'Z':
username = optarg;
ndo->ndo_packet_number = 1;
break;
+ case OPTION_LENGTHS:
+ ndo->ndo_lengths = 1;
+ break;
+
+ case OPTION_TIME_T_SIZE:
+ printf("%zu\n", sizeof(time_t) * 8);
+ return 0;
+
case OPTION_VERSION:
print_version(stdout);
exit_tcpdump(S_SUCCESS);
- break;
+ /* NOTREACHED */
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
case OPTION_TSTAMP_PRECISION:
case OPTION_PRINT_SAMPLING:
print = 1;
++ndo->ndo_Sflag;
- ndo->ndo_print_sampling = atoi(optarg);
- if (ndo->ndo_print_sampling <= 0)
- error("invalid print sampling %s", optarg);
+ ndo->ndo_print_sampling = parse_int("print sampling",
+ optarg, NULL, 1, INT_MAX, 10);
+ break;
+
+ case OPTION_SKIP:
+ packets_to_skip = parse_u_int("packet skip count",
+ optarg, NULL, 0, INT_MAX, 0);
break;
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
/* NOTREACHED */
}
-#ifdef HAVE_PCAP_FINDALLDEVS
+ if (ndo->ndo_Aflag && ndo->ndo_xflag)
+ error("-A and -x[x] are mutually exclusive.");
+ if (ndo->ndo_Aflag && ndo->ndo_Xflag)
+ error("-A and -X[X] are mutually exclusive.");
+ if (ndo->ndo_xflag && ndo->ndo_Xflag)
+ error("-x[x] and -X[X] are mutually exclusive.");
+ if (Cflag != 0 && WFileName == NULL)
+ error("-C cannot be used without -w.");
+ if (Gflag != 0 && WFileName == NULL)
+ error("-G cannot be used without -w.");
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
+ if (zflag != NULL && (WFileName == NULL || (Cflag == 0 && Gflag == 0)))
+ error("-z cannot be used without -w and (-C or -G).");
+#endif
+
+ if (cnt != -1)
+ if ((int)packets_to_skip > (INT_MAX - cnt))
+ // cnt + (int)packets_to_skip used in pcap_loop() call
+ error("Overflow (-c count) %d + (--skip count) %d", cnt,
+ (int)packets_to_skip);
+
if (Dflag)
show_devices_and_exit();
-#endif
#ifdef HAVE_PCAP_FINDALLDEVS_EX
if (remote_interfaces_source != NULL)
show_remote_devices_and_exit();
default: /* Not supported */
error("only -t, -tt, -ttt, -tttt and -ttttt are supported");
- break;
+ /* NOTREACHED */
}
if (ndo->ndo_fflag != 0 && (VFileName != NULL || RFileName != NULL))
- error("-f can not be used with -V or -r");
+ error("-f cannot be used with -V or -r.");
if (VFileName != NULL && RFileName != NULL)
error("-V and -r are mutually exclusive.");
VFile = fopen(VFileName, "r");
if (VFile == NULL)
- error("Unable to open file: %s\n", pcap_strerror(errno));
+ error("Unable to open file: %s", pcap_strerror(errno));
ret = get_next_file(VFile, VFileLine);
if (!ret)
- error("Nothing in %s\n", VFileName);
+ error("Nothing in %s", VFileName);
RFileName = VFileLine;
}
pcap_datalink_val_to_description(dlt));
}
fprintf(stderr, ", snapshot length %d\n", pcap_snapshot(pd));
-#ifdef DLT_LINUX_SLL2
+#if defined(DLT_LINUX_SLL2) && defined(__linux__)
if (dlt == DLT_LINUX_SLL2)
fprintf(stderr, "Warning: interface names might be incorrect\n");
#endif
/*
* No interface was specified. Pick one.
*/
-#ifdef HAVE_PCAP_FINDALLDEVS
/*
* Find the list of interfaces, and pick
* the first interface.
error("no interfaces available for capture");
device = strdup(devlist->name);
pcap_freealldevs(devlist);
-#else /* HAVE_PCAP_FINDALLDEVS */
- /*
- * Use whatever interface pcap_lookupdev()
- * chooses.
- */
- device = pcap_lookupdev(ebuf);
- if (device == NULL)
- error("%s", ebuf);
-#endif
}
/*
* a 1-based index in the list of
* interfaces.
*/
-#ifdef HAVE_PCAP_FINDALLDEVS
devnum = parse_interface_number(device);
if (devnum == -1) {
/*
pd = open_interface(device, ndo, ebuf);
if (pd == NULL)
error("%s", ebuf);
-#else /* HAVE_PCAP_FINDALLDEVS */
- /*
- * We can't get a list of interfaces; just
- * fail.
- */
- error("%s", ebuf);
-#endif /* HAVE_PCAP_FINDALLDEVS */
}
/*
if (setgid(getgid()) != 0 || setuid(getuid()) != 0)
fprintf(stderr, "Warning: setgid/setuid failed !\n");
#endif /* _WIN32 */
-#if !defined(HAVE_PCAP_CREATE) && defined(_WIN32)
- if(Bflag != 0)
- if(pcap_setbuff(pd, Bflag)==-1){
- error("%s", pcap_geterr(pd));
- }
-#endif /* !defined(HAVE_PCAP_CREATE) && defined(_WIN32) */
if (Lflag)
show_dlts_and_exit(pd, device);
if (yflag_dlt >= 0) {
-#ifdef HAVE_PCAP_SET_DATALINK
if (pcap_set_datalink(pd, yflag_dlt) < 0)
error("%s", pcap_geterr(pd));
-#else
- /*
- * We don't actually support changing the
- * data link type, so we only let them
- * set it to what it already is.
- */
- if (yflag_dlt != pcap_datalink(pd)) {
- error("%s is not one of the DLTs supported by this device\n",
- yflag_dlt_name);
- }
-#endif
(void)fprintf(stderr, "%s: data link type %s\n",
program_name,
pcap_datalink_val_to_name(yflag_dlt));
(void)fflush(stderr);
}
-#if defined(DLT_LINUX_SLL2) && defined(HAVE_PCAP_SET_DATALINK)
+#if defined(DLT_LINUX_SLL2)
else {
/*
* Attempt to set default linktype to
* on; this may be a non-Linux "any" device
* that doesn't support DLT_LINUX_SLL2.
*/
- if (strcmp(device, "any") == 0)
+ if (strcmp(device, "any") == 0) {
+DIAG_OFF_WARN_UNUSED_RESULT
(void) pcap_set_datalink(pd, DLT_LINUX_SLL2);
+DIAG_ON_WARN_UNUSED_RESULT
+ }
}
#endif
i = pcap_snapshot(pd);
#ifdef HAVE_PCAP_SET_OPTIMIZER_DEBUG
pcap_set_optimizer_debug(dflag);
#endif
- if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
+ /*
+ * netmask is in network byte order, pcap_compile() takes it
+ * in host byte order.
+ */
+ if (pcap_compile(pd, &fcode, cmdbuf, Oflag, ntohl(netmask)) < 0)
error("%s", pcap_geterr(pd));
if (dflag) {
bpf_dump(&fcode, dflag);
capdns = capdns_setup();
#endif /* HAVE_CASPER */
+ // Both localnet and netmask are in network byte order.
init_print(ndo, localnet, netmask);
#ifndef _WIN32
#endif
/* Cooperate with nohup(1) */
#ifndef _WIN32
+ /*
+ * In illumos /usr/include/sys/iso/signal_iso.h causes Clang to
+ * generate a -Wstrict-prototypes warning here, see [1]. The
+ * __illumos__ macro is available since at least GCC 11 and Clang 13,
+ * see [2].
+ * 1: https://www.illumos.org/issues/16344
+ * 2: https://www.illumos.org/issues/13726
+ */
+#ifdef __illumos__
+ DIAG_OFF_STRICT_PROTOTYPES
+#endif /* __illumos__ */
if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
+#ifdef __illumos__
+ DIAG_ON_STRICT_PROTOTYPES
+#endif /* __illumos__ */
(void)setsignal(SIGHUP, oldhandler);
#endif /* _WIN32 */
* devices, and can't just give users that permission,
* you'd make tcpdump set-UID or set-GID).
*
- * Tcpdump doesn't necessarily write only to one savefile;
+ * tcpdump doesn't necessarily write only to one savefile;
* the general only way to allow a -Z instance to write to
* savefiles as the user under whose UID it's run, rather
* than as the user specified with -Z, would thus be to switch
} else
dumpinfo.ndo = NULL;
-#ifdef HAVE_PCAP_DUMP_FLUSH
if (Uflag)
pcap_dump_flush(pdd);
-#endif
} else {
dlt = pcap_datalink(pd);
ndo->ndo_if_printer = get_if_printer(dlt);
#endif /* HAVE_CAPSICUM */
do {
- status = pcap_loop(pd, cnt, callback, pcap_userdata);
+ status = pcap_loop(pd,
+ (cnt == -1 ? -1 : cnt + (int)packets_to_skip),
+ callback, pcap_userdata);
if (WFileName == NULL) {
/*
* We're printing packets. Flush the printed output,
ndo->ndo_if_printer = get_if_printer(dlt);
/* Free the old filter */
pcap_freecode(&fcode);
- if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
+ /*
+ * netmask is in network byte order, pcap_compile() takes it
+ * in host byte order.
+ */
+ if (pcap_compile(pd, &fcode, cmdbuf, Oflag, ntohl(netmask)) < 0)
error("%s", pcap_geterr(pd));
}
exit_tcpdump(status == -1 ? S_ERR_HOST_PROGRAM : S_SUCCESS);
}
+/*
+ * Routines to parse numerical command-line arguments and check for
+ * errors, including "too large for that type".
+ */
+static int
+parse_int(const char *argname, const char *string, char **endpp,
+ int minval, int maxval, int base)
+{
+ long val;
+ char *endp;
+
+ errno = 0;
+ val = strtol(string, &endp, base);
+
+ /*
+ * Did it either not parse any of the string, find extra stuff
+ * at the end that the caller isn't interested in, or get
+ * another parsing error?
+ */
+ if (string == endp || (endpp == NULL && *endp != '\0') ||
+ (val == 0 && errno == EINVAL)) {
+ error("invalid %s \"%s\" (not a valid number)", argname,
+ string);
+ }
+
+ /*
+ * Did it get a value that's out of range?
+ */
+ if (((val == LONG_MAX || val == LONG_MIN) && errno == ERANGE) ||
+ val < minval || val > maxval) {
+ error("invalid %s %s (must be >= %d and <= %d)",
+ argname, string, minval, maxval);
+ }
+
+ /*
+ * OK, it passes all the tests.
+ */
+ if (endpp != NULL)
+ *endpp = endp;
+ return ((int)val);
+}
+
+static u_int
+parse_u_int(const char *argname, const char *string, char **endpp,
+ u_int minval, u_int maxval, int base)
+{
+ unsigned long val;
+ char *endp;
+
+ errno = 0;
+
+ /*
+ * strtoul() does *NOT* report an error if the string
+ * begins with a minus sign. We do.
+ */
+ if (*string == '-') {
+ error("invalid %s \"%s\" (not a valid unsigned number)",
+ argname, string);
+ }
+
+ val = strtoul(string, &endp, base);
+
+ /*
+ * Did it either not parse any of the string, find extra stuff
+ * at the end that the caller isn't interested in, or get
+ * another parsing error?
+ */
+ if (string == endp || (endpp == NULL && *endp != '\0') ||
+ (val == 0 && errno == EINVAL)) {
+ error("invalid %s \"%s\" (not a valid unsigned number)",
+ argname, string);
+ }
+
+ /*
+ * Did it get a value that's out of range?
+ */
+ if ((val == ULONG_MAX && errno == ERANGE) ||
+ val < minval || val > maxval) {
+ error("invalid %s %s (must be >= %u and <= %u)",
+ argname, string, minval, maxval);
+ }
+
+ /*
+ * OK, it passes all the tests.
+ */
+ if (endpp != NULL)
+ *endpp = endp;
+ return ((u_int)val);
+}
+
+static int64_t
+parse_int64(const char *argname, const char *string, char **endpp,
+ int64_t minval, int64_t maxval, int base)
+{
+ intmax_t val;
+ char *endp;
+
+ errno = 0;
+ val = strtoimax(string, &endp, base);
+
+ /*
+ * Did it either not parse any of the string, find extra stuff
+ * at the end that the caller isn't interested in, or get
+ * another parsing error?
+ */
+ if (string == endp || (endpp == NULL && *endp != '\0') ||
+ (val == 0 && errno == EINVAL)) {
+ error("invalid %s \"%s\" (not a valid number)", argname,
+ string);
+ }
+
+ /*
+ * Did it get a value that's out of range?
+ */
+ if (((val == INTMAX_MAX || val == INTMAX_MIN) && errno == ERANGE) ||
+ val < minval || val > maxval) {
+ error("invalid %s %s (must be >= %" PRId64 " and <= %" PRId64 ")",
+ argname, string, minval, maxval);
+ }
+
+ /*
+ * OK, it passes all the tests.
+ */
+ if (endpp != NULL)
+ *endpp = endp;
+ return ((int64_t)val);
+}
+
/*
* Catch a signal.
*/
)
new.sa_flags = SA_RESTART;
if (sigaction(sig, &new, &old) < 0)
+ /* The same workaround as for SIG_DFL above. */
+#ifdef __illumos__
+ DIAG_OFF_STRICT_PROTOTYPES
+#endif /* __illumos__ */
return (SIG_ERR);
+#ifdef __illumos__
+ DIAG_ON_STRICT_PROTOTYPES
+#endif /* __illumos__ */
return (old.sa_handler);
#endif
}
setitimer(ITIMER_REAL, &timer, NULL);
#endif /* _WIN32 */
-#ifdef HAVE_PCAP_BREAKLOOP
/*
* We have "pcap_breakloop()"; use it, so that we do as little
* as possible in the signal handler (it's probably not safe
* the ANSI C standard doesn't say it is).
*/
pcap_breakloop(pd);
-#else
- /*
- * We don't have "pcap_breakloop()"; this isn't safe, but
- * it's the best we can do. Print the summary if we're
- * not reading from a savefile - i.e., if we're doing a
- * live capture - and exit.
- */
- if (pd != NULL && pcap_file(pd) == NULL) {
- /*
- * We got interrupted, so perhaps we didn't
- * manage to finish a line we were printing.
- * Print an extra newline, just in case.
- */
- putchar('\n');
- (void)fflush(stdout);
- info(1);
- }
- exit_tcpdump(S_SUCCESS);
-#endif
}
/*
child = fork_subprocess();
if (child == -1) {
fprintf(stderr,
- "compress_savefile: fork failed: %s\n",
- pcap_strerror(errno));
+ "%s: fork failed: %s\n",
+ __func__, pcap_strerror(errno));
return;
}
if (child != 0) {
#endif
if (execlp(zflag, zflag, filename, (char *)NULL) == -1)
fprintf(stderr,
- "compress_savefile: execlp(%s, %s) failed: %s\n",
- zflag,
- filename,
- pcap_strerror(errno));
+ "%s: execlp(%s, %s) failed: %s\n",
+ __func__, zflag, filename, pcap_strerror(errno));
#ifdef HAVE_FORK
exit(S_ERR_HOST_PROGRAM);
#else
_exit(S_ERR_HOST_PROGRAM);
#endif
}
-#else /* HAVE_FORK && HAVE_VFORK */
+#endif /* HAVE_FORK || HAVE_VFORK */
+
static void
-compress_savefile(const char *filename)
+close_old_dump_file(struct dump_info *dump_info)
{
- fprintf(stderr,
- "compress_savefile failed. Functionality not implemented under your system\n");
+ /*
+ * Close the current file and open a new one.
+ */
+ pcap_dump_close(dump_info->pdd);
+
+#if defined(HAVE_FORK) || defined(HAVE_VFORK)
+ /*
+ * Compress the file we just closed, if the user asked for it.
+ */
+ if (zflag != NULL)
+ compress_savefile(dump_info->CurrentFileName);
+#endif
+}
+
+static void
+open_new_dump_file(struct dump_info *dump_info)
+{
+#ifdef HAVE_CAPSICUM
+ FILE *fp;
+ int fd;
+#endif
+
+#ifdef HAVE_LIBCAP_NG
+ capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
+ capng_apply(CAPNG_SELECT_BOTH);
+#endif /* HAVE_LIBCAP_NG */
+#ifdef HAVE_CAPSICUM
+ fd = openat(dump_info->dirfd, dump_info->CurrentFileName,
+ O_CREAT | O_WRONLY | O_TRUNC, 0644);
+ if (fd < 0) {
+ error("unable to open file %s", dump_info->CurrentFileName);
+ }
+ fp = fdopen(fd, "w");
+ if (fp == NULL) {
+ error("unable to fdopen file %s", dump_info->CurrentFileName);
+ }
+ dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp);
+#else /* !HAVE_CAPSICUM */
+ dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+#endif
+#ifdef HAVE_LIBCAP_NG
+ capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
+ capng_apply(CAPNG_SELECT_BOTH);
+#endif /* HAVE_LIBCAP_NG */
+ if (dump_info->pdd == NULL)
+ error("%s", pcap_geterr(pd));
+#ifdef HAVE_CAPSICUM
+ set_dumper_capsicum_rights(dump_info->pdd);
+#endif
}
-#endif /* HAVE_FORK && HAVE_VFORK */
static void
dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
dump_info = (struct dump_info *)user;
+ if (packets_captured <= packets_to_skip)
+ return;
+
/*
* XXX - this won't force the file to rotate on the specified time
* boundary, but it will rotate on the first packet received after the
/* If the time is greater than the specified window, rotate */
if (t - Gflag_time >= Gflag) {
-#ifdef HAVE_CAPSICUM
- FILE *fp;
- int fd;
-#endif
-
/* Update the Gflag_time */
Gflag_time = t;
/* Update Gflag_count */
Gflag_count++;
- /*
- * Close the current file and open a new one.
- */
- pcap_dump_close(dump_info->pdd);
- /*
- * Compress the file we just closed, if the user asked for it
- */
- if (zflag != NULL)
- compress_savefile(dump_info->CurrentFileName);
+ close_old_dump_file(dump_info);
/*
* Check to see if we've exceeded the Wflag (when
else
MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0);
-#ifdef HAVE_LIBCAP_NG
- capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
- capng_apply(CAPNG_SELECT_BOTH);
-#endif /* HAVE_LIBCAP_NG */
-#ifdef HAVE_CAPSICUM
- fd = openat(dump_info->dirfd,
- dump_info->CurrentFileName,
- O_CREAT | O_WRONLY | O_TRUNC, 0644);
- if (fd < 0) {
- error("unable to open file %s",
- dump_info->CurrentFileName);
- }
- fp = fdopen(fd, "w");
- if (fp == NULL) {
- error("unable to fdopen file %s",
- dump_info->CurrentFileName);
- }
- dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp);
-#else /* !HAVE_CAPSICUM */
- dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
-#endif
-#ifdef HAVE_LIBCAP_NG
- capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
- capng_apply(CAPNG_SELECT_BOTH);
-#endif /* HAVE_LIBCAP_NG */
- if (dump_info->pdd == NULL)
- error("%s", pcap_geterr(pd));
-#ifdef HAVE_CAPSICUM
- set_dumper_capsicum_rights(dump_info->pdd);
-#endif
+ open_new_dump_file(dump_info);
}
}
if (size == -1)
error("ftell fails on output file");
if (size > Cflag) {
-#ifdef HAVE_CAPSICUM
- FILE *fp;
- int fd;
-#endif
-
- /*
- * Close the current file and open a new one.
- */
- pcap_dump_close(dump_info->pdd);
-
- /*
- * Compress the file we just closed, if the user
- * asked for it.
- */
- if (zflag != NULL)
- compress_savefile(dump_info->CurrentFileName);
+ close_old_dump_file(dump_info);
Cflag_count++;
if (Wflag > 0) {
if (dump_info->CurrentFileName == NULL)
error("%s: malloc", __func__);
MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars);
-#ifdef HAVE_LIBCAP_NG
- capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
- capng_apply(CAPNG_SELECT_BOTH);
-#endif /* HAVE_LIBCAP_NG */
-#ifdef HAVE_CAPSICUM
- fd = openat(dump_info->dirfd, dump_info->CurrentFileName,
- O_CREAT | O_WRONLY | O_TRUNC, 0644);
- if (fd < 0) {
- error("unable to open file %s",
- dump_info->CurrentFileName);
- }
- fp = fdopen(fd, "w");
- if (fp == NULL) {
- error("unable to fdopen file %s",
- dump_info->CurrentFileName);
- }
- dump_info->pdd = pcap_dump_fopen(dump_info->pd, fp);
-#else /* !HAVE_CAPSICUM */
- dump_info->pdd = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
-#endif
-#ifdef HAVE_LIBCAP_NG
- capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE);
- capng_apply(CAPNG_SELECT_BOTH);
-#endif /* HAVE_LIBCAP_NG */
- if (dump_info->pdd == NULL)
- error("%s", pcap_geterr(pd));
-#ifdef HAVE_CAPSICUM
- set_dumper_capsicum_rights(dump_info->pdd);
-#endif
+
+ open_new_dump_file(dump_info);
}
}
pcap_dump((u_char *)dump_info->pdd, h, sp);
-#ifdef HAVE_PCAP_DUMP_FLUSH
if (Uflag)
pcap_dump_flush(dump_info->pdd);
-#endif
if (dump_info->ndo != NULL)
pretty_print_packet(dump_info->ndo, h, sp, packets_captured);
dump_info = (struct dump_info *)user;
+ if (packets_captured <= packets_to_skip)
+ return;
+
pcap_dump((u_char *)dump_info->pdd, h, sp);
-#ifdef HAVE_PCAP_DUMP_FLUSH
if (Uflag)
pcap_dump_flush(dump_info->pdd);
-#endif
if (dump_info->ndo != NULL)
pretty_print_packet(dump_info->ndo, h, sp, packets_captured);
++infodelay;
- if (!count_mode)
+ if (!count_mode && packets_captured > packets_to_skip)
pretty_print_packet((netdissect_options *)user, h, sp, packets_captured);
--infodelay;
static void
print_version(FILE *f)
{
-#ifndef HAVE_PCAP_LIB_VERSION
- #ifdef HAVE_PCAP_VERSION
- extern char pcap_version[];
- #else /* HAVE_PCAP_VERSION */
- static char pcap_version[] = "unknown";
- #endif /* HAVE_PCAP_VERSION */
-#endif /* HAVE_PCAP_LIB_VERSION */
const char *smi_version_string;
(void)fprintf(f, "%s version " PACKAGE_VERSION "\n", program_name);
-#ifdef HAVE_PCAP_LIB_VERSION
(void)fprintf(f, "%s\n", pcap_lib_version());
-#else /* HAVE_PCAP_LIB_VERSION */
- (void)fprintf(f, "libpcap version %s\n", pcap_version);
-#endif /* HAVE_PCAP_LIB_VERSION */
#if defined(HAVE_LIBCRYPTO) && defined(SSLEAY_VERSION)
(void)fprintf (f, "%s\n", SSLeay_version(SSLEAY_VERSION));
(void)fprintf (f, "Compiled with MemorySanitizer/Clang.\n");
# endif
#endif /* __SANITIZE_ADDRESS__ or __has_feature */
+ (void)fprintf (f, "%zu-bit build, %zu-bit time_t\n",
+ sizeof(void *) * 8, sizeof(time_t) * 8);
}
DIAG_ON_DEPRECATION
{
print_version(f);
(void)fprintf(f,
-"Usage: %s [-Abd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ] [--count]\n", program_name);
+"Usage: %s [-AbdDefhHI" J_FLAG "KlLnNOpqStuUvxX#] [ -B size ] [ -c count ] [--count]\n", program_name);
(void)fprintf(f,
-"\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n");
+"\t\t[ -C file_size ] " E_FLAG_USAGE "[ -F file ] [ -G seconds ]\n");
(void)fprintf(f,
"\t\t[ -i interface ]" IMMEDIATE_MODE_USAGE j_FLAG_USAGE "\n");
-#ifdef HAVE_PCAP_FINDALLDEVS_EX
(void)fprintf(f,
-"\t\t" LIST_REMOTE_INTERFACES_USAGE "\n");
-#endif
+"\t\t[ --lengths ]" LIST_REMOTE_INTERFACES_USAGE "\n");
#ifdef USE_LIBSMI
(void)fprintf(f,
"\t\t" m_FLAG_USAGE "\n");
#endif
(void)fprintf(f,
-"\t\t[ -M secret ] [ --number ] [ --print ]\n");
+"\t\t" M_FLAG_USAGE "[ --number ] [ --print ]\n");
(void)fprintf(f,
-"\t\t[ --print-sampling nth ]" Q_FLAG_USAGE " [ -r file ]\n");
+"\t\t[ --print-sampling nth ] [ -Q in|out|inout ] [ -r file ]\n");
(void)fprintf(f,
-"\t\t[ -s snaplen ] [ -T type ] [ --version ]\n");
+"\t\t[ -s snaplen ] [ --skip count ] [ -T type ] [ --version ]\n");
(void)fprintf(f,
"\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n");
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
"\t\t[ --time-stamp-precision precision ] [ --micro ] [ --nano ]\n");
#endif
(void)fprintf(f,
-"\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n");
+"\t\t" z_FLAG_USAGE "[ -Z user ] [ expression ]\n");
}