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_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
263 uint16_t nlmsg_type, int index,
264 unsigned char family) {
265 struct ifaddrmsg *ifa;
268 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
269 assert_return(index > 0, -EINVAL);
270 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
271 assert_return(ret, -EINVAL);
273 r = message_new(rtnl, ret, nlmsg_type);
277 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
278 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
280 ifa = NLMSG_DATA((*ret)->hdr);
282 ifa->ifa_index = index;
283 ifa->ifa_family = family;
284 if (family == AF_INET)
285 ifa->ifa_prefixlen = 32;
286 else if (family == AF_INET6)
287 ifa->ifa_prefixlen = 128;
292 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
293 int index, unsigned char family) {
296 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
300 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
305 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
307 assert_se(REFCNT_INC(m->n_ref) >= 2);
312 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
313 if (m && REFCNT_DEC(m->n_ref) <= 0) {
318 for (i = 0; i <= m->n_containers; i++)
319 free(m->rta_offset_tb[i]);
327 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
328 assert_return(m, -EINVAL);
329 assert_return(type, -EINVAL);
331 *type = m->hdr->nlmsg_type;
336 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
337 assert_return(m, -EINVAL);
339 return !m->hdr->nlmsg_pid;
342 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
343 struct ifinfomsg *ifi;
345 assert_return(m, -EINVAL);
346 assert_return(m->hdr, -EINVAL);
347 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
348 assert_return(ifindex, -EINVAL);
350 ifi = NLMSG_DATA(m->hdr);
352 *ifindex = ifi->ifi_index;
357 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
358 struct ifinfomsg *ifi;
360 assert_return(m, -EINVAL);
361 assert_return(m->hdr, -EINVAL);
362 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
363 assert_return(flags, -EINVAL);
365 ifi = NLMSG_DATA(m->hdr);
367 *flags = ifi->ifi_flags;
372 /* If successful the updated message will be correctly aligned, if
373 unsuccessful the old message is untouched. */
374 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
375 uint32_t rta_length, message_length;
376 struct nlmsghdr *new_hdr;
384 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
385 assert(!data || data_length > 0);
386 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
388 /* get the size of the new rta attribute (with padding at the end) */
389 rta_length = RTA_LENGTH(data_length);
391 /* get the new message size (with padding at the end) */
392 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
394 /* realloc to fit the new attribute */
395 new_hdr = realloc(m->hdr, message_length);
400 /* get pointer to the attribute we are about to add */
401 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
403 /* if we are inside containers, extend them */
404 for (i = 0; i < m->n_containers; i++)
405 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
407 /* fill in the attribute */
408 rta->rta_type = type;
409 rta->rta_len = rta_length;
411 //TODO: simply return this value rather than check for !data
412 /* this is the start of a new container */
413 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
415 /* we don't deal with the case where the user lies about the type
416 * and gives us too little data (so don't do that)
418 padding = mempcpy(RTA_DATA(rta), data, data_length);
419 /* make sure also the padding at the end of the message is initialized */
421 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
424 /* update message size */
425 m->hdr->nlmsg_len = message_length;
430 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
434 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
438 if (type->type != data_type)
444 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
448 assert_return(m, -EINVAL);
449 assert_return(!m->sealed, -EPERM);
450 assert_return(data, -EINVAL);
452 r = message_attribute_has_type(m, type, NLA_STRING);
459 length = strnlen(data, size);
463 length = strlen(data);
465 r = add_rtattr(m, type, data, length + 1);
472 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
475 assert_return(m, -EINVAL);
476 assert_return(!m->sealed, -EPERM);
478 r = message_attribute_has_type(m, type, NLA_U8);
482 r = add_rtattr(m, type, &data, sizeof(uint8_t));
490 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
493 assert_return(m, -EINVAL);
494 assert_return(!m->sealed, -EPERM);
496 r = message_attribute_has_type(m, type, NLA_U16);
500 r = add_rtattr(m, type, &data, sizeof(uint16_t));
507 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
510 assert_return(m, -EINVAL);
511 assert_return(!m->sealed, -EPERM);
513 r = message_attribute_has_type(m, type, NLA_U32);
517 r = add_rtattr(m, type, &data, sizeof(uint32_t));
524 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
527 assert_return(m, -EINVAL);
528 assert_return(!m->sealed, -EPERM);
529 assert_return(data, -EINVAL);
531 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
535 r = add_rtattr(m, type, data, sizeof(struct in_addr));
542 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
545 assert_return(m, -EINVAL);
546 assert_return(!m->sealed, -EPERM);
547 assert_return(data, -EINVAL);
549 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
553 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
560 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
563 assert_return(m, -EINVAL);
564 assert_return(!m->sealed, -EPERM);
565 assert_return(data, -EINVAL);
567 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
571 r = add_rtattr(m, type, data, ETH_ALEN);
578 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
581 assert_return(m, -EINVAL);
582 assert_return(!m->sealed, -EPERM);
583 assert_return(info, -EINVAL);
585 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
589 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
596 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
600 assert_return(m, -EINVAL);
601 assert_return(!m->sealed, -EPERM);
603 r = message_attribute_has_type(m, type, NLA_NESTED);
609 r = type_system_get_type_system(m->container_type_system[m->n_containers],
610 &m->container_type_system[m->n_containers + 1],
615 r = add_rtattr(m, type, NULL, size);
622 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
623 const NLTypeSystemUnion *type_system_union;
626 assert_return(m, -EINVAL);
627 assert_return(!m->sealed, -EPERM);
629 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
633 r = type_system_union_get_type_system(type_system_union,
634 &m->container_type_system[m->n_containers + 1],
639 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
643 /* do we evere need non-null size */
644 r = add_rtattr(m, type, NULL, 0);
652 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
653 assert_return(m, -EINVAL);
654 assert_return(!m->sealed, -EPERM);
655 assert_return(m->n_containers > 0, -EINVAL);
657 m->container_type_system[m->n_containers] = NULL;
663 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
666 assert_return(m, -EINVAL);
667 assert_return(m->sealed, -EPERM);
668 assert_return(data, -EINVAL);
669 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
670 assert(m->rta_offset_tb[m->n_containers]);
671 assert(type < m->rta_tb_size[m->n_containers]);
673 if(!m->rta_offset_tb[m->n_containers][type])
676 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
678 *data = RTA_DATA(rta);
680 return RTA_PAYLOAD(rta);
683 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
687 r = message_attribute_has_type(m, type, NLA_STRING);
691 r = rtnl_message_read_internal(m, type, &attr_data);
694 else if (strnlen(attr_data, r) >= (size_t) r)
697 *data = (char *) attr_data;
702 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
706 r = message_attribute_has_type(m, type, NLA_U8);
710 r = rtnl_message_read_internal(m, type, &attr_data);
713 else if ((size_t) r < sizeof(uint8_t))
716 *data = *(uint8_t *) attr_data;
721 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
725 r = message_attribute_has_type(m, type, NLA_U16);
729 r = rtnl_message_read_internal(m, type, &attr_data);
732 else if ((size_t) r < sizeof(uint16_t))
735 *data = *(uint16_t *) attr_data;
740 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
744 r = message_attribute_has_type(m, type, NLA_U32);
748 r = rtnl_message_read_internal(m, type, &attr_data);
751 else if ((size_t)r < sizeof(uint32_t))
754 *data = *(uint32_t *) attr_data;
759 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
763 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
767 r = rtnl_message_read_internal(m, type, &attr_data);
770 else if ((size_t)r < sizeof(struct ether_addr))
773 memcpy(data, attr_data, sizeof(struct ether_addr));
778 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
782 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
786 r = rtnl_message_read_internal(m, type, &attr_data);
789 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
792 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
797 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
801 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
805 r = rtnl_message_read_internal(m, type, &attr_data);
808 else if ((size_t)r < sizeof(struct in_addr))
811 memcpy(data, attr_data, sizeof(struct in_addr));
816 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
820 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
824 r = rtnl_message_read_internal(m, type, &attr_data);
827 else if ((size_t)r < sizeof(struct in6_addr))
830 memcpy(data, attr_data, sizeof(struct in6_addr));
835 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
836 const NLType *nl_type;
837 const NLTypeSystem *type_system;
842 assert_return(m, -EINVAL);
843 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
845 r = type_system_get_type(m->container_type_system[m->n_containers],
851 if (nl_type->type == NLA_NESTED) {
852 r = type_system_get_type_system(m->container_type_system[m->n_containers],
857 } else if (nl_type->type == NLA_UNION) {
858 const NLTypeSystemUnion *type_system_union;
861 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
867 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
871 r = type_system_union_get_type_system(type_system_union,
879 r = rtnl_message_read_internal(m, type, &container);
887 r = rtnl_message_parse(m,
888 &m->rta_offset_tb[m->n_containers],
889 &m->rta_tb_size[m->n_containers],
898 m->container_type_system[m->n_containers] = type_system;
903 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
904 assert_return(m, -EINVAL);
905 assert_return(m->sealed, -EINVAL);
906 assert_return(m->n_containers > 0, -EINVAL);
908 free(m->rta_offset_tb[m->n_containers]);
909 m->rta_offset_tb[m->n_containers] = NULL;
910 m->container_type_system[m->n_containers] = NULL;
917 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
921 return m->hdr->nlmsg_seq;
924 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
925 struct nlmsgerr *err;
927 assert_return(m, -EINVAL);
928 assert_return(m->hdr, -EINVAL);
930 if (m->hdr->nlmsg_type != NLMSG_ERROR)
933 err = NLMSG_DATA(m->hdr);
938 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
942 /* ioctl(rtnl->fd, FIONREAD, &need)
943 Does not appear to work on netlink sockets. libnl uses
944 MSG_PEEK instead. I don't know if that is worth the
947 For now we simply use the maximum message size the kernel
948 may use (NLMSG_GOODSIZE), and then realloc to the actual
949 size after reading the message (hence avoiding huge memory
950 usage in case many small messages are kept around) */
958 int rtnl_message_parse(sd_rtnl_message *m,
959 size_t **rta_offset_tb,
960 unsigned short *rta_tb_size,
963 unsigned int rt_len) {
967 tb = new0(size_t, max + 1);
971 *rta_tb_size = max + 1;
973 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
974 type = rta->rta_type;
976 /* if the kernel is newer than the headers we used
977 when building, we ignore out-of-range attributes
983 log_debug("rtnl: message parse - overwriting repeated attribute");
985 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
993 /* returns the number of bytes sent, or a negative error code */
994 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
997 struct sockaddr_nl nl;
999 .nl.nl_family = AF_NETLINK,
1007 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1008 0, &addr.sa, sizeof(addr));
1010 return (errno == EAGAIN) ? 0 : -errno;
1015 /* On success, the number of bytes received is returned and *ret points to the received message
1016 * which has a valid header and the correct size.
1017 * If nothing useful was received 0 is returned.
1018 * On failure, a negative error code is returned.
1020 int socket_read_message(sd_rtnl *rtnl) {
1021 _cleanup_free_ void *buffer = NULL;
1022 struct nlmsghdr *new_msg;
1025 struct sockaddr_nl nl;
1027 socklen_t addr_len = sizeof(addr);
1033 r = message_receive_need(rtnl, &need);
1037 buffer = malloc0(need);
1041 r = recvfrom(rtnl->fd, buffer, need, 0, &addr.sa, &addr_len);
1043 return (errno == EAGAIN) ? 0 : -errno; /* no data */
1045 return -ECONNRESET; /* connection was closed by the kernel */
1046 else if (addr_len != sizeof(addr.nl) ||
1047 addr.nl.nl_family != AF_NETLINK)
1048 return -EIO; /* not a netlink message */
1049 else if (addr.nl.nl_pid != 0)
1050 return 0; /* not from the kernel */
1054 for (new_msg = buffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1055 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1056 const NLType *nl_type;
1058 if (new_msg->nlmsg_pid && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1059 /* not broadcast and not for us */
1062 /* silently drop noop messages */
1063 if (new_msg->nlmsg_type == NLMSG_NOOP)
1066 /* check that we support this message type */
1067 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1070 log_debug("sd-rtnl: ignored message with unknown type: %u",
1071 new_msg->nlmsg_type);
1076 /* check that the size matches the message type */
1077 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1080 r = message_new_empty(rtnl, &m);
1084 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1088 /* seal and parse the top-level message */
1089 r = sd_rtnl_message_rewind(m);
1093 r = rtnl_rqueue_make_room(rtnl);
1097 rtnl->rqueue[rtnl->rqueue_size ++] = m;
1099 ret += new_msg->nlmsg_len;
1101 /* reached end of multi-part message, or not a multi-part
1103 if (new_msg->nlmsg_type == NLMSG_DONE ||
1104 !(new_msg->nlmsg_flags & NLM_F_MULTI))
1111 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1116 assert_return(m, -EINVAL);
1118 /* don't allow appending to message once parsed */
1120 rtnl_message_seal(m);
1122 for (i = 1; i <= m->n_containers; i++) {
1123 free(m->rta_offset_tb[i]);
1124 m->rta_offset_tb[i] = NULL;
1125 m->rta_tb_size[i] = 0;
1126 m->container_type_system[i] = NULL;
1129 m->n_containers = 0;
1131 if (m->rta_offset_tb[0]) {
1132 /* top-level attributes have already been parsed */
1138 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1142 if (type->type == NLA_NESTED) {
1143 const NLTypeSystem *type_system = type->type_system;
1145 assert(type_system);
1147 m->container_type_system[0] = type_system;
1149 r = rtnl_message_parse(m,
1150 &m->rta_offset_tb[m->n_containers],
1151 &m->rta_tb_size[m->n_containers],
1153 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1154 NLMSG_ALIGN(type->size)),
1155 NLMSG_PAYLOAD(m->hdr, type->size));
1163 void rtnl_message_seal(sd_rtnl_message *m) {