1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/in.h>
23 #include <netinet/ether.h>
26 #include <linux/netlink.h>
27 #include <linux/veth.h>
30 #include <linux/if_tunnel.h>
31 #include <linux/if_bridge.h>
38 #include "rtnl-util.h"
39 #include "rtnl-internal.h"
40 #include "rtnl-types.h"
42 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
43 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
45 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
48 assert_return(ret, -EINVAL);
50 /* Note that 'rtnl' is curretly unused, if we start using it internally
51 we must take care to avoid problems due to mutual references between
52 busses and their queued messages. See sd-bus.
55 m = new0(sd_rtnl_message, 1);
59 m->n_ref = REFCNT_INIT;
68 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
69 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
70 const NLType *nl_type;
74 r = type_system_get_type(NULL, &nl_type, type);
78 assert(nl_type->type == NLA_NESTED);
80 r = message_new_empty(rtnl, &m);
84 size = NLMSG_SPACE(nl_type->size);
86 assert(size >= sizeof(struct nlmsghdr));
87 m->hdr = malloc0(size);
91 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
93 m->container_type_system[0] = nl_type->type_system;
94 m->hdr->nlmsg_len = size;
95 m->hdr->nlmsg_type = type;
103 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
106 assert_return(m, -EINVAL);
107 assert_return(m->hdr, -EINVAL);
108 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
110 rtm = NLMSG_DATA(m->hdr);
112 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
113 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
116 rtm->rtm_dst_len = prefixlen;
121 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
124 assert_return(m, -EINVAL);
125 assert_return(m->hdr, -EINVAL);
126 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
128 rtm = NLMSG_DATA(m->hdr);
130 rtm->rtm_scope = scope;
135 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
136 uint16_t nlmsg_type, unsigned char rtm_family) {
140 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
141 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
142 assert_return(ret, -EINVAL);
144 r = message_new(rtnl, ret, nlmsg_type);
148 if (nlmsg_type == RTM_NEWROUTE)
149 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
151 rtm = NLMSG_DATA((*ret)->hdr);
153 rtm->rtm_family = rtm_family;
154 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
155 rtm->rtm_type = RTN_UNICAST;
156 rtm->rtm_table = RT_TABLE_MAIN;
157 rtm->rtm_protocol = RTPROT_BOOT;
162 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
163 struct ifinfomsg *ifi;
165 assert_return(m, -EINVAL);
166 assert_return(m->hdr, -EINVAL);
167 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
168 assert_return(change, -EINVAL);
170 ifi = NLMSG_DATA(m->hdr);
172 ifi->ifi_flags = flags;
173 ifi->ifi_change = change;
178 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
179 struct ifinfomsg *ifi;
181 assert_return(m, -EINVAL);
182 assert_return(m->hdr, -EINVAL);
183 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
185 ifi = NLMSG_DATA(m->hdr);
187 ifi->ifi_type = type;
192 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
193 uint16_t nlmsg_type, int index) {
194 struct ifinfomsg *ifi;
197 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
198 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
199 assert_return(ret, -EINVAL);
201 r = message_new(rtnl, ret, nlmsg_type);
205 if (nlmsg_type == RTM_NEWLINK)
206 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
208 ifi = NLMSG_DATA((*ret)->hdr);
210 ifi->ifi_family = AF_UNSPEC;
211 ifi->ifi_index = index;
216 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
217 struct ifaddrmsg *ifa;
219 assert_return(m, -EINVAL);
220 assert_return(m->hdr, -EINVAL);
221 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
223 ifa = NLMSG_DATA(m->hdr);
225 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
226 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
229 ifa->ifa_prefixlen = prefixlen;
234 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
235 struct ifaddrmsg *ifa;
237 assert_return(m, -EINVAL);
238 assert_return(m->hdr, -EINVAL);
239 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
241 ifa = NLMSG_DATA(m->hdr);
243 ifa->ifa_flags = flags;
248 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
249 struct ifaddrmsg *ifa;
251 assert_return(m, -EINVAL);
252 assert_return(m->hdr, -EINVAL);
253 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
255 ifa = NLMSG_DATA(m->hdr);
257 ifa->ifa_scope = scope;
262 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, unsigned char *family) {
263 struct ifaddrmsg *ifa;
265 assert_return(m, -EINVAL);
266 assert_return(m->hdr, -EINVAL);
267 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
268 assert_return(family, -EINVAL);
270 ifa = NLMSG_DATA(m->hdr);
272 *family = ifa->ifa_family;
277 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
278 struct ifaddrmsg *ifa;
280 assert_return(m, -EINVAL);
281 assert_return(m->hdr, -EINVAL);
282 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
283 assert_return(scope, -EINVAL);
285 ifa = NLMSG_DATA(m->hdr);
287 *scope = ifa->ifa_scope;
292 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
293 struct ifaddrmsg *ifa;
295 assert_return(m, -EINVAL);
296 assert_return(m->hdr, -EINVAL);
297 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
298 assert_return(flags, -EINVAL);
300 ifa = NLMSG_DATA(m->hdr);
302 *flags = ifa->ifa_flags;
307 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
308 struct ifaddrmsg *ifa;
310 assert_return(m, -EINVAL);
311 assert_return(m->hdr, -EINVAL);
312 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
313 assert_return(ifindex, -EINVAL);
315 ifa = NLMSG_DATA(m->hdr);
317 *ifindex = ifa->ifa_index;
322 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
323 uint16_t nlmsg_type, int index,
324 unsigned char family) {
325 struct ifaddrmsg *ifa;
328 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
329 assert_return(index > 0, -EINVAL);
330 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
331 assert_return(ret, -EINVAL);
333 r = message_new(rtnl, ret, nlmsg_type);
337 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
338 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
340 ifa = NLMSG_DATA((*ret)->hdr);
342 ifa->ifa_index = index;
343 ifa->ifa_family = family;
344 if (family == AF_INET)
345 ifa->ifa_prefixlen = 32;
346 else if (family == AF_INET6)
347 ifa->ifa_prefixlen = 128;
352 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
353 int index, unsigned char family) {
356 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
360 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
365 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
367 assert_se(REFCNT_INC(m->n_ref) >= 2);
372 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
373 if (m && REFCNT_DEC(m->n_ref) <= 0) {
378 for (i = 0; i <= m->n_containers; i++)
379 free(m->rta_offset_tb[i]);
381 sd_rtnl_message_unref(m->next);
389 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
390 assert_return(m, -EINVAL);
391 assert_return(type, -EINVAL);
393 *type = m->hdr->nlmsg_type;
398 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
399 assert_return(m, -EINVAL);
401 return !m->hdr->nlmsg_pid;
404 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
405 struct ifinfomsg *ifi;
407 assert_return(m, -EINVAL);
408 assert_return(m->hdr, -EINVAL);
409 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
410 assert_return(ifindex, -EINVAL);
412 ifi = NLMSG_DATA(m->hdr);
414 *ifindex = ifi->ifi_index;
419 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
420 struct ifinfomsg *ifi;
422 assert_return(m, -EINVAL);
423 assert_return(m->hdr, -EINVAL);
424 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
425 assert_return(flags, -EINVAL);
427 ifi = NLMSG_DATA(m->hdr);
429 *flags = ifi->ifi_flags;
434 /* If successful the updated message will be correctly aligned, if
435 unsuccessful the old message is untouched. */
436 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
437 uint32_t rta_length, message_length;
438 struct nlmsghdr *new_hdr;
446 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
447 assert(!data || data_length > 0);
448 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
450 /* get the size of the new rta attribute (with padding at the end) */
451 rta_length = RTA_LENGTH(data_length);
453 /* get the new message size (with padding at the end) */
454 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
456 /* realloc to fit the new attribute */
457 new_hdr = realloc(m->hdr, message_length);
462 /* get pointer to the attribute we are about to add */
463 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
465 /* if we are inside containers, extend them */
466 for (i = 0; i < m->n_containers; i++)
467 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
469 /* fill in the attribute */
470 rta->rta_type = type;
471 rta->rta_len = rta_length;
473 //TODO: simply return this value rather than check for !data
474 /* this is the start of a new container */
475 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
477 /* we don't deal with the case where the user lies about the type
478 * and gives us too little data (so don't do that)
480 padding = mempcpy(RTA_DATA(rta), data, data_length);
481 /* make sure also the padding at the end of the message is initialized */
483 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
486 /* update message size */
487 m->hdr->nlmsg_len = message_length;
492 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
496 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
500 if (type->type != data_type)
506 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
510 assert_return(m, -EINVAL);
511 assert_return(!m->sealed, -EPERM);
512 assert_return(data, -EINVAL);
514 r = message_attribute_has_type(m, type, NLA_STRING);
521 length = strnlen(data, size);
525 length = strlen(data);
527 r = add_rtattr(m, type, data, length + 1);
534 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
537 assert_return(m, -EINVAL);
538 assert_return(!m->sealed, -EPERM);
540 r = message_attribute_has_type(m, type, NLA_U8);
544 r = add_rtattr(m, type, &data, sizeof(uint8_t));
552 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
555 assert_return(m, -EINVAL);
556 assert_return(!m->sealed, -EPERM);
558 r = message_attribute_has_type(m, type, NLA_U16);
562 r = add_rtattr(m, type, &data, sizeof(uint16_t));
569 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
572 assert_return(m, -EINVAL);
573 assert_return(!m->sealed, -EPERM);
575 r = message_attribute_has_type(m, type, NLA_U32);
579 r = add_rtattr(m, type, &data, sizeof(uint32_t));
586 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
589 assert_return(m, -EINVAL);
590 assert_return(!m->sealed, -EPERM);
591 assert_return(data, -EINVAL);
593 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
597 r = add_rtattr(m, type, data, sizeof(struct in_addr));
604 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
607 assert_return(m, -EINVAL);
608 assert_return(!m->sealed, -EPERM);
609 assert_return(data, -EINVAL);
611 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
615 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
622 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
625 assert_return(m, -EINVAL);
626 assert_return(!m->sealed, -EPERM);
627 assert_return(data, -EINVAL);
629 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
633 r = add_rtattr(m, type, data, ETH_ALEN);
640 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
643 assert_return(m, -EINVAL);
644 assert_return(!m->sealed, -EPERM);
645 assert_return(info, -EINVAL);
647 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
651 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
658 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
662 assert_return(m, -EINVAL);
663 assert_return(!m->sealed, -EPERM);
665 r = message_attribute_has_type(m, type, NLA_NESTED);
671 r = type_system_get_type_system(m->container_type_system[m->n_containers],
672 &m->container_type_system[m->n_containers + 1],
677 r = add_rtattr(m, type, NULL, size);
684 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
685 const NLTypeSystemUnion *type_system_union;
688 assert_return(m, -EINVAL);
689 assert_return(!m->sealed, -EPERM);
691 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
695 r = type_system_union_get_type_system(type_system_union,
696 &m->container_type_system[m->n_containers + 1],
701 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
705 /* do we evere need non-null size */
706 r = add_rtattr(m, type, NULL, 0);
714 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
715 assert_return(m, -EINVAL);
716 assert_return(!m->sealed, -EPERM);
717 assert_return(m->n_containers > 0, -EINVAL);
719 m->container_type_system[m->n_containers] = NULL;
725 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
728 assert_return(m, -EINVAL);
729 assert_return(m->sealed, -EPERM);
730 assert_return(data, -EINVAL);
731 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
732 assert(m->rta_offset_tb[m->n_containers]);
733 assert(type < m->rta_tb_size[m->n_containers]);
735 if(!m->rta_offset_tb[m->n_containers][type])
738 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
740 *data = RTA_DATA(rta);
742 return RTA_PAYLOAD(rta);
745 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
749 r = message_attribute_has_type(m, type, NLA_STRING);
753 r = rtnl_message_read_internal(m, type, &attr_data);
756 else if (strnlen(attr_data, r) >= (size_t) r)
759 *data = (char *) attr_data;
764 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
768 r = message_attribute_has_type(m, type, NLA_U8);
772 r = rtnl_message_read_internal(m, type, &attr_data);
775 else if ((size_t) r < sizeof(uint8_t))
778 *data = *(uint8_t *) attr_data;
783 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
787 r = message_attribute_has_type(m, type, NLA_U16);
791 r = rtnl_message_read_internal(m, type, &attr_data);
794 else if ((size_t) r < sizeof(uint16_t))
797 *data = *(uint16_t *) attr_data;
802 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
806 r = message_attribute_has_type(m, type, NLA_U32);
810 r = rtnl_message_read_internal(m, type, &attr_data);
813 else if ((size_t)r < sizeof(uint32_t))
816 *data = *(uint32_t *) attr_data;
821 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
825 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
829 r = rtnl_message_read_internal(m, type, &attr_data);
832 else if ((size_t)r < sizeof(struct ether_addr))
835 memcpy(data, attr_data, sizeof(struct ether_addr));
840 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
844 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
848 r = rtnl_message_read_internal(m, type, &attr_data);
851 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
854 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
859 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
863 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
867 r = rtnl_message_read_internal(m, type, &attr_data);
870 else if ((size_t)r < sizeof(struct in_addr))
873 memcpy(data, attr_data, sizeof(struct in_addr));
878 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
882 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
886 r = rtnl_message_read_internal(m, type, &attr_data);
889 else if ((size_t)r < sizeof(struct in6_addr))
892 memcpy(data, attr_data, sizeof(struct in6_addr));
897 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
898 const NLType *nl_type;
899 const NLTypeSystem *type_system;
904 assert_return(m, -EINVAL);
905 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
907 r = type_system_get_type(m->container_type_system[m->n_containers],
913 if (nl_type->type == NLA_NESTED) {
914 r = type_system_get_type_system(m->container_type_system[m->n_containers],
919 } else if (nl_type->type == NLA_UNION) {
920 const NLTypeSystemUnion *type_system_union;
923 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
929 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
933 r = type_system_union_get_type_system(type_system_union,
941 r = rtnl_message_read_internal(m, type, &container);
949 r = rtnl_message_parse(m,
950 &m->rta_offset_tb[m->n_containers],
951 &m->rta_tb_size[m->n_containers],
960 m->container_type_system[m->n_containers] = type_system;
965 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
966 assert_return(m, -EINVAL);
967 assert_return(m->sealed, -EINVAL);
968 assert_return(m->n_containers > 0, -EINVAL);
970 free(m->rta_offset_tb[m->n_containers]);
971 m->rta_offset_tb[m->n_containers] = NULL;
972 m->container_type_system[m->n_containers] = NULL;
979 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
983 return m->hdr->nlmsg_seq;
986 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
987 struct nlmsgerr *err;
989 assert_return(m, -EINVAL);
990 assert_return(m->hdr, -EINVAL);
992 if (m->hdr->nlmsg_type != NLMSG_ERROR)
995 err = NLMSG_DATA(m->hdr);
1000 int rtnl_message_parse(sd_rtnl_message *m,
1001 size_t **rta_offset_tb,
1002 unsigned short *rta_tb_size,
1005 unsigned int rt_len) {
1006 unsigned short type;
1009 tb = new0(size_t, max + 1);
1013 *rta_tb_size = max + 1;
1015 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1016 type = rta->rta_type;
1018 /* if the kernel is newer than the headers we used
1019 when building, we ignore out-of-range attributes
1025 log_debug("rtnl: message parse - overwriting repeated attribute");
1027 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1030 *rta_offset_tb = tb;
1035 /* returns the number of bytes sent, or a negative error code */
1036 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1039 struct sockaddr_nl nl;
1041 .nl.nl_family = AF_NETLINK,
1049 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1050 0, &addr.sa, sizeof(addr));
1052 return (errno == EAGAIN) ? 0 : -errno;
1057 /* On success, the number of bytes received is returned and *ret points to the received message
1058 * which has a valid header and the correct size.
1059 * If nothing useful was received 0 is returned.
1060 * On failure, a negative error code is returned.
1062 int socket_read_message(sd_rtnl *rtnl) {
1063 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1064 sd_rtnl_message *previous = NULL;
1065 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
1066 struct iovec iov = {};
1067 struct msghdr msg = {
1070 .msg_control = cred_buffer,
1071 .msg_controllen = sizeof(cred_buffer),
1073 struct cmsghdr *cmsg;
1075 struct nlmsghdr *new_msg;
1080 assert(rtnl->rbuffer);
1082 iov.iov_base = rtnl->rbuffer;
1083 iov.iov_len = rtnl->rbuffer_allocated;
1085 /* peek at the pending message header to get the message size */
1086 r = recvmsg(rtnl->fd, &msg, MSG_PEEK);
1089 return (errno == EAGAIN) ? 0 : -errno;
1091 /* connection was closed by the kernel */
1093 else if ((size_t)r < sizeof(struct nlmsghdr))
1096 /* make room for the pending message */
1097 if (!greedy_realloc((void **)&rtnl->rbuffer,
1098 &rtnl->rbuffer_allocated,
1099 rtnl->rbuffer->nlmsg_len,
1103 iov.iov_base = rtnl->rbuffer;
1104 iov.iov_len = rtnl->rbuffer_allocated;
1106 r = recvmsg(rtnl->fd, &msg, MSG_TRUNC);
1109 return (errno == EAGAIN) ? 0 : -errno;
1111 /* connection was closed by the kernel */
1116 if (len > rtnl->rbuffer_allocated)
1117 /* message did not fit in read buffer */
1120 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1121 if (cmsg->cmsg_level == SOL_SOCKET &&
1122 cmsg->cmsg_type == SCM_CREDENTIALS &&
1123 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1124 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1126 /* from the kernel */
1127 if (ucred->uid == 0 && ucred->pid == 0) {
1135 /* not from the kernel, ignore */
1138 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1139 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1140 const NLType *nl_type;
1142 if (new_msg->nlmsg_pid && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1143 /* not broadcast and not for us */
1146 /* silently drop noop messages */
1147 if (new_msg->nlmsg_type == NLMSG_NOOP)
1150 /* finished reading multi-part message */
1151 if (new_msg->nlmsg_type == NLMSG_DONE)
1154 /* check that we support this message type */
1155 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1158 log_debug("sd-rtnl: ignored message with unknown type: %u",
1159 new_msg->nlmsg_type);
1164 /* check that the size matches the message type */
1165 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1168 r = message_new_empty(rtnl, &m);
1172 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1176 /* seal and parse the top-level message */
1177 r = sd_rtnl_message_rewind(m);
1191 ret += new_msg->nlmsg_len;
1193 /* not a multi-part message, so stop reading*/
1194 if (!(new_msg->nlmsg_flags & NLM_F_MULTI))
1198 r = rtnl_rqueue_make_room(rtnl);
1202 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1208 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1213 assert_return(m, -EINVAL);
1215 /* don't allow appending to message once parsed */
1217 rtnl_message_seal(m);
1219 for (i = 1; i <= m->n_containers; i++) {
1220 free(m->rta_offset_tb[i]);
1221 m->rta_offset_tb[i] = NULL;
1222 m->rta_tb_size[i] = 0;
1223 m->container_type_system[i] = NULL;
1226 m->n_containers = 0;
1228 if (m->rta_offset_tb[0]) {
1229 /* top-level attributes have already been parsed */
1235 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1239 if (type->type == NLA_NESTED) {
1240 const NLTypeSystem *type_system = type->type_system;
1242 assert(type_system);
1244 m->container_type_system[0] = type_system;
1246 r = rtnl_message_parse(m,
1247 &m->rta_offset_tb[m->n_containers],
1248 &m->rta_tb_size[m->n_containers],
1250 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1251 NLMSG_ALIGN(type->size)),
1252 NLMSG_PAYLOAD(m->hdr, type->size));
1260 void rtnl_message_seal(sd_rtnl_message *m) {
1267 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1268 assert_return(m, NULL);