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 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
41 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
44 assert_return(ret, -EINVAL);
46 /* Note that 'rtnl' is curretly unused, if we start using it internally
47 we must take care to avoid problems due to mutual references between
48 busses and their queued messages. See sd-bus.
51 m = new0(sd_rtnl_message, 1);
55 m->n_ref = REFCNT_INIT;
64 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
65 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
66 const NLType *nl_type;
70 r = type_system_get_type(NULL, &nl_type, type);
74 assert(nl_type->type == NLA_NESTED);
76 r = message_new_empty(rtnl, &m);
80 size = NLMSG_SPACE(nl_type->size);
82 assert(size >= sizeof(struct nlmsghdr));
83 m->hdr = malloc0(size);
87 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
89 m->container_type_system[0] = nl_type->type_system;
90 m->hdr->nlmsg_len = size;
91 m->hdr->nlmsg_type = type;
99 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
102 assert_return(m, -EINVAL);
103 assert_return(m->hdr, -EINVAL);
104 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
106 rtm = NLMSG_DATA(m->hdr);
108 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
109 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
112 rtm->rtm_dst_len = prefixlen;
117 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
120 assert_return(m, -EINVAL);
121 assert_return(m->hdr, -EINVAL);
122 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
124 rtm = NLMSG_DATA(m->hdr);
126 rtm->rtm_scope = scope;
131 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
132 uint16_t nlmsg_type, int rtm_family,
133 unsigned char rtm_protocol) {
137 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
138 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
139 assert_return(ret, -EINVAL);
141 r = message_new(rtnl, ret, nlmsg_type);
145 if (nlmsg_type == RTM_NEWROUTE)
146 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
148 rtm = NLMSG_DATA((*ret)->hdr);
150 rtm->rtm_family = rtm_family;
151 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
152 rtm->rtm_type = RTN_UNICAST;
153 rtm->rtm_table = RT_TABLE_MAIN;
154 rtm->rtm_protocol = rtm_protocol;
159 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
160 struct ifinfomsg *ifi;
162 assert_return(m, -EINVAL);
163 assert_return(m->hdr, -EINVAL);
164 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
165 assert_return(change, -EINVAL);
167 ifi = NLMSG_DATA(m->hdr);
169 ifi->ifi_flags = flags;
170 ifi->ifi_change = change;
175 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
176 struct ifinfomsg *ifi;
178 assert_return(m, -EINVAL);
179 assert_return(m->hdr, -EINVAL);
180 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
182 ifi = NLMSG_DATA(m->hdr);
184 ifi->ifi_type = type;
189 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
190 struct ifinfomsg *ifi;
192 assert_return(m, -EINVAL);
193 assert_return(m->hdr, -EINVAL);
194 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
196 ifi = NLMSG_DATA(m->hdr);
198 ifi->ifi_family = family;
203 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
204 uint16_t nlmsg_type, int index) {
205 struct ifinfomsg *ifi;
208 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
209 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
210 assert_return(ret, -EINVAL);
212 r = message_new(rtnl, ret, nlmsg_type);
216 if (nlmsg_type == RTM_NEWLINK)
217 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
219 ifi = NLMSG_DATA((*ret)->hdr);
221 ifi->ifi_family = AF_UNSPEC;
222 ifi->ifi_index = index;
227 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
228 assert_return(m, -EINVAL);
229 assert_return(m->hdr, -EINVAL);
230 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
231 m->hdr->nlmsg_type == RTM_GETADDR ||
232 m->hdr->nlmsg_type == RTM_GETROUTE,
236 m->hdr->nlmsg_flags |= NLM_F_DUMP;
238 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
243 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
244 struct ifaddrmsg *ifa;
246 assert_return(m, -EINVAL);
247 assert_return(m->hdr, -EINVAL);
248 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
250 ifa = NLMSG_DATA(m->hdr);
252 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
253 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
256 ifa->ifa_prefixlen = prefixlen;
261 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
262 struct ifaddrmsg *ifa;
264 assert_return(m, -EINVAL);
265 assert_return(m->hdr, -EINVAL);
266 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
268 ifa = NLMSG_DATA(m->hdr);
270 ifa->ifa_flags = flags;
275 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
276 struct ifaddrmsg *ifa;
278 assert_return(m, -EINVAL);
279 assert_return(m->hdr, -EINVAL);
280 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
282 ifa = NLMSG_DATA(m->hdr);
284 ifa->ifa_scope = scope;
289 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
290 struct ifaddrmsg *ifa;
292 assert_return(m, -EINVAL);
293 assert_return(m->hdr, -EINVAL);
294 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
295 assert_return(family, -EINVAL);
297 ifa = NLMSG_DATA(m->hdr);
299 *family = ifa->ifa_family;
304 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
305 struct ifaddrmsg *ifa;
307 assert_return(m, -EINVAL);
308 assert_return(m->hdr, -EINVAL);
309 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
310 assert_return(prefixlen, -EINVAL);
312 ifa = NLMSG_DATA(m->hdr);
314 *prefixlen = ifa->ifa_prefixlen;
319 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
320 struct ifaddrmsg *ifa;
322 assert_return(m, -EINVAL);
323 assert_return(m->hdr, -EINVAL);
324 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
325 assert_return(scope, -EINVAL);
327 ifa = NLMSG_DATA(m->hdr);
329 *scope = ifa->ifa_scope;
334 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
335 struct ifaddrmsg *ifa;
337 assert_return(m, -EINVAL);
338 assert_return(m->hdr, -EINVAL);
339 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
340 assert_return(flags, -EINVAL);
342 ifa = NLMSG_DATA(m->hdr);
344 *flags = ifa->ifa_flags;
349 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
350 struct ifaddrmsg *ifa;
352 assert_return(m, -EINVAL);
353 assert_return(m->hdr, -EINVAL);
354 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
355 assert_return(ifindex, -EINVAL);
357 ifa = NLMSG_DATA(m->hdr);
359 *ifindex = ifa->ifa_index;
364 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
365 uint16_t nlmsg_type, int index,
367 struct ifaddrmsg *ifa;
370 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
371 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
373 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
374 family == AF_INET || family == AF_INET6, -EINVAL);
375 assert_return(ret, -EINVAL);
377 r = message_new(rtnl, ret, nlmsg_type);
381 if (nlmsg_type == RTM_GETADDR)
382 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
384 ifa = NLMSG_DATA((*ret)->hdr);
386 ifa->ifa_index = index;
387 ifa->ifa_family = family;
388 if (family == AF_INET)
389 ifa->ifa_prefixlen = 32;
390 else if (family == AF_INET6)
391 ifa->ifa_prefixlen = 128;
396 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
397 int index, int family) {
400 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
404 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
409 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
411 assert_se(REFCNT_INC(m->n_ref) >= 2);
416 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
417 if (m && REFCNT_DEC(m->n_ref) <= 0) {
422 for (i = 0; i <= m->n_containers; i++)
423 free(m->rta_offset_tb[i]);
425 sd_rtnl_message_unref(m->next);
433 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
434 assert_return(m, -EINVAL);
435 assert_return(type, -EINVAL);
437 *type = m->hdr->nlmsg_type;
442 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
443 assert_return(m, -EINVAL);
445 return !m->hdr->nlmsg_pid;
448 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
449 struct ifinfomsg *ifi;
451 assert_return(m, -EINVAL);
452 assert_return(m->hdr, -EINVAL);
453 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
454 assert_return(ifindex, -EINVAL);
456 ifi = NLMSG_DATA(m->hdr);
458 *ifindex = ifi->ifi_index;
463 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
464 struct ifinfomsg *ifi;
466 assert_return(m, -EINVAL);
467 assert_return(m->hdr, -EINVAL);
468 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
469 assert_return(flags, -EINVAL);
471 ifi = NLMSG_DATA(m->hdr);
473 *flags = ifi->ifi_flags;
478 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
479 struct ifinfomsg *ifi;
481 assert_return(m, -EINVAL);
482 assert_return(m->hdr, -EINVAL);
483 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
484 assert_return(type, -EINVAL);
486 ifi = NLMSG_DATA(m->hdr);
488 *type = ifi->ifi_type;
493 /* If successful the updated message will be correctly aligned, if
494 unsuccessful the old message is untouched. */
495 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
497 size_t message_length, padding_length;
498 struct nlmsghdr *new_hdr;
507 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
508 assert(!data || data_length);
510 /* get offset of the new attribute */
511 offset = m->hdr->nlmsg_len;
513 /* get the size of the new rta attribute (with padding at the end) */
514 rta_length = RTA_LENGTH(data_length);
516 /* get the new message size (with padding at the end) */
517 message_length = offset + RTA_ALIGN(rta_length);
519 /* realloc to fit the new attribute */
520 new_hdr = realloc(m->hdr, message_length);
525 /* get pointer to the attribute we are about to add */
526 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
528 /* if we are inside containers, extend them */
529 for (i = 0; i < m->n_containers; i++)
530 GET_CONTAINER(m, i)->rta_len += message_length - offset;
532 /* fill in the attribute */
533 rta->rta_type = type;
534 rta->rta_len = rta_length;
536 /* we don't deal with the case where the user lies about the type
537 * and gives us too little data (so don't do that)
539 padding = mempcpy(RTA_DATA(rta), data, data_length);
541 /* if no data was passed, make sure we still initialize the padding
542 note that we can have data_length > 0 (used by some containers) */
543 padding = RTA_DATA(rta);
546 /* make sure also the padding at the end of the message is initialized */
547 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
548 memzero(padding, padding_length);
550 /* update message size */
551 m->hdr->nlmsg_len = message_length;
556 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
560 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
564 if (type->type != data_type)
570 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
574 assert_return(m, -EINVAL);
575 assert_return(!m->sealed, -EPERM);
576 assert_return(data, -EINVAL);
578 r = message_attribute_has_type(m, type, NLA_STRING);
585 length = strnlen(data, size);
589 length = strlen(data);
591 r = add_rtattr(m, type, data, length + 1);
598 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
601 assert_return(m, -EINVAL);
602 assert_return(!m->sealed, -EPERM);
604 r = message_attribute_has_type(m, type, NLA_U8);
608 r = add_rtattr(m, type, &data, sizeof(uint8_t));
616 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
619 assert_return(m, -EINVAL);
620 assert_return(!m->sealed, -EPERM);
622 r = message_attribute_has_type(m, type, NLA_U16);
626 r = add_rtattr(m, type, &data, sizeof(uint16_t));
633 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
636 assert_return(m, -EINVAL);
637 assert_return(!m->sealed, -EPERM);
639 r = message_attribute_has_type(m, type, NLA_U32);
643 r = add_rtattr(m, type, &data, sizeof(uint32_t));
650 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
653 assert_return(m, -EINVAL);
654 assert_return(!m->sealed, -EPERM);
655 assert_return(data, -EINVAL);
657 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
661 r = add_rtattr(m, type, data, sizeof(struct in_addr));
668 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
671 assert_return(m, -EINVAL);
672 assert_return(!m->sealed, -EPERM);
673 assert_return(data, -EINVAL);
675 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
679 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
686 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
689 assert_return(m, -EINVAL);
690 assert_return(!m->sealed, -EPERM);
691 assert_return(data, -EINVAL);
693 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
697 r = add_rtattr(m, type, data, ETH_ALEN);
704 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
707 assert_return(m, -EINVAL);
708 assert_return(!m->sealed, -EPERM);
709 assert_return(info, -EINVAL);
711 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
715 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
722 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
726 assert_return(m, -EINVAL);
727 assert_return(!m->sealed, -EPERM);
728 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
730 r = message_attribute_has_type(m, type, NLA_NESTED);
736 r = type_system_get_type_system(m->container_type_system[m->n_containers],
737 &m->container_type_system[m->n_containers + 1],
742 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
746 m->container_offsets[m->n_containers ++] = r;
751 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
752 const NLTypeSystemUnion *type_system_union;
755 assert_return(m, -EINVAL);
756 assert_return(!m->sealed, -EPERM);
758 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
762 r = type_system_union_get_type_system(type_system_union,
763 &m->container_type_system[m->n_containers + 1],
768 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
772 /* do we evere need non-null size */
773 r = add_rtattr(m, type, NULL, 0);
777 m->container_offsets[m->n_containers ++] = r;
783 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
784 assert_return(m, -EINVAL);
785 assert_return(!m->sealed, -EPERM);
786 assert_return(m->n_containers > 0, -EINVAL);
788 m->container_type_system[m->n_containers] = NULL;
794 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
797 assert_return(m, -EINVAL);
798 assert_return(m->sealed, -EPERM);
799 assert_return(data, -EINVAL);
800 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
801 assert(m->rta_offset_tb[m->n_containers]);
802 assert(type < m->rta_tb_size[m->n_containers]);
804 if(!m->rta_offset_tb[m->n_containers][type])
807 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
809 *data = RTA_DATA(rta);
811 return RTA_PAYLOAD(rta);
814 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
818 r = message_attribute_has_type(m, type, NLA_STRING);
822 r = rtnl_message_read_internal(m, type, &attr_data);
825 else if (strnlen(attr_data, r) >= (size_t) r)
828 *data = (const char *) attr_data;
833 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
837 r = message_attribute_has_type(m, type, NLA_U8);
841 r = rtnl_message_read_internal(m, type, &attr_data);
844 else if ((size_t) r < sizeof(uint8_t))
847 *data = *(uint8_t *) attr_data;
852 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
856 r = message_attribute_has_type(m, type, NLA_U16);
860 r = rtnl_message_read_internal(m, type, &attr_data);
863 else if ((size_t) r < sizeof(uint16_t))
866 *data = *(uint16_t *) attr_data;
871 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
875 r = message_attribute_has_type(m, type, NLA_U32);
879 r = rtnl_message_read_internal(m, type, &attr_data);
882 else if ((size_t)r < sizeof(uint32_t))
885 *data = *(uint32_t *) attr_data;
890 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
894 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
898 r = rtnl_message_read_internal(m, type, &attr_data);
901 else if ((size_t)r < sizeof(struct ether_addr))
904 memcpy(data, attr_data, sizeof(struct ether_addr));
909 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
913 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
917 r = rtnl_message_read_internal(m, type, &attr_data);
920 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
923 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
928 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
932 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
936 r = rtnl_message_read_internal(m, type, &attr_data);
939 else if ((size_t)r < sizeof(struct in_addr))
942 memcpy(data, attr_data, sizeof(struct in_addr));
947 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
951 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
955 r = rtnl_message_read_internal(m, type, &attr_data);
958 else if ((size_t)r < sizeof(struct in6_addr))
961 memcpy(data, attr_data, sizeof(struct in6_addr));
966 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
967 const NLType *nl_type;
968 const NLTypeSystem *type_system;
973 assert_return(m, -EINVAL);
974 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
976 r = type_system_get_type(m->container_type_system[m->n_containers],
982 if (nl_type->type == NLA_NESTED) {
983 r = type_system_get_type_system(m->container_type_system[m->n_containers],
988 } else if (nl_type->type == NLA_UNION) {
989 const NLTypeSystemUnion *type_system_union;
992 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
998 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1002 r = type_system_union_get_type_system(type_system_union,
1010 r = rtnl_message_read_internal(m, type, &container);
1018 r = rtnl_message_parse(m,
1019 &m->rta_offset_tb[m->n_containers],
1020 &m->rta_tb_size[m->n_containers],
1029 m->container_type_system[m->n_containers] = type_system;
1034 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1035 assert_return(m, -EINVAL);
1036 assert_return(m->sealed, -EINVAL);
1037 assert_return(m->n_containers > 0, -EINVAL);
1039 free(m->rta_offset_tb[m->n_containers]);
1040 m->rta_offset_tb[m->n_containers] = NULL;
1041 m->container_type_system[m->n_containers] = NULL;
1048 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1052 return m->hdr->nlmsg_seq;
1055 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1056 struct nlmsgerr *err;
1058 assert_return(m, -EINVAL);
1059 assert_return(m->hdr, -EINVAL);
1061 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1064 err = NLMSG_DATA(m->hdr);
1069 int rtnl_message_parse(sd_rtnl_message *m,
1070 size_t **rta_offset_tb,
1071 unsigned short *rta_tb_size,
1074 unsigned int rt_len) {
1075 unsigned short type;
1078 tb = new0(size_t, max + 1);
1082 *rta_tb_size = max + 1;
1084 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1085 type = RTA_TYPE(rta);
1087 /* if the kernel is newer than the headers we used
1088 when building, we ignore out-of-range attributes
1094 log_debug("rtnl: message parse - overwriting repeated attribute");
1096 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1099 *rta_offset_tb = tb;
1104 /* returns the number of bytes sent, or a negative error code */
1105 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1108 struct sockaddr_nl nl;
1110 .nl.nl_family = AF_NETLINK,
1118 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1119 0, &addr.sa, sizeof(addr));
1121 return (errno == EAGAIN) ? 0 : -errno;
1126 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1127 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1128 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1129 struct msghdr msg = {
1132 .msg_control = cred_buffer,
1133 .msg_controllen = sizeof(cred_buffer),
1135 struct cmsghdr *cmsg;
1143 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1146 if (errno == ENOBUFS)
1147 log_debug("rtnl: kernel receive buffer overrun");
1149 return (errno == EAGAIN) ? 0 : -errno;
1151 /* connection was closed by the kernel */
1154 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1155 if (cmsg->cmsg_level == SOL_SOCKET &&
1156 cmsg->cmsg_type == SCM_CREDENTIALS &&
1157 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1158 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1160 /* from the kernel */
1161 if (ucred->uid == 0 && ucred->pid == 0)
1163 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1164 cmsg->cmsg_type == NETLINK_PKTINFO &&
1165 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1166 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1168 /* multi-cast group */
1169 group = pktinfo->group;
1174 /* not from the kernel, ignore */
1183 /* On success, the number of bytes received is returned and *ret points to the received message
1184 * which has a valid header and the correct size.
1185 * If nothing useful was received 0 is returned.
1186 * On failure, a negative error code is returned.
1188 int socket_read_message(sd_rtnl *rtnl) {
1189 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1190 struct iovec iov = {};
1192 bool multi_part = false, done = false;
1193 struct nlmsghdr *new_msg;
1199 assert(rtnl->rbuffer);
1200 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1202 /* read nothing, just get the pending message size */
1203 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1209 /* make room for the pending message */
1210 if (!greedy_realloc((void **)&rtnl->rbuffer,
1211 &rtnl->rbuffer_allocated,
1212 len, sizeof(uint8_t)))
1215 iov.iov_base = rtnl->rbuffer;
1216 iov.iov_len = rtnl->rbuffer_allocated;
1218 /* read the pending message */
1219 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1225 if (len > rtnl->rbuffer_allocated)
1226 /* message did not fit in read buffer */
1229 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1232 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1233 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1234 rtnl->rbuffer->nlmsg_seq) {
1235 first = rtnl->rqueue_partial[i];
1241 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1242 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1243 const NLType *nl_type;
1245 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1246 /* not broadcast and not for us */
1249 if (new_msg->nlmsg_type == NLMSG_NOOP)
1250 /* silently drop noop messages */
1253 if (new_msg->nlmsg_type == NLMSG_DONE) {
1254 /* finished reading multi-part message */
1259 /* check that we support this message type */
1260 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1263 log_debug("sd-rtnl: ignored message with unknown type: %u",
1264 new_msg->nlmsg_type);
1269 /* check that the size matches the message type */
1270 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1273 r = message_new_empty(rtnl, &m);
1277 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1281 /* seal and parse the top-level message */
1282 r = sd_rtnl_message_rewind(m);
1286 /* push the message onto the multi-part message stack */
1294 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1299 if (!multi_part || done) {
1300 /* we got a complete message, push it on the read queue */
1301 r = rtnl_rqueue_make_room(rtnl);
1305 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1308 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1309 /* remove the message form the partial read queue */
1310 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1311 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1312 rtnl->rqueue_partial_size --;
1317 /* we only got a partial multi-part message, push it on the
1318 partial read queue */
1319 if (i < rtnl->rqueue_partial_size) {
1320 rtnl->rqueue_partial[i] = first;
1322 r = rtnl_rqueue_partial_make_room(rtnl);
1326 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1334 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1339 assert_return(m, -EINVAL);
1341 /* don't allow appending to message once parsed */
1343 rtnl_message_seal(m);
1345 for (i = 1; i <= m->n_containers; i++) {
1346 free(m->rta_offset_tb[i]);
1347 m->rta_offset_tb[i] = NULL;
1348 m->rta_tb_size[i] = 0;
1349 m->container_type_system[i] = NULL;
1352 m->n_containers = 0;
1354 if (m->rta_offset_tb[0]) {
1355 /* top-level attributes have already been parsed */
1361 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1365 if (type->type == NLA_NESTED) {
1366 const NLTypeSystem *type_system = type->type_system;
1368 assert(type_system);
1370 m->container_type_system[0] = type_system;
1372 r = rtnl_message_parse(m,
1373 &m->rta_offset_tb[m->n_containers],
1374 &m->rta_tb_size[m->n_containers],
1376 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1377 NLMSG_ALIGN(type->size)),
1378 NLMSG_PAYLOAD(m->hdr, type->size));
1386 void rtnl_message_seal(sd_rtnl_message *m) {
1393 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1394 assert_return(m, NULL);