libbb: move netlink socket binding to the utility function

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>
This commit is contained in:
Denys Vlasenko 2019-06-03 14:16:52 +02:00
parent 498cec202a
commit 45e3967c20
5 changed files with 55 additions and 56 deletions

View File

@ -688,6 +688,7 @@ int xsocket_stream(len_and_sockaddr **lsap) FAST_FUNC;
/* NB: these set SO_REUSEADDR before bind */ /* 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_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_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. /* 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, * 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"). * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT").

View File

@ -11,6 +11,9 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <net/if.h> #include <net/if.h>
#include <sys/un.h> #include <sys/un.h>
#if ENABLE_IFPLUGD || ENABLE_FEATURE_MDEV_DAEMON || ENABLE_UEVENT
# include <linux/netlink.h>
#endif
#include "libbb.h" #include "libbb.h"
int FAST_FUNC setsockopt_int(int fd, int level, int optname, int optval) 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 FAST_FUNC create_and_connect_stream_or_die(const char *peer, int port)
{ {
int fd; int fd;

View File

@ -604,15 +604,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), ioctl_fd); xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), ioctl_fd);
if (opts & FLAG_MONITOR) { if (opts & FLAG_MONITOR) {
struct sockaddr_nl addr; int fd = create_and_bind_to_netlink(NETLINK_ROUTE, RTMGRP_LINK, 0);
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));
xmove_fd(fd, netlink_fd); xmove_fd(fd, netlink_fd);
} }

View File

@ -1225,28 +1225,16 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
/* /*
* Daemon mode listening on uevent netlink socket. * Daemon mode listening on uevent netlink socket.
*/ */
struct sockaddr_nl sa;
int fd; int fd;
//TODO: reuse same code in uevent /* Subscribe for UEVENT kernel messages */
// Subscribe for UEVENT kernel messages /* Without a sufficiently big RCVBUF, a ton of simultaneous events
sa.nl_family = AF_NETLINK; * can trigger ENOBUFS on read, which is unrecoverable.
sa.nl_pad = 0; * Reproducer:
sa.nl_pid = getpid(); * mdev -d
sa.nl_groups = 1 << 0; * find /sys -name uevent -exec sh -c 'echo add >"{}"' ';'
fd = xsocket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); */
xbind(fd, (struct sockaddr *) &sa, sizeof(sa)); fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, 1 << 0, RCVBUF);
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);
/* /*
* Make inital scan after the uevent socket is alive and * Make inital scan after the uevent socket is alive and

View 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, char **argv) MAIN_EXTERNALLY_VISIBLE;
int uevent_main(int argc UNUSED_PARAM, char **argv) int uevent_main(int argc UNUSED_PARAM, char **argv)
{ {
struct sockaddr_nl sa;
int fd; int fd;
INIT_G(); INIT_G();
argv++; argv++;
// Subscribe for UEVENT kernel messages // 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 // Without a sufficiently big RCVBUF, a ton of simultaneous events
// can trigger ENOBUFS on read, which is unrecoverable. // can trigger ENOBUFS on read, which is unrecoverable.
// Reproducer: // Reproducer:
// uevent mdev & // uevent mdev &
// find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';'
// fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, /*groups:*/ 1 << 0, RCVBUF);
// 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);
}
for (;;) { for (;;) {
char *netbuf; char *netbuf;
@ -118,14 +100,15 @@ int uevent_main(int argc UNUSED_PARAM, char **argv)
} }
env[idx] = NULL; env[idx] = NULL;
if (argv[0]) {
idx = 0; idx = 0;
while (env[idx]) while (env[idx])
putenv(env[idx++]); putenv(env[idx++]);
if (argv[0])
spawn_and_wait(argv); spawn_and_wait(argv);
idx = 0; idx = 0;
while (env[idx]) while (env[idx])
bb_unsetenv(env[idx++]); bb_unsetenv(env[idx++]);
}
munmap(netbuf, BUFFER_SIZE); munmap(netbuf, BUFFER_SIZE);
} }