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>
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_route_new(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);
122 ifi = NLMSG_DATA(m->hdr);
124 ifi->ifi_flags = flags;
126 ifi->ifi_change = change;
128 ifi->ifi_change = 0xffffffff;
133 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
134 struct ifinfomsg *ifi;
136 assert_return(m, -EINVAL);
137 assert_return(m->hdr, -EINVAL);
138 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
140 ifi = NLMSG_DATA(m->hdr);
142 ifi->ifi_type = type;
147 int sd_rtnl_message_link_new(uint16_t nlmsg_type, int index, sd_rtnl_message **ret) {
148 struct ifinfomsg *ifi;
151 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
152 assert_return(nlmsg_type == RTM_NEWLINK || index > 0, -EINVAL);
153 assert_return(ret, -EINVAL);
155 r = message_new(ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
159 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
160 (*ret)->hdr->nlmsg_type = nlmsg_type;
161 if (nlmsg_type == RTM_NEWLINK)
162 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
164 ifi = NLMSG_DATA((*ret)->hdr);
166 ifi->ifi_family = AF_UNSPEC;
167 ifi->ifi_index = index;
169 UPDATE_RTA(*ret, IFLA_RTA(ifi));
174 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
175 struct ifaddrmsg *ifa;
177 assert_return(m, -EINVAL);
178 assert_return(m->hdr, -EINVAL);
179 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
181 ifa = NLMSG_DATA(m->hdr);
183 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
184 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
187 ifa->ifa_prefixlen = prefixlen;
192 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
193 struct ifaddrmsg *ifa;
195 assert_return(m, -EINVAL);
196 assert_return(m->hdr, -EINVAL);
197 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
199 ifa = NLMSG_DATA(m->hdr);
201 ifa->ifa_flags = flags;
206 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
207 struct ifaddrmsg *ifa;
209 assert_return(m, -EINVAL);
210 assert_return(m->hdr, -EINVAL);
211 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
213 ifa = NLMSG_DATA(m->hdr);
215 ifa->ifa_scope = scope;
220 int sd_rtnl_message_addr_new(uint16_t nlmsg_type, int index, unsigned char family,
221 sd_rtnl_message **ret) {
222 struct ifaddrmsg *ifa;
225 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
226 assert_return(index > 0, -EINVAL);
227 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
228 assert_return(ret, -EINVAL);
230 r = message_new(ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
234 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
235 (*ret)->hdr->nlmsg_type = nlmsg_type;
237 ifa = NLMSG_DATA((*ret)->hdr);
239 ifa->ifa_index = index;
240 ifa->ifa_family = family;
241 if (family == AF_INET)
242 ifa->ifa_prefixlen = 32;
243 else if (family == AF_INET6)
244 ifa->ifa_prefixlen = 128;
246 UPDATE_RTA(*ret, IFA_RTA(ifa));
251 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
253 assert_se(REFCNT_INC(m->n_ref) >= 2);
258 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
259 if (m && REFCNT_DEC(m->n_ref) <= 0) {
267 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
268 assert_return(m, -EINVAL);
269 assert_return(type, -EINVAL);
271 *type = m->hdr->nlmsg_type;
276 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
277 struct ifinfomsg *ifi;
279 assert_return(m, -EINVAL);
280 assert_return(m->hdr, -EINVAL);
281 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
282 assert_return(ifindex, -EINVAL);
284 ifi = NLMSG_DATA(m->hdr);
286 *ifindex = ifi->ifi_index;
291 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
292 struct ifinfomsg *ifi;
294 assert_return(m, -EINVAL);
295 assert_return(m->hdr, -EINVAL);
296 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
297 assert_return(flags, -EINVAL);
299 ifi = NLMSG_DATA(m->hdr);
301 *flags = ifi->ifi_flags;
306 /* If successful the updated message will be correctly aligned, if
307 unsuccessful the old message is untouched. */
308 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
309 uint32_t rta_length, message_length;
310 struct nlmsghdr *new_hdr;
318 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
319 assert(!data || data_length > 0);
320 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
322 /* get the size of the new rta attribute (with padding at the end) */
323 rta_length = RTA_LENGTH(data_length);
325 /* get the new message size (with padding at the end) */
326 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
328 /* realloc to fit the new attribute */
329 new_hdr = realloc(m->hdr, message_length);
334 /* get pointer to the attribute we are about to add */
335 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
337 /* if we are inside containers, extend them */
338 for (i = 0; i < m->n_containers; i++)
339 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
341 /* fill in the attribute */
342 rta->rta_type = type;
343 rta->rta_len = rta_length;
345 /* this is the start of a new container */
346 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
348 /* we don't deal with the case where the user lies about the type
349 * and gives us too little data (so don't do that)
351 padding = mempcpy(RTA_DATA(rta), data, data_length);
352 /* make sure also the padding at the end of the message is initialized */
354 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
357 /* update message size */
358 m->hdr->nlmsg_len = message_length;
363 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
367 assert_return(m, -EINVAL);
368 assert_return(!m->sealed, -EPERM);
369 assert_return(data, -EINVAL);
371 r = sd_rtnl_message_get_type(m, &rtm_type);
375 /* check that the type is correct */
381 if (m->n_containers == 1) {
382 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
383 type != IFLA_INFO_KIND)
399 if (type != IFA_LABEL)
406 r = add_rtattr(m, type, data, strlen(data) + 1);
413 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
417 assert_return(m, -EINVAL);
418 assert_return(!m->sealed, -EPERM);
420 r = sd_rtnl_message_get_type(m, &rtm_type);
424 /* check that the type is correct */
430 if (m->n_containers == 2 &&
431 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
432 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
433 type == IFLA_VLAN_ID)
442 r = add_rtattr(m, type, &data, sizeof(uint16_t));
449 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
453 assert_return(m, -EINVAL);
454 assert_return(!m->sealed, -EPERM);
456 r = sd_rtnl_message_get_type(m, &rtm_type);
460 /* check that the type is correct */
492 r = add_rtattr(m, type, &data, sizeof(uint32_t));
499 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
500 struct ifaddrmsg *ifa;
505 assert_return(m, -EINVAL);
506 assert_return(!m->sealed, -EPERM);
507 assert_return(data, -EINVAL);
509 r = sd_rtnl_message_get_type(m, &rtm_type);
513 /* check that the type is correct */
523 ifa = NLMSG_DATA(m->hdr);
525 if (ifa->ifa_family != AF_INET)
540 rtm = NLMSG_DATA(m->hdr);
542 if (rtm->rtm_family != AF_INET)
554 r = add_rtattr(m, type, data, sizeof(struct in_addr));
561 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
562 struct ifaddrmsg *ifa;
567 assert_return(m, -EINVAL);
568 assert_return(!m->sealed, -EPERM);
569 assert_return(data, -EINVAL);
571 r = sd_rtnl_message_get_type(m, &rtm_type);
575 /* check that the type is correct */
585 ifa = NLMSG_DATA(m->hdr);
587 if (ifa->ifa_family != AF_INET6)
602 rtm = NLMSG_DATA(m->hdr);
604 if (rtm->rtm_family != AF_INET6)
615 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
622 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
626 assert_return(m, -EINVAL);
627 assert_return(!m->sealed, -EPERM);
628 assert_return(data, -EINVAL);
630 sd_rtnl_message_get_type(m, &rtm_type);
649 r = add_rtattr(m, type, data, ETH_ALEN);
656 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
659 assert_return(m, -EINVAL);
660 assert_return(!m->sealed, -EPERM);
662 sd_rtnl_message_get_type(m, &rtm_type);
664 if (rtnl_message_type_is_link(rtm_type)) {
665 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
666 (type == IFLA_INFO_DATA && m->n_containers == 1 &&
667 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
668 return add_rtattr(m, type, NULL, 0);
677 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
678 assert_return(m, -EINVAL);
679 assert_return(!m->sealed, -EPERM);
680 assert_return(m->n_containers > 0, -EINVAL);
687 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
688 size_t remaining_size;
692 assert_return(m, -EINVAL);
693 assert_return(m->sealed, -EPERM);
694 assert_return(m->next_rta_offset, -EINVAL);
695 assert_return(type, -EINVAL);
696 assert_return(data, -EINVAL);
698 /* only read until the end of the current container */
700 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
701 (m->next_rta_offset -
702 m->container_offsets[m->n_containers - 1]);
704 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
706 if (!RTA_OK(NEXT_RTA(m), remaining_size))
709 /* if we read a container, enter it and return its type */
710 r = sd_rtnl_message_get_type(m, &rtm_type);
714 *type = NEXT_RTA(m)->rta_type;
716 if (rtnl_message_type_is_link(rtm_type) &&
717 ((m->n_containers == 0 &&
718 NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
719 (m->n_containers == 1 &&
720 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
721 NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
723 PUSH_CONTAINER(m, NEXT_RTA(m));
724 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
726 *data = RTA_DATA(NEXT_RTA(m));
727 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
733 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
734 assert_return(m, -EINVAL);
735 assert_return(m->sealed, -EINVAL);
736 assert_return(m->n_containers > 0, -EINVAL);
743 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
747 return m->hdr->nlmsg_seq;
750 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
751 struct nlmsgerr *err;
753 assert_return(m, -EINVAL);
754 assert_return(m->hdr, -EINVAL);
756 if (m->hdr->nlmsg_type != NLMSG_ERROR)
759 err = NLMSG_DATA(m->hdr);
764 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
774 m->hdr->nlmsg_seq = nl->serial++;
778 r = sd_rtnl_message_rewind(m);
785 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
789 /* ioctl(rtnl->fd, FIONREAD, &need)
790 Does not appear to work on netlink sockets. libnl uses
791 MSG_PEEK instead. I don't know if that is worth the
794 For now we simply use the maximum message size the kernel
795 may use (NLMSG_GOODSIZE), and then realloc to the actual
796 size after reading the message (hence avoiding huge memory
797 usage in case many small messages are kept around) */
805 /* returns the number of bytes sent, or a negative error code */
806 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
809 struct sockaddr_nl nl;
811 .nl.nl_family = AF_NETLINK,
819 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
820 0, &addr.sa, sizeof(addr));
822 return (errno == EAGAIN) ? 0 : -errno;
827 /* On success, the number of bytes received is returned and *ret points to the received message
828 * which has a valid header and the correct size.
829 * If nothing useful was received 0 is returned.
830 * On failure, a negative error code is returned.
832 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
836 struct sockaddr_nl nl;
846 r = message_receive_need(nl, &need);
850 r = message_new(&m, need);
854 /* don't allow sealing/appending to received messages */
857 addr_len = sizeof(addr);
859 k = recvfrom(nl->fd, m->hdr, need,
860 0, &addr.sa, &addr_len);
862 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
864 k = -ECONNRESET; /* connection was closed by the kernel */
865 else if (addr_len != sizeof(addr.nl) ||
866 addr.nl.nl_family != AF_NETLINK)
867 k = -EIO; /* not a netlink message */
868 else if (addr.nl.nl_pid != 0)
869 k = 0; /* not from the kernel */
870 else if ((size_t) k < sizeof(struct nlmsghdr) ||
871 (size_t) k < m->hdr->nlmsg_len)
872 k = -EIO; /* too small (we do accept too big though) */
873 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
874 k = 0; /* not broadcast and not for us */
877 switch (m->hdr->nlmsg_type) {
878 struct ifinfomsg *ifi;
879 struct ifaddrmsg *ifa;
882 /* check that the size matches the message type */
884 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
891 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
894 ifi = NLMSG_DATA(m->hdr);
895 UPDATE_RTA(m, IFLA_RTA(ifi));
901 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
904 ifa = NLMSG_DATA(m->hdr);
905 UPDATE_RTA(m, IFA_RTA(ifa));
911 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
914 rtm = NLMSG_DATA(m->hdr);
915 UPDATE_RTA(m, RTM_RTA(rtm));
922 k = 0; /* ignoring message of unknown type */
926 sd_rtnl_message_unref(m);
928 /* we probably allocated way too much memory, give it back */
929 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
936 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
937 struct ifinfomsg *ifi;
938 struct ifaddrmsg *ifa;
941 assert_return(m, -EINVAL);
942 assert_return(m->sealed, -EPERM);
943 assert_return(m->hdr, -EINVAL);
945 switch(m->hdr->nlmsg_type) {
950 ifi = NLMSG_DATA(m->hdr);
951 UPDATE_RTA(m, IFLA_RTA(ifi));
957 ifa = NLMSG_DATA(m->hdr);
958 UPDATE_RTA(m, IFA_RTA(ifa));
964 rtm = NLMSG_DATA(m->hdr);
965 UPDATE_RTA(m, RTM_RTA(rtm));