diff options
author | Nathan Hjelm <hjelmn@me.com> | 2013-08-07 21:01:43 -0600 |
---|---|---|
committer | Nathan Hjelm <hjelmn@me.com> | 2013-08-07 21:01:43 -0600 |
commit | b50a433c164996761344efb6c90594de7906fe56 (patch) | |
tree | fa44e559b337b54ed6282eedae0b9d753651cef0 | |
parent | c848e5b72a1670a33eb84f210b951177a3de19e9 (diff) | |
download | android_external_libusbx-b50a433c164996761344efb6c90594de7906fe56.tar.gz android_external_libusbx-b50a433c164996761344efb6c90594de7906fe56.tar.bz2 android_external_libusbx-b50a433c164996761344efb6c90594de7906fe56.zip |
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.
-rw-r--r-- | libusb/os/linux_netlink.c | 36 | ||||
-rw-r--r-- | 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 |