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);
123 ifi = NLMSG_DATA(m->hdr);
125 ifi->ifi_flags = flags;
127 ifi->ifi_change = change;
129 ifi->ifi_change = 0xffffffff;
134 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
135 struct ifinfomsg *ifi;
137 assert_return(m, -EINVAL);
138 assert_return(m->hdr, -EINVAL);
139 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
141 ifi = NLMSG_DATA(m->hdr);
143 ifi->ifi_type = type;
148 int sd_rtnl_message_new_link(uint16_t nlmsg_type, int index, sd_rtnl_message **ret) {
149 struct ifinfomsg *ifi;
152 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
153 assert_return(nlmsg_type == RTM_NEWLINK || index > 0, -EINVAL);
154 assert_return(ret, -EINVAL);
156 r = message_new(ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
160 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
161 (*ret)->hdr->nlmsg_type = nlmsg_type;
162 if (nlmsg_type == RTM_NEWLINK)
163 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
165 ifi = NLMSG_DATA((*ret)->hdr);
167 ifi->ifi_family = AF_UNSPEC;
168 ifi->ifi_index = index;
170 UPDATE_RTA(*ret, IFLA_RTA(ifi));
175 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
176 struct ifaddrmsg *ifa;
178 assert_return(m, -EINVAL);
179 assert_return(m->hdr, -EINVAL);
180 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
182 ifa = NLMSG_DATA(m->hdr);
184 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
185 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
188 ifa->ifa_prefixlen = prefixlen;
193 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
194 struct ifaddrmsg *ifa;
196 assert_return(m, -EINVAL);
197 assert_return(m->hdr, -EINVAL);
198 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
200 ifa = NLMSG_DATA(m->hdr);
202 ifa->ifa_flags = flags;
207 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
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_scope = scope;
221 int sd_rtnl_message_new_addr(uint16_t nlmsg_type, int index, unsigned char family,
222 sd_rtnl_message **ret) {
223 struct ifaddrmsg *ifa;
226 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
227 assert_return(index > 0, -EINVAL);
228 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
229 assert_return(ret, -EINVAL);
231 r = message_new(ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
235 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
236 (*ret)->hdr->nlmsg_type = nlmsg_type;
238 ifa = NLMSG_DATA((*ret)->hdr);
240 ifa->ifa_index = index;
241 ifa->ifa_family = family;
242 if (family == AF_INET)
243 ifa->ifa_prefixlen = 32;
244 else if (family == AF_INET6)
245 ifa->ifa_prefixlen = 128;
247 UPDATE_RTA(*ret, IFA_RTA(ifa));
252 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
254 assert_se(REFCNT_INC(m->n_ref) >= 2);
259 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
260 if (m && REFCNT_DEC(m->n_ref) <= 0) {
268 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
269 assert_return(m, -EINVAL);
270 assert_return(type, -EINVAL);
272 *type = m->hdr->nlmsg_type;
277 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
278 struct ifinfomsg *ifi;
280 assert_return(m, -EINVAL);
281 assert_return(m->hdr, -EINVAL);
282 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
283 assert_return(ifindex, -EINVAL);
285 ifi = NLMSG_DATA(m->hdr);
287 *ifindex = ifi->ifi_index;
292 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
293 struct ifinfomsg *ifi;
295 assert_return(m, -EINVAL);
296 assert_return(m->hdr, -EINVAL);
297 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
298 assert_return(flags, -EINVAL);
300 ifi = NLMSG_DATA(m->hdr);
302 *flags = ifi->ifi_flags;
307 /* If successful the updated message will be correctly aligned, if
308 unsuccessful the old message is untouched. */
309 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
310 uint32_t rta_length, message_length;
311 struct nlmsghdr *new_hdr;
319 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
320 assert(!data || data_length > 0);
321 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
323 /* get the size of the new rta attribute (with padding at the end) */
324 rta_length = RTA_LENGTH(data_length);
326 /* get the new message size (with padding at the end) */
327 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
329 /* realloc to fit the new attribute */
330 new_hdr = realloc(m->hdr, message_length);
335 /* get pointer to the attribute we are about to add */
336 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
338 /* if we are inside containers, extend them */
339 for (i = 0; i < m->n_containers; i++)
340 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
342 /* fill in the attribute */
343 rta->rta_type = type;
344 rta->rta_len = rta_length;
346 /* this is the start of a new container */
347 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
349 /* we don't deal with the case where the user lies about the type
350 * and gives us too little data (so don't do that)
352 padding = mempcpy(RTA_DATA(rta), data, data_length);
353 /* make sure also the padding at the end of the message is initialized */
355 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
358 /* update message size */
359 m->hdr->nlmsg_len = message_length;
364 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
368 assert_return(m, -EINVAL);
369 assert_return(!m->sealed, -EPERM);
370 assert_return(data, -EINVAL);
372 r = sd_rtnl_message_get_type(m, &rtm_type);
376 /* check that the type is correct */
382 if (m->n_containers == 1) {
383 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
384 type != IFLA_INFO_KIND)
400 if (type != IFA_LABEL)
407 r = add_rtattr(m, type, data, strlen(data) + 1);
414 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
418 assert_return(m, -EINVAL);
419 assert_return(!m->sealed, -EPERM);
421 r = sd_rtnl_message_get_type(m, &rtm_type);
444 r = add_rtattr(m, type, &data, sizeof(uint8_t));
452 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
456 assert_return(m, -EINVAL);
457 assert_return(!m->sealed, -EPERM);
459 r = sd_rtnl_message_get_type(m, &rtm_type);
463 /* check that the type is correct */
469 if (m->n_containers == 2 &&
470 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
471 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
472 type == IFLA_VLAN_ID)
481 r = add_rtattr(m, type, &data, sizeof(uint16_t));
488 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
492 assert_return(m, -EINVAL);
493 assert_return(!m->sealed, -EPERM);
495 r = sd_rtnl_message_get_type(m, &rtm_type);
499 /* check that the type is correct */
513 case IFLA_NET_NS_PID:
514 case IFLA_PROMISCUITY:
515 case IFLA_NUM_TX_QUEUES:
516 case IFLA_NUM_RX_QUEUES:
540 r = add_rtattr(m, type, &data, sizeof(uint32_t));
547 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
548 struct ifaddrmsg *ifa;
553 assert_return(m, -EINVAL);
554 assert_return(!m->sealed, -EPERM);
555 assert_return(data, -EINVAL);
557 r = sd_rtnl_message_get_type(m, &rtm_type);
561 /* check that the type is correct */
571 ifa = NLMSG_DATA(m->hdr);
573 if (ifa->ifa_family != AF_INET)
588 rtm = NLMSG_DATA(m->hdr);
590 if (rtm->rtm_family != AF_INET)
602 r = add_rtattr(m, type, data, sizeof(struct in_addr));
609 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
610 struct ifaddrmsg *ifa;
615 assert_return(m, -EINVAL);
616 assert_return(!m->sealed, -EPERM);
617 assert_return(data, -EINVAL);
619 r = sd_rtnl_message_get_type(m, &rtm_type);
623 /* check that the type is correct */
633 ifa = NLMSG_DATA(m->hdr);
635 if (ifa->ifa_family != AF_INET6)
650 rtm = NLMSG_DATA(m->hdr);
652 if (rtm->rtm_family != AF_INET6)
663 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
670 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
674 assert_return(m, -EINVAL);
675 assert_return(!m->sealed, -EPERM);
676 assert_return(data, -EINVAL);
678 sd_rtnl_message_get_type(m, &rtm_type);
697 r = add_rtattr(m, type, data, ETH_ALEN);
704 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type, size_t extra) {
707 assert_return(m, -EINVAL);
708 assert_return(!m->sealed, -EPERM);
710 sd_rtnl_message_get_type(m, &rtm_type);
712 if (rtnl_message_type_is_link(rtm_type)) {
714 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
715 (type == IFLA_INFO_DATA && m->n_containers == 1 && GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO) ||
716 (type == VETH_INFO_PEER && m->n_containers == 2 && GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA))
717 return add_rtattr(m, type, NULL, extra);
723 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
724 assert_return(m, -EINVAL);
725 assert_return(!m->sealed, -EPERM);
726 assert_return(m->n_containers > 0, -EINVAL);
733 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
734 size_t remaining_size;
738 assert_return(m, -EINVAL);
739 assert_return(m->sealed, -EPERM);
740 assert_return(m->next_rta_offset, -EINVAL);
741 assert_return(type, -EINVAL);
742 assert_return(data, -EINVAL);
744 /* only read until the end of the current container */
746 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
747 (m->next_rta_offset -
748 m->container_offsets[m->n_containers - 1]);
750 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
752 if (!RTA_OK(NEXT_RTA(m), remaining_size))
755 /* if we read a container, enter it and return its type */
756 r = sd_rtnl_message_get_type(m, &rtm_type);
760 *type = NEXT_RTA(m)->rta_type;
762 if (rtnl_message_type_is_link(rtm_type) &&
763 ((m->n_containers == 0 &&
764 NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
765 (m->n_containers == 1 &&
766 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
767 NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
769 PUSH_CONTAINER(m, NEXT_RTA(m));
770 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
772 *data = RTA_DATA(NEXT_RTA(m));
773 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
779 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
780 assert_return(m, -EINVAL);
781 assert_return(m->sealed, -EINVAL);
782 assert_return(m->n_containers > 0, -EINVAL);
789 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
793 return m->hdr->nlmsg_seq;
796 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
797 struct nlmsgerr *err;
799 assert_return(m, -EINVAL);
800 assert_return(m->hdr, -EINVAL);
802 if (m->hdr->nlmsg_type != NLMSG_ERROR)
805 err = NLMSG_DATA(m->hdr);
810 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
820 m->hdr->nlmsg_seq = nl->serial++;
824 r = sd_rtnl_message_rewind(m);
831 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
835 /* ioctl(rtnl->fd, FIONREAD, &need)
836 Does not appear to work on netlink sockets. libnl uses
837 MSG_PEEK instead. I don't know if that is worth the
840 For now we simply use the maximum message size the kernel
841 may use (NLMSG_GOODSIZE), and then realloc to the actual
842 size after reading the message (hence avoiding huge memory
843 usage in case many small messages are kept around) */
851 /* returns the number of bytes sent, or a negative error code */
852 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
855 struct sockaddr_nl nl;
857 .nl.nl_family = AF_NETLINK,
865 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
866 0, &addr.sa, sizeof(addr));
868 return (errno == EAGAIN) ? 0 : -errno;
873 /* On success, the number of bytes received is returned and *ret points to the received message
874 * which has a valid header and the correct size.
875 * If nothing useful was received 0 is returned.
876 * On failure, a negative error code is returned.
878 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
882 struct sockaddr_nl nl;
892 r = message_receive_need(nl, &need);
896 r = message_new(&m, need);
900 /* don't allow sealing/appending to received messages */
903 addr_len = sizeof(addr);
905 k = recvfrom(nl->fd, m->hdr, need,
906 0, &addr.sa, &addr_len);
908 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
910 k = -ECONNRESET; /* connection was closed by the kernel */
911 else if (addr_len != sizeof(addr.nl) ||
912 addr.nl.nl_family != AF_NETLINK)
913 k = -EIO; /* not a netlink message */
914 else if (addr.nl.nl_pid != 0)
915 k = 0; /* not from the kernel */
916 else if ((size_t) k < sizeof(struct nlmsghdr) ||
917 (size_t) k < m->hdr->nlmsg_len)
918 k = -EIO; /* too small (we do accept too big though) */
919 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
920 k = 0; /* not broadcast and not for us */
923 switch (m->hdr->nlmsg_type) {
924 struct ifinfomsg *ifi;
925 struct ifaddrmsg *ifa;
928 /* check that the size matches the message type */
930 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
937 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
940 ifi = NLMSG_DATA(m->hdr);
941 UPDATE_RTA(m, IFLA_RTA(ifi));
947 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
950 ifa = NLMSG_DATA(m->hdr);
951 UPDATE_RTA(m, IFA_RTA(ifa));
957 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
960 rtm = NLMSG_DATA(m->hdr);
961 UPDATE_RTA(m, RTM_RTA(rtm));
968 k = 0; /* ignoring message of unknown type */
972 sd_rtnl_message_unref(m);
974 /* we probably allocated way too much memory, give it back */
975 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
982 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
983 struct ifinfomsg *ifi;
984 struct ifaddrmsg *ifa;
987 assert_return(m, -EINVAL);
988 assert_return(m->sealed, -EPERM);
989 assert_return(m->hdr, -EINVAL);
991 switch(m->hdr->nlmsg_type) {
996 ifi = NLMSG_DATA(m->hdr);
997 UPDATE_RTA(m, IFLA_RTA(ifi));
1003 ifa = NLMSG_DATA(m->hdr);
1004 UPDATE_RTA(m, IFA_RTA(ifa));
1010 rtm = NLMSG_DATA(m->hdr);
1011 UPDATE_RTA(m, RTM_RTA(rtm));
1018 m->n_containers = 0;