If available.
Upstream PR: https://github.com/the-tcpdump-group/libpcap/pull/1683
This should only be done on systems that lack the needed kernel hooks
as libpcap does not support a write filter and is vulnerable
if the application is exploited.
+An upstream PR has been submitted to add `pcap_setwritefilter()` and
+`pcap_lockfilter()` to libpcap:
+ https://github.com/the-tcpdump-group/libpcap/pull/1683
## Init systems
We try and detect how dhcpcd should interact with system services at runtime.
LIBPCAP_CFLAGS=$($PKG_CONFIG --cflags libpcap 2>/dev/null)
LIBPCAP_LIBS=$($PKG_CONFIG --libs libpcap 2>/dev/null)
echo "yes"
- echo "CFLAGS+= $LIBPCAP_CFLAGS" >>$CONFIG_MK
- echo "LDADD+= $LIBPCAP_LIBS" >>$CONFIG_MK
else
cat <<EOF >_libpcap.c
#include <pcap.h>
EOF
if $XCC _libpcap.c -o libpcap -lpcap 2>&3; then
echo "yes"
- echo "LDADD+= -lpcap" >>$CONFIG_MK
+ LIBPCAP_CFLAGS=
+ LIBPCAP_LIBS="-lpcap"
abort=false
else
echo "no"
rm -f _libpcap.c libpcap
$abort && exit 1
fi
+ LIBPCAP_LIBS="-L/tmp/foo/usr/local/lib -lpcap"
+ echo "CFLAGS+= $LIBPCAP_CFLAGS" >>$CONFIG_MK
+ echo "LDADD+= $LIBPCAP_LIBS" >>$CONFIG_MK
echo "#define USE_LIBPCAP" >>$CONFIG_H
+
+ printf "Testing for pcap_setwritefilter() ... "
+ cat <<EOF >_libpcap_write.c
+#include <pcap.h>
+
+int main(void) {
+ return pcap_setwritefilter(NULL, NULL);
+}
+EOF
+ if $XCC $LIBPCAP_CFLAGS _libpcap_write.c -o libpcap_write $LIBPCAP_LIBS 2>&3; then
+ echo "yes"
+ echo "#define HAVE_PCAP_SETWRITEFILTER" >>$CONFIG_H
+ else
+ echo "no"
+ fi
+ rm -f _libpcap_write.c libpcap_write
+
+ printf "Testing for pcap_lockfilter() ... "
+ cat <<EOF >_libpcap_lock.c
+#include <pcap.h>
+
+int main(void) {
+ return pcap_lockfilter(NULL);
+}
+EOF
+ if $XCC $LIBPCAP_CFLAGS _libpcap_lock.c -o libpcap_lock $LIBPCAP_LIBS 2>&3; then
+ echo "yes"
+ echo "#define HAVE_PCAP_LOCKFILTER" >>$CONFIG_H
+ else
+ echo "no"
+ fi
+ rm -f _libpcap_lock.c libpcap_lock
fi
# Workaround for DragonFlyBSD import
}
int
-bpf_lock(const struct bpf *bpf)
+bpf_lockfilter(const struct bpf *bpf)
{
#ifdef BIOCLOCK
return ioctl(bpf->bpf_fd, BIOCLOCK);
}
int
-bpf_lock(const struct bpf *bpf)
+bpf_lockfilter(const struct bpf *bpf)
{
#ifdef SO_LOCK_FILTER
int fd = bpf->bpf_fd, on = 1;
#define PCAP_CHECK(call, name) \
do { \
int status = (call); \
- if (status < 0) \
+ if (status < 0) { \
logerrx("%s: %s failed: %s", __func__, name, \
pcap_statustostr(status)); \
- else if (status > 0) \
+ goto eexit; \
+ } else if (status > 0) \
logwarnx("%s: %s warning: %s", __func__, name, \
pcap_statustostr(status)); \
} while (0)
struct bpf *
bpf_open(const struct interface *ifp,
int (*filter)(const struct bpf *, const struct in_addr *),
- __unused const struct in_addr *ia)
+ const struct in_addr *ia)
{
int err;
struct bpf *bpf;
goto eexit;
}
- PCAP_CHECK(pcap_set_snaplen(handle, (int)bpf->bpf_size), "pcap_set_snaplen");
+ PCAP_CHECK(pcap_set_snaplen(handle, (int)bpf->bpf_size),
+ "pcap_set_snaplen");
PCAP_CHECK(pcap_set_promisc(handle, 0), "pcap_set_promisc");
PCAP_CHECK(pcap_set_immediate_mode(handle, 1),
"pcap_set_immediate_mode");
}
int
-bpf_setwfilter(__unused const struct bpf *bpf, __unused void *filter,
- __unused unsigned int filter_len)
+bpf_setwfilter(const struct bpf *bpf, void *filter, unsigned int filter_len)
{
+#ifdef HAVE_PCAP_SETWRITEFILTER
+ struct bpf_program pf = { .bf_insns = filter, .bf_len = filter_len };
+
+ return pcap_setwritefilter(bpf->bpf_handle, &pf);
+#else
#warning A compromised libpcap socket can be used as a raw socket
+ UNUSED(bpf);
+ UNUSED(filter);
+ UNUSED(filter_len);
errno = ENOSYS;
return -1;
+#endif
}
int
-bpf_lock(__unused const struct bpf *bpf)
+bpf_lockfilter(const struct bpf *bpf)
{
+#ifdef HAVE_PCAP_LOCKFILTER
+ return pcap_lockfilter(bpf->bpf_handle);
+#else
+ UNUSED(bpf);
errno = ENOSYS;
return -1;
+#endif
}
void
return -1;
if (bpf_arp_rw(bpf, ia, false) == -1 && errno != ENOSYS)
return -1;
- if (bpf_lock(bpf) == -1 && errno != ENOSYS)
+ if (bpf_lockfilter(bpf) == -1 && errno != ENOSYS)
return -1;
return 0;
}
return -1;
if (bpf_bootp_rw(bpf, false) == -1 && errno != ENOSYS)
return -1;
- if (bpf_lock(bpf) == -1 && errno != ENOSYS)
+ if (bpf_lockfilter(bpf) == -1 && errno != ENOSYS)
return -1;
return 0;
}
void bpf_close(struct bpf *);
int bpf_setfilter(const struct bpf *, void *, unsigned int);
int bpf_setwfilter(const struct bpf *, void *, unsigned int);
-int bpf_lock(const struct bpf *);
+int bpf_lockfilter(const struct bpf *);
ssize_t bpf_send(const struct bpf *, uint16_t, const void *, size_t);
ssize_t bpf_writev(const struct bpf *, struct iovec *, int);
ssize_t bpf_read(struct bpf *, void *, size_t);