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>
32 #include "rtnl-util.h"
33 #include "rtnl-internal.h"
34 #include "rtnl-types.h"
36 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
37 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
39 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
42 assert_return(ret, -EINVAL);
44 /* Note that 'rtnl' is curretly unused, if we start using it internally
45 we must take care to avoid problems due to mutual references between
46 busses and their queued messages. See sd-bus.
49 m = new0(sd_rtnl_message, 1);
53 m->n_ref = REFCNT_INIT;
62 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
63 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
64 const NLType *nl_type;
68 r = type_system_get_type(NULL, &nl_type, type);
72 assert(nl_type->type == NLA_NESTED);
74 r = message_new_empty(rtnl, &m);
78 size = NLMSG_SPACE(nl_type->size);
80 assert(size >= sizeof(struct nlmsghdr));
81 m->hdr = malloc0(size);
85 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
87 m->container_type_system[0] = nl_type->type_system;
88 m->hdr->nlmsg_len = size;
89 m->hdr->nlmsg_type = type;
97 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
100 assert_return(m, -EINVAL);
101 assert_return(m->hdr, -EINVAL);
102 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
104 rtm = NLMSG_DATA(m->hdr);
106 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
107 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
110 rtm->rtm_dst_len = prefixlen;
115 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
118 assert_return(m, -EINVAL);
119 assert_return(m->hdr, -EINVAL);
120 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
122 rtm = NLMSG_DATA(m->hdr);
124 rtm->rtm_scope = scope;
129 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
130 uint16_t nlmsg_type, int rtm_family,
131 unsigned char rtm_protocol) {
135 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
136 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
137 assert_return(ret, -EINVAL);
139 r = message_new(rtnl, ret, nlmsg_type);
143 if (nlmsg_type == RTM_NEWROUTE)
144 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
146 rtm = NLMSG_DATA((*ret)->hdr);
148 rtm->rtm_family = rtm_family;
149 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
150 rtm->rtm_type = RTN_UNICAST;
151 rtm->rtm_table = RT_TABLE_MAIN;
152 rtm->rtm_protocol = rtm_protocol;
157 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
158 struct ifinfomsg *ifi;
160 assert_return(m, -EINVAL);
161 assert_return(m->hdr, -EINVAL);
162 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
163 assert_return(change, -EINVAL);
165 ifi = NLMSG_DATA(m->hdr);
167 ifi->ifi_flags = flags;
168 ifi->ifi_change = change;
173 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
174 struct ifinfomsg *ifi;
176 assert_return(m, -EINVAL);
177 assert_return(m->hdr, -EINVAL);
178 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
180 ifi = NLMSG_DATA(m->hdr);
182 ifi->ifi_type = type;
187 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
188 uint16_t nlmsg_type, int index) {
189 struct ifinfomsg *ifi;
192 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
193 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
194 assert_return(ret, -EINVAL);
196 r = message_new(rtnl, ret, nlmsg_type);
200 if (nlmsg_type == RTM_NEWLINK)
201 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
203 ifi = NLMSG_DATA((*ret)->hdr);
205 ifi->ifi_family = AF_UNSPEC;
206 ifi->ifi_index = index;
211 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
212 assert_return(m, -EINVAL);
213 assert_return(m->hdr, -EINVAL);
214 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
215 m->hdr->nlmsg_type == RTM_GETADDR ||
216 m->hdr->nlmsg_type == RTM_GETROUTE,
220 m->hdr->nlmsg_flags |= NLM_F_DUMP;
222 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
227 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
228 struct ifaddrmsg *ifa;
230 assert_return(m, -EINVAL);
231 assert_return(m->hdr, -EINVAL);
232 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
234 ifa = NLMSG_DATA(m->hdr);
236 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
237 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
240 ifa->ifa_prefixlen = prefixlen;
245 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
246 struct ifaddrmsg *ifa;
248 assert_return(m, -EINVAL);
249 assert_return(m->hdr, -EINVAL);
250 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
252 ifa = NLMSG_DATA(m->hdr);
254 ifa->ifa_flags = flags;
259 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
260 struct ifaddrmsg *ifa;
262 assert_return(m, -EINVAL);
263 assert_return(m->hdr, -EINVAL);
264 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
266 ifa = NLMSG_DATA(m->hdr);
268 ifa->ifa_scope = scope;
273 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
274 struct ifaddrmsg *ifa;
276 assert_return(m, -EINVAL);
277 assert_return(m->hdr, -EINVAL);
278 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
279 assert_return(family, -EINVAL);
281 ifa = NLMSG_DATA(m->hdr);
283 *family = ifa->ifa_family;
288 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
289 struct ifaddrmsg *ifa;
291 assert_return(m, -EINVAL);
292 assert_return(m->hdr, -EINVAL);
293 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
294 assert_return(prefixlen, -EINVAL);
296 ifa = NLMSG_DATA(m->hdr);
298 *prefixlen = ifa->ifa_prefixlen;
303 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
304 struct ifaddrmsg *ifa;
306 assert_return(m, -EINVAL);
307 assert_return(m->hdr, -EINVAL);
308 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
309 assert_return(scope, -EINVAL);
311 ifa = NLMSG_DATA(m->hdr);
313 *scope = ifa->ifa_scope;
318 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
319 struct ifaddrmsg *ifa;
321 assert_return(m, -EINVAL);
322 assert_return(m->hdr, -EINVAL);
323 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
324 assert_return(flags, -EINVAL);
326 ifa = NLMSG_DATA(m->hdr);
328 *flags = ifa->ifa_flags;
333 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
334 struct ifaddrmsg *ifa;
336 assert_return(m, -EINVAL);
337 assert_return(m->hdr, -EINVAL);
338 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
339 assert_return(ifindex, -EINVAL);
341 ifa = NLMSG_DATA(m->hdr);
343 *ifindex = ifa->ifa_index;
348 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
349 uint16_t nlmsg_type, int index,
351 struct ifaddrmsg *ifa;
354 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
355 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
357 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
358 family == AF_INET || family == AF_INET6, -EINVAL);
359 assert_return(ret, -EINVAL);
361 r = message_new(rtnl, ret, nlmsg_type);
365 if (nlmsg_type == RTM_GETADDR)
366 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
368 ifa = NLMSG_DATA((*ret)->hdr);
370 ifa->ifa_index = index;
371 ifa->ifa_family = family;
372 if (family == AF_INET)
373 ifa->ifa_prefixlen = 32;
374 else if (family == AF_INET6)
375 ifa->ifa_prefixlen = 128;
380 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
381 int index, int family) {
384 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
388 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
393 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
395 assert_se(REFCNT_INC(m->n_ref) >= 2);
400 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
401 if (m && REFCNT_DEC(m->n_ref) <= 0) {
406 for (i = 0; i <= m->n_containers; i++)
407 free(m->rta_offset_tb[i]);
409 sd_rtnl_message_unref(m->next);
417 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
418 assert_return(m, -EINVAL);
419 assert_return(type, -EINVAL);
421 *type = m->hdr->nlmsg_type;
426 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
427 assert_return(m, -EINVAL);
429 return !m->hdr->nlmsg_pid;
432 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
433 struct ifinfomsg *ifi;
435 assert_return(m, -EINVAL);
436 assert_return(m->hdr, -EINVAL);
437 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
438 assert_return(ifindex, -EINVAL);
440 ifi = NLMSG_DATA(m->hdr);
442 *ifindex = ifi->ifi_index;
447 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
448 struct ifinfomsg *ifi;
450 assert_return(m, -EINVAL);
451 assert_return(m->hdr, -EINVAL);
452 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
453 assert_return(flags, -EINVAL);
455 ifi = NLMSG_DATA(m->hdr);
457 *flags = ifi->ifi_flags;
462 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
463 struct ifinfomsg *ifi;
465 assert_return(m, -EINVAL);
466 assert_return(m->hdr, -EINVAL);
467 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
468 assert_return(type, -EINVAL);
470 ifi = NLMSG_DATA(m->hdr);
472 *type = ifi->ifi_type;
477 /* If successful the updated message will be correctly aligned, if
478 unsuccessful the old message is untouched. */
479 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
481 size_t message_length, padding_length;
482 struct nlmsghdr *new_hdr;
491 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
492 assert(!data || data_length);
494 /* get offset of the new attribute */
495 offset = m->hdr->nlmsg_len;
497 /* get the size of the new rta attribute (with padding at the end) */
498 rta_length = RTA_LENGTH(data_length);
500 /* get the new message size (with padding at the end) */
501 message_length = offset + RTA_ALIGN(rta_length);
503 /* realloc to fit the new attribute */
504 new_hdr = realloc(m->hdr, message_length);
509 /* get pointer to the attribute we are about to add */
510 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
512 /* if we are inside containers, extend them */
513 for (i = 0; i < m->n_containers; i++)
514 GET_CONTAINER(m, i)->rta_len += message_length - offset;
516 /* fill in the attribute */
517 rta->rta_type = type;
518 rta->rta_len = rta_length;
520 /* we don't deal with the case where the user lies about the type
521 * and gives us too little data (so don't do that)
523 padding = mempcpy(RTA_DATA(rta), data, data_length);
525 /* if no data was passed, make sure we still initialize the padding
526 note that we can have data_length > 0 (used by some containers) */
527 padding = RTA_DATA(rta);
530 /* make sure also the padding at the end of the message is initialized */
531 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
532 memzero(padding, padding_length);
534 /* update message size */
535 m->hdr->nlmsg_len = message_length;
540 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
544 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
548 if (type->type != data_type)
554 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
558 assert_return(m, -EINVAL);
559 assert_return(!m->sealed, -EPERM);
560 assert_return(data, -EINVAL);
562 r = message_attribute_has_type(m, type, NLA_STRING);
569 length = strnlen(data, size);
573 length = strlen(data);
575 r = add_rtattr(m, type, data, length + 1);
582 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
585 assert_return(m, -EINVAL);
586 assert_return(!m->sealed, -EPERM);
588 r = message_attribute_has_type(m, type, NLA_U8);
592 r = add_rtattr(m, type, &data, sizeof(uint8_t));
600 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
603 assert_return(m, -EINVAL);
604 assert_return(!m->sealed, -EPERM);
606 r = message_attribute_has_type(m, type, NLA_U16);
610 r = add_rtattr(m, type, &data, sizeof(uint16_t));
617 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
620 assert_return(m, -EINVAL);
621 assert_return(!m->sealed, -EPERM);
623 r = message_attribute_has_type(m, type, NLA_U32);
627 r = add_rtattr(m, type, &data, sizeof(uint32_t));
634 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
637 assert_return(m, -EINVAL);
638 assert_return(!m->sealed, -EPERM);
639 assert_return(data, -EINVAL);
641 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
645 r = add_rtattr(m, type, data, sizeof(struct in_addr));
652 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
655 assert_return(m, -EINVAL);
656 assert_return(!m->sealed, -EPERM);
657 assert_return(data, -EINVAL);
659 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
663 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
670 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
673 assert_return(m, -EINVAL);
674 assert_return(!m->sealed, -EPERM);
675 assert_return(data, -EINVAL);
677 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
681 r = add_rtattr(m, type, data, ETH_ALEN);
688 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
691 assert_return(m, -EINVAL);
692 assert_return(!m->sealed, -EPERM);
693 assert_return(info, -EINVAL);
695 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
699 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
706 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
710 assert_return(m, -EINVAL);
711 assert_return(!m->sealed, -EPERM);
712 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
714 r = message_attribute_has_type(m, type, NLA_NESTED);
720 r = type_system_get_type_system(m->container_type_system[m->n_containers],
721 &m->container_type_system[m->n_containers + 1],
726 r = add_rtattr(m, type, NULL, size);
730 m->container_offsets[m->n_containers ++] = r;
735 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
736 const NLTypeSystemUnion *type_system_union;
739 assert_return(m, -EINVAL);
740 assert_return(!m->sealed, -EPERM);
742 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
746 r = type_system_union_get_type_system(type_system_union,
747 &m->container_type_system[m->n_containers + 1],
752 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
756 /* do we evere need non-null size */
757 r = add_rtattr(m, type, NULL, 0);
761 m->container_offsets[m->n_containers ++] = r;
767 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
768 assert_return(m, -EINVAL);
769 assert_return(!m->sealed, -EPERM);
770 assert_return(m->n_containers > 0, -EINVAL);
772 m->container_type_system[m->n_containers] = NULL;
778 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
781 assert_return(m, -EINVAL);
782 assert_return(m->sealed, -EPERM);
783 assert_return(data, -EINVAL);
784 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
785 assert(m->rta_offset_tb[m->n_containers]);
786 assert(type < m->rta_tb_size[m->n_containers]);
788 if(!m->rta_offset_tb[m->n_containers][type])
791 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
793 *data = RTA_DATA(rta);
795 return RTA_PAYLOAD(rta);
798 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
802 r = message_attribute_has_type(m, type, NLA_STRING);
806 r = rtnl_message_read_internal(m, type, &attr_data);
809 else if (strnlen(attr_data, r) >= (size_t) r)
812 *data = (const char *) attr_data;
817 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
821 r = message_attribute_has_type(m, type, NLA_U8);
825 r = rtnl_message_read_internal(m, type, &attr_data);
828 else if ((size_t) r < sizeof(uint8_t))
831 *data = *(uint8_t *) attr_data;
836 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
840 r = message_attribute_has_type(m, type, NLA_U16);
844 r = rtnl_message_read_internal(m, type, &attr_data);
847 else if ((size_t) r < sizeof(uint16_t))
850 *data = *(uint16_t *) attr_data;
855 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
859 r = message_attribute_has_type(m, type, NLA_U32);
863 r = rtnl_message_read_internal(m, type, &attr_data);
866 else if ((size_t)r < sizeof(uint32_t))
869 *data = *(uint32_t *) attr_data;
874 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
878 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
882 r = rtnl_message_read_internal(m, type, &attr_data);
885 else if ((size_t)r < sizeof(struct ether_addr))
888 memcpy(data, attr_data, sizeof(struct ether_addr));
893 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
897 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
901 r = rtnl_message_read_internal(m, type, &attr_data);
904 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
907 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
912 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
916 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
920 r = rtnl_message_read_internal(m, type, &attr_data);
923 else if ((size_t)r < sizeof(struct in_addr))
926 memcpy(data, attr_data, sizeof(struct in_addr));
931 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
935 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
939 r = rtnl_message_read_internal(m, type, &attr_data);
942 else if ((size_t)r < sizeof(struct in6_addr))
945 memcpy(data, attr_data, sizeof(struct in6_addr));
950 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
951 const NLType *nl_type;
952 const NLTypeSystem *type_system;
957 assert_return(m, -EINVAL);
958 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
960 r = type_system_get_type(m->container_type_system[m->n_containers],
966 if (nl_type->type == NLA_NESTED) {
967 r = type_system_get_type_system(m->container_type_system[m->n_containers],
972 } else if (nl_type->type == NLA_UNION) {
973 const NLTypeSystemUnion *type_system_union;
976 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
982 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
986 r = type_system_union_get_type_system(type_system_union,
994 r = rtnl_message_read_internal(m, type, &container);
1002 r = rtnl_message_parse(m,
1003 &m->rta_offset_tb[m->n_containers],
1004 &m->rta_tb_size[m->n_containers],
1013 m->container_type_system[m->n_containers] = type_system;
1018 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1019 assert_return(m, -EINVAL);
1020 assert_return(m->sealed, -EINVAL);
1021 assert_return(m->n_containers > 0, -EINVAL);
1023 free(m->rta_offset_tb[m->n_containers]);
1024 m->rta_offset_tb[m->n_containers] = NULL;
1025 m->container_type_system[m->n_containers] = NULL;
1032 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1036 return m->hdr->nlmsg_seq;
1039 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1040 struct nlmsgerr *err;
1042 assert_return(m, -EINVAL);
1043 assert_return(m->hdr, -EINVAL);
1045 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1048 err = NLMSG_DATA(m->hdr);
1053 int rtnl_message_parse(sd_rtnl_message *m,
1054 size_t **rta_offset_tb,
1055 unsigned short *rta_tb_size,
1058 unsigned int rt_len) {
1059 unsigned short type;
1062 tb = new0(size_t, max + 1);
1066 *rta_tb_size = max + 1;
1068 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1069 type = rta->rta_type;
1071 /* if the kernel is newer than the headers we used
1072 when building, we ignore out-of-range attributes
1078 log_debug("rtnl: message parse - overwriting repeated attribute");
1080 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1083 *rta_offset_tb = tb;
1088 /* returns the number of bytes sent, or a negative error code */
1089 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1092 struct sockaddr_nl nl;
1094 .nl.nl_family = AF_NETLINK,
1102 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1103 0, &addr.sa, sizeof(addr));
1105 return (errno == EAGAIN) ? 0 : -errno;
1110 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1111 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1112 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1113 struct msghdr msg = {
1116 .msg_control = cred_buffer,
1117 .msg_controllen = sizeof(cred_buffer),
1119 struct cmsghdr *cmsg;
1127 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1130 if (errno == ENOBUFS)
1131 log_debug("rtnl: kernel receive buffer overrun");
1133 return (errno == EAGAIN) ? 0 : -errno;
1135 /* connection was closed by the kernel */
1138 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1139 if (cmsg->cmsg_level == SOL_SOCKET &&
1140 cmsg->cmsg_type == SCM_CREDENTIALS &&
1141 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1142 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1144 /* from the kernel */
1145 if (ucred->uid == 0 && ucred->pid == 0)
1147 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1148 cmsg->cmsg_type == NETLINK_PKTINFO &&
1149 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1150 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1152 /* multi-cast group */
1153 group = pktinfo->group;
1158 /* not from the kernel, ignore */
1167 /* On success, the number of bytes received is returned and *ret points to the received message
1168 * which has a valid header and the correct size.
1169 * If nothing useful was received 0 is returned.
1170 * On failure, a negative error code is returned.
1172 int socket_read_message(sd_rtnl *rtnl) {
1173 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1174 struct iovec iov = {};
1176 bool multi_part = false, done = false;
1177 struct nlmsghdr *new_msg;
1183 assert(rtnl->rbuffer);
1184 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1186 /* read nothing, just get the pending message size */
1187 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1193 /* make room for the pending message */
1194 if (!greedy_realloc((void **)&rtnl->rbuffer,
1195 &rtnl->rbuffer_allocated,
1196 len, sizeof(uint8_t)))
1199 iov.iov_base = rtnl->rbuffer;
1200 iov.iov_len = rtnl->rbuffer_allocated;
1202 /* read the pending message */
1203 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1209 if (len > rtnl->rbuffer_allocated)
1210 /* message did not fit in read buffer */
1213 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1216 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1217 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1218 rtnl->rbuffer->nlmsg_seq) {
1219 first = rtnl->rqueue_partial[i];
1225 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1226 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1227 const NLType *nl_type;
1229 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1230 /* not broadcast and not for us */
1233 if (new_msg->nlmsg_type == NLMSG_NOOP)
1234 /* silently drop noop messages */
1237 if (new_msg->nlmsg_type == NLMSG_DONE) {
1238 /* finished reading multi-part message */
1243 /* check that we support this message type */
1244 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1247 log_debug("sd-rtnl: ignored message with unknown type: %u",
1248 new_msg->nlmsg_type);
1253 /* check that the size matches the message type */
1254 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1257 r = message_new_empty(rtnl, &m);
1261 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1265 /* seal and parse the top-level message */
1266 r = sd_rtnl_message_rewind(m);
1270 /* push the message onto the multi-part message stack */
1278 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1283 if (!multi_part || done) {
1284 /* we got a complete message, push it on the read queue */
1285 r = rtnl_rqueue_make_room(rtnl);
1289 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1292 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1293 /* remove the message form the partial read queue */
1294 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1295 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1296 rtnl->rqueue_partial_size --;
1301 /* we only got a partial multi-part message, push it on the
1302 partial read queue */
1303 if (i < rtnl->rqueue_partial_size) {
1304 rtnl->rqueue_partial[i] = first;
1306 r = rtnl_rqueue_partial_make_room(rtnl);
1310 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1318 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1323 assert_return(m, -EINVAL);
1325 /* don't allow appending to message once parsed */
1327 rtnl_message_seal(m);
1329 for (i = 1; i <= m->n_containers; i++) {
1330 free(m->rta_offset_tb[i]);
1331 m->rta_offset_tb[i] = NULL;
1332 m->rta_tb_size[i] = 0;
1333 m->container_type_system[i] = NULL;
1336 m->n_containers = 0;
1338 if (m->rta_offset_tb[0]) {
1339 /* top-level attributes have already been parsed */
1345 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1349 if (type->type == NLA_NESTED) {
1350 const NLTypeSystem *type_system = type->type_system;
1352 assert(type_system);
1354 m->container_type_system[0] = type_system;
1356 r = rtnl_message_parse(m,
1357 &m->rta_offset_tb[m->n_containers],
1358 &m->rta_tb_size[m->n_containers],
1360 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1361 NLMSG_ALIGN(type->size)),
1362 NLMSG_PAYLOAD(m->hdr, type->size));
1370 void rtnl_message_seal(sd_rtnl_message *m) {
1377 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1378 assert_return(m, NULL);