1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Tom Gundersen <teg@jklm.no>
8 #include <netinet/in.h>
12 #include "sd-netlink.h"
14 #include "alloc-util.h"
15 #include "format-util.h"
17 #include "netlink-internal.h"
18 #include "netlink-types.h"
19 #include "netlink-util.h"
21 #include "socket-util.h"
24 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL)
25 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
27 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
28 #define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
30 int message_new_empty(sd_netlink
*rtnl
, sd_netlink_message
**ret
) {
31 sd_netlink_message
*m
;
33 assert_return(ret
, -EINVAL
);
35 /* Note that 'rtnl' is currently unused, if we start using it internally
36 we must take care to avoid problems due to mutual references between
37 buses and their queued messages. See sd-bus.
40 m
= new0(sd_netlink_message
, 1);
44 m
->n_ref
= REFCNT_INIT
;
45 m
->protocol
= rtnl
->protocol
;
53 int message_new(sd_netlink
*rtnl
, sd_netlink_message
**ret
, uint16_t type
) {
54 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
55 const NLType
*nl_type
;
56 const NLTypeSystem
*type_system_root
;
60 assert_return(rtnl
, -EINVAL
);
62 type_system_root
= type_system_get_root(rtnl
->protocol
);
64 r
= type_system_get_type(type_system_root
, &nl_type
, type
);
68 if (type_get_type(nl_type
) != NETLINK_TYPE_NESTED
)
71 r
= message_new_empty(rtnl
, &m
);
75 size
= NLMSG_SPACE(type_get_size(nl_type
));
77 assert(size
>= sizeof(struct nlmsghdr
));
78 m
->hdr
= malloc0(size
);
82 m
->hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
84 type_get_type_system(nl_type
, &m
->containers
[0].type_system
);
85 m
->hdr
->nlmsg_len
= size
;
86 m
->hdr
->nlmsg_type
= type
;
93 int sd_netlink_message_request_dump(sd_netlink_message
*m
, int dump
) {
94 assert_return(m
, -EINVAL
);
95 assert_return(m
->hdr
, -EINVAL
);
97 assert_return(IN_SET(m
->hdr
->nlmsg_type
, RTM_GETLINK
, RTM_GETADDR
, RTM_GETROUTE
, RTM_GETNEIGH
, RTM_GETRULE
, RTM_GETADDRLABEL
), -EINVAL
);
99 SET_FLAG(m
->hdr
->nlmsg_flags
, NLM_F_DUMP
, dump
);
104 sd_netlink_message
*sd_netlink_message_ref(sd_netlink_message
*m
) {
108 assert_se(REFCNT_INC(m
->n_ref
) >= 2);
112 sd_netlink_message
*sd_netlink_message_unref(sd_netlink_message
*m
) {
113 sd_netlink_message
*t
;
115 while (m
&& REFCNT_DEC(m
->n_ref
) == 0) {
120 for (i
= 0; i
<= m
->n_containers
; i
++)
121 free(m
->containers
[i
].attributes
);
131 int sd_netlink_message_get_type(sd_netlink_message
*m
, uint16_t *type
) {
132 assert_return(m
, -EINVAL
);
133 assert_return(type
, -EINVAL
);
135 *type
= m
->hdr
->nlmsg_type
;
140 int sd_netlink_message_set_flags(sd_netlink_message
*m
, uint16_t flags
) {
141 assert_return(m
, -EINVAL
);
142 assert_return(flags
, -EINVAL
);
144 m
->hdr
->nlmsg_flags
= flags
;
149 int sd_netlink_message_is_broadcast(sd_netlink_message
*m
) {
150 assert_return(m
, -EINVAL
);
155 /* If successful the updated message will be correctly aligned, if
156 unsuccessful the old message is untouched. */
157 static int add_rtattr(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t data_length
) {
159 size_t message_length
, padding_length
;
160 struct nlmsghdr
*new_hdr
;
169 assert(NLMSG_ALIGN(m
->hdr
->nlmsg_len
) == m
->hdr
->nlmsg_len
);
170 assert(!data
|| data_length
);
172 /* get offset of the new attribute */
173 offset
= m
->hdr
->nlmsg_len
;
175 /* get the size of the new rta attribute (with padding at the end) */
176 rta_length
= RTA_LENGTH(data_length
);
178 /* get the new message size (with padding at the end) */
179 message_length
= offset
+ RTA_ALIGN(rta_length
);
181 /* buffer should be smaller than both one page or 8K to be accepted by the kernel */
182 if (message_length
> MIN(page_size(), 8192UL))
185 /* realloc to fit the new attribute */
186 new_hdr
= realloc(m
->hdr
, message_length
);
191 /* get pointer to the attribute we are about to add */
192 rta
= (struct rtattr
*) ((uint8_t *) m
->hdr
+ offset
);
194 /* if we are inside containers, extend them */
195 for (i
= 0; i
< m
->n_containers
; i
++)
196 GET_CONTAINER(m
, i
)->rta_len
+= message_length
- offset
;
198 /* fill in the attribute */
199 rta
->rta_type
= type
;
200 rta
->rta_len
= rta_length
;
202 /* we don't deal with the case where the user lies about the type
203 * and gives us too little data (so don't do that)
205 padding
= mempcpy(RTA_DATA(rta
), data
, data_length
);
208 /* if no data was passed, make sure we still initialize the padding
209 note that we can have data_length > 0 (used by some containers) */
210 padding
= RTA_DATA(rta
);
212 /* make sure also the padding at the end of the message is initialized */
213 padding_length
= (uint8_t*)m
->hdr
+ message_length
- (uint8_t*)padding
;
214 memzero(padding
, padding_length
);
216 /* update message size */
217 m
->hdr
->nlmsg_len
= message_length
;
222 static int message_attribute_has_type(sd_netlink_message
*m
, size_t *out_size
, uint16_t attribute_type
, uint16_t data_type
) {
228 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
, &type
, attribute_type
);
232 if (type_get_type(type
) != data_type
)
236 *out_size
= type_get_size(type
);
240 int sd_netlink_message_append_string(sd_netlink_message
*m
, unsigned short type
, const char *data
) {
244 assert_return(m
, -EINVAL
);
245 assert_return(!m
->sealed
, -EPERM
);
246 assert_return(data
, -EINVAL
);
248 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_STRING
);
253 length
= strnlen(data
, size
+1);
257 length
= strlen(data
);
259 r
= add_rtattr(m
, type
, data
, length
+ 1);
266 int sd_netlink_message_append_flag(sd_netlink_message
*m
, unsigned short type
) {
270 assert_return(m
, -EINVAL
);
271 assert_return(!m
->sealed
, -EPERM
);
273 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_FLAG
);
277 r
= add_rtattr(m
, type
, NULL
, 0);
284 int sd_netlink_message_append_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t data
) {
287 assert_return(m
, -EINVAL
);
288 assert_return(!m
->sealed
, -EPERM
);
290 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
294 r
= add_rtattr(m
, type
, &data
, sizeof(uint8_t));
302 int sd_netlink_message_append_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t data
) {
305 assert_return(m
, -EINVAL
);
306 assert_return(!m
->sealed
, -EPERM
);
308 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
312 r
= add_rtattr(m
, type
, &data
, sizeof(uint16_t));
319 int sd_netlink_message_append_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t data
) {
322 assert_return(m
, -EINVAL
);
323 assert_return(!m
->sealed
, -EPERM
);
325 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
329 r
= add_rtattr(m
, type
, &data
, sizeof(uint32_t));
336 int sd_netlink_message_append_data(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t len
) {
339 assert_return(m
, -EINVAL
);
340 assert_return(!m
->sealed
, -EPERM
);
342 r
= add_rtattr(m
, type
, data
, len
);
349 int sd_netlink_message_append_in_addr(sd_netlink_message
*m
, unsigned short type
, const struct in_addr
*data
) {
352 assert_return(m
, -EINVAL
);
353 assert_return(!m
->sealed
, -EPERM
);
354 assert_return(data
, -EINVAL
);
356 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
360 r
= add_rtattr(m
, type
, data
, sizeof(struct in_addr
));
367 int sd_netlink_message_append_in6_addr(sd_netlink_message
*m
, unsigned short type
, const struct in6_addr
*data
) {
370 assert_return(m
, -EINVAL
);
371 assert_return(!m
->sealed
, -EPERM
);
372 assert_return(data
, -EINVAL
);
374 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
378 r
= add_rtattr(m
, type
, data
, sizeof(struct in6_addr
));
385 int sd_netlink_message_append_ether_addr(sd_netlink_message
*m
, unsigned short type
, const struct ether_addr
*data
) {
388 assert_return(m
, -EINVAL
);
389 assert_return(!m
->sealed
, -EPERM
);
390 assert_return(data
, -EINVAL
);
392 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
396 r
= add_rtattr(m
, type
, data
, ETH_ALEN
);
403 int sd_netlink_message_append_cache_info(sd_netlink_message
*m
, unsigned short type
, const struct ifa_cacheinfo
*info
) {
406 assert_return(m
, -EINVAL
);
407 assert_return(!m
->sealed
, -EPERM
);
408 assert_return(info
, -EINVAL
);
410 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
414 r
= add_rtattr(m
, type
, info
, sizeof(struct ifa_cacheinfo
));
421 int sd_netlink_message_open_container(sd_netlink_message
*m
, unsigned short type
) {
425 assert_return(m
, -EINVAL
);
426 assert_return(!m
->sealed
, -EPERM
);
427 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -ERANGE
);
429 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_NESTED
);
431 const NLTypeSystemUnion
*type_system_union
;
434 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_UNION
);
438 r
= sd_rtnl_message_get_family(m
, &family
);
442 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
446 r
= type_system_union_protocol_get_type_system(type_system_union
,
447 &m
->containers
[m
->n_containers
+ 1].type_system
,
452 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
453 &m
->containers
[m
->n_containers
+ 1].type_system
,
459 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, size
);
463 m
->containers
[m
->n_containers
++].offset
= r
;
468 int sd_netlink_message_open_container_union(sd_netlink_message
*m
, unsigned short type
, const char *key
) {
469 const NLTypeSystemUnion
*type_system_union
;
472 assert_return(m
, -EINVAL
);
473 assert_return(!m
->sealed
, -EPERM
);
475 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
479 r
= type_system_union_get_type_system(type_system_union
,
480 &m
->containers
[m
->n_containers
+ 1].type_system
,
485 r
= sd_netlink_message_append_string(m
, type_system_union
->match
, key
);
489 /* do we ever need non-null size */
490 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, 0);
494 m
->containers
[m
->n_containers
++].offset
= r
;
499 int sd_netlink_message_close_container(sd_netlink_message
*m
) {
500 assert_return(m
, -EINVAL
);
501 assert_return(!m
->sealed
, -EPERM
);
502 assert_return(m
->n_containers
> 0, -EINVAL
);
504 m
->containers
[m
->n_containers
].type_system
= NULL
;
505 m
->containers
[m
->n_containers
].offset
= 0;
511 int sd_netlink_message_open_array(sd_netlink_message
*m
, uint16_t type
) {
514 assert_return(m
, -EINVAL
);
515 assert_return(!m
->sealed
, -EPERM
);
516 assert_return(m
->n_containers
> 0, -EINVAL
);
518 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, 0);
522 m
->containers
[m
->n_containers
].offset
= r
;
524 m
->containers
[m
->n_containers
].type_system
= m
->containers
[m
->n_containers
- 1].type_system
;
529 int sd_netlink_message_cancel_array(sd_netlink_message
*m
) {
533 assert_return(m
, -EINVAL
);
534 assert_return(!m
->sealed
, -EPERM
);
535 assert_return(m
->n_containers
> 1, -EINVAL
);
537 rta_len
= GET_CONTAINER(m
, (m
->n_containers
- 1))->rta_len
;
539 for (i
= 0; i
< m
->n_containers
; i
++)
540 GET_CONTAINER(m
, i
)->rta_len
-= rta_len
;
542 m
->hdr
->nlmsg_len
-= rta_len
;
545 m
->containers
[m
->n_containers
].type_system
= NULL
;
550 static int netlink_message_read_internal(sd_netlink_message
*m
, unsigned short type
, void **data
, bool *net_byteorder
) {
551 struct netlink_attribute
*attribute
;
554 assert_return(m
, -EINVAL
);
555 assert_return(m
->sealed
, -EPERM
);
556 assert_return(data
, -EINVAL
);
558 assert(m
->n_containers
< RTNL_CONTAINER_DEPTH
);
559 assert(m
->containers
[m
->n_containers
].attributes
);
560 assert(type
< m
->containers
[m
->n_containers
].n_attributes
);
562 attribute
= &m
->containers
[m
->n_containers
].attributes
[type
];
564 if (attribute
->offset
== 0)
567 rta
= (struct rtattr
*)((uint8_t *) m
->hdr
+ attribute
->offset
);
569 *data
= RTA_DATA(rta
);
572 *net_byteorder
= attribute
->net_byteorder
;
574 return RTA_PAYLOAD(rta
);
577 int sd_netlink_message_read_string(sd_netlink_message
*m
, unsigned short type
, const char **data
) {
581 assert_return(m
, -EINVAL
);
583 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_STRING
);
587 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
590 else if (strnlen(attr_data
, r
) >= (size_t) r
)
594 *data
= (const char *) attr_data
;
599 int sd_netlink_message_read_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t *data
) {
603 assert_return(m
, -EINVAL
);
605 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
609 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
612 else if ((size_t) r
< sizeof(uint8_t))
616 *data
= *(uint8_t *) attr_data
;
621 int sd_netlink_message_read_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t *data
) {
626 assert_return(m
, -EINVAL
);
628 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
632 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
635 else if ((size_t) r
< sizeof(uint16_t))
640 *data
= be16toh(*(uint16_t *) attr_data
);
642 *data
= *(uint16_t *) attr_data
;
648 int sd_netlink_message_read_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t *data
) {
653 assert_return(m
, -EINVAL
);
655 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
659 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
662 else if ((size_t)r
< sizeof(uint32_t))
667 *data
= be32toh(*(uint32_t *) attr_data
);
669 *data
= *(uint32_t *) attr_data
;
675 int sd_netlink_message_read_ether_addr(sd_netlink_message
*m
, unsigned short type
, struct ether_addr
*data
) {
679 assert_return(m
, -EINVAL
);
681 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
685 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
688 else if ((size_t)r
< sizeof(struct ether_addr
))
692 memcpy(data
, attr_data
, sizeof(struct ether_addr
));
697 int sd_netlink_message_read_cache_info(sd_netlink_message
*m
, unsigned short type
, struct ifa_cacheinfo
*info
) {
701 assert_return(m
, -EINVAL
);
703 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
707 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
710 else if ((size_t)r
< sizeof(struct ifa_cacheinfo
))
714 memcpy(info
, attr_data
, sizeof(struct ifa_cacheinfo
));
719 int sd_netlink_message_read_in_addr(sd_netlink_message
*m
, unsigned short type
, struct in_addr
*data
) {
723 assert_return(m
, -EINVAL
);
725 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
729 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
732 else if ((size_t)r
< sizeof(struct in_addr
))
736 memcpy(data
, attr_data
, sizeof(struct in_addr
));
741 int sd_netlink_message_read_in6_addr(sd_netlink_message
*m
, unsigned short type
, struct in6_addr
*data
) {
745 assert_return(m
, -EINVAL
);
747 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
751 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
754 else if ((size_t)r
< sizeof(struct in6_addr
))
758 memcpy(data
, attr_data
, sizeof(struct in6_addr
));
763 static int netlink_container_parse(sd_netlink_message
*m
,
764 struct netlink_container
*container
,
767 unsigned int rt_len
) {
768 _cleanup_free_
struct netlink_attribute
*attributes
= NULL
;
770 attributes
= new0(struct netlink_attribute
, count
);
774 for (; RTA_OK(rta
, rt_len
); rta
= RTA_NEXT(rta
, rt_len
)) {
777 type
= RTA_TYPE(rta
);
779 /* if the kernel is newer than the headers we used
780 when building, we ignore out-of-range attributes */
784 if (attributes
[type
].offset
!= 0)
785 log_debug("rtnl: message parse - overwriting repeated attribute");
787 attributes
[type
].offset
= (uint8_t *) rta
- (uint8_t *) m
->hdr
;
788 attributes
[type
].nested
= RTA_FLAGS(rta
) & NLA_F_NESTED
;
789 attributes
[type
].net_byteorder
= RTA_FLAGS(rta
) & NLA_F_NET_BYTEORDER
;
792 container
->attributes
= TAKE_PTR(attributes
);
793 container
->n_attributes
= count
;
798 int sd_netlink_message_enter_container(sd_netlink_message
*m
, unsigned short type_id
) {
799 const NLType
*nl_type
;
800 const NLTypeSystem
*type_system
;
806 assert_return(m
, -EINVAL
);
807 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -EINVAL
);
809 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
,
815 type
= type_get_type(nl_type
);
817 if (type
== NETLINK_TYPE_NESTED
) {
818 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
823 } else if (type
== NETLINK_TYPE_UNION
) {
824 const NLTypeSystemUnion
*type_system_union
;
826 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
,
832 switch (type_system_union
->match_type
) {
833 case NL_MATCH_SIBLING
:
837 r
= sd_netlink_message_read_string(m
, type_system_union
->match
, &key
);
841 r
= type_system_union_get_type_system(type_system_union
,
849 case NL_MATCH_PROTOCOL
:
853 r
= sd_rtnl_message_get_family(m
, &family
);
857 r
= type_system_union_protocol_get_type_system(type_system_union
,
866 assert_not_reached("sd-netlink: invalid type system union type");
871 r
= netlink_message_read_internal(m
, type_id
, &container
, NULL
);
879 r
= netlink_container_parse(m
,
880 &m
->containers
[m
->n_containers
],
881 type_system_get_count(type_system
),
889 m
->containers
[m
->n_containers
].type_system
= type_system
;
894 int sd_netlink_message_exit_container(sd_netlink_message
*m
) {
895 assert_return(m
, -EINVAL
);
896 assert_return(m
->sealed
, -EINVAL
);
897 assert_return(m
->n_containers
> 0, -EINVAL
);
899 m
->containers
[m
->n_containers
].attributes
= mfree(m
->containers
[m
->n_containers
].attributes
);
900 m
->containers
[m
->n_containers
].type_system
= NULL
;
907 uint32_t rtnl_message_get_serial(sd_netlink_message
*m
) {
911 return m
->hdr
->nlmsg_seq
;
914 int sd_netlink_message_is_error(sd_netlink_message
*m
) {
916 assert_return(m
->hdr
, 0);
918 return m
->hdr
->nlmsg_type
== NLMSG_ERROR
;
921 int sd_netlink_message_get_errno(sd_netlink_message
*m
) {
922 struct nlmsgerr
*err
;
924 assert_return(m
, -EINVAL
);
925 assert_return(m
->hdr
, -EINVAL
);
927 if (!sd_netlink_message_is_error(m
))
930 err
= NLMSG_DATA(m
->hdr
);
935 int sd_netlink_message_rewind(sd_netlink_message
*m
) {
936 const NLType
*nl_type
;
937 const NLTypeSystem
*type_system_root
;
943 assert_return(m
, -EINVAL
);
945 /* don't allow appending to message once parsed */
947 rtnl_message_seal(m
);
949 type_system_root
= type_system_get_root(m
->protocol
);
951 for (i
= 1; i
<= m
->n_containers
; i
++)
952 m
->containers
[i
].attributes
= mfree(m
->containers
[i
].attributes
);
956 if (m
->containers
[0].attributes
)
957 /* top-level attributes have already been parsed */
962 r
= type_system_get_type(type_system_root
, &nl_type
, m
->hdr
->nlmsg_type
);
966 type
= type_get_type(nl_type
);
967 size
= type_get_size(nl_type
);
969 if (type
== NETLINK_TYPE_NESTED
) {
970 const NLTypeSystem
*type_system
;
972 type_get_type_system(nl_type
, &type_system
);
974 m
->containers
[0].type_system
= type_system
;
976 r
= netlink_container_parse(m
,
977 &m
->containers
[m
->n_containers
],
978 type_system_get_count(type_system
),
979 (struct rtattr
*)((uint8_t*)NLMSG_DATA(m
->hdr
) + NLMSG_ALIGN(size
)),
980 NLMSG_PAYLOAD(m
->hdr
, size
));
988 void rtnl_message_seal(sd_netlink_message
*m
) {
995 sd_netlink_message
*sd_netlink_message_next(sd_netlink_message
*m
) {
996 assert_return(m
, NULL
);