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-internal.h"
34 struct sd_rtnl_message {
38 size_t container_offsets[RTNL_CONTAINER_DEPTH]; /* offset from hdr to each container's start */
39 unsigned n_containers; /* number of containers */
40 size_t next_rta_offset; /* offset from hdr to next rta */
45 #define GET_CONTAINER(m, i) (i < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
46 #define NEXT_RTA(m) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->next_rta_offset))
47 #define UPDATE_RTA(m, new) (m)->next_rta_offset = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
48 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
50 static int message_new(sd_rtnl_message **ret, size_t initial_size) {
53 assert_return(ret, -EINVAL);
54 assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
56 m = new0(sd_rtnl_message, 1);
60 m->hdr = malloc0(initial_size);
66 m->n_ref = REFCNT_INIT;
68 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
76 int message_new_synthetic_error(int error, uint32_t serial, sd_rtnl_message **ret) {
82 r = message_new(ret, NLMSG_SPACE(sizeof(struct nlmsgerr)));
86 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
87 (*ret)->hdr->nlmsg_type = NLMSG_ERROR;
88 (*ret)->hdr->nlmsg_seq = serial;
90 err = NLMSG_DATA((*ret)->hdr);
97 bool message_type_is_route(uint16_t type) {
108 bool message_type_is_link(uint16_t type) {
120 bool message_type_is_addr(uint16_t type) {
131 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
134 assert_return(m, -EINVAL);
135 assert_return(m->hdr, -EINVAL);
136 assert_return(message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
138 rtm = NLMSG_DATA(m->hdr);
140 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
141 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
144 rtm->rtm_dst_len = prefixlen;
149 int sd_rtnl_message_route_new(uint16_t nlmsg_type, unsigned char rtm_family,
150 sd_rtnl_message **ret) {
154 assert_return(message_type_is_route(nlmsg_type), -EINVAL);
155 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
156 assert_return(ret, -EINVAL);
158 r = message_new(ret, NLMSG_SPACE(sizeof(struct rtmsg)));
162 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
163 (*ret)->hdr->nlmsg_type = nlmsg_type;
164 if (nlmsg_type == RTM_NEWROUTE)
165 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
167 rtm = NLMSG_DATA((*ret)->hdr);
169 UPDATE_RTA(*ret, RTM_RTA(rtm));
171 rtm->rtm_family = rtm_family;
172 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
173 rtm->rtm_type = RTN_UNICAST;
174 rtm->rtm_table = RT_TABLE_MAIN;
175 rtm->rtm_protocol = RTPROT_BOOT;
180 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
181 struct ifinfomsg *ifi;
183 assert_return(m, -EINVAL);
184 assert_return(m->hdr, -EINVAL);
185 assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
187 ifi = NLMSG_DATA(m->hdr);
189 ifi->ifi_flags = flags;
191 ifi->ifi_change = change;
193 ifi->ifi_change = 0xffffffff;
198 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
199 struct ifinfomsg *ifi;
201 assert_return(m, -EINVAL);
202 assert_return(m->hdr, -EINVAL);
203 assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
205 ifi = NLMSG_DATA(m->hdr);
207 ifi->ifi_type = type;
212 int sd_rtnl_message_link_new(uint16_t nlmsg_type, int index, sd_rtnl_message **ret) {
213 struct ifinfomsg *ifi;
216 assert_return(message_type_is_link(nlmsg_type), -EINVAL);
217 assert_return(nlmsg_type == RTM_NEWLINK || index > 0, -EINVAL);
218 assert_return(ret, -EINVAL);
220 r = message_new(ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
224 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
225 (*ret)->hdr->nlmsg_type = nlmsg_type;
226 if (nlmsg_type == RTM_NEWLINK)
227 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
229 ifi = NLMSG_DATA((*ret)->hdr);
231 ifi->ifi_family = AF_UNSPEC;
232 ifi->ifi_index = index;
234 UPDATE_RTA(*ret, IFLA_RTA(ifi));
239 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
240 struct ifaddrmsg *ifa;
242 assert_return(m, -EINVAL);
243 assert_return(m->hdr, -EINVAL);
244 assert_return(message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
246 ifa = NLMSG_DATA(m->hdr);
248 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
249 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
252 ifa->ifa_prefixlen = prefixlen;
257 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
258 struct ifaddrmsg *ifa;
260 assert_return(m, -EINVAL);
261 assert_return(m->hdr, -EINVAL);
262 assert_return(message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
264 ifa = NLMSG_DATA(m->hdr);
266 ifa->ifa_flags = flags;
271 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
272 struct ifaddrmsg *ifa;
274 assert_return(m, -EINVAL);
275 assert_return(m->hdr, -EINVAL);
276 assert_return(message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
278 ifa = NLMSG_DATA(m->hdr);
280 ifa->ifa_scope = scope;
285 int sd_rtnl_message_addr_new(uint16_t nlmsg_type, int index, unsigned char family,
286 sd_rtnl_message **ret) {
287 struct ifaddrmsg *ifa;
290 assert_return(message_type_is_addr(nlmsg_type), -EINVAL);
291 assert_return(index > 0, -EINVAL);
292 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
293 assert_return(ret, -EINVAL);
295 r = message_new(ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
299 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
300 (*ret)->hdr->nlmsg_type = nlmsg_type;
302 ifa = NLMSG_DATA((*ret)->hdr);
304 ifa->ifa_index = index;
305 ifa->ifa_family = family;
306 if (family == AF_INET)
307 ifa->ifa_prefixlen = 32;
308 else if (family == AF_INET6)
309 ifa->ifa_prefixlen = 128;
311 UPDATE_RTA(*ret, IFA_RTA(ifa));
316 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
318 assert_se(REFCNT_INC(m->n_ref) >= 2);
323 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
324 if (m && REFCNT_DEC(m->n_ref) <= 0) {
332 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
333 assert_return(m, -EINVAL);
334 assert_return(type, -EINVAL);
336 *type = m->hdr->nlmsg_type;
341 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
342 struct ifinfomsg *ifi;
344 assert_return(m, -EINVAL);
345 assert_return(m->hdr, -EINVAL);
346 assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
347 assert_return(ifindex, -EINVAL);
349 ifi = NLMSG_DATA(m->hdr);
351 *ifindex = ifi->ifi_index;
356 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
357 struct ifinfomsg *ifi;
359 assert_return(m, -EINVAL);
360 assert_return(m->hdr, -EINVAL);
361 assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
362 assert_return(flags, -EINVAL);
364 ifi = NLMSG_DATA(m->hdr);
366 *flags = ifi->ifi_flags;
371 /* If successful the updated message will be correctly aligned, if
372 unsuccessful the old message is untouched. */
373 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
374 uint32_t rta_length, message_length;
375 struct nlmsghdr *new_hdr;
383 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
384 assert(!data || data_length > 0);
385 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
387 /* get the size of the new rta attribute (with padding at the end) */
388 rta_length = RTA_LENGTH(data_length);
390 /* get the new message size (with padding at the end) */
391 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
393 /* realloc to fit the new attribute */
394 new_hdr = realloc(m->hdr, message_length);
399 /* get pointer to the attribute we are about to add */
400 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
402 /* if we are inside containers, extend them */
403 for (i = 0; i < m->n_containers; i++)
404 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
406 /* fill in the attribute */
407 rta->rta_type = type;
408 rta->rta_len = rta_length;
410 /* this is the start of a new container */
411 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
413 /* we don't deal with the case where the user lies about the type
414 * and gives us too little data (so don't do that)
416 padding = mempcpy(RTA_DATA(rta), data, data_length);
417 /* make sure also the padding at the end of the message is initialized */
419 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
422 /* update message size */
423 m->hdr->nlmsg_len = message_length;
428 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
432 assert_return(m, -EINVAL);
433 assert_return(!m->sealed, -EPERM);
434 assert_return(data, -EINVAL);
436 r = sd_rtnl_message_get_type(m, &rtm_type);
440 /* check that the type is correct */
446 if (m->n_containers == 1) {
447 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
448 type != IFLA_INFO_KIND)
464 if (type != IFA_LABEL)
471 r = add_rtattr(m, type, data, strlen(data) + 1);
478 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
482 assert_return(m, -EINVAL);
483 assert_return(!m->sealed, -EPERM);
485 r = sd_rtnl_message_get_type(m, &rtm_type);
489 /* check that the type is correct */
495 if (m->n_containers == 2 &&
496 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
497 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
498 type == IFLA_VLAN_ID)
507 r = add_rtattr(m, type, &data, sizeof(uint16_t));
514 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
518 assert_return(m, -EINVAL);
519 assert_return(!m->sealed, -EPERM);
521 r = sd_rtnl_message_get_type(m, &rtm_type);
525 /* check that the type is correct */
557 r = add_rtattr(m, type, &data, sizeof(uint32_t));
564 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
565 struct ifaddrmsg *ifa;
570 assert_return(m, -EINVAL);
571 assert_return(!m->sealed, -EPERM);
572 assert_return(data, -EINVAL);
574 r = sd_rtnl_message_get_type(m, &rtm_type);
578 /* check that the type is correct */
588 ifa = NLMSG_DATA(m->hdr);
590 if (ifa->ifa_family != AF_INET)
605 rtm = NLMSG_DATA(m->hdr);
607 if (rtm->rtm_family != AF_INET)
619 r = add_rtattr(m, type, data, sizeof(struct in_addr));
626 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
627 struct ifaddrmsg *ifa;
632 assert_return(m, -EINVAL);
633 assert_return(!m->sealed, -EPERM);
634 assert_return(data, -EINVAL);
636 r = sd_rtnl_message_get_type(m, &rtm_type);
640 /* check that the type is correct */
650 ifa = NLMSG_DATA(m->hdr);
652 if (ifa->ifa_family != AF_INET6)
667 rtm = NLMSG_DATA(m->hdr);
669 if (rtm->rtm_family != AF_INET6)
680 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
687 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
691 assert_return(m, -EINVAL);
692 assert_return(!m->sealed, -EPERM);
693 assert_return(data, -EINVAL);
695 sd_rtnl_message_get_type(m, &rtm_type);
714 r = add_rtattr(m, type, data, ETH_ALEN);
721 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
724 assert_return(m, -EINVAL);
725 assert_return(!m->sealed, -EPERM);
727 sd_rtnl_message_get_type(m, &rtm_type);
729 if (message_type_is_link(rtm_type)) {
730 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
731 (type == IFLA_INFO_DATA && m->n_containers == 1 &&
732 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
733 return add_rtattr(m, type, NULL, 0);
742 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
743 assert_return(m, -EINVAL);
744 assert_return(!m->sealed, -EPERM);
745 assert_return(m->n_containers > 0, -EINVAL);
752 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
753 size_t remaining_size;
757 assert_return(m, -EINVAL);
758 assert_return(m->sealed, -EPERM);
759 assert_return(m->next_rta_offset, -EINVAL);
760 assert_return(type, -EINVAL);
761 assert_return(data, -EINVAL);
763 /* only read until the end of the current container */
765 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
766 (m->next_rta_offset -
767 m->container_offsets[m->n_containers - 1]);
769 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
771 if (!RTA_OK(NEXT_RTA(m), remaining_size))
774 /* if we read a container, enter it and return its type */
775 r = sd_rtnl_message_get_type(m, &rtm_type);
779 *type = NEXT_RTA(m)->rta_type;
781 if (message_type_is_link(rtm_type) &&
782 ((m->n_containers == 0 &&
783 NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
784 (m->n_containers == 1 &&
785 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
786 NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
788 PUSH_CONTAINER(m, NEXT_RTA(m));
789 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
791 *data = RTA_DATA(NEXT_RTA(m));
792 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
798 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
799 assert_return(m, -EINVAL);
800 assert_return(m->sealed, -EINVAL);
801 assert_return(m->n_containers > 0, -EINVAL);
808 uint32_t message_get_serial(sd_rtnl_message *m) {
812 return m->hdr->nlmsg_seq;
815 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
816 struct nlmsgerr *err;
818 assert_return(m, -EINVAL);
819 assert_return(m->hdr, -EINVAL);
821 if (m->hdr->nlmsg_type != NLMSG_ERROR)
824 err = NLMSG_DATA(m->hdr);
829 int message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
839 m->hdr->nlmsg_seq = nl->serial++;
843 r = sd_rtnl_message_rewind(m);
850 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
854 /* ioctl(rtnl->fd, FIONREAD, &need)
855 Does not appear to work on netlink sockets. libnl uses
856 MSG_PEEK instead. I don't know if that is worth the
859 For now we simply use the maximum message size the kernel
860 may use (NLMSG_GOODSIZE), and then realloc to the actual
861 size after reading the message (hence avoiding huge memory
862 usage in case many small messages are kept around) */
870 /* returns the number of bytes sent, or a negative error code */
871 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
874 struct sockaddr_nl nl;
876 .nl.nl_family = AF_NETLINK,
884 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
885 0, &addr.sa, sizeof(addr));
887 return (errno == EAGAIN) ? 0 : -errno;
892 /* On success, the number of bytes received is returned and *ret points to the received message
893 * which has a valid header and the correct size.
894 * If nothing useful was received 0 is returned.
895 * On failure, a negative error code is returned.
897 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
901 struct sockaddr_nl nl;
911 r = message_receive_need(nl, &need);
915 r = message_new(&m, need);
919 /* don't allow sealing/appending to received messages */
922 addr_len = sizeof(addr);
924 k = recvfrom(nl->fd, m->hdr, need,
925 0, &addr.sa, &addr_len);
927 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
929 k = -ECONNRESET; /* connection was closed by the kernel */
930 else if (addr_len != sizeof(addr.nl) ||
931 addr.nl.nl_family != AF_NETLINK)
932 k = -EIO; /* not a netlink message */
933 else if (addr.nl.nl_pid != 0)
934 k = 0; /* not from the kernel */
935 else if ((size_t) k < sizeof(struct nlmsghdr) ||
936 (size_t) k < m->hdr->nlmsg_len)
937 k = -EIO; /* too small (we do accept too big though) */
938 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
939 k = 0; /* not broadcast and not for us */
942 switch (m->hdr->nlmsg_type) {
943 struct ifinfomsg *ifi;
944 struct ifaddrmsg *ifa;
947 /* check that the size matches the message type */
949 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
956 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
959 ifi = NLMSG_DATA(m->hdr);
960 UPDATE_RTA(m, IFLA_RTA(ifi));
966 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
969 ifa = NLMSG_DATA(m->hdr);
970 UPDATE_RTA(m, IFA_RTA(ifa));
976 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
979 rtm = NLMSG_DATA(m->hdr);
980 UPDATE_RTA(m, RTM_RTA(rtm));
987 k = 0; /* ignoring message of unknown type */
991 sd_rtnl_message_unref(m);
993 /* we probably allocated way too much memory, give it back */
994 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
1001 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1002 struct ifinfomsg *ifi;
1003 struct ifaddrmsg *ifa;
1006 assert_return(m, -EINVAL);
1007 assert_return(m->sealed, -EPERM);
1008 assert_return(m->hdr, -EINVAL);
1010 switch(m->hdr->nlmsg_type) {
1015 ifi = NLMSG_DATA(m->hdr);
1016 UPDATE_RTA(m, IFLA_RTA(ifi));
1022 ifa = NLMSG_DATA(m->hdr);
1023 UPDATE_RTA(m, IFA_RTA(ifa));
1029 rtm = NLMSG_DATA(m->hdr);
1030 UPDATE_RTA(m, RTM_RTA(rtm));
1037 m->n_containers = 0;