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>
32 #include "rtnl-util.h"
33 #include "rtnl-internal.h"
35 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
36 #define NEXT_RTA(m) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->next_rta_offset))
37 #define UPDATE_RTA(m, new) (m)->next_rta_offset = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
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_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;
66 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
69 assert_return(m, -EINVAL);
70 assert_return(m->hdr, -EINVAL);
71 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
73 rtm = NLMSG_DATA(m->hdr);
75 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
76 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
79 rtm->rtm_dst_len = prefixlen;
84 int sd_rtnl_message_new_route(uint16_t nlmsg_type, unsigned char rtm_family,
85 sd_rtnl_message **ret) {
89 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
90 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
91 assert_return(ret, -EINVAL);
93 r = message_new(ret, NLMSG_SPACE(sizeof(struct rtmsg)));
97 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
98 (*ret)->hdr->nlmsg_type = nlmsg_type;
99 if (nlmsg_type == RTM_NEWROUTE)
100 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
102 rtm = NLMSG_DATA((*ret)->hdr);
104 UPDATE_RTA(*ret, RTM_RTA(rtm));
106 rtm->rtm_family = rtm_family;
107 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
108 rtm->rtm_type = RTN_UNICAST;
109 rtm->rtm_table = RT_TABLE_MAIN;
110 rtm->rtm_protocol = RTPROT_BOOT;
115 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
116 struct ifinfomsg *ifi;
118 assert_return(m, -EINVAL);
119 assert_return(m->hdr, -EINVAL);
120 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
121 assert_return(change, -EINVAL);
123 ifi = NLMSG_DATA(m->hdr);
125 ifi->ifi_flags = flags;
126 ifi->ifi_change = change;
131 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
132 struct ifinfomsg *ifi;
134 assert_return(m, -EINVAL);
135 assert_return(m->hdr, -EINVAL);
136 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
138 ifi = NLMSG_DATA(m->hdr);
140 ifi->ifi_type = type;
145 int sd_rtnl_message_new_link(uint16_t nlmsg_type, int index, sd_rtnl_message **ret) {
146 struct ifinfomsg *ifi;
149 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
150 assert_return(nlmsg_type == RTM_NEWLINK || index > 0, -EINVAL);
151 assert_return(ret, -EINVAL);
153 r = message_new(ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
157 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
158 (*ret)->hdr->nlmsg_type = nlmsg_type;
159 if (nlmsg_type == RTM_NEWLINK)
160 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
162 ifi = NLMSG_DATA((*ret)->hdr);
164 ifi->ifi_family = AF_UNSPEC;
165 ifi->ifi_index = index;
167 UPDATE_RTA(*ret, IFLA_RTA(ifi));
172 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
173 struct ifaddrmsg *ifa;
175 assert_return(m, -EINVAL);
176 assert_return(m->hdr, -EINVAL);
177 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
179 ifa = NLMSG_DATA(m->hdr);
181 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
182 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
185 ifa->ifa_prefixlen = prefixlen;
190 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
191 struct ifaddrmsg *ifa;
193 assert_return(m, -EINVAL);
194 assert_return(m->hdr, -EINVAL);
195 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
197 ifa = NLMSG_DATA(m->hdr);
199 ifa->ifa_flags = flags;
204 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
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_scope = scope;
218 int sd_rtnl_message_new_addr(uint16_t nlmsg_type, int index, unsigned char family,
219 sd_rtnl_message **ret) {
220 struct ifaddrmsg *ifa;
223 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
224 assert_return(index > 0, -EINVAL);
225 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
226 assert_return(ret, -EINVAL);
228 r = message_new(ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
232 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
233 (*ret)->hdr->nlmsg_type = nlmsg_type;
234 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
235 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
237 ifa = NLMSG_DATA((*ret)->hdr);
239 ifa->ifa_index = index;
240 ifa->ifa_family = family;
241 if (family == AF_INET)
242 ifa->ifa_prefixlen = 32;
243 else if (family == AF_INET6)
244 ifa->ifa_prefixlen = 128;
246 UPDATE_RTA(*ret, IFA_RTA(ifa));
251 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
253 assert_se(REFCNT_INC(m->n_ref) >= 2);
258 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
259 if (m && REFCNT_DEC(m->n_ref) <= 0) {
267 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
268 assert_return(m, -EINVAL);
269 assert_return(type, -EINVAL);
271 *type = m->hdr->nlmsg_type;
276 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
277 struct ifinfomsg *ifi;
279 assert_return(m, -EINVAL);
280 assert_return(m->hdr, -EINVAL);
281 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
282 assert_return(ifindex, -EINVAL);
284 ifi = NLMSG_DATA(m->hdr);
286 *ifindex = ifi->ifi_index;
291 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
292 struct ifinfomsg *ifi;
294 assert_return(m, -EINVAL);
295 assert_return(m->hdr, -EINVAL);
296 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
297 assert_return(flags, -EINVAL);
299 ifi = NLMSG_DATA(m->hdr);
301 *flags = ifi->ifi_flags;
306 /* If successful the updated message will be correctly aligned, if
307 unsuccessful the old message is untouched. */
308 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
309 uint32_t rta_length, message_length;
310 struct nlmsghdr *new_hdr;
318 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
319 assert(!data || data_length > 0);
320 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
322 /* get the size of the new rta attribute (with padding at the end) */
323 rta_length = RTA_LENGTH(data_length);
325 /* get the new message size (with padding at the end) */
326 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
328 /* realloc to fit the new attribute */
329 new_hdr = realloc(m->hdr, message_length);
334 /* get pointer to the attribute we are about to add */
335 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
337 /* if we are inside containers, extend them */
338 for (i = 0; i < m->n_containers; i++)
339 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
341 /* fill in the attribute */
342 rta->rta_type = type;
343 rta->rta_len = rta_length;
345 /* this is the start of a new container */
346 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
348 /* we don't deal with the case where the user lies about the type
349 * and gives us too little data (so don't do that)
351 padding = mempcpy(RTA_DATA(rta), data, data_length);
352 /* make sure also the padding at the end of the message is initialized */
354 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
357 /* update message size */
358 m->hdr->nlmsg_len = message_length;
363 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
367 assert_return(m, -EINVAL);
368 assert_return(!m->sealed, -EPERM);
369 assert_return(data, -EINVAL);
371 r = sd_rtnl_message_get_type(m, &rtm_type);
375 /* check that the type is correct */
381 if (m->n_containers == 1) {
382 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
383 type != IFLA_INFO_KIND)
399 if (type != IFA_LABEL)
406 r = add_rtattr(m, type, data, strlen(data) + 1);
413 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
417 assert_return(m, -EINVAL);
418 assert_return(!m->sealed, -EPERM);
420 r = sd_rtnl_message_get_type(m, &rtm_type);
443 r = add_rtattr(m, type, &data, sizeof(uint8_t));
451 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
455 assert_return(m, -EINVAL);
456 assert_return(!m->sealed, -EPERM);
458 r = sd_rtnl_message_get_type(m, &rtm_type);
462 /* check that the type is correct */
468 if (m->n_containers == 2 &&
469 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
470 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
471 type == IFLA_VLAN_ID)
480 r = add_rtattr(m, type, &data, sizeof(uint16_t));
487 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_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 */
512 case IFLA_NET_NS_PID:
513 case IFLA_PROMISCUITY:
514 case IFLA_NUM_TX_QUEUES:
515 case IFLA_NUM_RX_QUEUES:
539 r = add_rtattr(m, type, &data, sizeof(uint32_t));
546 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
547 struct ifaddrmsg *ifa;
552 assert_return(m, -EINVAL);
553 assert_return(!m->sealed, -EPERM);
554 assert_return(data, -EINVAL);
556 r = sd_rtnl_message_get_type(m, &rtm_type);
560 /* check that the type is correct */
570 ifa = NLMSG_DATA(m->hdr);
572 if (ifa->ifa_family != AF_INET)
587 rtm = NLMSG_DATA(m->hdr);
589 if (rtm->rtm_family != AF_INET)
601 r = add_rtattr(m, type, data, sizeof(struct in_addr));
608 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
609 struct ifaddrmsg *ifa;
614 assert_return(m, -EINVAL);
615 assert_return(!m->sealed, -EPERM);
616 assert_return(data, -EINVAL);
618 r = sd_rtnl_message_get_type(m, &rtm_type);
622 /* check that the type is correct */
632 ifa = NLMSG_DATA(m->hdr);
634 if (ifa->ifa_family != AF_INET6)
649 rtm = NLMSG_DATA(m->hdr);
651 if (rtm->rtm_family != AF_INET6)
662 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
669 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
673 assert_return(m, -EINVAL);
674 assert_return(!m->sealed, -EPERM);
675 assert_return(data, -EINVAL);
677 sd_rtnl_message_get_type(m, &rtm_type);
696 r = add_rtattr(m, type, data, ETH_ALEN);
703 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
706 assert_return(m, -EINVAL);
707 assert_return(!m->sealed, -EPERM);
709 sd_rtnl_message_get_type(m, &rtm_type);
711 if (rtnl_message_type_is_link(rtm_type)) {
713 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
714 (type == IFLA_INFO_DATA && m->n_containers == 1 &&
715 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
716 return add_rtattr(m, type, NULL, 0);
717 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
718 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
719 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
720 return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
726 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
727 assert_return(m, -EINVAL);
728 assert_return(!m->sealed, -EPERM);
729 assert_return(m->n_containers > 0, -EINVAL);
736 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
737 size_t remaining_size;
741 assert_return(m, -EINVAL);
742 assert_return(m->sealed, -EPERM);
743 assert_return(m->next_rta_offset, -EINVAL);
744 assert_return(type, -EINVAL);
745 assert_return(data, -EINVAL);
747 /* only read until the end of the current container */
749 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
750 (m->next_rta_offset -
751 m->container_offsets[m->n_containers - 1]);
753 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
755 if (!RTA_OK(NEXT_RTA(m), remaining_size))
758 /* if we read a container, enter it and return its type */
759 r = sd_rtnl_message_get_type(m, &rtm_type);
763 *type = NEXT_RTA(m)->rta_type;
765 if (rtnl_message_type_is_link(rtm_type) &&
766 ((m->n_containers == 0 &&
767 NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
768 (m->n_containers == 1 &&
769 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
770 NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
772 PUSH_CONTAINER(m, NEXT_RTA(m));
773 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
775 *data = RTA_DATA(NEXT_RTA(m));
776 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
782 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
783 assert_return(m, -EINVAL);
784 assert_return(m->sealed, -EINVAL);
785 assert_return(m->n_containers > 0, -EINVAL);
792 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
796 return m->hdr->nlmsg_seq;
799 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
800 struct nlmsgerr *err;
802 assert_return(m, -EINVAL);
803 assert_return(m->hdr, -EINVAL);
805 if (m->hdr->nlmsg_type != NLMSG_ERROR)
808 err = NLMSG_DATA(m->hdr);
813 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
823 m->hdr->nlmsg_seq = nl->serial++;
827 r = sd_rtnl_message_rewind(m);
834 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
838 /* ioctl(rtnl->fd, FIONREAD, &need)
839 Does not appear to work on netlink sockets. libnl uses
840 MSG_PEEK instead. I don't know if that is worth the
843 For now we simply use the maximum message size the kernel
844 may use (NLMSG_GOODSIZE), and then realloc to the actual
845 size after reading the message (hence avoiding huge memory
846 usage in case many small messages are kept around) */
854 /* returns the number of bytes sent, or a negative error code */
855 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
858 struct sockaddr_nl nl;
860 .nl.nl_family = AF_NETLINK,
868 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
869 0, &addr.sa, sizeof(addr));
871 return (errno == EAGAIN) ? 0 : -errno;
876 /* On success, the number of bytes received is returned and *ret points to the received message
877 * which has a valid header and the correct size.
878 * If nothing useful was received 0 is returned.
879 * On failure, a negative error code is returned.
881 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
885 struct sockaddr_nl nl;
895 r = message_receive_need(nl, &need);
899 r = message_new(&m, need);
903 /* don't allow sealing/appending to received messages */
906 addr_len = sizeof(addr);
908 k = recvfrom(nl->fd, m->hdr, need,
909 0, &addr.sa, &addr_len);
911 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
913 k = -ECONNRESET; /* connection was closed by the kernel */
914 else if (addr_len != sizeof(addr.nl) ||
915 addr.nl.nl_family != AF_NETLINK)
916 k = -EIO; /* not a netlink message */
917 else if (addr.nl.nl_pid != 0)
918 k = 0; /* not from the kernel */
919 else if ((size_t) k < sizeof(struct nlmsghdr) ||
920 (size_t) k < m->hdr->nlmsg_len)
921 k = -EIO; /* too small (we do accept too big though) */
922 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
923 k = 0; /* not broadcast and not for us */
926 switch (m->hdr->nlmsg_type) {
927 struct ifinfomsg *ifi;
928 struct ifaddrmsg *ifa;
931 /* check that the size matches the message type */
933 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
940 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
943 ifi = NLMSG_DATA(m->hdr);
944 UPDATE_RTA(m, IFLA_RTA(ifi));
950 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
953 ifa = NLMSG_DATA(m->hdr);
954 UPDATE_RTA(m, IFA_RTA(ifa));
960 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
963 rtm = NLMSG_DATA(m->hdr);
964 UPDATE_RTA(m, RTM_RTA(rtm));
971 k = 0; /* ignoring message of unknown type */
975 sd_rtnl_message_unref(m);
977 /* we probably allocated way too much memory, give it back */
978 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
985 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
986 struct ifinfomsg *ifi;
987 struct ifaddrmsg *ifa;
990 assert_return(m, -EINVAL);
991 assert_return(m->sealed, -EPERM);
992 assert_return(m->hdr, -EINVAL);
994 switch(m->hdr->nlmsg_type) {
999 ifi = NLMSG_DATA(m->hdr);
1000 UPDATE_RTA(m, IFLA_RTA(ifi));
1006 ifa = NLMSG_DATA(m->hdr);
1007 UPDATE_RTA(m, IFA_RTA(ifa));
1013 rtm = NLMSG_DATA(m->hdr);
1014 UPDATE_RTA(m, RTM_RTA(rtm));
1021 m->n_containers = 0;