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 ||
151 nlmsg_type == RTM_SETLINK || 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;
235 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
236 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
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) {
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 &&
716 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
717 return add_rtattr(m, type, NULL, 0);
718 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
719 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
720 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
721 return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
727 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
728 assert_return(m, -EINVAL);
729 assert_return(!m->sealed, -EPERM);
730 assert_return(m->n_containers > 0, -EINVAL);
737 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
738 size_t remaining_size;
742 assert_return(m, -EINVAL);
743 assert_return(m->sealed, -EPERM);
744 assert_return(m->next_rta_offset, -EINVAL);
745 assert_return(type, -EINVAL);
746 assert_return(data, -EINVAL);
748 /* only read until the end of the current container */
750 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
751 (m->next_rta_offset -
752 m->container_offsets[m->n_containers - 1]);
754 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
756 if (!RTA_OK(NEXT_RTA(m), remaining_size))
759 /* if we read a container, enter it and return its type */
760 r = sd_rtnl_message_get_type(m, &rtm_type);
764 *type = NEXT_RTA(m)->rta_type;
766 if (rtnl_message_type_is_link(rtm_type) &&
767 ((m->n_containers == 0 &&
768 NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
769 (m->n_containers == 1 &&
770 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
771 NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
773 PUSH_CONTAINER(m, NEXT_RTA(m));
774 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
776 *data = RTA_DATA(NEXT_RTA(m));
777 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
783 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
784 assert_return(m, -EINVAL);
785 assert_return(m->sealed, -EINVAL);
786 assert_return(m->n_containers > 0, -EINVAL);
793 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
797 return m->hdr->nlmsg_seq;
800 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
801 struct nlmsgerr *err;
803 assert_return(m, -EINVAL);
804 assert_return(m->hdr, -EINVAL);
806 if (m->hdr->nlmsg_type != NLMSG_ERROR)
809 err = NLMSG_DATA(m->hdr);
814 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
824 m->hdr->nlmsg_seq = nl->serial++;
828 r = sd_rtnl_message_rewind(m);
835 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
839 /* ioctl(rtnl->fd, FIONREAD, &need)
840 Does not appear to work on netlink sockets. libnl uses
841 MSG_PEEK instead. I don't know if that is worth the
844 For now we simply use the maximum message size the kernel
845 may use (NLMSG_GOODSIZE), and then realloc to the actual
846 size after reading the message (hence avoiding huge memory
847 usage in case many small messages are kept around) */
855 /* returns the number of bytes sent, or a negative error code */
856 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
859 struct sockaddr_nl nl;
861 .nl.nl_family = AF_NETLINK,
869 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
870 0, &addr.sa, sizeof(addr));
872 return (errno == EAGAIN) ? 0 : -errno;
877 /* On success, the number of bytes received is returned and *ret points to the received message
878 * which has a valid header and the correct size.
879 * If nothing useful was received 0 is returned.
880 * On failure, a negative error code is returned.
882 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
886 struct sockaddr_nl nl;
896 r = message_receive_need(nl, &need);
900 r = message_new(&m, need);
904 /* don't allow sealing/appending to received messages */
907 addr_len = sizeof(addr);
909 k = recvfrom(nl->fd, m->hdr, need,
910 0, &addr.sa, &addr_len);
912 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
914 k = -ECONNRESET; /* connection was closed by the kernel */
915 else if (addr_len != sizeof(addr.nl) ||
916 addr.nl.nl_family != AF_NETLINK)
917 k = -EIO; /* not a netlink message */
918 else if (addr.nl.nl_pid != 0)
919 k = 0; /* not from the kernel */
920 else if ((size_t) k < sizeof(struct nlmsghdr) ||
921 (size_t) k < m->hdr->nlmsg_len)
922 k = -EIO; /* too small (we do accept too big though) */
923 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
924 k = 0; /* not broadcast and not for us */
927 switch (m->hdr->nlmsg_type) {
928 struct ifinfomsg *ifi;
929 struct ifaddrmsg *ifa;
932 /* check that the size matches the message type */
934 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
941 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
944 ifi = NLMSG_DATA(m->hdr);
945 UPDATE_RTA(m, IFLA_RTA(ifi));
951 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
954 ifa = NLMSG_DATA(m->hdr);
955 UPDATE_RTA(m, IFA_RTA(ifa));
961 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
964 rtm = NLMSG_DATA(m->hdr);
965 UPDATE_RTA(m, RTM_RTA(rtm));
972 k = 0; /* ignoring message of unknown type */
976 sd_rtnl_message_unref(m);
978 /* we probably allocated way too much memory, give it back */
979 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
986 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
987 struct ifinfomsg *ifi;
988 struct ifaddrmsg *ifa;
991 assert_return(m, -EINVAL);
992 assert_return(m->sealed, -EPERM);
993 assert_return(m->hdr, -EINVAL);
995 switch(m->hdr->nlmsg_type) {
1000 ifi = NLMSG_DATA(m->hdr);
1001 UPDATE_RTA(m, IFLA_RTA(ifi));
1007 ifa = NLMSG_DATA(m->hdr);
1008 UPDATE_RTA(m, IFA_RTA(ifa));
1014 rtm = NLMSG_DATA(m->hdr);
1015 UPDATE_RTA(m, RTM_RTA(rtm));
1022 m->n_containers = 0;