1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include <netinet/in.h>
7 #include "sd-netlink.h"
9 #include "alloc-util.h"
10 #include "format-util.h"
12 #include "netlink-internal.h"
13 #include "netlink-types.h"
14 #include "netlink-util.h"
16 #include "socket-util.h"
19 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL)
20 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
22 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
23 #define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
25 int message_new_empty(sd_netlink
*rtnl
, sd_netlink_message
**ret
) {
26 sd_netlink_message
*m
;
28 assert_return(ret
, -EINVAL
);
30 /* Note that 'rtnl' is currently unused, if we start using it internally
31 we must take care to avoid problems due to mutual references between
32 buses and their queued messages. See sd-bus.
35 m
= new0(sd_netlink_message
, 1);
39 m
->n_ref
= REFCNT_INIT
;
40 m
->protocol
= rtnl
->protocol
;
48 int message_new(sd_netlink
*rtnl
, sd_netlink_message
**ret
, uint16_t type
) {
49 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
50 const NLType
*nl_type
;
51 const NLTypeSystem
*type_system_root
;
55 assert_return(rtnl
, -EINVAL
);
57 type_system_root
= type_system_get_root(rtnl
->protocol
);
59 r
= type_system_get_type(type_system_root
, &nl_type
, type
);
63 if (type_get_type(nl_type
) != NETLINK_TYPE_NESTED
)
66 r
= message_new_empty(rtnl
, &m
);
70 size
= NLMSG_SPACE(type_get_size(nl_type
));
72 assert(size
>= sizeof(struct nlmsghdr
));
73 m
->hdr
= malloc0(size
);
77 m
->hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
79 type_get_type_system(nl_type
, &m
->containers
[0].type_system
);
80 m
->hdr
->nlmsg_len
= size
;
81 m
->hdr
->nlmsg_type
= type
;
88 int sd_netlink_message_request_dump(sd_netlink_message
*m
, int dump
) {
89 assert_return(m
, -EINVAL
);
90 assert_return(m
->hdr
, -EINVAL
);
92 assert_return(IN_SET(m
->hdr
->nlmsg_type
, RTM_GETLINK
, RTM_GETADDR
, RTM_GETROUTE
, RTM_GETNEIGH
, RTM_GETRULE
, RTM_GETADDRLABEL
), -EINVAL
);
94 SET_FLAG(m
->hdr
->nlmsg_flags
, NLM_F_DUMP
, dump
);
99 DEFINE_ATOMIC_REF_FUNC(sd_netlink_message
, sd_netlink_message
);
101 sd_netlink_message
*sd_netlink_message_unref(sd_netlink_message
*m
) {
102 sd_netlink_message
*t
;
104 while (m
&& REFCNT_DEC(m
->n_ref
) == 0) {
109 for (i
= 0; i
<= m
->n_containers
; i
++)
110 free(m
->containers
[i
].attributes
);
120 int sd_netlink_message_get_type(sd_netlink_message
*m
, uint16_t *type
) {
121 assert_return(m
, -EINVAL
);
122 assert_return(type
, -EINVAL
);
124 *type
= m
->hdr
->nlmsg_type
;
129 int sd_netlink_message_set_flags(sd_netlink_message
*m
, uint16_t flags
) {
130 assert_return(m
, -EINVAL
);
131 assert_return(flags
, -EINVAL
);
133 m
->hdr
->nlmsg_flags
= flags
;
138 int sd_netlink_message_is_broadcast(sd_netlink_message
*m
) {
139 assert_return(m
, -EINVAL
);
144 /* If successful the updated message will be correctly aligned, if
145 unsuccessful the old message is untouched. */
146 static int add_rtattr(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t data_length
) {
148 size_t message_length
, padding_length
;
149 struct nlmsghdr
*new_hdr
;
158 assert(NLMSG_ALIGN(m
->hdr
->nlmsg_len
) == m
->hdr
->nlmsg_len
);
159 assert(!data
|| data_length
);
161 /* get offset of the new attribute */
162 offset
= m
->hdr
->nlmsg_len
;
164 /* get the size of the new rta attribute (with padding at the end) */
165 rta_length
= RTA_LENGTH(data_length
);
167 /* get the new message size (with padding at the end) */
168 message_length
= offset
+ RTA_ALIGN(rta_length
);
170 /* buffer should be smaller than both one page or 8K to be accepted by the kernel */
171 if (message_length
> MIN(page_size(), 8192UL))
174 /* realloc to fit the new attribute */
175 new_hdr
= realloc(m
->hdr
, message_length
);
180 /* get pointer to the attribute we are about to add */
181 rta
= (struct rtattr
*) ((uint8_t *) m
->hdr
+ offset
);
183 /* if we are inside containers, extend them */
184 for (i
= 0; i
< m
->n_containers
; i
++)
185 GET_CONTAINER(m
, i
)->rta_len
+= message_length
- offset
;
187 /* fill in the attribute */
188 rta
->rta_type
= type
;
189 rta
->rta_len
= rta_length
;
191 /* we don't deal with the case where the user lies about the type
192 * and gives us too little data (so don't do that)
194 padding
= mempcpy(RTA_DATA(rta
), data
, data_length
);
197 /* if no data was passed, make sure we still initialize the padding
198 note that we can have data_length > 0 (used by some containers) */
199 padding
= RTA_DATA(rta
);
201 /* make sure also the padding at the end of the message is initialized */
202 padding_length
= (uint8_t*)m
->hdr
+ message_length
- (uint8_t*)padding
;
203 memzero(padding
, padding_length
);
205 /* update message size */
206 m
->hdr
->nlmsg_len
= message_length
;
211 static int message_attribute_has_type(sd_netlink_message
*m
, size_t *out_size
, uint16_t attribute_type
, uint16_t data_type
) {
217 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
, &type
, attribute_type
);
221 if (type_get_type(type
) != data_type
)
225 *out_size
= type_get_size(type
);
229 int sd_netlink_message_append_string(sd_netlink_message
*m
, unsigned short type
, const char *data
) {
233 assert_return(m
, -EINVAL
);
234 assert_return(!m
->sealed
, -EPERM
);
235 assert_return(data
, -EINVAL
);
237 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_STRING
);
242 length
= strnlen(data
, size
+1);
246 length
= strlen(data
);
248 r
= add_rtattr(m
, type
, data
, length
+ 1);
255 int sd_netlink_message_append_flag(sd_netlink_message
*m
, unsigned short type
) {
259 assert_return(m
, -EINVAL
);
260 assert_return(!m
->sealed
, -EPERM
);
262 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_FLAG
);
266 r
= add_rtattr(m
, type
, NULL
, 0);
273 int sd_netlink_message_append_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t data
) {
276 assert_return(m
, -EINVAL
);
277 assert_return(!m
->sealed
, -EPERM
);
279 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
283 r
= add_rtattr(m
, type
, &data
, sizeof(uint8_t));
290 int sd_netlink_message_append_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t data
) {
293 assert_return(m
, -EINVAL
);
294 assert_return(!m
->sealed
, -EPERM
);
296 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
300 r
= add_rtattr(m
, type
, &data
, sizeof(uint16_t));
307 int sd_netlink_message_append_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t data
) {
310 assert_return(m
, -EINVAL
);
311 assert_return(!m
->sealed
, -EPERM
);
313 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
317 r
= add_rtattr(m
, type
, &data
, sizeof(uint32_t));
324 int sd_netlink_message_append_data(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t len
) {
327 assert_return(m
, -EINVAL
);
328 assert_return(!m
->sealed
, -EPERM
);
330 r
= add_rtattr(m
, type
, data
, len
);
337 int sd_netlink_message_append_in_addr(sd_netlink_message
*m
, unsigned short type
, const struct in_addr
*data
) {
340 assert_return(m
, -EINVAL
);
341 assert_return(!m
->sealed
, -EPERM
);
342 assert_return(data
, -EINVAL
);
344 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
348 r
= add_rtattr(m
, type
, data
, sizeof(struct in_addr
));
355 int sd_netlink_message_append_in6_addr(sd_netlink_message
*m
, unsigned short type
, const struct in6_addr
*data
) {
358 assert_return(m
, -EINVAL
);
359 assert_return(!m
->sealed
, -EPERM
);
360 assert_return(data
, -EINVAL
);
362 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
366 r
= add_rtattr(m
, type
, data
, sizeof(struct in6_addr
));
373 int sd_netlink_message_append_ether_addr(sd_netlink_message
*m
, unsigned short type
, const struct ether_addr
*data
) {
376 assert_return(m
, -EINVAL
);
377 assert_return(!m
->sealed
, -EPERM
);
378 assert_return(data
, -EINVAL
);
380 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
384 r
= add_rtattr(m
, type
, data
, ETH_ALEN
);
391 int sd_netlink_message_append_cache_info(sd_netlink_message
*m
, unsigned short type
, const struct ifa_cacheinfo
*info
) {
394 assert_return(m
, -EINVAL
);
395 assert_return(!m
->sealed
, -EPERM
);
396 assert_return(info
, -EINVAL
);
398 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
402 r
= add_rtattr(m
, type
, info
, sizeof(struct ifa_cacheinfo
));
409 int sd_netlink_message_open_container(sd_netlink_message
*m
, unsigned short type
) {
413 assert_return(m
, -EINVAL
);
414 assert_return(!m
->sealed
, -EPERM
);
415 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -ERANGE
);
417 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_NESTED
);
419 const NLTypeSystemUnion
*type_system_union
;
422 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_UNION
);
426 r
= sd_rtnl_message_get_family(m
, &family
);
430 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
434 r
= type_system_union_protocol_get_type_system(type_system_union
,
435 &m
->containers
[m
->n_containers
+ 1].type_system
,
440 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
441 &m
->containers
[m
->n_containers
+ 1].type_system
,
447 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, size
);
451 m
->containers
[m
->n_containers
++].offset
= r
;
456 int sd_netlink_message_open_container_union(sd_netlink_message
*m
, unsigned short type
, const char *key
) {
457 const NLTypeSystemUnion
*type_system_union
;
460 assert_return(m
, -EINVAL
);
461 assert_return(!m
->sealed
, -EPERM
);
463 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
467 r
= type_system_union_get_type_system(type_system_union
,
468 &m
->containers
[m
->n_containers
+ 1].type_system
,
473 r
= sd_netlink_message_append_string(m
, type_system_union
->match
, key
);
477 /* do we ever need non-null size */
478 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, 0);
482 m
->containers
[m
->n_containers
++].offset
= r
;
487 int sd_netlink_message_close_container(sd_netlink_message
*m
) {
488 assert_return(m
, -EINVAL
);
489 assert_return(!m
->sealed
, -EPERM
);
490 assert_return(m
->n_containers
> 0, -EINVAL
);
492 m
->containers
[m
->n_containers
].type_system
= NULL
;
493 m
->containers
[m
->n_containers
].offset
= 0;
499 int sd_netlink_message_open_array(sd_netlink_message
*m
, uint16_t type
) {
502 assert_return(m
, -EINVAL
);
503 assert_return(!m
->sealed
, -EPERM
);
504 assert_return(m
->n_containers
> 0, -EINVAL
);
506 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, 0);
510 m
->containers
[m
->n_containers
].offset
= r
;
512 m
->containers
[m
->n_containers
].type_system
= m
->containers
[m
->n_containers
- 1].type_system
;
517 int sd_netlink_message_cancel_array(sd_netlink_message
*m
) {
521 assert_return(m
, -EINVAL
);
522 assert_return(!m
->sealed
, -EPERM
);
523 assert_return(m
->n_containers
> 1, -EINVAL
);
525 rta_len
= GET_CONTAINER(m
, (m
->n_containers
- 1))->rta_len
;
527 for (i
= 0; i
< m
->n_containers
; i
++)
528 GET_CONTAINER(m
, i
)->rta_len
-= rta_len
;
530 m
->hdr
->nlmsg_len
-= rta_len
;
533 m
->containers
[m
->n_containers
].type_system
= NULL
;
538 static int netlink_message_read_internal(sd_netlink_message
*m
, unsigned short type
, void **data
, bool *net_byteorder
) {
539 struct netlink_attribute
*attribute
;
542 assert_return(m
, -EINVAL
);
543 assert_return(m
->sealed
, -EPERM
);
544 assert_return(data
, -EINVAL
);
546 assert(m
->n_containers
< RTNL_CONTAINER_DEPTH
);
547 assert(m
->containers
[m
->n_containers
].attributes
);
548 assert(type
< m
->containers
[m
->n_containers
].n_attributes
);
550 attribute
= &m
->containers
[m
->n_containers
].attributes
[type
];
552 if (attribute
->offset
== 0)
555 rta
= (struct rtattr
*)((uint8_t *) m
->hdr
+ attribute
->offset
);
557 *data
= RTA_DATA(rta
);
560 *net_byteorder
= attribute
->net_byteorder
;
562 return RTA_PAYLOAD(rta
);
565 int sd_netlink_message_read_string(sd_netlink_message
*m
, unsigned short type
, const char **data
) {
569 assert_return(m
, -EINVAL
);
571 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_STRING
);
575 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
578 else if (strnlen(attr_data
, r
) >= (size_t) r
)
582 *data
= (const char *) attr_data
;
587 int sd_netlink_message_read_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t *data
) {
591 assert_return(m
, -EINVAL
);
593 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
597 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
600 else if ((size_t) r
< sizeof(uint8_t))
604 *data
= *(uint8_t *) attr_data
;
609 int sd_netlink_message_read_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t *data
) {
614 assert_return(m
, -EINVAL
);
616 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
620 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
623 else if ((size_t) r
< sizeof(uint16_t))
628 *data
= be16toh(*(uint16_t *) attr_data
);
630 *data
= *(uint16_t *) attr_data
;
636 int sd_netlink_message_read_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t *data
) {
641 assert_return(m
, -EINVAL
);
643 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
647 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
650 else if ((size_t)r
< sizeof(uint32_t))
655 *data
= be32toh(*(uint32_t *) attr_data
);
657 *data
= *(uint32_t *) attr_data
;
663 int sd_netlink_message_read_ether_addr(sd_netlink_message
*m
, unsigned short type
, struct ether_addr
*data
) {
667 assert_return(m
, -EINVAL
);
669 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
673 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
676 else if ((size_t)r
< sizeof(struct ether_addr
))
680 memcpy(data
, attr_data
, sizeof(struct ether_addr
));
685 int sd_netlink_message_read_cache_info(sd_netlink_message
*m
, unsigned short type
, struct ifa_cacheinfo
*info
) {
689 assert_return(m
, -EINVAL
);
691 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
695 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
698 else if ((size_t)r
< sizeof(struct ifa_cacheinfo
))
702 memcpy(info
, attr_data
, sizeof(struct ifa_cacheinfo
));
707 int sd_netlink_message_read_in_addr(sd_netlink_message
*m
, unsigned short type
, struct in_addr
*data
) {
711 assert_return(m
, -EINVAL
);
713 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
717 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
720 else if ((size_t)r
< sizeof(struct in_addr
))
724 memcpy(data
, attr_data
, sizeof(struct in_addr
));
729 int sd_netlink_message_read_in6_addr(sd_netlink_message
*m
, unsigned short type
, struct in6_addr
*data
) {
733 assert_return(m
, -EINVAL
);
735 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
739 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
742 else if ((size_t)r
< sizeof(struct in6_addr
))
746 memcpy(data
, attr_data
, sizeof(struct in6_addr
));
751 static int netlink_container_parse(sd_netlink_message
*m
,
752 struct netlink_container
*container
,
756 _cleanup_free_
struct netlink_attribute
*attributes
= NULL
;
758 attributes
= new0(struct netlink_attribute
, count
);
762 for (; RTA_OK(rta
, rt_len
); rta
= RTA_NEXT(rta
, rt_len
)) {
765 type
= RTA_TYPE(rta
);
767 /* if the kernel is newer than the headers we used
768 when building, we ignore out-of-range attributes */
772 if (attributes
[type
].offset
!= 0)
773 log_debug("rtnl: message parse - overwriting repeated attribute");
775 attributes
[type
].offset
= (uint8_t *) rta
- (uint8_t *) m
->hdr
;
776 attributes
[type
].nested
= RTA_FLAGS(rta
) & NLA_F_NESTED
;
777 attributes
[type
].net_byteorder
= RTA_FLAGS(rta
) & NLA_F_NET_BYTEORDER
;
780 container
->attributes
= TAKE_PTR(attributes
);
781 container
->n_attributes
= count
;
786 int sd_netlink_message_enter_container(sd_netlink_message
*m
, unsigned short type_id
) {
787 const NLType
*nl_type
;
788 const NLTypeSystem
*type_system
;
794 assert_return(m
, -EINVAL
);
795 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -EINVAL
);
797 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
,
803 type
= type_get_type(nl_type
);
805 if (type
== NETLINK_TYPE_NESTED
) {
806 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
811 } else if (type
== NETLINK_TYPE_UNION
) {
812 const NLTypeSystemUnion
*type_system_union
;
814 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
,
820 switch (type_system_union
->match_type
) {
821 case NL_MATCH_SIBLING
:
825 r
= sd_netlink_message_read_string(m
, type_system_union
->match
, &key
);
829 r
= type_system_union_get_type_system(type_system_union
,
837 case NL_MATCH_PROTOCOL
:
841 r
= sd_rtnl_message_get_family(m
, &family
);
845 r
= type_system_union_protocol_get_type_system(type_system_union
,
854 assert_not_reached("sd-netlink: invalid type system union type");
859 r
= netlink_message_read_internal(m
, type_id
, &container
, NULL
);
867 r
= netlink_container_parse(m
,
868 &m
->containers
[m
->n_containers
],
869 type_system_get_count(type_system
),
877 m
->containers
[m
->n_containers
].type_system
= type_system
;
882 int sd_netlink_message_exit_container(sd_netlink_message
*m
) {
883 assert_return(m
, -EINVAL
);
884 assert_return(m
->sealed
, -EINVAL
);
885 assert_return(m
->n_containers
> 0, -EINVAL
);
887 m
->containers
[m
->n_containers
].attributes
= mfree(m
->containers
[m
->n_containers
].attributes
);
888 m
->containers
[m
->n_containers
].type_system
= NULL
;
895 uint32_t rtnl_message_get_serial(sd_netlink_message
*m
) {
899 return m
->hdr
->nlmsg_seq
;
902 int sd_netlink_message_is_error(sd_netlink_message
*m
) {
904 assert_return(m
->hdr
, 0);
906 return m
->hdr
->nlmsg_type
== NLMSG_ERROR
;
909 int sd_netlink_message_get_errno(sd_netlink_message
*m
) {
910 struct nlmsgerr
*err
;
912 assert_return(m
, -EINVAL
);
913 assert_return(m
->hdr
, -EINVAL
);
915 if (!sd_netlink_message_is_error(m
))
918 err
= NLMSG_DATA(m
->hdr
);
923 int sd_netlink_message_rewind(sd_netlink_message
*m
) {
924 const NLType
*nl_type
;
925 const NLTypeSystem
*type_system_root
;
931 assert_return(m
, -EINVAL
);
933 /* don't allow appending to message once parsed */
935 rtnl_message_seal(m
);
937 type_system_root
= type_system_get_root(m
->protocol
);
939 for (i
= 1; i
<= m
->n_containers
; i
++)
940 m
->containers
[i
].attributes
= mfree(m
->containers
[i
].attributes
);
944 if (m
->containers
[0].attributes
)
945 /* top-level attributes have already been parsed */
950 r
= type_system_get_type(type_system_root
, &nl_type
, m
->hdr
->nlmsg_type
);
954 type
= type_get_type(nl_type
);
955 size
= type_get_size(nl_type
);
957 if (type
== NETLINK_TYPE_NESTED
) {
958 const NLTypeSystem
*type_system
;
960 type_get_type_system(nl_type
, &type_system
);
962 m
->containers
[0].type_system
= type_system
;
964 r
= netlink_container_parse(m
,
965 &m
->containers
[m
->n_containers
],
966 type_system_get_count(type_system
),
967 (struct rtattr
*)((uint8_t*)NLMSG_DATA(m
->hdr
) + NLMSG_ALIGN(size
)),
968 NLMSG_PAYLOAD(m
->hdr
, size
));
976 void rtnl_message_seal(sd_netlink_message
*m
) {
983 sd_netlink_message
*sd_netlink_message_next(sd_netlink_message
*m
) {
984 assert_return(m
, NULL
);