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 *rtnl, 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;
62 m->rtnl = sd_rtnl_ref(rtnl);
69 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
72 assert_return(m, -EINVAL);
73 assert_return(m->hdr, -EINVAL);
74 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
76 rtm = NLMSG_DATA(m->hdr);
78 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
79 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
82 rtm->rtm_dst_len = prefixlen;
87 int sd_rtnl_message_new_route(sd_rtnl *rtnl, uint16_t nlmsg_type,
88 unsigned char rtm_family,
89 sd_rtnl_message **ret) {
93 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
94 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
95 assert_return(ret, -EINVAL);
97 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct rtmsg)));
101 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
102 (*ret)->hdr->nlmsg_type = nlmsg_type;
103 if (nlmsg_type == RTM_NEWROUTE)
104 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
106 rtm = NLMSG_DATA((*ret)->hdr);
108 UPDATE_RTA(*ret, RTM_RTA(rtm));
110 rtm->rtm_family = rtm_family;
111 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
112 rtm->rtm_type = RTN_UNICAST;
113 rtm->rtm_table = RT_TABLE_MAIN;
114 rtm->rtm_protocol = RTPROT_BOOT;
119 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
120 struct ifinfomsg *ifi;
122 assert_return(m, -EINVAL);
123 assert_return(m->hdr, -EINVAL);
124 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
125 assert_return(change, -EINVAL);
127 ifi = NLMSG_DATA(m->hdr);
129 ifi->ifi_flags = flags;
130 ifi->ifi_change = change;
135 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
136 struct ifinfomsg *ifi;
138 assert_return(m, -EINVAL);
139 assert_return(m->hdr, -EINVAL);
140 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
142 ifi = NLMSG_DATA(m->hdr);
144 ifi->ifi_type = type;
149 int sd_rtnl_message_new_link(sd_rtnl *rtnl, uint16_t nlmsg_type, int index,
150 sd_rtnl_message **ret) {
151 struct ifinfomsg *ifi;
154 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
155 assert_return(nlmsg_type == RTM_NEWLINK ||
156 nlmsg_type == RTM_SETLINK || index > 0, -EINVAL);
157 assert_return(ret, -EINVAL);
159 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
163 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
164 (*ret)->hdr->nlmsg_type = nlmsg_type;
165 if (nlmsg_type == RTM_NEWLINK)
166 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
168 ifi = NLMSG_DATA((*ret)->hdr);
170 ifi->ifi_family = AF_UNSPEC;
171 ifi->ifi_index = index;
173 UPDATE_RTA(*ret, IFLA_RTA(ifi));
178 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
179 struct ifaddrmsg *ifa;
181 assert_return(m, -EINVAL);
182 assert_return(m->hdr, -EINVAL);
183 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
185 ifa = NLMSG_DATA(m->hdr);
187 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
188 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
191 ifa->ifa_prefixlen = prefixlen;
196 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
197 struct ifaddrmsg *ifa;
199 assert_return(m, -EINVAL);
200 assert_return(m->hdr, -EINVAL);
201 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
203 ifa = NLMSG_DATA(m->hdr);
205 ifa->ifa_flags = flags;
210 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
211 struct ifaddrmsg *ifa;
213 assert_return(m, -EINVAL);
214 assert_return(m->hdr, -EINVAL);
215 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
217 ifa = NLMSG_DATA(m->hdr);
219 ifa->ifa_scope = scope;
224 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, uint16_t nlmsg_type, int index,
225 unsigned char family,
226 sd_rtnl_message **ret) {
227 struct ifaddrmsg *ifa;
230 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
231 assert_return(index > 0, -EINVAL);
232 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
233 assert_return(ret, -EINVAL);
235 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
239 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
240 (*ret)->hdr->nlmsg_type = nlmsg_type;
241 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
242 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
244 ifa = NLMSG_DATA((*ret)->hdr);
246 ifa->ifa_index = index;
247 ifa->ifa_family = family;
248 if (family == AF_INET)
249 ifa->ifa_prefixlen = 32;
250 else if (family == AF_INET6)
251 ifa->ifa_prefixlen = 128;
253 UPDATE_RTA(*ret, IFA_RTA(ifa));
258 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
260 assert_se(REFCNT_INC(m->n_ref) >= 2);
265 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
266 if (m && REFCNT_DEC(m->n_ref) <= 0) {
267 sd_rtnl_unref(m->rtnl);
275 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
276 assert_return(m, -EINVAL);
277 assert_return(type, -EINVAL);
279 *type = m->hdr->nlmsg_type;
284 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
285 struct ifinfomsg *ifi;
287 assert_return(m, -EINVAL);
288 assert_return(m->hdr, -EINVAL);
289 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
290 assert_return(ifindex, -EINVAL);
292 ifi = NLMSG_DATA(m->hdr);
294 *ifindex = ifi->ifi_index;
299 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
300 struct ifinfomsg *ifi;
302 assert_return(m, -EINVAL);
303 assert_return(m->hdr, -EINVAL);
304 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
305 assert_return(flags, -EINVAL);
307 ifi = NLMSG_DATA(m->hdr);
309 *flags = ifi->ifi_flags;
314 /* If successful the updated message will be correctly aligned, if
315 unsuccessful the old message is untouched. */
316 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
317 uint32_t rta_length, message_length;
318 struct nlmsghdr *new_hdr;
326 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
327 assert(!data || data_length > 0);
328 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
330 /* get the size of the new rta attribute (with padding at the end) */
331 rta_length = RTA_LENGTH(data_length);
333 /* get the new message size (with padding at the end) */
334 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
336 /* realloc to fit the new attribute */
337 new_hdr = realloc(m->hdr, message_length);
342 /* get pointer to the attribute we are about to add */
343 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
345 /* if we are inside containers, extend them */
346 for (i = 0; i < m->n_containers; i++)
347 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
349 /* fill in the attribute */
350 rta->rta_type = type;
351 rta->rta_len = rta_length;
353 /* this is the start of a new container */
354 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
356 /* we don't deal with the case where the user lies about the type
357 * and gives us too little data (so don't do that)
359 padding = mempcpy(RTA_DATA(rta), data, data_length);
360 /* make sure also the padding at the end of the message is initialized */
362 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
365 /* update message size */
366 m->hdr->nlmsg_len = message_length;
371 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
375 assert_return(m, -EINVAL);
376 assert_return(!m->sealed, -EPERM);
377 assert_return(data, -EINVAL);
379 r = sd_rtnl_message_get_type(m, &rtm_type);
383 /* check that the type is correct */
389 if (m->n_containers == 1) {
390 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
391 type != IFLA_INFO_KIND)
407 if (type != IFA_LABEL)
414 r = add_rtattr(m, type, data, strlen(data) + 1);
421 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
425 assert_return(m, -EINVAL);
426 assert_return(!m->sealed, -EPERM);
428 r = sd_rtnl_message_get_type(m, &rtm_type);
451 r = add_rtattr(m, type, &data, sizeof(uint8_t));
459 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
463 assert_return(m, -EINVAL);
464 assert_return(!m->sealed, -EPERM);
466 r = sd_rtnl_message_get_type(m, &rtm_type);
470 /* check that the type is correct */
476 if (m->n_containers == 2 &&
477 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
478 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
479 type == IFLA_VLAN_ID)
488 r = add_rtattr(m, type, &data, sizeof(uint16_t));
495 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
499 assert_return(m, -EINVAL);
500 assert_return(!m->sealed, -EPERM);
502 r = sd_rtnl_message_get_type(m, &rtm_type);
506 /* check that the type is correct */
520 case IFLA_NET_NS_PID:
521 case IFLA_PROMISCUITY:
522 case IFLA_NUM_TX_QUEUES:
523 case IFLA_NUM_RX_QUEUES:
547 r = add_rtattr(m, type, &data, sizeof(uint32_t));
554 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
555 struct ifaddrmsg *ifa;
560 assert_return(m, -EINVAL);
561 assert_return(!m->sealed, -EPERM);
562 assert_return(data, -EINVAL);
564 r = sd_rtnl_message_get_type(m, &rtm_type);
568 /* check that the type is correct */
578 ifa = NLMSG_DATA(m->hdr);
580 if (ifa->ifa_family != AF_INET)
595 rtm = NLMSG_DATA(m->hdr);
597 if (rtm->rtm_family != AF_INET)
609 r = add_rtattr(m, type, data, sizeof(struct in_addr));
616 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
617 struct ifaddrmsg *ifa;
622 assert_return(m, -EINVAL);
623 assert_return(!m->sealed, -EPERM);
624 assert_return(data, -EINVAL);
626 r = sd_rtnl_message_get_type(m, &rtm_type);
630 /* check that the type is correct */
640 ifa = NLMSG_DATA(m->hdr);
642 if (ifa->ifa_family != AF_INET6)
657 rtm = NLMSG_DATA(m->hdr);
659 if (rtm->rtm_family != AF_INET6)
670 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
677 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
681 assert_return(m, -EINVAL);
682 assert_return(!m->sealed, -EPERM);
683 assert_return(data, -EINVAL);
685 sd_rtnl_message_get_type(m, &rtm_type);
704 r = add_rtattr(m, type, data, ETH_ALEN);
711 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
714 assert_return(m, -EINVAL);
715 assert_return(!m->sealed, -EPERM);
717 sd_rtnl_message_get_type(m, &rtm_type);
719 if (rtnl_message_type_is_link(rtm_type)) {
721 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
722 (type == IFLA_INFO_DATA && m->n_containers == 1 &&
723 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
724 return add_rtattr(m, type, NULL, 0);
725 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
726 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
727 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
728 return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
734 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
735 assert_return(m, -EINVAL);
736 assert_return(!m->sealed, -EPERM);
737 assert_return(m->n_containers > 0, -EINVAL);
744 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
745 size_t remaining_size;
749 assert_return(m, -EINVAL);
750 assert_return(m->sealed, -EPERM);
751 assert_return(m->next_rta_offset, -EINVAL);
752 assert_return(type, -EINVAL);
753 assert_return(data, -EINVAL);
755 /* only read until the end of the current container */
757 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
758 (m->next_rta_offset -
759 m->container_offsets[m->n_containers - 1]);
761 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
763 if (!RTA_OK(NEXT_RTA(m), remaining_size))
766 /* if we read a container, enter it and return its type */
767 r = sd_rtnl_message_get_type(m, &rtm_type);
771 *type = NEXT_RTA(m)->rta_type;
773 if (rtnl_message_type_is_link(rtm_type) &&
774 ((m->n_containers == 0 &&
775 NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
776 (m->n_containers == 1 &&
777 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
778 NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
780 PUSH_CONTAINER(m, NEXT_RTA(m));
781 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
783 *data = RTA_DATA(NEXT_RTA(m));
784 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
790 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
791 assert_return(m, -EINVAL);
792 assert_return(m->sealed, -EINVAL);
793 assert_return(m->n_containers > 0, -EINVAL);
800 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
804 return m->hdr->nlmsg_seq;
807 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
808 struct nlmsgerr *err;
810 assert_return(m, -EINVAL);
811 assert_return(m->hdr, -EINVAL);
813 if (m->hdr->nlmsg_type != NLMSG_ERROR)
816 err = NLMSG_DATA(m->hdr);
821 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
831 m->hdr->nlmsg_seq = nl->serial++;
835 r = sd_rtnl_message_rewind(m);
842 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
846 /* ioctl(rtnl->fd, FIONREAD, &need)
847 Does not appear to work on netlink sockets. libnl uses
848 MSG_PEEK instead. I don't know if that is worth the
851 For now we simply use the maximum message size the kernel
852 may use (NLMSG_GOODSIZE), and then realloc to the actual
853 size after reading the message (hence avoiding huge memory
854 usage in case many small messages are kept around) */
862 /* returns the number of bytes sent, or a negative error code */
863 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
866 struct sockaddr_nl nl;
868 .nl.nl_family = AF_NETLINK,
876 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
877 0, &addr.sa, sizeof(addr));
879 return (errno == EAGAIN) ? 0 : -errno;
884 /* On success, the number of bytes received is returned and *ret points to the received message
885 * which has a valid header and the correct size.
886 * If nothing useful was received 0 is returned.
887 * On failure, a negative error code is returned.
889 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
893 struct sockaddr_nl nl;
903 r = message_receive_need(nl, &need);
907 r = message_new(nl, &m, need);
911 /* don't allow sealing/appending to received messages */
914 addr_len = sizeof(addr);
916 k = recvfrom(nl->fd, m->hdr, need,
917 0, &addr.sa, &addr_len);
919 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
921 k = -ECONNRESET; /* connection was closed by the kernel */
922 else if (addr_len != sizeof(addr.nl) ||
923 addr.nl.nl_family != AF_NETLINK)
924 k = -EIO; /* not a netlink message */
925 else if (addr.nl.nl_pid != 0)
926 k = 0; /* not from the kernel */
927 else if ((size_t) k < sizeof(struct nlmsghdr) ||
928 (size_t) k < m->hdr->nlmsg_len)
929 k = -EIO; /* too small (we do accept too big though) */
930 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
931 k = 0; /* not broadcast and not for us */
934 switch (m->hdr->nlmsg_type) {
935 struct ifinfomsg *ifi;
936 struct ifaddrmsg *ifa;
939 /* check that the size matches the message type */
941 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
948 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
951 ifi = NLMSG_DATA(m->hdr);
952 UPDATE_RTA(m, IFLA_RTA(ifi));
958 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
961 ifa = NLMSG_DATA(m->hdr);
962 UPDATE_RTA(m, IFA_RTA(ifa));
968 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
971 rtm = NLMSG_DATA(m->hdr);
972 UPDATE_RTA(m, RTM_RTA(rtm));
979 k = 0; /* ignoring message of unknown type */
983 sd_rtnl_message_unref(m);
985 /* we probably allocated way too much memory, give it back */
986 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
993 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
994 struct ifinfomsg *ifi;
995 struct ifaddrmsg *ifa;
998 assert_return(m, -EINVAL);
999 assert_return(m->sealed, -EPERM);
1000 assert_return(m->hdr, -EINVAL);
1002 switch(m->hdr->nlmsg_type) {
1007 ifi = NLMSG_DATA(m->hdr);
1008 UPDATE_RTA(m, IFLA_RTA(ifi));
1014 ifa = NLMSG_DATA(m->hdr);
1015 UPDATE_RTA(m, IFA_RTA(ifa));
1021 rtm = NLMSG_DATA(m->hdr);
1022 UPDATE_RTA(m, RTM_RTA(rtm));
1029 m->n_containers = 0;