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 /* Note that 'rtnl' is curretly unused, if we start using it internally
50 we must take care to avoid problems due to mutual references between
51 busses and their queued messages. See sd-bus.
54 m = new0(sd_rtnl_message, 1);
58 m->hdr = malloc0(initial_size);
64 m->n_ref = REFCNT_INIT;
66 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
74 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
77 assert_return(m, -EINVAL);
78 assert_return(m->hdr, -EINVAL);
79 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
81 rtm = NLMSG_DATA(m->hdr);
83 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
84 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
87 rtm->rtm_dst_len = prefixlen;
92 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
95 assert_return(m, -EINVAL);
96 assert_return(m->hdr, -EINVAL);
97 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
99 rtm = NLMSG_DATA(m->hdr);
101 rtm->rtm_scope = scope;
106 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
107 uint16_t nlmsg_type, unsigned char rtm_family) {
111 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
112 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
113 assert_return(ret, -EINVAL);
115 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct rtmsg)));
119 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
120 (*ret)->hdr->nlmsg_type = nlmsg_type;
121 if (nlmsg_type == RTM_NEWROUTE)
122 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
124 rtm = NLMSG_DATA((*ret)->hdr);
126 rtm->rtm_family = rtm_family;
127 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
128 rtm->rtm_type = RTN_UNICAST;
129 rtm->rtm_table = RT_TABLE_MAIN;
130 rtm->rtm_protocol = RTPROT_BOOT;
135 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
136 struct ifinfomsg *ifi;
138 assert_return(m, -EINVAL);
139 assert_return(m->hdr, -EINVAL);
140 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
141 assert_return(change, -EINVAL);
143 ifi = NLMSG_DATA(m->hdr);
145 ifi->ifi_flags = flags;
146 ifi->ifi_change = change;
151 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
152 struct ifinfomsg *ifi;
154 assert_return(m, -EINVAL);
155 assert_return(m->hdr, -EINVAL);
156 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
158 ifi = NLMSG_DATA(m->hdr);
160 ifi->ifi_type = type;
165 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
166 uint16_t nlmsg_type, int index) {
167 struct ifinfomsg *ifi;
170 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
171 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
172 assert_return(ret, -EINVAL);
174 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
178 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
179 (*ret)->hdr->nlmsg_type = nlmsg_type;
180 if (nlmsg_type == RTM_NEWLINK)
181 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
183 ifi = NLMSG_DATA((*ret)->hdr);
185 ifi->ifi_family = AF_UNSPEC;
186 ifi->ifi_index = index;
191 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
192 struct ifaddrmsg *ifa;
194 assert_return(m, -EINVAL);
195 assert_return(m->hdr, -EINVAL);
196 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
198 ifa = NLMSG_DATA(m->hdr);
200 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
201 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
204 ifa->ifa_prefixlen = prefixlen;
209 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
210 struct ifaddrmsg *ifa;
212 assert_return(m, -EINVAL);
213 assert_return(m->hdr, -EINVAL);
214 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
216 ifa = NLMSG_DATA(m->hdr);
218 ifa->ifa_flags = flags;
223 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
224 struct ifaddrmsg *ifa;
226 assert_return(m, -EINVAL);
227 assert_return(m->hdr, -EINVAL);
228 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
230 ifa = NLMSG_DATA(m->hdr);
232 ifa->ifa_scope = scope;
237 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
238 uint16_t nlmsg_type, int index,
239 unsigned char family) {
240 struct ifaddrmsg *ifa;
243 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
244 assert_return(index > 0, -EINVAL);
245 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
246 assert_return(ret, -EINVAL);
248 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
252 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
253 (*ret)->hdr->nlmsg_type = nlmsg_type;
254 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
255 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
257 ifa = NLMSG_DATA((*ret)->hdr);
259 ifa->ifa_index = index;
260 ifa->ifa_family = family;
261 if (family == AF_INET)
262 ifa->ifa_prefixlen = 32;
263 else if (family == AF_INET6)
264 ifa->ifa_prefixlen = 128;
269 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
271 assert_se(REFCNT_INC(m->n_ref) >= 2);
276 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
277 if (m && REFCNT_DEC(m->n_ref) <= 0) {
282 for (i = 0; i < m->n_containers; i++)
283 free(m->rta_offset_tb[i]);
291 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
292 assert_return(m, -EINVAL);
293 assert_return(type, -EINVAL);
295 *type = m->hdr->nlmsg_type;
300 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
301 assert_return(m, -EINVAL);
303 return !m->hdr->nlmsg_pid;
306 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
307 struct ifinfomsg *ifi;
309 assert_return(m, -EINVAL);
310 assert_return(m->hdr, -EINVAL);
311 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
312 assert_return(ifindex, -EINVAL);
314 ifi = NLMSG_DATA(m->hdr);
316 *ifindex = ifi->ifi_index;
321 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
322 struct ifinfomsg *ifi;
324 assert_return(m, -EINVAL);
325 assert_return(m->hdr, -EINVAL);
326 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
327 assert_return(flags, -EINVAL);
329 ifi = NLMSG_DATA(m->hdr);
331 *flags = ifi->ifi_flags;
336 /* If successful the updated message will be correctly aligned, if
337 unsuccessful the old message is untouched. */
338 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
339 uint32_t rta_length, message_length;
340 struct nlmsghdr *new_hdr;
348 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
349 assert(!data || data_length > 0);
350 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
352 /* get the size of the new rta attribute (with padding at the end) */
353 rta_length = RTA_LENGTH(data_length);
355 /* get the new message size (with padding at the end) */
356 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
358 /* realloc to fit the new attribute */
359 new_hdr = realloc(m->hdr, message_length);
364 /* get pointer to the attribute we are about to add */
365 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
367 /* if we are inside containers, extend them */
368 for (i = 0; i < m->n_containers; i++)
369 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
371 /* fill in the attribute */
372 rta->rta_type = type;
373 rta->rta_len = rta_length;
375 /* this is the start of a new container */
376 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
378 /* we don't deal with the case where the user lies about the type
379 * and gives us too little data (so don't do that)
381 padding = mempcpy(RTA_DATA(rta), data, data_length);
382 /* make sure also the padding at the end of the message is initialized */
384 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
387 /* update message size */
388 m->hdr->nlmsg_len = message_length;
393 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
397 assert_return(m, -EINVAL);
398 assert_return(!m->sealed, -EPERM);
399 assert_return(data, -EINVAL);
401 r = sd_rtnl_message_get_type(m, &rtm_type);
405 /* check that the type is correct */
411 if (m->n_containers == 1) {
412 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
413 type != IFLA_INFO_KIND)
429 if (type != IFA_LABEL)
436 r = add_rtattr(m, type, data, strlen(data) + 1);
443 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
447 assert_return(m, -EINVAL);
448 assert_return(!m->sealed, -EPERM);
450 r = sd_rtnl_message_get_type(m, &rtm_type);
465 case IFLA_IPTUN_PROTO:
466 case IFLA_IPTUN_PMTUDISC:
467 case IFLA_IPTUN_ENCAP_LIMIT:
479 r = add_rtattr(m, type, &data, sizeof(uint8_t));
487 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
491 assert_return(m, -EINVAL);
492 assert_return(!m->sealed, -EPERM);
494 r = sd_rtnl_message_get_type(m, &rtm_type);
498 /* check that the type is correct */
504 if (m->n_containers == 2 &&
505 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
506 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA) {
509 case IFLA_IPTUN_FLAGS:
510 case IFLA_GRE_IFLAGS:
511 case IFLA_GRE_OFLAGS:
512 case IFLA_IPTUN_6RD_PREFIXLEN:
513 case IFLA_IPTUN_6RD_RELAY_PREFIXLEN:
526 r = add_rtattr(m, type, &data, sizeof(uint16_t));
533 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
537 assert_return(m, -EINVAL);
538 assert_return(!m->sealed, -EPERM);
540 r = sd_rtnl_message_get_type(m, &rtm_type);
544 /* check that the type is correct */
558 case IFLA_NET_NS_PID:
559 case IFLA_PROMISCUITY:
560 case IFLA_NUM_TX_QUEUES:
561 case IFLA_NUM_RX_QUEUES:
562 case IFLA_IPTUN_LOCAL:
563 case IFLA_IPTUN_REMOTE:
564 case IFLA_MACVLAN_MODE:
565 case IFLA_IPTUN_FLAGS:
566 case IFLA_IPTUN_FLOWINFO:
567 case IFLA_GRE_FLOWINFO:
591 r = add_rtattr(m, type, &data, sizeof(uint32_t));
598 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
599 struct ifaddrmsg *ifa;
604 assert_return(m, -EINVAL);
605 assert_return(!m->sealed, -EPERM);
606 assert_return(data, -EINVAL);
608 r = sd_rtnl_message_get_type(m, &rtm_type);
612 /* check that the type is correct */
623 case IFLA_GRE_REMOTE:
624 ifa = NLMSG_DATA(m->hdr);
626 if (ifa->ifa_family != AF_INET)
641 rtm = NLMSG_DATA(m->hdr);
643 if (rtm->rtm_family != AF_INET)
655 r = add_rtattr(m, type, data, sizeof(struct in_addr));
662 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
663 struct ifaddrmsg *ifa;
668 assert_return(m, -EINVAL);
669 assert_return(!m->sealed, -EPERM);
670 assert_return(data, -EINVAL);
672 r = sd_rtnl_message_get_type(m, &rtm_type);
676 /* check that the type is correct */
687 case IFLA_GRE_REMOTE:
688 case IFLA_IPTUN_6RD_PREFIX:
689 ifa = NLMSG_DATA(m->hdr);
691 if (ifa->ifa_family != AF_INET6)
706 rtm = NLMSG_DATA(m->hdr);
708 if (rtm->rtm_family != AF_INET6)
719 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
726 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
730 assert_return(m, -EINVAL);
731 assert_return(!m->sealed, -EPERM);
732 assert_return(data, -EINVAL);
734 sd_rtnl_message_get_type(m, &rtm_type);
753 r = add_rtattr(m, type, data, ETH_ALEN);
760 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
763 assert_return(m, -EINVAL);
764 assert_return(!m->sealed, -EPERM);
766 sd_rtnl_message_get_type(m, &rtm_type);
768 if (rtnl_message_type_is_link(rtm_type)) {
770 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
771 (type == IFLA_INFO_DATA && m->n_containers == 1 &&
772 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
773 return add_rtattr(m, type, NULL, 0);
774 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
775 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
776 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
777 return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
783 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
784 assert_return(m, -EINVAL);
785 assert_return(!m->sealed, -EPERM);
786 assert_return(m->n_containers > 0, -EINVAL);
793 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
796 assert_return(m, -EINVAL);
797 assert_return(m->sealed, -EPERM);
798 assert_return(data, -EINVAL);
799 assert_return(m->rta_offset_tb[m->n_containers], -EINVAL);
800 assert_return(type < m->rta_tb_size[m->n_containers], -EINVAL);
802 if(!m->rta_offset_tb[m->n_containers][type])
805 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
807 *data = RTA_DATA(rta);
809 return RTA_PAYLOAD(rta);
812 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
816 assert_return(data, -EINVAL);
818 r = rtnl_message_read_internal(m, type, &attr_data);
821 else if (strnlen(attr_data, r) >= (size_t) r)
824 *data = (char *) attr_data;
829 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
833 assert_return(data, -EINVAL);
835 r = rtnl_message_read_internal(m, type, &attr_data);
838 else if ((size_t) r < sizeof(uint8_t))
841 *data = *(uint8_t *) attr_data;
846 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
850 assert_return(data, -EINVAL);
852 r = rtnl_message_read_internal(m, type, &attr_data);
855 else if ((size_t) r < sizeof(uint16_t))
858 *data = *(uint16_t *) attr_data;
863 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
867 assert_return(data, -EINVAL);
869 r = rtnl_message_read_internal(m, type, &attr_data);
872 else if ((size_t)r < sizeof(uint32_t))
875 *data = *(uint32_t *) attr_data;
880 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
884 assert_return(data, -EINVAL);
886 r = rtnl_message_read_internal(m, type, &attr_data);
889 else if ((size_t)r < sizeof(struct ether_addr))
892 memcpy(data, attr_data, sizeof(struct ether_addr));
897 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
901 assert_return(data, -EINVAL);
903 r = rtnl_message_read_internal(m, type, &attr_data);
906 else if ((size_t)r < sizeof(struct in_addr))
909 memcpy(data, attr_data, sizeof(struct in_addr));
914 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
918 assert_return(data, -EINVAL);
920 r = rtnl_message_read_internal(m, type, &attr_data);
923 else if ((size_t)r < sizeof(struct in6_addr))
926 memcpy(data, attr_data, sizeof(struct in6_addr));
931 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
933 unsigned short parent_type;
935 size_t container_length;
938 assert_return(m, -EINVAL);
939 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
941 r = rtnl_message_read_internal(m, type, &container);
945 container_length = r;
947 r = sd_rtnl_message_get_type(m, &rtm_type);
951 if (rtnl_message_type_is_link(rtm_type)) {
952 switch (m->n_containers) {
963 parent_type = GET_CONTAINER(m, 0)->rta_type;
964 switch (parent_type) {
967 case IFLA_INFO_DATA: {
970 r = sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &kind);
974 if (streq(kind, "vlan")) {
976 } else if (streq(kind, "bridge")) {
977 max = IFLA_BRIDGE_MAX;
978 } else if (streq(kind, "veth")) {
980 container = IFLA_RTA(container);
1000 r = rtnl_message_parse(m,
1001 &m->rta_offset_tb[m->n_containers + 1],
1002 &m->rta_tb_size[m->n_containers + 1],
1014 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1015 assert_return(m, -EINVAL);
1016 assert_return(m->sealed, -EINVAL);
1017 assert_return(m->n_containers > 0, -EINVAL);
1019 free(m->rta_offset_tb[m->n_containers]);
1020 m->rta_offset_tb[m->n_containers] = NULL;
1027 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1031 return m->hdr->nlmsg_seq;
1034 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1035 struct nlmsgerr *err;
1037 assert_return(m, -EINVAL);
1038 assert_return(m->hdr, -EINVAL);
1040 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1043 err = NLMSG_DATA(m->hdr);
1048 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
1052 /* ioctl(rtnl->fd, FIONREAD, &need)
1053 Does not appear to work on netlink sockets. libnl uses
1054 MSG_PEEK instead. I don't know if that is worth the
1057 For now we simply use the maximum message size the kernel
1058 may use (NLMSG_GOODSIZE), and then realloc to the actual
1059 size after reading the message (hence avoiding huge memory
1060 usage in case many small messages are kept around) */
1061 *need = page_size();
1068 int rtnl_message_parse(sd_rtnl_message *m,
1069 size_t **rta_offset_tb,
1070 unsigned short *rta_tb_size,
1073 unsigned int rt_len) {
1074 unsigned short type;
1077 tb = (size_t *) new0(size_t *, max);
1083 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1084 type = rta->rta_type;
1087 log_debug("rtnl: message parse - ignore out of range attribute type");
1092 log_debug("rtnl: message parse - overwriting repeated attribute");
1094 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1097 *rta_offset_tb = tb;
1102 /* returns the number of bytes sent, or a negative error code */
1103 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1106 struct sockaddr_nl nl;
1108 .nl.nl_family = AF_NETLINK,
1116 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1117 0, &addr.sa, sizeof(addr));
1119 return (errno == EAGAIN) ? 0 : -errno;
1124 /* On success, the number of bytes received is returned and *ret points to the received message
1125 * which has a valid header and the correct size.
1126 * If nothing useful was received 0 is returned.
1127 * On failure, a negative error code is returned.
1129 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
1130 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1131 struct nlmsghdr *new_hdr;
1134 struct sockaddr_nl nl;
1143 r = message_receive_need(nl, &need);
1147 r = message_new(nl, &m, need);
1151 addr_len = sizeof(addr);
1153 r = recvfrom(nl->fd, m->hdr, need,
1154 0, &addr.sa, &addr_len);
1156 return (errno == EAGAIN) ? 0 : -errno; /* no data */
1158 return -ECONNRESET; /* connection was closed by the kernel */
1159 else if (addr_len != sizeof(addr.nl) ||
1160 addr.nl.nl_family != AF_NETLINK)
1161 return -EIO; /* not a netlink message */
1162 else if (addr.nl.nl_pid != 0)
1163 return 0; /* not from the kernel */
1164 else if ((size_t) r < sizeof(struct nlmsghdr) ||
1165 (size_t) r < m->hdr->nlmsg_len)
1166 return -EIO; /* too small (we do accept too big though) */
1167 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1168 return 0; /* not broadcast and not for us */
1172 /* check that the size matches the message type */
1173 switch (m->hdr->nlmsg_type) {
1176 if (len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1184 if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
1191 if (len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
1197 if (len < NLMSG_LENGTH(sizeof(struct rtmsg)))
1203 log_debug("sd-rtnl: ignored message with unknown type");
1207 /* we probably allocated way too much memory, give it back */
1208 new_hdr = realloc(m->hdr, len);
1213 /* seal and parse the top-level message */
1214 r = sd_rtnl_message_rewind(m);
1224 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1225 struct ifinfomsg *ifi;
1226 struct ifaddrmsg *ifa;
1231 assert_return(m, -EINVAL);
1232 assert_return(m->hdr, -EINVAL);
1234 /* don't allow appending to message once parsed */
1236 rtnl_message_seal(m);
1238 for (i = 1; i <= m->n_containers; i++) {
1239 free(m->rta_offset_tb[i]);
1240 m->rta_offset_tb[i] = NULL;
1241 m->rta_tb_size[i] = 0;
1244 m->n_containers = 0;
1246 if (m->rta_offset_tb[0]) {
1247 /* top-level attributes have already been parsed */
1251 /* parse top-level attributes */
1252 switch(m->hdr->nlmsg_type) {
1260 ifi = NLMSG_DATA(m->hdr);
1262 r = rtnl_message_parse(m,
1263 &m->rta_offset_tb[0],
1267 IFLA_PAYLOAD(m->hdr));
1275 ifa = NLMSG_DATA(m->hdr);
1277 r = rtnl_message_parse(m,
1278 &m->rta_offset_tb[0],
1282 IFA_PAYLOAD(m->hdr));
1290 rtm = NLMSG_DATA(m->hdr);
1292 r = rtnl_message_parse(m,
1293 &m->rta_offset_tb[0],
1297 RTM_PAYLOAD(m->hdr));
1307 void rtnl_message_seal(sd_rtnl_message *m) {