diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2019-06-03 14:16:52 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2019-06-03 14:16:52 +0200 |
commit | 45e3967c20b5020bf720b9497592e231104398f3 (patch) | |
tree | 364a53e80d1c2246e33fb00c4f6bb26e854912ae | |
parent | 498cec202adbf69a7a72af5e204260682d614183 (diff) | |
download | busybox-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.h | 1 | ||||
-rw-r--r-- | libbb/xconnect.c | 35 | ||||
-rw-r--r-- | networking/ifplugd.c | 10 | ||||
-rw-r--r-- | util-linux/mdev.c | 28 | ||||
-rw-r--r-- | 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; | |||
688 | /* NB: these set SO_REUSEADDR before bind */ | 688 | /* NB: these set SO_REUSEADDR before bind */ |
689 | int create_and_bind_stream_or_die(const char *bindaddr, int port) FAST_FUNC; | 689 | int create_and_bind_stream_or_die(const char *bindaddr, int port) FAST_FUNC; |
690 | int create_and_bind_dgram_or_die(const char *bindaddr, int port) FAST_FUNC; | 690 | int create_and_bind_dgram_or_die(const char *bindaddr, int port) FAST_FUNC; |
691 | int 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 | ||
16 | int FAST_FUNC setsockopt_int(int fd, int level, int optname, int optval) | 19 | 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) | |||
412 | } | 415 | } |
413 | 416 | ||
414 | 417 | ||
418 | #if ENABLE_IFPLUGD || ENABLE_FEATURE_MDEV_DAEMON || ENABLE_UEVENT | ||
419 | int 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 | |||
415 | int FAST_FUNC create_and_connect_stream_or_die(const char *peer, int port) | 450 | int 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 }; | |||
46 | int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 46 | int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
47 | int uevent_main(int argc UNUSED_PARAM, char **argv) | 47 | int 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 | ||