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, int rtm_family,
137 unsigned char rtm_protocol) {
141 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
142 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
143 assert_return(ret, -EINVAL);
145 r = message_new(rtnl, ret, nlmsg_type);
149 if (nlmsg_type == RTM_NEWROUTE)
150 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
152 rtm = NLMSG_DATA((*ret)->hdr);
154 rtm->rtm_family = rtm_family;
155 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
156 rtm->rtm_type = RTN_UNICAST;
157 rtm->rtm_table = RT_TABLE_MAIN;
158 rtm->rtm_protocol = rtm_protocol;
163 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
164 struct ifinfomsg *ifi;
166 assert_return(m, -EINVAL);
167 assert_return(m->hdr, -EINVAL);
168 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
169 assert_return(change, -EINVAL);
171 ifi = NLMSG_DATA(m->hdr);
173 ifi->ifi_flags = flags;
174 ifi->ifi_change = change;
179 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
180 struct ifinfomsg *ifi;
182 assert_return(m, -EINVAL);
183 assert_return(m->hdr, -EINVAL);
184 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
186 ifi = NLMSG_DATA(m->hdr);
188 ifi->ifi_type = type;
193 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
194 uint16_t nlmsg_type, int index) {
195 struct ifinfomsg *ifi;
198 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
199 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
200 assert_return(ret, -EINVAL);
202 r = message_new(rtnl, ret, nlmsg_type);
206 if (nlmsg_type == RTM_NEWLINK)
207 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
209 ifi = NLMSG_DATA((*ret)->hdr);
211 ifi->ifi_family = AF_UNSPEC;
212 ifi->ifi_index = index;
217 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
218 assert_return(m, -EINVAL);
219 assert_return(m->hdr, -EINVAL);
220 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
221 m->hdr->nlmsg_type == RTM_GETADDR ||
222 m->hdr->nlmsg_type == RTM_GETROUTE,
226 m->hdr->nlmsg_flags |= NLM_F_DUMP;
228 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
233 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
234 struct ifaddrmsg *ifa;
236 assert_return(m, -EINVAL);
237 assert_return(m->hdr, -EINVAL);
238 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
240 ifa = NLMSG_DATA(m->hdr);
242 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
243 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
246 ifa->ifa_prefixlen = prefixlen;
251 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
252 struct ifaddrmsg *ifa;
254 assert_return(m, -EINVAL);
255 assert_return(m->hdr, -EINVAL);
256 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
258 ifa = NLMSG_DATA(m->hdr);
260 ifa->ifa_flags = flags;
265 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
266 struct ifaddrmsg *ifa;
268 assert_return(m, -EINVAL);
269 assert_return(m->hdr, -EINVAL);
270 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
272 ifa = NLMSG_DATA(m->hdr);
274 ifa->ifa_scope = scope;
279 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
280 struct ifaddrmsg *ifa;
282 assert_return(m, -EINVAL);
283 assert_return(m->hdr, -EINVAL);
284 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
285 assert_return(family, -EINVAL);
287 ifa = NLMSG_DATA(m->hdr);
289 *family = ifa->ifa_family;
294 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
295 struct ifaddrmsg *ifa;
297 assert_return(m, -EINVAL);
298 assert_return(m->hdr, -EINVAL);
299 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
300 assert_return(prefixlen, -EINVAL);
302 ifa = NLMSG_DATA(m->hdr);
304 *prefixlen = ifa->ifa_prefixlen;
309 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
310 struct ifaddrmsg *ifa;
312 assert_return(m, -EINVAL);
313 assert_return(m->hdr, -EINVAL);
314 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
315 assert_return(scope, -EINVAL);
317 ifa = NLMSG_DATA(m->hdr);
319 *scope = ifa->ifa_scope;
324 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
325 struct ifaddrmsg *ifa;
327 assert_return(m, -EINVAL);
328 assert_return(m->hdr, -EINVAL);
329 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
330 assert_return(flags, -EINVAL);
332 ifa = NLMSG_DATA(m->hdr);
334 *flags = ifa->ifa_flags;
339 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
340 struct ifaddrmsg *ifa;
342 assert_return(m, -EINVAL);
343 assert_return(m->hdr, -EINVAL);
344 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
345 assert_return(ifindex, -EINVAL);
347 ifa = NLMSG_DATA(m->hdr);
349 *ifindex = ifa->ifa_index;
354 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
355 uint16_t nlmsg_type, int index,
357 struct ifaddrmsg *ifa;
360 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
361 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
363 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
364 family == AF_INET || family == AF_INET6, -EINVAL);
365 assert_return(ret, -EINVAL);
367 r = message_new(rtnl, ret, nlmsg_type);
371 if (nlmsg_type == RTM_GETADDR)
372 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
374 ifa = NLMSG_DATA((*ret)->hdr);
376 ifa->ifa_index = index;
377 ifa->ifa_family = family;
378 if (family == AF_INET)
379 ifa->ifa_prefixlen = 32;
380 else if (family == AF_INET6)
381 ifa->ifa_prefixlen = 128;
386 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
387 int index, int family) {
390 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
394 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
399 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
401 assert_se(REFCNT_INC(m->n_ref) >= 2);
406 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
407 if (m && REFCNT_DEC(m->n_ref) <= 0) {
412 for (i = 0; i <= m->n_containers; i++)
413 free(m->rta_offset_tb[i]);
415 sd_rtnl_message_unref(m->next);
423 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
424 assert_return(m, -EINVAL);
425 assert_return(type, -EINVAL);
427 *type = m->hdr->nlmsg_type;
432 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
433 assert_return(m, -EINVAL);
435 return !m->hdr->nlmsg_pid;
438 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
439 struct ifinfomsg *ifi;
441 assert_return(m, -EINVAL);
442 assert_return(m->hdr, -EINVAL);
443 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
444 assert_return(ifindex, -EINVAL);
446 ifi = NLMSG_DATA(m->hdr);
448 *ifindex = ifi->ifi_index;
453 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
454 struct ifinfomsg *ifi;
456 assert_return(m, -EINVAL);
457 assert_return(m->hdr, -EINVAL);
458 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
459 assert_return(flags, -EINVAL);
461 ifi = NLMSG_DATA(m->hdr);
463 *flags = ifi->ifi_flags;
468 /* If successful the updated message will be correctly aligned, if
469 unsuccessful the old message is untouched. */
470 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
472 size_t message_length, padding_length;
473 struct nlmsghdr *new_hdr;
482 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
483 assert(!data || data_length);
485 /* get offset of the new attribute */
486 offset = m->hdr->nlmsg_len;
488 /* get the size of the new rta attribute (with padding at the end) */
489 rta_length = RTA_LENGTH(data_length);
491 /* get the new message size (with padding at the end) */
492 message_length = offset + RTA_ALIGN(rta_length);
494 /* realloc to fit the new attribute */
495 new_hdr = realloc(m->hdr, message_length);
500 /* get pointer to the attribute we are about to add */
501 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
503 /* if we are inside containers, extend them */
504 for (i = 0; i < m->n_containers; i++)
505 GET_CONTAINER(m, i)->rta_len += message_length - offset;
507 /* fill in the attribute */
508 rta->rta_type = type;
509 rta->rta_len = rta_length;
511 /* we don't deal with the case where the user lies about the type
512 * and gives us too little data (so don't do that)
514 padding = mempcpy(RTA_DATA(rta), data, data_length);
516 /* if no data was passed, make sure we still initialize the padding
517 note that we can have data_length > 0 (used by some containers) */
518 padding = RTA_DATA(rta);
522 /* make sure also the padding at the end of the message is initialized */
523 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
524 memzero(padding, padding_length);
526 /* update message size */
527 m->hdr->nlmsg_len = message_length;
532 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
536 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
540 if (type->type != data_type)
546 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
550 assert_return(m, -EINVAL);
551 assert_return(!m->sealed, -EPERM);
552 assert_return(data, -EINVAL);
554 r = message_attribute_has_type(m, type, NLA_STRING);
561 length = strnlen(data, size);
565 length = strlen(data);
567 r = add_rtattr(m, type, data, length + 1);
574 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
577 assert_return(m, -EINVAL);
578 assert_return(!m->sealed, -EPERM);
580 r = message_attribute_has_type(m, type, NLA_U8);
584 r = add_rtattr(m, type, &data, sizeof(uint8_t));
592 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
595 assert_return(m, -EINVAL);
596 assert_return(!m->sealed, -EPERM);
598 r = message_attribute_has_type(m, type, NLA_U16);
602 r = add_rtattr(m, type, &data, sizeof(uint16_t));
609 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
612 assert_return(m, -EINVAL);
613 assert_return(!m->sealed, -EPERM);
615 r = message_attribute_has_type(m, type, NLA_U32);
619 r = add_rtattr(m, type, &data, sizeof(uint32_t));
626 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
629 assert_return(m, -EINVAL);
630 assert_return(!m->sealed, -EPERM);
631 assert_return(data, -EINVAL);
633 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
637 r = add_rtattr(m, type, data, sizeof(struct in_addr));
644 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
647 assert_return(m, -EINVAL);
648 assert_return(!m->sealed, -EPERM);
649 assert_return(data, -EINVAL);
651 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
655 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
662 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
665 assert_return(m, -EINVAL);
666 assert_return(!m->sealed, -EPERM);
667 assert_return(data, -EINVAL);
669 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
673 r = add_rtattr(m, type, data, ETH_ALEN);
680 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
683 assert_return(m, -EINVAL);
684 assert_return(!m->sealed, -EPERM);
685 assert_return(info, -EINVAL);
687 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
691 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
698 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
702 assert_return(m, -EINVAL);
703 assert_return(!m->sealed, -EPERM);
704 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
706 r = message_attribute_has_type(m, type, NLA_NESTED);
712 r = type_system_get_type_system(m->container_type_system[m->n_containers],
713 &m->container_type_system[m->n_containers + 1],
718 r = add_rtattr(m, type, NULL, size);
722 m->container_offsets[m->n_containers ++] = r;
727 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
728 const NLTypeSystemUnion *type_system_union;
731 assert_return(m, -EINVAL);
732 assert_return(!m->sealed, -EPERM);
734 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
738 r = type_system_union_get_type_system(type_system_union,
739 &m->container_type_system[m->n_containers + 1],
744 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
748 /* do we evere need non-null size */
749 r = add_rtattr(m, type, NULL, 0);
753 m->container_offsets[m->n_containers ++] = r;
759 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
760 assert_return(m, -EINVAL);
761 assert_return(!m->sealed, -EPERM);
762 assert_return(m->n_containers > 0, -EINVAL);
764 m->container_type_system[m->n_containers] = NULL;
770 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
773 assert_return(m, -EINVAL);
774 assert_return(m->sealed, -EPERM);
775 assert_return(data, -EINVAL);
776 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
777 assert(m->rta_offset_tb[m->n_containers]);
778 assert(type < m->rta_tb_size[m->n_containers]);
780 if(!m->rta_offset_tb[m->n_containers][type])
783 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
785 *data = RTA_DATA(rta);
787 return RTA_PAYLOAD(rta);
790 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
794 r = message_attribute_has_type(m, type, NLA_STRING);
798 r = rtnl_message_read_internal(m, type, &attr_data);
801 else if (strnlen(attr_data, r) >= (size_t) r)
804 *data = (const char *) attr_data;
809 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
813 r = message_attribute_has_type(m, type, NLA_U8);
817 r = rtnl_message_read_internal(m, type, &attr_data);
820 else if ((size_t) r < sizeof(uint8_t))
823 *data = *(uint8_t *) attr_data;
828 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
832 r = message_attribute_has_type(m, type, NLA_U16);
836 r = rtnl_message_read_internal(m, type, &attr_data);
839 else if ((size_t) r < sizeof(uint16_t))
842 *data = *(uint16_t *) attr_data;
847 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
851 r = message_attribute_has_type(m, type, NLA_U32);
855 r = rtnl_message_read_internal(m, type, &attr_data);
858 else if ((size_t)r < sizeof(uint32_t))
861 *data = *(uint32_t *) attr_data;
866 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
870 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
874 r = rtnl_message_read_internal(m, type, &attr_data);
877 else if ((size_t)r < sizeof(struct ether_addr))
880 memcpy(data, attr_data, sizeof(struct ether_addr));
885 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
889 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
893 r = rtnl_message_read_internal(m, type, &attr_data);
896 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
899 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
904 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
908 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
912 r = rtnl_message_read_internal(m, type, &attr_data);
915 else if ((size_t)r < sizeof(struct in_addr))
918 memcpy(data, attr_data, sizeof(struct in_addr));
923 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
927 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
931 r = rtnl_message_read_internal(m, type, &attr_data);
934 else if ((size_t)r < sizeof(struct in6_addr))
937 memcpy(data, attr_data, sizeof(struct in6_addr));
942 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
943 const NLType *nl_type;
944 const NLTypeSystem *type_system;
949 assert_return(m, -EINVAL);
950 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
952 r = type_system_get_type(m->container_type_system[m->n_containers],
958 if (nl_type->type == NLA_NESTED) {
959 r = type_system_get_type_system(m->container_type_system[m->n_containers],
964 } else if (nl_type->type == NLA_UNION) {
965 const NLTypeSystemUnion *type_system_union;
968 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
974 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
978 r = type_system_union_get_type_system(type_system_union,
986 r = rtnl_message_read_internal(m, type, &container);
994 r = rtnl_message_parse(m,
995 &m->rta_offset_tb[m->n_containers],
996 &m->rta_tb_size[m->n_containers],
1005 m->container_type_system[m->n_containers] = type_system;
1010 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1011 assert_return(m, -EINVAL);
1012 assert_return(m->sealed, -EINVAL);
1013 assert_return(m->n_containers > 0, -EINVAL);
1015 free(m->rta_offset_tb[m->n_containers]);
1016 m->rta_offset_tb[m->n_containers] = NULL;
1017 m->container_type_system[m->n_containers] = NULL;
1024 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1028 return m->hdr->nlmsg_seq;
1031 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1032 struct nlmsgerr *err;
1034 assert_return(m, -EINVAL);
1035 assert_return(m->hdr, -EINVAL);
1037 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1040 err = NLMSG_DATA(m->hdr);
1045 int rtnl_message_parse(sd_rtnl_message *m,
1046 size_t **rta_offset_tb,
1047 unsigned short *rta_tb_size,
1050 unsigned int rt_len) {
1051 unsigned short type;
1054 tb = new0(size_t, max + 1);
1058 *rta_tb_size = max + 1;
1060 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1061 type = rta->rta_type;
1063 /* if the kernel is newer than the headers we used
1064 when building, we ignore out-of-range attributes
1070 log_debug("rtnl: message parse - overwriting repeated attribute");
1072 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1075 *rta_offset_tb = tb;
1080 /* returns the number of bytes sent, or a negative error code */
1081 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1084 struct sockaddr_nl nl;
1086 .nl.nl_family = AF_NETLINK,
1094 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1095 0, &addr.sa, sizeof(addr));
1097 return (errno == EAGAIN) ? 0 : -errno;
1102 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1103 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1104 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1105 struct msghdr msg = {
1108 .msg_control = cred_buffer,
1109 .msg_controllen = sizeof(cred_buffer),
1111 struct cmsghdr *cmsg;
1119 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1122 return (errno == EAGAIN) ? 0 : -errno;
1124 /* connection was closed by the kernel */
1127 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1128 if (cmsg->cmsg_level == SOL_SOCKET &&
1129 cmsg->cmsg_type == SCM_CREDENTIALS &&
1130 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1131 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1133 /* from the kernel */
1134 if (ucred->uid == 0 && ucred->pid == 0)
1136 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1137 cmsg->cmsg_type == NETLINK_PKTINFO &&
1138 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1139 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1141 /* multi-cast group */
1142 group = pktinfo->group;
1147 /* not from the kernel, ignore */
1156 /* On success, the number of bytes received is returned and *ret points to the received message
1157 * which has a valid header and the correct size.
1158 * If nothing useful was received 0 is returned.
1159 * On failure, a negative error code is returned.
1161 int socket_read_message(sd_rtnl *rtnl) {
1162 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1163 struct iovec iov = {};
1165 bool multi_part = false, done = false;
1166 struct nlmsghdr *new_msg;
1172 assert(rtnl->rbuffer);
1173 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1175 /* read nothing, just get the pending message size */
1176 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1182 /* make room for the pending message */
1183 if (!greedy_realloc((void **)&rtnl->rbuffer,
1184 &rtnl->rbuffer_allocated,
1185 len, sizeof(uint8_t)))
1188 iov.iov_base = rtnl->rbuffer;
1189 iov.iov_len = rtnl->rbuffer_allocated;
1191 /* read the pending message */
1192 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1198 if (len > rtnl->rbuffer_allocated)
1199 /* message did not fit in read buffer */
1202 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1205 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1206 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1207 rtnl->rbuffer->nlmsg_seq) {
1208 first = rtnl->rqueue_partial[i];
1214 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1215 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1216 const NLType *nl_type;
1218 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1219 /* not broadcast and not for us */
1222 if (new_msg->nlmsg_type == NLMSG_NOOP)
1223 /* silently drop noop messages */
1226 if (new_msg->nlmsg_type == NLMSG_DONE) {
1227 /* finished reading multi-part message */
1232 /* check that we support this message type */
1233 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1236 log_debug("sd-rtnl: ignored message with unknown type: %u",
1237 new_msg->nlmsg_type);
1242 /* check that the size matches the message type */
1243 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1246 r = message_new_empty(rtnl, &m);
1250 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1254 /* seal and parse the top-level message */
1255 r = sd_rtnl_message_rewind(m);
1259 /* push the message onto the multi-part message stack */
1267 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1272 if (!multi_part || done) {
1273 /* we got a complete message, push it on the read queue */
1274 r = rtnl_rqueue_make_room(rtnl);
1278 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1281 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1282 /* remove the message form the partial read queue */
1283 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1284 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1285 rtnl->rqueue_partial_size --;
1290 /* we only got a partial multi-part message, push it on the
1291 partial read queue */
1292 if (i < rtnl->rqueue_partial_size) {
1293 rtnl->rqueue_partial[i] = first;
1295 r = rtnl_rqueue_partial_make_room(rtnl);
1299 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1307 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1312 assert_return(m, -EINVAL);
1314 /* don't allow appending to message once parsed */
1316 rtnl_message_seal(m);
1318 for (i = 1; i <= m->n_containers; i++) {
1319 free(m->rta_offset_tb[i]);
1320 m->rta_offset_tb[i] = NULL;
1321 m->rta_tb_size[i] = 0;
1322 m->container_type_system[i] = NULL;
1325 m->n_containers = 0;
1327 if (m->rta_offset_tb[0]) {
1328 /* top-level attributes have already been parsed */
1334 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1338 if (type->type == NLA_NESTED) {
1339 const NLTypeSystem *type_system = type->type_system;
1341 assert(type_system);
1343 m->container_type_system[0] = type_system;
1345 r = rtnl_message_parse(m,
1346 &m->rta_offset_tb[m->n_containers],
1347 &m->rta_tb_size[m->n_containers],
1349 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1350 NLMSG_ALIGN(type->size)),
1351 NLMSG_PAYLOAD(m->hdr, type->size));
1359 void rtnl_message_seal(sd_rtnl_message *m) {
1366 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1367 assert_return(m, NULL);