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 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
469 struct ifinfomsg *ifi;
471 assert_return(m, -EINVAL);
472 assert_return(m->hdr, -EINVAL);
473 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
474 assert_return(type, -EINVAL);
476 ifi = NLMSG_DATA(m->hdr);
478 *type = ifi->ifi_type;
483 /* If successful the updated message will be correctly aligned, if
484 unsuccessful the old message is untouched. */
485 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
487 size_t message_length, padding_length;
488 struct nlmsghdr *new_hdr;
497 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
498 assert(!data || data_length);
500 /* get offset of the new attribute */
501 offset = m->hdr->nlmsg_len;
503 /* get the size of the new rta attribute (with padding at the end) */
504 rta_length = RTA_LENGTH(data_length);
506 /* get the new message size (with padding at the end) */
507 message_length = offset + RTA_ALIGN(rta_length);
509 /* realloc to fit the new attribute */
510 new_hdr = realloc(m->hdr, message_length);
515 /* get pointer to the attribute we are about to add */
516 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
518 /* if we are inside containers, extend them */
519 for (i = 0; i < m->n_containers; i++)
520 GET_CONTAINER(m, i)->rta_len += message_length - offset;
522 /* fill in the attribute */
523 rta->rta_type = type;
524 rta->rta_len = rta_length;
526 /* we don't deal with the case where the user lies about the type
527 * and gives us too little data (so don't do that)
529 padding = mempcpy(RTA_DATA(rta), data, data_length);
531 /* if no data was passed, make sure we still initialize the padding
532 note that we can have data_length > 0 (used by some containers) */
533 padding = RTA_DATA(rta);
537 /* make sure also the padding at the end of the message is initialized */
538 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
539 memzero(padding, padding_length);
541 /* update message size */
542 m->hdr->nlmsg_len = message_length;
547 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
551 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
555 if (type->type != data_type)
561 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
565 assert_return(m, -EINVAL);
566 assert_return(!m->sealed, -EPERM);
567 assert_return(data, -EINVAL);
569 r = message_attribute_has_type(m, type, NLA_STRING);
576 length = strnlen(data, size);
580 length = strlen(data);
582 r = add_rtattr(m, type, data, length + 1);
589 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
592 assert_return(m, -EINVAL);
593 assert_return(!m->sealed, -EPERM);
595 r = message_attribute_has_type(m, type, NLA_U8);
599 r = add_rtattr(m, type, &data, sizeof(uint8_t));
607 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
610 assert_return(m, -EINVAL);
611 assert_return(!m->sealed, -EPERM);
613 r = message_attribute_has_type(m, type, NLA_U16);
617 r = add_rtattr(m, type, &data, sizeof(uint16_t));
624 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
627 assert_return(m, -EINVAL);
628 assert_return(!m->sealed, -EPERM);
630 r = message_attribute_has_type(m, type, NLA_U32);
634 r = add_rtattr(m, type, &data, sizeof(uint32_t));
641 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
644 assert_return(m, -EINVAL);
645 assert_return(!m->sealed, -EPERM);
646 assert_return(data, -EINVAL);
648 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
652 r = add_rtattr(m, type, data, sizeof(struct in_addr));
659 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
662 assert_return(m, -EINVAL);
663 assert_return(!m->sealed, -EPERM);
664 assert_return(data, -EINVAL);
666 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
670 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
677 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
680 assert_return(m, -EINVAL);
681 assert_return(!m->sealed, -EPERM);
682 assert_return(data, -EINVAL);
684 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
688 r = add_rtattr(m, type, data, ETH_ALEN);
695 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
698 assert_return(m, -EINVAL);
699 assert_return(!m->sealed, -EPERM);
700 assert_return(info, -EINVAL);
702 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
706 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
713 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
717 assert_return(m, -EINVAL);
718 assert_return(!m->sealed, -EPERM);
719 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
721 r = message_attribute_has_type(m, type, NLA_NESTED);
727 r = type_system_get_type_system(m->container_type_system[m->n_containers],
728 &m->container_type_system[m->n_containers + 1],
733 r = add_rtattr(m, type, NULL, size);
737 m->container_offsets[m->n_containers ++] = r;
742 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
743 const NLTypeSystemUnion *type_system_union;
746 assert_return(m, -EINVAL);
747 assert_return(!m->sealed, -EPERM);
749 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
753 r = type_system_union_get_type_system(type_system_union,
754 &m->container_type_system[m->n_containers + 1],
759 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
763 /* do we evere need non-null size */
764 r = add_rtattr(m, type, NULL, 0);
768 m->container_offsets[m->n_containers ++] = r;
774 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
775 assert_return(m, -EINVAL);
776 assert_return(!m->sealed, -EPERM);
777 assert_return(m->n_containers > 0, -EINVAL);
779 m->container_type_system[m->n_containers] = NULL;
785 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
788 assert_return(m, -EINVAL);
789 assert_return(m->sealed, -EPERM);
790 assert_return(data, -EINVAL);
791 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
792 assert(m->rta_offset_tb[m->n_containers]);
793 assert(type < m->rta_tb_size[m->n_containers]);
795 if(!m->rta_offset_tb[m->n_containers][type])
798 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
800 *data = RTA_DATA(rta);
802 return RTA_PAYLOAD(rta);
805 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
809 r = message_attribute_has_type(m, type, NLA_STRING);
813 r = rtnl_message_read_internal(m, type, &attr_data);
816 else if (strnlen(attr_data, r) >= (size_t) r)
819 *data = (const char *) attr_data;
824 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
828 r = message_attribute_has_type(m, type, NLA_U8);
832 r = rtnl_message_read_internal(m, type, &attr_data);
835 else if ((size_t) r < sizeof(uint8_t))
838 *data = *(uint8_t *) attr_data;
843 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
847 r = message_attribute_has_type(m, type, NLA_U16);
851 r = rtnl_message_read_internal(m, type, &attr_data);
854 else if ((size_t) r < sizeof(uint16_t))
857 *data = *(uint16_t *) attr_data;
862 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
866 r = message_attribute_has_type(m, type, NLA_U32);
870 r = rtnl_message_read_internal(m, type, &attr_data);
873 else if ((size_t)r < sizeof(uint32_t))
876 *data = *(uint32_t *) attr_data;
881 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
885 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
889 r = rtnl_message_read_internal(m, type, &attr_data);
892 else if ((size_t)r < sizeof(struct ether_addr))
895 memcpy(data, attr_data, sizeof(struct ether_addr));
900 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
904 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
908 r = rtnl_message_read_internal(m, type, &attr_data);
911 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
914 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
919 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
923 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
927 r = rtnl_message_read_internal(m, type, &attr_data);
930 else if ((size_t)r < sizeof(struct in_addr))
933 memcpy(data, attr_data, sizeof(struct in_addr));
938 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
942 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
946 r = rtnl_message_read_internal(m, type, &attr_data);
949 else if ((size_t)r < sizeof(struct in6_addr))
952 memcpy(data, attr_data, sizeof(struct in6_addr));
957 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
958 const NLType *nl_type;
959 const NLTypeSystem *type_system;
964 assert_return(m, -EINVAL);
965 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
967 r = type_system_get_type(m->container_type_system[m->n_containers],
973 if (nl_type->type == NLA_NESTED) {
974 r = type_system_get_type_system(m->container_type_system[m->n_containers],
979 } else if (nl_type->type == NLA_UNION) {
980 const NLTypeSystemUnion *type_system_union;
983 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
989 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
993 r = type_system_union_get_type_system(type_system_union,
1001 r = rtnl_message_read_internal(m, type, &container);
1009 r = rtnl_message_parse(m,
1010 &m->rta_offset_tb[m->n_containers],
1011 &m->rta_tb_size[m->n_containers],
1020 m->container_type_system[m->n_containers] = type_system;
1025 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1026 assert_return(m, -EINVAL);
1027 assert_return(m->sealed, -EINVAL);
1028 assert_return(m->n_containers > 0, -EINVAL);
1030 free(m->rta_offset_tb[m->n_containers]);
1031 m->rta_offset_tb[m->n_containers] = NULL;
1032 m->container_type_system[m->n_containers] = NULL;
1039 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1043 return m->hdr->nlmsg_seq;
1046 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1047 struct nlmsgerr *err;
1049 assert_return(m, -EINVAL);
1050 assert_return(m->hdr, -EINVAL);
1052 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1055 err = NLMSG_DATA(m->hdr);
1060 int rtnl_message_parse(sd_rtnl_message *m,
1061 size_t **rta_offset_tb,
1062 unsigned short *rta_tb_size,
1065 unsigned int rt_len) {
1066 unsigned short type;
1069 tb = new0(size_t, max + 1);
1073 *rta_tb_size = max + 1;
1075 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1076 type = rta->rta_type;
1078 /* if the kernel is newer than the headers we used
1079 when building, we ignore out-of-range attributes
1085 log_debug("rtnl: message parse - overwriting repeated attribute");
1087 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1090 *rta_offset_tb = tb;
1095 /* returns the number of bytes sent, or a negative error code */
1096 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1099 struct sockaddr_nl nl;
1101 .nl.nl_family = AF_NETLINK,
1109 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1110 0, &addr.sa, sizeof(addr));
1112 return (errno == EAGAIN) ? 0 : -errno;
1117 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1118 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1119 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1120 struct msghdr msg = {
1123 .msg_control = cred_buffer,
1124 .msg_controllen = sizeof(cred_buffer),
1126 struct cmsghdr *cmsg;
1134 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1137 return (errno == EAGAIN) ? 0 : -errno;
1139 /* connection was closed by the kernel */
1142 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1143 if (cmsg->cmsg_level == SOL_SOCKET &&
1144 cmsg->cmsg_type == SCM_CREDENTIALS &&
1145 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1146 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1148 /* from the kernel */
1149 if (ucred->uid == 0 && ucred->pid == 0)
1151 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1152 cmsg->cmsg_type == NETLINK_PKTINFO &&
1153 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1154 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1156 /* multi-cast group */
1157 group = pktinfo->group;
1162 /* not from the kernel, ignore */
1171 /* On success, the number of bytes received is returned and *ret points to the received message
1172 * which has a valid header and the correct size.
1173 * If nothing useful was received 0 is returned.
1174 * On failure, a negative error code is returned.
1176 int socket_read_message(sd_rtnl *rtnl) {
1177 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1178 struct iovec iov = {};
1180 bool multi_part = false, done = false;
1181 struct nlmsghdr *new_msg;
1187 assert(rtnl->rbuffer);
1188 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1190 /* read nothing, just get the pending message size */
1191 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1197 /* make room for the pending message */
1198 if (!greedy_realloc((void **)&rtnl->rbuffer,
1199 &rtnl->rbuffer_allocated,
1200 len, sizeof(uint8_t)))
1203 iov.iov_base = rtnl->rbuffer;
1204 iov.iov_len = rtnl->rbuffer_allocated;
1206 /* read the pending message */
1207 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1213 if (len > rtnl->rbuffer_allocated)
1214 /* message did not fit in read buffer */
1217 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1220 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1221 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1222 rtnl->rbuffer->nlmsg_seq) {
1223 first = rtnl->rqueue_partial[i];
1229 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1230 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1231 const NLType *nl_type;
1233 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1234 /* not broadcast and not for us */
1237 if (new_msg->nlmsg_type == NLMSG_NOOP)
1238 /* silently drop noop messages */
1241 if (new_msg->nlmsg_type == NLMSG_DONE) {
1242 /* finished reading multi-part message */
1247 /* check that we support this message type */
1248 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1251 log_debug("sd-rtnl: ignored message with unknown type: %u",
1252 new_msg->nlmsg_type);
1257 /* check that the size matches the message type */
1258 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1261 r = message_new_empty(rtnl, &m);
1265 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1269 /* seal and parse the top-level message */
1270 r = sd_rtnl_message_rewind(m);
1274 /* push the message onto the multi-part message stack */
1282 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1287 if (!multi_part || done) {
1288 /* we got a complete message, push it on the read queue */
1289 r = rtnl_rqueue_make_room(rtnl);
1293 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1296 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1297 /* remove the message form the partial read queue */
1298 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1299 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1300 rtnl->rqueue_partial_size --;
1305 /* we only got a partial multi-part message, push it on the
1306 partial read queue */
1307 if (i < rtnl->rqueue_partial_size) {
1308 rtnl->rqueue_partial[i] = first;
1310 r = rtnl_rqueue_partial_make_room(rtnl);
1314 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1322 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1327 assert_return(m, -EINVAL);
1329 /* don't allow appending to message once parsed */
1331 rtnl_message_seal(m);
1333 for (i = 1; i <= m->n_containers; i++) {
1334 free(m->rta_offset_tb[i]);
1335 m->rta_offset_tb[i] = NULL;
1336 m->rta_tb_size[i] = 0;
1337 m->container_type_system[i] = NULL;
1340 m->n_containers = 0;
1342 if (m->rta_offset_tb[0]) {
1343 /* top-level attributes have already been parsed */
1349 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1353 if (type->type == NLA_NESTED) {
1354 const NLTypeSystem *type_system = type->type_system;
1356 assert(type_system);
1358 m->container_type_system[0] = type_system;
1360 r = rtnl_message_parse(m,
1361 &m->rta_offset_tb[m->n_containers],
1362 &m->rta_tb_size[m->n_containers],
1364 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1365 NLMSG_ALIGN(type->size)),
1366 NLMSG_PAYLOAD(m->hdr, type->size));
1374 void rtnl_message_seal(sd_rtnl_message *m) {
1381 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1382 assert_return(m, NULL);