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 <linux/rtnetlink.h>
23 #include <netinet/in.h>
24 #include <netinet/ether.h>
27 #include <linux/veth.h>
33 #include "rtnl-util.h"
34 #include "rtnl-internal.h"
36 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
37 #define NEXT_RTA(m) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->next_rta_offset))
38 #define UPDATE_RTA(m, new) (m)->next_rta_offset = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
39 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
41 int message_new(sd_rtnl_message **ret, size_t initial_size) {
44 assert_return(ret, -EINVAL);
45 assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
47 m = new0(sd_rtnl_message, 1);
51 m->hdr = malloc0(initial_size);
57 m->n_ref = REFCNT_INIT;
59 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
67 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
70 assert_return(m, -EINVAL);
71 assert_return(m->hdr, -EINVAL);
72 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
74 rtm = NLMSG_DATA(m->hdr);
76 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
77 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
80 rtm->rtm_dst_len = prefixlen;
85 int sd_rtnl_message_new_route(uint16_t nlmsg_type, unsigned char rtm_family,
86 sd_rtnl_message **ret) {
90 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
91 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
92 assert_return(ret, -EINVAL);
94 r = message_new(ret, NLMSG_SPACE(sizeof(struct rtmsg)));
98 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
99 (*ret)->hdr->nlmsg_type = nlmsg_type;
100 if (nlmsg_type == RTM_NEWROUTE)
101 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
103 rtm = NLMSG_DATA((*ret)->hdr);
105 UPDATE_RTA(*ret, RTM_RTA(rtm));
107 rtm->rtm_family = rtm_family;
108 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
109 rtm->rtm_type = RTN_UNICAST;
110 rtm->rtm_table = RT_TABLE_MAIN;
111 rtm->rtm_protocol = RTPROT_BOOT;
116 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
117 struct ifinfomsg *ifi;
119 assert_return(m, -EINVAL);
120 assert_return(m->hdr, -EINVAL);
121 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
122 assert_return(change, -EINVAL);
124 ifi = NLMSG_DATA(m->hdr);
126 ifi->ifi_flags = flags;
127 ifi->ifi_change = change;
132 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
133 struct ifinfomsg *ifi;
135 assert_return(m, -EINVAL);
136 assert_return(m->hdr, -EINVAL);
137 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
139 ifi = NLMSG_DATA(m->hdr);
141 ifi->ifi_type = type;
146 int sd_rtnl_message_new_link(uint16_t nlmsg_type, int index, sd_rtnl_message **ret) {
147 struct ifinfomsg *ifi;
150 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
151 assert_return(nlmsg_type == RTM_NEWLINK || index > 0, -EINVAL);
152 assert_return(ret, -EINVAL);
154 r = message_new(ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
158 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
159 (*ret)->hdr->nlmsg_type = nlmsg_type;
160 if (nlmsg_type == RTM_NEWLINK)
161 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
163 ifi = NLMSG_DATA((*ret)->hdr);
165 ifi->ifi_family = AF_UNSPEC;
166 ifi->ifi_index = index;
168 UPDATE_RTA(*ret, IFLA_RTA(ifi));
173 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
174 struct ifaddrmsg *ifa;
176 assert_return(m, -EINVAL);
177 assert_return(m->hdr, -EINVAL);
178 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
180 ifa = NLMSG_DATA(m->hdr);
182 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
183 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
186 ifa->ifa_prefixlen = prefixlen;
191 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
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 ifa->ifa_flags = flags;
205 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
206 struct ifaddrmsg *ifa;
208 assert_return(m, -EINVAL);
209 assert_return(m->hdr, -EINVAL);
210 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
212 ifa = NLMSG_DATA(m->hdr);
214 ifa->ifa_scope = scope;
219 int sd_rtnl_message_new_addr(uint16_t nlmsg_type, int index, unsigned char family,
220 sd_rtnl_message **ret) {
221 struct ifaddrmsg *ifa;
224 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
225 assert_return(index > 0, -EINVAL);
226 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
227 assert_return(ret, -EINVAL);
229 r = message_new(ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
233 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
234 (*ret)->hdr->nlmsg_type = nlmsg_type;
236 ifa = NLMSG_DATA((*ret)->hdr);
238 ifa->ifa_index = index;
239 ifa->ifa_family = family;
240 if (family == AF_INET)
241 ifa->ifa_prefixlen = 32;
242 else if (family == AF_INET6)
243 ifa->ifa_prefixlen = 128;
245 UPDATE_RTA(*ret, IFA_RTA(ifa));
250 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
252 assert_se(REFCNT_INC(m->n_ref) >= 2);
257 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
258 if (m && REFCNT_DEC(m->n_ref) <= 0) {
266 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
267 assert_return(m, -EINVAL);
268 assert_return(type, -EINVAL);
270 *type = m->hdr->nlmsg_type;
275 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
276 struct ifinfomsg *ifi;
278 assert_return(m, -EINVAL);
279 assert_return(m->hdr, -EINVAL);
280 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
281 assert_return(ifindex, -EINVAL);
283 ifi = NLMSG_DATA(m->hdr);
285 *ifindex = ifi->ifi_index;
290 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
291 struct ifinfomsg *ifi;
293 assert_return(m, -EINVAL);
294 assert_return(m->hdr, -EINVAL);
295 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
296 assert_return(flags, -EINVAL);
298 ifi = NLMSG_DATA(m->hdr);
300 *flags = ifi->ifi_flags;
305 /* If successful the updated message will be correctly aligned, if
306 unsuccessful the old message is untouched. */
307 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
308 uint32_t rta_length, message_length;
309 struct nlmsghdr *new_hdr;
317 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
318 assert(!data || data_length > 0);
319 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
321 /* get the size of the new rta attribute (with padding at the end) */
322 rta_length = RTA_LENGTH(data_length);
324 /* get the new message size (with padding at the end) */
325 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
327 /* realloc to fit the new attribute */
328 new_hdr = realloc(m->hdr, message_length);
333 /* get pointer to the attribute we are about to add */
334 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
336 /* if we are inside containers, extend them */
337 for (i = 0; i < m->n_containers; i++)
338 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
340 /* fill in the attribute */
341 rta->rta_type = type;
342 rta->rta_len = rta_length;
344 /* this is the start of a new container */
345 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
347 /* we don't deal with the case where the user lies about the type
348 * and gives us too little data (so don't do that)
350 padding = mempcpy(RTA_DATA(rta), data, data_length);
351 /* make sure also the padding at the end of the message is initialized */
353 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
356 /* update message size */
357 m->hdr->nlmsg_len = message_length;
362 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
366 assert_return(m, -EINVAL);
367 assert_return(!m->sealed, -EPERM);
368 assert_return(data, -EINVAL);
370 r = sd_rtnl_message_get_type(m, &rtm_type);
374 /* check that the type is correct */
380 if (m->n_containers == 1) {
381 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
382 type != IFLA_INFO_KIND)
398 if (type != IFA_LABEL)
405 r = add_rtattr(m, type, data, strlen(data) + 1);
412 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
416 assert_return(m, -EINVAL);
417 assert_return(!m->sealed, -EPERM);
419 r = sd_rtnl_message_get_type(m, &rtm_type);
442 r = add_rtattr(m, type, &data, sizeof(uint8_t));
450 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
454 assert_return(m, -EINVAL);
455 assert_return(!m->sealed, -EPERM);
457 r = sd_rtnl_message_get_type(m, &rtm_type);
461 /* check that the type is correct */
467 if (m->n_containers == 2 &&
468 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
469 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
470 type == IFLA_VLAN_ID)
479 r = add_rtattr(m, type, &data, sizeof(uint16_t));
486 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_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 */
511 case IFLA_NET_NS_PID:
512 case IFLA_PROMISCUITY:
513 case IFLA_NUM_TX_QUEUES:
514 case IFLA_NUM_RX_QUEUES:
538 r = add_rtattr(m, type, &data, sizeof(uint32_t));
545 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
546 struct ifaddrmsg *ifa;
551 assert_return(m, -EINVAL);
552 assert_return(!m->sealed, -EPERM);
553 assert_return(data, -EINVAL);
555 r = sd_rtnl_message_get_type(m, &rtm_type);
559 /* check that the type is correct */
569 ifa = NLMSG_DATA(m->hdr);
571 if (ifa->ifa_family != AF_INET)
586 rtm = NLMSG_DATA(m->hdr);
588 if (rtm->rtm_family != AF_INET)
600 r = add_rtattr(m, type, data, sizeof(struct in_addr));
607 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
608 struct ifaddrmsg *ifa;
613 assert_return(m, -EINVAL);
614 assert_return(!m->sealed, -EPERM);
615 assert_return(data, -EINVAL);
617 r = sd_rtnl_message_get_type(m, &rtm_type);
621 /* check that the type is correct */
631 ifa = NLMSG_DATA(m->hdr);
633 if (ifa->ifa_family != AF_INET6)
648 rtm = NLMSG_DATA(m->hdr);
650 if (rtm->rtm_family != AF_INET6)
661 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
668 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
672 assert_return(m, -EINVAL);
673 assert_return(!m->sealed, -EPERM);
674 assert_return(data, -EINVAL);
676 sd_rtnl_message_get_type(m, &rtm_type);
695 r = add_rtattr(m, type, data, ETH_ALEN);
702 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
705 assert_return(m, -EINVAL);
706 assert_return(!m->sealed, -EPERM);
708 sd_rtnl_message_get_type(m, &rtm_type);
710 if (rtnl_message_type_is_link(rtm_type)) {
712 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
713 (type == IFLA_INFO_DATA && m->n_containers == 1 &&
714 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
715 return add_rtattr(m, type, NULL, 0);
716 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
717 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
718 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
719 return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
725 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
726 assert_return(m, -EINVAL);
727 assert_return(!m->sealed, -EPERM);
728 assert_return(m->n_containers > 0, -EINVAL);
735 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
736 size_t remaining_size;
740 assert_return(m, -EINVAL);
741 assert_return(m->sealed, -EPERM);
742 assert_return(m->next_rta_offset, -EINVAL);
743 assert_return(type, -EINVAL);
744 assert_return(data, -EINVAL);
746 /* only read until the end of the current container */
748 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
749 (m->next_rta_offset -
750 m->container_offsets[m->n_containers - 1]);
752 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
754 if (!RTA_OK(NEXT_RTA(m), remaining_size))
757 /* if we read a container, enter it and return its type */
758 r = sd_rtnl_message_get_type(m, &rtm_type);
762 *type = NEXT_RTA(m)->rta_type;
764 if (rtnl_message_type_is_link(rtm_type) &&
765 ((m->n_containers == 0 &&
766 NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
767 (m->n_containers == 1 &&
768 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
769 NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
771 PUSH_CONTAINER(m, NEXT_RTA(m));
772 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
774 *data = RTA_DATA(NEXT_RTA(m));
775 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
781 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
782 assert_return(m, -EINVAL);
783 assert_return(m->sealed, -EINVAL);
784 assert_return(m->n_containers > 0, -EINVAL);
791 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
795 return m->hdr->nlmsg_seq;
798 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
799 struct nlmsgerr *err;
801 assert_return(m, -EINVAL);
802 assert_return(m->hdr, -EINVAL);
804 if (m->hdr->nlmsg_type != NLMSG_ERROR)
807 err = NLMSG_DATA(m->hdr);
812 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
822 m->hdr->nlmsg_seq = nl->serial++;
826 r = sd_rtnl_message_rewind(m);
833 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
837 /* ioctl(rtnl->fd, FIONREAD, &need)
838 Does not appear to work on netlink sockets. libnl uses
839 MSG_PEEK instead. I don't know if that is worth the
842 For now we simply use the maximum message size the kernel
843 may use (NLMSG_GOODSIZE), and then realloc to the actual
844 size after reading the message (hence avoiding huge memory
845 usage in case many small messages are kept around) */
853 /* returns the number of bytes sent, or a negative error code */
854 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
857 struct sockaddr_nl nl;
859 .nl.nl_family = AF_NETLINK,
867 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
868 0, &addr.sa, sizeof(addr));
870 return (errno == EAGAIN) ? 0 : -errno;
875 /* On success, the number of bytes received is returned and *ret points to the received message
876 * which has a valid header and the correct size.
877 * If nothing useful was received 0 is returned.
878 * On failure, a negative error code is returned.
880 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
884 struct sockaddr_nl nl;
894 r = message_receive_need(nl, &need);
898 r = message_new(&m, need);
902 /* don't allow sealing/appending to received messages */
905 addr_len = sizeof(addr);
907 k = recvfrom(nl->fd, m->hdr, need,
908 0, &addr.sa, &addr_len);
910 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
912 k = -ECONNRESET; /* connection was closed by the kernel */
913 else if (addr_len != sizeof(addr.nl) ||
914 addr.nl.nl_family != AF_NETLINK)
915 k = -EIO; /* not a netlink message */
916 else if (addr.nl.nl_pid != 0)
917 k = 0; /* not from the kernel */
918 else if ((size_t) k < sizeof(struct nlmsghdr) ||
919 (size_t) k < m->hdr->nlmsg_len)
920 k = -EIO; /* too small (we do accept too big though) */
921 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
922 k = 0; /* not broadcast and not for us */
925 switch (m->hdr->nlmsg_type) {
926 struct ifinfomsg *ifi;
927 struct ifaddrmsg *ifa;
930 /* check that the size matches the message type */
932 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
939 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
942 ifi = NLMSG_DATA(m->hdr);
943 UPDATE_RTA(m, IFLA_RTA(ifi));
949 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
952 ifa = NLMSG_DATA(m->hdr);
953 UPDATE_RTA(m, IFA_RTA(ifa));
959 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
962 rtm = NLMSG_DATA(m->hdr);
963 UPDATE_RTA(m, RTM_RTA(rtm));
970 k = 0; /* ignoring message of unknown type */
974 sd_rtnl_message_unref(m);
976 /* we probably allocated way too much memory, give it back */
977 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
984 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
985 struct ifinfomsg *ifi;
986 struct ifaddrmsg *ifa;
989 assert_return(m, -EINVAL);
990 assert_return(m->sealed, -EPERM);
991 assert_return(m->hdr, -EINVAL);
993 switch(m->hdr->nlmsg_type) {
998 ifi = NLMSG_DATA(m->hdr);
999 UPDATE_RTA(m, IFLA_RTA(ifi));
1005 ifa = NLMSG_DATA(m->hdr);
1006 UPDATE_RTA(m, IFA_RTA(ifa));
1012 rtm = NLMSG_DATA(m->hdr);
1013 UPDATE_RTA(m, RTM_RTA(rtm));
1020 m->n_containers = 0;