Work around a Linux bonding driver bug (and the lack of a libpcap workaround).
The bonding driver does not properly handle unknown ioctls; it returns ENODEV rather than ENOTSUP, EOPNOTSUPP, ENOTTY, or a "not supported" error of that type. This causes problems detailed in bug 11058. On Linux, check for bonding devices before checking for monitor-mode support. While we're at it, get rid of a commented-out include of CheckCSourceCompiles (it's presumably already been implicitly included by other functions that use it). Bug: 11058 Change-Id: I13035de0650634c51a52f262829b2b6fb86b39e9 Reviewed-on: https://code.wireshark.org/review/7856 Petri-Dish: Guy Harris <guy@alum.mit.edu> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
parent
f341fd930e
commit
7181ae4713
@ -53,6 +53,35 @@ check_include_file("unistd.h" HAVE_UNISTD_H)
|
|||||||
check_include_file("windows.h" HAVE_WINDOWS_H)
|
check_include_file("windows.h" HAVE_WINDOWS_H)
|
||||||
check_include_file("winsock2.h" HAVE_WINSOCK2_H)
|
check_include_file("winsock2.h" HAVE_WINSOCK2_H)
|
||||||
|
|
||||||
|
#
|
||||||
|
# On Linux, check for some additional headers, which we need as a
|
||||||
|
# workaround for a bonding driver bug and for libpcap's current lack
|
||||||
|
# of its own workaround for that bug.
|
||||||
|
#
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
#
|
||||||
|
# Those header files require <sys/socket.h>.
|
||||||
|
#
|
||||||
|
check_c_source_compiles(
|
||||||
|
"#include <sys/socket.h>
|
||||||
|
#include <linux/sockios.h>
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
HAVE_LINUX_SOCKIOS_H
|
||||||
|
)
|
||||||
|
check_c_source_compiles(
|
||||||
|
"#include <sys/socket.h>
|
||||||
|
#include <linux/if_bonding.h>
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}"
|
||||||
|
HAVE_LINUX_IF_BONDING_H
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
#Functions
|
#Functions
|
||||||
include(CheckFunctionExists)
|
include(CheckFunctionExists)
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
@ -107,7 +136,6 @@ check_struct_has_member("struct tm" tm_zone time.h HAVE_TM_ZONE)
|
|||||||
check_symbol_exists(tzname "time.h" HAVE_TZNAME)
|
check_symbol_exists(tzname "time.h" HAVE_TZNAME)
|
||||||
|
|
||||||
# Check for stuff that isn't testable via the tests above
|
# Check for stuff that isn't testable via the tests above
|
||||||
#include(CheckCSourceCompiles)
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# *If* we found libnl, check if we can use nl80211 stuff with it.
|
# *If* we found libnl, check if we can use nl80211 stuff with it.
|
||||||
|
11
configure.ac
11
configure.ac
@ -2606,6 +2606,17 @@ AC_CHECK_HEADERS(sys/ioctl.h sys/param.h sys/socket.h sys/sockio.h sys/stat.h sy
|
|||||||
AC_CHECK_HEADERS(netinet/in.h)
|
AC_CHECK_HEADERS(netinet/in.h)
|
||||||
AC_CHECK_HEADERS(arpa/inet.h arpa/nameser.h)
|
AC_CHECK_HEADERS(arpa/inet.h arpa/nameser.h)
|
||||||
|
|
||||||
|
#
|
||||||
|
# On Linux, check for some additional headers, which we need as a
|
||||||
|
# workaround for a bonding driver bug and for libpcap's current lack
|
||||||
|
# of its own workaround for that bug.
|
||||||
|
#
|
||||||
|
case "$host_os" in
|
||||||
|
linux*)
|
||||||
|
AC_CHECK_HEADERS(linux/sockios.h linux/if_bonding.h,,,[#include <sys/socket.h>])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
dnl SSL Check
|
dnl SSL Check
|
||||||
SSL_LIBS=''
|
SSL_LIBS=''
|
||||||
AC_MSG_CHECKING(whether to use SSL library)
|
AC_MSG_CHECKING(whether to use SSL library)
|
||||||
|
83
dumpcap.c
83
dumpcap.c
@ -63,6 +63,39 @@
|
|||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linux bonding devices mishandle unknown ioctls; they fail
|
||||||
|
* with ENODEV rather than ENOTSUP, EOPNOTSUPP, or ENOTTY,
|
||||||
|
* so pcap_can_set_rfmon() returns a "no such device" indication
|
||||||
|
* if we try to do SIOCGIWMODE on them.
|
||||||
|
*
|
||||||
|
* So, on Linux, we check for bonding devices, if we can, before
|
||||||
|
* trying pcap_can_set_rfmon(), as pcap_can_set_rfmon() will
|
||||||
|
* end up trying SIOCGIWMODE on the device if that ioctl exists.
|
||||||
|
*/
|
||||||
|
#if defined(HAVE_PCAP_CREATE) && defined(__linux__)
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we're building for a Linux version that supports bonding,
|
||||||
|
* HAVE_BONDING will be defined.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_SOCKIOS_H
|
||||||
|
#include <linux/sockios.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_IF_BONDING_H
|
||||||
|
#include <linux/if_bonding.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BOND_INFO_QUERY_OLD) || defined(SIOCBONDINFOQUERY)
|
||||||
|
#define HAVE_BONDING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* defined(HAVE_PCAP_CREATE) && defined(__linux__) */
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
@ -1117,6 +1150,44 @@ create_data_link_info(int dlt)
|
|||||||
return data_link_info;
|
return data_link_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_BONDING
|
||||||
|
gboolean
|
||||||
|
is_linux_bonding_device(const char *ifname)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct ifreq ifr;
|
||||||
|
ifbond ifb;
|
||||||
|
|
||||||
|
fd = socket(PF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (fd == -1)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
memset(&ifr, 0, sizeof ifr);
|
||||||
|
g_strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
|
||||||
|
memset(&ifb, 0, sizeof ifb);
|
||||||
|
ifr.ifr_data = (caddr_t)&ifb;
|
||||||
|
#if defined(SIOCBONDINFOQUERY)
|
||||||
|
if (ioctl(fd, SIOCBONDINFOQUERY, &ifr) == 0) {
|
||||||
|
close(fd);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (ioctl(fd, BOND_INFO_QUERY_OLD, &ifr) == 0) {
|
||||||
|
close(fd);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static gboolean
|
||||||
|
is_linux_bonding_device(const char *ifname _U_)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the capabilities of a network device.
|
* Get the capabilities of a network device.
|
||||||
*/
|
*/
|
||||||
@ -1177,7 +1248,19 @@ get_if_capabilities(const char *devicename, gboolean monitor_mode
|
|||||||
g_free(caps);
|
g_free(caps);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (is_linux_bonding_device(devicename)) {
|
||||||
|
/*
|
||||||
|
* Linux bonding device; not Wi-Fi, so no monitor mode, and
|
||||||
|
* calling pcap_can_set_rfmon() might get a "no such device"
|
||||||
|
* error.
|
||||||
|
*/
|
||||||
|
status = 0;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Not a Linux bonding device, so go ahead.
|
||||||
|
*/
|
||||||
status = pcap_can_set_rfmon(pch);
|
status = pcap_can_set_rfmon(pch);
|
||||||
|
}
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
/* Error. */
|
/* Error. */
|
||||||
if (status == PCAP_ERROR)
|
if (status == PCAP_ERROR)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user