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, size_t extra) {
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 && GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO) ||
714 (type == VETH_INFO_PEER && m->n_containers == 2 && GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA))
715 return add_rtattr(m, type, NULL, extra);
721 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
722 assert_return(m, -EINVAL);
723 assert_return(!m->sealed, -EPERM);
724 assert_return(m->n_containers > 0, -EINVAL);
731 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
732 size_t remaining_size;
736 assert_return(m, -EINVAL);
737 assert_return(m->sealed, -EPERM);
738 assert_return(m->next_rta_offset, -EINVAL);
739 assert_return(type, -EINVAL);
740 assert_return(data, -EINVAL);
742 /* only read until the end of the current container */
744 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
745 (m->next_rta_offset -
746 m->container_offsets[m->n_containers - 1]);
748 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
750 if (!RTA_OK(NEXT_RTA(m), remaining_size))
753 /* if we read a container, enter it and return its type */
754 r = sd_rtnl_message_get_type(m, &rtm_type);
758 *type = NEXT_RTA(m)->rta_type;
760 if (rtnl_message_type_is_link(rtm_type) &&
761 ((m->n_containers == 0 &&
762 NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
763 (m->n_containers == 1 &&
764 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
765 NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
767 PUSH_CONTAINER(m, NEXT_RTA(m));
768 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
770 *data = RTA_DATA(NEXT_RTA(m));
771 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
777 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
778 assert_return(m, -EINVAL);
779 assert_return(m->sealed, -EINVAL);
780 assert_return(m->n_containers > 0, -EINVAL);
787 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
791 return m->hdr->nlmsg_seq;
794 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
795 struct nlmsgerr *err;
797 assert_return(m, -EINVAL);
798 assert_return(m->hdr, -EINVAL);
800 if (m->hdr->nlmsg_type != NLMSG_ERROR)
803 err = NLMSG_DATA(m->hdr);
808 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
818 m->hdr->nlmsg_seq = nl->serial++;
822 r = sd_rtnl_message_rewind(m);
829 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
833 /* ioctl(rtnl->fd, FIONREAD, &need)
834 Does not appear to work on netlink sockets. libnl uses
835 MSG_PEEK instead. I don't know if that is worth the
838 For now we simply use the maximum message size the kernel
839 may use (NLMSG_GOODSIZE), and then realloc to the actual
840 size after reading the message (hence avoiding huge memory
841 usage in case many small messages are kept around) */
849 /* returns the number of bytes sent, or a negative error code */
850 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
853 struct sockaddr_nl nl;
855 .nl.nl_family = AF_NETLINK,
863 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
864 0, &addr.sa, sizeof(addr));
866 return (errno == EAGAIN) ? 0 : -errno;
871 /* On success, the number of bytes received is returned and *ret points to the received message
872 * which has a valid header and the correct size.
873 * If nothing useful was received 0 is returned.
874 * On failure, a negative error code is returned.
876 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
880 struct sockaddr_nl nl;
890 r = message_receive_need(nl, &need);
894 r = message_new(&m, need);
898 /* don't allow sealing/appending to received messages */
901 addr_len = sizeof(addr);
903 k = recvfrom(nl->fd, m->hdr, need,
904 0, &addr.sa, &addr_len);
906 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
908 k = -ECONNRESET; /* connection was closed by the kernel */
909 else if (addr_len != sizeof(addr.nl) ||
910 addr.nl.nl_family != AF_NETLINK)
911 k = -EIO; /* not a netlink message */
912 else if (addr.nl.nl_pid != 0)
913 k = 0; /* not from the kernel */
914 else if ((size_t) k < sizeof(struct nlmsghdr) ||
915 (size_t) k < m->hdr->nlmsg_len)
916 k = -EIO; /* too small (we do accept too big though) */
917 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
918 k = 0; /* not broadcast and not for us */
921 switch (m->hdr->nlmsg_type) {
922 struct ifinfomsg *ifi;
923 struct ifaddrmsg *ifa;
926 /* check that the size matches the message type */
928 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
935 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
938 ifi = NLMSG_DATA(m->hdr);
939 UPDATE_RTA(m, IFLA_RTA(ifi));
945 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
948 ifa = NLMSG_DATA(m->hdr);
949 UPDATE_RTA(m, IFA_RTA(ifa));
955 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
958 rtm = NLMSG_DATA(m->hdr);
959 UPDATE_RTA(m, RTM_RTA(rtm));
966 k = 0; /* ignoring message of unknown type */
970 sd_rtnl_message_unref(m);
972 /* we probably allocated way too much memory, give it back */
973 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
980 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
981 struct ifinfomsg *ifi;
982 struct ifaddrmsg *ifa;
985 assert_return(m, -EINVAL);
986 assert_return(m->sealed, -EPERM);
987 assert_return(m->hdr, -EINVAL);
989 switch(m->hdr->nlmsg_type) {
994 ifi = NLMSG_DATA(m->hdr);
995 UPDATE_RTA(m, IFLA_RTA(ifi));
1001 ifa = NLMSG_DATA(m->hdr);
1002 UPDATE_RTA(m, IFA_RTA(ifa));
1008 rtm = NLMSG_DATA(m->hdr);
1009 UPDATE_RTA(m, RTM_RTA(rtm));
1016 m->n_containers = 0;