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/veth.h>
27 #include <linux/if_bridge.h>
34 #include "rtnl-util.h"
35 #include "rtnl-internal.h"
37 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
38 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
40 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, size_t initial_size) {
43 assert_return(ret, -EINVAL);
44 assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
46 m = new0(sd_rtnl_message, 1);
50 m->hdr = malloc0(initial_size);
56 m->n_ref = REFCNT_INIT;
58 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
62 m->rtnl = sd_rtnl_ref(rtnl);
69 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
72 assert_return(m, -EINVAL);
73 assert_return(m->hdr, -EINVAL);
74 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
76 rtm = NLMSG_DATA(m->hdr);
78 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
79 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
82 rtm->rtm_dst_len = prefixlen;
87 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
90 assert_return(m, -EINVAL);
91 assert_return(m->hdr, -EINVAL);
92 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
94 rtm = NLMSG_DATA(m->hdr);
96 rtm->rtm_scope = scope;
101 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
102 uint16_t nlmsg_type, unsigned char rtm_family) {
106 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
107 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
108 assert_return(ret, -EINVAL);
110 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct rtmsg)));
114 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
115 (*ret)->hdr->nlmsg_type = nlmsg_type;
116 if (nlmsg_type == RTM_NEWROUTE)
117 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
119 rtm = NLMSG_DATA((*ret)->hdr);
121 rtm->rtm_family = rtm_family;
122 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
123 rtm->rtm_type = RTN_UNICAST;
124 rtm->rtm_table = RT_TABLE_MAIN;
125 rtm->rtm_protocol = RTPROT_BOOT;
130 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
131 struct ifinfomsg *ifi;
133 assert_return(m, -EINVAL);
134 assert_return(m->hdr, -EINVAL);
135 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
136 assert_return(change, -EINVAL);
138 ifi = NLMSG_DATA(m->hdr);
140 ifi->ifi_flags = flags;
141 ifi->ifi_change = change;
146 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
147 struct ifinfomsg *ifi;
149 assert_return(m, -EINVAL);
150 assert_return(m->hdr, -EINVAL);
151 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
153 ifi = NLMSG_DATA(m->hdr);
155 ifi->ifi_type = type;
160 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
161 uint16_t nlmsg_type, int index) {
162 struct ifinfomsg *ifi;
165 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
166 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
167 assert_return(ret, -EINVAL);
169 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
173 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
174 (*ret)->hdr->nlmsg_type = nlmsg_type;
175 if (nlmsg_type == RTM_NEWLINK)
176 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
178 ifi = NLMSG_DATA((*ret)->hdr);
180 ifi->ifi_family = AF_UNSPEC;
181 ifi->ifi_index = index;
186 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
187 struct ifaddrmsg *ifa;
189 assert_return(m, -EINVAL);
190 assert_return(m->hdr, -EINVAL);
191 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
193 ifa = NLMSG_DATA(m->hdr);
195 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
196 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
199 ifa->ifa_prefixlen = prefixlen;
204 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
205 struct ifaddrmsg *ifa;
207 assert_return(m, -EINVAL);
208 assert_return(m->hdr, -EINVAL);
209 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
211 ifa = NLMSG_DATA(m->hdr);
213 ifa->ifa_flags = flags;
218 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
219 struct ifaddrmsg *ifa;
221 assert_return(m, -EINVAL);
222 assert_return(m->hdr, -EINVAL);
223 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
225 ifa = NLMSG_DATA(m->hdr);
227 ifa->ifa_scope = scope;
232 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
233 uint16_t nlmsg_type, int index,
234 unsigned char family) {
235 struct ifaddrmsg *ifa;
238 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
239 assert_return(index > 0, -EINVAL);
240 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
241 assert_return(ret, -EINVAL);
243 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
247 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
248 (*ret)->hdr->nlmsg_type = nlmsg_type;
249 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
250 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
252 ifa = NLMSG_DATA((*ret)->hdr);
254 ifa->ifa_index = index;
255 ifa->ifa_family = family;
256 if (family == AF_INET)
257 ifa->ifa_prefixlen = 32;
258 else if (family == AF_INET6)
259 ifa->ifa_prefixlen = 128;
264 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
266 assert_se(REFCNT_INC(m->n_ref) >= 2);
271 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
272 if (m && REFCNT_DEC(m->n_ref) <= 0) {
275 sd_rtnl_unref(m->rtnl);
278 for (i = 0; i < m->n_containers; i++)
279 free(m->rta_offset_tb[i]);
287 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
288 assert_return(m, -EINVAL);
289 assert_return(type, -EINVAL);
291 *type = m->hdr->nlmsg_type;
296 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
297 assert_return(m, -EINVAL);
299 return !m->hdr->nlmsg_pid;
302 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
303 struct ifinfomsg *ifi;
305 assert_return(m, -EINVAL);
306 assert_return(m->hdr, -EINVAL);
307 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
308 assert_return(ifindex, -EINVAL);
310 ifi = NLMSG_DATA(m->hdr);
312 *ifindex = ifi->ifi_index;
317 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
318 struct ifinfomsg *ifi;
320 assert_return(m, -EINVAL);
321 assert_return(m->hdr, -EINVAL);
322 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
323 assert_return(flags, -EINVAL);
325 ifi = NLMSG_DATA(m->hdr);
327 *flags = ifi->ifi_flags;
332 /* If successful the updated message will be correctly aligned, if
333 unsuccessful the old message is untouched. */
334 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
335 uint32_t rta_length, message_length;
336 struct nlmsghdr *new_hdr;
344 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
345 assert(!data || data_length > 0);
346 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
348 /* get the size of the new rta attribute (with padding at the end) */
349 rta_length = RTA_LENGTH(data_length);
351 /* get the new message size (with padding at the end) */
352 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
354 /* realloc to fit the new attribute */
355 new_hdr = realloc(m->hdr, message_length);
360 /* get pointer to the attribute we are about to add */
361 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
363 /* if we are inside containers, extend them */
364 for (i = 0; i < m->n_containers; i++)
365 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
367 /* fill in the attribute */
368 rta->rta_type = type;
369 rta->rta_len = rta_length;
371 /* this is the start of a new container */
372 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
374 /* we don't deal with the case where the user lies about the type
375 * and gives us too little data (so don't do that)
377 padding = mempcpy(RTA_DATA(rta), data, data_length);
378 /* make sure also the padding at the end of the message is initialized */
380 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
383 /* update message size */
384 m->hdr->nlmsg_len = message_length;
389 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
393 assert_return(m, -EINVAL);
394 assert_return(!m->sealed, -EPERM);
395 assert_return(data, -EINVAL);
397 r = sd_rtnl_message_get_type(m, &rtm_type);
401 /* check that the type is correct */
407 if (m->n_containers == 1) {
408 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
409 type != IFLA_INFO_KIND)
425 if (type != IFA_LABEL)
432 r = add_rtattr(m, type, data, strlen(data) + 1);
439 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
443 assert_return(m, -EINVAL);
444 assert_return(!m->sealed, -EPERM);
446 r = sd_rtnl_message_get_type(m, &rtm_type);
469 r = add_rtattr(m, type, &data, sizeof(uint8_t));
477 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
481 assert_return(m, -EINVAL);
482 assert_return(!m->sealed, -EPERM);
484 r = sd_rtnl_message_get_type(m, &rtm_type);
488 /* check that the type is correct */
494 if (m->n_containers == 2 &&
495 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
496 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
497 type == IFLA_VLAN_ID)
506 r = add_rtattr(m, type, &data, sizeof(uint16_t));
513 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
517 assert_return(m, -EINVAL);
518 assert_return(!m->sealed, -EPERM);
520 r = sd_rtnl_message_get_type(m, &rtm_type);
524 /* check that the type is correct */
538 case IFLA_NET_NS_PID:
539 case IFLA_PROMISCUITY:
540 case IFLA_NUM_TX_QUEUES:
541 case IFLA_NUM_RX_QUEUES:
542 case IFLA_MACVLAN_MODE:
566 r = add_rtattr(m, type, &data, sizeof(uint32_t));
573 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
574 struct ifaddrmsg *ifa;
579 assert_return(m, -EINVAL);
580 assert_return(!m->sealed, -EPERM);
581 assert_return(data, -EINVAL);
583 r = sd_rtnl_message_get_type(m, &rtm_type);
587 /* check that the type is correct */
597 ifa = NLMSG_DATA(m->hdr);
599 if (ifa->ifa_family != AF_INET)
614 rtm = NLMSG_DATA(m->hdr);
616 if (rtm->rtm_family != AF_INET)
628 r = add_rtattr(m, type, data, sizeof(struct in_addr));
635 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
636 struct ifaddrmsg *ifa;
641 assert_return(m, -EINVAL);
642 assert_return(!m->sealed, -EPERM);
643 assert_return(data, -EINVAL);
645 r = sd_rtnl_message_get_type(m, &rtm_type);
649 /* check that the type is correct */
659 ifa = NLMSG_DATA(m->hdr);
661 if (ifa->ifa_family != AF_INET6)
676 rtm = NLMSG_DATA(m->hdr);
678 if (rtm->rtm_family != AF_INET6)
689 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
696 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
700 assert_return(m, -EINVAL);
701 assert_return(!m->sealed, -EPERM);
702 assert_return(data, -EINVAL);
704 sd_rtnl_message_get_type(m, &rtm_type);
723 r = add_rtattr(m, type, data, ETH_ALEN);
730 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
733 assert_return(m, -EINVAL);
734 assert_return(!m->sealed, -EPERM);
736 sd_rtnl_message_get_type(m, &rtm_type);
738 if (rtnl_message_type_is_link(rtm_type)) {
740 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
741 (type == IFLA_INFO_DATA && m->n_containers == 1 &&
742 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
743 return add_rtattr(m, type, NULL, 0);
744 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
745 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
746 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
747 return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
753 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
754 assert_return(m, -EINVAL);
755 assert_return(!m->sealed, -EPERM);
756 assert_return(m->n_containers > 0, -EINVAL);
763 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
766 assert_return(m, -EINVAL);
767 assert_return(m->sealed, -EPERM);
768 assert_return(data, -EINVAL);
769 assert_return(m->rta_offset_tb[m->n_containers], -EINVAL);
770 assert_return(type < m->rta_tb_size[m->n_containers], -EINVAL);
772 if(!m->rta_offset_tb[m->n_containers][type])
775 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
777 *data = RTA_DATA(rta);
779 return RTA_PAYLOAD(rta);
782 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
786 assert_return(data, -EINVAL);
788 r = rtnl_message_read_internal(m, type, &attr_data);
791 else if (strnlen(attr_data, r) >= (size_t) r)
794 *data = (char *) attr_data;
799 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
803 assert_return(data, -EINVAL);
805 r = rtnl_message_read_internal(m, type, &attr_data);
808 else if ((size_t) r < sizeof(uint8_t))
811 *data = *(uint8_t *) attr_data;
816 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
820 assert_return(data, -EINVAL);
822 r = rtnl_message_read_internal(m, type, &attr_data);
825 else if ((size_t) r < sizeof(uint16_t))
828 *data = *(uint16_t *) attr_data;
833 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
837 assert_return(data, -EINVAL);
839 r = rtnl_message_read_internal(m, type, &attr_data);
842 else if ((size_t)r < sizeof(uint32_t))
845 *data = *(uint32_t *) attr_data;
850 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
854 assert_return(data, -EINVAL);
856 r = rtnl_message_read_internal(m, type, &attr_data);
859 else if ((size_t)r < sizeof(struct ether_addr))
862 memcpy(data, attr_data, sizeof(struct ether_addr));
867 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
871 assert_return(data, -EINVAL);
873 r = rtnl_message_read_internal(m, type, &attr_data);
876 else if ((size_t)r < sizeof(struct in_addr))
879 memcpy(data, attr_data, sizeof(struct in_addr));
884 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
888 assert_return(data, -EINVAL);
890 r = rtnl_message_read_internal(m, type, &attr_data);
893 else if ((size_t)r < sizeof(struct in6_addr))
896 memcpy(data, attr_data, sizeof(struct in6_addr));
901 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
903 unsigned short parent_type;
905 size_t container_length;
908 assert_return(m, -EINVAL);
909 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
911 r = rtnl_message_read_internal(m, type, &container);
915 container_length = r;
917 r = sd_rtnl_message_get_type(m, &rtm_type);
921 if (rtnl_message_type_is_link(rtm_type)) {
922 switch (m->n_containers) {
933 parent_type = GET_CONTAINER(m, 0)->rta_type;
934 switch (parent_type) {
937 case IFLA_INFO_DATA: {
940 r = sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &kind);
944 if (streq(kind, "vlan")) {
946 } else if (streq(kind, "bridge")) {
947 max = IFLA_BRIDGE_MAX;
948 } else if (streq(kind, "veth")) {
950 container = IFLA_RTA(container);
969 r = rtnl_message_parse(m,
970 &m->rta_offset_tb[m->n_containers + 1],
971 &m->rta_tb_size[m->n_containers + 1],
983 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
984 assert_return(m, -EINVAL);
985 assert_return(m->sealed, -EINVAL);
986 assert_return(m->n_containers > 0, -EINVAL);
988 free(m->rta_offset_tb[m->n_containers]);
989 m->rta_offset_tb[m->n_containers] = NULL;
996 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1000 return m->hdr->nlmsg_seq;
1003 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1004 struct nlmsgerr *err;
1006 assert_return(m, -EINVAL);
1007 assert_return(m->hdr, -EINVAL);
1009 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1012 err = NLMSG_DATA(m->hdr);
1017 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
1021 /* ioctl(rtnl->fd, FIONREAD, &need)
1022 Does not appear to work on netlink sockets. libnl uses
1023 MSG_PEEK instead. I don't know if that is worth the
1026 For now we simply use the maximum message size the kernel
1027 may use (NLMSG_GOODSIZE), and then realloc to the actual
1028 size after reading the message (hence avoiding huge memory
1029 usage in case many small messages are kept around) */
1030 *need = page_size();
1037 int rtnl_message_parse(sd_rtnl_message *m,
1038 size_t **rta_offset_tb,
1039 unsigned short *rta_tb_size,
1042 unsigned int rt_len) {
1046 tb = (size_t *) new0(size_t *, max);
1052 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1053 type = rta->rta_type;
1056 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1059 *rta_offset_tb = tb;
1064 /* returns the number of bytes sent, or a negative error code */
1065 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1068 struct sockaddr_nl nl;
1070 .nl.nl_family = AF_NETLINK,
1078 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1079 0, &addr.sa, sizeof(addr));
1081 return (errno == EAGAIN) ? 0 : -errno;
1086 /* On success, the number of bytes received is returned and *ret points to the received message
1087 * which has a valid header and the correct size.
1088 * If nothing useful was received 0 is returned.
1089 * On failure, a negative error code is returned.
1091 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
1092 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1093 struct nlmsghdr *new_hdr;
1096 struct sockaddr_nl nl;
1105 r = message_receive_need(nl, &need);
1109 r = message_new(nl, &m, need);
1113 addr_len = sizeof(addr);
1115 r = recvfrom(nl->fd, m->hdr, need,
1116 0, &addr.sa, &addr_len);
1118 return (errno == EAGAIN) ? 0 : -errno; /* no data */
1120 return -ECONNRESET; /* connection was closed by the kernel */
1121 else if (addr_len != sizeof(addr.nl) ||
1122 addr.nl.nl_family != AF_NETLINK)
1123 return -EIO; /* not a netlink message */
1124 else if (addr.nl.nl_pid != 0)
1125 return 0; /* not from the kernel */
1126 else if ((size_t) r < sizeof(struct nlmsghdr) ||
1127 (size_t) r < m->hdr->nlmsg_len)
1128 return -EIO; /* too small (we do accept too big though) */
1129 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1130 return 0; /* not broadcast and not for us */
1134 /* check that the size matches the message type */
1135 switch (m->hdr->nlmsg_type) {
1138 if (len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1146 if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
1153 if (len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
1159 if (len < NLMSG_LENGTH(sizeof(struct rtmsg)))
1165 log_debug("sd-rtnl: ignored message with unknown type");
1169 /* we probably allocated way too much memory, give it back */
1170 new_hdr = realloc(m->hdr, len);
1175 /* seal and parse the top-level message */
1176 r = sd_rtnl_message_rewind(m);
1186 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1187 struct ifinfomsg *ifi;
1188 struct ifaddrmsg *ifa;
1193 assert_return(m, -EINVAL);
1194 assert_return(m->hdr, -EINVAL);
1196 /* don't allow appending to message once parsed */
1198 rtnl_message_seal(m);
1200 for (i = 1; i <= m->n_containers; i++) {
1201 free(m->rta_offset_tb[i]);
1202 m->rta_offset_tb[i] = NULL;
1203 m->rta_tb_size[i] = 0;
1206 m->n_containers = 0;
1208 if (m->rta_offset_tb[0]) {
1209 /* top-level attributes have already been parsed */
1213 /* parse top-level attributes */
1214 switch(m->hdr->nlmsg_type) {
1222 ifi = NLMSG_DATA(m->hdr);
1224 r = rtnl_message_parse(m,
1225 &m->rta_offset_tb[0],
1229 IFLA_PAYLOAD(m->hdr));
1237 ifa = NLMSG_DATA(m->hdr);
1239 r = rtnl_message_parse(m,
1240 &m->rta_offset_tb[0],
1244 IFA_PAYLOAD(m->hdr));
1252 rtm = NLMSG_DATA(m->hdr);
1254 r = rtnl_message_parse(m,
1255 &m->rta_offset_tb[0],
1259 RTM_PAYLOAD(m->hdr));
1269 void rtnl_message_seal(sd_rtnl_message *m) {