[git commit] libbb: move netlink socket binding to the utility function

Denys Vlasenko vda.linux at googlemail.com
Mon Jun 3 12:16:52 UTC 2019


commit: https://git.busybox.net/busybox/commit/?id=45e3967c20b5020bf720b9497592e231104398f3
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at googlemail.com>
---
 include/libbb.h      |  1 +
 libbb/xconnect.c     | 35 +++++++++++++++++++++++++++++++++++
 networking/ifplugd.c | 10 +---------
 util-linux/mdev.c    | 28 ++++++++--------------------
 util-linux/uevent.c  | 37 ++++++++++---------------------------
 5 files changed, 55 insertions(+), 56 deletions(-)

diff --git a/include/libbb.h b/include/libbb.h
index 3a870bf80..100d6b606 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -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").
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
index 39e56b223..ea5fe173f 100644
--- a/libbb/xconnect.c
+++ b/libbb/xconnect.c
@@ -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;
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index 1426709cb..b7b26c113 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -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);
 	}
 
diff --git a/util-linux/mdev.c b/util-linux/mdev.c
index 88c82b6fb..9cb3586f1 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -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
diff --git a/util-linux/uevent.c b/util-linux/uevent.c
index 761743f45..2f8990ed9 100644
--- a/util-linux/uevent.c
+++ b/util-linux/uevent.c
@@ -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);
 	}
 


More information about the busybox-cvs mailing list