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>
27 #include "socket-util.h"
28 #include "formats-util.h"
32 #include "sd-netlink.h"
33 #include "netlink-util.h"
34 #include "netlink-internal.h"
35 #include "netlink-types.h"
37 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
38 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
40 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
42 static int message_new_empty(sd_netlink
*rtnl
, sd_netlink_message
**ret
) {
43 sd_netlink_message
*m
;
45 assert_return(ret
, -EINVAL
);
47 /* Note that 'rtnl' is currently unused, if we start using it internally
48 we must take care to avoid problems due to mutual references between
49 buses and their queued messages. See sd-bus.
52 m
= new0(sd_netlink_message
, 1);
56 m
->n_ref
= REFCNT_INIT
;
65 int message_new(sd_netlink
*rtnl
, sd_netlink_message
**ret
, uint16_t type
) {
66 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
67 const NLType
*nl_type
;
71 r
= type_system_get_type(NULL
, &nl_type
, type
);
75 r
= message_new_empty(rtnl
, &m
);
79 size
= NLMSG_SPACE(nl_type
->size
);
81 assert(size
>= sizeof(struct nlmsghdr
));
82 m
->hdr
= malloc0(size
);
86 m
->hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
88 m
->container_type_system
[0] = nl_type
->type_system
;
89 m
->hdr
->nlmsg_len
= size
;
90 m
->hdr
->nlmsg_type
= type
;
98 int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message
*m
, unsigned char prefixlen
) {
101 assert_return(m
, -EINVAL
);
102 assert_return(m
->hdr
, -EINVAL
);
103 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
105 rtm
= NLMSG_DATA(m
->hdr
);
107 if ((rtm
->rtm_family
== AF_INET
&& prefixlen
> 32) ||
108 (rtm
->rtm_family
== AF_INET6
&& prefixlen
> 128))
111 rtm
->rtm_dst_len
= prefixlen
;
116 int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message
*m
, unsigned char prefixlen
) {
119 assert_return(m
, -EINVAL
);
120 assert_return(m
->hdr
, -EINVAL
);
121 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
123 rtm
= NLMSG_DATA(m
->hdr
);
125 if ((rtm
->rtm_family
== AF_INET
&& prefixlen
> 32) ||
126 (rtm
->rtm_family
== AF_INET6
&& prefixlen
> 128))
129 rtm
->rtm_src_len
= prefixlen
;
134 int sd_rtnl_message_route_set_scope(sd_netlink_message
*m
, unsigned char scope
) {
137 assert_return(m
, -EINVAL
);
138 assert_return(m
->hdr
, -EINVAL
);
139 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
141 rtm
= NLMSG_DATA(m
->hdr
);
143 rtm
->rtm_scope
= scope
;
148 int sd_rtnl_message_route_get_family(sd_netlink_message
*m
, int *family
) {
151 assert_return(m
, -EINVAL
);
152 assert_return(m
->hdr
, -EINVAL
);
153 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
154 assert_return(family
, -EINVAL
);
156 rtm
= NLMSG_DATA(m
->hdr
);
158 *family
= rtm
->rtm_family
;
163 int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message
*m
, unsigned char *dst_len
) {
166 assert_return(m
, -EINVAL
);
167 assert_return(m
->hdr
, -EINVAL
);
168 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
169 assert_return(dst_len
, -EINVAL
);
171 rtm
= NLMSG_DATA(m
->hdr
);
173 *dst_len
= rtm
->rtm_dst_len
;
178 int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message
*m
, unsigned char *src_len
) {
181 assert_return(m
, -EINVAL
);
182 assert_return(m
->hdr
, -EINVAL
);
183 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
184 assert_return(src_len
, -EINVAL
);
186 rtm
= NLMSG_DATA(m
->hdr
);
188 *src_len
= rtm
->rtm_src_len
;
193 int sd_rtnl_message_new_route(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
194 uint16_t nlmsg_type
, int rtm_family
,
195 unsigned char rtm_protocol
) {
199 assert_return(rtnl_message_type_is_route(nlmsg_type
), -EINVAL
);
200 assert_return((nlmsg_type
== RTM_GETROUTE
&& rtm_family
== AF_UNSPEC
) ||
201 rtm_family
== AF_INET
|| rtm_family
== AF_INET6
, -EINVAL
);
202 assert_return(ret
, -EINVAL
);
204 r
= message_new(rtnl
, ret
, nlmsg_type
);
208 if (nlmsg_type
== RTM_NEWROUTE
)
209 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_APPEND
;
211 rtm
= NLMSG_DATA((*ret
)->hdr
);
213 rtm
->rtm_family
= rtm_family
;
214 rtm
->rtm_scope
= RT_SCOPE_UNIVERSE
;
215 rtm
->rtm_type
= RTN_UNICAST
;
216 rtm
->rtm_table
= RT_TABLE_MAIN
;
217 rtm
->rtm_protocol
= rtm_protocol
;
222 int sd_rtnl_message_neigh_set_flags(sd_netlink_message
*m
, uint8_t flags
) {
225 assert_return(m
, -EINVAL
);
226 assert_return(m
->hdr
, -EINVAL
);
227 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
229 ndm
= NLMSG_DATA(m
->hdr
);
230 ndm
->ndm_flags
|= flags
;
235 int sd_rtnl_message_neigh_set_state(sd_netlink_message
*m
, uint16_t state
) {
238 assert_return(m
, -EINVAL
);
239 assert_return(m
->hdr
, -EINVAL
);
240 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
242 ndm
= NLMSG_DATA(m
->hdr
);
243 ndm
->ndm_state
|= state
;
248 int sd_rtnl_message_neigh_get_flags(sd_netlink_message
*m
, uint8_t *flags
) {
251 assert_return(m
, -EINVAL
);
252 assert_return(m
->hdr
, -EINVAL
);
253 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
255 ndm
= NLMSG_DATA(m
->hdr
);
256 *flags
= ndm
->ndm_flags
;
261 int sd_rtnl_message_neigh_get_state(sd_netlink_message
*m
, uint16_t *state
) {
264 assert_return(m
, -EINVAL
);
265 assert_return(m
->hdr
, -EINVAL
);
266 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
268 ndm
= NLMSG_DATA(m
->hdr
);
269 *state
= ndm
->ndm_state
;
274 int sd_rtnl_message_neigh_get_family(sd_netlink_message
*m
, int *family
) {
277 assert_return(m
, -EINVAL
);
278 assert_return(m
->hdr
, -EINVAL
);
279 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
280 assert_return(family
, -EINVAL
);
282 ndm
= NLMSG_DATA(m
->hdr
);
284 *family
= ndm
->ndm_family
;
289 int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message
*m
, int *index
) {
292 assert_return(m
, -EINVAL
);
293 assert_return(m
->hdr
, -EINVAL
);
294 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
295 assert_return(index
, -EINVAL
);
297 ndm
= NLMSG_DATA(m
->hdr
);
299 *index
= ndm
->ndm_ifindex
;
304 int sd_rtnl_message_new_neigh(sd_netlink
*rtnl
, sd_netlink_message
**ret
, uint16_t nlmsg_type
, int index
, int ndm_family
) {
308 assert_return(rtnl_message_type_is_neigh(nlmsg_type
), -EINVAL
);
309 assert_return(ndm_family
== AF_INET
||
310 ndm_family
== AF_INET6
||
311 ndm_family
== PF_BRIDGE
, -EINVAL
);
312 assert_return(ret
, -EINVAL
);
314 r
= message_new(rtnl
, ret
, nlmsg_type
);
318 if (nlmsg_type
== RTM_NEWNEIGH
)
319 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_APPEND
;
321 ndm
= NLMSG_DATA((*ret
)->hdr
);
323 ndm
->ndm_family
= ndm_family
;
324 ndm
->ndm_ifindex
= index
;
329 int sd_rtnl_message_link_set_flags(sd_netlink_message
*m
, unsigned flags
, unsigned change
) {
330 struct ifinfomsg
*ifi
;
332 assert_return(m
, -EINVAL
);
333 assert_return(m
->hdr
, -EINVAL
);
334 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
335 assert_return(change
, -EINVAL
);
337 ifi
= NLMSG_DATA(m
->hdr
);
339 ifi
->ifi_flags
= flags
;
340 ifi
->ifi_change
= change
;
345 int sd_rtnl_message_link_set_type(sd_netlink_message
*m
, unsigned type
) {
346 struct ifinfomsg
*ifi
;
348 assert_return(m
, -EINVAL
);
349 assert_return(m
->hdr
, -EINVAL
);
350 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
352 ifi
= NLMSG_DATA(m
->hdr
);
354 ifi
->ifi_type
= type
;
359 int sd_rtnl_message_link_set_family(sd_netlink_message
*m
, unsigned family
) {
360 struct ifinfomsg
*ifi
;
362 assert_return(m
, -EINVAL
);
363 assert_return(m
->hdr
, -EINVAL
);
364 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
366 ifi
= NLMSG_DATA(m
->hdr
);
368 ifi
->ifi_family
= family
;
373 int sd_rtnl_message_new_link(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
374 uint16_t nlmsg_type
, int index
) {
375 struct ifinfomsg
*ifi
;
378 assert_return(rtnl_message_type_is_link(nlmsg_type
), -EINVAL
);
379 assert_return(nlmsg_type
!= RTM_DELLINK
|| index
> 0, -EINVAL
);
380 assert_return(ret
, -EINVAL
);
382 r
= message_new(rtnl
, ret
, nlmsg_type
);
386 if (nlmsg_type
== RTM_NEWLINK
)
387 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_EXCL
;
389 ifi
= NLMSG_DATA((*ret
)->hdr
);
391 ifi
->ifi_family
= AF_UNSPEC
;
392 ifi
->ifi_index
= index
;
397 int sd_netlink_message_request_dump(sd_netlink_message
*m
, int dump
) {
398 assert_return(m
, -EINVAL
);
399 assert_return(m
->hdr
, -EINVAL
);
400 assert_return(m
->hdr
->nlmsg_type
== RTM_GETLINK
||
401 m
->hdr
->nlmsg_type
== RTM_GETADDR
||
402 m
->hdr
->nlmsg_type
== RTM_GETROUTE
||
403 m
->hdr
->nlmsg_type
== RTM_GETNEIGH
,
407 m
->hdr
->nlmsg_flags
|= NLM_F_DUMP
;
409 m
->hdr
->nlmsg_flags
&= ~NLM_F_DUMP
;
414 int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message
*m
, unsigned char prefixlen
) {
415 struct ifaddrmsg
*ifa
;
417 assert_return(m
, -EINVAL
);
418 assert_return(m
->hdr
, -EINVAL
);
419 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
421 ifa
= NLMSG_DATA(m
->hdr
);
423 if ((ifa
->ifa_family
== AF_INET
&& prefixlen
> 32) ||
424 (ifa
->ifa_family
== AF_INET6
&& prefixlen
> 128))
427 ifa
->ifa_prefixlen
= prefixlen
;
432 int sd_rtnl_message_addr_set_flags(sd_netlink_message
*m
, unsigned char flags
) {
433 struct ifaddrmsg
*ifa
;
435 assert_return(m
, -EINVAL
);
436 assert_return(m
->hdr
, -EINVAL
);
437 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
439 ifa
= NLMSG_DATA(m
->hdr
);
441 ifa
->ifa_flags
= flags
;
446 int sd_rtnl_message_addr_set_scope(sd_netlink_message
*m
, unsigned char scope
) {
447 struct ifaddrmsg
*ifa
;
449 assert_return(m
, -EINVAL
);
450 assert_return(m
->hdr
, -EINVAL
);
451 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
453 ifa
= NLMSG_DATA(m
->hdr
);
455 ifa
->ifa_scope
= scope
;
460 int sd_rtnl_message_addr_get_family(sd_netlink_message
*m
, int *family
) {
461 struct ifaddrmsg
*ifa
;
463 assert_return(m
, -EINVAL
);
464 assert_return(m
->hdr
, -EINVAL
);
465 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
466 assert_return(family
, -EINVAL
);
468 ifa
= NLMSG_DATA(m
->hdr
);
470 *family
= ifa
->ifa_family
;
475 int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message
*m
, unsigned char *prefixlen
) {
476 struct ifaddrmsg
*ifa
;
478 assert_return(m
, -EINVAL
);
479 assert_return(m
->hdr
, -EINVAL
);
480 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
481 assert_return(prefixlen
, -EINVAL
);
483 ifa
= NLMSG_DATA(m
->hdr
);
485 *prefixlen
= ifa
->ifa_prefixlen
;
490 int sd_rtnl_message_addr_get_scope(sd_netlink_message
*m
, unsigned char *scope
) {
491 struct ifaddrmsg
*ifa
;
493 assert_return(m
, -EINVAL
);
494 assert_return(m
->hdr
, -EINVAL
);
495 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
496 assert_return(scope
, -EINVAL
);
498 ifa
= NLMSG_DATA(m
->hdr
);
500 *scope
= ifa
->ifa_scope
;
505 int sd_rtnl_message_addr_get_flags(sd_netlink_message
*m
, unsigned char *flags
) {
506 struct ifaddrmsg
*ifa
;
508 assert_return(m
, -EINVAL
);
509 assert_return(m
->hdr
, -EINVAL
);
510 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
511 assert_return(flags
, -EINVAL
);
513 ifa
= NLMSG_DATA(m
->hdr
);
515 *flags
= ifa
->ifa_flags
;
520 int sd_rtnl_message_addr_get_ifindex(sd_netlink_message
*m
, int *ifindex
) {
521 struct ifaddrmsg
*ifa
;
523 assert_return(m
, -EINVAL
);
524 assert_return(m
->hdr
, -EINVAL
);
525 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
526 assert_return(ifindex
, -EINVAL
);
528 ifa
= NLMSG_DATA(m
->hdr
);
530 *ifindex
= ifa
->ifa_index
;
535 int sd_rtnl_message_new_addr(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
536 uint16_t nlmsg_type
, int index
,
538 struct ifaddrmsg
*ifa
;
541 assert_return(rtnl_message_type_is_addr(nlmsg_type
), -EINVAL
);
542 assert_return((nlmsg_type
== RTM_GETADDR
&& index
== 0) ||
544 assert_return((nlmsg_type
== RTM_GETADDR
&& family
== AF_UNSPEC
) ||
545 family
== AF_INET
|| family
== AF_INET6
, -EINVAL
);
546 assert_return(ret
, -EINVAL
);
548 r
= message_new(rtnl
, ret
, nlmsg_type
);
552 if (nlmsg_type
== RTM_GETADDR
)
553 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_DUMP
;
555 ifa
= NLMSG_DATA((*ret
)->hdr
);
557 ifa
->ifa_index
= index
;
558 ifa
->ifa_family
= family
;
559 if (family
== AF_INET
)
560 ifa
->ifa_prefixlen
= 32;
561 else if (family
== AF_INET6
)
562 ifa
->ifa_prefixlen
= 128;
567 int sd_rtnl_message_new_addr_update(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
568 int index
, int family
) {
571 r
= sd_rtnl_message_new_addr(rtnl
, ret
, RTM_NEWADDR
, index
, family
);
575 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_REPLACE
;
580 sd_netlink_message
*sd_netlink_message_ref(sd_netlink_message
*m
) {
582 assert_se(REFCNT_INC(m
->n_ref
) >= 2);
587 sd_netlink_message
*sd_netlink_message_unref(sd_netlink_message
*m
) {
588 if (m
&& REFCNT_DEC(m
->n_ref
) == 0) {
593 for (i
= 0; i
<= m
->n_containers
; i
++)
594 free(m
->rta_offset_tb
[i
]);
596 sd_netlink_message_unref(m
->next
);
604 int sd_netlink_message_get_type(sd_netlink_message
*m
, uint16_t *type
) {
605 assert_return(m
, -EINVAL
);
606 assert_return(type
, -EINVAL
);
608 *type
= m
->hdr
->nlmsg_type
;
613 int sd_netlink_message_get_family(sd_netlink_message
*m
, int *family
) {
614 assert_return(m
, -EINVAL
);
615 assert_return(family
, -EINVAL
);
619 if (rtnl_message_type_is_link(m
->hdr
->nlmsg_type
)) {
620 struct ifinfomsg
*ifi
;
622 ifi
= NLMSG_DATA(m
->hdr
);
624 *family
= ifi
->ifi_family
;
627 } else if (rtnl_message_type_is_route(m
->hdr
->nlmsg_type
)) {
630 rtm
= NLMSG_DATA(m
->hdr
);
632 *family
= rtm
->rtm_family
;
635 } else if (rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
)) {
638 ndm
= NLMSG_DATA(m
->hdr
);
640 *family
= ndm
->ndm_family
;
643 } else if (rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
)) {
644 struct ifaddrmsg
*ifa
;
646 ifa
= NLMSG_DATA(m
->hdr
);
648 *family
= ifa
->ifa_family
;
656 int sd_netlink_message_is_broadcast(sd_netlink_message
*m
) {
657 assert_return(m
, -EINVAL
);
662 int sd_rtnl_message_link_get_ifindex(sd_netlink_message
*m
, int *ifindex
) {
663 struct ifinfomsg
*ifi
;
665 assert_return(m
, -EINVAL
);
666 assert_return(m
->hdr
, -EINVAL
);
667 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
668 assert_return(ifindex
, -EINVAL
);
670 ifi
= NLMSG_DATA(m
->hdr
);
672 *ifindex
= ifi
->ifi_index
;
677 int sd_rtnl_message_link_get_flags(sd_netlink_message
*m
, unsigned *flags
) {
678 struct ifinfomsg
*ifi
;
680 assert_return(m
, -EINVAL
);
681 assert_return(m
->hdr
, -EINVAL
);
682 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
683 assert_return(flags
, -EINVAL
);
685 ifi
= NLMSG_DATA(m
->hdr
);
687 *flags
= ifi
->ifi_flags
;
692 int sd_rtnl_message_link_get_type(sd_netlink_message
*m
, unsigned *type
) {
693 struct ifinfomsg
*ifi
;
695 assert_return(m
, -EINVAL
);
696 assert_return(m
->hdr
, -EINVAL
);
697 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
698 assert_return(type
, -EINVAL
);
700 ifi
= NLMSG_DATA(m
->hdr
);
702 *type
= ifi
->ifi_type
;
707 /* If successful the updated message will be correctly aligned, if
708 unsuccessful the old message is untouched. */
709 static int add_rtattr(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t data_length
) {
711 size_t message_length
, padding_length
;
712 struct nlmsghdr
*new_hdr
;
721 assert(NLMSG_ALIGN(m
->hdr
->nlmsg_len
) == m
->hdr
->nlmsg_len
);
722 assert(!data
|| data_length
);
724 /* get offset of the new attribute */
725 offset
= m
->hdr
->nlmsg_len
;
727 /* get the size of the new rta attribute (with padding at the end) */
728 rta_length
= RTA_LENGTH(data_length
);
730 /* get the new message size (with padding at the end) */
731 message_length
= offset
+ RTA_ALIGN(rta_length
);
733 /* realloc to fit the new attribute */
734 new_hdr
= realloc(m
->hdr
, message_length
);
739 /* get pointer to the attribute we are about to add */
740 rta
= (struct rtattr
*) ((uint8_t *) m
->hdr
+ offset
);
742 /* if we are inside containers, extend them */
743 for (i
= 0; i
< m
->n_containers
; i
++)
744 GET_CONTAINER(m
, i
)->rta_len
+= message_length
- offset
;
746 /* fill in the attribute */
747 rta
->rta_type
= type
;
748 rta
->rta_len
= rta_length
;
750 /* we don't deal with the case where the user lies about the type
751 * and gives us too little data (so don't do that)
753 padding
= mempcpy(RTA_DATA(rta
), data
, data_length
);
755 /* if no data was passed, make sure we still initialize the padding
756 note that we can have data_length > 0 (used by some containers) */
757 padding
= RTA_DATA(rta
);
760 /* make sure also the padding at the end of the message is initialized */
761 padding_length
= (uint8_t*)m
->hdr
+ message_length
- (uint8_t*)padding
;
762 memzero(padding
, padding_length
);
764 /* update message size */
765 m
->hdr
->nlmsg_len
= message_length
;
770 static int message_attribute_has_type(sd_netlink_message
*m
, uint16_t attribute_type
, uint16_t data_type
) {
774 r
= type_system_get_type(m
->container_type_system
[m
->n_containers
], &type
, attribute_type
);
778 if (type
->type
!= data_type
)
784 int sd_netlink_message_append_string(sd_netlink_message
*m
, unsigned short type
, const char *data
) {
788 assert_return(m
, -EINVAL
);
789 assert_return(!m
->sealed
, -EPERM
);
790 assert_return(data
, -EINVAL
);
792 r
= message_attribute_has_type(m
, type
, NLA_STRING
);
799 length
= strnlen(data
, size
+1);
803 length
= strlen(data
);
805 r
= add_rtattr(m
, type
, data
, length
+ 1);
812 int sd_netlink_message_append_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t data
) {
815 assert_return(m
, -EINVAL
);
816 assert_return(!m
->sealed
, -EPERM
);
818 r
= message_attribute_has_type(m
, type
, NLA_U8
);
822 r
= add_rtattr(m
, type
, &data
, sizeof(uint8_t));
830 int sd_netlink_message_append_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t data
) {
833 assert_return(m
, -EINVAL
);
834 assert_return(!m
->sealed
, -EPERM
);
836 r
= message_attribute_has_type(m
, type
, NLA_U16
);
840 r
= add_rtattr(m
, type
, &data
, sizeof(uint16_t));
847 int sd_netlink_message_append_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t data
) {
850 assert_return(m
, -EINVAL
);
851 assert_return(!m
->sealed
, -EPERM
);
853 r
= message_attribute_has_type(m
, type
, NLA_U32
);
857 r
= add_rtattr(m
, type
, &data
, sizeof(uint32_t));
864 int sd_netlink_message_append_in_addr(sd_netlink_message
*m
, unsigned short type
, const struct in_addr
*data
) {
867 assert_return(m
, -EINVAL
);
868 assert_return(!m
->sealed
, -EPERM
);
869 assert_return(data
, -EINVAL
);
871 r
= message_attribute_has_type(m
, type
, NLA_IN_ADDR
);
875 r
= add_rtattr(m
, type
, data
, sizeof(struct in_addr
));
882 int sd_netlink_message_append_in6_addr(sd_netlink_message
*m
, unsigned short type
, const struct in6_addr
*data
) {
885 assert_return(m
, -EINVAL
);
886 assert_return(!m
->sealed
, -EPERM
);
887 assert_return(data
, -EINVAL
);
889 r
= message_attribute_has_type(m
, type
, NLA_IN_ADDR
);
893 r
= add_rtattr(m
, type
, data
, sizeof(struct in6_addr
));
900 int sd_netlink_message_append_ether_addr(sd_netlink_message
*m
, unsigned short type
, const struct ether_addr
*data
) {
903 assert_return(m
, -EINVAL
);
904 assert_return(!m
->sealed
, -EPERM
);
905 assert_return(data
, -EINVAL
);
907 r
= message_attribute_has_type(m
, type
, NLA_ETHER_ADDR
);
911 r
= add_rtattr(m
, type
, data
, ETH_ALEN
);
918 int sd_netlink_message_append_cache_info(sd_netlink_message
*m
, unsigned short type
, const struct ifa_cacheinfo
*info
) {
921 assert_return(m
, -EINVAL
);
922 assert_return(!m
->sealed
, -EPERM
);
923 assert_return(info
, -EINVAL
);
925 r
= message_attribute_has_type(m
, type
, NLA_CACHE_INFO
);
929 r
= add_rtattr(m
, type
, info
, sizeof(struct ifa_cacheinfo
));
936 int sd_netlink_message_open_container(sd_netlink_message
*m
, unsigned short type
) {
940 assert_return(m
, -EINVAL
);
941 assert_return(!m
->sealed
, -EPERM
);
942 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -ERANGE
);
944 r
= message_attribute_has_type(m
, type
, NLA_NESTED
);
946 const NLTypeSystemUnion
*type_system_union
;
949 r
= message_attribute_has_type(m
, type
, NLA_UNION
);
954 r
= sd_netlink_message_get_family(m
, &family
);
958 r
= type_system_get_type_system_union(m
->container_type_system
[m
->n_containers
], &type_system_union
, type
);
962 r
= type_system_union_protocol_get_type_system(type_system_union
,
963 &m
->container_type_system
[m
->n_containers
+ 1],
970 r
= type_system_get_type_system(m
->container_type_system
[m
->n_containers
],
971 &m
->container_type_system
[m
->n_containers
+ 1],
977 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, size
);
981 m
->container_offsets
[m
->n_containers
++] = r
;
986 int sd_netlink_message_open_container_union(sd_netlink_message
*m
, unsigned short type
, const char *key
) {
987 const NLTypeSystemUnion
*type_system_union
;
990 assert_return(m
, -EINVAL
);
991 assert_return(!m
->sealed
, -EPERM
);
993 r
= type_system_get_type_system_union(m
->container_type_system
[m
->n_containers
], &type_system_union
, type
);
997 r
= type_system_union_get_type_system(type_system_union
,
998 &m
->container_type_system
[m
->n_containers
+ 1],
1003 r
= sd_netlink_message_append_string(m
, type_system_union
->match
, key
);
1007 /* do we evere need non-null size */
1008 r
= add_rtattr(m
, type
, NULL
, 0);
1012 m
->container_offsets
[m
->n_containers
++] = r
;
1018 int sd_netlink_message_close_container(sd_netlink_message
*m
) {
1019 assert_return(m
, -EINVAL
);
1020 assert_return(!m
->sealed
, -EPERM
);
1021 assert_return(m
->n_containers
> 0, -EINVAL
);
1023 m
->container_type_system
[m
->n_containers
] = NULL
;
1029 int rtnl_message_read_internal(sd_netlink_message
*m
, unsigned short type
, void **data
) {
1032 assert_return(m
, -EINVAL
);
1033 assert_return(m
->sealed
, -EPERM
);
1034 assert_return(data
, -EINVAL
);
1035 assert(m
->n_containers
<= RTNL_CONTAINER_DEPTH
);
1036 assert(m
->rta_offset_tb
[m
->n_containers
]);
1037 assert(type
< m
->rta_tb_size
[m
->n_containers
]);
1039 if(!m
->rta_offset_tb
[m
->n_containers
][type
])
1042 rta
= (struct rtattr
*)((uint8_t *) m
->hdr
+ m
->rta_offset_tb
[m
->n_containers
][type
]);
1044 *data
= RTA_DATA(rta
);
1046 return RTA_PAYLOAD(rta
);
1049 int sd_netlink_message_read_string(sd_netlink_message
*m
, unsigned short type
, const char **data
) {
1053 assert_return(m
, -EINVAL
);
1055 r
= message_attribute_has_type(m
, type
, NLA_STRING
);
1059 r
= rtnl_message_read_internal(m
, type
, &attr_data
);
1062 else if (strnlen(attr_data
, r
) >= (size_t) r
)
1066 *data
= (const char *) attr_data
;
1071 int sd_netlink_message_read_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t *data
) {
1075 assert_return(m
, -EINVAL
);
1077 r
= message_attribute_has_type(m
, type
, NLA_U8
);
1081 r
= rtnl_message_read_internal(m
, type
, &attr_data
);
1084 else if ((size_t) r
< sizeof(uint8_t))
1088 *data
= *(uint8_t *) attr_data
;
1093 int sd_netlink_message_read_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t *data
) {
1097 assert_return(m
, -EINVAL
);
1099 r
= message_attribute_has_type(m
, type
, NLA_U16
);
1103 r
= rtnl_message_read_internal(m
, type
, &attr_data
);
1106 else if ((size_t) r
< sizeof(uint16_t))
1110 *data
= *(uint16_t *) attr_data
;
1115 int sd_netlink_message_read_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t *data
) {
1119 assert_return(m
, -EINVAL
);
1121 r
= message_attribute_has_type(m
, type
, NLA_U32
);
1125 r
= rtnl_message_read_internal(m
, type
, &attr_data
);
1128 else if ((size_t)r
< sizeof(uint32_t))
1132 *data
= *(uint32_t *) attr_data
;
1137 int sd_netlink_message_read_ether_addr(sd_netlink_message
*m
, unsigned short type
, struct ether_addr
*data
) {
1141 assert_return(m
, -EINVAL
);
1143 r
= message_attribute_has_type(m
, type
, NLA_ETHER_ADDR
);
1147 r
= rtnl_message_read_internal(m
, type
, &attr_data
);
1150 else if ((size_t)r
< sizeof(struct ether_addr
))
1154 memcpy(data
, attr_data
, sizeof(struct ether_addr
));
1159 int sd_netlink_message_read_cache_info(sd_netlink_message
*m
, unsigned short type
, struct ifa_cacheinfo
*info
) {
1163 assert_return(m
, -EINVAL
);
1165 r
= message_attribute_has_type(m
, type
, NLA_CACHE_INFO
);
1169 r
= rtnl_message_read_internal(m
, type
, &attr_data
);
1172 else if ((size_t)r
< sizeof(struct ifa_cacheinfo
))
1176 memcpy(info
, attr_data
, sizeof(struct ifa_cacheinfo
));
1181 int sd_netlink_message_read_in_addr(sd_netlink_message
*m
, unsigned short type
, struct in_addr
*data
) {
1185 assert_return(m
, -EINVAL
);
1187 r
= message_attribute_has_type(m
, type
, NLA_IN_ADDR
);
1191 r
= rtnl_message_read_internal(m
, type
, &attr_data
);
1194 else if ((size_t)r
< sizeof(struct in_addr
))
1198 memcpy(data
, attr_data
, sizeof(struct in_addr
));
1203 int sd_netlink_message_read_in6_addr(sd_netlink_message
*m
, unsigned short type
, struct in6_addr
*data
) {
1207 assert_return(m
, -EINVAL
);
1209 r
= message_attribute_has_type(m
, type
, NLA_IN_ADDR
);
1213 r
= rtnl_message_read_internal(m
, type
, &attr_data
);
1216 else if ((size_t)r
< sizeof(struct in6_addr
))
1220 memcpy(data
, attr_data
, sizeof(struct in6_addr
));
1225 int sd_netlink_message_enter_container(sd_netlink_message
*m
, unsigned short type
) {
1226 const NLType
*nl_type
;
1227 const NLTypeSystem
*type_system
;
1232 assert_return(m
, -EINVAL
);
1233 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -EINVAL
);
1235 r
= type_system_get_type(m
->container_type_system
[m
->n_containers
],
1241 if (nl_type
->type
== NLA_NESTED
) {
1242 r
= type_system_get_type_system(m
->container_type_system
[m
->n_containers
],
1247 } else if (nl_type
->type
== NLA_UNION
) {
1248 const NLTypeSystemUnion
*type_system_union
;
1250 r
= type_system_get_type_system_union(m
->container_type_system
[m
->n_containers
],
1256 switch (type_system_union
->match_type
) {
1257 case NL_MATCH_SIBLING
:
1261 r
= sd_netlink_message_read_string(m
, type_system_union
->match
, &key
);
1265 r
= type_system_union_get_type_system(type_system_union
,
1273 case NL_MATCH_PROTOCOL
:
1277 r
= sd_netlink_message_get_family(m
, &family
);
1281 r
= type_system_union_protocol_get_type_system(type_system_union
,
1290 assert_not_reached("sd-netlink: invalid type system union type");
1295 r
= rtnl_message_read_internal(m
, type
, &container
);
1303 r
= rtnl_message_parse(m
,
1304 &m
->rta_offset_tb
[m
->n_containers
],
1305 &m
->rta_tb_size
[m
->n_containers
],
1314 m
->container_type_system
[m
->n_containers
] = type_system
;
1319 int sd_netlink_message_exit_container(sd_netlink_message
*m
) {
1320 assert_return(m
, -EINVAL
);
1321 assert_return(m
->sealed
, -EINVAL
);
1322 assert_return(m
->n_containers
> 0, -EINVAL
);
1324 free(m
->rta_offset_tb
[m
->n_containers
]);
1325 m
->rta_offset_tb
[m
->n_containers
] = NULL
;
1326 m
->container_type_system
[m
->n_containers
] = NULL
;
1333 uint32_t rtnl_message_get_serial(sd_netlink_message
*m
) {
1337 return m
->hdr
->nlmsg_seq
;
1340 int sd_netlink_message_is_error(sd_netlink_message
*m
) {
1341 assert_return(m
, 0);
1342 assert_return(m
->hdr
, 0);
1344 return m
->hdr
->nlmsg_type
== NLMSG_ERROR
;
1347 int sd_netlink_message_get_errno(sd_netlink_message
*m
) {
1348 struct nlmsgerr
*err
;
1350 assert_return(m
, -EINVAL
);
1351 assert_return(m
->hdr
, -EINVAL
);
1353 if (!sd_netlink_message_is_error(m
))
1356 err
= NLMSG_DATA(m
->hdr
);
1361 int rtnl_message_parse(sd_netlink_message
*m
,
1362 size_t **rta_offset_tb
,
1363 unsigned short *rta_tb_size
,
1366 unsigned int rt_len
) {
1367 unsigned short type
;
1370 tb
= new0(size_t, max
+ 1);
1374 *rta_tb_size
= max
+ 1;
1376 for (; RTA_OK(rta
, rt_len
); rta
= RTA_NEXT(rta
, rt_len
)) {
1377 type
= RTA_TYPE(rta
);
1379 /* if the kernel is newer than the headers we used
1380 when building, we ignore out-of-range attributes
1386 log_debug("rtnl: message parse - overwriting repeated attribute");
1388 tb
[type
] = (uint8_t *) rta
- (uint8_t *) m
->hdr
;
1391 *rta_offset_tb
= tb
;
1396 /* returns the number of bytes sent, or a negative error code */
1397 int socket_write_message(sd_netlink
*nl
, sd_netlink_message
*m
) {
1400 struct sockaddr_nl nl
;
1402 .nl
.nl_family
= AF_NETLINK
,
1410 k
= sendto(nl
->fd
, m
->hdr
, m
->hdr
->nlmsg_len
,
1411 0, &addr
.sa
, sizeof(addr
));
1418 static int socket_recv_message(int fd
, struct iovec
*iov
, uint32_t *_group
, bool peek
) {
1419 union sockaddr_union sender
;
1420 uint8_t cmsg_buffer
[CMSG_SPACE(sizeof(struct nl_pktinfo
))];
1421 struct msghdr msg
= {
1424 .msg_name
= &sender
,
1425 .msg_namelen
= sizeof(sender
),
1426 .msg_control
= cmsg_buffer
,
1427 .msg_controllen
= sizeof(cmsg_buffer
),
1429 struct cmsghdr
*cmsg
;
1436 r
= recvmsg(fd
, &msg
, MSG_TRUNC
| (peek
? MSG_PEEK
: 0));
1439 if (errno
== ENOBUFS
)
1440 log_debug("rtnl: kernel receive buffer overrun");
1441 else if (errno
== EAGAIN
)
1442 log_debug("rtnl: no data in socket");
1444 return (errno
== EAGAIN
|| errno
== EINTR
) ? 0 : -errno
;
1447 if (sender
.nl
.nl_pid
!= 0) {
1448 /* not from the kernel, ignore */
1449 log_debug("rtnl: ignoring message from portid %"PRIu32
, sender
.nl
.nl_pid
);
1452 /* drop the message */
1453 r
= recvmsg(fd
, &msg
, 0);
1455 return (errno
== EAGAIN
|| errno
== EINTR
) ? 0 : -errno
;
1461 CMSG_FOREACH(cmsg
, &msg
) {
1462 if (cmsg
->cmsg_level
== SOL_NETLINK
&&
1463 cmsg
->cmsg_type
== NETLINK_PKTINFO
&&
1464 cmsg
->cmsg_len
== CMSG_LEN(sizeof(struct nl_pktinfo
))) {
1465 struct nl_pktinfo
*pktinfo
= (void *)CMSG_DATA(cmsg
);
1467 /* multi-cast group */
1468 group
= pktinfo
->group
;
1478 /* On success, the number of bytes received is returned and *ret points to the received message
1479 * which has a valid header and the correct size.
1480 * If nothing useful was received 0 is returned.
1481 * On failure, a negative error code is returned.
1483 int socket_read_message(sd_netlink
*rtnl
) {
1484 _cleanup_netlink_message_unref_ sd_netlink_message
*first
= NULL
;
1485 struct iovec iov
= {};
1487 bool multi_part
= false, done
= false;
1488 struct nlmsghdr
*new_msg
;
1494 assert(rtnl
->rbuffer
);
1495 assert(rtnl
->rbuffer_allocated
>= sizeof(struct nlmsghdr
));
1497 /* read nothing, just get the pending message size */
1498 r
= socket_recv_message(rtnl
->fd
, &iov
, NULL
, true);
1504 /* make room for the pending message */
1505 if (!greedy_realloc((void **)&rtnl
->rbuffer
,
1506 &rtnl
->rbuffer_allocated
,
1507 len
, sizeof(uint8_t)))
1510 iov
.iov_base
= rtnl
->rbuffer
;
1511 iov
.iov_len
= rtnl
->rbuffer_allocated
;
1513 /* read the pending message */
1514 r
= socket_recv_message(rtnl
->fd
, &iov
, &group
, false);
1520 if (len
> rtnl
->rbuffer_allocated
)
1521 /* message did not fit in read buffer */
1524 if (NLMSG_OK(rtnl
->rbuffer
, len
) && rtnl
->rbuffer
->nlmsg_flags
& NLM_F_MULTI
) {
1527 for (i
= 0; i
< rtnl
->rqueue_partial_size
; i
++) {
1528 if (rtnl_message_get_serial(rtnl
->rqueue_partial
[i
]) ==
1529 rtnl
->rbuffer
->nlmsg_seq
) {
1530 first
= rtnl
->rqueue_partial
[i
];
1536 for (new_msg
= rtnl
->rbuffer
; NLMSG_OK(new_msg
, len
) && !done
; new_msg
= NLMSG_NEXT(new_msg
, len
)) {
1537 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
1538 const NLType
*nl_type
;
1540 if (!group
&& new_msg
->nlmsg_pid
!= rtnl
->sockaddr
.nl
.nl_pid
)
1541 /* not broadcast and not for us */
1544 if (new_msg
->nlmsg_type
== NLMSG_NOOP
)
1545 /* silently drop noop messages */
1548 if (new_msg
->nlmsg_type
== NLMSG_DONE
) {
1549 /* finished reading multi-part message */
1552 /* if first is not defined, put NLMSG_DONE into the receive queue. */
1557 /* check that we support this message type */
1558 r
= type_system_get_type(NULL
, &nl_type
, new_msg
->nlmsg_type
);
1560 if (r
== -EOPNOTSUPP
)
1561 log_debug("sd-netlink: ignored message with unknown type: %i",
1562 new_msg
->nlmsg_type
);
1567 /* check that the size matches the message type */
1568 if (new_msg
->nlmsg_len
< NLMSG_LENGTH(nl_type
->size
)) {
1569 log_debug("sd-netlink: message larger than expected, dropping");
1573 r
= message_new_empty(rtnl
, &m
);
1577 m
->broadcast
= !!group
;
1579 m
->hdr
= memdup(new_msg
, new_msg
->nlmsg_len
);
1583 /* seal and parse the top-level message */
1584 r
= sd_netlink_message_rewind(m
);
1588 /* push the message onto the multi-part message stack */
1596 log_debug("sd-netlink: discarding %zu bytes of incoming message", len
);
1601 if (!multi_part
|| done
) {
1602 /* we got a complete message, push it on the read queue */
1603 r
= rtnl_rqueue_make_room(rtnl
);
1607 rtnl
->rqueue
[rtnl
->rqueue_size
++] = first
;
1610 if (multi_part
&& (i
< rtnl
->rqueue_partial_size
)) {
1611 /* remove the message form the partial read queue */
1612 memmove(rtnl
->rqueue_partial
+ i
,rtnl
->rqueue_partial
+ i
+ 1,
1613 sizeof(sd_netlink_message
*) * (rtnl
->rqueue_partial_size
- i
- 1));
1614 rtnl
->rqueue_partial_size
--;
1619 /* we only got a partial multi-part message, push it on the
1620 partial read queue */
1621 if (i
< rtnl
->rqueue_partial_size
) {
1622 rtnl
->rqueue_partial
[i
] = first
;
1624 r
= rtnl_rqueue_partial_make_room(rtnl
);
1628 rtnl
->rqueue_partial
[rtnl
->rqueue_partial_size
++] = first
;
1636 int sd_netlink_message_rewind(sd_netlink_message
*m
) {
1641 assert_return(m
, -EINVAL
);
1643 /* don't allow appending to message once parsed */
1645 rtnl_message_seal(m
);
1647 for (i
= 1; i
<= m
->n_containers
; i
++) {
1648 free(m
->rta_offset_tb
[i
]);
1649 m
->rta_offset_tb
[i
] = NULL
;
1650 m
->rta_tb_size
[i
] = 0;
1651 m
->container_type_system
[i
] = NULL
;
1654 m
->n_containers
= 0;
1656 if (m
->rta_offset_tb
[0]) {
1657 /* top-level attributes have already been parsed */
1663 r
= type_system_get_type(NULL
, &type
, m
->hdr
->nlmsg_type
);
1667 if (type
->type
== NLA_NESTED
) {
1668 const NLTypeSystem
*type_system
= type
->type_system
;
1670 assert(type_system
);
1672 m
->container_type_system
[0] = type_system
;
1674 r
= rtnl_message_parse(m
,
1675 &m
->rta_offset_tb
[m
->n_containers
],
1676 &m
->rta_tb_size
[m
->n_containers
],
1678 (struct rtattr
*)((uint8_t*)NLMSG_DATA(m
->hdr
) +
1679 NLMSG_ALIGN(type
->size
)),
1680 NLMSG_PAYLOAD(m
->hdr
, type
->size
));
1688 void rtnl_message_seal(sd_netlink_message
*m
) {
1695 sd_netlink_message
*sd_netlink_message_next(sd_netlink_message
*m
) {
1696 assert_return(m
, NULL
);