X-Git-Url: https://git.tcpdump.org/libpcap/blobdiff_plain/ed88379764e5bfa754df224d6293793c0802654b..4e145de1143f597ef8277b51c5524af1e994f277:/tests/valgrindtest.c diff --git a/tests/valgrindtest.c b/tests/valgrindtest.c index 1cb36762..6bb6d4f6 100644 --- a/tests/valgrindtest.c +++ b/tests/valgrindtest.c @@ -19,19 +19,40 @@ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ +/* + * This doesn't actually test libpcap itself; it tests whether + * valgrind properly handles the APIs libpcap uses. If it doesn't, + * we end up getting patches submitted to "fix" references that + * valgrind claims are being made to uninitialized data, when, in + * fact, the OS isn't making any such references - or we get + * valgrind *not* detecting *actual* incorrect references. + * + * Both BPF and Linux socket filters aren't handled correctly + * by some versions of valgrind. See valgrind bug 318203 for + * Linux: + * + * https://bugs.kde.org/show_bug.cgi?id=318203 + * + * and valgrind bug 312989 for OS X: + * + * https://bugs.kde.org/show_bug.cgi?id=312989 + * + * The fixes for both of those are checked into the official valgrind + * repository. + * + * The unofficial FreeBSD port has similar issues to the official OS X + * port, for similar reasons. + */ #ifndef lint static const char copyright[] _U_ = "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ The Regents of the University of California. All rights reserved.\n"; -static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/filtertest.c,v 1.2 2005-08-08 17:50:13 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H -#include "config.h" +#include #endif -#include #include #include #include @@ -43,22 +64,47 @@ static const char rcsid[] _U_ = #include #include -#ifndef HAVE___ATTRIBUTE__ -#define __attribute__(x) +#include "pcap/funcattrs.h" + +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +/* BSD-flavored OS - use BPF */ +#define USE_BPF +#elif defined(linux) +/* Linux - use socket filters */ +#define USE_SOCKET_FILTERS +#else +#error "Unknown platform or platform that doesn't support Valgrind" #endif +#if defined(USE_BPF) + +#include +#include + +/* + * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the + * native OS version, as we're going to be doing our own ioctls to + * make sure that, in the uninitialized-data tests, the filters aren't + * checked by libpcap before being handed to BPF. + */ +#define PCAP_DONT_INCLUDE_PCAP_BPF_H + +#elif defined(USE_SOCKET_FILTERS) + +#include +#include +#include + +#endif + +#include + static char *program_name; /* Forwards */ -static void usage(void) __attribute__((noreturn)); -static void error(const char *, ...) - __attribute__((noreturn, format (printf, 1, 2))); -static void warning(const char *, ...) - __attribute__((format (printf, 1, 2))); - -extern int optind; -extern int opterr; -extern char *optarg; +static void PCAP_NORETURN usage(void); +static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2); +static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2); /* * On Windows, we need to open the file in binary mode, so that @@ -186,16 +232,24 @@ main(int argc, char **argv) char ebuf[PCAP_ERRBUF_SIZE]; char *infile; char *cmdbuf; + pcap_if_t *devlist; pcap_t *pd; int status = 0; - struct bpf_program fcode; + int pcap_fd; +#if defined(USE_BPF) + struct bpf_program bad_fcode; struct bpf_insn uninitialized[INSN_COUNT]; +#elif defined(USE_SOCKET_FILTERS) + struct sock_fprog bad_fcode; + struct sock_filter uninitialized[INSN_COUNT]; +#endif + struct bpf_program fcode; device = NULL; dorfmon = 0; useactivate = 0; infile = NULL; - + if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else @@ -233,11 +287,12 @@ main(int argc, char **argv) * No interface specified; get whatever pcap_lookupdev() * finds. */ - device = pcap_lookupdev(ebuf); - if (device == NULL) { - error("couldn't find interface to use: %s", - ebuf); - } + if (pcap_findalldevs(&devlist, ebuf) == -1) + error("%s", ebuf); + if (devlist == NULL) + error("no interfaces available for capture"); + device = strdup(devlist->name); + pcap_freealldevs(devlist); } if (infile != NULL) { @@ -308,6 +363,8 @@ main(int argc, char **argv) warning("%s", ebuf); } + pcap_fd = pcap_fileno(pd); + /* * Try setting a filter with an uninitialized bpf_program * structure. This should cause valgrind to report a @@ -316,7 +373,12 @@ main(int argc, char **argv) * We don't check for errors, because it could get an * error due to a bad pointer or count. */ - pcap_setfilter(pd, &fcode); +#if defined(USE_BPF) + ioctl(pcap_fd, BIOCSETF, &bad_fcode); +#elif defined(USE_SOCKET_FILTERS) + setsockopt(pcap_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bad_fcode, + sizeof(bad_fcode)); +#endif /* * Try setting a filter with an initialized bpf_program @@ -326,9 +388,16 @@ main(int argc, char **argv) * We don't check for errors, because it could get an * error due to a bad pointer or count. */ - fcode.bf_len = INSN_COUNT; - fcode.bf_insns = uninitialized; - pcap_setfilter(pd, &fcode); +#if defined(USE_BPF) + bad_fcode.bf_len = INSN_COUNT; + bad_fcode.bf_insns = uninitialized; + ioctl(pcap_fd, BIOCSETF, &bad_fcode); +#elif defined(USE_SOCKET_FILTERS) + bad_fcode.len = INSN_COUNT; + bad_fcode.filter = uninitialized; + setsockopt(pcap_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bad_fcode, + sizeof(bad_fcode)); +#endif /* * Now compile a filter and set the filter with that.