From b50a433c164996761344efb6c90594de7906fe56 Mon Sep 17 00:00:00 2001 From: Nathan Hjelm Date: Wed, 7 Aug 2013 21:01:43 -0600 Subject: [PATCH] linux: ensure the netlink socket is correctly opened with older Linux kernels It is possible for the extra socket flags (available from 2.6.27 on) to be defined but not available. Check for this case and set the flags correctly on the netlink socket. --- libusb/os/linux_netlink.c | 36 ++++++++++++++++++++++++++++++------ libusb/version_nano.h | 2 +- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/libusb/os/linux_netlink.c b/libusb/os/linux_netlink.c index 758974f..20f1d02 100644 --- a/libusb/os/linux_netlink.c +++ b/libusb/os/linux_netlink.c @@ -63,6 +63,26 @@ static void *linux_netlink_event_thread_main(void *arg); struct sockaddr_nl snl = { .nl_family=AF_NETLINK, .nl_groups=KERNEL }; +static int set_fd_cloexec_nb (int fd) +{ + int flags; + +#if defined(FD_CLOEXEC) + fcntl (linux_netlink_socket, F_GETFD, &flags); + + if (!(flags & FD_CLOEXEC)) { + fcntl (linux_netlink_socket, F_SETFD, flags | FD_CLOEXEC); + } +#endif + + fcntl (linux_netlink_socket, F_GETFL, &flags); + if (!(flags & O_NONBLOCK)) { + fcntl (linux_netlink_socket, F_SETFL, flags | O_NONBLOCK); + } + + return 0; +} + int linux_netlink_start_event_monitor(void) { int socktype = SOCK_RAW; @@ -78,16 +98,20 @@ int linux_netlink_start_event_monitor(void) #endif linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT); + if (-1 == linux_netlink_socket && EINVAL == errno) { + linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); + } + if (-1 == linux_netlink_socket) { return LIBUSB_ERROR_OTHER; } -#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC) - fcntl (linux_netlink_socket, F_SETFD, FD_CLOEXEC); -#endif -#if !defined(SOCK_NONBLOCK) - fcntl (linux_netlink_socket, F_SETFL, O_NONBLOCK); -#endif + ret = set_fd_cloexec_nb (linux_netlink_socket); + if (0 != ret) { + close (linux_netlink_socket); + linux_netlink_socket = -1; + return LIBUSB_ERROR_OTHER; + } ret = bind(linux_netlink_socket, (struct sockaddr *) &snl, sizeof(snl)); if (0 != ret) { diff --git a/libusb/version_nano.h b/libusb/version_nano.h index b8325ac..7ee3d41 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10803 +#define LIBUSB_NANO 10805 -- 2.7.4