#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().
+ * Some older versions of 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
#include <fcntl.h>
#endif
-#ifdef USE_LIBSMI
-#include <smi.h>
-#endif
-
#ifdef HAVE_LIBCRYPTO
#include <openssl/crypto.h>
#endif
#include <sys/ioccom.h>
#include <net/bpf.h>
#include <libgen.h>
+#ifdef HAVE_CASPER
+#include <libcasper.h>
+#include <casper/cap_dns.h>
+#include <sys/nv.h>
+#endif /* HAVE_CASPER */
#endif /* HAVE_CAPSICUM */
#include <pcap.h>
#include <signal.h>
#endif /* HAVE_CAP_NG_H */
#endif /* HAVE_LIBCAP_NG */
+#ifdef __FreeBSD__
+#include <sys/sysctl.h>
+#endif /* __FreeBSD__ */
+
#include "netdissect.h"
#include "interface.h"
#include "addrtoname.h"
#define SIGNAL_REQ_INFO SIGUSR1
#endif
-static int Cflag; /* rotate dump files after this many bytes */
+static int Bflag; /* buffer size */
+static long Cflag; /* rotate dump files after this many bytes */
static int Cflag_count; /* Keep track of which file number we're writing */
static int Dflag; /* list available devices and exit */
/*
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
static int Jflag; /* list available time stamp types */
#endif
+static int jflag = -1; /* packet time stamp source */
+static int pflag; /* don't go promiscuous */
#ifdef HAVE_PCAP_SETDIRECTION
-int Qflag = -1; /* restrict captured packet by send/receive direction */
+static int Qflag = -1; /* restrict captured packet by send/receive direction */
#endif
static int Uflag; /* "unbuffered" output of dump files */
static int Wflag; /* recycle output files after this number of files */
static int WflagChars;
static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */
+static int immediate_mode;
static int infodelay;
static int infoprint;
char *program_name;
+#ifdef HAVE_CASPER
+cap_channel_t *capdns;
+#endif
+
/* Forwards */
-static void error(const char *, ...)
- __attribute__((noreturn))
-#ifdef __ATTRIBUTE___FORMAT_OK
- __attribute__((format (printf, 1, 2)))
-#endif /* __ATTRIBUTE___FORMAT_OK */
- ;
-static void warning(const char *, ...)
-#ifdef __ATTRIBUTE___FORMAT_OK
- __attribute__((format (printf, 1, 2)))
-#endif /* __ATTRIBUTE___FORMAT_OK */
- ;
-static void exit_tcpdump(int) __attribute__((noreturn));
+static NORETURN void error(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2);
+static void warning(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2);
+static NORETURN void exit_tcpdump(int);
static RETSIGTYPE cleanup(int);
static RETSIGTYPE child_cleanup(int);
static void print_version(void);
static void print_usage(void);
-static void show_tstamp_types_and_exit(const char *device) __attribute__((noreturn));
-static void show_dlts_and_exit(const char *device) __attribute__((noreturn));
+static NORETURN void show_tstamp_types_and_exit(pcap_t *, const char *device);
+static NORETURN void show_dlts_and_exit(pcap_t *, const char *device);
+#ifdef HAVE_PCAP_FINDALLDEVS
+static NORETURN void show_devices_and_exit(void);
+#endif
static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *);
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" },
{ PCAP_IF_LOOPBACK, "Loopback" },
{ 0, NULL }
};
+#endif
static pcap_t *pd;
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
static void
-show_tstamp_types_and_exit(const char *device)
+show_tstamp_types_and_exit(pcap_t *pc, const char *device)
{
int n_tstamp_types;
int *tstamp_types = 0;
const char *tstamp_type_name;
int i;
- n_tstamp_types = pcap_list_tstamp_types(pd, &tstamp_types);
+ n_tstamp_types = pcap_list_tstamp_types(pc, &tstamp_types);
if (n_tstamp_types < 0)
- error("%s", pcap_geterr(pd));
+ error("%s", pcap_geterr(pc));
if (n_tstamp_types == 0) {
fprintf(stderr, "Time stamp type cannot be set for %s\n",
#endif
static void
-show_dlts_and_exit(const char *device)
+show_dlts_and_exit(pcap_t *pc, const char *device)
{
int n_dlts, i;
int *dlts = 0;
const char *dlt_name;
- n_dlts = pcap_list_datalinks(pd, &dlts);
+ n_dlts = pcap_list_datalinks(pc, &dlts);
if (n_dlts < 0)
- error("%s", pcap_geterr(pd));
+ error("%s", pcap_geterr(pc));
else if (n_dlts == 0 || !dlts)
error("No data link types.");
* OS X tcpdump uses -g to force non--v output for IP to be on one
* line, making it more "g"repable;
*
- * OS X tcpdump uses -k tospecify that packet comments in pcap-ng files
+ * OS X tcpdump uses -k to specify that packet comments in pcap-ng files
* should be printed;
*
* OpenBSD tcpdump uses -o to indicate that OS fingerprinting should be done
exit_tcpdump(1);
}
#ifdef HAVE_LIBCAP_NG
- /* We don't need CAP_SETUID and CAP_SETGID any more. */
+ /* We don't need CAP_SETUID, CAP_SETGID and CAP_SYS_CHROOT any more. */
capng_updatev(
CAPNG_DROP,
CAPNG_EFFECTIVE | CAPNG_PERMITTED,
CAP_SETUID,
CAP_SETGID,
+ CAP_SYS_CHROOT,
-1);
capng_apply(CAPNG_SELECT_BOTH);
#endif /* HAVE_LIBCAP_NG */
return ret;
}
+#ifdef HAVE_CASPER
+static cap_channel_t *
+capdns_setup(void)
+{
+ cap_channel_t *capcas, *capdnsloc;
+ const char *types[1];
+ int families[2];
+
+ capcas = cap_init();
+ if (capcas == NULL)
+ error("unable to create casper process");
+ capdnsloc = cap_service_open(capcas, "system.dns");
+ /* Casper capability no longer needed. */
+ cap_close(capcas);
+ if (capdnsloc == NULL)
+ error("unable to open system.dns service");
+ /* Limit system.dns to reverse DNS lookups. */
+ types[0] = "ADDR";
+ if (cap_dns_type_limit(capdnsloc, types, 1) < 0)
+ error("unable to limit access to system.dns service");
+ families[0] = AF_INET;
+ families[1] = AF_INET6;
+ if (cap_dns_family_limit(capdnsloc, families, 2) < 0)
+ error("unable to limit access to system.dns service");
+
+ return (capdnsloc);
+}
+#endif /* HAVE_CASPER */
+
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
static int
tstamp_precision_from_string(const char *precision)
char *src, *dst;
p = argv;
- if (*p == 0)
+ if (*p == NULL)
return 0;
while (*p)
return (cp);
}
+#ifdef HAVE_PCAP_FINDALLDEVS
+static long
+parse_interface_number(const char *device)
+{
+ long devnum;
+ char *end;
+
+ devnum = strtol(device, &end, 10);
+ if (device != end && *end == '\0') {
+ /*
+ * It's all-numeric, but is it a valid number?
+ */
+ if (devnum <= 0) {
+ /*
+ * No, it's not an ordinal.
+ */
+ error("Invalid adapter index");
+ }
+ return (devnum);
+ } else {
+ /*
+ * It's not all-numeric; return -1, so our caller
+ * knows that.
+ */
+ return (-1);
+ }
+}
+
+static char *
+find_interface_by_number(long devnum)
+{
+ pcap_if_t *dev, *devlist;
+ long i;
+ char ebuf[PCAP_ERRBUF_SIZE];
+ char *device;
+
+ if (pcap_findalldevs(&devlist, ebuf) < 0)
+ error("%s", ebuf);
+ /*
+ * Look for the devnum-th entry in the list of devices (1-based).
+ */
+ for (i = 0, dev = devlist; i < devnum-1 && dev != NULL;
+ i++, dev = dev->next)
+ ;
+ if (dev == NULL)
+ error("Invalid adapter index");
+ device = strdup(dev->name);
+ pcap_freealldevs(devlist);
+ return (device);
+}
+#endif
+
+static pcap_t *
+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_CREATE
+ pc = pcap_create(device, 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);
+ }
+#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
+ if (Jflag)
+ show_tstamp_types_and_exit(pc, device);
+#endif
+#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
+ status = pcap_set_tstamp_precision(pc, ndo->ndo_tstamp_precision);
+ if (status != 0)
+ error("%s: Can't set %ssecond time stamp precision: %s",
+ device,
+ tstamp_precision_to_string(ndo->ndo_tstamp_precision),
+ pcap_statustostr(status));
+#endif
+
+#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
+ if (immediate_mode) {
+ status = pcap_set_immediate_mode(pc, 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?
+ */
+ if (pcap_can_set_rfmon(pc) == 1)
+ supports_monitor_mode = 1;
+ else
+ supports_monitor_mode = 0;
+ if (ndo->ndo_snaplen != 0) {
+ /*
+ * A snapshot length was explicitly specified;
+ * use it.
+ */
+ status = pcap_set_snaplen(pc, ndo->ndo_snaplen);
+ if (status != 0)
+ error("%s: Can't set snapshot length: %s",
+ device, pcap_statustostr(status));
+ }
+ status = pcap_set_promisc(pc, !pflag);
+ if (status != 0)
+ error("%s: Can't set promiscuous mode: %s",
+ device, pcap_statustostr(status));
+ if (Iflag) {
+ status = pcap_set_rfmon(pc, 1);
+ if (status != 0)
+ error("%s: Can't set monitor mode: %s",
+ device, pcap_statustostr(status));
+ }
+ status = pcap_set_timeout(pc, 1000);
+ if (status != 0)
+ error("%s: pcap_set_timeout failed: %s",
+ device, pcap_statustostr(status));
+ if (Bflag != 0) {
+ status = pcap_set_buffer_size(pc, Bflag);
+ if (status != 0)
+ error("%s: Can't set buffer size: %s",
+ device, pcap_statustostr(status));
+ }
+#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
+ if (jflag != -1) {
+ status = pcap_set_tstamp_type(pc, jflag);
+ if (status < 0)
+ error("%s: Can't set time stamp type: %s",
+ device, pcap_statustostr(status));
+ }
+#endif
+ status = pcap_activate(pc);
+ if (status < 0) {
+ /*
+ * pcap_activate() failed.
+ */
+ cp = pcap_geterr(pc);
+ if (status == PCAP_ERROR)
+ error("%s", cp);
+ else if (status == PCAP_ERROR_NO_SUCH_DEVICE) {
+ /*
+ * Return an error for our caller to handle.
+ */
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s\n(%s)",
+ device, pcap_statustostr(status), cp);
+ pcap_close(pc);
+ return (NULL);
+ } else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0')
+ error("%s: %s\n(%s)", device,
+ pcap_statustostr(status), cp);
+#ifdef __FreeBSD__
+ else if (status == PCAP_ERROR_RFMON_NOTSUP &&
+ strncmp(device, "wlan", 4) == 0) {
+ char parent[8], newdev[8];
+ char sysctl[32];
+ size_t s = sizeof(parent);
+
+ snprintf(sysctl, sizeof(sysctl),
+ "net.wlan.%d.%%parent", atoi(device + 4));
+ sysctlbyname(sysctl, parent, &s, NULL, 0);
+ strlcpy(newdev, device, sizeof(newdev));
+ /* Suggest a new wlan device. */
+ /* FIXME: incrementing the index this way is not going to work well
+ * when the index is 9 or greater but the only consequence in this
+ * 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"
+ "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
+ else
+ error("%s: %s", device,
+ pcap_statustostr(status));
+ } else if (status > 0) {
+ /*
+ * pcap_activate() succeeded, but it's warning us
+ * of a problem it had.
+ */
+ cp = pcap_geterr(pc);
+ if (status == PCAP_WARNING)
+ warning("%s", cp);
+ else if (status == PCAP_WARNING_PROMISC_NOTSUP &&
+ *cp != '\0')
+ warning("%s: %s\n(%s)", device,
+ pcap_statustostr(status), cp);
+ else
+ 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 = 262144;
+ pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, 1000, 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);
+}
+
int
main(int argc, char **argv)
{
char *ret = NULL;
char *end;
#ifdef HAVE_PCAP_FINDALLDEVS
- pcap_if_t *dev, *devlist;
- int devnum;
+ pcap_if_t *devlist;
+ long devnum;
#endif
int status;
FILE *VFile;
cap_rights_t rights;
int cansandbox;
#endif /* HAVE_CAPSICUM */
- int Bflag = 0; /* buffer size */
- int jflag = -1; /* packet time stamp source */
int Oflag = 1; /* run filter code optimizer */
- int pflag = 0; /* don't go promiscuous */
int yflag_dlt = -1;
const char *yflag_dlt_name = NULL;
netdissect_options Ndo;
netdissect_options *ndo = &Ndo;
- int immediate_mode = 0;
/*
* Initialize the netdissect code.
memset(ndo, 0, sizeof(*ndo));
ndo_set_function_pointers(ndo);
- ndo->ndo_snaplen = DEFAULT_SNAPLEN;
cnt = -1;
device = NULL;
break;
case 'i':
- if (optarg[0] == '0' && optarg[1] == 0)
- error("Invalid adapter index");
-
-#ifdef HAVE_PCAP_FINDALLDEVS
- /*
- * If the argument is a number, treat it as
- * an index into the list of adapters, as
- * printed by "tcpdump -D".
- *
- * This should be OK on UNIX systems, as interfaces
- * shouldn't have names that begin with digits.
- * It can be useful on Windows, where more than
- * one interface can have the same name.
- */
- devnum = strtol(optarg, &end, 10);
- if (optarg != end && *end == '\0') {
- if (devnum < 0)
- error("Invalid adapter index");
-
- if (pcap_findalldevs(&devlist, ebuf) < 0)
- error("%s", ebuf);
- /*
- * Look for the devnum-th entry in the
- * list of devices (1-based).
- */
- for (i = 0, dev = devlist;
- i < devnum-1 && dev != NULL;
- i++, dev = dev->next)
- ;
- if (dev == NULL)
- error("Invalid adapter index");
- device = strdup(dev->name);
- pcap_freealldevs(devlist);
- break;
- }
-#endif /* HAVE_PCAP_FINDALLDEVS */
device = optarg;
break;
break;
case 'm':
-#ifdef USE_LIBSMI
- if (smiLoadModule(optarg) == 0) {
- error("could not load MIB module %s", optarg);
+ if (nd_have_smi_support()) {
+ if (nd_load_smi_module(optarg, ebuf, sizeof ebuf) == -1)
+ error("%s", ebuf);
+ } else {
+ (void)fprintf(stderr, "%s: ignoring option `-m %s' ",
+ program_name, optarg);
+ (void)fprintf(stderr, "(no libsmi support)\n");
}
- ndo->ndo_mflag = 1;
-#else
- (void)fprintf(stderr, "%s: ignoring option `-m %s' ",
- program_name, optarg);
- (void)fprintf(stderr, "(no libsmi support)\n");
-#endif
break;
case 'M':
if (optarg == end || *end != '\0'
|| ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN)
error("invalid snaplen %s", optarg);
- else if (ndo->ndo_snaplen == 0)
- ndo->ndo_snaplen = MAXIMUM_SNAPLEN;
break;
case 'S':
* We're doing a live capture.
*/
if (device == NULL) {
+ /*
+ * No interface was specified. Pick one.
+ */
#ifdef HAVE_PCAP_FINDALLDEVS
+ /*
+ * Find the list of interfaces, and pick
+ * the first interface.
+ */
if (pcap_findalldevs(&devlist, ebuf) >= 0 &&
devlist != NULL) {
device = strdup(devlist->name);
pcap_freealldevs(devlist);
}
#else /* HAVE_PCAP_FINDALLDEVS */
+ /*
+ * Use whatever interface pcap_lookupdev()
+ * chooses.
+ */
device = pcap_lookupdev(ebuf);
#endif
if (device == NULL)
error("%s", ebuf);
}
-#ifdef _WIN32
- /*
- * Print a message to the standard error on Windows.
- * XXX - why do it here, with a different message?
- */
- if(strlen(device) == 1) /* we assume that an ASCII string is always longer than 1 char */
- { /* a Unicode string has a \0 as second byte (so strlen() is 1) */
- fprintf(stderr, "%s: listening on %ws\n", program_name, device);
- }
- else
- {
- fprintf(stderr, "%s: listening on %s\n", program_name, device);
- }
- fflush(stderr);
-#endif /* _WIN32 */
-#ifdef HAVE_PCAP_CREATE
- pd = pcap_create(device, ebuf);
- if (pd == NULL)
- error("%s", ebuf);
-#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
- if (Jflag)
- show_tstamp_types_and_exit(device);
-#endif
-#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
- status = pcap_set_tstamp_precision(pd, ndo->ndo_tstamp_precision);
- if (status != 0)
- error("%s: Can't set %ssecond time stamp precision: %s",
- device,
- tstamp_precision_to_string(ndo->ndo_tstamp_precision),
- pcap_statustostr(status));
-#endif
-
-#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
- if (immediate_mode) {
- 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?
+ * Try to open the interface with the specified name.
*/
- if (pcap_can_set_rfmon(pd) == 1)
- supports_monitor_mode = 1;
- else
- supports_monitor_mode = 0;
- status = pcap_set_snaplen(pd, ndo->ndo_snaplen);
- if (status != 0)
- error("%s: Can't set snapshot length: %s",
- device, pcap_statustostr(status));
- status = pcap_set_promisc(pd, !pflag);
- if (status != 0)
- error("%s: Can't set promiscuous mode: %s",
- device, pcap_statustostr(status));
- if (Iflag) {
- status = pcap_set_rfmon(pd, 1);
- if (status != 0)
- error("%s: Can't set monitor mode: %s",
- device, pcap_statustostr(status));
- }
- status = pcap_set_timeout(pd, 1000);
- if (status != 0)
- error("%s: pcap_set_timeout failed: %s",
- device, pcap_statustostr(status));
- if (Bflag != 0) {
- status = pcap_set_buffer_size(pd, Bflag);
- if (status != 0)
- error("%s: Can't set buffer size: %s",
- device, pcap_statustostr(status));
- }
-#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
- if (jflag != -1) {
- status = pcap_set_tstamp_type(pd, jflag);
- if (status < 0)
- error("%s: Can't set time stamp type: %s",
- device, pcap_statustostr(status));
- }
-#endif
- status = pcap_activate(pd);
- if (status < 0) {
+ pd = open_interface(device, ndo, ebuf);
+ if (pd == NULL) {
/*
- * pcap_activate() failed.
+ * That failed. If we can get a list of
+ * interfaces, and the interface name
+ * is purely numeric, try to use it as
+ * a 1-based index in the list of
+ * interfaces.
*/
- cp = pcap_geterr(pd);
- if (status == PCAP_ERROR)
- error("%s", cp);
- else if ((status == PCAP_ERROR_NO_SUCH_DEVICE ||
- status == PCAP_ERROR_PERM_DENIED) &&
- *cp != '\0')
- error("%s: %s\n(%s)", device,
- pcap_statustostr(status), cp);
- else
- error("%s: %s", device,
- pcap_statustostr(status));
- } else if (status > 0) {
+#ifdef HAVE_PCAP_FINDALLDEVS
+ devnum = parse_interface_number(device);
+ if (devnum == -1) {
+ /*
+ * It's not a number; just report
+ * the open error and fail.
+ */
+ error("%s", ebuf);
+ }
+
/*
- * pcap_activate() succeeded, but it's warning us
- * of a problem it had.
+ * OK, it's a number; try to find the
+ * interface with that index, and try
+ * to open it.
+ *
+ * find_interface_by_number() exits if it
+ * couldn't be found.
+ */
+ device = find_interface_by_number(devnum);
+ 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.
*/
- cp = pcap_geterr(pd);
- if (status == PCAP_WARNING)
- warning("%s", cp);
- else if (status == PCAP_WARNING_PROMISC_NOTSUP &&
- *cp != '\0')
- warning("%s: %s\n(%s)", device,
- pcap_statustostr(status), cp);
- else
- warning("%s: %s", device,
- pcap_statustostr(status));
- }
-#ifdef HAVE_PCAP_SETDIRECTION
- if (Qflag != -1) {
- status = pcap_setdirection(pd, Qflag);
- if (status != 0)
- error("%s: pcap_setdirection() failed: %s",
- device, pcap_geterr(pd));
- }
-#endif /* HAVE_PCAP_SETDIRECTION */
-#else
- *ebuf = '\0';
- pd = pcap_open_live(device, ndo->ndo_snaplen, !pflag, 1000,
- ebuf);
- if (pd == NULL)
error("%s", ebuf);
- else if (*ebuf)
- warning("%s", ebuf);
-#endif /* HAVE_PCAP_CREATE */
+#endif /* HAVE_PCAP_FINDALLDEVS */
+ }
+
/*
- * Let user own process after socket has been opened.
+ * Let user own process after capture device has
+ * been opened.
*/
#ifndef _WIN32
if (setgid(getgid()) != 0 || setuid(getuid()) != 0)
}
#endif /* !defined(HAVE_PCAP_CREATE) && defined(_WIN32) */
if (Lflag)
- show_dlts_and_exit(device);
+ show_dlts_and_exit(pd, device);
if (yflag_dlt >= 0) {
#ifdef HAVE_PCAP_SET_DATALINK
if (pcap_set_datalink(pd, yflag_dlt) < 0)
}
i = pcap_snapshot(pd);
if (ndo->ndo_snaplen < i) {
- warning("snaplen raised from %d to %d", ndo->ndo_snaplen, i);
+ if (ndo->ndo_snaplen != 0)
+ warning("snaplen raised from %d to %d", ndo->ndo_snaplen, i);
+ ndo->ndo_snaplen = i;
+ } else if (ndo->ndo_snaplen > i) {
+ warning("snaplen lowered from %d to %d", ndo->ndo_snaplen, i);
ndo->ndo_snaplen = i;
}
if(ndo->ndo_fflag != 0) {
pcap_freecode(&fcode);
exit_tcpdump(0);
}
+
+#ifdef HAVE_CASPER
+ if (!ndo->ndo_nflag)
+ capdns = capdns_setup();
+#endif /* HAVE_CASPER */
+
init_print(ndo, localnet, netmask, timezone_offset);
#ifndef _WIN32
CAP_SETGID,
-1);
}
+ if (chroot_dir) {
+ capng_update(
+ CAPNG_ADD,
+ CAPNG_PERMITTED | CAPNG_EFFECTIVE,
+ CAP_SYS_CHROOT
+ );
+ }
if (WFileName) {
capng_update(
if (RFileName == NULL && VFileName == NULL) {
static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
- cap_rights_init(&rights, CAP_IOCTL, CAP_READ);
+ /*
+ * The various libpcap devices use a combination of
+ * read (bpf), ioctl (bpf, netmap), poll (netmap)
+ * so we add the relevant access rights.
+ */
+ cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_EVENT);
if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 &&
errno != ENOSYS) {
error("unable to limit pcap descriptor");
#endif
}
-#ifndef _WIN32
if (RFileName == NULL) {
/*
* Live capture (if -V was specified, we set RFileName
}
(void)fflush(stderr);
}
-#endif /* _WIN32 */
#ifdef HAVE_CAPSICUM
- cansandbox = (ndo->ndo_nflag && VFileName == NULL && zflag == NULL);
+ cansandbox = (VFileName == NULL && zflag == NULL);
+#ifdef HAVE_CASPER
+ cansandbox = (cansandbox && (ndo->ndo_nflag || capdns != NULL));
+#else
+ cansandbox = (cansandbox && ndo->ndo_nflag);
+#endif /* HAVE_CASPER */
if (cansandbox && cap_enter() < 0 && errno != ENOSYS)
error("unable to enter the capability mode");
#endif /* HAVE_CAPSICUM */
if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) {
(void)fprintf(stderr, "Maximum file limit reached: %d\n",
Wflag);
+ info(1);
exit_tcpdump(0);
/* NOTREACHED */
}
static char pcap_version[] = "unknown";
#endif /* defined(_WIN32) || defined(HAVE_PCAP_VERSION) */
#endif /* HAVE_PCAP_LIB_VERSION */
+ const char *smi_version_string;
#ifdef HAVE_PCAP_LIB_VERSION
#ifdef _WIN32
(void)fprintf (stderr, "%s\n", SSLeay_version(SSLEAY_VERSION));
#endif
-#ifdef USE_LIBSMI
- (void)fprintf (stderr, "SMI-library: %s\n", smi_version_string);
-#endif
+ smi_version_string = nd_smi_version_string();
+ if (smi_version_string != NULL)
+ (void)fprintf (stderr, "SMI-library: %s\n", smi_version_string);
+
+#if defined(__SANITIZE_ADDRESS__)
+ (void)fprintf (stderr, "Compiled with AddressSanitizer/GCC.\n");
+#elif defined(__has_feature)
+# if __has_feature(address_sanitizer)
+ (void)fprintf (stderr, "Compiled with AddressSanitizer/CLang.\n");
+# endif
+#endif /* __SANITIZE_ADDRESS__ or __has_feature */
}
USES_APPLE_RST