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>
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 *rtnl, 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;
63 m->rtnl = sd_rtnl_ref(rtnl);
70 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
73 assert_return(m, -EINVAL);
74 assert_return(m->hdr, -EINVAL);
75 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
77 rtm = NLMSG_DATA(m->hdr);
79 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
80 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
83 rtm->rtm_dst_len = prefixlen;
88 int sd_rtnl_message_new_route(sd_rtnl *rtnl, uint16_t nlmsg_type,
89 unsigned char rtm_family,
90 sd_rtnl_message **ret) {
94 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
95 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
96 assert_return(ret, -EINVAL);
98 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct rtmsg)));
102 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
103 (*ret)->hdr->nlmsg_type = nlmsg_type;
104 if (nlmsg_type == RTM_NEWROUTE)
105 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
107 rtm = NLMSG_DATA((*ret)->hdr);
109 UPDATE_RTA(*ret, RTM_RTA(rtm));
111 rtm->rtm_family = rtm_family;
112 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
113 rtm->rtm_type = RTN_UNICAST;
114 rtm->rtm_table = RT_TABLE_MAIN;
115 rtm->rtm_protocol = RTPROT_BOOT;
120 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
121 struct ifinfomsg *ifi;
123 assert_return(m, -EINVAL);
124 assert_return(m->hdr, -EINVAL);
125 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
126 assert_return(change, -EINVAL);
128 ifi = NLMSG_DATA(m->hdr);
130 ifi->ifi_flags = flags;
131 ifi->ifi_change = change;
136 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
137 struct ifinfomsg *ifi;
139 assert_return(m, -EINVAL);
140 assert_return(m->hdr, -EINVAL);
141 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
143 ifi = NLMSG_DATA(m->hdr);
145 ifi->ifi_type = type;
150 int sd_rtnl_message_new_link(sd_rtnl *rtnl, uint16_t nlmsg_type, int index,
151 sd_rtnl_message **ret) {
152 struct ifinfomsg *ifi;
155 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
156 assert_return(nlmsg_type == RTM_NEWLINK ||
157 nlmsg_type == RTM_SETLINK || index > 0, -EINVAL);
158 assert_return(ret, -EINVAL);
160 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
164 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
165 (*ret)->hdr->nlmsg_type = nlmsg_type;
166 if (nlmsg_type == RTM_NEWLINK)
167 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
169 ifi = NLMSG_DATA((*ret)->hdr);
171 ifi->ifi_family = AF_UNSPEC;
172 ifi->ifi_index = index;
174 UPDATE_RTA(*ret, IFLA_RTA(ifi));
179 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
180 struct ifaddrmsg *ifa;
182 assert_return(m, -EINVAL);
183 assert_return(m->hdr, -EINVAL);
184 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
186 ifa = NLMSG_DATA(m->hdr);
188 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
189 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
192 ifa->ifa_prefixlen = prefixlen;
197 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
198 struct ifaddrmsg *ifa;
200 assert_return(m, -EINVAL);
201 assert_return(m->hdr, -EINVAL);
202 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
204 ifa = NLMSG_DATA(m->hdr);
206 ifa->ifa_flags = flags;
211 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
212 struct ifaddrmsg *ifa;
214 assert_return(m, -EINVAL);
215 assert_return(m->hdr, -EINVAL);
216 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
218 ifa = NLMSG_DATA(m->hdr);
220 ifa->ifa_scope = scope;
225 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, uint16_t nlmsg_type, int index,
226 unsigned char family,
227 sd_rtnl_message **ret) {
228 struct ifaddrmsg *ifa;
231 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
232 assert_return(index > 0, -EINVAL);
233 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
234 assert_return(ret, -EINVAL);
236 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
240 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
241 (*ret)->hdr->nlmsg_type = nlmsg_type;
242 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
243 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
245 ifa = NLMSG_DATA((*ret)->hdr);
247 ifa->ifa_index = index;
248 ifa->ifa_family = family;
249 if (family == AF_INET)
250 ifa->ifa_prefixlen = 32;
251 else if (family == AF_INET6)
252 ifa->ifa_prefixlen = 128;
254 UPDATE_RTA(*ret, IFA_RTA(ifa));
259 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
261 assert_se(REFCNT_INC(m->n_ref) >= 2);
266 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
267 if (m && REFCNT_DEC(m->n_ref) <= 0) {
268 sd_rtnl_unref(m->rtnl);
276 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
277 assert_return(m, -EINVAL);
278 assert_return(type, -EINVAL);
280 *type = m->hdr->nlmsg_type;
285 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
286 struct ifinfomsg *ifi;
288 assert_return(m, -EINVAL);
289 assert_return(m->hdr, -EINVAL);
290 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
291 assert_return(ifindex, -EINVAL);
293 ifi = NLMSG_DATA(m->hdr);
295 *ifindex = ifi->ifi_index;
300 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
301 struct ifinfomsg *ifi;
303 assert_return(m, -EINVAL);
304 assert_return(m->hdr, -EINVAL);
305 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
306 assert_return(flags, -EINVAL);
308 ifi = NLMSG_DATA(m->hdr);
310 *flags = ifi->ifi_flags;
315 /* If successful the updated message will be correctly aligned, if
316 unsuccessful the old message is untouched. */
317 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
318 uint32_t rta_length, message_length;
319 struct nlmsghdr *new_hdr;
327 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
328 assert(!data || data_length > 0);
329 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
331 /* get the size of the new rta attribute (with padding at the end) */
332 rta_length = RTA_LENGTH(data_length);
334 /* get the new message size (with padding at the end) */
335 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
337 /* realloc to fit the new attribute */
338 new_hdr = realloc(m->hdr, message_length);
343 /* get pointer to the attribute we are about to add */
344 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
346 /* if we are inside containers, extend them */
347 for (i = 0; i < m->n_containers; i++)
348 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
350 /* fill in the attribute */
351 rta->rta_type = type;
352 rta->rta_len = rta_length;
354 /* this is the start of a new container */
355 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
357 /* we don't deal with the case where the user lies about the type
358 * and gives us too little data (so don't do that)
360 padding = mempcpy(RTA_DATA(rta), data, data_length);
361 /* make sure also the padding at the end of the message is initialized */
363 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
366 /* update message size */
367 m->hdr->nlmsg_len = message_length;
372 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
376 assert_return(m, -EINVAL);
377 assert_return(!m->sealed, -EPERM);
378 assert_return(data, -EINVAL);
380 r = sd_rtnl_message_get_type(m, &rtm_type);
384 /* check that the type is correct */
390 if (m->n_containers == 1) {
391 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
392 type != IFLA_INFO_KIND)
408 if (type != IFA_LABEL)
415 r = add_rtattr(m, type, data, strlen(data) + 1);
422 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
426 assert_return(m, -EINVAL);
427 assert_return(!m->sealed, -EPERM);
429 r = sd_rtnl_message_get_type(m, &rtm_type);
452 r = add_rtattr(m, type, &data, sizeof(uint8_t));
460 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
464 assert_return(m, -EINVAL);
465 assert_return(!m->sealed, -EPERM);
467 r = sd_rtnl_message_get_type(m, &rtm_type);
471 /* check that the type is correct */
477 if (m->n_containers == 2 &&
478 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
479 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
480 type == IFLA_VLAN_ID)
489 r = add_rtattr(m, type, &data, sizeof(uint16_t));
496 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
500 assert_return(m, -EINVAL);
501 assert_return(!m->sealed, -EPERM);
503 r = sd_rtnl_message_get_type(m, &rtm_type);
507 /* check that the type is correct */
521 case IFLA_NET_NS_PID:
522 case IFLA_PROMISCUITY:
523 case IFLA_NUM_TX_QUEUES:
524 case IFLA_NUM_RX_QUEUES:
548 r = add_rtattr(m, type, &data, sizeof(uint32_t));
555 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
556 struct ifaddrmsg *ifa;
561 assert_return(m, -EINVAL);
562 assert_return(!m->sealed, -EPERM);
563 assert_return(data, -EINVAL);
565 r = sd_rtnl_message_get_type(m, &rtm_type);
569 /* check that the type is correct */
579 ifa = NLMSG_DATA(m->hdr);
581 if (ifa->ifa_family != AF_INET)
596 rtm = NLMSG_DATA(m->hdr);
598 if (rtm->rtm_family != AF_INET)
610 r = add_rtattr(m, type, data, sizeof(struct in_addr));
617 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
618 struct ifaddrmsg *ifa;
623 assert_return(m, -EINVAL);
624 assert_return(!m->sealed, -EPERM);
625 assert_return(data, -EINVAL);
627 r = sd_rtnl_message_get_type(m, &rtm_type);
631 /* check that the type is correct */
641 ifa = NLMSG_DATA(m->hdr);
643 if (ifa->ifa_family != AF_INET6)
658 rtm = NLMSG_DATA(m->hdr);
660 if (rtm->rtm_family != AF_INET6)
671 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
678 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
682 assert_return(m, -EINVAL);
683 assert_return(!m->sealed, -EPERM);
684 assert_return(data, -EINVAL);
686 sd_rtnl_message_get_type(m, &rtm_type);
705 r = add_rtattr(m, type, data, ETH_ALEN);
712 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
715 assert_return(m, -EINVAL);
716 assert_return(!m->sealed, -EPERM);
718 sd_rtnl_message_get_type(m, &rtm_type);
720 if (rtnl_message_type_is_link(rtm_type)) {
722 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
723 (type == IFLA_INFO_DATA && m->n_containers == 1 &&
724 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
725 return add_rtattr(m, type, NULL, 0);
726 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
727 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
728 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
729 return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
735 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
736 assert_return(m, -EINVAL);
737 assert_return(!m->sealed, -EPERM);
738 assert_return(m->n_containers > 0, -EINVAL);
745 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
746 size_t remaining_size;
750 assert_return(m, -EINVAL);
751 assert_return(m->sealed, -EPERM);
752 assert_return(m->next_rta_offset, -EINVAL);
753 assert_return(type, -EINVAL);
754 assert_return(data, -EINVAL);
756 /* only read until the end of the current container */
758 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
759 (m->next_rta_offset -
760 m->container_offsets[m->n_containers - 1]);
762 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
764 if (!RTA_OK(NEXT_RTA(m), remaining_size))
767 /* if we read a container, enter it and return its type */
768 r = sd_rtnl_message_get_type(m, &rtm_type);
772 *type = NEXT_RTA(m)->rta_type;
774 if (rtnl_message_type_is_link(rtm_type) &&
775 ((m->n_containers == 0 &&
776 NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
777 (m->n_containers == 1 &&
778 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
779 NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
781 PUSH_CONTAINER(m, NEXT_RTA(m));
782 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
784 *data = RTA_DATA(NEXT_RTA(m));
785 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
791 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
792 assert_return(m, -EINVAL);
793 assert_return(m->sealed, -EINVAL);
794 assert_return(m->n_containers > 0, -EINVAL);
801 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
805 return m->hdr->nlmsg_seq;
808 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
809 struct nlmsgerr *err;
811 assert_return(m, -EINVAL);
812 assert_return(m->hdr, -EINVAL);
814 if (m->hdr->nlmsg_type != NLMSG_ERROR)
817 err = NLMSG_DATA(m->hdr);
822 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
832 m->hdr->nlmsg_seq = nl->serial++;
836 r = sd_rtnl_message_rewind(m);
843 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
847 /* ioctl(rtnl->fd, FIONREAD, &need)
848 Does not appear to work on netlink sockets. libnl uses
849 MSG_PEEK instead. I don't know if that is worth the
852 For now we simply use the maximum message size the kernel
853 may use (NLMSG_GOODSIZE), and then realloc to the actual
854 size after reading the message (hence avoiding huge memory
855 usage in case many small messages are kept around) */
863 /* returns the number of bytes sent, or a negative error code */
864 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
867 struct sockaddr_nl nl;
869 .nl.nl_family = AF_NETLINK,
877 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
878 0, &addr.sa, sizeof(addr));
880 return (errno == EAGAIN) ? 0 : -errno;
885 /* On success, the number of bytes received is returned and *ret points to the received message
886 * which has a valid header and the correct size.
887 * If nothing useful was received 0 is returned.
888 * On failure, a negative error code is returned.
890 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
894 struct sockaddr_nl nl;
904 r = message_receive_need(nl, &need);
908 r = message_new(nl, &m, need);
912 /* don't allow sealing/appending to received messages */
915 addr_len = sizeof(addr);
917 k = recvfrom(nl->fd, m->hdr, need,
918 0, &addr.sa, &addr_len);
920 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
922 k = -ECONNRESET; /* connection was closed by the kernel */
923 else if (addr_len != sizeof(addr.nl) ||
924 addr.nl.nl_family != AF_NETLINK)
925 k = -EIO; /* not a netlink message */
926 else if (addr.nl.nl_pid != 0)
927 k = 0; /* not from the kernel */
928 else if ((size_t) k < sizeof(struct nlmsghdr) ||
929 (size_t) k < m->hdr->nlmsg_len)
930 k = -EIO; /* too small (we do accept too big though) */
931 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
932 k = 0; /* not broadcast and not for us */
935 switch (m->hdr->nlmsg_type) {
936 struct ifinfomsg *ifi;
937 struct ifaddrmsg *ifa;
940 /* check that the size matches the message type */
942 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
949 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
952 ifi = NLMSG_DATA(m->hdr);
953 UPDATE_RTA(m, IFLA_RTA(ifi));
959 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
962 ifa = NLMSG_DATA(m->hdr);
963 UPDATE_RTA(m, IFA_RTA(ifa));
969 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
972 rtm = NLMSG_DATA(m->hdr);
973 UPDATE_RTA(m, RTM_RTA(rtm));
980 k = 0; /* ignoring message of unknown type */
984 sd_rtnl_message_unref(m);
986 /* we probably allocated way too much memory, give it back */
987 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
994 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
995 struct ifinfomsg *ifi;
996 struct ifaddrmsg *ifa;
999 assert_return(m, -EINVAL);
1000 assert_return(m->sealed, -EPERM);
1001 assert_return(m->hdr, -EINVAL);
1003 switch(m->hdr->nlmsg_type) {
1008 ifi = NLMSG_DATA(m->hdr);
1009 UPDATE_RTA(m, IFLA_RTA(ifi));
1015 ifa = NLMSG_DATA(m->hdr);
1016 UPDATE_RTA(m, IFA_RTA(ifa));
1022 rtm = NLMSG_DATA(m->hdr);
1023 UPDATE_RTA(m, RTM_RTA(rtm));
1030 m->n_containers = 0;