1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/in.h>
23 #include <netinet/ether.h>
26 #include <linux/netlink.h>
27 #include <linux/veth.h>
30 #include <linux/if_tunnel.h>
31 #include <linux/if_bridge.h>
38 #include "rtnl-util.h"
39 #include "rtnl-internal.h"
40 #include "rtnl-types.h"
42 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
43 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
45 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
48 assert_return(ret, -EINVAL);
50 /* Note that 'rtnl' is curretly unused, if we start using it internally
51 we must take care to avoid problems due to mutual references between
52 busses and their queued messages. See sd-bus.
55 m = new0(sd_rtnl_message, 1);
59 m->n_ref = REFCNT_INIT;
68 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
69 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
70 const NLType *nl_type;
74 r = type_system_get_type(NULL, &nl_type, type);
78 assert(nl_type->type == NLA_NESTED);
80 r = message_new_empty(rtnl, &m);
84 size = NLMSG_SPACE(nl_type->size);
86 assert(size >= sizeof(struct nlmsghdr));
87 m->hdr = malloc0(size);
91 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
93 m->container_type_system[0] = nl_type->type_system;
94 m->hdr->nlmsg_len = size;
95 m->hdr->nlmsg_type = type;
103 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
106 assert_return(m, -EINVAL);
107 assert_return(m->hdr, -EINVAL);
108 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
110 rtm = NLMSG_DATA(m->hdr);
112 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
113 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
116 rtm->rtm_dst_len = prefixlen;
121 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
124 assert_return(m, -EINVAL);
125 assert_return(m->hdr, -EINVAL);
126 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
128 rtm = NLMSG_DATA(m->hdr);
130 rtm->rtm_scope = scope;
135 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
136 uint16_t nlmsg_type, unsigned char rtm_family) {
140 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
141 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
142 assert_return(ret, -EINVAL);
144 r = message_new(rtnl, ret, nlmsg_type);
148 if (nlmsg_type == RTM_NEWROUTE)
149 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
151 rtm = NLMSG_DATA((*ret)->hdr);
153 rtm->rtm_family = rtm_family;
154 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
155 rtm->rtm_type = RTN_UNICAST;
156 rtm->rtm_table = RT_TABLE_MAIN;
157 rtm->rtm_protocol = RTPROT_BOOT;
162 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
163 struct ifinfomsg *ifi;
165 assert_return(m, -EINVAL);
166 assert_return(m->hdr, -EINVAL);
167 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
168 assert_return(change, -EINVAL);
170 ifi = NLMSG_DATA(m->hdr);
172 ifi->ifi_flags = flags;
173 ifi->ifi_change = change;
178 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
179 struct ifinfomsg *ifi;
181 assert_return(m, -EINVAL);
182 assert_return(m->hdr, -EINVAL);
183 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
185 ifi = NLMSG_DATA(m->hdr);
187 ifi->ifi_type = type;
192 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
193 uint16_t nlmsg_type, int index) {
194 struct ifinfomsg *ifi;
197 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
198 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
199 assert_return(ret, -EINVAL);
201 r = message_new(rtnl, ret, nlmsg_type);
205 if (nlmsg_type == RTM_NEWLINK)
206 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
208 ifi = NLMSG_DATA((*ret)->hdr);
210 ifi->ifi_family = AF_UNSPEC;
211 ifi->ifi_index = index;
216 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
217 assert_return(m, -EINVAL);
218 assert_return(m->hdr, -EINVAL);
219 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
220 m->hdr->nlmsg_type == RTM_GETADDR ||
221 m->hdr->nlmsg_type == RTM_GETROUTE,
225 m->hdr->nlmsg_flags |= NLM_F_DUMP;
227 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
232 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
233 struct ifaddrmsg *ifa;
235 assert_return(m, -EINVAL);
236 assert_return(m->hdr, -EINVAL);
237 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
239 ifa = NLMSG_DATA(m->hdr);
241 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
242 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
245 ifa->ifa_prefixlen = prefixlen;
250 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
251 struct ifaddrmsg *ifa;
253 assert_return(m, -EINVAL);
254 assert_return(m->hdr, -EINVAL);
255 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
257 ifa = NLMSG_DATA(m->hdr);
259 ifa->ifa_flags = flags;
264 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
265 struct ifaddrmsg *ifa;
267 assert_return(m, -EINVAL);
268 assert_return(m->hdr, -EINVAL);
269 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
271 ifa = NLMSG_DATA(m->hdr);
273 ifa->ifa_scope = scope;
278 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, unsigned char *family) {
279 struct ifaddrmsg *ifa;
281 assert_return(m, -EINVAL);
282 assert_return(m->hdr, -EINVAL);
283 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
284 assert_return(family, -EINVAL);
286 ifa = NLMSG_DATA(m->hdr);
288 *family = ifa->ifa_family;
293 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
294 struct ifaddrmsg *ifa;
296 assert_return(m, -EINVAL);
297 assert_return(m->hdr, -EINVAL);
298 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
299 assert_return(prefixlen, -EINVAL);
301 ifa = NLMSG_DATA(m->hdr);
303 *prefixlen = ifa->ifa_prefixlen;
308 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
309 struct ifaddrmsg *ifa;
311 assert_return(m, -EINVAL);
312 assert_return(m->hdr, -EINVAL);
313 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
314 assert_return(scope, -EINVAL);
316 ifa = NLMSG_DATA(m->hdr);
318 *scope = ifa->ifa_scope;
323 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
324 struct ifaddrmsg *ifa;
326 assert_return(m, -EINVAL);
327 assert_return(m->hdr, -EINVAL);
328 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
329 assert_return(flags, -EINVAL);
331 ifa = NLMSG_DATA(m->hdr);
333 *flags = ifa->ifa_flags;
338 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
339 struct ifaddrmsg *ifa;
341 assert_return(m, -EINVAL);
342 assert_return(m->hdr, -EINVAL);
343 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
344 assert_return(ifindex, -EINVAL);
346 ifa = NLMSG_DATA(m->hdr);
348 *ifindex = ifa->ifa_index;
353 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
354 uint16_t nlmsg_type, int index,
355 unsigned char family) {
356 struct ifaddrmsg *ifa;
359 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
360 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
362 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
363 family == AF_INET || family == AF_INET6, -EINVAL);
364 assert_return(ret, -EINVAL);
366 r = message_new(rtnl, ret, nlmsg_type);
370 if (nlmsg_type == RTM_GETADDR)
371 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
373 ifa = NLMSG_DATA((*ret)->hdr);
375 ifa->ifa_index = index;
376 ifa->ifa_family = family;
377 if (family == AF_INET)
378 ifa->ifa_prefixlen = 32;
379 else if (family == AF_INET6)
380 ifa->ifa_prefixlen = 128;
385 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
386 int index, unsigned char family) {
389 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
393 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
398 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
400 assert_se(REFCNT_INC(m->n_ref) >= 2);
405 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
406 if (m && REFCNT_DEC(m->n_ref) <= 0) {
411 for (i = 0; i <= m->n_containers; i++)
412 free(m->rta_offset_tb[i]);
414 sd_rtnl_message_unref(m->next);
422 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
423 assert_return(m, -EINVAL);
424 assert_return(type, -EINVAL);
426 *type = m->hdr->nlmsg_type;
431 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
432 assert_return(m, -EINVAL);
434 return !m->hdr->nlmsg_pid;
437 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
438 struct ifinfomsg *ifi;
440 assert_return(m, -EINVAL);
441 assert_return(m->hdr, -EINVAL);
442 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
443 assert_return(ifindex, -EINVAL);
445 ifi = NLMSG_DATA(m->hdr);
447 *ifindex = ifi->ifi_index;
452 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
453 struct ifinfomsg *ifi;
455 assert_return(m, -EINVAL);
456 assert_return(m->hdr, -EINVAL);
457 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
458 assert_return(flags, -EINVAL);
460 ifi = NLMSG_DATA(m->hdr);
462 *flags = ifi->ifi_flags;
467 /* If successful the updated message will be correctly aligned, if
468 unsuccessful the old message is untouched. */
469 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
471 size_t message_length, padding_length;
472 struct nlmsghdr *new_hdr;
481 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
482 assert(!data || data_length);
484 /* get offset of the new attribute */
485 offset = m->hdr->nlmsg_len;
487 /* get the size of the new rta attribute (with padding at the end) */
488 rta_length = RTA_LENGTH(data_length);
490 /* get the new message size (with padding at the end) */
491 message_length = offset + RTA_ALIGN(rta_length);
493 /* realloc to fit the new attribute */
494 new_hdr = realloc(m->hdr, message_length);
499 /* get pointer to the attribute we are about to add */
500 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
502 /* if we are inside containers, extend them */
503 for (i = 0; i < m->n_containers; i++)
504 GET_CONTAINER(m, i)->rta_len += message_length - offset;
506 /* fill in the attribute */
507 rta->rta_type = type;
508 rta->rta_len = rta_length;
510 /* we don't deal with the case where the user lies about the type
511 * and gives us too little data (so don't do that)
513 padding = mempcpy(RTA_DATA(rta), data, data_length);
515 /* if no data was passed, make sure we still initialize the padding
516 note that we can have data_length > 0 (used by some containers) */
517 padding = RTA_DATA(rta);
521 /* make sure also the padding at the end of the message is initialized */
522 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
523 memzero(padding, padding_length);
525 /* update message size */
526 m->hdr->nlmsg_len = message_length;
531 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
535 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
539 if (type->type != data_type)
545 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
549 assert_return(m, -EINVAL);
550 assert_return(!m->sealed, -EPERM);
551 assert_return(data, -EINVAL);
553 r = message_attribute_has_type(m, type, NLA_STRING);
560 length = strnlen(data, size);
564 length = strlen(data);
566 r = add_rtattr(m, type, data, length + 1);
573 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
576 assert_return(m, -EINVAL);
577 assert_return(!m->sealed, -EPERM);
579 r = message_attribute_has_type(m, type, NLA_U8);
583 r = add_rtattr(m, type, &data, sizeof(uint8_t));
591 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
594 assert_return(m, -EINVAL);
595 assert_return(!m->sealed, -EPERM);
597 r = message_attribute_has_type(m, type, NLA_U16);
601 r = add_rtattr(m, type, &data, sizeof(uint16_t));
608 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
611 assert_return(m, -EINVAL);
612 assert_return(!m->sealed, -EPERM);
614 r = message_attribute_has_type(m, type, NLA_U32);
618 r = add_rtattr(m, type, &data, sizeof(uint32_t));
625 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
628 assert_return(m, -EINVAL);
629 assert_return(!m->sealed, -EPERM);
630 assert_return(data, -EINVAL);
632 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
636 r = add_rtattr(m, type, data, sizeof(struct in_addr));
643 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
646 assert_return(m, -EINVAL);
647 assert_return(!m->sealed, -EPERM);
648 assert_return(data, -EINVAL);
650 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
654 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
661 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
664 assert_return(m, -EINVAL);
665 assert_return(!m->sealed, -EPERM);
666 assert_return(data, -EINVAL);
668 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
672 r = add_rtattr(m, type, data, ETH_ALEN);
679 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
682 assert_return(m, -EINVAL);
683 assert_return(!m->sealed, -EPERM);
684 assert_return(info, -EINVAL);
686 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
690 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
697 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
701 assert_return(m, -EINVAL);
702 assert_return(!m->sealed, -EPERM);
703 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
705 r = message_attribute_has_type(m, type, NLA_NESTED);
711 r = type_system_get_type_system(m->container_type_system[m->n_containers],
712 &m->container_type_system[m->n_containers + 1],
717 r = add_rtattr(m, type, NULL, size);
721 m->container_offsets[m->n_containers ++] = r;
726 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
727 const NLTypeSystemUnion *type_system_union;
730 assert_return(m, -EINVAL);
731 assert_return(!m->sealed, -EPERM);
733 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
737 r = type_system_union_get_type_system(type_system_union,
738 &m->container_type_system[m->n_containers + 1],
743 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
747 /* do we evere need non-null size */
748 r = add_rtattr(m, type, NULL, 0);
752 m->container_offsets[m->n_containers ++] = r;
758 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
759 assert_return(m, -EINVAL);
760 assert_return(!m->sealed, -EPERM);
761 assert_return(m->n_containers > 0, -EINVAL);
763 m->container_type_system[m->n_containers] = NULL;
769 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
772 assert_return(m, -EINVAL);
773 assert_return(m->sealed, -EPERM);
774 assert_return(data, -EINVAL);
775 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
776 assert(m->rta_offset_tb[m->n_containers]);
777 assert(type < m->rta_tb_size[m->n_containers]);
779 if(!m->rta_offset_tb[m->n_containers][type])
782 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
784 *data = RTA_DATA(rta);
786 return RTA_PAYLOAD(rta);
789 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
793 r = message_attribute_has_type(m, type, NLA_STRING);
797 r = rtnl_message_read_internal(m, type, &attr_data);
800 else if (strnlen(attr_data, r) >= (size_t) r)
803 *data = (char *) attr_data;
808 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
812 r = message_attribute_has_type(m, type, NLA_U8);
816 r = rtnl_message_read_internal(m, type, &attr_data);
819 else if ((size_t) r < sizeof(uint8_t))
822 *data = *(uint8_t *) attr_data;
827 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
831 r = message_attribute_has_type(m, type, NLA_U16);
835 r = rtnl_message_read_internal(m, type, &attr_data);
838 else if ((size_t) r < sizeof(uint16_t))
841 *data = *(uint16_t *) attr_data;
846 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
850 r = message_attribute_has_type(m, type, NLA_U32);
854 r = rtnl_message_read_internal(m, type, &attr_data);
857 else if ((size_t)r < sizeof(uint32_t))
860 *data = *(uint32_t *) attr_data;
865 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
869 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
873 r = rtnl_message_read_internal(m, type, &attr_data);
876 else if ((size_t)r < sizeof(struct ether_addr))
879 memcpy(data, attr_data, sizeof(struct ether_addr));
884 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
888 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
892 r = rtnl_message_read_internal(m, type, &attr_data);
895 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
898 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
903 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
907 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
911 r = rtnl_message_read_internal(m, type, &attr_data);
914 else if ((size_t)r < sizeof(struct in_addr))
917 memcpy(data, attr_data, sizeof(struct in_addr));
922 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
926 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
930 r = rtnl_message_read_internal(m, type, &attr_data);
933 else if ((size_t)r < sizeof(struct in6_addr))
936 memcpy(data, attr_data, sizeof(struct in6_addr));
941 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
942 const NLType *nl_type;
943 const NLTypeSystem *type_system;
948 assert_return(m, -EINVAL);
949 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
951 r = type_system_get_type(m->container_type_system[m->n_containers],
957 if (nl_type->type == NLA_NESTED) {
958 r = type_system_get_type_system(m->container_type_system[m->n_containers],
963 } else if (nl_type->type == NLA_UNION) {
964 const NLTypeSystemUnion *type_system_union;
967 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
973 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
977 r = type_system_union_get_type_system(type_system_union,
985 r = rtnl_message_read_internal(m, type, &container);
993 r = rtnl_message_parse(m,
994 &m->rta_offset_tb[m->n_containers],
995 &m->rta_tb_size[m->n_containers],
1004 m->container_type_system[m->n_containers] = type_system;
1009 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1010 assert_return(m, -EINVAL);
1011 assert_return(m->sealed, -EINVAL);
1012 assert_return(m->n_containers > 0, -EINVAL);
1014 free(m->rta_offset_tb[m->n_containers]);
1015 m->rta_offset_tb[m->n_containers] = NULL;
1016 m->container_type_system[m->n_containers] = NULL;
1023 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1027 return m->hdr->nlmsg_seq;
1030 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1031 struct nlmsgerr *err;
1033 assert_return(m, -EINVAL);
1034 assert_return(m->hdr, -EINVAL);
1036 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1039 err = NLMSG_DATA(m->hdr);
1044 int rtnl_message_parse(sd_rtnl_message *m,
1045 size_t **rta_offset_tb,
1046 unsigned short *rta_tb_size,
1049 unsigned int rt_len) {
1050 unsigned short type;
1053 tb = new0(size_t, max + 1);
1057 *rta_tb_size = max + 1;
1059 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1060 type = rta->rta_type;
1062 /* if the kernel is newer than the headers we used
1063 when building, we ignore out-of-range attributes
1069 log_debug("rtnl: message parse - overwriting repeated attribute");
1071 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1074 *rta_offset_tb = tb;
1079 /* returns the number of bytes sent, or a negative error code */
1080 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1083 struct sockaddr_nl nl;
1085 .nl.nl_family = AF_NETLINK,
1093 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1094 0, &addr.sa, sizeof(addr));
1096 return (errno == EAGAIN) ? 0 : -errno;
1101 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1102 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1103 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1104 struct msghdr msg = {
1107 .msg_control = cred_buffer,
1108 .msg_controllen = sizeof(cred_buffer),
1110 struct cmsghdr *cmsg;
1118 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1121 return (errno == EAGAIN) ? 0 : -errno;
1123 /* connection was closed by the kernel */
1126 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1127 if (cmsg->cmsg_level == SOL_SOCKET &&
1128 cmsg->cmsg_type == SCM_CREDENTIALS &&
1129 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1130 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1132 /* from the kernel */
1133 if (ucred->uid == 0 && ucred->pid == 0)
1135 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1136 cmsg->cmsg_type == NETLINK_PKTINFO &&
1137 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1138 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1140 /* multi-cast group */
1141 group = pktinfo->group;
1146 /* not from the kernel, ignore */
1155 /* On success, the number of bytes received is returned and *ret points to the received message
1156 * which has a valid header and the correct size.
1157 * If nothing useful was received 0 is returned.
1158 * On failure, a negative error code is returned.
1160 int socket_read_message(sd_rtnl *rtnl) {
1161 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1162 struct iovec iov = {};
1164 bool multi_part = false, done = false;
1165 struct nlmsghdr *new_msg;
1171 assert(rtnl->rbuffer);
1172 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1174 /* read nothing, just get the pending message size */
1175 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1181 /* make room for the pending message */
1182 if (!greedy_realloc((void **)&rtnl->rbuffer,
1183 &rtnl->rbuffer_allocated,
1184 len, sizeof(uint8_t)))
1187 iov.iov_base = rtnl->rbuffer;
1188 iov.iov_len = rtnl->rbuffer_allocated;
1190 /* read the pending message */
1191 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1197 if (len > rtnl->rbuffer_allocated)
1198 /* message did not fit in read buffer */
1201 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1204 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1205 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1206 rtnl->rbuffer->nlmsg_seq) {
1207 first = rtnl->rqueue_partial[i];
1213 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1214 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1215 const NLType *nl_type;
1217 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1218 /* not broadcast and not for us */
1221 if (new_msg->nlmsg_type == NLMSG_NOOP)
1222 /* silently drop noop messages */
1225 if (new_msg->nlmsg_type == NLMSG_DONE) {
1226 /* finished reading multi-part message */
1231 /* check that we support this message type */
1232 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1235 log_debug("sd-rtnl: ignored message with unknown type: %u",
1236 new_msg->nlmsg_type);
1241 /* check that the size matches the message type */
1242 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1245 r = message_new_empty(rtnl, &m);
1249 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1253 /* seal and parse the top-level message */
1254 r = sd_rtnl_message_rewind(m);
1258 /* push the message onto the multi-part message stack */
1266 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1271 if (!multi_part || done) {
1272 /* we got a complete message, push it on the read queue */
1273 r = rtnl_rqueue_make_room(rtnl);
1277 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1280 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1281 /* remove the message form the partial read queue */
1282 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1283 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1284 rtnl->rqueue_partial_size --;
1289 /* we only got a partial multi-part message, push it on the
1290 partial read queue */
1291 if (i < rtnl->rqueue_partial_size) {
1292 rtnl->rqueue_partial[i] = first;
1294 r = rtnl_rqueue_partial_make_room(rtnl);
1298 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1306 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1311 assert_return(m, -EINVAL);
1313 /* don't allow appending to message once parsed */
1315 rtnl_message_seal(m);
1317 for (i = 1; i <= m->n_containers; i++) {
1318 free(m->rta_offset_tb[i]);
1319 m->rta_offset_tb[i] = NULL;
1320 m->rta_tb_size[i] = 0;
1321 m->container_type_system[i] = NULL;
1324 m->n_containers = 0;
1326 if (m->rta_offset_tb[0]) {
1327 /* top-level attributes have already been parsed */
1333 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1337 if (type->type == NLA_NESTED) {
1338 const NLTypeSystem *type_system = type->type_system;
1340 assert(type_system);
1342 m->container_type_system[0] = type_system;
1344 r = rtnl_message_parse(m,
1345 &m->rta_offset_tb[m->n_containers],
1346 &m->rta_tb_size[m->n_containers],
1348 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1349 NLMSG_ALIGN(type->size)),
1350 NLMSG_PAYLOAD(m->hdr, type->size));
1358 void rtnl_message_seal(sd_rtnl_message *m) {
1365 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1366 assert_return(m, NULL);