netlink-socket.c revision 9c5a882b7fc256ddc0b227677fa06546f0e944a8
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/***
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2013 Tom Gundersen <teg@jklm.no>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering***/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include <netinet/in.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <stdbool.h>
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering#include <unistd.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include "util.h"
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering#include "socket-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "formats-util.h"
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen#include "refcnt.h"
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen#include "missing.h"
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen#include "sd-netlink.h"
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include "netlink-util.h"
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include "netlink-internal.h"
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen#include "netlink-types.h"
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersenint socket_open(int family) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen int fd;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, family);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (fd < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return fd;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering}
3c0cf502796be355431d4a64d738e75f543aa51dLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int broadcast_groups_get(sd_netlink *nl) {
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering _cleanup_free_ uint32_t *groups = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering socklen_t len = 0, old_len;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering unsigned i, j;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(nl);
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering assert(nl->fd > 0);
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len);
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering if (r < 0) {
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering if (errno == ENOPROTOOPT) {
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering nl->broadcast_group_dont_leave = true;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering return 0;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering } else
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering return -errno;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering }
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (len == 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering groups = new0(uint32_t, len);
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen if (!groups)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return -ENOMEM;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen old_len = len;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len);
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen if (old_len != len)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EIO;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (r < 0)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return r;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering for (i = 0; i < len; i++) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering for (j = 0; j < sizeof(uint32_t) * 8; j ++) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering uint32_t offset;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering unsigned group;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering offset = 1U << j;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (!(groups[i] & offset))
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering continue;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering group = i * sizeof(uint32_t) * 8 + j + 1;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering r = hashmap_put(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(1));
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (r < 0)
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering return r;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering}
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poetteringint socket_bind(sd_netlink *nl) {
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering socklen_t addrlen;
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering int r, one = 1;
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_PKTINFO, &one, sizeof(one));
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering addrlen = sizeof(nl->sockaddr);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = bind(nl->fd, &nl->sockaddr.sa, addrlen);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* ignore EINVAL to allow opening an already bound socket */
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen if (r < 0 && errno != EINVAL)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = getsockname(nl->fd, &nl->sockaddr.sa, &addrlen);
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen if (r < 0)
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen return -errno;
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen r = broadcast_groups_get(nl);
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen if (r < 0)
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen return r;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen return 0;
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen}
3e684349c2cead2e6fd2f816c34eb17daba23a49Lennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poetteringstatic unsigned broadcast_group_get_ref(sd_netlink *nl, unsigned group) {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering assert(nl);
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering return PTR_TO_UINT(hashmap_get(nl->broadcast_group_refs, UINT_TO_PTR(group)));
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int broadcast_group_set_ref(sd_netlink *nl, unsigned group, unsigned n_ref) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering assert(nl);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering r = hashmap_replace(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(n_ref));
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (r < 0)
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen return r;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering return 0;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering}
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poetteringstatic int broadcast_group_join(sd_netlink *nl, unsigned group) {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering int r;
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering assert(nl);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering assert(nl->fd >= 0);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering assert(group > 0);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group));
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (r < 0)
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering return -errno;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering return 0;
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering}
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poetteringint socket_broadcast_group_ref(sd_netlink *nl, unsigned group) {
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering unsigned n_ref;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering int r;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering assert(nl);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
eed857b71702f8551b46b66b31fa0d08583cf23cLennart Poettering n_ref = broadcast_group_get_ref(nl, group);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering n_ref ++;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (r < 0)
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering return r;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering r = broadcast_group_set_ref(nl, group, n_ref);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (r < 0)
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering return r;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (n_ref > 1)
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen /* not yet in the group */
91b14d6ff362b938a72db17b095ee9903d07381bTom Gundersen return 0;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering r = broadcast_group_join(nl, group);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (r < 0)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return r;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return 0;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering}
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poetteringstatic int broadcast_group_leave(sd_netlink *nl, unsigned group) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering int r;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering assert(nl);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering assert(nl->fd >= 0);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering assert(group > 0);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (nl->broadcast_group_dont_leave)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return 0;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_DROP_MEMBERSHIP, &group, sizeof(group));
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (r < 0)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return -errno;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return 0;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering}
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poetteringint socket_broadcast_group_unref(sd_netlink *nl, unsigned group) {
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering unsigned n_ref;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering int r;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering assert(nl);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering n_ref = broadcast_group_get_ref(nl, group);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering assert(n_ref > 0);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering n_ref --;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering r = broadcast_group_set_ref(nl, group, n_ref);
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (r < 0)
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering return r;
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering
0b58db658b5c3f586ac3a837427f1f7fec2abb2eLennart Poettering if (n_ref > 0)
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen /* still refs left */
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen return 0;
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen r = broadcast_group_leave(nl, group);
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering if (r < 0)
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering return r;
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering return 0;
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering}
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen/* returns the number of bytes sent, or a negative error code */
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersenint socket_write_message(sd_netlink *nl, sd_netlink_message *m) {
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen union {
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen struct sockaddr sa;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen struct sockaddr_nl nl;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen } addr = {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen .nl.nl_family = AF_NETLINK,
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen };
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen ssize_t k;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering assert(nl);
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen assert(m);
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen assert(m->hdr);
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen 0, &addr.sa, sizeof(addr));
d74fb368b18f0fbd9a4fe6f15691bbea7f3c4a01Tom Gundersen if (k < 0)
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return -errno;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return k;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen}
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersenstatic int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen union sockaddr_union sender;
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen uint8_t cmsg_buffer[CMSG_SPACE(sizeof(struct nl_pktinfo))];
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen struct msghdr msg = {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen .msg_iov = iov,
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen .msg_iovlen = 1,
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen .msg_name = &sender,
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen .msg_namelen = sizeof(sender),
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering .msg_control = cmsg_buffer,
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering .msg_controllen = sizeof(cmsg_buffer),
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering };
84129d46cd6e95e142973da93aede4c7433c9600Lennart Poettering struct cmsghdr *cmsg;
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen uint32_t group = 0;
9df3ba6c6cb65eecec06f39dfe85a3596cedac4eTom Gundersen int r;
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen assert(fd >= 0);
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen assert(iov);
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen if (r < 0) {
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen /* no data */
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen if (errno == ENOBUFS)
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen log_debug("rtnl: kernel receive buffer overrun");
4e0b8b17a7465653f4e7b819dad5f8e30d64c0c4Tom Gundersen else if (errno == EAGAIN)
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering log_debug("rtnl: no data in socket");
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering }
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering if (sender.nl.nl_pid != 0) {
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering /* not from the kernel, ignore */
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering log_debug("rtnl: ignoring message from portid %"PRIu32, sender.nl.nl_pid);
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering if (peek) {
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering /* drop the message */
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen r = recvmsg(fd, &msg, 0);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen if (r < 0)
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen }
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return 0;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen }
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen CMSG_FOREACH(cmsg, &msg) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen if (cmsg->cmsg_level == SOL_NETLINK &&
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen cmsg->cmsg_type == NETLINK_PKTINFO &&
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen /* multi-cast group */
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen group = pktinfo->group;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen }
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen }
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen if (_group)
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen *_group = group;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return r;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen}
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen/* On success, the number of bytes received is returned and *ret points to the received message
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen * which has a valid header and the correct size.
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen * If nothing useful was received 0 is returned.
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen * On failure, a negative error code is returned.
b652d4a2099d1c167584dcc1d179d47c58dc38a2Lennart Poettering */
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersenint socket_read_message(sd_netlink *rtnl) {
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen _cleanup_netlink_message_unref_ sd_netlink_message *first = NULL;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen struct iovec iov = {};
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen uint32_t group = 0;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen bool multi_part = false, done = false;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen struct nlmsghdr *new_msg;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen size_t len;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen int r;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen unsigned i = 0;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen assert(rtnl);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen assert(rtnl->rbuffer);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen /* read nothing, just get the pending message size */
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen r = socket_recv_message(rtnl->fd, &iov, NULL, true);
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen if (r <= 0)
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen return r;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen else
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen len = (size_t)r;
be808ea083fa07271116b4519c3c27fd20c5f077Tom Gundersen
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering /* make room for the pending message */
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering if (!greedy_realloc((void **)&rtnl->rbuffer,
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering &rtnl->rbuffer_allocated,
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering len, sizeof(uint8_t)))
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering return -ENOMEM;
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering iov.iov_base = rtnl->rbuffer;
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering iov.iov_len = rtnl->rbuffer_allocated;
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering /* read the pending message */
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering r = socket_recv_message(rtnl->fd, &iov, &group, false);
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering if (r <= 0)
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering return r;
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering else
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering len = (size_t)r;
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering if (len > rtnl->rbuffer_allocated)
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering /* message did not fit in read buffer */
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering return -EIO;
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering multi_part = true;
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering for (i = 0; i < rtnl->rqueue_partial_size; i++) {
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering rtnl->rbuffer->nlmsg_seq) {
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering first = rtnl->rqueue_partial[i];
519ef04651b07a547f010d6462603669d7fde4e5Lennart Poettering break;
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen }
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering }
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering }
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL;
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen const NLType *nl_type;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt /* not broadcast and not for us */
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering continue;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (new_msg->nlmsg_type == NLMSG_NOOP)
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering /* silently drop noop messages */
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering continue;
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering if (new_msg->nlmsg_type == NLMSG_DONE) {
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering /* finished reading multi-part message */
87f5a19343acf8ba697acc5a62bdb1a2b8c9eda3Lennart Poettering done = true;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt /* if first is not defined, put NLMSG_DONE into the receive queue. */
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt if (first)
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt continue;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt }
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering /* check that we support this message type */
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering r = type_system_get_type(&type_system_root, &nl_type, new_msg->nlmsg_type);
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (r < 0) {
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (r == -EOPNOTSUPP)
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering log_debug("sd-netlink: ignored message with unknown type: %i",
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering new_msg->nlmsg_type);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering continue;
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering }
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering /* check that the size matches the message type */
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering if (new_msg->nlmsg_len < NLMSG_LENGTH(type_get_size(nl_type))) {
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering log_debug("sd-netlink: message larger than expected, dropping");
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering continue;
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering }
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering r = message_new_empty(rtnl, &m);
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering if (r < 0)
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering return r;
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering m->broadcast = !!group;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering m->hdr = memdup(new_msg, new_msg->nlmsg_len);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (!m->hdr)
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering return -ENOMEM;
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering /* seal and parse the top-level message */
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering r = sd_netlink_message_rewind(m);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (r < 0)
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering return r;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering /* push the message onto the multi-part message stack */
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering if (first)
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering m->next = first;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering first = m;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering m = NULL;
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering }
636e813dc98ea40c58c6c85bc5e7e3c9f0904ea2Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (len)
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering log_debug("sd-netlink: discarding %zu bytes of incoming message", len);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (!first)
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering return 0;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (!multi_part || done) {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering /* we got a complete message, push it on the read queue */
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering r = rtnl_rqueue_make_room(rtnl);
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (r < 0)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering return r;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering rtnl->rqueue[rtnl->rqueue_size ++] = first;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering first = NULL;
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering if (multi_part && (i < rtnl->rqueue_partial_size)) {
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering /* remove the message form the partial read queue */
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering sizeof(sd_netlink_message*) * (rtnl->rqueue_partial_size - i - 1));
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering rtnl->rqueue_partial_size --;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering }
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering return 1;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering } else {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering /* we only got a partial multi-part message, push it on the
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering partial read queue */
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering if (i < rtnl->rqueue_partial_size) {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering rtnl->rqueue_partial[i] = first;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering } else {
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering r = rtnl_rqueue_partial_make_room(rtnl);
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering if (r < 0)
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering return r;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering }
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering first = NULL;
0eac462399c8e87bcce252cf058eba9f2678f2bdLennart Poettering
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering return 0;
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering }
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering}
f2f1dbe50fea13abadc9c1e845a29031b90b40f3Lennart Poettering