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_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
147 uint16_t nlmsg_type, int rtm_family,
148 unsigned char rtm_protocol) {
152 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
153 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
154 assert_return(ret, -EINVAL);
156 r = message_new(rtnl, ret, nlmsg_type);
160 if (nlmsg_type == RTM_NEWROUTE)
161 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
163 rtm = NLMSG_DATA((*ret)->hdr);
165 rtm->rtm_family = rtm_family;
166 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
167 rtm->rtm_type = RTN_UNICAST;
168 rtm->rtm_table = RT_TABLE_MAIN;
169 rtm->rtm_protocol = rtm_protocol;
174 int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
177 assert_return(m, -EINVAL);
178 assert_return(m->hdr, -EINVAL);
179 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
180 assert_return(family, -EINVAL);
182 ndm = NLMSG_DATA(m->hdr);
184 *family = ndm->ndm_family;
189 int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
192 assert_return(m, -EINVAL);
193 assert_return(m->hdr, -EINVAL);
194 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
195 assert_return(index, -EINVAL);
197 ndm = NLMSG_DATA(m->hdr);
199 *index = ndm->ndm_ifindex;
204 int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
208 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
209 assert_return(ndm_family == AF_INET || ndm_family == AF_INET6, -EINVAL);
210 assert_return(ret, -EINVAL);
212 r = message_new(rtnl, ret, nlmsg_type);
216 if (nlmsg_type == RTM_NEWNEIGH)
217 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
219 ndm = NLMSG_DATA((*ret)->hdr);
221 ndm->ndm_family = ndm_family;
222 ndm->ndm_ifindex = index;
227 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
228 struct ifinfomsg *ifi;
230 assert_return(m, -EINVAL);
231 assert_return(m->hdr, -EINVAL);
232 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
233 assert_return(change, -EINVAL);
235 ifi = NLMSG_DATA(m->hdr);
237 ifi->ifi_flags = flags;
238 ifi->ifi_change = change;
243 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
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);
250 ifi = NLMSG_DATA(m->hdr);
252 ifi->ifi_type = type;
257 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
258 struct ifinfomsg *ifi;
260 assert_return(m, -EINVAL);
261 assert_return(m->hdr, -EINVAL);
262 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
264 ifi = NLMSG_DATA(m->hdr);
266 ifi->ifi_family = family;
271 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
272 uint16_t nlmsg_type, int index) {
273 struct ifinfomsg *ifi;
276 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
277 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
278 assert_return(ret, -EINVAL);
280 r = message_new(rtnl, ret, nlmsg_type);
284 if (nlmsg_type == RTM_NEWLINK)
285 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
287 ifi = NLMSG_DATA((*ret)->hdr);
289 ifi->ifi_family = AF_UNSPEC;
290 ifi->ifi_index = index;
295 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
296 assert_return(m, -EINVAL);
297 assert_return(m->hdr, -EINVAL);
298 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
299 m->hdr->nlmsg_type == RTM_GETADDR ||
300 m->hdr->nlmsg_type == RTM_GETROUTE ||
301 m->hdr->nlmsg_type == RTM_GETNEIGH,
305 m->hdr->nlmsg_flags |= NLM_F_DUMP;
307 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
312 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
313 struct ifaddrmsg *ifa;
315 assert_return(m, -EINVAL);
316 assert_return(m->hdr, -EINVAL);
317 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
319 ifa = NLMSG_DATA(m->hdr);
321 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
322 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
325 ifa->ifa_prefixlen = prefixlen;
330 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
331 struct ifaddrmsg *ifa;
333 assert_return(m, -EINVAL);
334 assert_return(m->hdr, -EINVAL);
335 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
337 ifa = NLMSG_DATA(m->hdr);
339 ifa->ifa_flags = flags;
344 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
345 struct ifaddrmsg *ifa;
347 assert_return(m, -EINVAL);
348 assert_return(m->hdr, -EINVAL);
349 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
351 ifa = NLMSG_DATA(m->hdr);
353 ifa->ifa_scope = scope;
358 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
359 struct ifaddrmsg *ifa;
361 assert_return(m, -EINVAL);
362 assert_return(m->hdr, -EINVAL);
363 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
364 assert_return(family, -EINVAL);
366 ifa = NLMSG_DATA(m->hdr);
368 *family = ifa->ifa_family;
373 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
374 struct ifaddrmsg *ifa;
376 assert_return(m, -EINVAL);
377 assert_return(m->hdr, -EINVAL);
378 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
379 assert_return(prefixlen, -EINVAL);
381 ifa = NLMSG_DATA(m->hdr);
383 *prefixlen = ifa->ifa_prefixlen;
388 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
389 struct ifaddrmsg *ifa;
391 assert_return(m, -EINVAL);
392 assert_return(m->hdr, -EINVAL);
393 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
394 assert_return(scope, -EINVAL);
396 ifa = NLMSG_DATA(m->hdr);
398 *scope = ifa->ifa_scope;
403 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
404 struct ifaddrmsg *ifa;
406 assert_return(m, -EINVAL);
407 assert_return(m->hdr, -EINVAL);
408 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
409 assert_return(flags, -EINVAL);
411 ifa = NLMSG_DATA(m->hdr);
413 *flags = ifa->ifa_flags;
418 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
419 struct ifaddrmsg *ifa;
421 assert_return(m, -EINVAL);
422 assert_return(m->hdr, -EINVAL);
423 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
424 assert_return(ifindex, -EINVAL);
426 ifa = NLMSG_DATA(m->hdr);
428 *ifindex = ifa->ifa_index;
433 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
434 uint16_t nlmsg_type, int index,
436 struct ifaddrmsg *ifa;
439 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
440 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
442 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
443 family == AF_INET || family == AF_INET6, -EINVAL);
444 assert_return(ret, -EINVAL);
446 r = message_new(rtnl, ret, nlmsg_type);
450 if (nlmsg_type == RTM_GETADDR)
451 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
453 ifa = NLMSG_DATA((*ret)->hdr);
455 ifa->ifa_index = index;
456 ifa->ifa_family = family;
457 if (family == AF_INET)
458 ifa->ifa_prefixlen = 32;
459 else if (family == AF_INET6)
460 ifa->ifa_prefixlen = 128;
465 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
466 int index, int family) {
469 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
473 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
478 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
480 assert_se(REFCNT_INC(m->n_ref) >= 2);
485 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
486 if (m && REFCNT_DEC(m->n_ref) <= 0) {
491 for (i = 0; i <= m->n_containers; i++)
492 free(m->rta_offset_tb[i]);
494 sd_rtnl_message_unref(m->next);
502 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
503 assert_return(m, -EINVAL);
504 assert_return(type, -EINVAL);
506 *type = m->hdr->nlmsg_type;
511 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
512 assert_return(m, -EINVAL);
514 return !m->hdr->nlmsg_pid;
517 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
518 struct ifinfomsg *ifi;
520 assert_return(m, -EINVAL);
521 assert_return(m->hdr, -EINVAL);
522 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
523 assert_return(ifindex, -EINVAL);
525 ifi = NLMSG_DATA(m->hdr);
527 *ifindex = ifi->ifi_index;
532 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
533 struct ifinfomsg *ifi;
535 assert_return(m, -EINVAL);
536 assert_return(m->hdr, -EINVAL);
537 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
538 assert_return(flags, -EINVAL);
540 ifi = NLMSG_DATA(m->hdr);
542 *flags = ifi->ifi_flags;
547 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
548 struct ifinfomsg *ifi;
550 assert_return(m, -EINVAL);
551 assert_return(m->hdr, -EINVAL);
552 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
553 assert_return(type, -EINVAL);
555 ifi = NLMSG_DATA(m->hdr);
557 *type = ifi->ifi_type;
562 /* If successful the updated message will be correctly aligned, if
563 unsuccessful the old message is untouched. */
564 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
566 size_t message_length, padding_length;
567 struct nlmsghdr *new_hdr;
576 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
577 assert(!data || data_length);
579 /* get offset of the new attribute */
580 offset = m->hdr->nlmsg_len;
582 /* get the size of the new rta attribute (with padding at the end) */
583 rta_length = RTA_LENGTH(data_length);
585 /* get the new message size (with padding at the end) */
586 message_length = offset + RTA_ALIGN(rta_length);
588 /* realloc to fit the new attribute */
589 new_hdr = realloc(m->hdr, message_length);
594 /* get pointer to the attribute we are about to add */
595 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
597 /* if we are inside containers, extend them */
598 for (i = 0; i < m->n_containers; i++)
599 GET_CONTAINER(m, i)->rta_len += message_length - offset;
601 /* fill in the attribute */
602 rta->rta_type = type;
603 rta->rta_len = rta_length;
605 /* we don't deal with the case where the user lies about the type
606 * and gives us too little data (so don't do that)
608 padding = mempcpy(RTA_DATA(rta), data, data_length);
610 /* if no data was passed, make sure we still initialize the padding
611 note that we can have data_length > 0 (used by some containers) */
612 padding = RTA_DATA(rta);
615 /* make sure also the padding at the end of the message is initialized */
616 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
617 memzero(padding, padding_length);
619 /* update message size */
620 m->hdr->nlmsg_len = message_length;
625 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
629 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
633 if (type->type != data_type)
639 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
643 assert_return(m, -EINVAL);
644 assert_return(!m->sealed, -EPERM);
645 assert_return(data, -EINVAL);
647 r = message_attribute_has_type(m, type, NLA_STRING);
654 length = strnlen(data, size);
658 length = strlen(data);
660 r = add_rtattr(m, type, data, length + 1);
667 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
670 assert_return(m, -EINVAL);
671 assert_return(!m->sealed, -EPERM);
673 r = message_attribute_has_type(m, type, NLA_U8);
677 r = add_rtattr(m, type, &data, sizeof(uint8_t));
685 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
688 assert_return(m, -EINVAL);
689 assert_return(!m->sealed, -EPERM);
691 r = message_attribute_has_type(m, type, NLA_U16);
695 r = add_rtattr(m, type, &data, sizeof(uint16_t));
702 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
705 assert_return(m, -EINVAL);
706 assert_return(!m->sealed, -EPERM);
708 r = message_attribute_has_type(m, type, NLA_U32);
712 r = add_rtattr(m, type, &data, sizeof(uint32_t));
719 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
722 assert_return(m, -EINVAL);
723 assert_return(!m->sealed, -EPERM);
724 assert_return(data, -EINVAL);
726 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
730 r = add_rtattr(m, type, data, sizeof(struct in_addr));
737 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
740 assert_return(m, -EINVAL);
741 assert_return(!m->sealed, -EPERM);
742 assert_return(data, -EINVAL);
744 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
748 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
755 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
758 assert_return(m, -EINVAL);
759 assert_return(!m->sealed, -EPERM);
760 assert_return(data, -EINVAL);
762 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
766 r = add_rtattr(m, type, data, ETH_ALEN);
773 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
776 assert_return(m, -EINVAL);
777 assert_return(!m->sealed, -EPERM);
778 assert_return(info, -EINVAL);
780 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
784 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
791 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
795 assert_return(m, -EINVAL);
796 assert_return(!m->sealed, -EPERM);
797 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
799 r = message_attribute_has_type(m, type, NLA_NESTED);
805 r = type_system_get_type_system(m->container_type_system[m->n_containers],
806 &m->container_type_system[m->n_containers + 1],
811 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
815 m->container_offsets[m->n_containers ++] = r;
820 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
821 const NLTypeSystemUnion *type_system_union;
824 assert_return(m, -EINVAL);
825 assert_return(!m->sealed, -EPERM);
827 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
831 r = type_system_union_get_type_system(type_system_union,
832 &m->container_type_system[m->n_containers + 1],
837 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
841 /* do we evere need non-null size */
842 r = add_rtattr(m, type, NULL, 0);
846 m->container_offsets[m->n_containers ++] = r;
852 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
853 assert_return(m, -EINVAL);
854 assert_return(!m->sealed, -EPERM);
855 assert_return(m->n_containers > 0, -EINVAL);
857 m->container_type_system[m->n_containers] = NULL;
863 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
866 assert_return(m, -EINVAL);
867 assert_return(m->sealed, -EPERM);
868 assert_return(data, -EINVAL);
869 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
870 assert(m->rta_offset_tb[m->n_containers]);
871 assert(type < m->rta_tb_size[m->n_containers]);
873 if(!m->rta_offset_tb[m->n_containers][type])
876 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
878 *data = RTA_DATA(rta);
880 return RTA_PAYLOAD(rta);
883 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
887 assert_return(m, -EINVAL);
889 r = message_attribute_has_type(m, type, NLA_STRING);
893 r = rtnl_message_read_internal(m, type, &attr_data);
896 else if (strnlen(attr_data, r) >= (size_t) r)
900 *data = (const char *) attr_data;
905 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
909 assert_return(m, -EINVAL);
911 r = message_attribute_has_type(m, type, NLA_U8);
915 r = rtnl_message_read_internal(m, type, &attr_data);
918 else if ((size_t) r < sizeof(uint8_t))
922 *data = *(uint8_t *) attr_data;
927 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
931 assert_return(m, -EINVAL);
933 r = message_attribute_has_type(m, type, NLA_U16);
937 r = rtnl_message_read_internal(m, type, &attr_data);
940 else if ((size_t) r < sizeof(uint16_t))
944 *data = *(uint16_t *) attr_data;
949 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
953 assert_return(m, -EINVAL);
955 r = message_attribute_has_type(m, type, NLA_U32);
959 r = rtnl_message_read_internal(m, type, &attr_data);
962 else if ((size_t)r < sizeof(uint32_t))
966 *data = *(uint32_t *) attr_data;
971 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
975 assert_return(m, -EINVAL);
977 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
981 r = rtnl_message_read_internal(m, type, &attr_data);
984 else if ((size_t)r < sizeof(struct ether_addr))
988 memcpy(data, attr_data, sizeof(struct ether_addr));
993 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
997 assert_return(m, -EINVAL);
999 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
1003 r = rtnl_message_read_internal(m, type, &attr_data);
1006 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
1010 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
1015 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
1019 assert_return(m, -EINVAL);
1021 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1025 r = rtnl_message_read_internal(m, type, &attr_data);
1028 else if ((size_t)r < sizeof(struct in_addr))
1032 memcpy(data, attr_data, sizeof(struct in_addr));
1037 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
1041 assert_return(m, -EINVAL);
1043 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1047 r = rtnl_message_read_internal(m, type, &attr_data);
1050 else if ((size_t)r < sizeof(struct in6_addr))
1054 memcpy(data, attr_data, sizeof(struct in6_addr));
1059 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
1060 const NLType *nl_type;
1061 const NLTypeSystem *type_system;
1066 assert_return(m, -EINVAL);
1067 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1069 r = type_system_get_type(m->container_type_system[m->n_containers],
1075 if (nl_type->type == NLA_NESTED) {
1076 r = type_system_get_type_system(m->container_type_system[m->n_containers],
1081 } else if (nl_type->type == NLA_UNION) {
1082 const NLTypeSystemUnion *type_system_union;
1085 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1091 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1095 r = type_system_union_get_type_system(type_system_union,
1103 r = rtnl_message_read_internal(m, type, &container);
1111 r = rtnl_message_parse(m,
1112 &m->rta_offset_tb[m->n_containers],
1113 &m->rta_tb_size[m->n_containers],
1122 m->container_type_system[m->n_containers] = type_system;
1127 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1128 assert_return(m, -EINVAL);
1129 assert_return(m->sealed, -EINVAL);
1130 assert_return(m->n_containers > 0, -EINVAL);
1132 free(m->rta_offset_tb[m->n_containers]);
1133 m->rta_offset_tb[m->n_containers] = NULL;
1134 m->container_type_system[m->n_containers] = NULL;
1141 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1145 return m->hdr->nlmsg_seq;
1148 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1149 struct nlmsgerr *err;
1151 assert_return(m, -EINVAL);
1152 assert_return(m->hdr, -EINVAL);
1154 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1157 err = NLMSG_DATA(m->hdr);
1162 int rtnl_message_parse(sd_rtnl_message *m,
1163 size_t **rta_offset_tb,
1164 unsigned short *rta_tb_size,
1167 unsigned int rt_len) {
1168 unsigned short type;
1171 tb = new0(size_t, max + 1);
1175 *rta_tb_size = max + 1;
1177 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1178 type = RTA_TYPE(rta);
1180 /* if the kernel is newer than the headers we used
1181 when building, we ignore out-of-range attributes
1187 log_debug("rtnl: message parse - overwriting repeated attribute");
1189 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1192 *rta_offset_tb = tb;
1197 /* returns the number of bytes sent, or a negative error code */
1198 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1201 struct sockaddr_nl nl;
1203 .nl.nl_family = AF_NETLINK,
1211 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1212 0, &addr.sa, sizeof(addr));
1214 return (errno == EAGAIN) ? 0 : -errno;
1219 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1220 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1221 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1222 struct msghdr msg = {
1225 .msg_control = cred_buffer,
1226 .msg_controllen = sizeof(cred_buffer),
1228 struct cmsghdr *cmsg;
1236 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1239 if (errno == ENOBUFS)
1240 log_debug("rtnl: kernel receive buffer overrun");
1242 return (errno == EAGAIN) ? 0 : -errno;
1244 /* connection was closed by the kernel */
1247 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1248 if (cmsg->cmsg_level == SOL_SOCKET &&
1249 cmsg->cmsg_type == SCM_CREDENTIALS &&
1250 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1251 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1253 /* from the kernel */
1254 if (ucred->uid == 0 && ucred->pid == 0)
1256 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1257 cmsg->cmsg_type == NETLINK_PKTINFO &&
1258 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1259 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1261 /* multi-cast group */
1262 group = pktinfo->group;
1267 /* not from the kernel, ignore */
1276 /* On success, the number of bytes received is returned and *ret points to the received message
1277 * which has a valid header and the correct size.
1278 * If nothing useful was received 0 is returned.
1279 * On failure, a negative error code is returned.
1281 int socket_read_message(sd_rtnl *rtnl) {
1282 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1283 struct iovec iov = {};
1285 bool multi_part = false, done = false;
1286 struct nlmsghdr *new_msg;
1292 assert(rtnl->rbuffer);
1293 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1295 /* read nothing, just get the pending message size */
1296 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1302 /* make room for the pending message */
1303 if (!greedy_realloc((void **)&rtnl->rbuffer,
1304 &rtnl->rbuffer_allocated,
1305 len, sizeof(uint8_t)))
1308 iov.iov_base = rtnl->rbuffer;
1309 iov.iov_len = rtnl->rbuffer_allocated;
1311 /* read the pending message */
1312 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1318 if (len > rtnl->rbuffer_allocated)
1319 /* message did not fit in read buffer */
1322 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1325 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1326 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1327 rtnl->rbuffer->nlmsg_seq) {
1328 first = rtnl->rqueue_partial[i];
1334 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1335 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1336 const NLType *nl_type;
1338 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1339 /* not broadcast and not for us */
1342 if (new_msg->nlmsg_type == NLMSG_NOOP)
1343 /* silently drop noop messages */
1346 if (new_msg->nlmsg_type == NLMSG_DONE) {
1347 /* finished reading multi-part message */
1352 /* check that we support this message type */
1353 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1356 log_debug("sd-rtnl: ignored message with unknown type: %u",
1357 new_msg->nlmsg_type);
1362 /* check that the size matches the message type */
1363 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
1364 log_debug("sd-rtnl: message larger than expected, dropping");
1368 r = message_new_empty(rtnl, &m);
1372 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1376 /* seal and parse the top-level message */
1377 r = sd_rtnl_message_rewind(m);
1381 /* push the message onto the multi-part message stack */
1389 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1394 if (!multi_part || done) {
1395 /* we got a complete message, push it on the read queue */
1396 r = rtnl_rqueue_make_room(rtnl);
1400 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1403 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1404 /* remove the message form the partial read queue */
1405 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1406 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1407 rtnl->rqueue_partial_size --;
1412 /* we only got a partial multi-part message, push it on the
1413 partial read queue */
1414 if (i < rtnl->rqueue_partial_size) {
1415 rtnl->rqueue_partial[i] = first;
1417 r = rtnl_rqueue_partial_make_room(rtnl);
1421 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1429 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1434 assert_return(m, -EINVAL);
1436 /* don't allow appending to message once parsed */
1438 rtnl_message_seal(m);
1440 for (i = 1; i <= m->n_containers; i++) {
1441 free(m->rta_offset_tb[i]);
1442 m->rta_offset_tb[i] = NULL;
1443 m->rta_tb_size[i] = 0;
1444 m->container_type_system[i] = NULL;
1447 m->n_containers = 0;
1449 if (m->rta_offset_tb[0]) {
1450 /* top-level attributes have already been parsed */
1456 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1460 if (type->type == NLA_NESTED) {
1461 const NLTypeSystem *type_system = type->type_system;
1463 assert(type_system);
1465 m->container_type_system[0] = type_system;
1467 r = rtnl_message_parse(m,
1468 &m->rta_offset_tb[m->n_containers],
1469 &m->rta_tb_size[m->n_containers],
1471 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1472 NLMSG_ALIGN(type->size)),
1473 NLMSG_PAYLOAD(m->hdr, type->size));
1481 void rtnl_message_seal(sd_rtnl_message *m) {
1488 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1489 assert_return(m, NULL);