netlink-socket.c revision 9c5a882b7fc256ddc0b227677fa06546f0e944a8
b66914021bd429f41311d2909a7e9289866da7fdnd/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b66914021bd429f41311d2909a7e9289866da7fdnd This file is part of systemd.
031b91a62d25106ae69d4693475c79618dd5e884fielding Copyright 2013 Tom Gundersen <teg@jklm.no>
031b91a62d25106ae69d4693475c79618dd5e884fielding systemd is free software; you can redistribute it and/or modify it
031b91a62d25106ae69d4693475c79618dd5e884fielding under the terms of the GNU Lesser General Public License as published by
031b91a62d25106ae69d4693475c79618dd5e884fielding the Free Software Foundation; either version 2.1 of the License, or
031b91a62d25106ae69d4693475c79618dd5e884fielding (at your option) any later version.
b66914021bd429f41311d2909a7e9289866da7fdnd systemd is distributed in the hope that it will be useful, but
b66914021bd429f41311d2909a7e9289866da7fdnd WITHOUT ANY WARRANTY; without even the implied warranty of
b66914021bd429f41311d2909a7e9289866da7fdnd MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b66914021bd429f41311d2909a7e9289866da7fdnd Lesser General Public License for more details.
b66914021bd429f41311d2909a7e9289866da7fdnd You should have received a copy of the GNU Lesser General Public License
b66914021bd429f41311d2909a7e9289866da7fdnd along with systemd; If not, see <http://www.gnu.org/licenses/>.
eed2a23d9b5986937f1e2b1c120be97744508a72nd fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, family);
eed2a23d9b5986937f1e2b1c120be97744508a72nd unsigned i, j;
eed2a23d9b5986937f1e2b1c120be97744508a72nd r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, NULL, &len);
eed2a23d9b5986937f1e2b1c120be97744508a72nd if (r < 0) {
eed2a23d9b5986937f1e2b1c120be97744508a72nd r = getsockopt(nl->fd, SOL_NETLINK, NETLINK_LIST_MEMBERSHIPS, groups, &len);
eed2a23d9b5986937f1e2b1c120be97744508a72nd if (r < 0)
4930be147adf9e3f6d3ca9313a6524f9bf654b2dnd r = hashmap_ensure_allocated(&nl->broadcast_group_refs, NULL);
4930be147adf9e3f6d3ca9313a6524f9bf654b2dnd if (r < 0)
4930be147adf9e3f6d3ca9313a6524f9bf654b2dnd for (i = 0; i < len; i++) {
eed2a23d9b5986937f1e2b1c120be97744508a72nd r = hashmap_put(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(1));
eed2a23d9b5986937f1e2b1c120be97744508a72nd if (r < 0)
eed2a23d9b5986937f1e2b1c120be97744508a72nd r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_PKTINFO, &one, sizeof(one));
9963f91528694fb21e93da8584c31f226c6de97akess if (r < 0)
b51bf223f42d43ca6b1b33c95124edcfa5a871a4nd /* ignore EINVAL to allow opening an already bound socket */
eed2a23d9b5986937f1e2b1c120be97744508a72nd if (r < 0)
eed2a23d9b5986937f1e2b1c120be97744508a72ndstatic unsigned broadcast_group_get_ref(sd_netlink *nl, unsigned group) {
eed2a23d9b5986937f1e2b1c120be97744508a72nd return PTR_TO_UINT(hashmap_get(nl->broadcast_group_refs, UINT_TO_PTR(group)));
4930be147adf9e3f6d3ca9313a6524f9bf654b2dndstatic int broadcast_group_set_ref(sd_netlink *nl, unsigned group, unsigned n_ref) {
eed2a23d9b5986937f1e2b1c120be97744508a72nd r = hashmap_replace(nl->broadcast_group_refs, UINT_TO_PTR(group), UINT_TO_PTR(n_ref));
eed2a23d9b5986937f1e2b1c120be97744508a72nd if (r < 0)
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3ndstatic int broadcast_group_join(sd_netlink *nl, unsigned group) {
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd r = setsockopt(nl->fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group));
f1110149b5b6c28ecc39d1958d98ad9cfa8e41f3nd if (r < 0)
unsigned n_ref;
n_ref ++;
return -errno;
unsigned n_ref;
n_ref --;
if (n_ref > 0)
} addr = {
ssize_t k;
assert(m);
return -errno;
if (peek) {
if (_group)
return -ENOMEM;
return -EIO;
multi_part = true;
for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
done = true;
if (first)
if (r == -EOPNOTSUPP)
if (!m->hdr)
return -ENOMEM;
r = sd_netlink_message_rewind(m);
if (first)
first = m;
m = NULL;
if (len)
if (!first)