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>
31 #include "rtnl-util.h"
32 #include "rtnl-internal.h"
33 #include "rtnl-types.h"
35 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
36 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
38 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
40 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
43 assert_return(ret, -EINVAL);
45 /* Note that 'rtnl' is currently unused, if we start using it internally
46 we must take care to avoid problems due to mutual references between
47 busses and their queued messages. See sd-bus.
50 m = new0(sd_rtnl_message, 1);
54 m->n_ref = REFCNT_INIT;
63 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
64 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
65 const NLType *nl_type;
69 r = type_system_get_type(NULL, &nl_type, type);
73 r = message_new_empty(rtnl, &m);
77 size = NLMSG_SPACE(nl_type->size);
79 assert(size >= sizeof(struct nlmsghdr));
80 m->hdr = malloc0(size);
84 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
86 m->container_type_system[0] = nl_type->type_system;
87 m->hdr->nlmsg_len = size;
88 m->hdr->nlmsg_type = type;
96 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
99 assert_return(m, -EINVAL);
100 assert_return(m->hdr, -EINVAL);
101 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
103 rtm = NLMSG_DATA(m->hdr);
105 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
106 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
109 rtm->rtm_dst_len = prefixlen;
114 int sd_rtnl_message_route_set_src_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
117 assert_return(m, -EINVAL);
118 assert_return(m->hdr, -EINVAL);
119 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
121 rtm = NLMSG_DATA(m->hdr);
123 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
124 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
127 rtm->rtm_src_len = prefixlen;
132 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
135 assert_return(m, -EINVAL);
136 assert_return(m->hdr, -EINVAL);
137 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
139 rtm = NLMSG_DATA(m->hdr);
141 rtm->rtm_scope = scope;
146 int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) {
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(family, -EINVAL);
154 rtm = NLMSG_DATA(m->hdr);
156 *family = rtm->rtm_family;
161 int sd_rtnl_message_route_get_dst_prefixlen(sd_rtnl_message *m, unsigned char *dst_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(dst_len, -EINVAL);
169 rtm = NLMSG_DATA(m->hdr);
171 *dst_len = rtm->rtm_dst_len;
176 int sd_rtnl_message_route_get_src_prefixlen(sd_rtnl_message *m, unsigned char *src_len) {
179 assert_return(m, -EINVAL);
180 assert_return(m->hdr, -EINVAL);
181 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
182 assert_return(src_len, -EINVAL);
184 rtm = NLMSG_DATA(m->hdr);
186 *src_len = rtm->rtm_src_len;
191 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
192 uint16_t nlmsg_type, int rtm_family,
193 unsigned char rtm_protocol) {
197 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
198 assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
199 rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
200 assert_return(ret, -EINVAL);
202 r = message_new(rtnl, ret, nlmsg_type);
206 if (nlmsg_type == RTM_NEWROUTE)
207 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
209 rtm = NLMSG_DATA((*ret)->hdr);
211 rtm->rtm_family = rtm_family;
212 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
213 rtm->rtm_type = RTN_UNICAST;
214 rtm->rtm_table = RT_TABLE_MAIN;
215 rtm->rtm_protocol = rtm_protocol;
220 int sd_rtnl_message_neigh_set_flags(sd_rtnl_message *m, uint8_t flags) {
223 assert_return(m, -EINVAL);
224 assert_return(m->hdr, -EINVAL);
225 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
227 ndm = NLMSG_DATA(m->hdr);
228 ndm->ndm_flags |= flags;
233 int sd_rtnl_message_neigh_set_state(sd_rtnl_message *m, uint16_t state) {
236 assert_return(m, -EINVAL);
237 assert_return(m->hdr, -EINVAL);
238 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
240 ndm = NLMSG_DATA(m->hdr);
241 ndm->ndm_state |= state;
246 int sd_rtnl_message_neigh_get_flags(sd_rtnl_message *m, uint8_t *flags) {
249 assert_return(m, -EINVAL);
250 assert_return(m->hdr, -EINVAL);
251 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
253 ndm = NLMSG_DATA(m->hdr);
254 *flags = ndm->ndm_flags;
259 int sd_rtnl_message_neigh_get_state(sd_rtnl_message *m, uint16_t *state) {
262 assert_return(m, -EINVAL);
263 assert_return(m->hdr, -EINVAL);
264 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
266 ndm = NLMSG_DATA(m->hdr);
267 *state = ndm->ndm_state;
272 int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
275 assert_return(m, -EINVAL);
276 assert_return(m->hdr, -EINVAL);
277 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
278 assert_return(family, -EINVAL);
280 ndm = NLMSG_DATA(m->hdr);
282 *family = ndm->ndm_family;
287 int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
290 assert_return(m, -EINVAL);
291 assert_return(m->hdr, -EINVAL);
292 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
293 assert_return(index, -EINVAL);
295 ndm = NLMSG_DATA(m->hdr);
297 *index = ndm->ndm_ifindex;
302 int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
306 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
307 assert_return(ndm_family == AF_INET ||
308 ndm_family == AF_INET6 ||
309 ndm_family == PF_BRIDGE, -EINVAL);
310 assert_return(ret, -EINVAL);
312 r = message_new(rtnl, ret, nlmsg_type);
316 if (nlmsg_type == RTM_NEWNEIGH)
317 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
319 ndm = NLMSG_DATA((*ret)->hdr);
321 ndm->ndm_family = ndm_family;
322 ndm->ndm_ifindex = index;
327 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
328 struct ifinfomsg *ifi;
330 assert_return(m, -EINVAL);
331 assert_return(m->hdr, -EINVAL);
332 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
333 assert_return(change, -EINVAL);
335 ifi = NLMSG_DATA(m->hdr);
337 ifi->ifi_flags = flags;
338 ifi->ifi_change = change;
343 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
344 struct ifinfomsg *ifi;
346 assert_return(m, -EINVAL);
347 assert_return(m->hdr, -EINVAL);
348 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
350 ifi = NLMSG_DATA(m->hdr);
352 ifi->ifi_type = type;
357 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
358 struct ifinfomsg *ifi;
360 assert_return(m, -EINVAL);
361 assert_return(m->hdr, -EINVAL);
362 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
364 ifi = NLMSG_DATA(m->hdr);
366 ifi->ifi_family = family;
371 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
372 uint16_t nlmsg_type, int index) {
373 struct ifinfomsg *ifi;
376 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
377 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
378 assert_return(ret, -EINVAL);
380 r = message_new(rtnl, ret, nlmsg_type);
384 if (nlmsg_type == RTM_NEWLINK)
385 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
387 ifi = NLMSG_DATA((*ret)->hdr);
389 ifi->ifi_family = AF_UNSPEC;
390 ifi->ifi_index = index;
395 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
396 assert_return(m, -EINVAL);
397 assert_return(m->hdr, -EINVAL);
398 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
399 m->hdr->nlmsg_type == RTM_GETADDR ||
400 m->hdr->nlmsg_type == RTM_GETROUTE ||
401 m->hdr->nlmsg_type == RTM_GETNEIGH,
405 m->hdr->nlmsg_flags |= NLM_F_DUMP;
407 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
412 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
413 struct ifaddrmsg *ifa;
415 assert_return(m, -EINVAL);
416 assert_return(m->hdr, -EINVAL);
417 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
419 ifa = NLMSG_DATA(m->hdr);
421 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
422 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
425 ifa->ifa_prefixlen = prefixlen;
430 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
431 struct ifaddrmsg *ifa;
433 assert_return(m, -EINVAL);
434 assert_return(m->hdr, -EINVAL);
435 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
437 ifa = NLMSG_DATA(m->hdr);
439 ifa->ifa_flags = flags;
444 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
445 struct ifaddrmsg *ifa;
447 assert_return(m, -EINVAL);
448 assert_return(m->hdr, -EINVAL);
449 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
451 ifa = NLMSG_DATA(m->hdr);
453 ifa->ifa_scope = scope;
458 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
459 struct ifaddrmsg *ifa;
461 assert_return(m, -EINVAL);
462 assert_return(m->hdr, -EINVAL);
463 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
464 assert_return(family, -EINVAL);
466 ifa = NLMSG_DATA(m->hdr);
468 *family = ifa->ifa_family;
473 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
474 struct ifaddrmsg *ifa;
476 assert_return(m, -EINVAL);
477 assert_return(m->hdr, -EINVAL);
478 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
479 assert_return(prefixlen, -EINVAL);
481 ifa = NLMSG_DATA(m->hdr);
483 *prefixlen = ifa->ifa_prefixlen;
488 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
489 struct ifaddrmsg *ifa;
491 assert_return(m, -EINVAL);
492 assert_return(m->hdr, -EINVAL);
493 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
494 assert_return(scope, -EINVAL);
496 ifa = NLMSG_DATA(m->hdr);
498 *scope = ifa->ifa_scope;
503 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
504 struct ifaddrmsg *ifa;
506 assert_return(m, -EINVAL);
507 assert_return(m->hdr, -EINVAL);
508 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
509 assert_return(flags, -EINVAL);
511 ifa = NLMSG_DATA(m->hdr);
513 *flags = ifa->ifa_flags;
518 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
519 struct ifaddrmsg *ifa;
521 assert_return(m, -EINVAL);
522 assert_return(m->hdr, -EINVAL);
523 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
524 assert_return(ifindex, -EINVAL);
526 ifa = NLMSG_DATA(m->hdr);
528 *ifindex = ifa->ifa_index;
533 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
534 uint16_t nlmsg_type, int index,
536 struct ifaddrmsg *ifa;
539 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
540 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
542 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
543 family == AF_INET || family == AF_INET6, -EINVAL);
544 assert_return(ret, -EINVAL);
546 r = message_new(rtnl, ret, nlmsg_type);
550 if (nlmsg_type == RTM_GETADDR)
551 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
553 ifa = NLMSG_DATA((*ret)->hdr);
555 ifa->ifa_index = index;
556 ifa->ifa_family = family;
557 if (family == AF_INET)
558 ifa->ifa_prefixlen = 32;
559 else if (family == AF_INET6)
560 ifa->ifa_prefixlen = 128;
565 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
566 int index, int family) {
569 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
573 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
578 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
580 assert_se(REFCNT_INC(m->n_ref) >= 2);
585 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
586 if (m && REFCNT_DEC(m->n_ref) == 0) {
591 for (i = 0; i <= m->n_containers; i++)
592 free(m->rta_offset_tb[i]);
594 sd_rtnl_message_unref(m->next);
602 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
603 assert_return(m, -EINVAL);
604 assert_return(type, -EINVAL);
606 *type = m->hdr->nlmsg_type;
611 int sd_rtnl_message_get_family(sd_rtnl_message *m, int *family) {
612 assert_return(m, -EINVAL);
613 assert_return(family, -EINVAL);
617 if (rtnl_message_type_is_link(m->hdr->nlmsg_type)) {
618 struct ifinfomsg *ifi;
620 ifi = NLMSG_DATA(m->hdr);
622 *family = ifi->ifi_family;
625 } else if (rtnl_message_type_is_route(m->hdr->nlmsg_type)) {
628 rtm = NLMSG_DATA(m->hdr);
630 *family = rtm->rtm_family;
633 } else if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type)) {
636 ndm = NLMSG_DATA(m->hdr);
638 *family = ndm->ndm_family;
641 } else if (rtnl_message_type_is_addr(m->hdr->nlmsg_type)) {
642 struct ifaddrmsg *ifa;
644 ifa = NLMSG_DATA(m->hdr);
646 *family = ifa->ifa_family;
654 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
655 assert_return(m, -EINVAL);
660 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
661 struct ifinfomsg *ifi;
663 assert_return(m, -EINVAL);
664 assert_return(m->hdr, -EINVAL);
665 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
666 assert_return(ifindex, -EINVAL);
668 ifi = NLMSG_DATA(m->hdr);
670 *ifindex = ifi->ifi_index;
675 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
676 struct ifinfomsg *ifi;
678 assert_return(m, -EINVAL);
679 assert_return(m->hdr, -EINVAL);
680 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
681 assert_return(flags, -EINVAL);
683 ifi = NLMSG_DATA(m->hdr);
685 *flags = ifi->ifi_flags;
690 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
691 struct ifinfomsg *ifi;
693 assert_return(m, -EINVAL);
694 assert_return(m->hdr, -EINVAL);
695 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
696 assert_return(type, -EINVAL);
698 ifi = NLMSG_DATA(m->hdr);
700 *type = ifi->ifi_type;
705 /* If successful the updated message will be correctly aligned, if
706 unsuccessful the old message is untouched. */
707 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
709 size_t message_length, padding_length;
710 struct nlmsghdr *new_hdr;
719 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
720 assert(!data || data_length);
722 /* get offset of the new attribute */
723 offset = m->hdr->nlmsg_len;
725 /* get the size of the new rta attribute (with padding at the end) */
726 rta_length = RTA_LENGTH(data_length);
728 /* get the new message size (with padding at the end) */
729 message_length = offset + RTA_ALIGN(rta_length);
731 /* realloc to fit the new attribute */
732 new_hdr = realloc(m->hdr, message_length);
737 /* get pointer to the attribute we are about to add */
738 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
740 /* if we are inside containers, extend them */
741 for (i = 0; i < m->n_containers; i++)
742 GET_CONTAINER(m, i)->rta_len += message_length - offset;
744 /* fill in the attribute */
745 rta->rta_type = type;
746 rta->rta_len = rta_length;
748 /* we don't deal with the case where the user lies about the type
749 * and gives us too little data (so don't do that)
751 padding = mempcpy(RTA_DATA(rta), data, data_length);
753 /* if no data was passed, make sure we still initialize the padding
754 note that we can have data_length > 0 (used by some containers) */
755 padding = RTA_DATA(rta);
758 /* make sure also the padding at the end of the message is initialized */
759 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
760 memzero(padding, padding_length);
762 /* update message size */
763 m->hdr->nlmsg_len = message_length;
768 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
772 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
776 if (type->type != data_type)
782 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
786 assert_return(m, -EINVAL);
787 assert_return(!m->sealed, -EPERM);
788 assert_return(data, -EINVAL);
790 r = message_attribute_has_type(m, type, NLA_STRING);
797 length = strnlen(data, size+1);
801 length = strlen(data);
803 r = add_rtattr(m, type, data, length + 1);
810 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
813 assert_return(m, -EINVAL);
814 assert_return(!m->sealed, -EPERM);
816 r = message_attribute_has_type(m, type, NLA_U8);
820 r = add_rtattr(m, type, &data, sizeof(uint8_t));
828 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
831 assert_return(m, -EINVAL);
832 assert_return(!m->sealed, -EPERM);
834 r = message_attribute_has_type(m, type, NLA_U16);
838 r = add_rtattr(m, type, &data, sizeof(uint16_t));
845 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
848 assert_return(m, -EINVAL);
849 assert_return(!m->sealed, -EPERM);
851 r = message_attribute_has_type(m, type, NLA_U32);
855 r = add_rtattr(m, type, &data, sizeof(uint32_t));
862 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
865 assert_return(m, -EINVAL);
866 assert_return(!m->sealed, -EPERM);
867 assert_return(data, -EINVAL);
869 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
873 r = add_rtattr(m, type, data, sizeof(struct in_addr));
880 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
883 assert_return(m, -EINVAL);
884 assert_return(!m->sealed, -EPERM);
885 assert_return(data, -EINVAL);
887 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
891 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
898 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
901 assert_return(m, -EINVAL);
902 assert_return(!m->sealed, -EPERM);
903 assert_return(data, -EINVAL);
905 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
909 r = add_rtattr(m, type, data, ETH_ALEN);
916 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
919 assert_return(m, -EINVAL);
920 assert_return(!m->sealed, -EPERM);
921 assert_return(info, -EINVAL);
923 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
927 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
934 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
938 assert_return(m, -EINVAL);
939 assert_return(!m->sealed, -EPERM);
940 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
942 r = message_attribute_has_type(m, type, NLA_NESTED);
944 const NLTypeSystemUnion *type_system_union;
947 r = message_attribute_has_type(m, type, NLA_UNION);
952 r = sd_rtnl_message_get_family(m, &family);
956 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
960 r = type_system_union_protocol_get_type_system(type_system_union,
961 &m->container_type_system[m->n_containers + 1],
968 r = type_system_get_type_system(m->container_type_system[m->n_containers],
969 &m->container_type_system[m->n_containers + 1],
975 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
979 m->container_offsets[m->n_containers ++] = r;
984 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
985 const NLTypeSystemUnion *type_system_union;
988 assert_return(m, -EINVAL);
989 assert_return(!m->sealed, -EPERM);
991 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
995 r = type_system_union_get_type_system(type_system_union,
996 &m->container_type_system[m->n_containers + 1],
1001 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
1005 /* do we evere need non-null size */
1006 r = add_rtattr(m, type, NULL, 0);
1010 m->container_offsets[m->n_containers ++] = r;
1016 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
1017 assert_return(m, -EINVAL);
1018 assert_return(!m->sealed, -EPERM);
1019 assert_return(m->n_containers > 0, -EINVAL);
1021 m->container_type_system[m->n_containers] = NULL;
1027 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
1030 assert_return(m, -EINVAL);
1031 assert_return(m->sealed, -EPERM);
1032 assert_return(data, -EINVAL);
1033 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
1034 assert(m->rta_offset_tb[m->n_containers]);
1035 assert(type < m->rta_tb_size[m->n_containers]);
1037 if(!m->rta_offset_tb[m->n_containers][type])
1040 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
1042 *data = RTA_DATA(rta);
1044 return RTA_PAYLOAD(rta);
1047 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
1051 assert_return(m, -EINVAL);
1053 r = message_attribute_has_type(m, type, NLA_STRING);
1057 r = rtnl_message_read_internal(m, type, &attr_data);
1060 else if (strnlen(attr_data, r) >= (size_t) r)
1064 *data = (const char *) attr_data;
1069 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
1073 assert_return(m, -EINVAL);
1075 r = message_attribute_has_type(m, type, NLA_U8);
1079 r = rtnl_message_read_internal(m, type, &attr_data);
1082 else if ((size_t) r < sizeof(uint8_t))
1086 *data = *(uint8_t *) attr_data;
1091 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
1095 assert_return(m, -EINVAL);
1097 r = message_attribute_has_type(m, type, NLA_U16);
1101 r = rtnl_message_read_internal(m, type, &attr_data);
1104 else if ((size_t) r < sizeof(uint16_t))
1108 *data = *(uint16_t *) attr_data;
1113 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
1117 assert_return(m, -EINVAL);
1119 r = message_attribute_has_type(m, type, NLA_U32);
1123 r = rtnl_message_read_internal(m, type, &attr_data);
1126 else if ((size_t)r < sizeof(uint32_t))
1130 *data = *(uint32_t *) attr_data;
1135 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
1139 assert_return(m, -EINVAL);
1141 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
1145 r = rtnl_message_read_internal(m, type, &attr_data);
1148 else if ((size_t)r < sizeof(struct ether_addr))
1152 memcpy(data, attr_data, sizeof(struct ether_addr));
1157 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
1161 assert_return(m, -EINVAL);
1163 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
1167 r = rtnl_message_read_internal(m, type, &attr_data);
1170 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
1174 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
1179 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
1183 assert_return(m, -EINVAL);
1185 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1189 r = rtnl_message_read_internal(m, type, &attr_data);
1192 else if ((size_t)r < sizeof(struct in_addr))
1196 memcpy(data, attr_data, sizeof(struct in_addr));
1201 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
1205 assert_return(m, -EINVAL);
1207 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1211 r = rtnl_message_read_internal(m, type, &attr_data);
1214 else if ((size_t)r < sizeof(struct in6_addr))
1218 memcpy(data, attr_data, sizeof(struct in6_addr));
1223 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
1224 const NLType *nl_type;
1225 const NLTypeSystem *type_system;
1230 assert_return(m, -EINVAL);
1231 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1233 r = type_system_get_type(m->container_type_system[m->n_containers],
1239 if (nl_type->type == NLA_NESTED) {
1240 r = type_system_get_type_system(m->container_type_system[m->n_containers],
1245 } else if (nl_type->type == NLA_UNION) {
1246 const NLTypeSystemUnion *type_system_union;
1248 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1254 switch (type_system_union->match_type) {
1255 case NL_MATCH_SIBLING:
1259 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1263 r = type_system_union_get_type_system(type_system_union,
1271 case NL_MATCH_PROTOCOL:
1275 r = sd_rtnl_message_get_family(m, &family);
1279 r = type_system_union_protocol_get_type_system(type_system_union,
1288 assert_not_reached("sd-rtnl: invalid type system union type");
1293 r = rtnl_message_read_internal(m, type, &container);
1301 r = rtnl_message_parse(m,
1302 &m->rta_offset_tb[m->n_containers],
1303 &m->rta_tb_size[m->n_containers],
1312 m->container_type_system[m->n_containers] = type_system;
1317 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1318 assert_return(m, -EINVAL);
1319 assert_return(m->sealed, -EINVAL);
1320 assert_return(m->n_containers > 0, -EINVAL);
1322 free(m->rta_offset_tb[m->n_containers]);
1323 m->rta_offset_tb[m->n_containers] = NULL;
1324 m->container_type_system[m->n_containers] = NULL;
1331 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1335 return m->hdr->nlmsg_seq;
1338 int sd_rtnl_message_is_error(sd_rtnl_message *m) {
1339 assert_return(m, 0);
1340 assert_return(m->hdr, 0);
1342 return m->hdr->nlmsg_type == NLMSG_ERROR;
1345 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1346 struct nlmsgerr *err;
1348 assert_return(m, -EINVAL);
1349 assert_return(m->hdr, -EINVAL);
1351 if (!sd_rtnl_message_is_error(m))
1354 err = NLMSG_DATA(m->hdr);
1359 int rtnl_message_parse(sd_rtnl_message *m,
1360 size_t **rta_offset_tb,
1361 unsigned short *rta_tb_size,
1364 unsigned int rt_len) {
1365 unsigned short type;
1368 tb = new0(size_t, max + 1);
1372 *rta_tb_size = max + 1;
1374 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1375 type = RTA_TYPE(rta);
1377 /* if the kernel is newer than the headers we used
1378 when building, we ignore out-of-range attributes
1384 log_debug("rtnl: message parse - overwriting repeated attribute");
1386 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1389 *rta_offset_tb = tb;
1394 /* returns the number of bytes sent, or a negative error code */
1395 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1398 struct sockaddr_nl nl;
1400 .nl.nl_family = AF_NETLINK,
1408 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1409 0, &addr.sa, sizeof(addr));
1411 return (errno == EAGAIN) ? 0 : -errno;
1416 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1417 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1418 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1419 struct msghdr msg = {
1422 .msg_control = cred_buffer,
1423 .msg_controllen = sizeof(cred_buffer),
1425 struct cmsghdr *cmsg;
1433 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1436 if (errno == ENOBUFS)
1437 log_debug("rtnl: kernel receive buffer overrun");
1438 else if (errno == EAGAIN)
1439 log_debug("rtnl: no data in socket");
1441 return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
1444 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1445 if (cmsg->cmsg_level == SOL_SOCKET &&
1446 cmsg->cmsg_type == SCM_CREDENTIALS &&
1447 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1448 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1450 /* from the kernel */
1451 if (ucred->pid == 0)
1454 log_debug("rtnl: ignoring message from PID "PID_FMT, ucred->pid);
1455 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1456 cmsg->cmsg_type == NETLINK_PKTINFO &&
1457 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1458 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1460 /* multi-cast group */
1461 group = pktinfo->group;
1466 /* not from the kernel, ignore */
1468 /* drop the message */
1469 r = recvmsg(fd, &msg, 0);
1471 return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
1483 /* On success, the number of bytes received is returned and *ret points to the received message
1484 * which has a valid header and the correct size.
1485 * If nothing useful was received 0 is returned.
1486 * On failure, a negative error code is returned.
1488 int socket_read_message(sd_rtnl *rtnl) {
1489 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1490 struct iovec iov = {};
1492 bool multi_part = false, done = false;
1493 struct nlmsghdr *new_msg;
1499 assert(rtnl->rbuffer);
1500 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1502 /* read nothing, just get the pending message size */
1503 r = socket_recv_message(rtnl->fd, &iov, NULL, true);
1509 /* make room for the pending message */
1510 if (!greedy_realloc((void **)&rtnl->rbuffer,
1511 &rtnl->rbuffer_allocated,
1512 len, sizeof(uint8_t)))
1515 iov.iov_base = rtnl->rbuffer;
1516 iov.iov_len = rtnl->rbuffer_allocated;
1518 /* read the pending message */
1519 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1525 if (len > rtnl->rbuffer_allocated)
1526 /* message did not fit in read buffer */
1529 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1532 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1533 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1534 rtnl->rbuffer->nlmsg_seq) {
1535 first = rtnl->rqueue_partial[i];
1541 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
1542 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1543 const NLType *nl_type;
1545 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1546 /* not broadcast and not for us */
1549 if (new_msg->nlmsg_type == NLMSG_NOOP)
1550 /* silently drop noop messages */
1553 if (new_msg->nlmsg_type == NLMSG_DONE) {
1554 /* finished reading multi-part message */
1557 /* if first is not defined, put NLMSG_DONE into the receive queue. */
1562 /* check that we support this message type */
1563 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1565 if (r == -EOPNOTSUPP)
1566 log_debug("sd-rtnl: ignored message with unknown type: %i",
1567 new_msg->nlmsg_type);
1572 /* check that the size matches the message type */
1573 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
1574 log_debug("sd-rtnl: message larger than expected, dropping");
1578 r = message_new_empty(rtnl, &m);
1582 m->broadcast = !!group;
1584 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1588 /* seal and parse the top-level message */
1589 r = sd_rtnl_message_rewind(m);
1593 /* push the message onto the multi-part message stack */
1601 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1606 if (!multi_part || done) {
1607 /* we got a complete message, push it on the read queue */
1608 r = rtnl_rqueue_make_room(rtnl);
1612 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1615 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1616 /* remove the message form the partial read queue */
1617 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1618 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1619 rtnl->rqueue_partial_size --;
1624 /* we only got a partial multi-part message, push it on the
1625 partial read queue */
1626 if (i < rtnl->rqueue_partial_size) {
1627 rtnl->rqueue_partial[i] = first;
1629 r = rtnl_rqueue_partial_make_room(rtnl);
1633 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1641 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1646 assert_return(m, -EINVAL);
1648 /* don't allow appending to message once parsed */
1650 rtnl_message_seal(m);
1652 for (i = 1; i <= m->n_containers; i++) {
1653 free(m->rta_offset_tb[i]);
1654 m->rta_offset_tb[i] = NULL;
1655 m->rta_tb_size[i] = 0;
1656 m->container_type_system[i] = NULL;
1659 m->n_containers = 0;
1661 if (m->rta_offset_tb[0]) {
1662 /* top-level attributes have already been parsed */
1668 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1672 if (type->type == NLA_NESTED) {
1673 const NLTypeSystem *type_system = type->type_system;
1675 assert(type_system);
1677 m->container_type_system[0] = type_system;
1679 r = rtnl_message_parse(m,
1680 &m->rta_offset_tb[m->n_containers],
1681 &m->rta_tb_size[m->n_containers],
1683 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1684 NLMSG_ALIGN(type->size)),
1685 NLMSG_PAYLOAD(m->hdr, type->size));
1693 void rtnl_message_seal(sd_rtnl_message *m) {
1700 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1701 assert_return(m, NULL);