rtnl-message.c revision 8facc3498ed037f842891ff55d1f60fe834f4ba0
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/***
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2013 Tom Gundersen <teg@jklm.no>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering***/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <netinet/in.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <netinet/ether.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <stdbool.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include <unistd.h>
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "refcnt.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "missing.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "sd-rtnl.h"
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "rtnl-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "rtnl-internal.h"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#include "rtnl-types.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
0d39fa9c69b97a2ceb156053deef69c0866c2b97Lennart Poettering#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
5f311f8c0e51e2f13773823feb6a71f7c6f2838cLennart Poettering
9bf3b53533cdc9b95c921b71da755401f223f765Lennart Poetteringstatic int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering sd_rtnl_message *m;
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering assert_return(ret, -EINVAL);
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering /* Note that 'rtnl' is currently unused, if we start using it internally
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering we must take care to avoid problems due to mutual references between
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek busses and their queued messages. See sd-bus.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m = new0(sd_rtnl_message, 1);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!m)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->n_ref = REFCNT_INIT;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->sealed = false;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *ret = m;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering return 0;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const NLType *nl_type;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size_t size;
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = type_system_get_type(NULL, &nl_type, type);
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen assert(nl_type->type == NLA_NESTED);
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = message_new_empty(rtnl, &m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering size = NLMSG_SPACE(nl_type->size);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(size >= sizeof(struct nlmsghdr));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->hdr = malloc0(size);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (!m->hdr)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ENOMEM;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek m->container_type_system[0] = nl_type->type_system;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->hdr->nlmsg_len = size;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->hdr->nlmsg_type = type;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt *ret = m;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt m = NULL;
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct rtmsg *rtm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rtm = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (rtm->rtm_family == AF_INET6 && prefixlen > 128))
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return -ERANGE;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rtm->rtm_dst_len = prefixlen;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_route_set_src_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct rtmsg *rtm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek rtm = NLMSG_DATA(m->hdr);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (rtm->rtm_family == AF_INET6 && prefixlen > 128))
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek return -ERANGE;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek rtm->rtm_src_len = prefixlen;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek return 0;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmekint sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct rtmsg *rtm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek rtm = NLMSG_DATA(m->hdr);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek rtm->rtm_scope = scope;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek return 0;
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek}
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmekint sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) {
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek struct rtmsg *rtm;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_return(m, -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert_return(family, -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek rtm = NLMSG_DATA(m->hdr);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek *family = rtm->rtm_family;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek return 0;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek}
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmekint sd_rtnl_message_route_get_dst_prefixlen(sd_rtnl_message *m, unsigned char *dst_len) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek struct rtmsg *rtm;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert_return(m, -EINVAL);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert_return(dst_len, -EINVAL);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek rtm = NLMSG_DATA(m->hdr);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek *dst_len = rtm->rtm_dst_len;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek return 0;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek}
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmekint sd_rtnl_message_route_get_src_prefixlen(sd_rtnl_message *m, unsigned char *src_len) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek struct rtmsg *rtm;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert_return(m, -EINVAL);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek assert_return(src_len, -EINVAL);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek rtm = NLMSG_DATA(m->hdr);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek *src_len = rtm->rtm_src_len;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint16_t nlmsg_type, int rtm_family,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned char rtm_protocol) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek struct rtmsg *rtm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(ret, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = message_new(rtnl, ret, nlmsg_type);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (r < 0)
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek if (nlmsg_type == RTM_NEWROUTE)
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek rtm = NLMSG_DATA((*ret)->hdr);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek rtm->rtm_family = rtm_family;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rtm->rtm_scope = RT_SCOPE_UNIVERSE;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rtm->rtm_type = RTN_UNICAST;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rtm->rtm_table = RT_TABLE_MAIN;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering rtm->rtm_protocol = rtm_protocol;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_neigh_set_flags(sd_rtnl_message *m, uint8_t flags) {
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt struct ndmsg *ndm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ndm = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ndm->ndm_flags |= flags;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_neigh_set_state(sd_rtnl_message *m, uint16_t state) {
d3b6d0c21ea5a0d15ec6dbd8b8d179138b7463bcZbigniew Jędrzejewski-Szmek struct ndmsg *ndm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ndm = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ndm->ndm_state |= state;
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_neigh_get_flags(sd_rtnl_message *m, uint8_t *flags) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ndmsg *ndm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek assert_return(m, -EINVAL);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ndm = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *flags = ndm->ndm_flags;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
97b11eedff9d2e17101ad453caf9e48b73246719David Herrmannint sd_rtnl_message_neigh_get_state(sd_rtnl_message *m, uint16_t *state) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ndmsg *ndm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek ndm = NLMSG_DATA(m->hdr);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek *state = ndm->ndm_state;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ndmsg *ndm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(family, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ndm = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *family = ndm->ndm_family;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ndmsg *ndm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(index, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ndm = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *index = ndm->ndm_ifindex;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ndmsg *ndm;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(ndm_family == AF_INET ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ndm_family == AF_INET6 ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ndm_family == PF_BRIDGE, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(ret, -EINVAL);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = message_new(rtnl, ret, nlmsg_type);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (nlmsg_type == RTM_NEWNEIGH)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek ndm = NLMSG_DATA((*ret)->hdr);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek ndm->ndm_family = ndm_family;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek ndm->ndm_ifindex = index;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekint sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek struct ifinfomsg *ifi;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(m, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt assert_return(change, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek ifi = NLMSG_DATA(m->hdr);
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt ifi->ifi_flags = flags;
eb56eb9b40950f1edcffdb7313f8de4f8572a6d5Michal Schmidt ifi->ifi_change = change;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekint sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek struct ifinfomsg *ifi;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(m, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek ifi = NLMSG_DATA(m->hdr);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek ifi->ifi_type = type;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekint sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek struct ifinfomsg *ifi;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(m, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek ifi = NLMSG_DATA(m->hdr);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering ifi->ifi_family = family;
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekint sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek uint16_t nlmsg_type, int index) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek struct ifinfomsg *ifi;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek int r;
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(ret, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek r = message_new(rtnl, ret, nlmsg_type);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (r < 0)
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poettering return r;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (nlmsg_type == RTM_NEWLINK)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifi = NLMSG_DATA((*ret)->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifi->ifi_family = AF_UNSPEC;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek ifi->ifi_index = index;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekint sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek m->hdr->nlmsg_type == RTM_GETADDR ||
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek m->hdr->nlmsg_type == RTM_GETROUTE ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering m->hdr->nlmsg_type == RTM_GETNEIGH,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (dump)
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek m->hdr->nlmsg_flags |= NLM_F_DUMP;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmekint sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek struct ifaddrmsg *ifa;
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering assert_return(m, -EINVAL);
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (ifa->ifa_family == AF_INET6 && prefixlen > 128))
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek return -ERANGE;
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa->ifa_prefixlen = prefixlen;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ifaddrmsg *ifa;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek ifa = NLMSG_DATA(m->hdr);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa->ifa_flags = flags;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
7ff7394d9e4e9189c30fd018235e6b1728c6f2d0Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek struct ifaddrmsg *ifa;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt assert_return(m, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa->ifa_scope = scope;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek struct ifaddrmsg *ifa;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(family, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *family = ifa->ifa_family;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering struct ifaddrmsg *ifa;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering assert_return(prefixlen, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *prefixlen = ifa->ifa_prefixlen;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ifaddrmsg *ifa;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering assert_return(m, -EINVAL);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering assert_return(scope, -EINVAL);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering ifa = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *scope = ifa->ifa_scope;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ifaddrmsg *ifa;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(flags, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *flags = ifa->ifa_flags;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ifaddrmsg *ifa;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(ifindex, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering *ifindex = ifa->ifa_index;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering uint16_t nlmsg_type, int index,
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering int family) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ifaddrmsg *ifa;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering index > 0, -EINVAL);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering family == AF_INET || family == AF_INET6, -EINVAL);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering assert_return(ret, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = message_new(rtnl, ret, nlmsg_type);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
a7f7d1bde43fc825c49afea3f946f5b4b3d563e0Harald Hoyer if (nlmsg_type == RTM_GETADDR)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa = NLMSG_DATA((*ret)->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa->ifa_index = index;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa->ifa_family = family;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (family == AF_INET)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa->ifa_prefixlen = 32;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (family == AF_INET6)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifa->ifa_prefixlen = 128;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int index, int family) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering int r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return r;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringsd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (m)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_se(REFCNT_INC(m->n_ref) >= 2);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return m;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringsd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (m && REFCNT_DEC(m->n_ref) == 0) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unsigned i;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering for (i = 0; i <= m->n_containers; i++)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(m->rta_offset_tb[i]);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_rtnl_message_unref(m->next);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering free(m);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering }
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return NULL;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(type, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *type = m->hdr->nlmsg_type;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return 0;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek}
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmekint sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert_return(m, -EINVAL);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return !m->hdr->nlmsg_pid;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek}
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmekint sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek struct ifinfomsg *ifi;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert_return(m, -EINVAL);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert_return(m->hdr, -EINVAL);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_return(ifindex, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifi = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *ifindex = ifi->ifi_index;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ifinfomsg *ifi;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(flags, -EINVAL);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifi = NLMSG_DATA(m->hdr);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *flags = ifi->ifi_flags;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return 0;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering}
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringint sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering struct ifinfomsg *ifi;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(m->hdr, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_return(type, -EINVAL);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering ifi = NLMSG_DATA(m->hdr);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering *type = ifi->ifi_type;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek return 0;
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek}
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek/* If successful the updated message will be correctly aligned, if
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek unsuccessful the old message is untouched. */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmekstatic int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek uint32_t rta_length;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek size_t message_length, padding_length;
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer struct nlmsghdr *new_hdr;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek struct rtattr *rta;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek char *padding;
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek unsigned i;
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering int offset;
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykryn
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert(m);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert(m->hdr);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert(!m->sealed);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert(!data || data_length);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering /* get offset of the new attribute */
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering offset = m->hdr->nlmsg_len;
464264ac5a35b655065c5d95b8d8ffbbc7ff3bcfLukas Nykryn
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* get the size of the new rta attribute (with padding at the end) */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek rta_length = RTA_LENGTH(data_length);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* get the new message size (with padding at the end) */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek message_length = offset + RTA_ALIGN(rta_length);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* realloc to fit the new attribute */
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek new_hdr = realloc(m->hdr, message_length);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek if (!new_hdr)
return -ENOMEM;
m->hdr = new_hdr;
/* get pointer to the attribute we are about to add */
rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
/* if we are inside containers, extend them */
for (i = 0; i < m->n_containers; i++)
GET_CONTAINER(m, i)->rta_len += message_length - offset;
/* fill in the attribute */
rta->rta_type = type;
rta->rta_len = rta_length;
if (data)
/* we don't deal with the case where the user lies about the type
* and gives us too little data (so don't do that)
*/
padding = mempcpy(RTA_DATA(rta), data, data_length);
else {
/* if no data was passed, make sure we still initialize the padding
note that we can have data_length > 0 (used by some containers) */
padding = RTA_DATA(rta);
}
/* make sure also the padding at the end of the message is initialized */
padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
memzero(padding, padding_length);
/* update message size */
m->hdr->nlmsg_len = message_length;
return offset;
}
static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
const NLType *type;
int r;
r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
if (r < 0)
return r;
if (type->type != data_type)
return -EINVAL;
return type->size;
}
int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
size_t length, size;
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
assert_return(data, -EINVAL);
r = message_attribute_has_type(m, type, NLA_STRING);
if (r < 0)
return r;
else
size = (size_t)r;
if (size) {
length = strnlen(data, size+1);
if (length > size)
return -EINVAL;
} else
length = strlen(data);
r = add_rtattr(m, type, data, length + 1);
if (r < 0)
return r;
return 0;
}
int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
r = message_attribute_has_type(m, type, NLA_U8);
if (r < 0)
return r;
r = add_rtattr(m, type, &data, sizeof(uint8_t));
if (r < 0)
return r;
return 0;
}
int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
r = message_attribute_has_type(m, type, NLA_U16);
if (r < 0)
return r;
r = add_rtattr(m, type, &data, sizeof(uint16_t));
if (r < 0)
return r;
return 0;
}
int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
r = message_attribute_has_type(m, type, NLA_U32);
if (r < 0)
return r;
r = add_rtattr(m, type, &data, sizeof(uint32_t));
if (r < 0)
return r;
return 0;
}
int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
assert_return(data, -EINVAL);
r = message_attribute_has_type(m, type, NLA_IN_ADDR);
if (r < 0)
return r;
r = add_rtattr(m, type, data, sizeof(struct in_addr));
if (r < 0)
return r;
return 0;
}
int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
assert_return(data, -EINVAL);
r = message_attribute_has_type(m, type, NLA_IN_ADDR);
if (r < 0)
return r;
r = add_rtattr(m, type, data, sizeof(struct in6_addr));
if (r < 0)
return r;
return 0;
}
int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
assert_return(data, -EINVAL);
r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
if (r < 0)
return r;
r = add_rtattr(m, type, data, ETH_ALEN);
if (r < 0)
return r;
return 0;
}
int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
assert_return(info, -EINVAL);
r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
if (r < 0)
return r;
r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
if (r < 0)
return r;
return 0;
}
int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
size_t size;
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
r = message_attribute_has_type(m, type, NLA_NESTED);
if (r < 0)
return r;
else
size = (size_t)r;
r = type_system_get_type_system(m->container_type_system[m->n_containers],
&m->container_type_system[m->n_containers + 1],
type);
if (r < 0)
return r;
r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
if (r < 0)
return r;
m->container_offsets[m->n_containers ++] = r;
return 0;
}
int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
const NLTypeSystemUnion *type_system_union;
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
if (r < 0)
return r;
r = type_system_union_get_type_system(type_system_union,
&m->container_type_system[m->n_containers + 1],
key);
if (r < 0)
return r;
r = sd_rtnl_message_append_string(m, type_system_union->match, key);
if (r < 0)
return r;
/* do we evere need non-null size */
r = add_rtattr(m, type, NULL, 0);
if (r < 0)
return r;
m->container_offsets[m->n_containers ++] = r;
return 0;
}
int sd_rtnl_message_close_container(sd_rtnl_message *m) {
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
assert_return(m->n_containers > 0, -EINVAL);
m->container_type_system[m->n_containers] = NULL;
m->n_containers --;
return 0;
}
int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
struct rtattr *rta;
assert_return(m, -EINVAL);
assert_return(m->sealed, -EPERM);
assert_return(data, -EINVAL);
assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
assert(m->rta_offset_tb[m->n_containers]);
assert(type < m->rta_tb_size[m->n_containers]);
if(!m->rta_offset_tb[m->n_containers][type])
return -ENODATA;
rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
*data = RTA_DATA(rta);
return RTA_PAYLOAD(rta);
}
int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
int r;
void *attr_data;
assert_return(m, -EINVAL);
r = message_attribute_has_type(m, type, NLA_STRING);
if (r < 0)
return r;
r = rtnl_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if (strnlen(attr_data, r) >= (size_t) r)
return -EIO;
if (data)
*data = (const char *) attr_data;
return 0;
}
int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
int r;
void *attr_data;
assert_return(m, -EINVAL);
r = message_attribute_has_type(m, type, NLA_U8);
if (r < 0)
return r;
r = rtnl_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t) r < sizeof(uint8_t))
return -EIO;
if (data)
*data = *(uint8_t *) attr_data;
return 0;
}
int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
int r;
void *attr_data;
assert_return(m, -EINVAL);
r = message_attribute_has_type(m, type, NLA_U16);
if (r < 0)
return r;
r = rtnl_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t) r < sizeof(uint16_t))
return -EIO;
if (data)
*data = *(uint16_t *) attr_data;
return 0;
}
int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
int r;
void *attr_data;
assert_return(m, -EINVAL);
r = message_attribute_has_type(m, type, NLA_U32);
if (r < 0)
return r;
r = rtnl_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t)r < sizeof(uint32_t))
return -EIO;
if (data)
*data = *(uint32_t *) attr_data;
return 0;
}
int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
int r;
void *attr_data;
assert_return(m, -EINVAL);
r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
if (r < 0)
return r;
r = rtnl_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct ether_addr))
return -EIO;
if (data)
memcpy(data, attr_data, sizeof(struct ether_addr));
return 0;
}
int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
int r;
void *attr_data;
assert_return(m, -EINVAL);
r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
if (r < 0)
return r;
r = rtnl_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct ifa_cacheinfo))
return -EIO;
if (info)
memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
return 0;
}
int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
int r;
void *attr_data;
assert_return(m, -EINVAL);
r = message_attribute_has_type(m, type, NLA_IN_ADDR);
if (r < 0)
return r;
r = rtnl_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct in_addr))
return -EIO;
if (data)
memcpy(data, attr_data, sizeof(struct in_addr));
return 0;
}
int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
int r;
void *attr_data;
assert_return(m, -EINVAL);
r = message_attribute_has_type(m, type, NLA_IN_ADDR);
if (r < 0)
return r;
r = rtnl_message_read_internal(m, type, &attr_data);
if (r < 0)
return r;
else if ((size_t)r < sizeof(struct in6_addr))
return -EIO;
if (data)
memcpy(data, attr_data, sizeof(struct in6_addr));
return 0;
}
int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
const NLType *nl_type;
const NLTypeSystem *type_system;
void *container;
size_t size;
int r;
assert_return(m, -EINVAL);
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
r = type_system_get_type(m->container_type_system[m->n_containers],
&nl_type,
type);
if (r < 0)
return r;
if (nl_type->type == NLA_NESTED) {
r = type_system_get_type_system(m->container_type_system[m->n_containers],
&type_system,
type);
if (r < 0)
return r;
} else if (nl_type->type == NLA_UNION) {
const NLTypeSystemUnion *type_system_union;
const char *key;
r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
&type_system_union,
type);
if (r < 0)
return r;
r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
if (r < 0)
return r;
r = type_system_union_get_type_system(type_system_union,
&type_system,
key);
if (r < 0)
return r;
} else
return -EINVAL;
r = rtnl_message_read_internal(m, type, &container);
if (r < 0)
return r;
else
size = (size_t)r;
m->n_containers ++;
r = rtnl_message_parse(m,
&m->rta_offset_tb[m->n_containers],
&m->rta_tb_size[m->n_containers],
type_system->max,
container,
size);
if (r < 0) {
m->n_containers --;
return r;
}
m->container_type_system[m->n_containers] = type_system;
return 0;
}
int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
assert_return(m, -EINVAL);
assert_return(m->sealed, -EINVAL);
assert_return(m->n_containers > 0, -EINVAL);
free(m->rta_offset_tb[m->n_containers]);
m->rta_offset_tb[m->n_containers] = NULL;
m->container_type_system[m->n_containers] = NULL;
m->n_containers --;
return 0;
}
uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
assert(m);
assert(m->hdr);
return m->hdr->nlmsg_seq;
}
int sd_rtnl_message_is_error(sd_rtnl_message *m) {
assert_return(m, 0);
assert_return(m->hdr, 0);
return m->hdr->nlmsg_type == NLMSG_ERROR;
}
int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
struct nlmsgerr *err;
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
if (!sd_rtnl_message_is_error(m))
return 0;
err = NLMSG_DATA(m->hdr);
return err->error;
}
int rtnl_message_parse(sd_rtnl_message *m,
size_t **rta_offset_tb,
unsigned short *rta_tb_size,
int max,
struct rtattr *rta,
unsigned int rt_len) {
unsigned short type;
size_t *tb;
tb = new0(size_t, max + 1);
if(!tb)
return -ENOMEM;
*rta_tb_size = max + 1;
for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
type = RTA_TYPE(rta);
/* if the kernel is newer than the headers we used
when building, we ignore out-of-range attributes
*/
if (type > max)
continue;
if (tb[type])
log_debug("rtnl: message parse - overwriting repeated attribute");
tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
}
*rta_offset_tb = tb;
return 0;
}
/* returns the number of bytes sent, or a negative error code */
int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
union {
struct sockaddr sa;
struct sockaddr_nl nl;
} addr = {
.nl.nl_family = AF_NETLINK,
};
ssize_t k;
assert(nl);
assert(m);
assert(m->hdr);
k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
0, &addr.sa, sizeof(addr));
if (k < 0)
return (errno == EAGAIN) ? 0 : -errno;
return k;
}
static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
CMSG_SPACE(sizeof(struct nl_pktinfo))];
struct msghdr msg = {
.msg_iov = iov,
.msg_iovlen = 1,
.msg_control = cred_buffer,
.msg_controllen = sizeof(cred_buffer),
};
struct cmsghdr *cmsg;
uint32_t group = 0;
bool auth = false;
int r;
assert(fd >= 0);
assert(iov);
r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
if (r < 0) {
/* no data */
if (errno == ENOBUFS)
log_debug("rtnl: kernel receive buffer overrun");
else if (errno == EAGAIN)
log_debug("rtnl: no data in socket");
return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
} else if (r == 0)
/* connection was closed by the kernel */
return -ECONNRESET;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_CREDENTIALS &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
struct ucred *ucred = (void *)CMSG_DATA(cmsg);
/* from the kernel */
if (ucred->pid == 0)
auth = true;
else
log_debug("rtnl: ignoring message from pid %u", ucred->pid);
} else if (cmsg->cmsg_level == SOL_NETLINK &&
cmsg->cmsg_type == NETLINK_PKTINFO &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
/* multi-cast group */
group = pktinfo->group;
}
}
if (!auth) {
/* not from the kernel, ignore */
if (peek) {
/* drop the message */
r = recvmsg(fd, &msg, 0);
if (r < 0)
return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
}
return 0;
}
if (group)
*_group = group;
return r;
}
/* On success, the number of bytes received is returned and *ret points to the received message
* which has a valid header and the correct size.
* If nothing useful was received 0 is returned.
* On failure, a negative error code is returned.
*/
int socket_read_message(sd_rtnl *rtnl) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
struct iovec iov = {};
uint32_t group = 0;
bool multi_part = false, done = false;
struct nlmsghdr *new_msg;
size_t len;
int r;
unsigned i = 0;
assert(rtnl);
assert(rtnl->rbuffer);
assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
/* read nothing, just get the pending message size */
r = socket_recv_message(rtnl->fd, &iov, &group, true);
if (r <= 0)
return r;
else
len = (size_t)r;
/* make room for the pending message */
if (!greedy_realloc((void **)&rtnl->rbuffer,
&rtnl->rbuffer_allocated,
len, sizeof(uint8_t)))
return -ENOMEM;
iov.iov_base = rtnl->rbuffer;
iov.iov_len = rtnl->rbuffer_allocated;
/* read the pending message */
r = socket_recv_message(rtnl->fd, &iov, &group, false);
if (r <= 0)
return r;
else
len = (size_t)r;
if (len > rtnl->rbuffer_allocated)
/* message did not fit in read buffer */
return -EIO;
if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
multi_part = true;
for (i = 0; i < rtnl->rqueue_partial_size; i++) {
if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
rtnl->rbuffer->nlmsg_seq) {
first = rtnl->rqueue_partial[i];
break;
}
}
}
for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
_cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
const NLType *nl_type;
if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
/* not broadcast and not for us */
continue;
if (new_msg->nlmsg_type == NLMSG_NOOP)
/* silently drop noop messages */
continue;
if (new_msg->nlmsg_type == NLMSG_DONE) {
/* finished reading multi-part message */
done = true;
continue;
}
/* check that we support this message type */
r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
if (r < 0) {
if (r == -ENOTSUP)
log_debug("sd-rtnl: ignored message with unknown type: %i",
new_msg->nlmsg_type);
continue;
}
/* check that the size matches the message type */
if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
log_debug("sd-rtnl: message larger than expected, dropping");
continue;
}
r = message_new_empty(rtnl, &m);
if (r < 0)
return r;
m->hdr = memdup(new_msg, new_msg->nlmsg_len);
if (!m->hdr)
return -ENOMEM;
/* seal and parse the top-level message */
r = sd_rtnl_message_rewind(m);
if (r < 0)
return r;
/* push the message onto the multi-part message stack */
if (first)
m->next = first;
first = m;
m = NULL;
}
if (len)
log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
if (!first)
return 0;
if (!multi_part || done) {
/* we got a complete message, push it on the read queue */
r = rtnl_rqueue_make_room(rtnl);
if (r < 0)
return r;
rtnl->rqueue[rtnl->rqueue_size ++] = first;
first = NULL;
if (multi_part && (i < rtnl->rqueue_partial_size)) {
/* remove the message form the partial read queue */
memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
rtnl->rqueue_partial_size --;
}
return 1;
} else {
/* we only got a partial multi-part message, push it on the
partial read queue */
if (i < rtnl->rqueue_partial_size) {
rtnl->rqueue_partial[i] = first;
} else {
r = rtnl_rqueue_partial_make_room(rtnl);
if (r < 0)
return r;
rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
}
first = NULL;
return 0;
}
}
int sd_rtnl_message_rewind(sd_rtnl_message *m) {
const NLType *type;
unsigned i;
int r;
assert_return(m, -EINVAL);
/* don't allow appending to message once parsed */
if (!m->sealed)
rtnl_message_seal(m);
for (i = 1; i <= m->n_containers; i++) {
free(m->rta_offset_tb[i]);
m->rta_offset_tb[i] = NULL;
m->rta_tb_size[i] = 0;
m->container_type_system[i] = NULL;
}
m->n_containers = 0;
if (m->rta_offset_tb[0]) {
/* top-level attributes have already been parsed */
return 0;
}
assert(m->hdr);
r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
if (r < 0)
return r;
if (type->type == NLA_NESTED) {
const NLTypeSystem *type_system = type->type_system;
assert(type_system);
m->container_type_system[0] = type_system;
r = rtnl_message_parse(m,
&m->rta_offset_tb[m->n_containers],
&m->rta_tb_size[m->n_containers],
type_system->max,
(struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
NLMSG_ALIGN(type->size)),
NLMSG_PAYLOAD(m->hdr, type->size));
if (r < 0)
return r;
}
return 0;
}
void rtnl_message_seal(sd_rtnl_message *m) {
assert(m);
assert(!m->sealed);
m->sealed = true;
}
sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
assert_return(m, NULL);
return m->next;
}