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);
970 r = rtnl_message_parse(m,
971 &m->rta_offset_tb[m->n_containers + 1],
972 &m->rta_tb_size[m->n_containers + 1],
984 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
985 assert_return(m, -EINVAL);
986 assert_return(m->sealed, -EINVAL);
987 assert_return(m->n_containers > 0, -EINVAL);
989 free(m->rta_offset_tb[m->n_containers]);
990 m->rta_offset_tb[m->n_containers] = NULL;
997 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1001 return m->hdr->nlmsg_seq;
1004 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1005 struct nlmsgerr *err;
1007 assert_return(m, -EINVAL);
1008 assert_return(m->hdr, -EINVAL);
1010 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1013 err = NLMSG_DATA(m->hdr);
1018 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
1022 /* ioctl(rtnl->fd, FIONREAD, &need)
1023 Does not appear to work on netlink sockets. libnl uses
1024 MSG_PEEK instead. I don't know if that is worth the
1027 For now we simply use the maximum message size the kernel
1028 may use (NLMSG_GOODSIZE), and then realloc to the actual
1029 size after reading the message (hence avoiding huge memory
1030 usage in case many small messages are kept around) */
1031 *need = page_size();
1038 int rtnl_message_parse(sd_rtnl_message *m,
1039 size_t **rta_offset_tb,
1040 unsigned short *rta_tb_size,
1043 unsigned int rt_len) {
1044 unsigned short type;
1047 tb = (size_t *) new0(size_t *, max);
1053 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1054 type = rta->rta_type;
1057 log_debug("rtnl: message parse - ignore out of range attribute type");
1062 log_debug("rtnl: message parse - overwriting repeated attribute");
1064 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1067 *rta_offset_tb = tb;
1072 /* returns the number of bytes sent, or a negative error code */
1073 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1076 struct sockaddr_nl nl;
1078 .nl.nl_family = AF_NETLINK,
1086 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1087 0, &addr.sa, sizeof(addr));
1089 return (errno == EAGAIN) ? 0 : -errno;
1094 /* On success, the number of bytes received is returned and *ret points to the received message
1095 * which has a valid header and the correct size.
1096 * If nothing useful was received 0 is returned.
1097 * On failure, a negative error code is returned.
1099 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
1100 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1101 struct nlmsghdr *new_hdr;
1104 struct sockaddr_nl nl;
1113 r = message_receive_need(nl, &need);
1117 r = message_new(nl, &m, need);
1121 addr_len = sizeof(addr);
1123 r = recvfrom(nl->fd, m->hdr, need,
1124 0, &addr.sa, &addr_len);
1126 return (errno == EAGAIN) ? 0 : -errno; /* no data */
1128 return -ECONNRESET; /* connection was closed by the kernel */
1129 else if (addr_len != sizeof(addr.nl) ||
1130 addr.nl.nl_family != AF_NETLINK)
1131 return -EIO; /* not a netlink message */
1132 else if (addr.nl.nl_pid != 0)
1133 return 0; /* not from the kernel */
1134 else if ((size_t) r < sizeof(struct nlmsghdr) ||
1135 (size_t) r < m->hdr->nlmsg_len)
1136 return -EIO; /* too small (we do accept too big though) */
1137 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1138 return 0; /* not broadcast and not for us */
1142 /* check that the size matches the message type */
1143 switch (m->hdr->nlmsg_type) {
1146 if (len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1154 if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
1161 if (len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
1167 if (len < NLMSG_LENGTH(sizeof(struct rtmsg)))
1173 log_debug("sd-rtnl: ignored message with unknown type");
1177 /* we probably allocated way too much memory, give it back */
1178 new_hdr = realloc(m->hdr, len);
1183 /* seal and parse the top-level message */
1184 r = sd_rtnl_message_rewind(m);
1194 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1195 struct ifinfomsg *ifi;
1196 struct ifaddrmsg *ifa;
1201 assert_return(m, -EINVAL);
1202 assert_return(m->hdr, -EINVAL);
1204 /* don't allow appending to message once parsed */
1206 rtnl_message_seal(m);
1208 for (i = 1; i <= m->n_containers; i++) {
1209 free(m->rta_offset_tb[i]);
1210 m->rta_offset_tb[i] = NULL;
1211 m->rta_tb_size[i] = 0;
1214 m->n_containers = 0;
1216 if (m->rta_offset_tb[0]) {
1217 /* top-level attributes have already been parsed */
1221 /* parse top-level attributes */
1222 switch(m->hdr->nlmsg_type) {
1230 ifi = NLMSG_DATA(m->hdr);
1232 r = rtnl_message_parse(m,
1233 &m->rta_offset_tb[0],
1237 IFLA_PAYLOAD(m->hdr));
1245 ifa = NLMSG_DATA(m->hdr);
1247 r = rtnl_message_parse(m,
1248 &m->rta_offset_tb[0],
1252 IFA_PAYLOAD(m->hdr));
1260 rtm = NLMSG_DATA(m->hdr);
1262 r = rtnl_message_parse(m,
1263 &m->rta_offset_tb[0],
1267 RTM_PAYLOAD(m->hdr));
1277 void rtnl_message_seal(sd_rtnl_message *m) {