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_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
190 uint16_t nlmsg_type, int index) {
191 struct ifinfomsg *ifi;
194 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
195 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
196 assert_return(ret, -EINVAL);
198 r = message_new(rtnl, ret, nlmsg_type);
202 if (nlmsg_type == RTM_NEWLINK)
203 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
205 ifi = NLMSG_DATA((*ret)->hdr);
207 ifi->ifi_family = AF_UNSPEC;
208 ifi->ifi_index = index;
213 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
214 assert_return(m, -EINVAL);
215 assert_return(m->hdr, -EINVAL);
216 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
217 m->hdr->nlmsg_type == RTM_GETADDR ||
218 m->hdr->nlmsg_type == RTM_GETROUTE,
222 m->hdr->nlmsg_flags |= NLM_F_DUMP;
224 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
229 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
230 struct ifaddrmsg *ifa;
232 assert_return(m, -EINVAL);
233 assert_return(m->hdr, -EINVAL);
234 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
236 ifa = NLMSG_DATA(m->hdr);
238 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
239 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
242 ifa->ifa_prefixlen = prefixlen;
247 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
248 struct ifaddrmsg *ifa;
250 assert_return(m, -EINVAL);
251 assert_return(m->hdr, -EINVAL);
252 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
254 ifa = NLMSG_DATA(m->hdr);
256 ifa->ifa_flags = flags;
261 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
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_scope = scope;
275 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
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);
281 assert_return(family, -EINVAL);
283 ifa = NLMSG_DATA(m->hdr);
285 *family = ifa->ifa_family;
290 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
291 struct ifaddrmsg *ifa;
293 assert_return(m, -EINVAL);
294 assert_return(m->hdr, -EINVAL);
295 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
296 assert_return(prefixlen, -EINVAL);
298 ifa = NLMSG_DATA(m->hdr);
300 *prefixlen = ifa->ifa_prefixlen;
305 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
306 struct ifaddrmsg *ifa;
308 assert_return(m, -EINVAL);
309 assert_return(m->hdr, -EINVAL);
310 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
311 assert_return(scope, -EINVAL);
313 ifa = NLMSG_DATA(m->hdr);
315 *scope = ifa->ifa_scope;
320 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
321 struct ifaddrmsg *ifa;
323 assert_return(m, -EINVAL);
324 assert_return(m->hdr, -EINVAL);
325 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
326 assert_return(flags, -EINVAL);
328 ifa = NLMSG_DATA(m->hdr);
330 *flags = ifa->ifa_flags;
335 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
336 struct ifaddrmsg *ifa;
338 assert_return(m, -EINVAL);
339 assert_return(m->hdr, -EINVAL);
340 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
341 assert_return(ifindex, -EINVAL);
343 ifa = NLMSG_DATA(m->hdr);
345 *ifindex = ifa->ifa_index;
350 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
351 uint16_t nlmsg_type, int index,
353 struct ifaddrmsg *ifa;
356 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
357 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
359 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
360 family == AF_INET || family == AF_INET6, -EINVAL);
361 assert_return(ret, -EINVAL);
363 r = message_new(rtnl, ret, nlmsg_type);
367 if (nlmsg_type == RTM_GETADDR)
368 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
370 ifa = NLMSG_DATA((*ret)->hdr);
372 ifa->ifa_index = index;
373 ifa->ifa_family = family;
374 if (family == AF_INET)
375 ifa->ifa_prefixlen = 32;
376 else if (family == AF_INET6)
377 ifa->ifa_prefixlen = 128;
382 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
383 int index, int family) {
386 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
390 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
395 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
397 assert_se(REFCNT_INC(m->n_ref) >= 2);
402 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
403 if (m && REFCNT_DEC(m->n_ref) <= 0) {
408 for (i = 0; i <= m->n_containers; i++)
409 free(m->rta_offset_tb[i]);
411 sd_rtnl_message_unref(m->next);
419 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
420 assert_return(m, -EINVAL);
421 assert_return(type, -EINVAL);
423 *type = m->hdr->nlmsg_type;
428 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
429 assert_return(m, -EINVAL);
431 return !m->hdr->nlmsg_pid;
434 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
435 struct ifinfomsg *ifi;
437 assert_return(m, -EINVAL);
438 assert_return(m->hdr, -EINVAL);
439 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
440 assert_return(ifindex, -EINVAL);
442 ifi = NLMSG_DATA(m->hdr);
444 *ifindex = ifi->ifi_index;
449 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
450 struct ifinfomsg *ifi;
452 assert_return(m, -EINVAL);
453 assert_return(m->hdr, -EINVAL);
454 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
455 assert_return(flags, -EINVAL);
457 ifi = NLMSG_DATA(m->hdr);
459 *flags = ifi->ifi_flags;
464 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
465 struct ifinfomsg *ifi;
467 assert_return(m, -EINVAL);
468 assert_return(m->hdr, -EINVAL);
469 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
470 assert_return(type, -EINVAL);
472 ifi = NLMSG_DATA(m->hdr);
474 *type = ifi->ifi_type;
479 /* If successful the updated message will be correctly aligned, if
480 unsuccessful the old message is untouched. */
481 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
483 size_t message_length, padding_length;
484 struct nlmsghdr *new_hdr;
493 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
494 assert(!data || data_length);
496 /* get offset of the new attribute */
497 offset = m->hdr->nlmsg_len;
499 /* get the size of the new rta attribute (with padding at the end) */
500 rta_length = RTA_LENGTH(data_length);
502 /* get the new message size (with padding at the end) */
503 message_length = offset + RTA_ALIGN(rta_length);
505 /* realloc to fit the new attribute */
506 new_hdr = realloc(m->hdr, message_length);
511 /* get pointer to the attribute we are about to add */
512 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
514 /* if we are inside containers, extend them */
515 for (i = 0; i < m->n_containers; i++)
516 GET_CONTAINER(m, i)->rta_len += message_length - offset;
518 /* fill in the attribute */
519 rta->rta_type = type;
520 rta->rta_len = rta_length;
522 /* we don't deal with the case where the user lies about the type
523 * and gives us too little data (so don't do that)
525 padding = mempcpy(RTA_DATA(rta), data, data_length);
527 /* if no data was passed, make sure we still initialize the padding
528 note that we can have data_length > 0 (used by some containers) */
529 padding = RTA_DATA(rta);
532 /* make sure also the padding at the end of the message is initialized */
533 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
534 memzero(padding, padding_length);
536 /* update message size */
537 m->hdr->nlmsg_len = message_length;
542 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
546 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
550 if (type->type != data_type)
556 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
560 assert_return(m, -EINVAL);
561 assert_return(!m->sealed, -EPERM);
562 assert_return(data, -EINVAL);
564 r = message_attribute_has_type(m, type, NLA_STRING);
571 length = strnlen(data, size);
575 length = strlen(data);
577 r = add_rtattr(m, type, data, length + 1);
584 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
587 assert_return(m, -EINVAL);
588 assert_return(!m->sealed, -EPERM);
590 r = message_attribute_has_type(m, type, NLA_U8);
594 r = add_rtattr(m, type, &data, sizeof(uint8_t));
602 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
605 assert_return(m, -EINVAL);
606 assert_return(!m->sealed, -EPERM);
608 r = message_attribute_has_type(m, type, NLA_U16);
612 r = add_rtattr(m, type, &data, sizeof(uint16_t));
619 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
622 assert_return(m, -EINVAL);
623 assert_return(!m->sealed, -EPERM);
625 r = message_attribute_has_type(m, type, NLA_U32);
629 r = add_rtattr(m, type, &data, sizeof(uint32_t));
636 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
639 assert_return(m, -EINVAL);
640 assert_return(!m->sealed, -EPERM);
641 assert_return(data, -EINVAL);
643 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
647 r = add_rtattr(m, type, data, sizeof(struct in_addr));
654 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
657 assert_return(m, -EINVAL);
658 assert_return(!m->sealed, -EPERM);
659 assert_return(data, -EINVAL);
661 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
665 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
672 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
675 assert_return(m, -EINVAL);
676 assert_return(!m->sealed, -EPERM);
677 assert_return(data, -EINVAL);
679 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
683 r = add_rtattr(m, type, data, ETH_ALEN);
690 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
693 assert_return(m, -EINVAL);
694 assert_return(!m->sealed, -EPERM);
695 assert_return(info, -EINVAL);
697 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
701 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
708 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
712 assert_return(m, -EINVAL);
713 assert_return(!m->sealed, -EPERM);
714 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
716 r = message_attribute_has_type(m, type, NLA_NESTED);
722 r = type_system_get_type_system(m->container_type_system[m->n_containers],
723 &m->container_type_system[m->n_containers + 1],
728 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
732 m->container_offsets[m->n_containers ++] = r;
737 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
738 const NLTypeSystemUnion *type_system_union;
741 assert_return(m, -EINVAL);
742 assert_return(!m->sealed, -EPERM);
744 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
748 r = type_system_union_get_type_system(type_system_union,
749 &m->container_type_system[m->n_containers + 1],
754 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
758 /* do we evere need non-null size */
759 r = add_rtattr(m, type, NULL, 0);
763 m->container_offsets[m->n_containers ++] = r;
769 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
770 assert_return(m, -EINVAL);
771 assert_return(!m->sealed, -EPERM);
772 assert_return(m->n_containers > 0, -EINVAL);
774 m->container_type_system[m->n_containers] = NULL;
780 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
783 assert_return(m, -EINVAL);
784 assert_return(m->sealed, -EPERM);
785 assert_return(data, -EINVAL);
786 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
787 assert(m->rta_offset_tb[m->n_containers]);
788 assert(type < m->rta_tb_size[m->n_containers]);
790 if(!m->rta_offset_tb[m->n_containers][type])
793 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
795 *data = RTA_DATA(rta);
797 return RTA_PAYLOAD(rta);
800 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
804 r = message_attribute_has_type(m, type, NLA_STRING);
808 r = rtnl_message_read_internal(m, type, &attr_data);
811 else if (strnlen(attr_data, r) >= (size_t) r)
814 *data = (const char *) attr_data;
819 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
823 r = message_attribute_has_type(m, type, NLA_U8);
827 r = rtnl_message_read_internal(m, type, &attr_data);
830 else if ((size_t) r < sizeof(uint8_t))
833 *data = *(uint8_t *) attr_data;
838 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
842 r = message_attribute_has_type(m, type, NLA_U16);
846 r = rtnl_message_read_internal(m, type, &attr_data);
849 else if ((size_t) r < sizeof(uint16_t))
852 *data = *(uint16_t *) attr_data;
857 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
861 r = message_attribute_has_type(m, type, NLA_U32);
865 r = rtnl_message_read_internal(m, type, &attr_data);
868 else if ((size_t)r < sizeof(uint32_t))
871 *data = *(uint32_t *) attr_data;
876 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
880 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
884 r = rtnl_message_read_internal(m, type, &attr_data);
887 else if ((size_t)r < sizeof(struct ether_addr))
890 memcpy(data, attr_data, sizeof(struct ether_addr));
895 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
899 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
903 r = rtnl_message_read_internal(m, type, &attr_data);
906 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
909 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
914 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
918 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
922 r = rtnl_message_read_internal(m, type, &attr_data);
925 else if ((size_t)r < sizeof(struct in_addr))
928 memcpy(data, attr_data, sizeof(struct in_addr));
933 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
937 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
941 r = rtnl_message_read_internal(m, type, &attr_data);
944 else if ((size_t)r < sizeof(struct in6_addr))
947 memcpy(data, attr_data, sizeof(struct in6_addr));
952 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
953 const NLType *nl_type;
954 const NLTypeSystem *type_system;
959 assert_return(m, -EINVAL);
960 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
962 r = type_system_get_type(m->container_type_system[m->n_containers],
968 if (nl_type->type == NLA_NESTED) {
969 r = type_system_get_type_system(m->container_type_system[m->n_containers],
974 } else if (nl_type->type == NLA_UNION) {
975 const NLTypeSystemUnion *type_system_union;
978 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
984 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
988 r = type_system_union_get_type_system(type_system_union,
996 r = rtnl_message_read_internal(m, type, &container);
1004 r = rtnl_message_parse(m,
1005 &m->rta_offset_tb[m->n_containers],
1006 &m->rta_tb_size[m->n_containers],
1015 m->container_type_system[m->n_containers] = type_system;
1020 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1021 assert_return(m, -EINVAL);
1022 assert_return(m->sealed, -EINVAL);
1023 assert_return(m->n_containers > 0, -EINVAL);
1025 free(m->rta_offset_tb[m->n_containers]);
1026 m->rta_offset_tb[m->n_containers] = NULL;
1027 m->container_type_system[m->n_containers] = NULL;
1034 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1038 return m->hdr->nlmsg_seq;
1041 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1042 struct nlmsgerr *err;
1044 assert_return(m, -EINVAL);
1045 assert_return(m->hdr, -EINVAL);
1047 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1050 err = NLMSG_DATA(m->hdr);
1055 int rtnl_message_parse(sd_rtnl_message *m,
1056 size_t **rta_offset_tb,
1057 unsigned short *rta_tb_size,
1060 unsigned int rt_len) {
1061 unsigned short type;
1064 tb = new0(size_t, max + 1);
1068 *rta_tb_size = max + 1;
1070 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1071 type = RTA_TYPE(rta);
1073 /* if the kernel is newer than the headers we used
1074 when building, we ignore out-of-range attributes
1080 log_debug("rtnl: message parse - overwriting repeated attribute");
1082 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1085 *rta_offset_tb = tb;
1090 /* returns the number of bytes sent, or a negative error code */
1091 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1094 struct sockaddr_nl nl;
1096 .nl.nl_family = AF_NETLINK,
1104 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1105 0, &addr.sa, sizeof(addr));
1107 return (errno == EAGAIN) ? 0 : -errno;
1112 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1113 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1114 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1115 struct msghdr msg = {
1118 .msg_control = cred_buffer,
1119 .msg_controllen = sizeof(cred_buffer),
1121 struct cmsghdr *cmsg;
1129 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1132 if (errno == ENOBUFS)
1133 log_debug("rtnl: kernel receive buffer overrun");
1135 return (errno == EAGAIN) ? 0 : -errno;
1137 /* connection was closed by the kernel */
1140 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1141 if (cmsg->cmsg_level == SOL_SOCKET &&
1142 cmsg->cmsg_type == SCM_CREDENTIALS &&
1143 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1144 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1146 /* from the kernel */
1147 if (ucred->uid == 0 && ucred->pid == 0)
1149 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1150 cmsg->cmsg_type == NETLINK_PKTINFO &&
1151 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1152 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1154 /* multi-cast group */
1155 group = pktinfo->group;
1160 /* not from the kernel, ignore */
1169 /* On success, the number of bytes received is returned and *ret points to the received message
1170 * which has a valid header and the correct size.
1171 * If nothing useful was received 0 is returned.
1172 * On failure, a negative error code is returned.
1174 int socket_read_message(sd_rtnl *rtnl) {
1175 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1176 struct iovec iov = {};
1178 bool multi_part = false, done = false;
1179 struct nlmsghdr *new_msg;
1185 assert(rtnl->rbuffer);
1186 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1188 /* read nothing, just get the pending message size */
1189 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1195 /* make room for the pending message */
1196 if (!greedy_realloc((void **)&rtnl->rbuffer,
1197 &rtnl->rbuffer_allocated,
1198 len, sizeof(uint8_t)))
1201 iov.iov_base = rtnl->rbuffer;
1202 iov.iov_len = rtnl->rbuffer_allocated;
1204 /* read the pending message */
1205 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1211 if (len > rtnl->rbuffer_allocated)
1212 /* message did not fit in read buffer */
1215 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1218 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1219 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1220 rtnl->rbuffer->nlmsg_seq) {
1221 first = rtnl->rqueue_partial[i];
1227 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1228 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1229 const NLType *nl_type;
1231 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1232 /* not broadcast and not for us */
1235 if (new_msg->nlmsg_type == NLMSG_NOOP)
1236 /* silently drop noop messages */
1239 if (new_msg->nlmsg_type == NLMSG_DONE) {
1240 /* finished reading multi-part message */
1245 /* check that we support this message type */
1246 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1249 log_debug("sd-rtnl: ignored message with unknown type: %u",
1250 new_msg->nlmsg_type);
1255 /* check that the size matches the message type */
1256 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1259 r = message_new_empty(rtnl, &m);
1263 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1267 /* seal and parse the top-level message */
1268 r = sd_rtnl_message_rewind(m);
1272 /* push the message onto the multi-part message stack */
1280 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1285 if (!multi_part || done) {
1286 /* we got a complete message, push it on the read queue */
1287 r = rtnl_rqueue_make_room(rtnl);
1291 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1294 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1295 /* remove the message form the partial read queue */
1296 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1297 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1298 rtnl->rqueue_partial_size --;
1303 /* we only got a partial multi-part message, push it on the
1304 partial read queue */
1305 if (i < rtnl->rqueue_partial_size) {
1306 rtnl->rqueue_partial[i] = first;
1308 r = rtnl_rqueue_partial_make_room(rtnl);
1312 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1320 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1325 assert_return(m, -EINVAL);
1327 /* don't allow appending to message once parsed */
1329 rtnl_message_seal(m);
1331 for (i = 1; i <= m->n_containers; i++) {
1332 free(m->rta_offset_tb[i]);
1333 m->rta_offset_tb[i] = NULL;
1334 m->rta_tb_size[i] = 0;
1335 m->container_type_system[i] = NULL;
1338 m->n_containers = 0;
1340 if (m->rta_offset_tb[0]) {
1341 /* top-level attributes have already been parsed */
1347 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1351 if (type->type == NLA_NESTED) {
1352 const NLTypeSystem *type_system = type->type_system;
1354 assert(type_system);
1356 m->container_type_system[0] = type_system;
1358 r = rtnl_message_parse(m,
1359 &m->rta_offset_tb[m->n_containers],
1360 &m->rta_tb_size[m->n_containers],
1362 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1363 NLMSG_ALIGN(type->size)),
1364 NLMSG_PAYLOAD(m->hdr, type->size));
1372 void rtnl_message_seal(sd_rtnl_message *m) {
1379 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1380 assert_return(m, NULL);