libbb: move netlink socket binding to the utility function
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 3 Jun 2019 12:16:52 +0000 (14:16 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 3 Jun 2019 12:16:52 +0000 (14:16 +0200)
function                                             old     new   delta
create_and_bind_to_netlink                             -     134    +134
ifplugd_main                                        1117    1052     -65
uevent_main                                          399     306     -93
mdev_main                                            314     215     -99
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/3 up/down: 134/-257)         Total: -123 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
include/libbb.h
libbb/xconnect.c
networking/ifplugd.c
util-linux/mdev.c
util-linux/uevent.c

index 3a870bf80ce55566881f4b61f5ce0349e1094f33..100d6b606314bdf199b4a6b7a4d49d4e6b7d0415 100644 (file)
@@ -688,6 +688,7 @@ int xsocket_stream(len_and_sockaddr **lsap) FAST_FUNC;
 /* NB: these set SO_REUSEADDR before bind */
 int create_and_bind_stream_or_die(const char *bindaddr, int port) FAST_FUNC;
 int create_and_bind_dgram_or_die(const char *bindaddr, int port) FAST_FUNC;
+int create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf) FAST_FUNC;
 /* Create client TCP socket connected to peer:port. Peer cannot be NULL.
  * Peer can be numeric IP ("N.N.N.N"), numeric IPv6 address or hostname,
  * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT").
index 39e56b223b5f8577e9f95c87251d3178380daee9..ea5fe173f984132bcd6e7938ee40f468129c5073 100644 (file)
@@ -11,6 +11,9 @@
 #include <netinet/in.h>
 #include <net/if.h>
 #include <sys/un.h>
+#if ENABLE_IFPLUGD || ENABLE_FEATURE_MDEV_DAEMON || ENABLE_UEVENT
+# include <linux/netlink.h>
+#endif
 #include "libbb.h"
 
 int FAST_FUNC setsockopt_int(int fd, int level, int optname, int optval)
@@ -412,6 +415,38 @@ int FAST_FUNC create_and_bind_dgram_or_die(const char *bindaddr, int port)
 }
 
 
+#if ENABLE_IFPLUGD || ENABLE_FEATURE_MDEV_DAEMON || ENABLE_UEVENT
+int FAST_FUNC create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf)
+{
+       struct sockaddr_nl sa;
+       int fd;
+
+       memset(&sa, 0, sizeof(sa));
+       sa.nl_family = AF_NETLINK;
+       sa.nl_pid = getpid();
+       sa.nl_groups = grp;
+       fd = xsocket(AF_NETLINK, SOCK_DGRAM, proto);
+       xbind(fd, (struct sockaddr *) &sa, sizeof(sa));
+       close_on_exec_on(fd);
+
+       if (rcvbuf != 0) {
+               // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl
+               setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF,      rcvbuf);
+               setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, rcvbuf);
+# if 0
+               {
+                       int z;
+                       socklen_t zl = sizeof(z);
+                       getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &z, &zl);
+                       bb_error_msg("SO_RCVBUF:%d", z);
+               }
+# endif
+       }
+
+       return fd;
+}
+#endif
+
 int FAST_FUNC create_and_connect_stream_or_die(const char *peer, int port)
 {
        int fd;
index 1426709cbc65c8506a0d83cae592e3076a3f2215..b7b26c1136300d90e5f3833fede9983faf2a1f1a 100644 (file)
@@ -604,15 +604,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
 
        xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), ioctl_fd);
        if (opts & FLAG_MONITOR) {
-               struct sockaddr_nl addr;
-               int fd = xsocket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
-
-               memset(&addr, 0, sizeof(addr));
-               addr.nl_family = AF_NETLINK;
-               addr.nl_groups = RTMGRP_LINK;
-               addr.nl_pid = getpid();
-
-               xbind(fd, (struct sockaddr*)&addr, sizeof(addr));
+               int fd = create_and_bind_to_netlink(NETLINK_ROUTE, RTMGRP_LINK, 0);
                xmove_fd(fd, netlink_fd);
        }
 
index 88c82b6fb898c0d3de4d97239fef5e177b896553..9cb3586f185829430879acfcb4673bdf923ecafe 100644 (file)
@@ -1225,28 +1225,16 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
                /*
                 * Daemon mode listening on uevent netlink socket.
                 */
-               struct sockaddr_nl sa;
                int fd;
 
-//TODO: reuse same code in uevent
-               // Subscribe for UEVENT kernel messages
-               sa.nl_family = AF_NETLINK;
-               sa.nl_pad = 0;
-               sa.nl_pid = getpid();
-               sa.nl_groups = 1 << 0;
-               fd = xsocket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
-               xbind(fd, (struct sockaddr *) &sa, sizeof(sa));
-               close_on_exec_on(fd);
-
-               // Without a sufficiently big RCVBUF, a ton of simultaneous events
-               // can trigger ENOBUFS on read, which is unrecoverable.
-               // Reproducer:
-               //      mdev -d
-               //      find /sys -name uevent -exec sh -c 'echo add >"{}"' ';'
-               //
-               // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl
-               setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF,      RCVBUF);
-               setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, RCVBUF);
+               /* Subscribe for UEVENT kernel messages */
+               /* Without a sufficiently big RCVBUF, a ton of simultaneous events
+                * can trigger ENOBUFS on read, which is unrecoverable.
+                * Reproducer:
+                *      mdev -d
+                *      find /sys -name uevent -exec sh -c 'echo add >"{}"' ';'
+                */
+               fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, 1 << 0, RCVBUF);
 
                /*
                 * Make inital scan after the uevent socket is alive and
index 761743f454922e460de95ca55111dcf31c8665a3..2f8990ed94d57ff6830d6eb6460ec5676d3187ab 100644 (file)
@@ -46,37 +46,19 @@ enum { RCVBUF = 2 * 1024 * 1024 };
 int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int uevent_main(int argc UNUSED_PARAM, char **argv)
 {
-       struct sockaddr_nl sa;
        int fd;
 
        INIT_G();
 
        argv++;
 
-       // Subscribe for UEVENT kernel messages
-       sa.nl_family = AF_NETLINK;
-       sa.nl_pad = 0;
-       sa.nl_pid = getpid();
-       sa.nl_groups = 1 << 0;
-       fd = xsocket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
-       xbind(fd, (struct sockaddr *) &sa, sizeof(sa));
-       close_on_exec_on(fd);
-
+       // Subscribe for UEVENT kernel messages.
        // Without a sufficiently big RCVBUF, a ton of simultaneous events
        // can trigger ENOBUFS on read, which is unrecoverable.
        // Reproducer:
        //      uevent mdev &
        //      find /sys -name uevent -exec sh -c 'echo add >"{}"' ';'
-       //
-       // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl
-       setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF,      RCVBUF);
-       setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, RCVBUF);
-       if (0) {
-               int z;
-               socklen_t zl = sizeof(z);
-               getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &z, &zl);
-               bb_error_msg("SO_RCVBUF:%d", z);
-       }
+       fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, /*groups:*/ 1 << 0, RCVBUF);
 
        for (;;) {
                char *netbuf;
@@ -118,14 +100,15 @@ int uevent_main(int argc UNUSED_PARAM, char **argv)
                }
                env[idx] = NULL;
 
-               idx = 0;
-               while (env[idx])
-                       putenv(env[idx++]);
-               if (argv[0])
+               if (argv[0]) {
+                       idx = 0;
+                       while (env[idx])
+                               putenv(env[idx++]);
                        spawn_and_wait(argv);
-               idx = 0;
-               while (env[idx])
-                       bb_unsetenv(env[idx++]);
+                       idx = 0;
+                       while (env[idx])
+                               bb_unsetenv(env[idx++]);
+               }
                munmap(netbuf, BUFFER_SIZE);
        }