]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
socket-util: introduce netlink_socket_get_multicast_groups()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 31 Jul 2024 04:21:08 +0000 (13:21 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 2 Aug 2024 02:16:33 +0000 (11:16 +0900)
No functional change. Preparation for later commits.

src/basic/socket-util.c
src/basic/socket-util.h
src/libsystemd/sd-netlink/netlink-socket.c

index 5849799f05d3432d7f9d7855317a1dde3cd19410..c59c6a16a14924128457963e81e77b446a40e9a4 100644 (file)
@@ -1767,3 +1767,38 @@ int vsock_get_local_cid(unsigned *ret) {
 
         return 0;
 }
+
+int netlink_socket_get_multicast_groups(int fd, size_t *ret_len, uint32_t **ret_groups) {
+        _cleanup_free_ uint32_t *groups = NULL;
+        socklen_t len = 0, old_len;
+
+        assert(fd >= 0);
+
+        /* This returns ENOPROTOOPT if the kernel is older than 4.2. */
+
+        if (getsockopt(fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len) < 0)
+                return -errno;
+
+        if (len == 0)
+                goto finalize;
+
+        groups = new0(uint32_t, len);
+        if (!groups)
+                return -ENOMEM;
+
+        old_len = len;
+
+        if (getsockopt(fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len) < 0)
+                return -errno;
+
+        if (old_len != len)
+                return -EIO;
+
+finalize:
+        if (ret_len)
+                *ret_len = len;
+        if (ret_groups)
+                *ret_groups = TAKE_PTR(groups);
+
+        return 0;
+}
index c784125ccb423450063f116ee7bb216d8e342c42..18699a5349ed42f8fea7b3018b2586670e5ee919 100644 (file)
@@ -396,3 +396,5 @@ int socket_address_parse_vsock(SocketAddress *ret_address, const char *s);
 #define SOMAXCONN_DELUXE INT_MAX
 
 int vsock_get_local_cid(unsigned *ret);
+
+int netlink_socket_get_multicast_groups(int fd, size_t *ret_len, uint32_t **ret_groups);
index d09dc31fa32f39ddd267d7cdeccdf1f7fbbe7f53..79729decbc2d235d92eea41f5a3d7aee8024ec9f 100644 (file)
 
 static int broadcast_groups_get(sd_netlink *nl) {
         _cleanup_free_ uint32_t *groups = NULL;
-        socklen_t len = 0, old_len;
+        size_t len;
         int r;
 
         assert(nl);
         assert(nl->fd >= 0);
 
-        if (getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len) < 0) {
-                if (errno != ENOPROTOOPT)
-                        return -errno;
-
+        r = netlink_socket_get_multicast_groups(nl->fd, &len, &groups);
+        if (r == -ENOPROTOOPT) {
                 nl->broadcast_group_dont_leave = true;
                 return 0;
         }
+        if (r < 0)
+                return r;
 
-        if (len == 0)
-                return 0;
-
-        groups = new0(uint32_t, len);
-        if (!groups)
-                return -ENOMEM;
-
-        old_len = len;
-
-        if (getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len) < 0)
-                return -errno;
-
-        if (old_len != len)
-                return -EIO;
-
-        for (unsigned i = 0; i < len; i++)
+        for (size_t i = 0; i < len; i++)
                 for (unsigned j = 0; j < sizeof(uint32_t) * 8; j++)
                         if (groups[i] & (1U << j)) {
                                 unsigned group = i * sizeof(uint32_t) * 8 + j + 1;