aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2019-06-03 14:16:52 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2019-06-03 14:16:52 +0200
commit45e3967c20b5020bf720b9497592e231104398f3 (patch)
tree364a53e80d1c2246e33fb00c4f6bb26e854912ae
parent498cec202adbf69a7a72af5e204260682d614183 (diff)
downloadbusybox-w32-45e3967c20b5020bf720b9497592e231104398f3.tar.gz
busybox-w32-45e3967c20b5020bf720b9497592e231104398f3.tar.bz2
busybox-w32-45e3967c20b5020bf720b9497592e231104398f3.zip
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>
-rw-r--r--include/libbb.h1
-rw-r--r--libbb/xconnect.c35
-rw-r--r--networking/ifplugd.c10
-rw-r--r--util-linux/mdev.c28
-rw-r--r--util-linux/uevent.c37
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;
688/* NB: these set SO_REUSEADDR before bind */ 688/* NB: these set SO_REUSEADDR before bind */
689int create_and_bind_stream_or_die(const char *bindaddr, int port) FAST_FUNC; 689int create_and_bind_stream_or_die(const char *bindaddr, int port) FAST_FUNC;
690int create_and_bind_dgram_or_die(const char *bindaddr, int port) FAST_FUNC; 690int create_and_bind_dgram_or_die(const char *bindaddr, int port) FAST_FUNC;
691int create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf) FAST_FUNC;
691/* Create client TCP socket connected to peer:port. Peer cannot be NULL. 692/* Create client TCP socket connected to peer:port. Peer cannot be NULL.
692 * Peer can be numeric IP ("N.N.N.N"), numeric IPv6 address or hostname, 693 * Peer can be numeric IP ("N.N.N.N"), numeric IPv6 address or hostname,
693 * and can have ":PORT" suffix (for IPv6 use "[X:X:...:X]:PORT"). 694 * 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 @@
11#include <netinet/in.h> 11#include <netinet/in.h>
12#include <net/if.h> 12#include <net/if.h>
13#include <sys/un.h> 13#include <sys/un.h>
14#if ENABLE_IFPLUGD || ENABLE_FEATURE_MDEV_DAEMON || ENABLE_UEVENT
15# include <linux/netlink.h>
16#endif
14#include "libbb.h" 17#include "libbb.h"
15 18
16int FAST_FUNC setsockopt_int(int fd, int level, int optname, int optval) 19int 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)
412} 415}
413 416
414 417
418#if ENABLE_IFPLUGD || ENABLE_FEATURE_MDEV_DAEMON || ENABLE_UEVENT
419int FAST_FUNC create_and_bind_to_netlink(int proto, int grp, unsigned rcvbuf)
420{
421 struct sockaddr_nl sa;
422 int fd;
423
424 memset(&sa, 0, sizeof(sa));
425 sa.nl_family = AF_NETLINK;
426 sa.nl_pid = getpid();
427 sa.nl_groups = grp;
428 fd = xsocket(AF_NETLINK, SOCK_DGRAM, proto);
429 xbind(fd, (struct sockaddr *) &sa, sizeof(sa));
430 close_on_exec_on(fd);
431
432 if (rcvbuf != 0) {
433 // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl
434 setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, rcvbuf);
435 setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, rcvbuf);
436# if 0
437 {
438 int z;
439 socklen_t zl = sizeof(z);
440 getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &z, &zl);
441 bb_error_msg("SO_RCVBUF:%d", z);
442 }
443# endif
444 }
445
446 return fd;
447}
448#endif
449
415int FAST_FUNC create_and_connect_stream_or_die(const char *peer, int port) 450int FAST_FUNC create_and_connect_stream_or_die(const char *peer, int port)
416{ 451{
417 int fd; 452 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)
604 604
605 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), ioctl_fd); 605 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), ioctl_fd);
606 if (opts & FLAG_MONITOR) { 606 if (opts & FLAG_MONITOR) {
607 struct sockaddr_nl addr; 607 int fd = create_and_bind_to_netlink(NETLINK_ROUTE, RTMGRP_LINK, 0);
608 int fd = xsocket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
609
610 memset(&addr, 0, sizeof(addr));
611 addr.nl_family = AF_NETLINK;
612 addr.nl_groups = RTMGRP_LINK;
613 addr.nl_pid = getpid();
614
615 xbind(fd, (struct sockaddr*)&addr, sizeof(addr));
616 xmove_fd(fd, netlink_fd); 608 xmove_fd(fd, netlink_fd);
617 } 609 }
618 610
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)
1225 /* 1225 /*
1226 * Daemon mode listening on uevent netlink socket. 1226 * Daemon mode listening on uevent netlink socket.
1227 */ 1227 */
1228 struct sockaddr_nl sa;
1229 int fd; 1228 int fd;
1230 1229
1231//TODO: reuse same code in uevent 1230 /* Subscribe for UEVENT kernel messages */
1232 // Subscribe for UEVENT kernel messages 1231 /* Without a sufficiently big RCVBUF, a ton of simultaneous events
1233 sa.nl_family = AF_NETLINK; 1232 * can trigger ENOBUFS on read, which is unrecoverable.
1234 sa.nl_pad = 0; 1233 * Reproducer:
1235 sa.nl_pid = getpid(); 1234 * mdev -d
1236 sa.nl_groups = 1 << 0; 1235 * find /sys -name uevent -exec sh -c 'echo add >"{}"' ';'
1237 fd = xsocket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); 1236 */
1238 xbind(fd, (struct sockaddr *) &sa, sizeof(sa)); 1237 fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, 1 << 0, RCVBUF);
1239 close_on_exec_on(fd);
1240
1241 // Without a sufficiently big RCVBUF, a ton of simultaneous events
1242 // can trigger ENOBUFS on read, which is unrecoverable.
1243 // Reproducer:
1244 // mdev -d
1245 // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';'
1246 //
1247 // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl
1248 setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, RCVBUF);
1249 setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, RCVBUF);
1250 1238
1251 /* 1239 /*
1252 * Make inital scan after the uevent socket is alive and 1240 * 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 };
46int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 46int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
47int uevent_main(int argc UNUSED_PARAM, char **argv) 47int uevent_main(int argc UNUSED_PARAM, char **argv)
48{ 48{
49 struct sockaddr_nl sa;
50 int fd; 49 int fd;
51 50
52 INIT_G(); 51 INIT_G();
53 52
54 argv++; 53 argv++;
55 54
56 // Subscribe for UEVENT kernel messages 55 // Subscribe for UEVENT kernel messages.
57 sa.nl_family = AF_NETLINK;
58 sa.nl_pad = 0;
59 sa.nl_pid = getpid();
60 sa.nl_groups = 1 << 0;
61 fd = xsocket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
62 xbind(fd, (struct sockaddr *) &sa, sizeof(sa));
63 close_on_exec_on(fd);
64
65 // Without a sufficiently big RCVBUF, a ton of simultaneous events 56 // Without a sufficiently big RCVBUF, a ton of simultaneous events
66 // can trigger ENOBUFS on read, which is unrecoverable. 57 // can trigger ENOBUFS on read, which is unrecoverable.
67 // Reproducer: 58 // Reproducer:
68 // uevent mdev & 59 // uevent mdev &
69 // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' 60 // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';'
70 // 61 fd = create_and_bind_to_netlink(NETLINK_KOBJECT_UEVENT, /*groups:*/ 1 << 0, RCVBUF);
71 // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl
72 setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, RCVBUF);
73 setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, RCVBUF);
74 if (0) {
75 int z;
76 socklen_t zl = sizeof(z);
77 getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &z, &zl);
78 bb_error_msg("SO_RCVBUF:%d", z);
79 }
80 62
81 for (;;) { 63 for (;;) {
82 char *netbuf; 64 char *netbuf;
@@ -118,14 +100,15 @@ int uevent_main(int argc UNUSED_PARAM, char **argv)
118 } 100 }
119 env[idx] = NULL; 101 env[idx] = NULL;
120 102
121 idx = 0; 103 if (argv[0]) {
122 while (env[idx]) 104 idx = 0;
123 putenv(env[idx++]); 105 while (env[idx])
124 if (argv[0]) 106 putenv(env[idx++]);
125 spawn_and_wait(argv); 107 spawn_and_wait(argv);
126 idx = 0; 108 idx = 0;
127 while (env[idx]) 109 while (env[idx])
128 bb_unsetenv(env[idx++]); 110 bb_unsetenv(env[idx++]);
111 }
129 munmap(netbuf, BUFFER_SIZE); 112 munmap(netbuf, BUFFER_SIZE);
130 } 113 }
131 114