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_EXCL;
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_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
217 struct ifaddrmsg *ifa;
219 assert_return(m, -EINVAL);
220 assert_return(m->hdr, -EINVAL);
221 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
223 ifa = NLMSG_DATA(m->hdr);
225 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
226 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
229 ifa->ifa_prefixlen = prefixlen;
234 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
235 struct ifaddrmsg *ifa;
237 assert_return(m, -EINVAL);
238 assert_return(m->hdr, -EINVAL);
239 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
241 ifa = NLMSG_DATA(m->hdr);
243 ifa->ifa_flags = flags;
248 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
249 struct ifaddrmsg *ifa;
251 assert_return(m, -EINVAL);
252 assert_return(m->hdr, -EINVAL);
253 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
255 ifa = NLMSG_DATA(m->hdr);
257 ifa->ifa_scope = scope;
262 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, unsigned char *family) {
263 struct ifaddrmsg *ifa;
265 assert_return(m, -EINVAL);
266 assert_return(m->hdr, -EINVAL);
267 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
268 assert_return(family, -EINVAL);
270 ifa = NLMSG_DATA(m->hdr);
272 *family = ifa->ifa_family;
277 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
278 struct ifaddrmsg *ifa;
280 assert_return(m, -EINVAL);
281 assert_return(m->hdr, -EINVAL);
282 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
283 assert_return(scope, -EINVAL);
285 ifa = NLMSG_DATA(m->hdr);
287 *scope = ifa->ifa_scope;
292 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
293 struct ifaddrmsg *ifa;
295 assert_return(m, -EINVAL);
296 assert_return(m->hdr, -EINVAL);
297 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
298 assert_return(flags, -EINVAL);
300 ifa = NLMSG_DATA(m->hdr);
302 *flags = ifa->ifa_flags;
307 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
308 struct ifaddrmsg *ifa;
310 assert_return(m, -EINVAL);
311 assert_return(m->hdr, -EINVAL);
312 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
313 assert_return(ifindex, -EINVAL);
315 ifa = NLMSG_DATA(m->hdr);
317 *ifindex = ifa->ifa_index;
322 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
323 uint16_t nlmsg_type, int index,
324 unsigned char family) {
325 struct ifaddrmsg *ifa;
328 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
329 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
331 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
332 family == AF_INET || family == AF_INET6, -EINVAL);
333 assert_return(ret, -EINVAL);
335 r = message_new(rtnl, ret, nlmsg_type);
339 if (nlmsg_type == RTM_GETADDR)
340 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
342 ifa = NLMSG_DATA((*ret)->hdr);
344 ifa->ifa_index = index;
345 ifa->ifa_family = family;
346 if (family == AF_INET)
347 ifa->ifa_prefixlen = 32;
348 else if (family == AF_INET6)
349 ifa->ifa_prefixlen = 128;
354 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
355 int index, unsigned char family) {
358 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
362 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
367 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
369 assert_se(REFCNT_INC(m->n_ref) >= 2);
374 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
375 if (m && REFCNT_DEC(m->n_ref) <= 0) {
380 for (i = 0; i <= m->n_containers; i++)
381 free(m->rta_offset_tb[i]);
383 sd_rtnl_message_unref(m->next);
391 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
392 assert_return(m, -EINVAL);
393 assert_return(type, -EINVAL);
395 *type = m->hdr->nlmsg_type;
400 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
401 assert_return(m, -EINVAL);
403 return !m->hdr->nlmsg_pid;
406 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
407 struct ifinfomsg *ifi;
409 assert_return(m, -EINVAL);
410 assert_return(m->hdr, -EINVAL);
411 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
412 assert_return(ifindex, -EINVAL);
414 ifi = NLMSG_DATA(m->hdr);
416 *ifindex = ifi->ifi_index;
421 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
422 struct ifinfomsg *ifi;
424 assert_return(m, -EINVAL);
425 assert_return(m->hdr, -EINVAL);
426 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
427 assert_return(flags, -EINVAL);
429 ifi = NLMSG_DATA(m->hdr);
431 *flags = ifi->ifi_flags;
436 /* If successful the updated message will be correctly aligned, if
437 unsuccessful the old message is untouched. */
438 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
439 uint32_t rta_length, message_length;
440 struct nlmsghdr *new_hdr;
448 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
449 assert(!data || data_length > 0);
450 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
452 /* get the size of the new rta attribute (with padding at the end) */
453 rta_length = RTA_LENGTH(data_length);
455 /* get the new message size (with padding at the end) */
456 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
458 /* realloc to fit the new attribute */
459 new_hdr = realloc(m->hdr, message_length);
464 /* get pointer to the attribute we are about to add */
465 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
467 /* if we are inside containers, extend them */
468 for (i = 0; i < m->n_containers; i++)
469 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
471 /* fill in the attribute */
472 rta->rta_type = type;
473 rta->rta_len = rta_length;
475 //TODO: simply return this value rather than check for !data
476 /* this is the start of a new container */
477 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
479 /* we don't deal with the case where the user lies about the type
480 * and gives us too little data (so don't do that)
482 padding = mempcpy(RTA_DATA(rta), data, data_length);
483 /* make sure also the padding at the end of the message is initialized */
485 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
488 /* update message size */
489 m->hdr->nlmsg_len = message_length;
494 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
498 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
502 if (type->type != data_type)
508 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
512 assert_return(m, -EINVAL);
513 assert_return(!m->sealed, -EPERM);
514 assert_return(data, -EINVAL);
516 r = message_attribute_has_type(m, type, NLA_STRING);
523 length = strnlen(data, size);
527 length = strlen(data);
529 r = add_rtattr(m, type, data, length + 1);
536 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
539 assert_return(m, -EINVAL);
540 assert_return(!m->sealed, -EPERM);
542 r = message_attribute_has_type(m, type, NLA_U8);
546 r = add_rtattr(m, type, &data, sizeof(uint8_t));
554 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
557 assert_return(m, -EINVAL);
558 assert_return(!m->sealed, -EPERM);
560 r = message_attribute_has_type(m, type, NLA_U16);
564 r = add_rtattr(m, type, &data, sizeof(uint16_t));
571 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
574 assert_return(m, -EINVAL);
575 assert_return(!m->sealed, -EPERM);
577 r = message_attribute_has_type(m, type, NLA_U32);
581 r = add_rtattr(m, type, &data, sizeof(uint32_t));
588 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
591 assert_return(m, -EINVAL);
592 assert_return(!m->sealed, -EPERM);
593 assert_return(data, -EINVAL);
595 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
599 r = add_rtattr(m, type, data, sizeof(struct in_addr));
606 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
609 assert_return(m, -EINVAL);
610 assert_return(!m->sealed, -EPERM);
611 assert_return(data, -EINVAL);
613 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
617 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
624 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
627 assert_return(m, -EINVAL);
628 assert_return(!m->sealed, -EPERM);
629 assert_return(data, -EINVAL);
631 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
635 r = add_rtattr(m, type, data, ETH_ALEN);
642 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
645 assert_return(m, -EINVAL);
646 assert_return(!m->sealed, -EPERM);
647 assert_return(info, -EINVAL);
649 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
653 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
660 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
664 assert_return(m, -EINVAL);
665 assert_return(!m->sealed, -EPERM);
667 r = message_attribute_has_type(m, type, NLA_NESTED);
673 r = type_system_get_type_system(m->container_type_system[m->n_containers],
674 &m->container_type_system[m->n_containers + 1],
679 r = add_rtattr(m, type, NULL, size);
686 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
687 const NLTypeSystemUnion *type_system_union;
690 assert_return(m, -EINVAL);
691 assert_return(!m->sealed, -EPERM);
693 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
697 r = type_system_union_get_type_system(type_system_union,
698 &m->container_type_system[m->n_containers + 1],
703 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
707 /* do we evere need non-null size */
708 r = add_rtattr(m, type, NULL, 0);
716 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
717 assert_return(m, -EINVAL);
718 assert_return(!m->sealed, -EPERM);
719 assert_return(m->n_containers > 0, -EINVAL);
721 m->container_type_system[m->n_containers] = NULL;
727 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
730 assert_return(m, -EINVAL);
731 assert_return(m->sealed, -EPERM);
732 assert_return(data, -EINVAL);
733 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
734 assert(m->rta_offset_tb[m->n_containers]);
735 assert(type < m->rta_tb_size[m->n_containers]);
737 if(!m->rta_offset_tb[m->n_containers][type])
740 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
742 *data = RTA_DATA(rta);
744 return RTA_PAYLOAD(rta);
747 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
751 r = message_attribute_has_type(m, type, NLA_STRING);
755 r = rtnl_message_read_internal(m, type, &attr_data);
758 else if (strnlen(attr_data, r) >= (size_t) r)
761 *data = (char *) attr_data;
766 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
770 r = message_attribute_has_type(m, type, NLA_U8);
774 r = rtnl_message_read_internal(m, type, &attr_data);
777 else if ((size_t) r < sizeof(uint8_t))
780 *data = *(uint8_t *) attr_data;
785 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
789 r = message_attribute_has_type(m, type, NLA_U16);
793 r = rtnl_message_read_internal(m, type, &attr_data);
796 else if ((size_t) r < sizeof(uint16_t))
799 *data = *(uint16_t *) attr_data;
804 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
808 r = message_attribute_has_type(m, type, NLA_U32);
812 r = rtnl_message_read_internal(m, type, &attr_data);
815 else if ((size_t)r < sizeof(uint32_t))
818 *data = *(uint32_t *) attr_data;
823 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
827 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
831 r = rtnl_message_read_internal(m, type, &attr_data);
834 else if ((size_t)r < sizeof(struct ether_addr))
837 memcpy(data, attr_data, sizeof(struct ether_addr));
842 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
846 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
850 r = rtnl_message_read_internal(m, type, &attr_data);
853 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
856 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
861 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
865 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
869 r = rtnl_message_read_internal(m, type, &attr_data);
872 else if ((size_t)r < sizeof(struct in_addr))
875 memcpy(data, attr_data, sizeof(struct in_addr));
880 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
884 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
888 r = rtnl_message_read_internal(m, type, &attr_data);
891 else if ((size_t)r < sizeof(struct in6_addr))
894 memcpy(data, attr_data, sizeof(struct in6_addr));
899 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
900 const NLType *nl_type;
901 const NLTypeSystem *type_system;
906 assert_return(m, -EINVAL);
907 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
909 r = type_system_get_type(m->container_type_system[m->n_containers],
915 if (nl_type->type == NLA_NESTED) {
916 r = type_system_get_type_system(m->container_type_system[m->n_containers],
921 } else if (nl_type->type == NLA_UNION) {
922 const NLTypeSystemUnion *type_system_union;
925 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
931 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
935 r = type_system_union_get_type_system(type_system_union,
943 r = rtnl_message_read_internal(m, type, &container);
951 r = rtnl_message_parse(m,
952 &m->rta_offset_tb[m->n_containers],
953 &m->rta_tb_size[m->n_containers],
962 m->container_type_system[m->n_containers] = type_system;
967 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
968 assert_return(m, -EINVAL);
969 assert_return(m->sealed, -EINVAL);
970 assert_return(m->n_containers > 0, -EINVAL);
972 free(m->rta_offset_tb[m->n_containers]);
973 m->rta_offset_tb[m->n_containers] = NULL;
974 m->container_type_system[m->n_containers] = NULL;
981 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
985 return m->hdr->nlmsg_seq;
988 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
989 struct nlmsgerr *err;
991 assert_return(m, -EINVAL);
992 assert_return(m->hdr, -EINVAL);
994 if (m->hdr->nlmsg_type != NLMSG_ERROR)
997 err = NLMSG_DATA(m->hdr);
1002 int rtnl_message_parse(sd_rtnl_message *m,
1003 size_t **rta_offset_tb,
1004 unsigned short *rta_tb_size,
1007 unsigned int rt_len) {
1008 unsigned short type;
1011 tb = new0(size_t, max + 1);
1015 *rta_tb_size = max + 1;
1017 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1018 type = rta->rta_type;
1020 /* if the kernel is newer than the headers we used
1021 when building, we ignore out-of-range attributes
1027 log_debug("rtnl: message parse - overwriting repeated attribute");
1029 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1032 *rta_offset_tb = tb;
1037 /* returns the number of bytes sent, or a negative error code */
1038 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1041 struct sockaddr_nl nl;
1043 .nl.nl_family = AF_NETLINK,
1051 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1052 0, &addr.sa, sizeof(addr));
1054 return (errno == EAGAIN) ? 0 : -errno;
1059 /* On success, the number of bytes received is returned and *ret points to the received message
1060 * which has a valid header and the correct size.
1061 * If nothing useful was received 0 is returned.
1062 * On failure, a negative error code is returned.
1064 int socket_read_message(sd_rtnl *rtnl) {
1065 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1066 sd_rtnl_message *previous = NULL;
1067 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
1068 struct iovec iov = {};
1069 struct msghdr msg = {
1072 .msg_control = cred_buffer,
1073 .msg_controllen = sizeof(cred_buffer),
1075 struct cmsghdr *cmsg;
1077 struct nlmsghdr *new_msg;
1082 assert(rtnl->rbuffer);
1083 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1085 /* read nothing, just get the pending message size */
1086 r = recvmsg(rtnl->fd, &msg, MSG_PEEK | MSG_TRUNC);
1089 return (errno == EAGAIN) ? 0 : -errno;
1091 /* connection was closed by the kernel */
1096 /* make room for the pending message */
1097 if (!greedy_realloc((void **)&rtnl->rbuffer,
1098 &rtnl->rbuffer_allocated,
1099 len, sizeof(uint8_t)))
1102 iov.iov_base = rtnl->rbuffer;
1103 iov.iov_len = rtnl->rbuffer_allocated;
1105 r = recvmsg(rtnl->fd, &msg, MSG_TRUNC);
1108 return (errno == EAGAIN) ? 0 : -errno;
1110 /* connection was closed by the kernel */
1115 if (len > rtnl->rbuffer_allocated)
1116 /* message did not fit in read buffer */
1119 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1120 if (cmsg->cmsg_level == SOL_SOCKET &&
1121 cmsg->cmsg_type == SCM_CREDENTIALS &&
1122 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1123 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1125 /* from the kernel */
1126 if (ucred->uid == 0 && ucred->pid == 0) {
1134 /* not from the kernel, ignore */
1137 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1138 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1139 const NLType *nl_type;
1141 if (new_msg->nlmsg_pid && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1142 /* not broadcast and not for us */
1145 /* silently drop noop messages */
1146 if (new_msg->nlmsg_type == NLMSG_NOOP)
1149 /* finished reading multi-part message */
1150 if (new_msg->nlmsg_type == NLMSG_DONE)
1153 /* check that we support this message type */
1154 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1157 log_debug("sd-rtnl: ignored message with unknown type: %u",
1158 new_msg->nlmsg_type);
1163 /* check that the size matches the message type */
1164 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1167 r = message_new_empty(rtnl, &m);
1171 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1175 /* seal and parse the top-level message */
1176 r = sd_rtnl_message_rewind(m);
1190 ret += new_msg->nlmsg_len;
1192 /* not a multi-part message, so stop reading*/
1193 if (!(new_msg->nlmsg_flags & NLM_F_MULTI))
1198 r = rtnl_rqueue_make_room(rtnl);
1202 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1207 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1212 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1217 assert_return(m, -EINVAL);
1219 /* don't allow appending to message once parsed */
1221 rtnl_message_seal(m);
1223 for (i = 1; i <= m->n_containers; i++) {
1224 free(m->rta_offset_tb[i]);
1225 m->rta_offset_tb[i] = NULL;
1226 m->rta_tb_size[i] = 0;
1227 m->container_type_system[i] = NULL;
1230 m->n_containers = 0;
1232 if (m->rta_offset_tb[0]) {
1233 /* top-level attributes have already been parsed */
1239 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1243 if (type->type == NLA_NESTED) {
1244 const NLTypeSystem *type_system = type->type_system;
1246 assert(type_system);
1248 m->container_type_system[0] = type_system;
1250 r = rtnl_message_parse(m,
1251 &m->rta_offset_tb[m->n_containers],
1252 &m->rta_tb_size[m->n_containers],
1254 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1255 NLMSG_ALIGN(type->size)),
1256 NLMSG_PAYLOAD(m->hdr, type->size));
1264 void rtnl_message_seal(sd_rtnl_message *m) {
1271 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1272 assert_return(m, NULL);