linux: ensure the netlink socket is correctly opened with older Linux kernels
authorNathan Hjelm <hjelmn@me.com>
Thu, 8 Aug 2013 03:01:43 +0000 (21:01 -0600)
committerNathan Hjelm <hjelmn@me.com>
Thu, 8 Aug 2013 03:01:43 +0000 (21:01 -0600)
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
libusb/version_nano.h

index 758974f..20f1d02 100644 (file)
@@ -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) {
index b8325ac..7ee3d41 100644 (file)
@@ -1 +1 @@
-#define LIBUSB_NANO 10803
+#define LIBUSB_NANO 10805