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>
32 #include "rtnl-util.h"
33 #include "rtnl-internal.h"
34 #include "rtnl-types.h"
36 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
37 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
39 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
41 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
44 assert_return(ret, -EINVAL);
46 /* Note that 'rtnl' is curretly unused, if we start using it internally
47 we must take care to avoid problems due to mutual references between
48 busses and their queued messages. See sd-bus.
51 m = new0(sd_rtnl_message, 1);
55 m->n_ref = REFCNT_INIT;
64 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
65 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
66 const NLType *nl_type;
70 r = type_system_get_type(NULL, &nl_type, type);
74 assert(nl_type->type == NLA_NESTED);
76 r = message_new_empty(rtnl, &m);
80 size = NLMSG_SPACE(nl_type->size);
82 assert(size >= sizeof(struct nlmsghdr));
83 m->hdr = malloc0(size);
87 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
89 m->container_type_system[0] = nl_type->type_system;
90 m->hdr->nlmsg_len = size;
91 m->hdr->nlmsg_type = type;
99 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
102 assert_return(m, -EINVAL);
103 assert_return(m->hdr, -EINVAL);
104 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
106 rtm = NLMSG_DATA(m->hdr);
108 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
109 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
112 rtm->rtm_dst_len = prefixlen;
117 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
120 assert_return(m, -EINVAL);
121 assert_return(m->hdr, -EINVAL);
122 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
124 rtm = NLMSG_DATA(m->hdr);
126 rtm->rtm_scope = scope;
131 int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) {
134 assert_return(m, -EINVAL);
135 assert_return(m->hdr, -EINVAL);
136 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
137 assert_return(family, -EINVAL);
139 rtm = NLMSG_DATA(m->hdr);
141 *family = rtm->rtm_family;
146 int sd_rtnl_message_route_get_dst_len(sd_rtnl_message *m, unsigned char *dst_len) {
149 assert_return(m, -EINVAL);
150 assert_return(m->hdr, -EINVAL);
151 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
152 assert_return(dst_len, -EINVAL);
154 rtm = NLMSG_DATA(m->hdr);
156 *dst_len = rtm->rtm_dst_len;
161 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
162 uint16_t nlmsg_type, int rtm_family,
163 unsigned char rtm_protocol) {
167 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
168 assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
169 rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
170 assert_return(ret, -EINVAL);
172 r = message_new(rtnl, ret, nlmsg_type);
176 if (nlmsg_type == RTM_NEWROUTE)
177 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
179 rtm = NLMSG_DATA((*ret)->hdr);
181 rtm->rtm_family = rtm_family;
182 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
183 rtm->rtm_type = RTN_UNICAST;
184 rtm->rtm_table = RT_TABLE_MAIN;
185 rtm->rtm_protocol = rtm_protocol;
190 int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
193 assert_return(m, -EINVAL);
194 assert_return(m->hdr, -EINVAL);
195 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
196 assert_return(family, -EINVAL);
198 ndm = NLMSG_DATA(m->hdr);
200 *family = ndm->ndm_family;
205 int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
208 assert_return(m, -EINVAL);
209 assert_return(m->hdr, -EINVAL);
210 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
211 assert_return(index, -EINVAL);
213 ndm = NLMSG_DATA(m->hdr);
215 *index = ndm->ndm_ifindex;
220 int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
224 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
225 assert_return(ndm_family == AF_INET || ndm_family == AF_INET6, -EINVAL);
226 assert_return(ret, -EINVAL);
228 r = message_new(rtnl, ret, nlmsg_type);
232 if (nlmsg_type == RTM_NEWNEIGH)
233 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
235 ndm = NLMSG_DATA((*ret)->hdr);
237 ndm->ndm_family = ndm_family;
238 ndm->ndm_ifindex = index;
243 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
244 struct ifinfomsg *ifi;
246 assert_return(m, -EINVAL);
247 assert_return(m->hdr, -EINVAL);
248 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
249 assert_return(change, -EINVAL);
251 ifi = NLMSG_DATA(m->hdr);
253 ifi->ifi_flags = flags;
254 ifi->ifi_change = change;
259 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
260 struct ifinfomsg *ifi;
262 assert_return(m, -EINVAL);
263 assert_return(m->hdr, -EINVAL);
264 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
266 ifi = NLMSG_DATA(m->hdr);
268 ifi->ifi_type = type;
273 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
274 struct ifinfomsg *ifi;
276 assert_return(m, -EINVAL);
277 assert_return(m->hdr, -EINVAL);
278 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
280 ifi = NLMSG_DATA(m->hdr);
282 ifi->ifi_family = family;
287 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
288 uint16_t nlmsg_type, int index) {
289 struct ifinfomsg *ifi;
292 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
293 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
294 assert_return(ret, -EINVAL);
296 r = message_new(rtnl, ret, nlmsg_type);
300 if (nlmsg_type == RTM_NEWLINK)
301 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
303 ifi = NLMSG_DATA((*ret)->hdr);
305 ifi->ifi_family = AF_UNSPEC;
306 ifi->ifi_index = index;
311 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
312 assert_return(m, -EINVAL);
313 assert_return(m->hdr, -EINVAL);
314 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
315 m->hdr->nlmsg_type == RTM_GETADDR ||
316 m->hdr->nlmsg_type == RTM_GETROUTE ||
317 m->hdr->nlmsg_type == RTM_GETNEIGH,
321 m->hdr->nlmsg_flags |= NLM_F_DUMP;
323 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
328 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
329 struct ifaddrmsg *ifa;
331 assert_return(m, -EINVAL);
332 assert_return(m->hdr, -EINVAL);
333 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
335 ifa = NLMSG_DATA(m->hdr);
337 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
338 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
341 ifa->ifa_prefixlen = prefixlen;
346 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
347 struct ifaddrmsg *ifa;
349 assert_return(m, -EINVAL);
350 assert_return(m->hdr, -EINVAL);
351 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
353 ifa = NLMSG_DATA(m->hdr);
355 ifa->ifa_flags = flags;
360 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
361 struct ifaddrmsg *ifa;
363 assert_return(m, -EINVAL);
364 assert_return(m->hdr, -EINVAL);
365 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
367 ifa = NLMSG_DATA(m->hdr);
369 ifa->ifa_scope = scope;
374 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
375 struct ifaddrmsg *ifa;
377 assert_return(m, -EINVAL);
378 assert_return(m->hdr, -EINVAL);
379 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
380 assert_return(family, -EINVAL);
382 ifa = NLMSG_DATA(m->hdr);
384 *family = ifa->ifa_family;
389 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
390 struct ifaddrmsg *ifa;
392 assert_return(m, -EINVAL);
393 assert_return(m->hdr, -EINVAL);
394 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
395 assert_return(prefixlen, -EINVAL);
397 ifa = NLMSG_DATA(m->hdr);
399 *prefixlen = ifa->ifa_prefixlen;
404 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
405 struct ifaddrmsg *ifa;
407 assert_return(m, -EINVAL);
408 assert_return(m->hdr, -EINVAL);
409 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
410 assert_return(scope, -EINVAL);
412 ifa = NLMSG_DATA(m->hdr);
414 *scope = ifa->ifa_scope;
419 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
420 struct ifaddrmsg *ifa;
422 assert_return(m, -EINVAL);
423 assert_return(m->hdr, -EINVAL);
424 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
425 assert_return(flags, -EINVAL);
427 ifa = NLMSG_DATA(m->hdr);
429 *flags = ifa->ifa_flags;
434 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
435 struct ifaddrmsg *ifa;
437 assert_return(m, -EINVAL);
438 assert_return(m->hdr, -EINVAL);
439 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
440 assert_return(ifindex, -EINVAL);
442 ifa = NLMSG_DATA(m->hdr);
444 *ifindex = ifa->ifa_index;
449 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
450 uint16_t nlmsg_type, int index,
452 struct ifaddrmsg *ifa;
455 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
456 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
458 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
459 family == AF_INET || family == AF_INET6, -EINVAL);
460 assert_return(ret, -EINVAL);
462 r = message_new(rtnl, ret, nlmsg_type);
466 if (nlmsg_type == RTM_GETADDR)
467 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
469 ifa = NLMSG_DATA((*ret)->hdr);
471 ifa->ifa_index = index;
472 ifa->ifa_family = family;
473 if (family == AF_INET)
474 ifa->ifa_prefixlen = 32;
475 else if (family == AF_INET6)
476 ifa->ifa_prefixlen = 128;
481 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
482 int index, int family) {
485 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
489 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
494 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
496 assert_se(REFCNT_INC(m->n_ref) >= 2);
501 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
502 if (m && REFCNT_DEC(m->n_ref) <= 0) {
507 for (i = 0; i <= m->n_containers; i++)
508 free(m->rta_offset_tb[i]);
510 sd_rtnl_message_unref(m->next);
518 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
519 assert_return(m, -EINVAL);
520 assert_return(type, -EINVAL);
522 *type = m->hdr->nlmsg_type;
527 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
528 assert_return(m, -EINVAL);
530 return !m->hdr->nlmsg_pid;
533 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
534 struct ifinfomsg *ifi;
536 assert_return(m, -EINVAL);
537 assert_return(m->hdr, -EINVAL);
538 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
539 assert_return(ifindex, -EINVAL);
541 ifi = NLMSG_DATA(m->hdr);
543 *ifindex = ifi->ifi_index;
548 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
549 struct ifinfomsg *ifi;
551 assert_return(m, -EINVAL);
552 assert_return(m->hdr, -EINVAL);
553 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
554 assert_return(flags, -EINVAL);
556 ifi = NLMSG_DATA(m->hdr);
558 *flags = ifi->ifi_flags;
563 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
564 struct ifinfomsg *ifi;
566 assert_return(m, -EINVAL);
567 assert_return(m->hdr, -EINVAL);
568 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
569 assert_return(type, -EINVAL);
571 ifi = NLMSG_DATA(m->hdr);
573 *type = ifi->ifi_type;
578 /* If successful the updated message will be correctly aligned, if
579 unsuccessful the old message is untouched. */
580 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
582 size_t message_length, padding_length;
583 struct nlmsghdr *new_hdr;
592 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
593 assert(!data || data_length);
595 /* get offset of the new attribute */
596 offset = m->hdr->nlmsg_len;
598 /* get the size of the new rta attribute (with padding at the end) */
599 rta_length = RTA_LENGTH(data_length);
601 /* get the new message size (with padding at the end) */
602 message_length = offset + RTA_ALIGN(rta_length);
604 /* realloc to fit the new attribute */
605 new_hdr = realloc(m->hdr, message_length);
610 /* get pointer to the attribute we are about to add */
611 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
613 /* if we are inside containers, extend them */
614 for (i = 0; i < m->n_containers; i++)
615 GET_CONTAINER(m, i)->rta_len += message_length - offset;
617 /* fill in the attribute */
618 rta->rta_type = type;
619 rta->rta_len = rta_length;
621 /* we don't deal with the case where the user lies about the type
622 * and gives us too little data (so don't do that)
624 padding = mempcpy(RTA_DATA(rta), data, data_length);
626 /* if no data was passed, make sure we still initialize the padding
627 note that we can have data_length > 0 (used by some containers) */
628 padding = RTA_DATA(rta);
631 /* make sure also the padding at the end of the message is initialized */
632 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
633 memzero(padding, padding_length);
635 /* update message size */
636 m->hdr->nlmsg_len = message_length;
641 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
645 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
649 if (type->type != data_type)
655 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
659 assert_return(m, -EINVAL);
660 assert_return(!m->sealed, -EPERM);
661 assert_return(data, -EINVAL);
663 r = message_attribute_has_type(m, type, NLA_STRING);
670 length = strnlen(data, size);
674 length = strlen(data);
676 r = add_rtattr(m, type, data, length + 1);
683 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
686 assert_return(m, -EINVAL);
687 assert_return(!m->sealed, -EPERM);
689 r = message_attribute_has_type(m, type, NLA_U8);
693 r = add_rtattr(m, type, &data, sizeof(uint8_t));
701 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
704 assert_return(m, -EINVAL);
705 assert_return(!m->sealed, -EPERM);
707 r = message_attribute_has_type(m, type, NLA_U16);
711 r = add_rtattr(m, type, &data, sizeof(uint16_t));
718 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
721 assert_return(m, -EINVAL);
722 assert_return(!m->sealed, -EPERM);
724 r = message_attribute_has_type(m, type, NLA_U32);
728 r = add_rtattr(m, type, &data, sizeof(uint32_t));
735 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
738 assert_return(m, -EINVAL);
739 assert_return(!m->sealed, -EPERM);
740 assert_return(data, -EINVAL);
742 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
746 r = add_rtattr(m, type, data, sizeof(struct in_addr));
753 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
756 assert_return(m, -EINVAL);
757 assert_return(!m->sealed, -EPERM);
758 assert_return(data, -EINVAL);
760 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
764 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
771 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
774 assert_return(m, -EINVAL);
775 assert_return(!m->sealed, -EPERM);
776 assert_return(data, -EINVAL);
778 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
782 r = add_rtattr(m, type, data, ETH_ALEN);
789 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
792 assert_return(m, -EINVAL);
793 assert_return(!m->sealed, -EPERM);
794 assert_return(info, -EINVAL);
796 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
800 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
807 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
811 assert_return(m, -EINVAL);
812 assert_return(!m->sealed, -EPERM);
813 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
815 r = message_attribute_has_type(m, type, NLA_NESTED);
821 r = type_system_get_type_system(m->container_type_system[m->n_containers],
822 &m->container_type_system[m->n_containers + 1],
827 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
831 m->container_offsets[m->n_containers ++] = r;
836 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
837 const NLTypeSystemUnion *type_system_union;
840 assert_return(m, -EINVAL);
841 assert_return(!m->sealed, -EPERM);
843 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
847 r = type_system_union_get_type_system(type_system_union,
848 &m->container_type_system[m->n_containers + 1],
853 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
857 /* do we evere need non-null size */
858 r = add_rtattr(m, type, NULL, 0);
862 m->container_offsets[m->n_containers ++] = r;
868 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
869 assert_return(m, -EINVAL);
870 assert_return(!m->sealed, -EPERM);
871 assert_return(m->n_containers > 0, -EINVAL);
873 m->container_type_system[m->n_containers] = NULL;
879 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
882 assert_return(m, -EINVAL);
883 assert_return(m->sealed, -EPERM);
884 assert_return(data, -EINVAL);
885 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
886 assert(m->rta_offset_tb[m->n_containers]);
887 assert(type < m->rta_tb_size[m->n_containers]);
889 if(!m->rta_offset_tb[m->n_containers][type])
892 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
894 *data = RTA_DATA(rta);
896 return RTA_PAYLOAD(rta);
899 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
903 assert_return(m, -EINVAL);
905 r = message_attribute_has_type(m, type, NLA_STRING);
909 r = rtnl_message_read_internal(m, type, &attr_data);
912 else if (strnlen(attr_data, r) >= (size_t) r)
916 *data = (const char *) attr_data;
921 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
925 assert_return(m, -EINVAL);
927 r = message_attribute_has_type(m, type, NLA_U8);
931 r = rtnl_message_read_internal(m, type, &attr_data);
934 else if ((size_t) r < sizeof(uint8_t))
938 *data = *(uint8_t *) attr_data;
943 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
947 assert_return(m, -EINVAL);
949 r = message_attribute_has_type(m, type, NLA_U16);
953 r = rtnl_message_read_internal(m, type, &attr_data);
956 else if ((size_t) r < sizeof(uint16_t))
960 *data = *(uint16_t *) attr_data;
965 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
969 assert_return(m, -EINVAL);
971 r = message_attribute_has_type(m, type, NLA_U32);
975 r = rtnl_message_read_internal(m, type, &attr_data);
978 else if ((size_t)r < sizeof(uint32_t))
982 *data = *(uint32_t *) attr_data;
987 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
991 assert_return(m, -EINVAL);
993 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
997 r = rtnl_message_read_internal(m, type, &attr_data);
1000 else if ((size_t)r < sizeof(struct ether_addr))
1004 memcpy(data, attr_data, sizeof(struct ether_addr));
1009 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
1013 assert_return(m, -EINVAL);
1015 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
1019 r = rtnl_message_read_internal(m, type, &attr_data);
1022 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
1026 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
1031 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
1035 assert_return(m, -EINVAL);
1037 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1041 r = rtnl_message_read_internal(m, type, &attr_data);
1044 else if ((size_t)r < sizeof(struct in_addr))
1048 memcpy(data, attr_data, sizeof(struct in_addr));
1053 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
1057 assert_return(m, -EINVAL);
1059 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1063 r = rtnl_message_read_internal(m, type, &attr_data);
1066 else if ((size_t)r < sizeof(struct in6_addr))
1070 memcpy(data, attr_data, sizeof(struct in6_addr));
1075 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
1076 const NLType *nl_type;
1077 const NLTypeSystem *type_system;
1082 assert_return(m, -EINVAL);
1083 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1085 r = type_system_get_type(m->container_type_system[m->n_containers],
1091 if (nl_type->type == NLA_NESTED) {
1092 r = type_system_get_type_system(m->container_type_system[m->n_containers],
1097 } else if (nl_type->type == NLA_UNION) {
1098 const NLTypeSystemUnion *type_system_union;
1101 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1107 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1111 r = type_system_union_get_type_system(type_system_union,
1119 r = rtnl_message_read_internal(m, type, &container);
1127 r = rtnl_message_parse(m,
1128 &m->rta_offset_tb[m->n_containers],
1129 &m->rta_tb_size[m->n_containers],
1138 m->container_type_system[m->n_containers] = type_system;
1143 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1144 assert_return(m, -EINVAL);
1145 assert_return(m->sealed, -EINVAL);
1146 assert_return(m->n_containers > 0, -EINVAL);
1148 free(m->rta_offset_tb[m->n_containers]);
1149 m->rta_offset_tb[m->n_containers] = NULL;
1150 m->container_type_system[m->n_containers] = NULL;
1157 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1161 return m->hdr->nlmsg_seq;
1164 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1165 struct nlmsgerr *err;
1167 assert_return(m, -EINVAL);
1168 assert_return(m->hdr, -EINVAL);
1170 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1173 err = NLMSG_DATA(m->hdr);
1178 int rtnl_message_parse(sd_rtnl_message *m,
1179 size_t **rta_offset_tb,
1180 unsigned short *rta_tb_size,
1183 unsigned int rt_len) {
1184 unsigned short type;
1187 tb = new0(size_t, max + 1);
1191 *rta_tb_size = max + 1;
1193 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1194 type = RTA_TYPE(rta);
1196 /* if the kernel is newer than the headers we used
1197 when building, we ignore out-of-range attributes
1203 log_debug("rtnl: message parse - overwriting repeated attribute");
1205 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1208 *rta_offset_tb = tb;
1213 /* returns the number of bytes sent, or a negative error code */
1214 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1217 struct sockaddr_nl nl;
1219 .nl.nl_family = AF_NETLINK,
1227 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1228 0, &addr.sa, sizeof(addr));
1230 return (errno == EAGAIN) ? 0 : -errno;
1235 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1236 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1237 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1238 struct msghdr msg = {
1241 .msg_control = cred_buffer,
1242 .msg_controllen = sizeof(cred_buffer),
1244 struct cmsghdr *cmsg;
1252 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1255 if (errno == ENOBUFS)
1256 log_debug("rtnl: kernel receive buffer overrun");
1258 return (errno == EAGAIN) ? 0 : -errno;
1260 /* connection was closed by the kernel */
1263 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1264 if (cmsg->cmsg_level == SOL_SOCKET &&
1265 cmsg->cmsg_type == SCM_CREDENTIALS &&
1266 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1267 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1269 /* from the kernel */
1270 if (ucred->uid == 0 && ucred->pid == 0)
1272 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1273 cmsg->cmsg_type == NETLINK_PKTINFO &&
1274 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1275 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1277 /* multi-cast group */
1278 group = pktinfo->group;
1283 /* not from the kernel, ignore */
1292 /* On success, the number of bytes received is returned and *ret points to the received message
1293 * which has a valid header and the correct size.
1294 * If nothing useful was received 0 is returned.
1295 * On failure, a negative error code is returned.
1297 int socket_read_message(sd_rtnl *rtnl) {
1298 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1299 struct iovec iov = {};
1301 bool multi_part = false, done = false;
1302 struct nlmsghdr *new_msg;
1308 assert(rtnl->rbuffer);
1309 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1311 /* read nothing, just get the pending message size */
1312 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1318 /* make room for the pending message */
1319 if (!greedy_realloc((void **)&rtnl->rbuffer,
1320 &rtnl->rbuffer_allocated,
1321 len, sizeof(uint8_t)))
1324 iov.iov_base = rtnl->rbuffer;
1325 iov.iov_len = rtnl->rbuffer_allocated;
1327 /* read the pending message */
1328 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1334 if (len > rtnl->rbuffer_allocated)
1335 /* message did not fit in read buffer */
1338 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1341 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1342 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1343 rtnl->rbuffer->nlmsg_seq) {
1344 first = rtnl->rqueue_partial[i];
1350 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1351 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1352 const NLType *nl_type;
1354 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1355 /* not broadcast and not for us */
1358 if (new_msg->nlmsg_type == NLMSG_NOOP)
1359 /* silently drop noop messages */
1362 if (new_msg->nlmsg_type == NLMSG_DONE) {
1363 /* finished reading multi-part message */
1368 /* check that we support this message type */
1369 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1372 log_debug("sd-rtnl: ignored message with unknown type: %u",
1373 new_msg->nlmsg_type);
1378 /* check that the size matches the message type */
1379 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
1380 log_debug("sd-rtnl: message larger than expected, dropping");
1384 r = message_new_empty(rtnl, &m);
1388 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1392 /* seal and parse the top-level message */
1393 r = sd_rtnl_message_rewind(m);
1397 /* push the message onto the multi-part message stack */
1405 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1410 if (!multi_part || done) {
1411 /* we got a complete message, push it on the read queue */
1412 r = rtnl_rqueue_make_room(rtnl);
1416 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1419 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1420 /* remove the message form the partial read queue */
1421 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1422 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1423 rtnl->rqueue_partial_size --;
1428 /* we only got a partial multi-part message, push it on the
1429 partial read queue */
1430 if (i < rtnl->rqueue_partial_size) {
1431 rtnl->rqueue_partial[i] = first;
1433 r = rtnl_rqueue_partial_make_room(rtnl);
1437 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1445 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1450 assert_return(m, -EINVAL);
1452 /* don't allow appending to message once parsed */
1454 rtnl_message_seal(m);
1456 for (i = 1; i <= m->n_containers; i++) {
1457 free(m->rta_offset_tb[i]);
1458 m->rta_offset_tb[i] = NULL;
1459 m->rta_tb_size[i] = 0;
1460 m->container_type_system[i] = NULL;
1463 m->n_containers = 0;
1465 if (m->rta_offset_tb[0]) {
1466 /* top-level attributes have already been parsed */
1472 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1476 if (type->type == NLA_NESTED) {
1477 const NLTypeSystem *type_system = type->type_system;
1479 assert(type_system);
1481 m->container_type_system[0] = type_system;
1483 r = rtnl_message_parse(m,
1484 &m->rta_offset_tb[m->n_containers],
1485 &m->rta_tb_size[m->n_containers],
1487 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1488 NLMSG_ALIGN(type->size)),
1489 NLMSG_PAYLOAD(m->hdr, type->size));
1497 void rtnl_message_seal(sd_rtnl_message *m) {
1504 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1505 assert_return(m, NULL);