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_APPEND;
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_request_dump(sd_rtnl_message *m, int dump) {
217 assert_return(m, -EINVAL);
218 assert_return(m->hdr, -EINVAL);
219 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
220 m->hdr->nlmsg_type == RTM_GETADDR ||
221 m->hdr->nlmsg_type == RTM_GETROUTE,
225 m->hdr->nlmsg_flags |= NLM_F_DUMP;
227 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
232 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
233 struct ifaddrmsg *ifa;
235 assert_return(m, -EINVAL);
236 assert_return(m->hdr, -EINVAL);
237 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
239 ifa = NLMSG_DATA(m->hdr);
241 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
242 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
245 ifa->ifa_prefixlen = prefixlen;
250 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
251 struct ifaddrmsg *ifa;
253 assert_return(m, -EINVAL);
254 assert_return(m->hdr, -EINVAL);
255 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
257 ifa = NLMSG_DATA(m->hdr);
259 ifa->ifa_flags = flags;
264 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
265 struct ifaddrmsg *ifa;
267 assert_return(m, -EINVAL);
268 assert_return(m->hdr, -EINVAL);
269 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
271 ifa = NLMSG_DATA(m->hdr);
273 ifa->ifa_scope = scope;
278 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, unsigned char *family) {
279 struct ifaddrmsg *ifa;
281 assert_return(m, -EINVAL);
282 assert_return(m->hdr, -EINVAL);
283 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
284 assert_return(family, -EINVAL);
286 ifa = NLMSG_DATA(m->hdr);
288 *family = ifa->ifa_family;
293 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
294 struct ifaddrmsg *ifa;
296 assert_return(m, -EINVAL);
297 assert_return(m->hdr, -EINVAL);
298 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
299 assert_return(scope, -EINVAL);
301 ifa = NLMSG_DATA(m->hdr);
303 *scope = ifa->ifa_scope;
308 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
309 struct ifaddrmsg *ifa;
311 assert_return(m, -EINVAL);
312 assert_return(m->hdr, -EINVAL);
313 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
314 assert_return(flags, -EINVAL);
316 ifa = NLMSG_DATA(m->hdr);
318 *flags = ifa->ifa_flags;
323 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
324 struct ifaddrmsg *ifa;
326 assert_return(m, -EINVAL);
327 assert_return(m->hdr, -EINVAL);
328 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
329 assert_return(ifindex, -EINVAL);
331 ifa = NLMSG_DATA(m->hdr);
333 *ifindex = ifa->ifa_index;
338 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
339 uint16_t nlmsg_type, int index,
340 unsigned char family) {
341 struct ifaddrmsg *ifa;
344 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
345 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
347 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
348 family == AF_INET || family == AF_INET6, -EINVAL);
349 assert_return(ret, -EINVAL);
351 r = message_new(rtnl, ret, nlmsg_type);
355 if (nlmsg_type == RTM_GETADDR)
356 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
358 ifa = NLMSG_DATA((*ret)->hdr);
360 ifa->ifa_index = index;
361 ifa->ifa_family = family;
362 if (family == AF_INET)
363 ifa->ifa_prefixlen = 32;
364 else if (family == AF_INET6)
365 ifa->ifa_prefixlen = 128;
370 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
371 int index, unsigned char family) {
374 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
378 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
383 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
385 assert_se(REFCNT_INC(m->n_ref) >= 2);
390 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
391 if (m && REFCNT_DEC(m->n_ref) <= 0) {
396 for (i = 0; i <= m->n_containers; i++)
397 free(m->rta_offset_tb[i]);
399 sd_rtnl_message_unref(m->next);
407 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
408 assert_return(m, -EINVAL);
409 assert_return(type, -EINVAL);
411 *type = m->hdr->nlmsg_type;
416 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
417 assert_return(m, -EINVAL);
419 return !m->hdr->nlmsg_pid;
422 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
423 struct ifinfomsg *ifi;
425 assert_return(m, -EINVAL);
426 assert_return(m->hdr, -EINVAL);
427 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
428 assert_return(ifindex, -EINVAL);
430 ifi = NLMSG_DATA(m->hdr);
432 *ifindex = ifi->ifi_index;
437 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
438 struct ifinfomsg *ifi;
440 assert_return(m, -EINVAL);
441 assert_return(m->hdr, -EINVAL);
442 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
443 assert_return(flags, -EINVAL);
445 ifi = NLMSG_DATA(m->hdr);
447 *flags = ifi->ifi_flags;
452 /* If successful the updated message will be correctly aligned, if
453 unsuccessful the old message is untouched. */
454 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
456 size_t message_length, padding_length;
457 struct nlmsghdr *new_hdr;
466 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
467 assert(!data || data_length);
469 /* get offset of the new attribute */
470 offset = m->hdr->nlmsg_len;
472 /* get the size of the new rta attribute (with padding at the end) */
473 rta_length = RTA_LENGTH(data_length);
475 /* get the new message size (with padding at the end) */
476 message_length = offset + RTA_ALIGN(rta_length);
478 /* realloc to fit the new attribute */
479 new_hdr = realloc(m->hdr, message_length);
484 /* get pointer to the attribute we are about to add */
485 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
487 /* if we are inside containers, extend them */
488 for (i = 0; i < m->n_containers; i++)
489 GET_CONTAINER(m, i)->rta_len += message_length - offset;
491 /* fill in the attribute */
492 rta->rta_type = type;
493 rta->rta_len = rta_length;
495 /* we don't deal with the case where the user lies about the type
496 * and gives us too little data (so don't do that)
498 padding = mempcpy(RTA_DATA(rta), data, data_length);
500 /* if no data was passed, make sure we still initialize the padding
501 note that we can have data_length > 0 (used by some containers) */
502 padding = RTA_DATA(rta);
506 /* make sure also the padding at the end of the message is initialized */
507 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
508 memzero(padding, padding_length);
510 /* update message size */
511 m->hdr->nlmsg_len = message_length;
516 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
520 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
524 if (type->type != data_type)
530 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
534 assert_return(m, -EINVAL);
535 assert_return(!m->sealed, -EPERM);
536 assert_return(data, -EINVAL);
538 r = message_attribute_has_type(m, type, NLA_STRING);
545 length = strnlen(data, size);
549 length = strlen(data);
551 r = add_rtattr(m, type, data, length + 1);
558 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
561 assert_return(m, -EINVAL);
562 assert_return(!m->sealed, -EPERM);
564 r = message_attribute_has_type(m, type, NLA_U8);
568 r = add_rtattr(m, type, &data, sizeof(uint8_t));
576 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
579 assert_return(m, -EINVAL);
580 assert_return(!m->sealed, -EPERM);
582 r = message_attribute_has_type(m, type, NLA_U16);
586 r = add_rtattr(m, type, &data, sizeof(uint16_t));
593 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
596 assert_return(m, -EINVAL);
597 assert_return(!m->sealed, -EPERM);
599 r = message_attribute_has_type(m, type, NLA_U32);
603 r = add_rtattr(m, type, &data, sizeof(uint32_t));
610 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
613 assert_return(m, -EINVAL);
614 assert_return(!m->sealed, -EPERM);
615 assert_return(data, -EINVAL);
617 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
621 r = add_rtattr(m, type, data, sizeof(struct in_addr));
628 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
631 assert_return(m, -EINVAL);
632 assert_return(!m->sealed, -EPERM);
633 assert_return(data, -EINVAL);
635 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
639 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
646 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
649 assert_return(m, -EINVAL);
650 assert_return(!m->sealed, -EPERM);
651 assert_return(data, -EINVAL);
653 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
657 r = add_rtattr(m, type, data, ETH_ALEN);
664 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
667 assert_return(m, -EINVAL);
668 assert_return(!m->sealed, -EPERM);
669 assert_return(info, -EINVAL);
671 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
675 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
682 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
686 assert_return(m, -EINVAL);
687 assert_return(!m->sealed, -EPERM);
688 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
690 r = message_attribute_has_type(m, type, NLA_NESTED);
696 r = type_system_get_type_system(m->container_type_system[m->n_containers],
697 &m->container_type_system[m->n_containers + 1],
702 r = add_rtattr(m, type, NULL, size);
706 m->container_offsets[m->n_containers ++] = r;
711 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
712 const NLTypeSystemUnion *type_system_union;
715 assert_return(m, -EINVAL);
716 assert_return(!m->sealed, -EPERM);
718 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
722 r = type_system_union_get_type_system(type_system_union,
723 &m->container_type_system[m->n_containers + 1],
728 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
732 /* do we evere need non-null size */
733 r = add_rtattr(m, type, NULL, 0);
737 m->container_offsets[m->n_containers ++] = r;
743 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
744 assert_return(m, -EINVAL);
745 assert_return(!m->sealed, -EPERM);
746 assert_return(m->n_containers > 0, -EINVAL);
748 m->container_type_system[m->n_containers] = NULL;
754 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
757 assert_return(m, -EINVAL);
758 assert_return(m->sealed, -EPERM);
759 assert_return(data, -EINVAL);
760 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
761 assert(m->rta_offset_tb[m->n_containers]);
762 assert(type < m->rta_tb_size[m->n_containers]);
764 if(!m->rta_offset_tb[m->n_containers][type])
767 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
769 *data = RTA_DATA(rta);
771 return RTA_PAYLOAD(rta);
774 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
778 r = message_attribute_has_type(m, type, NLA_STRING);
782 r = rtnl_message_read_internal(m, type, &attr_data);
785 else if (strnlen(attr_data, r) >= (size_t) r)
788 *data = (char *) attr_data;
793 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
797 r = message_attribute_has_type(m, type, NLA_U8);
801 r = rtnl_message_read_internal(m, type, &attr_data);
804 else if ((size_t) r < sizeof(uint8_t))
807 *data = *(uint8_t *) attr_data;
812 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
816 r = message_attribute_has_type(m, type, NLA_U16);
820 r = rtnl_message_read_internal(m, type, &attr_data);
823 else if ((size_t) r < sizeof(uint16_t))
826 *data = *(uint16_t *) attr_data;
831 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
835 r = message_attribute_has_type(m, type, NLA_U32);
839 r = rtnl_message_read_internal(m, type, &attr_data);
842 else if ((size_t)r < sizeof(uint32_t))
845 *data = *(uint32_t *) attr_data;
850 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
854 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
858 r = rtnl_message_read_internal(m, type, &attr_data);
861 else if ((size_t)r < sizeof(struct ether_addr))
864 memcpy(data, attr_data, sizeof(struct ether_addr));
869 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
873 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
877 r = rtnl_message_read_internal(m, type, &attr_data);
880 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
883 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
888 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
892 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
896 r = rtnl_message_read_internal(m, type, &attr_data);
899 else if ((size_t)r < sizeof(struct in_addr))
902 memcpy(data, attr_data, sizeof(struct in_addr));
907 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
911 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
915 r = rtnl_message_read_internal(m, type, &attr_data);
918 else if ((size_t)r < sizeof(struct in6_addr))
921 memcpy(data, attr_data, sizeof(struct in6_addr));
926 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
927 const NLType *nl_type;
928 const NLTypeSystem *type_system;
933 assert_return(m, -EINVAL);
934 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
936 r = type_system_get_type(m->container_type_system[m->n_containers],
942 if (nl_type->type == NLA_NESTED) {
943 r = type_system_get_type_system(m->container_type_system[m->n_containers],
948 } else if (nl_type->type == NLA_UNION) {
949 const NLTypeSystemUnion *type_system_union;
952 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
958 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
962 r = type_system_union_get_type_system(type_system_union,
970 r = rtnl_message_read_internal(m, type, &container);
978 r = rtnl_message_parse(m,
979 &m->rta_offset_tb[m->n_containers],
980 &m->rta_tb_size[m->n_containers],
989 m->container_type_system[m->n_containers] = type_system;
994 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
995 assert_return(m, -EINVAL);
996 assert_return(m->sealed, -EINVAL);
997 assert_return(m->n_containers > 0, -EINVAL);
999 free(m->rta_offset_tb[m->n_containers]);
1000 m->rta_offset_tb[m->n_containers] = NULL;
1001 m->container_type_system[m->n_containers] = NULL;
1008 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1012 return m->hdr->nlmsg_seq;
1015 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1016 struct nlmsgerr *err;
1018 assert_return(m, -EINVAL);
1019 assert_return(m->hdr, -EINVAL);
1021 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1024 err = NLMSG_DATA(m->hdr);
1029 int rtnl_message_parse(sd_rtnl_message *m,
1030 size_t **rta_offset_tb,
1031 unsigned short *rta_tb_size,
1034 unsigned int rt_len) {
1035 unsigned short type;
1038 tb = new0(size_t, max + 1);
1042 *rta_tb_size = max + 1;
1044 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1045 type = rta->rta_type;
1047 /* if the kernel is newer than the headers we used
1048 when building, we ignore out-of-range attributes
1054 log_debug("rtnl: message parse - overwriting repeated attribute");
1056 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1059 *rta_offset_tb = tb;
1064 /* returns the number of bytes sent, or a negative error code */
1065 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1068 struct sockaddr_nl nl;
1070 .nl.nl_family = AF_NETLINK,
1078 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1079 0, &addr.sa, sizeof(addr));
1081 return (errno == EAGAIN) ? 0 : -errno;
1086 /* On success, the number of bytes received is returned and *ret points to the received message
1087 * which has a valid header and the correct size.
1088 * If nothing useful was received 0 is returned.
1089 * On failure, a negative error code is returned.
1091 int socket_read_message(sd_rtnl *rtnl) {
1092 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1093 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
1094 struct iovec iov = {};
1095 struct msghdr msg = {
1098 .msg_control = cred_buffer,
1099 .msg_controllen = sizeof(cred_buffer),
1101 struct cmsghdr *cmsg;
1102 bool auth = false, multi_part = false, done = false;
1103 struct nlmsghdr *new_msg;
1109 assert(rtnl->rbuffer);
1110 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1112 /* read nothing, just get the pending message size */
1113 r = recvmsg(rtnl->fd, &msg, MSG_PEEK | MSG_TRUNC);
1116 return (errno == EAGAIN) ? 0 : -errno;
1118 /* connection was closed by the kernel */
1123 /* make room for the pending message */
1124 if (!greedy_realloc((void **)&rtnl->rbuffer,
1125 &rtnl->rbuffer_allocated,
1126 len, sizeof(uint8_t)))
1129 iov.iov_base = rtnl->rbuffer;
1130 iov.iov_len = rtnl->rbuffer_allocated;
1132 r = recvmsg(rtnl->fd, &msg, MSG_TRUNC);
1135 return (errno == EAGAIN) ? 0 : -errno;
1137 /* connection was closed by the kernel */
1142 if (len > rtnl->rbuffer_allocated)
1143 /* message did not fit in read buffer */
1146 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1147 if (cmsg->cmsg_level == SOL_SOCKET &&
1148 cmsg->cmsg_type == SCM_CREDENTIALS &&
1149 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1150 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1152 /* from the kernel */
1153 if (ucred->uid == 0 && ucred->pid == 0) {
1161 /* not from the kernel, ignore */
1164 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1167 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1168 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1169 rtnl->rbuffer->nlmsg_seq) {
1170 first = rtnl->rqueue_partial[i];
1176 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1177 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1178 const NLType *nl_type;
1180 if (new_msg->nlmsg_pid && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1181 /* not broadcast and not for us */
1184 if (new_msg->nlmsg_type == NLMSG_NOOP)
1185 /* silently drop noop messages */
1188 if (new_msg->nlmsg_type == NLMSG_DONE) {
1189 /* finished reading multi-part message */
1194 /* check that we support this message type */
1195 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1198 log_debug("sd-rtnl: ignored message with unknown type: %u",
1199 new_msg->nlmsg_type);
1204 /* check that the size matches the message type */
1205 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1208 r = message_new_empty(rtnl, &m);
1212 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1216 /* seal and parse the top-level message */
1217 r = sd_rtnl_message_rewind(m);
1221 /* push the message onto the multi-part message stack */
1229 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1234 if (!multi_part || done) {
1235 /* we got a complete message, push it on the read queue */
1236 r = rtnl_rqueue_make_room(rtnl);
1240 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1243 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1244 /* remove the message form the partial read queue */
1245 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1246 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1247 rtnl->rqueue_partial_size --;
1252 /* we only got a partial multi-part message, push it on the
1253 partial read queue */
1254 if (i < rtnl->rqueue_partial_size) {
1255 rtnl->rqueue_partial[i] = first;
1257 r = rtnl_rqueue_partial_make_room(rtnl);
1261 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1269 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1274 assert_return(m, -EINVAL);
1276 /* don't allow appending to message once parsed */
1278 rtnl_message_seal(m);
1280 for (i = 1; i <= m->n_containers; i++) {
1281 free(m->rta_offset_tb[i]);
1282 m->rta_offset_tb[i] = NULL;
1283 m->rta_tb_size[i] = 0;
1284 m->container_type_system[i] = NULL;
1287 m->n_containers = 0;
1289 if (m->rta_offset_tb[0]) {
1290 /* top-level attributes have already been parsed */
1296 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1300 if (type->type == NLA_NESTED) {
1301 const NLTypeSystem *type_system = type->type_system;
1303 assert(type_system);
1305 m->container_type_system[0] = type_system;
1307 r = rtnl_message_parse(m,
1308 &m->rta_offset_tb[m->n_containers],
1309 &m->rta_tb_size[m->n_containers],
1311 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1312 NLMSG_ALIGN(type->size)),
1313 NLMSG_PAYLOAD(m->hdr, type->size));
1321 void rtnl_message_seal(sd_rtnl_message *m) {
1328 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1329 assert_return(m, NULL);