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_route_get_src_len(sd_rtnl_message *m, unsigned char *src_len) {
164 assert_return(m, -EINVAL);
165 assert_return(m->hdr, -EINVAL);
166 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
167 assert_return(src_len, -EINVAL);
169 rtm = NLMSG_DATA(m->hdr);
171 *src_len = rtm->rtm_src_len;
176 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
177 uint16_t nlmsg_type, int rtm_family,
178 unsigned char rtm_protocol) {
182 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
183 assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
184 rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
185 assert_return(ret, -EINVAL);
187 r = message_new(rtnl, ret, nlmsg_type);
191 if (nlmsg_type == RTM_NEWROUTE)
192 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
194 rtm = NLMSG_DATA((*ret)->hdr);
196 rtm->rtm_family = rtm_family;
197 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
198 rtm->rtm_type = RTN_UNICAST;
199 rtm->rtm_table = RT_TABLE_MAIN;
200 rtm->rtm_protocol = rtm_protocol;
205 int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
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(family, -EINVAL);
213 ndm = NLMSG_DATA(m->hdr);
215 *family = ndm->ndm_family;
220 int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
223 assert_return(m, -EINVAL);
224 assert_return(m->hdr, -EINVAL);
225 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
226 assert_return(index, -EINVAL);
228 ndm = NLMSG_DATA(m->hdr);
230 *index = ndm->ndm_ifindex;
235 int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
239 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
240 assert_return(ndm_family == AF_INET || ndm_family == AF_INET6, -EINVAL);
241 assert_return(ret, -EINVAL);
243 r = message_new(rtnl, ret, nlmsg_type);
247 if (nlmsg_type == RTM_NEWNEIGH)
248 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
250 ndm = NLMSG_DATA((*ret)->hdr);
252 ndm->ndm_family = ndm_family;
253 ndm->ndm_ifindex = index;
258 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
259 struct ifinfomsg *ifi;
261 assert_return(m, -EINVAL);
262 assert_return(m->hdr, -EINVAL);
263 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
264 assert_return(change, -EINVAL);
266 ifi = NLMSG_DATA(m->hdr);
268 ifi->ifi_flags = flags;
269 ifi->ifi_change = change;
274 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
275 struct ifinfomsg *ifi;
277 assert_return(m, -EINVAL);
278 assert_return(m->hdr, -EINVAL);
279 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
281 ifi = NLMSG_DATA(m->hdr);
283 ifi->ifi_type = type;
288 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
289 struct ifinfomsg *ifi;
291 assert_return(m, -EINVAL);
292 assert_return(m->hdr, -EINVAL);
293 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
295 ifi = NLMSG_DATA(m->hdr);
297 ifi->ifi_family = family;
302 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
303 uint16_t nlmsg_type, int index) {
304 struct ifinfomsg *ifi;
307 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
308 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
309 assert_return(ret, -EINVAL);
311 r = message_new(rtnl, ret, nlmsg_type);
315 if (nlmsg_type == RTM_NEWLINK)
316 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
318 ifi = NLMSG_DATA((*ret)->hdr);
320 ifi->ifi_family = AF_UNSPEC;
321 ifi->ifi_index = index;
326 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
327 assert_return(m, -EINVAL);
328 assert_return(m->hdr, -EINVAL);
329 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
330 m->hdr->nlmsg_type == RTM_GETADDR ||
331 m->hdr->nlmsg_type == RTM_GETROUTE ||
332 m->hdr->nlmsg_type == RTM_GETNEIGH,
336 m->hdr->nlmsg_flags |= NLM_F_DUMP;
338 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
343 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
344 struct ifaddrmsg *ifa;
346 assert_return(m, -EINVAL);
347 assert_return(m->hdr, -EINVAL);
348 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
350 ifa = NLMSG_DATA(m->hdr);
352 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
353 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
356 ifa->ifa_prefixlen = prefixlen;
361 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
362 struct ifaddrmsg *ifa;
364 assert_return(m, -EINVAL);
365 assert_return(m->hdr, -EINVAL);
366 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
368 ifa = NLMSG_DATA(m->hdr);
370 ifa->ifa_flags = flags;
375 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
376 struct ifaddrmsg *ifa;
378 assert_return(m, -EINVAL);
379 assert_return(m->hdr, -EINVAL);
380 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
382 ifa = NLMSG_DATA(m->hdr);
384 ifa->ifa_scope = scope;
389 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
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(family, -EINVAL);
397 ifa = NLMSG_DATA(m->hdr);
399 *family = ifa->ifa_family;
404 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
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(prefixlen, -EINVAL);
412 ifa = NLMSG_DATA(m->hdr);
414 *prefixlen = ifa->ifa_prefixlen;
419 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
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(scope, -EINVAL);
427 ifa = NLMSG_DATA(m->hdr);
429 *scope = ifa->ifa_scope;
434 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
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(flags, -EINVAL);
442 ifa = NLMSG_DATA(m->hdr);
444 *flags = ifa->ifa_flags;
449 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
450 struct ifaddrmsg *ifa;
452 assert_return(m, -EINVAL);
453 assert_return(m->hdr, -EINVAL);
454 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
455 assert_return(ifindex, -EINVAL);
457 ifa = NLMSG_DATA(m->hdr);
459 *ifindex = ifa->ifa_index;
464 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
465 uint16_t nlmsg_type, int index,
467 struct ifaddrmsg *ifa;
470 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
471 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
473 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
474 family == AF_INET || family == AF_INET6, -EINVAL);
475 assert_return(ret, -EINVAL);
477 r = message_new(rtnl, ret, nlmsg_type);
481 if (nlmsg_type == RTM_GETADDR)
482 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
484 ifa = NLMSG_DATA((*ret)->hdr);
486 ifa->ifa_index = index;
487 ifa->ifa_family = family;
488 if (family == AF_INET)
489 ifa->ifa_prefixlen = 32;
490 else if (family == AF_INET6)
491 ifa->ifa_prefixlen = 128;
496 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
497 int index, int family) {
500 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
504 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
509 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
511 assert_se(REFCNT_INC(m->n_ref) >= 2);
516 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
517 if (m && REFCNT_DEC(m->n_ref) <= 0) {
522 for (i = 0; i <= m->n_containers; i++)
523 free(m->rta_offset_tb[i]);
525 sd_rtnl_message_unref(m->next);
533 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
534 assert_return(m, -EINVAL);
535 assert_return(type, -EINVAL);
537 *type = m->hdr->nlmsg_type;
542 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
543 assert_return(m, -EINVAL);
545 return !m->hdr->nlmsg_pid;
548 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
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(ifindex, -EINVAL);
556 ifi = NLMSG_DATA(m->hdr);
558 *ifindex = ifi->ifi_index;
563 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
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(flags, -EINVAL);
571 ifi = NLMSG_DATA(m->hdr);
573 *flags = ifi->ifi_flags;
578 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
579 struct ifinfomsg *ifi;
581 assert_return(m, -EINVAL);
582 assert_return(m->hdr, -EINVAL);
583 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
584 assert_return(type, -EINVAL);
586 ifi = NLMSG_DATA(m->hdr);
588 *type = ifi->ifi_type;
593 /* If successful the updated message will be correctly aligned, if
594 unsuccessful the old message is untouched. */
595 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
597 size_t message_length, padding_length;
598 struct nlmsghdr *new_hdr;
607 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
608 assert(!data || data_length);
610 /* get offset of the new attribute */
611 offset = m->hdr->nlmsg_len;
613 /* get the size of the new rta attribute (with padding at the end) */
614 rta_length = RTA_LENGTH(data_length);
616 /* get the new message size (with padding at the end) */
617 message_length = offset + RTA_ALIGN(rta_length);
619 /* realloc to fit the new attribute */
620 new_hdr = realloc(m->hdr, message_length);
625 /* get pointer to the attribute we are about to add */
626 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
628 /* if we are inside containers, extend them */
629 for (i = 0; i < m->n_containers; i++)
630 GET_CONTAINER(m, i)->rta_len += message_length - offset;
632 /* fill in the attribute */
633 rta->rta_type = type;
634 rta->rta_len = rta_length;
636 /* we don't deal with the case where the user lies about the type
637 * and gives us too little data (so don't do that)
639 padding = mempcpy(RTA_DATA(rta), data, data_length);
641 /* if no data was passed, make sure we still initialize the padding
642 note that we can have data_length > 0 (used by some containers) */
643 padding = RTA_DATA(rta);
646 /* make sure also the padding at the end of the message is initialized */
647 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
648 memzero(padding, padding_length);
650 /* update message size */
651 m->hdr->nlmsg_len = message_length;
656 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
660 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
664 if (type->type != data_type)
670 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
674 assert_return(m, -EINVAL);
675 assert_return(!m->sealed, -EPERM);
676 assert_return(data, -EINVAL);
678 r = message_attribute_has_type(m, type, NLA_STRING);
685 length = strnlen(data, size);
689 length = strlen(data);
691 r = add_rtattr(m, type, data, length + 1);
698 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
701 assert_return(m, -EINVAL);
702 assert_return(!m->sealed, -EPERM);
704 r = message_attribute_has_type(m, type, NLA_U8);
708 r = add_rtattr(m, type, &data, sizeof(uint8_t));
716 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
719 assert_return(m, -EINVAL);
720 assert_return(!m->sealed, -EPERM);
722 r = message_attribute_has_type(m, type, NLA_U16);
726 r = add_rtattr(m, type, &data, sizeof(uint16_t));
733 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
736 assert_return(m, -EINVAL);
737 assert_return(!m->sealed, -EPERM);
739 r = message_attribute_has_type(m, type, NLA_U32);
743 r = add_rtattr(m, type, &data, sizeof(uint32_t));
750 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
753 assert_return(m, -EINVAL);
754 assert_return(!m->sealed, -EPERM);
755 assert_return(data, -EINVAL);
757 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
761 r = add_rtattr(m, type, data, sizeof(struct in_addr));
768 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
771 assert_return(m, -EINVAL);
772 assert_return(!m->sealed, -EPERM);
773 assert_return(data, -EINVAL);
775 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
779 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
786 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
789 assert_return(m, -EINVAL);
790 assert_return(!m->sealed, -EPERM);
791 assert_return(data, -EINVAL);
793 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
797 r = add_rtattr(m, type, data, ETH_ALEN);
804 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
807 assert_return(m, -EINVAL);
808 assert_return(!m->sealed, -EPERM);
809 assert_return(info, -EINVAL);
811 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
815 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
822 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
826 assert_return(m, -EINVAL);
827 assert_return(!m->sealed, -EPERM);
828 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
830 r = message_attribute_has_type(m, type, NLA_NESTED);
836 r = type_system_get_type_system(m->container_type_system[m->n_containers],
837 &m->container_type_system[m->n_containers + 1],
842 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
846 m->container_offsets[m->n_containers ++] = r;
851 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
852 const NLTypeSystemUnion *type_system_union;
855 assert_return(m, -EINVAL);
856 assert_return(!m->sealed, -EPERM);
858 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
862 r = type_system_union_get_type_system(type_system_union,
863 &m->container_type_system[m->n_containers + 1],
868 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
872 /* do we evere need non-null size */
873 r = add_rtattr(m, type, NULL, 0);
877 m->container_offsets[m->n_containers ++] = r;
883 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
884 assert_return(m, -EINVAL);
885 assert_return(!m->sealed, -EPERM);
886 assert_return(m->n_containers > 0, -EINVAL);
888 m->container_type_system[m->n_containers] = NULL;
894 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
897 assert_return(m, -EINVAL);
898 assert_return(m->sealed, -EPERM);
899 assert_return(data, -EINVAL);
900 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
901 assert(m->rta_offset_tb[m->n_containers]);
902 assert(type < m->rta_tb_size[m->n_containers]);
904 if(!m->rta_offset_tb[m->n_containers][type])
907 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
909 *data = RTA_DATA(rta);
911 return RTA_PAYLOAD(rta);
914 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
918 assert_return(m, -EINVAL);
920 r = message_attribute_has_type(m, type, NLA_STRING);
924 r = rtnl_message_read_internal(m, type, &attr_data);
927 else if (strnlen(attr_data, r) >= (size_t) r)
931 *data = (const char *) attr_data;
936 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
940 assert_return(m, -EINVAL);
942 r = message_attribute_has_type(m, type, NLA_U8);
946 r = rtnl_message_read_internal(m, type, &attr_data);
949 else if ((size_t) r < sizeof(uint8_t))
953 *data = *(uint8_t *) attr_data;
958 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
962 assert_return(m, -EINVAL);
964 r = message_attribute_has_type(m, type, NLA_U16);
968 r = rtnl_message_read_internal(m, type, &attr_data);
971 else if ((size_t) r < sizeof(uint16_t))
975 *data = *(uint16_t *) attr_data;
980 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
984 assert_return(m, -EINVAL);
986 r = message_attribute_has_type(m, type, NLA_U32);
990 r = rtnl_message_read_internal(m, type, &attr_data);
993 else if ((size_t)r < sizeof(uint32_t))
997 *data = *(uint32_t *) attr_data;
1002 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
1006 assert_return(m, -EINVAL);
1008 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
1012 r = rtnl_message_read_internal(m, type, &attr_data);
1015 else if ((size_t)r < sizeof(struct ether_addr))
1019 memcpy(data, attr_data, sizeof(struct ether_addr));
1024 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
1028 assert_return(m, -EINVAL);
1030 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
1034 r = rtnl_message_read_internal(m, type, &attr_data);
1037 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
1041 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
1046 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
1050 assert_return(m, -EINVAL);
1052 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1056 r = rtnl_message_read_internal(m, type, &attr_data);
1059 else if ((size_t)r < sizeof(struct in_addr))
1063 memcpy(data, attr_data, sizeof(struct in_addr));
1068 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
1072 assert_return(m, -EINVAL);
1074 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1078 r = rtnl_message_read_internal(m, type, &attr_data);
1081 else if ((size_t)r < sizeof(struct in6_addr))
1085 memcpy(data, attr_data, sizeof(struct in6_addr));
1090 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
1091 const NLType *nl_type;
1092 const NLTypeSystem *type_system;
1097 assert_return(m, -EINVAL);
1098 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1100 r = type_system_get_type(m->container_type_system[m->n_containers],
1106 if (nl_type->type == NLA_NESTED) {
1107 r = type_system_get_type_system(m->container_type_system[m->n_containers],
1112 } else if (nl_type->type == NLA_UNION) {
1113 const NLTypeSystemUnion *type_system_union;
1116 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1122 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1126 r = type_system_union_get_type_system(type_system_union,
1134 r = rtnl_message_read_internal(m, type, &container);
1142 r = rtnl_message_parse(m,
1143 &m->rta_offset_tb[m->n_containers],
1144 &m->rta_tb_size[m->n_containers],
1153 m->container_type_system[m->n_containers] = type_system;
1158 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1159 assert_return(m, -EINVAL);
1160 assert_return(m->sealed, -EINVAL);
1161 assert_return(m->n_containers > 0, -EINVAL);
1163 free(m->rta_offset_tb[m->n_containers]);
1164 m->rta_offset_tb[m->n_containers] = NULL;
1165 m->container_type_system[m->n_containers] = NULL;
1172 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1176 return m->hdr->nlmsg_seq;
1179 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1180 struct nlmsgerr *err;
1182 assert_return(m, -EINVAL);
1183 assert_return(m->hdr, -EINVAL);
1185 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1188 err = NLMSG_DATA(m->hdr);
1193 int rtnl_message_parse(sd_rtnl_message *m,
1194 size_t **rta_offset_tb,
1195 unsigned short *rta_tb_size,
1198 unsigned int rt_len) {
1199 unsigned short type;
1202 tb = new0(size_t, max + 1);
1206 *rta_tb_size = max + 1;
1208 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1209 type = RTA_TYPE(rta);
1211 /* if the kernel is newer than the headers we used
1212 when building, we ignore out-of-range attributes
1218 log_debug("rtnl: message parse - overwriting repeated attribute");
1220 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1223 *rta_offset_tb = tb;
1228 /* returns the number of bytes sent, or a negative error code */
1229 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1232 struct sockaddr_nl nl;
1234 .nl.nl_family = AF_NETLINK,
1242 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1243 0, &addr.sa, sizeof(addr));
1245 return (errno == EAGAIN) ? 0 : -errno;
1250 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1251 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1252 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1253 struct msghdr msg = {
1256 .msg_control = cred_buffer,
1257 .msg_controllen = sizeof(cred_buffer),
1259 struct cmsghdr *cmsg;
1267 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1270 if (errno == ENOBUFS)
1271 log_debug("rtnl: kernel receive buffer overrun");
1273 return (errno == EAGAIN) ? 0 : -errno;
1275 /* connection was closed by the kernel */
1278 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1279 if (cmsg->cmsg_level == SOL_SOCKET &&
1280 cmsg->cmsg_type == SCM_CREDENTIALS &&
1281 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1282 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1284 /* from the kernel */
1285 if (ucred->uid == 0 && ucred->pid == 0)
1287 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1288 cmsg->cmsg_type == NETLINK_PKTINFO &&
1289 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1290 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1292 /* multi-cast group */
1293 group = pktinfo->group;
1298 /* not from the kernel, ignore */
1307 /* On success, the number of bytes received is returned and *ret points to the received message
1308 * which has a valid header and the correct size.
1309 * If nothing useful was received 0 is returned.
1310 * On failure, a negative error code is returned.
1312 int socket_read_message(sd_rtnl *rtnl) {
1313 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1314 struct iovec iov = {};
1316 bool multi_part = false, done = false;
1317 struct nlmsghdr *new_msg;
1323 assert(rtnl->rbuffer);
1324 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1326 /* read nothing, just get the pending message size */
1327 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1333 /* make room for the pending message */
1334 if (!greedy_realloc((void **)&rtnl->rbuffer,
1335 &rtnl->rbuffer_allocated,
1336 len, sizeof(uint8_t)))
1339 iov.iov_base = rtnl->rbuffer;
1340 iov.iov_len = rtnl->rbuffer_allocated;
1342 /* read the pending message */
1343 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1349 if (len > rtnl->rbuffer_allocated)
1350 /* message did not fit in read buffer */
1353 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1356 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1357 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1358 rtnl->rbuffer->nlmsg_seq) {
1359 first = rtnl->rqueue_partial[i];
1365 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1366 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1367 const NLType *nl_type;
1369 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1370 /* not broadcast and not for us */
1373 if (new_msg->nlmsg_type == NLMSG_NOOP)
1374 /* silently drop noop messages */
1377 if (new_msg->nlmsg_type == NLMSG_DONE) {
1378 /* finished reading multi-part message */
1383 /* check that we support this message type */
1384 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1387 log_debug("sd-rtnl: ignored message with unknown type: %u",
1388 new_msg->nlmsg_type);
1393 /* check that the size matches the message type */
1394 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
1395 log_debug("sd-rtnl: message larger than expected, dropping");
1399 r = message_new_empty(rtnl, &m);
1403 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1407 /* seal and parse the top-level message */
1408 r = sd_rtnl_message_rewind(m);
1412 /* push the message onto the multi-part message stack */
1420 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1425 if (!multi_part || done) {
1426 /* we got a complete message, push it on the read queue */
1427 r = rtnl_rqueue_make_room(rtnl);
1431 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1434 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1435 /* remove the message form the partial read queue */
1436 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1437 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1438 rtnl->rqueue_partial_size --;
1443 /* we only got a partial multi-part message, push it on the
1444 partial read queue */
1445 if (i < rtnl->rqueue_partial_size) {
1446 rtnl->rqueue_partial[i] = first;
1448 r = rtnl_rqueue_partial_make_room(rtnl);
1452 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1460 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1465 assert_return(m, -EINVAL);
1467 /* don't allow appending to message once parsed */
1469 rtnl_message_seal(m);
1471 for (i = 1; i <= m->n_containers; i++) {
1472 free(m->rta_offset_tb[i]);
1473 m->rta_offset_tb[i] = NULL;
1474 m->rta_tb_size[i] = 0;
1475 m->container_type_system[i] = NULL;
1478 m->n_containers = 0;
1480 if (m->rta_offset_tb[0]) {
1481 /* top-level attributes have already been parsed */
1487 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1491 if (type->type == NLA_NESTED) {
1492 const NLTypeSystem *type_system = type->type_system;
1494 assert(type_system);
1496 m->container_type_system[0] = type_system;
1498 r = rtnl_message_parse(m,
1499 &m->rta_offset_tb[m->n_containers],
1500 &m->rta_tb_size[m->n_containers],
1502 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1503 NLMSG_ALIGN(type->size)),
1504 NLMSG_PAYLOAD(m->hdr, type->size));
1512 void rtnl_message_seal(sd_rtnl_message *m) {
1519 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1520 assert_return(m, NULL);