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>
29 #include <linux/if_tunnel.h>
30 #include <linux/if_bridge.h>
37 #include "rtnl-util.h"
38 #include "rtnl-internal.h"
40 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
41 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
43 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, size_t initial_size) {
46 assert_return(ret, -EINVAL);
47 assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
49 m = new0(sd_rtnl_message, 1);
53 m->hdr = malloc0(initial_size);
59 m->n_ref = REFCNT_INIT;
61 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
65 m->rtnl = sd_rtnl_ref(rtnl);
72 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
75 assert_return(m, -EINVAL);
76 assert_return(m->hdr, -EINVAL);
77 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
79 rtm = NLMSG_DATA(m->hdr);
81 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
82 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
85 rtm->rtm_dst_len = prefixlen;
90 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
93 assert_return(m, -EINVAL);
94 assert_return(m->hdr, -EINVAL);
95 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
97 rtm = NLMSG_DATA(m->hdr);
99 rtm->rtm_scope = scope;
104 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
105 uint16_t nlmsg_type, unsigned char rtm_family) {
109 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
110 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
111 assert_return(ret, -EINVAL);
113 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct rtmsg)));
117 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
118 (*ret)->hdr->nlmsg_type = nlmsg_type;
119 if (nlmsg_type == RTM_NEWROUTE)
120 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
122 rtm = NLMSG_DATA((*ret)->hdr);
124 rtm->rtm_family = rtm_family;
125 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
126 rtm->rtm_type = RTN_UNICAST;
127 rtm->rtm_table = RT_TABLE_MAIN;
128 rtm->rtm_protocol = RTPROT_BOOT;
133 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
134 struct ifinfomsg *ifi;
136 assert_return(m, -EINVAL);
137 assert_return(m->hdr, -EINVAL);
138 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
139 assert_return(change, -EINVAL);
141 ifi = NLMSG_DATA(m->hdr);
143 ifi->ifi_flags = flags;
144 ifi->ifi_change = change;
149 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
150 struct ifinfomsg *ifi;
152 assert_return(m, -EINVAL);
153 assert_return(m->hdr, -EINVAL);
154 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
156 ifi = NLMSG_DATA(m->hdr);
158 ifi->ifi_type = type;
163 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
164 uint16_t nlmsg_type, int index) {
165 struct ifinfomsg *ifi;
168 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
169 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
170 assert_return(ret, -EINVAL);
172 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
176 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
177 (*ret)->hdr->nlmsg_type = nlmsg_type;
178 if (nlmsg_type == RTM_NEWLINK)
179 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
181 ifi = NLMSG_DATA((*ret)->hdr);
183 ifi->ifi_family = AF_UNSPEC;
184 ifi->ifi_index = index;
189 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
190 struct ifaddrmsg *ifa;
192 assert_return(m, -EINVAL);
193 assert_return(m->hdr, -EINVAL);
194 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
196 ifa = NLMSG_DATA(m->hdr);
198 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
199 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
202 ifa->ifa_prefixlen = prefixlen;
207 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
208 struct ifaddrmsg *ifa;
210 assert_return(m, -EINVAL);
211 assert_return(m->hdr, -EINVAL);
212 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
214 ifa = NLMSG_DATA(m->hdr);
216 ifa->ifa_flags = flags;
221 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
222 struct ifaddrmsg *ifa;
224 assert_return(m, -EINVAL);
225 assert_return(m->hdr, -EINVAL);
226 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
228 ifa = NLMSG_DATA(m->hdr);
230 ifa->ifa_scope = scope;
235 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
236 uint16_t nlmsg_type, int index,
237 unsigned char family) {
238 struct ifaddrmsg *ifa;
241 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
242 assert_return(index > 0, -EINVAL);
243 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
244 assert_return(ret, -EINVAL);
246 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
250 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
251 (*ret)->hdr->nlmsg_type = nlmsg_type;
252 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
253 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
255 ifa = NLMSG_DATA((*ret)->hdr);
257 ifa->ifa_index = index;
258 ifa->ifa_family = family;
259 if (family == AF_INET)
260 ifa->ifa_prefixlen = 32;
261 else if (family == AF_INET6)
262 ifa->ifa_prefixlen = 128;
267 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
269 assert_se(REFCNT_INC(m->n_ref) >= 2);
274 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
275 if (m && REFCNT_DEC(m->n_ref) <= 0) {
278 sd_rtnl_unref(m->rtnl);
281 for (i = 0; i < m->n_containers; i++)
282 free(m->rta_offset_tb[i]);
290 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
291 assert_return(m, -EINVAL);
292 assert_return(type, -EINVAL);
294 *type = m->hdr->nlmsg_type;
299 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
300 assert_return(m, -EINVAL);
302 return !m->hdr->nlmsg_pid;
305 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
306 struct ifinfomsg *ifi;
308 assert_return(m, -EINVAL);
309 assert_return(m->hdr, -EINVAL);
310 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
311 assert_return(ifindex, -EINVAL);
313 ifi = NLMSG_DATA(m->hdr);
315 *ifindex = ifi->ifi_index;
320 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
321 struct ifinfomsg *ifi;
323 assert_return(m, -EINVAL);
324 assert_return(m->hdr, -EINVAL);
325 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
326 assert_return(flags, -EINVAL);
328 ifi = NLMSG_DATA(m->hdr);
330 *flags = ifi->ifi_flags;
335 /* If successful the updated message will be correctly aligned, if
336 unsuccessful the old message is untouched. */
337 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
338 uint32_t rta_length, message_length;
339 struct nlmsghdr *new_hdr;
347 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
348 assert(!data || data_length > 0);
349 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
351 /* get the size of the new rta attribute (with padding at the end) */
352 rta_length = RTA_LENGTH(data_length);
354 /* get the new message size (with padding at the end) */
355 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
357 /* realloc to fit the new attribute */
358 new_hdr = realloc(m->hdr, message_length);
363 /* get pointer to the attribute we are about to add */
364 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
366 /* if we are inside containers, extend them */
367 for (i = 0; i < m->n_containers; i++)
368 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
370 /* fill in the attribute */
371 rta->rta_type = type;
372 rta->rta_len = rta_length;
374 /* this is the start of a new container */
375 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
377 /* we don't deal with the case where the user lies about the type
378 * and gives us too little data (so don't do that)
380 padding = mempcpy(RTA_DATA(rta), data, data_length);
381 /* make sure also the padding at the end of the message is initialized */
383 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
386 /* update message size */
387 m->hdr->nlmsg_len = message_length;
392 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
396 assert_return(m, -EINVAL);
397 assert_return(!m->sealed, -EPERM);
398 assert_return(data, -EINVAL);
400 r = sd_rtnl_message_get_type(m, &rtm_type);
404 /* check that the type is correct */
410 if (m->n_containers == 1) {
411 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
412 type != IFLA_INFO_KIND)
428 if (type != IFA_LABEL)
435 r = add_rtattr(m, type, data, strlen(data) + 1);
442 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
446 assert_return(m, -EINVAL);
447 assert_return(!m->sealed, -EPERM);
449 r = sd_rtnl_message_get_type(m, &rtm_type);
464 case IFLA_IPTUN_PROTO:
465 case IFLA_IPTUN_PMTUDISC:
466 case IFLA_IPTUN_ENCAP_LIMIT:
478 r = add_rtattr(m, type, &data, sizeof(uint8_t));
486 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
490 assert_return(m, -EINVAL);
491 assert_return(!m->sealed, -EPERM);
493 r = sd_rtnl_message_get_type(m, &rtm_type);
497 /* check that the type is correct */
503 if (m->n_containers == 2 &&
504 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
505 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA) {
508 case IFLA_IPTUN_FLAGS:
509 case IFLA_GRE_IFLAGS:
510 case IFLA_GRE_OFLAGS:
511 case IFLA_IPTUN_6RD_PREFIXLEN:
512 case IFLA_IPTUN_6RD_RELAY_PREFIXLEN:
525 r = add_rtattr(m, type, &data, sizeof(uint16_t));
532 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
536 assert_return(m, -EINVAL);
537 assert_return(!m->sealed, -EPERM);
539 r = sd_rtnl_message_get_type(m, &rtm_type);
543 /* check that the type is correct */
557 case IFLA_NET_NS_PID:
558 case IFLA_PROMISCUITY:
559 case IFLA_NUM_TX_QUEUES:
560 case IFLA_NUM_RX_QUEUES:
561 case IFLA_IPTUN_LOCAL:
562 case IFLA_IPTUN_REMOTE:
563 case IFLA_MACVLAN_MODE:
564 case IFLA_IPTUN_FLAGS:
565 case IFLA_IPTUN_FLOWINFO:
566 case IFLA_GRE_FLOWINFO:
590 r = add_rtattr(m, type, &data, sizeof(uint32_t));
597 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
598 struct ifaddrmsg *ifa;
603 assert_return(m, -EINVAL);
604 assert_return(!m->sealed, -EPERM);
605 assert_return(data, -EINVAL);
607 r = sd_rtnl_message_get_type(m, &rtm_type);
611 /* check that the type is correct */
622 case IFLA_GRE_REMOTE:
623 ifa = NLMSG_DATA(m->hdr);
625 if (ifa->ifa_family != AF_INET)
640 rtm = NLMSG_DATA(m->hdr);
642 if (rtm->rtm_family != AF_INET)
654 r = add_rtattr(m, type, data, sizeof(struct in_addr));
661 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
662 struct ifaddrmsg *ifa;
667 assert_return(m, -EINVAL);
668 assert_return(!m->sealed, -EPERM);
669 assert_return(data, -EINVAL);
671 r = sd_rtnl_message_get_type(m, &rtm_type);
675 /* check that the type is correct */
686 case IFLA_GRE_REMOTE:
687 case IFLA_IPTUN_6RD_PREFIX:
688 ifa = NLMSG_DATA(m->hdr);
690 if (ifa->ifa_family != AF_INET6)
705 rtm = NLMSG_DATA(m->hdr);
707 if (rtm->rtm_family != AF_INET6)
718 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
725 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
729 assert_return(m, -EINVAL);
730 assert_return(!m->sealed, -EPERM);
731 assert_return(data, -EINVAL);
733 sd_rtnl_message_get_type(m, &rtm_type);
752 r = add_rtattr(m, type, data, ETH_ALEN);
759 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
762 assert_return(m, -EINVAL);
763 assert_return(!m->sealed, -EPERM);
765 sd_rtnl_message_get_type(m, &rtm_type);
767 if (rtnl_message_type_is_link(rtm_type)) {
769 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
770 (type == IFLA_INFO_DATA && m->n_containers == 1 &&
771 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
772 return add_rtattr(m, type, NULL, 0);
773 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
774 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
775 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
776 return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
782 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
783 assert_return(m, -EINVAL);
784 assert_return(!m->sealed, -EPERM);
785 assert_return(m->n_containers > 0, -EINVAL);
792 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
795 assert_return(m, -EINVAL);
796 assert_return(m->sealed, -EPERM);
797 assert_return(data, -EINVAL);
798 assert_return(m->rta_offset_tb[m->n_containers], -EINVAL);
799 assert_return(type < m->rta_tb_size[m->n_containers], -EINVAL);
801 if(!m->rta_offset_tb[m->n_containers][type])
804 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
806 *data = RTA_DATA(rta);
808 return RTA_PAYLOAD(rta);
811 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
815 assert_return(data, -EINVAL);
817 r = rtnl_message_read_internal(m, type, &attr_data);
820 else if (strnlen(attr_data, r) >= (size_t) r)
823 *data = (char *) attr_data;
828 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
832 assert_return(data, -EINVAL);
834 r = rtnl_message_read_internal(m, type, &attr_data);
837 else if ((size_t) r < sizeof(uint8_t))
840 *data = *(uint8_t *) attr_data;
845 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
849 assert_return(data, -EINVAL);
851 r = rtnl_message_read_internal(m, type, &attr_data);
854 else if ((size_t) r < sizeof(uint16_t))
857 *data = *(uint16_t *) attr_data;
862 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
866 assert_return(data, -EINVAL);
868 r = rtnl_message_read_internal(m, type, &attr_data);
871 else if ((size_t)r < sizeof(uint32_t))
874 *data = *(uint32_t *) attr_data;
879 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
883 assert_return(data, -EINVAL);
885 r = rtnl_message_read_internal(m, type, &attr_data);
888 else if ((size_t)r < sizeof(struct ether_addr))
891 memcpy(data, attr_data, sizeof(struct ether_addr));
896 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
900 assert_return(data, -EINVAL);
902 r = rtnl_message_read_internal(m, type, &attr_data);
905 else if ((size_t)r < sizeof(struct in_addr))
908 memcpy(data, attr_data, sizeof(struct in_addr));
913 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
917 assert_return(data, -EINVAL);
919 r = rtnl_message_read_internal(m, type, &attr_data);
922 else if ((size_t)r < sizeof(struct in6_addr))
925 memcpy(data, attr_data, sizeof(struct in6_addr));
930 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
932 unsigned short parent_type;
934 size_t container_length;
937 assert_return(m, -EINVAL);
938 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
940 r = rtnl_message_read_internal(m, type, &container);
944 container_length = r;
946 r = sd_rtnl_message_get_type(m, &rtm_type);
950 if (rtnl_message_type_is_link(rtm_type)) {
951 switch (m->n_containers) {
962 parent_type = GET_CONTAINER(m, 0)->rta_type;
963 switch (parent_type) {
966 case IFLA_INFO_DATA: {
969 r = sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &kind);
973 if (streq(kind, "vlan")) {
975 } else if (streq(kind, "bridge")) {
976 max = IFLA_BRIDGE_MAX;
977 } else if (streq(kind, "veth")) {
979 container = IFLA_RTA(container);
999 r = rtnl_message_parse(m,
1000 &m->rta_offset_tb[m->n_containers + 1],
1001 &m->rta_tb_size[m->n_containers + 1],
1013 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1014 assert_return(m, -EINVAL);
1015 assert_return(m->sealed, -EINVAL);
1016 assert_return(m->n_containers > 0, -EINVAL);
1018 free(m->rta_offset_tb[m->n_containers]);
1019 m->rta_offset_tb[m->n_containers] = NULL;
1026 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1030 return m->hdr->nlmsg_seq;
1033 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1034 struct nlmsgerr *err;
1036 assert_return(m, -EINVAL);
1037 assert_return(m->hdr, -EINVAL);
1039 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1042 err = NLMSG_DATA(m->hdr);
1047 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
1051 /* ioctl(rtnl->fd, FIONREAD, &need)
1052 Does not appear to work on netlink sockets. libnl uses
1053 MSG_PEEK instead. I don't know if that is worth the
1056 For now we simply use the maximum message size the kernel
1057 may use (NLMSG_GOODSIZE), and then realloc to the actual
1058 size after reading the message (hence avoiding huge memory
1059 usage in case many small messages are kept around) */
1060 *need = page_size();
1067 int rtnl_message_parse(sd_rtnl_message *m,
1068 size_t **rta_offset_tb,
1069 unsigned short *rta_tb_size,
1072 unsigned int rt_len) {
1073 unsigned short type;
1076 tb = (size_t *) new0(size_t *, max);
1082 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1083 type = rta->rta_type;
1086 log_debug("rtnl: message parse - ignore out of range attribute type");
1091 log_debug("rtnl: message parse - overwriting repeated attribute");
1093 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1096 *rta_offset_tb = tb;
1101 /* returns the number of bytes sent, or a negative error code */
1102 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1105 struct sockaddr_nl nl;
1107 .nl.nl_family = AF_NETLINK,
1115 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1116 0, &addr.sa, sizeof(addr));
1118 return (errno == EAGAIN) ? 0 : -errno;
1123 /* On success, the number of bytes received is returned and *ret points to the received message
1124 * which has a valid header and the correct size.
1125 * If nothing useful was received 0 is returned.
1126 * On failure, a negative error code is returned.
1128 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
1129 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1130 struct nlmsghdr *new_hdr;
1133 struct sockaddr_nl nl;
1142 r = message_receive_need(nl, &need);
1146 r = message_new(nl, &m, need);
1150 addr_len = sizeof(addr);
1152 r = recvfrom(nl->fd, m->hdr, need,
1153 0, &addr.sa, &addr_len);
1155 return (errno == EAGAIN) ? 0 : -errno; /* no data */
1157 return -ECONNRESET; /* connection was closed by the kernel */
1158 else if (addr_len != sizeof(addr.nl) ||
1159 addr.nl.nl_family != AF_NETLINK)
1160 return -EIO; /* not a netlink message */
1161 else if (addr.nl.nl_pid != 0)
1162 return 0; /* not from the kernel */
1163 else if ((size_t) r < sizeof(struct nlmsghdr) ||
1164 (size_t) r < m->hdr->nlmsg_len)
1165 return -EIO; /* too small (we do accept too big though) */
1166 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1167 return 0; /* not broadcast and not for us */
1171 /* check that the size matches the message type */
1172 switch (m->hdr->nlmsg_type) {
1175 if (len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1183 if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
1190 if (len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
1196 if (len < NLMSG_LENGTH(sizeof(struct rtmsg)))
1202 log_debug("sd-rtnl: ignored message with unknown type");
1206 /* we probably allocated way too much memory, give it back */
1207 new_hdr = realloc(m->hdr, len);
1212 /* seal and parse the top-level message */
1213 r = sd_rtnl_message_rewind(m);
1223 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1224 struct ifinfomsg *ifi;
1225 struct ifaddrmsg *ifa;
1230 assert_return(m, -EINVAL);
1231 assert_return(m->hdr, -EINVAL);
1233 /* don't allow appending to message once parsed */
1235 rtnl_message_seal(m);
1237 for (i = 1; i <= m->n_containers; i++) {
1238 free(m->rta_offset_tb[i]);
1239 m->rta_offset_tb[i] = NULL;
1240 m->rta_tb_size[i] = 0;
1243 m->n_containers = 0;
1245 if (m->rta_offset_tb[0]) {
1246 /* top-level attributes have already been parsed */
1250 /* parse top-level attributes */
1251 switch(m->hdr->nlmsg_type) {
1259 ifi = NLMSG_DATA(m->hdr);
1261 r = rtnl_message_parse(m,
1262 &m->rta_offset_tb[0],
1266 IFLA_PAYLOAD(m->hdr));
1274 ifa = NLMSG_DATA(m->hdr);
1276 r = rtnl_message_parse(m,
1277 &m->rta_offset_tb[0],
1281 IFA_PAYLOAD(m->hdr));
1289 rtm = NLMSG_DATA(m->hdr);
1291 r = rtnl_message_parse(m,
1292 &m->rta_offset_tb[0],
1296 RTM_PAYLOAD(m->hdr));
1306 void rtnl_message_seal(sd_rtnl_message *m) {