Changeset View
Changeset View
Standalone View
Standalone View
head/contrib/tcpdump/tcpdump.c
Show All 39 Lines | |||||
* Mercilessly hacked and occasionally improved since then via the | * Mercilessly hacked and occasionally improved since then via the | ||||
* combined efforts of Van, Steve McCanne and Craig Leres of LBL. | * combined efforts of Van, Steve McCanne and Craig Leres of LBL. | ||||
*/ | */ | ||||
#ifdef HAVE_CONFIG_H | #ifdef HAVE_CONFIG_H | ||||
#include "config.h" | #include "config.h" | ||||
#endif | #endif | ||||
/* | |||||
* Mac OS X may 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 | |||||
#endif | |||||
#include <tcpdump-stdinc.h> | #include <tcpdump-stdinc.h> | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
#include "w32_fzs.h" | #include "w32_fzs.h" | ||||
extern int strcasecmp (const char *__s1, const char *__s2); | extern int strcasecmp (const char *__s1, const char *__s2); | ||||
extern int SIZE_BUF; | extern int SIZE_BUF; | ||||
#define off_t long | #define off_t long | ||||
#define uint UINT | #define uint UINT | ||||
#endif /* WIN32 */ | #endif /* WIN32 */ | ||||
#ifdef USE_LIBSMI | #ifdef USE_LIBSMI | ||||
#include <smi.h> | #include <smi.h> | ||||
#endif | #endif | ||||
#ifdef HAVE_LIBCRYPTO | #ifdef HAVE_LIBCRYPTO | ||||
#include <openssl/crypto.h> | #include <openssl/crypto.h> | ||||
#endif | #endif | ||||
#ifdef HAVE_GETOPT_LONG | #ifdef HAVE_GETOPT_LONG | ||||
#include <getopt.h> | #include <getopt.h> | ||||
#else | #else | ||||
#include "getopt_long.h" | #include "getopt_long.h" | ||||
#endif | #endif | ||||
#include <pcap.h> | /* Capsicum-specific code requires macros from <net/bpf.h>, which will fail | ||||
#include <signal.h> | * to compile if <pcap.h> has already been included; including the headers | ||||
#include <stdio.h> | * in the opposite order works fine. | ||||
#include <stdlib.h> | */ | ||||
#include <string.h> | |||||
#include <limits.h> | |||||
#ifdef __FreeBSD__ | #ifdef __FreeBSD__ | ||||
#include <sys/capsicum.h> | #include <sys/capsicum.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#endif /* __FreeBSD__ */ | #endif /* __FreeBSD__ */ | ||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
#include <libcapsicum.h> | #include <libcapsicum.h> | ||||
#include <libcapsicum_dns.h> | #include <libcapsicum_dns.h> | ||||
#include <libcapsicum_service.h> | #include <libcapsicum_service.h> | ||||
#include <sys/nv.h> | #include <sys/nv.h> | ||||
#include <sys/capability.h> | #include <sys/capability.h> | ||||
#include <sys/ioccom.h> | #include <sys/ioccom.h> | ||||
#include <net/bpf.h> | #include <net/bpf.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <libgen.h> | #include <libgen.h> | ||||
#endif /* HAVE_CAPSICUM */ | #endif /* HAVE_CAPSICUM */ | ||||
#include <pcap.h> | |||||
#include <signal.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <limits.h> | |||||
#ifndef WIN32 | #ifndef WIN32 | ||||
#include <sys/wait.h> | #include <sys/wait.h> | ||||
#include <sys/resource.h> | #include <sys/resource.h> | ||||
#include <pwd.h> | #include <pwd.h> | ||||
#include <grp.h> | #include <grp.h> | ||||
#endif /* WIN32 */ | #endif /* WIN32 */ | ||||
/* capabilities convinience library */ | /* capabilities convenience library */ | ||||
/* If a code depends on HAVE_LIBCAP_NG, it depends also on HAVE_CAP_NG_H. | |||||
* If HAVE_CAP_NG_H is not defined, undefine HAVE_LIBCAP_NG. | |||||
* Thus, the later tests are done only on HAVE_LIBCAP_NG. | |||||
*/ | |||||
#ifdef HAVE_LIBCAP_NG | |||||
#ifdef HAVE_CAP_NG_H | #ifdef HAVE_CAP_NG_H | ||||
#include <cap-ng.h> | #include <cap-ng.h> | ||||
#else | |||||
#undef HAVE_LIBCAP_NG | |||||
#endif /* HAVE_CAP_NG_H */ | #endif /* HAVE_CAP_NG_H */ | ||||
#endif /* HAVE_LIBCAP_NG */ | |||||
#include "netdissect.h" | #include "netdissect.h" | ||||
#include "interface.h" | #include "interface.h" | ||||
#include "addrtoname.h" | #include "addrtoname.h" | ||||
#include "machdep.h" | #include "machdep.h" | ||||
#include "setsignal.h" | #include "setsignal.h" | ||||
#include "gmt2local.h" | #include "gmt2local.h" | ||||
#include "pcap-missing.h" | #include "pcap-missing.h" | ||||
▲ Show 20 Lines • Show All 482 Lines • ▼ Show 20 Lines | |||||
* OS X tcpdump uses -k tospecify that packet comments in pcap-ng files | * OS X tcpdump uses -k tospecify that packet comments in pcap-ng files | ||||
* should be printed; | * should be printed; | ||||
* | * | ||||
* OpenBSD tcpdump uses -o to indicate that OS fingerprinting should be done | * OpenBSD tcpdump uses -o to indicate that OS fingerprinting should be done | ||||
* for hosts sending TCP SYN packets; | * for hosts sending TCP SYN packets; | ||||
* | * | ||||
* OS X tcpdump uses -P to indicate that -w should write pcap-ng rather | * OS X tcpdump uses -P to indicate that -w should write pcap-ng rather | ||||
* than pcap files. | * than pcap files. | ||||
* | |||||
* OS X tcpdump also uses -Q to specify expressions that match packet | |||||
* metadata, including but not limited to the packet direction. | |||||
* The expression syntax is different from a simple "in|out|inout", | |||||
* and those expressions aren't accepted by OS X tcpdump, but the | |||||
* equivalents would be "in" = "dir=in", "out" = "dir=out", and | |||||
* "inout" = "dir=in or dir=out", and the parser could conceivably | |||||
* special-case "in", "out", and "inout" as expressions for backwards | |||||
* compatibility, so all is not (yet) lost. | |||||
*/ | */ | ||||
/* | /* | ||||
* Set up flags that might or might not be supported depending on the | * Set up flags that might or might not be supported depending on the | ||||
* version of libpcap we're using. | * version of libpcap we're using. | ||||
*/ | */ | ||||
#if defined(HAVE_PCAP_CREATE) || defined(WIN32) | #if defined(HAVE_PCAP_CREATE) || defined(WIN32) | ||||
#define B_FLAG "B:" | #define B_FLAG "B:" | ||||
Show All 15 Lines | |||||
#define J_FLAG "J" | #define J_FLAG "J" | ||||
#else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ | #else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ | ||||
#define j_FLAG | #define j_FLAG | ||||
#define j_FLAG_USAGE | #define j_FLAG_USAGE | ||||
#define J_FLAG | #define J_FLAG | ||||
#endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ | #endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ | ||||
#ifdef HAVE_PCAP_FINDALLDEVS | #ifdef HAVE_PCAP_FINDALLDEVS | ||||
#ifndef HAVE_PCAP_IF_T | |||||
#undef HAVE_PCAP_FINDALLDEVS | |||||
#endif | |||||
#endif | |||||
#ifdef HAVE_PCAP_FINDALLDEVS | |||||
#define D_FLAG "D" | #define D_FLAG "D" | ||||
#else | #else | ||||
#define D_FLAG | #define D_FLAG | ||||
#endif | #endif | ||||
#ifdef HAVE_PCAP_DUMP_FLUSH | #ifdef HAVE_PCAP_DUMP_FLUSH | ||||
#define U_FLAG "U" | #define U_FLAG "U" | ||||
#else | #else | ||||
#define U_FLAG | #define U_FLAG | ||||
#endif | #endif | ||||
#ifdef HAVE_PCAP_SETDIRECTION | #ifdef HAVE_PCAP_SETDIRECTION | ||||
#define Q_FLAG "Q:" | #define Q_FLAG "Q:" | ||||
#else | #else | ||||
#define Q_FLAG | #define Q_FLAG | ||||
#endif | #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:Rs:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#" | |||||
/* | /* | ||||
* Long options. | * Long options. | ||||
* | * | ||||
* We do not currently have long options corresponding to all short | * We do not currently have long options corresponding to all short | ||||
* options; we should probably pick appropriate option names for them. | * options; we should probably pick appropriate option names for them. | ||||
* | * | ||||
* However, the short options where the number of times the option is | * However, the short options where the number of times the option is | ||||
* specified matters, such as -v and -d and -t, should probably not | * specified matters, such as -v and -d and -t, should probably not | ||||
* just map to a long option, as saying | * just map to a long option, as saying | ||||
* | * | ||||
* tcpdump --verbose --verbose | * tcpdump --verbose --verbose | ||||
* | * | ||||
* doesn't make sense; it should be --verbosity={N} or something such | * doesn't make sense; it should be --verbosity={N} or something such | ||||
* as that. | * as that. | ||||
* | * | ||||
* For long options with no corresponding short options, we define values | * For long options with no corresponding short options, we define values | ||||
* outside the range of ASCII graphic characters, make that the last | * outside the range of ASCII graphic characters, make that the last | ||||
* component of the entry for the long option, and have a case for that | * component of the entry for the long option, and have a case for that | ||||
* option in the switch statement. | * option in the switch statement. | ||||
*/ | */ | ||||
#define OPTION_VERSION 128 | #define OPTION_VERSION 128 | ||||
#define OPTION_TSTAMP_PRECISION 129 | #define OPTION_TSTAMP_PRECISION 129 | ||||
#define OPTION_IMMEDIATE_MODE 130 | |||||
static const struct option longopts[] = { | static const struct option longopts[] = { | ||||
#if defined(HAVE_PCAP_CREATE) || defined(WIN32) | #if defined(HAVE_PCAP_CREATE) || defined(WIN32) | ||||
{ "buffer-size", required_argument, NULL, 'B' }, | { "buffer-size", required_argument, NULL, 'B' }, | ||||
#endif | #endif | ||||
{ "list-interfaces", no_argument, NULL, 'D' }, | { "list-interfaces", no_argument, NULL, 'D' }, | ||||
{ "help", no_argument, NULL, 'h' }, | { "help", no_argument, NULL, 'h' }, | ||||
{ "interface", required_argument, NULL, 'i' }, | { "interface", required_argument, NULL, 'i' }, | ||||
Show All 15 Lines | #ifdef HAVE_PCAP_SETDIRECTION | ||||
{ "direction", required_argument, NULL, 'Q' }, | { "direction", required_argument, NULL, 'Q' }, | ||||
#endif | #endif | ||||
{ "snapshot-length", required_argument, NULL, 's' }, | { "snapshot-length", required_argument, NULL, 's' }, | ||||
{ "absolute-tcp-sequence-numbers", no_argument, NULL, 'S' }, | { "absolute-tcp-sequence-numbers", no_argument, NULL, 'S' }, | ||||
#ifdef HAVE_PCAP_DUMP_FLUSH | #ifdef HAVE_PCAP_DUMP_FLUSH | ||||
{ "packet-buffered", no_argument, NULL, 'U' }, | { "packet-buffered", no_argument, NULL, 'U' }, | ||||
#endif | #endif | ||||
{ "linktype", required_argument, NULL, 'y' }, | { "linktype", required_argument, NULL, 'y' }, | ||||
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE | |||||
{ "immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE }, | |||||
#endif | |||||
#if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) | #if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) | ||||
{ "debug-filter-parser", no_argument, NULL, 'Y' }, | { "debug-filter-parser", no_argument, NULL, 'Y' }, | ||||
#endif | #endif | ||||
{ "relinquish-privileges", required_argument, NULL, 'Z' }, | { "relinquish-privileges", required_argument, NULL, 'Z' }, | ||||
{ "number", no_argument, NULL, '#' }, | { "number", no_argument, NULL, '#' }, | ||||
{ "version", no_argument, NULL, OPTION_VERSION }, | { "version", no_argument, NULL, OPTION_VERSION }, | ||||
{ NULL, 0, NULL, 0 } | { NULL, 0, NULL, 0 } | ||||
}; | }; | ||||
Show All 14 Lines | droproot(const char *username, const char *chroot_dir) | ||||
if (pw) { | if (pw) { | ||||
if (chroot_dir) { | if (chroot_dir) { | ||||
if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { | if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { | ||||
fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n", | fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n", | ||||
chroot_dir, pcap_strerror(errno)); | chroot_dir, pcap_strerror(errno)); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
} | } | ||||
#ifdef HAVE_CAP_NG_H | #ifdef HAVE_LIBCAP_NG | ||||
int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG); | int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
fprintf(stderr, "error : ret %d\n", ret); | fprintf(stderr, "error : ret %d\n", ret); | ||||
} | } | ||||
else { | else { | ||||
printf("dropped privs to %s\n", username); | fprintf(stderr, "dropped privs to %s\n", username); | ||||
} | } | ||||
/* We don't need CAP_SETUID and CAP_SETGID */ | |||||
capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID); | |||||
capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID); | |||||
capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID); | |||||
capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID); | |||||
capng_apply(CAPNG_SELECT_BOTH); | |||||
#else | #else | ||||
if (initgroups(pw->pw_name, pw->pw_gid) != 0 || | if (initgroups(pw->pw_name, pw->pw_gid) != 0 || | ||||
setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { | setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { | ||||
fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", | fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", | ||||
username, | username, | ||||
(unsigned long)pw->pw_uid, | (unsigned long)pw->pw_uid, | ||||
(unsigned long)pw->pw_gid, | (unsigned long)pw->pw_gid, | ||||
pcap_strerror(errno)); | pcap_strerror(errno)); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
else { | else { | ||||
printf("dropped privs to %s\n", username); | fprintf(stderr, "dropped privs to %s\n", username); | ||||
} | } | ||||
#endif /* HAVE_CAP_NG_H */ | #endif /* HAVE_LIBCAP_NG */ | ||||
} | } | ||||
else { | else { | ||||
fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", | fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", | ||||
username); | username); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
#ifdef HAVE_LIBCAP_NG | |||||
/* We don't need CAP_SETUID and CAP_SETGID any more. */ | |||||
capng_updatev( | |||||
CAPNG_DROP, | |||||
CAPNG_EFFECTIVE | CAPNG_PERMITTED, | |||||
CAP_SETUID, | |||||
CAP_SETGID, | |||||
-1); | |||||
capng_apply(CAPNG_SELECT_BOTH); | |||||
#endif /* HAVE_LIBCAP_NG */ | |||||
} | } | ||||
#endif /* WIN32 */ | #endif /* WIN32 */ | ||||
static int | static int | ||||
getWflagChars(int x) | getWflagChars(int x) | ||||
{ | { | ||||
int c = 0; | int c = 0; | ||||
▲ Show 20 Lines • Show All 148 Lines • ▼ Show 20 Lines | case PCAP_TSTAMP_PRECISION_NANO: | ||||
return "nano"; | return "nano"; | ||||
default: | default: | ||||
return "unknown"; | return "unknown"; | ||||
} | } | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef HAVE_CAPSICUM | |||||
/* | |||||
* Ensure that, on a dump file's descriptor, we have all the rights | |||||
* necessary to make the standard I/O library work with an fdopen()ed | |||||
* FILE * from that descriptor. | |||||
* | |||||
* A long time ago, in a galaxy far far away, AT&T decided that, instead | |||||
* of providing separate APIs for getting and setting the FD_ flags on a | |||||
* descriptor, getting and setting the O_ flags on a descriptor, and | |||||
* locking files, they'd throw them all into a kitchen-sink fcntl() call | |||||
* along the lines of ioctl(), the fact that ioctl() operations are | |||||
* largely specific to particular character devices but fcntl() operations | |||||
* are either generic to all descriptors or generic to all descriptors for | |||||
* regular files nonwithstanding. | |||||
* | |||||
* The Capsicum people decided that fine-grained control of descriptor | |||||
* operations was required, so that you need to grant permission for | |||||
* reading, writing, seeking, and fcntl-ing. The latter, courtesy of | |||||
* AT&T's decision, means that "fcntl-ing" isn't a thing, but a motley | |||||
* collection of things, so there are *individual* fcntls for which | |||||
* permission needs to be granted. | |||||
* | |||||
* The FreeBSD standard I/O people implemented some optimizations that | |||||
* requires that the standard I/O routines be able to determine whether | |||||
* the descriptor for the FILE * is open append-only or not; as that | |||||
* descriptor could have come from an open() rather than an fopen(), | |||||
* 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 | |||||
* 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 | |||||
* optimization, also know whether the descriptor is open append-only | |||||
* or not. | |||||
* | |||||
* The net result of all the above is that we need to grant CAP_SEEK, | |||||
* CAP_WRITE, and CAP_FCNTL with the CAP_FCNTL_GETFL subcapability. | |||||
* | |||||
* Perhaps this is the universe's way of saying that either | |||||
* | |||||
* 1) there needs to be an fopenat() call and a pcap_dump_openat() call | |||||
* using it, so that Capsicum-capable tcpdump wouldn't need to do | |||||
* an fdopen() | |||||
* | |||||
* or | |||||
* | |||||
* 2) there needs to be a cap_fdopen() call in the FreeBSD standard | |||||
* I/O library that knows what rights are needed by the standard | |||||
* I/O library, based on the open mode, and assigns them, perhaps | |||||
* with an additional argument indicating, for example, whether | |||||
* seeking should be allowed, so that tcpdump doesn't need to know | |||||
* what the standard I/O library happens to require this week. | |||||
*/ | |||||
static void | |||||
set_dumper_capsicum_rights(pcap_dumper_t *p) | |||||
{ | |||||
int fd = fileno(pcap_dump_file(p)); | |||||
cap_rights_t rights; | |||||
cap_rights_init(&rights, CAP_SEEK, CAP_WRITE, CAP_FCNTL); | |||||
if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) { | |||||
error("unable to limit dump descriptor"); | |||||
} | |||||
if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS) { | |||||
error("unable to limit dump descriptor fcntls"); | |||||
} | |||||
} | |||||
#endif | |||||
int | int | ||||
main(int argc, char **argv) | main(int argc, char **argv) | ||||
{ | { | ||||
register int cnt, op, i; | register int cnt, op, i; | ||||
bpf_u_int32 localnet =0 , netmask = 0; | bpf_u_int32 localnet =0 , netmask = 0; | ||||
register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; | register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; | ||||
pcap_handler callback; | pcap_handler callback; | ||||
int type; | int type; | ||||
Show All 32 Lines | jflag=-1; /* not set */ | ||||
gndo->ndo_Oflag=1; | gndo->ndo_Oflag=1; | ||||
gndo->ndo_Rflag=1; | gndo->ndo_Rflag=1; | ||||
gndo->ndo_dlt=-1; | gndo->ndo_dlt=-1; | ||||
gndo->ndo_default_print=ndo_default_print; | gndo->ndo_default_print=ndo_default_print; | ||||
gndo->ndo_printf=tcpdump_printf; | gndo->ndo_printf=tcpdump_printf; | ||||
gndo->ndo_error=ndo_error; | gndo->ndo_error=ndo_error; | ||||
gndo->ndo_warning=ndo_warning; | gndo->ndo_warning=ndo_warning; | ||||
gndo->ndo_snaplen = DEFAULT_SNAPLEN; | gndo->ndo_snaplen = DEFAULT_SNAPLEN; | ||||
gndo->ndo_immediate = 0; | |||||
cnt = -1; | cnt = -1; | ||||
device = NULL; | device = NULL; | ||||
infile = NULL; | infile = NULL; | ||||
RFileName = NULL; | RFileName = NULL; | ||||
VFileName = NULL; | VFileName = NULL; | ||||
VFile = NULL; | VFile = NULL; | ||||
WFileName = NULL; | WFileName = NULL; | ||||
dlt = -1; | dlt = -1; | ||||
if ((cp = strrchr(argv[0], '/')) != NULL) | if ((cp = strrchr(argv[0], '/')) != NULL) | ||||
program_name = cp + 1; | program_name = cp + 1; | ||||
else | else | ||||
program_name = argv[0]; | program_name = argv[0]; | ||||
/* | |||||
* 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) | if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) | ||||
error("%s", ebuf); | error("%s", ebuf); | ||||
#ifdef USE_LIBSMI | #ifdef USE_LIBSMI | ||||
smiInit("tcpdump"); | smiInit("tcpdump"); | ||||
#endif | #endif | ||||
while ( | while ( | ||||
(op = getopt_long(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:Rs:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#", longopts, NULL)) != -1) | (op = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != -1) | ||||
switch (op) { | switch (op) { | ||||
case 'a': | case 'a': | ||||
/* compatibility for old -a */ | /* compatibility for old -a */ | ||||
break; | break; | ||||
case 'A': | case 'A': | ||||
++Aflag; | ++Aflag; | ||||
▲ Show 20 Lines • Show All 361 Lines • ▼ Show 20 Lines | |||||
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION | ||||
case OPTION_TSTAMP_PRECISION: | case OPTION_TSTAMP_PRECISION: | ||||
gndo->ndo_tstamp_precision = tstamp_precision_from_string(optarg); | gndo->ndo_tstamp_precision = tstamp_precision_from_string(optarg); | ||||
if (gndo->ndo_tstamp_precision < 0) | if (gndo->ndo_tstamp_precision < 0) | ||||
error("unsupported time stamp precision"); | error("unsupported time stamp precision"); | ||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE | |||||
case OPTION_IMMEDIATE_MODE: | |||||
gndo->ndo_immediate = 1; | |||||
break; | |||||
#endif | |||||
default: | default: | ||||
print_usage(); | print_usage(); | ||||
exit(1); | exit(1); | ||||
/* NOTREACHED */ | /* NOTREACHED */ | ||||
} | } | ||||
#ifdef HAVE_PCAP_FINDALLDEVS | #ifdef HAVE_PCAP_FINDALLDEVS | ||||
if (Dflag) | if (Dflag) | ||||
Show All 19 Lines | #endif | ||||
} | } | ||||
if (fflag != 0 && (VFileName != NULL || RFileName != NULL)) | if (fflag != 0 && (VFileName != NULL || RFileName != NULL)) | ||||
error("-f can not be used with -V or -r"); | error("-f can not be used with -V or -r"); | ||||
if (VFileName != NULL && RFileName != NULL) | if (VFileName != NULL && RFileName != NULL) | ||||
error("-V and -r are mutually exclusive."); | error("-V and -r are mutually exclusive."); | ||||
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE | |||||
/* | |||||
* If we're printing dissected packets to the standard output | |||||
* rather than saving raw packets to a file, and the standard | |||||
* output is a terminal, use immediate mode, as the user's | |||||
* probably expecting to see packets pop up immediately. | |||||
*/ | |||||
if (WFileName == NULL && isatty(1)) | |||||
gndo->ndo_immediate = 1; | |||||
#endif | |||||
#ifdef WITH_CHROOT | #ifdef WITH_CHROOT | ||||
/* if run as root, prepare for chrooting */ | /* if run as root, prepare for chrooting */ | ||||
if (getuid() == 0 || geteuid() == 0) { | if (getuid() == 0 || geteuid() == 0) { | ||||
/* future extensibility for cmd-line arguments */ | /* future extensibility for cmd-line arguments */ | ||||
if (!chroot_dir) | if (!chroot_dir) | ||||
chroot_dir = WITH_CHROOT; | chroot_dir = WITH_CHROOT; | ||||
} | } | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION | ||||
status = pcap_set_tstamp_precision(pd, gndo->ndo_tstamp_precision); | status = pcap_set_tstamp_precision(pd, gndo->ndo_tstamp_precision); | ||||
if (status != 0) | if (status != 0) | ||||
error("%s: Can't set %ssecond time stamp precision: %s", | error("%s: Can't set %ssecond time stamp precision: %s", | ||||
device, | device, | ||||
tstamp_precision_to_string(gndo->ndo_tstamp_precision), | tstamp_precision_to_string(gndo->ndo_tstamp_precision), | ||||
pcap_statustostr(status)); | pcap_statustostr(status)); | ||||
#endif | #endif | ||||
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE | |||||
if (gndo->ndo_immediate) { | |||||
status = pcap_set_immediate_mode(pd, 1); | |||||
if (status != 0) | |||||
error("%s: Can't set immediate mode: %s", | |||||
device, | |||||
pcap_statustostr(status)); | |||||
} | |||||
#endif | |||||
/* | /* | ||||
* Is this an interface that supports monitor mode? | * Is this an interface that supports monitor mode? | ||||
*/ | */ | ||||
if (pcap_can_set_rfmon(pd) == 1) | if (pcap_can_set_rfmon(pd) == 1) | ||||
supports_monitor_mode = 1; | supports_monitor_mode = 1; | ||||
else | else | ||||
supports_monitor_mode = 0; | supports_monitor_mode = 0; | ||||
status = pcap_set_snaplen(pd, snaplen); | status = pcap_set_snaplen(pd, snaplen); | ||||
Show All 20 Lines | if (Bflag != 0) { | ||||
error("%s: Can't set buffer size: %s", | error("%s: Can't set buffer size: %s", | ||||
device, pcap_statustostr(status)); | device, pcap_statustostr(status)); | ||||
} | } | ||||
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE | #ifdef HAVE_PCAP_SET_TSTAMP_TYPE | ||||
if (jflag != -1) { | if (jflag != -1) { | ||||
status = pcap_set_tstamp_type(pd, jflag); | status = pcap_set_tstamp_type(pd, jflag); | ||||
if (status < 0) | if (status < 0) | ||||
error("%s: Can't set time stamp type: %s", | error("%s: Can't set time stamp type: %s", | ||||
device, pcap_statustostr(status)); | device, pcap_statustostr(status)); | ||||
} | } | ||||
#endif | #endif | ||||
status = pcap_activate(pd); | status = pcap_activate(pd); | ||||
if (status < 0) { | if (status < 0) { | ||||
/* | /* | ||||
* pcap_activate() failed. | * pcap_activate() failed. | ||||
*/ | */ | ||||
cp = pcap_geterr(pd); | cp = pcap_geterr(pd); | ||||
▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | #ifndef WIN32 | ||||
* savefiles as the user under whose UID it's run, rather | * savefiles as the user under whose UID it's run, rather | ||||
* than as the user specified with -Z, would thus be to switch | * than as the user specified with -Z, would thus be to switch | ||||
* to the original user ID before opening a capture file and | * to the original user ID before opening a capture file and | ||||
* then switch back to the -Z user ID after opening the savefile. | * then switch back to the -Z user ID after opening the savefile. | ||||
* Switching to the -Z user ID only after opening the first | * Switching to the -Z user ID only after opening the first | ||||
* savefile doesn't handle the general case. | * savefile doesn't handle the general case. | ||||
*/ | */ | ||||
#ifdef HAVE_CAP_NG_H | if (getuid() == 0 || geteuid() == 0) { | ||||
/* We are running as root and we will be writing to savefile */ | #ifdef HAVE_LIBCAP_NG | ||||
if ((getuid() == 0 || geteuid() == 0) && WFileName) { | /* Initialize capng */ | ||||
capng_clear(CAPNG_SELECT_BOTH); | |||||
if (username) { | if (username) { | ||||
/* Drop all capabilities from effective set */ | capng_updatev( | ||||
capng_clear(CAPNG_EFFECTIVE); | CAPNG_ADD, | ||||
/* Add capabilities we will need*/ | CAPNG_PERMITTED | CAPNG_EFFECTIVE, | ||||
capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETUID); | CAP_SETUID, | ||||
capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETGID); | CAP_SETGID, | ||||
capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_DAC_OVERRIDE); | -1); | ||||
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETUID); | |||||
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETGID); | |||||
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); | |||||
capng_apply(CAPNG_SELECT_BOTH); | |||||
} | } | ||||
} | |||||
#endif /* HAVE_CAP_NG_H */ | |||||
if (getuid() == 0 || geteuid() == 0) { | if (WFileName) { | ||||
capng_update( | |||||
CAPNG_ADD, | |||||
CAPNG_PERMITTED | CAPNG_EFFECTIVE, | |||||
CAP_DAC_OVERRIDE | |||||
); | |||||
} | |||||
capng_apply(CAPNG_SELECT_BOTH); | |||||
#endif /* HAVE_LIBCAP_NG */ | |||||
if (username || chroot_dir) | if (username || chroot_dir) | ||||
droproot(username, chroot_dir); | droproot(username, chroot_dir); | ||||
} | } | ||||
#endif /* WIN32 */ | #endif /* WIN32 */ | ||||
if (pcap_setfilter(pd, &fcode) < 0) | if (pcap_setfilter(pd, &fcode) < 0) | ||||
error("%s", pcap_geterr(pd)); | error("%s", pcap_geterr(pd)); | ||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
if (RFileName == NULL && VFileName == NULL) { | if (RFileName == NULL && VFileName == NULL) { | ||||
static const unsigned long cmds[] = { BIOCGSTATS }; | static const unsigned long cmds[] = { BIOCGSTATS }; | ||||
cap_rights_init(&rights, CAP_IOCTL, CAP_READ); | /* | ||||
* The various libpcap devices use a combination of | |||||
* read (bpf), ioctl (bpf, netmap), poll (netmap). | |||||
* Grant the relevant access rights, sorted by name. | |||||
*/ | |||||
cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ); | |||||
if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 && | if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 && | ||||
errno != ENOSYS) { | errno != ENOSYS) { | ||||
error("unable to limit pcap descriptor"); | error("unable to limit pcap descriptor"); | ||||
} | } | ||||
if (cap_ioctls_limit(pcap_fileno(pd), cmds, | if (cap_ioctls_limit(pcap_fileno(pd), cmds, | ||||
sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) { | sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) { | ||||
error("unable to limit ioctls on pcap descriptor"); | error("unable to limit ioctls on pcap descriptor"); | ||||
} | } | ||||
Show All 9 Lines | if (WFileName) { | ||||
/* We do not need numbering for dumpfiles if Cflag isn't set. */ | /* We do not need numbering for dumpfiles if Cflag isn't set. */ | ||||
if (Cflag != 0) | if (Cflag != 0) | ||||
MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars); | MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars); | ||||
else | else | ||||
MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); | MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); | ||||
p = pcap_dump_open(pd, dumpinfo.CurrentFileName); | p = pcap_dump_open(pd, dumpinfo.CurrentFileName); | ||||
#ifdef HAVE_CAP_NG_H | #ifdef HAVE_LIBCAP_NG | ||||
/* Give up capabilities, clear Effective set */ | /* Give up CAP_DAC_OVERRIDE capability. | ||||
capng_clear(CAPNG_EFFECTIVE); | * Only allow it to be restored if the -C or -G flag have been | ||||
#endif | * set since we may need to create more files later on. | ||||
*/ | |||||
capng_update( | |||||
CAPNG_DROP, | |||||
(Cflag || Gflag ? 0 : CAPNG_PERMITTED) | |||||
| CAPNG_EFFECTIVE, | |||||
CAP_DAC_OVERRIDE | |||||
); | |||||
capng_apply(CAPNG_SELECT_BOTH); | |||||
#endif /* HAVE_LIBCAP_NG */ | |||||
if (p == NULL) | if (p == NULL) | ||||
error("%s", pcap_geterr(pd)); | error("%s", pcap_geterr(pd)); | ||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); | set_dumper_capsicum_rights(p); | ||||
if (cap_rights_limit(fileno(pcap_dump_file(p)), &rights) < 0 && | |||||
errno != ENOSYS) { | |||||
error("unable to limit dump descriptor"); | |||||
} | |||||
#endif | #endif | ||||
if (Cflag != 0 || Gflag != 0) { | if (Cflag != 0 || Gflag != 0) { | ||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
dumpinfo.WFileName = strdup(basename(WFileName)); | dumpinfo.WFileName = strdup(basename(WFileName)); | ||||
dumpinfo.dirfd = open(dirname(WFileName), | dumpinfo.dirfd = open(dirname(WFileName), | ||||
O_DIRECTORY | O_RDONLY); | O_DIRECTORY | O_RDONLY); | ||||
if (dumpinfo.dirfd < 0) { | if (dumpinfo.dirfd < 0) { | ||||
error("unable to open directory %s", | error("unable to open directory %s", | ||||
dirname(WFileName)); | dirname(WFileName)); | ||||
} | } | ||||
cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, | cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, | ||||
CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); | CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); | ||||
if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 && | if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 && | ||||
errno != ENOSYS) { | errno != ENOSYS) { | ||||
error("unable to limit directory rights"); | error("unable to limit directory rights"); | ||||
} | } | ||||
if (cap_fcntls_limit(dumpinfo.dirfd, CAP_FCNTL_GETFL) < 0 && | |||||
errno != ENOSYS) { | |||||
error("unable to limit dump descriptor fcntls"); | |||||
} | |||||
#else /* !HAVE_CAPSICUM */ | #else /* !HAVE_CAPSICUM */ | ||||
dumpinfo.WFileName = WFileName; | dumpinfo.WFileName = WFileName; | ||||
#endif | #endif | ||||
callback = dump_packet_and_trunc; | callback = dump_packet_and_trunc; | ||||
dumpinfo.pd = pd; | dumpinfo.pd = pd; | ||||
dumpinfo.p = p; | dumpinfo.p = p; | ||||
pcap_userdata = (u_char *)&dumpinfo; | pcap_userdata = (u_char *)&dumpinfo; | ||||
} else { | } else { | ||||
▲ Show 20 Lines • Show All 291 Lines • ▼ Show 20 Lines | fprintf(stderr, | ||||
"compress_savefile failed. Functionality not implemented under your system\n"); | "compress_savefile failed. Functionality not implemented under your system\n"); | ||||
} | } | ||||
#endif /* HAVE_FORK && HAVE_VFORK */ | #endif /* HAVE_FORK && HAVE_VFORK */ | ||||
static void | static void | ||||
dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) | dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) | ||||
{ | { | ||||
struct dump_info *dump_info; | struct dump_info *dump_info; | ||||
#ifdef HAVE_CAPSICUM | |||||
cap_rights_t rights; | |||||
#endif | |||||
++packets_captured; | ++packets_captured; | ||||
++infodelay; | ++infodelay; | ||||
dump_info = (struct dump_info *)user; | dump_info = (struct dump_info *)user; | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | #endif | ||||
* We also don't need numbering if Cflag is not set. | * We also don't need numbering if Cflag is not set. | ||||
*/ | */ | ||||
if (Cflag != 0) | if (Cflag != 0) | ||||
MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, | MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, | ||||
WflagChars); | WflagChars); | ||||
else | else | ||||
MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); | MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); | ||||
#ifdef HAVE_CAP_NG_H | #ifdef HAVE_LIBCAP_NG | ||||
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); | capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); | ||||
capng_apply(CAPNG_EFFECTIVE); | capng_apply(CAPNG_SELECT_BOTH); | ||||
#endif /* HAVE_CAP_NG_H */ | #endif /* HAVE_LIBCAP_NG */ | ||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
fd = openat(dump_info->dirfd, | fd = openat(dump_info->dirfd, | ||||
dump_info->CurrentFileName, | dump_info->CurrentFileName, | ||||
O_CREAT | O_WRONLY | O_TRUNC, 0644); | O_CREAT | O_WRONLY | O_TRUNC, 0644); | ||||
if (fd < 0) { | if (fd < 0) { | ||||
error("unable to open file %s", | error("unable to open file %s", | ||||
dump_info->CurrentFileName); | dump_info->CurrentFileName); | ||||
} | } | ||||
fp = fdopen(fd, "w"); | fp = fdopen(fd, "w"); | ||||
if (fp == NULL) { | if (fp == NULL) { | ||||
error("unable to fdopen file %s", | error("unable to fdopen file %s", | ||||
dump_info->CurrentFileName); | dump_info->CurrentFileName); | ||||
} | } | ||||
dump_info->p = pcap_dump_fopen(dump_info->pd, fp); | dump_info->p = pcap_dump_fopen(dump_info->pd, fp); | ||||
#else /* !HAVE_CAPSICUM */ | #else /* !HAVE_CAPSICUM */ | ||||
dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); | dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); | ||||
#endif | #endif | ||||
#ifdef HAVE_CAP_NG_H | #ifdef HAVE_LIBCAP_NG | ||||
capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); | capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); | ||||
capng_apply(CAPNG_EFFECTIVE); | capng_apply(CAPNG_SELECT_BOTH); | ||||
#endif /* HAVE_CAP_NG_H */ | #endif /* HAVE_LIBCAP_NG */ | ||||
if (dump_info->p == NULL) | if (dump_info->p == NULL) | ||||
error("%s", pcap_geterr(pd)); | error("%s", pcap_geterr(pd)); | ||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); | set_dumper_capsicum_rights(dump_info->p); | ||||
if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)), | |||||
&rights) < 0 && errno != ENOSYS) { | |||||
error("unable to limit dump descriptor"); | |||||
} | |||||
#endif | #endif | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* XXX - this won't prevent capture files from getting | * XXX - this won't prevent capture files from getting | ||||
* larger than Cflag - the last packet written to the | * larger than Cflag - the last packet written to the | ||||
* file could put it over Cflag. | * file could put it over Cflag. | ||||
*/ | */ | ||||
if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) { | if (Cflag != 0) { | ||||
long size = pcap_dump_ftell(dump_info->p); | |||||
if (size == -1) | |||||
error("ftell fails on output file"); | |||||
if (size > Cflag) { | |||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
FILE *fp; | FILE *fp; | ||||
int fd; | int fd; | ||||
#endif | #endif | ||||
/* | /* | ||||
* Close the current file and open a new one. | * Close the current file and open a new one. | ||||
*/ | */ | ||||
pcap_dump_close(dump_info->p); | pcap_dump_close(dump_info->p); | ||||
/* | /* | ||||
* Compress the file we just closed, if the user asked for it | * Compress the file we just closed, if the user | ||||
* asked for it. | |||||
*/ | */ | ||||
if (zflag != NULL) | if (zflag != NULL) | ||||
compress_savefile(dump_info->CurrentFileName); | compress_savefile(dump_info->CurrentFileName); | ||||
Cflag_count++; | Cflag_count++; | ||||
if (Wflag > 0) { | if (Wflag > 0) { | ||||
if (Cflag_count >= Wflag) | if (Cflag_count >= Wflag) | ||||
Cflag_count = 0; | Cflag_count = 0; | ||||
} | } | ||||
if (dump_info->CurrentFileName != NULL) | if (dump_info->CurrentFileName != NULL) | ||||
free(dump_info->CurrentFileName); | free(dump_info->CurrentFileName); | ||||
dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); | dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); | ||||
if (dump_info->CurrentFileName == NULL) | if (dump_info->CurrentFileName == NULL) | ||||
error("dump_packet_and_trunc: malloc"); | error("dump_packet_and_trunc: malloc"); | ||||
MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); | 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 | #ifdef HAVE_CAPSICUM | ||||
fd = openat(dump_info->dirfd, dump_info->CurrentFileName, | fd = openat(dump_info->dirfd, dump_info->CurrentFileName, | ||||
O_CREAT | O_WRONLY | O_TRUNC, 0644); | O_CREAT | O_WRONLY | O_TRUNC, 0644); | ||||
if (fd < 0) { | if (fd < 0) { | ||||
error("unable to open file %s", | error("unable to open file %s", | ||||
dump_info->CurrentFileName); | dump_info->CurrentFileName); | ||||
} | } | ||||
fp = fdopen(fd, "w"); | fp = fdopen(fd, "w"); | ||||
if (fp == NULL) { | if (fp == NULL) { | ||||
error("unable to fdopen file %s", | error("unable to fdopen file %s", | ||||
dump_info->CurrentFileName); | dump_info->CurrentFileName); | ||||
} | } | ||||
dump_info->p = pcap_dump_fopen(dump_info->pd, fp); | dump_info->p = pcap_dump_fopen(dump_info->pd, fp); | ||||
#else /* !HAVE_CAPSICUM */ | #else /* !HAVE_CAPSICUM */ | ||||
dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); | dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); | ||||
#endif | #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->p == NULL) | if (dump_info->p == NULL) | ||||
error("%s", pcap_geterr(pd)); | error("%s", pcap_geterr(pd)); | ||||
#ifdef HAVE_CAPSICUM | #ifdef HAVE_CAPSICUM | ||||
cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); | set_dumper_capsicum_rights(dump_info->p); | ||||
if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)), | |||||
&rights) < 0 && errno != ENOSYS) { | |||||
error("unable to limit dump descriptor"); | |||||
} | |||||
#endif | #endif | ||||
} | } | ||||
} | |||||
pcap_dump((u_char *)dump_info->p, h, sp); | pcap_dump((u_char *)dump_info->p, h, sp); | ||||
#ifdef HAVE_PCAP_DUMP_FLUSH | #ifdef HAVE_PCAP_DUMP_FLUSH | ||||
if (Uflag) | if (Uflag) | ||||
pcap_dump_flush(dump_info->p); | pcap_dump_flush(dump_info->p); | ||||
#endif | #endif | ||||
--infodelay; | --infodelay; | ||||
Show All 36 Lines | print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) | ||||
if(ndo->ndo_packet_number) | if(ndo->ndo_packet_number) | ||||
ND_PRINT((ndo, "%5u ", packets_captured)); | ND_PRINT((ndo, "%5u ", packets_captured)); | ||||
ts_print(ndo, &h->ts); | ts_print(ndo, &h->ts); | ||||
/* | /* | ||||
* Some printers want to check that they're not walking off the | * Some printers want to check that they're not walking off the | ||||
* end of the packet. | * end of the packet. | ||||
* Rather than pass it all the way down, we set this global. | * Rather than pass it all the way down, we set this member | ||||
* of the netdissect_options structure. | |||||
*/ | */ | ||||
ndo->ndo_snapend = sp + h->caplen; | ndo->ndo_snapend = sp + h->caplen; | ||||
if(print_info->ndo_type) { | if(print_info->ndo_type) { | ||||
hdrlen = (*print_info->p.ndo_printer)(print_info->ndo, h, sp); | hdrlen = (*print_info->p.ndo_printer)(print_info->ndo, h, sp); | ||||
} else { | } else { | ||||
hdrlen = (*print_info->p.printer)(h, sp); | hdrlen = (*print_info->p.printer)(h, sp); | ||||
} | } | ||||
/* | |||||
* Restore the original snapend, as a printer might have | |||||
* changed it. | |||||
*/ | |||||
ndo->ndo_snapend = sp + h->caplen; | |||||
if (ndo->ndo_Xflag) { | if (ndo->ndo_Xflag) { | ||||
/* | /* | ||||
* Print the raw packet data in hex and ASCII. | * Print the raw packet data in hex and ASCII. | ||||
*/ | */ | ||||
if (ndo->ndo_Xflag > 1) { | if (ndo->ndo_Xflag > 1) { | ||||
/* | /* | ||||
* Include the link-layer header. | * Include the link-layer header. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | |||||
#endif | #endif | ||||
/* | /* | ||||
* By default, print the specified data out in hex and ASCII. | * By default, print the specified data out in hex and ASCII. | ||||
*/ | */ | ||||
static void | static void | ||||
ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length) | ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length) | ||||
{ | { | ||||
hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and identation string */ | hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */ | ||||
} | } | ||||
void | void | ||||
default_print(const u_char *bp, u_int length) | default_print(const u_char *bp, u_int length) | ||||
{ | { | ||||
ndo_default_print(gndo, bp, length); | ndo_default_print(gndo, bp, length); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | |||||
"\t\t[ -Q in|out|inout ]\n"); | "\t\t[ -Q in|out|inout ]\n"); | ||||
#endif | #endif | ||||
(void)fprintf(stderr, | (void)fprintf(stderr, | ||||
"\t\t[ -r file ] [ -s snaplen ] "); | "\t\t[ -r file ] [ -s snaplen ] "); | ||||
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION | #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION | ||||
(void)fprintf(stderr, "[ --time-stamp-precision precision ]\n"); | (void)fprintf(stderr, "[ --time-stamp-precision precision ]\n"); | ||||
(void)fprintf(stderr, | (void)fprintf(stderr, | ||||
"\t\t"); | "\t\t"); | ||||
#endif | |||||
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE | |||||
(void)fprintf(stderr, "[ --immediate-mode ] "); | |||||
#endif | #endif | ||||
(void)fprintf(stderr, "[ -T type ] [ --version ] [ -V file ]\n"); | (void)fprintf(stderr, "[ -T type ] [ --version ] [ -V file ]\n"); | ||||
(void)fprintf(stderr, | (void)fprintf(stderr, | ||||
"\t\t[ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z command ]\n"); | "\t\t[ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z command ]\n"); | ||||
(void)fprintf(stderr, | (void)fprintf(stderr, | ||||
"\t\t[ -Z user ] [ expression ]\n"); | "\t\t[ -Z user ] [ expression ]\n"); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 43 Lines • Show Last 20 Lines |