1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <netinet/in.h>
7 #include "sd-netlink.h"
9 #include "alloc-util.h"
10 #include "format-util.h"
11 #include "memory-util.h"
12 #include "netlink-internal.h"
13 #include "netlink-types.h"
14 #include "netlink-util.h"
15 #include "socket-util.h"
18 #define GET_CONTAINER(m, i) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset))
20 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
21 #define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
23 int message_new_empty(sd_netlink
*rtnl
, sd_netlink_message
**ret
) {
24 sd_netlink_message
*m
;
26 assert_return(ret
, -EINVAL
);
28 /* Note that 'rtnl' is currently unused, if we start using it internally
29 we must take care to avoid problems due to mutual references between
30 buses and their queued messages. See sd-bus.
33 m
= new(sd_netlink_message
, 1);
37 *m
= (sd_netlink_message
) {
39 .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
;
54 assert_return(rtnl
, -EINVAL
);
56 r
= type_system_root_get_type(rtnl
, &nl_type
, type
);
60 if (type_get_type(nl_type
) != NETLINK_TYPE_NESTED
)
63 r
= message_new_empty(rtnl
, &m
);
67 size
= NLMSG_SPACE(type_get_size(nl_type
));
69 assert(size
>= sizeof(struct nlmsghdr
));
70 m
->hdr
= malloc0(size
);
74 m
->hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
76 type_get_type_system(nl_type
, &m
->containers
[0].type_system
);
77 m
->hdr
->nlmsg_len
= size
;
78 m
->hdr
->nlmsg_type
= type
;
85 int sd_netlink_message_request_dump(sd_netlink_message
*m
, int dump
) {
86 assert_return(m
, -EINVAL
);
87 assert_return(m
->hdr
, -EINVAL
);
89 assert_return(IN_SET(m
->hdr
->nlmsg_type
,
90 RTM_GETLINK
, RTM_GETLINKPROP
, RTM_GETADDR
, RTM_GETROUTE
, RTM_GETNEIGH
,
91 RTM_GETRULE
, RTM_GETADDRLABEL
, RTM_GETNEXTHOP
), -EINVAL
);
93 SET_FLAG(m
->hdr
->nlmsg_flags
, NLM_F_DUMP
, dump
);
98 DEFINE_TRIVIAL_REF_FUNC(sd_netlink_message
, sd_netlink_message
);
100 sd_netlink_message
*sd_netlink_message_unref(sd_netlink_message
*m
) {
101 while (m
&& --m
->n_ref
== 0) {
106 for (i
= 0; i
<= m
->n_containers
; i
++)
107 free(m
->containers
[i
].attributes
);
109 sd_netlink_message
*t
= m
;
117 int sd_netlink_message_get_type(sd_netlink_message
*m
, uint16_t *type
) {
118 assert_return(m
, -EINVAL
);
119 assert_return(type
, -EINVAL
);
121 *type
= m
->hdr
->nlmsg_type
;
126 int sd_netlink_message_set_flags(sd_netlink_message
*m
, uint16_t flags
) {
127 assert_return(m
, -EINVAL
);
128 assert_return(flags
, -EINVAL
);
130 m
->hdr
->nlmsg_flags
= flags
;
135 int sd_netlink_message_is_broadcast(sd_netlink_message
*m
) {
136 assert_return(m
, -EINVAL
);
141 /* If successful the updated message will be correctly aligned, if
142 unsuccessful the old message is untouched. */
143 static int add_rtattr(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t data_length
) {
144 size_t message_length
;
145 struct nlmsghdr
*new_hdr
;
152 assert(NLMSG_ALIGN(m
->hdr
->nlmsg_len
) == m
->hdr
->nlmsg_len
);
153 assert(!data
|| data_length
> 0);
155 /* get the new message size (with padding at the end) */
156 message_length
= m
->hdr
->nlmsg_len
+ RTA_SPACE(data_length
);
158 /* buffer should be smaller than both one page or 8K to be accepted by the kernel */
159 if (message_length
> MIN(page_size(), 8192UL))
162 /* realloc to fit the new attribute */
163 new_hdr
= realloc(m
->hdr
, message_length
);
168 /* get pointer to the attribute we are about to add */
169 rta
= (struct rtattr
*) ((uint8_t *) m
->hdr
+ m
->hdr
->nlmsg_len
);
171 rtattr_append_attribute_internal(rta
, type
, data
, data_length
);
173 /* if we are inside containers, extend them */
174 for (unsigned i
= 0; i
< m
->n_containers
; i
++)
175 GET_CONTAINER(m
, i
)->rta_len
+= RTA_SPACE(data_length
);
177 /* update message size */
178 offset
= m
->hdr
->nlmsg_len
;
179 m
->hdr
->nlmsg_len
= message_length
;
181 /* return old message size */
185 static int message_attribute_has_type(sd_netlink_message
*m
, size_t *out_size
, uint16_t attribute_type
, uint16_t data_type
) {
191 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
, &type
, attribute_type
);
195 if (type_get_type(type
) != data_type
)
199 *out_size
= type_get_size(type
);
203 int sd_netlink_message_append_string(sd_netlink_message
*m
, unsigned short type
, const char *data
) {
207 assert_return(m
, -EINVAL
);
208 assert_return(!m
->sealed
, -EPERM
);
209 assert_return(data
, -EINVAL
);
211 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_STRING
);
216 length
= strnlen(data
, size
+1);
220 length
= strlen(data
);
222 r
= add_rtattr(m
, type
, data
, length
+ 1);
229 int sd_netlink_message_append_strv(sd_netlink_message
*m
, unsigned short type
, char * const *data
) {
234 assert_return(m
, -EINVAL
);
235 assert_return(!m
->sealed
, -EPERM
);
236 assert_return(data
, -EINVAL
);
238 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_STRING
);
242 STRV_FOREACH(p
, data
) {
244 length
= strnlen(*p
, size
+1);
250 r
= add_rtattr(m
, type
, *p
, length
+ 1);
258 int sd_netlink_message_append_flag(sd_netlink_message
*m
, unsigned short type
) {
262 assert_return(m
, -EINVAL
);
263 assert_return(!m
->sealed
, -EPERM
);
265 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_FLAG
);
269 r
= add_rtattr(m
, type
, NULL
, 0);
276 int sd_netlink_message_append_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t data
) {
279 assert_return(m
, -EINVAL
);
280 assert_return(!m
->sealed
, -EPERM
);
282 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
286 r
= add_rtattr(m
, type
, &data
, sizeof(uint8_t));
293 int sd_netlink_message_append_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t data
) {
296 assert_return(m
, -EINVAL
);
297 assert_return(!m
->sealed
, -EPERM
);
299 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
303 r
= add_rtattr(m
, type
, &data
, sizeof(uint16_t));
310 int sd_netlink_message_append_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t data
) {
313 assert_return(m
, -EINVAL
);
314 assert_return(!m
->sealed
, -EPERM
);
316 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
320 r
= add_rtattr(m
, type
, &data
, sizeof(uint32_t));
327 int sd_netlink_message_append_u64(sd_netlink_message
*m
, unsigned short type
, uint64_t data
) {
330 assert_return(m
, -EINVAL
);
331 assert_return(!m
->sealed
, -EPERM
);
333 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U64
);
337 r
= add_rtattr(m
, type
, &data
, sizeof(uint64_t));
344 int sd_netlink_message_append_s8(sd_netlink_message
*m
, unsigned short type
, int8_t data
) {
347 assert_return(m
, -EINVAL
);
348 assert_return(!m
->sealed
, -EPERM
);
350 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_S8
);
354 r
= add_rtattr(m
, type
, &data
, sizeof(int8_t));
361 int sd_netlink_message_append_s16(sd_netlink_message
*m
, unsigned short type
, int16_t data
) {
364 assert_return(m
, -EINVAL
);
365 assert_return(!m
->sealed
, -EPERM
);
367 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_S16
);
371 r
= add_rtattr(m
, type
, &data
, sizeof(int16_t));
378 int sd_netlink_message_append_s32(sd_netlink_message
*m
, unsigned short type
, int32_t data
) {
381 assert_return(m
, -EINVAL
);
382 assert_return(!m
->sealed
, -EPERM
);
384 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_S32
);
388 r
= add_rtattr(m
, type
, &data
, sizeof(int32_t));
395 int sd_netlink_message_append_s64(sd_netlink_message
*m
, unsigned short type
, int64_t data
) {
398 assert_return(m
, -EINVAL
);
399 assert_return(!m
->sealed
, -EPERM
);
401 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_S64
);
405 r
= add_rtattr(m
, type
, &data
, sizeof(int64_t));
412 int sd_netlink_message_append_data(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t len
) {
415 assert_return(m
, -EINVAL
);
416 assert_return(!m
->sealed
, -EPERM
);
418 r
= add_rtattr(m
, type
, data
, len
);
425 int netlink_message_append_in_addr_union(sd_netlink_message
*m
, unsigned short type
, int family
, const union in_addr_union
*data
) {
428 assert_return(m
, -EINVAL
);
429 assert_return(!m
->sealed
, -EPERM
);
430 assert_return(data
, -EINVAL
);
431 assert_return(IN_SET(family
, AF_INET
, AF_INET6
), -EINVAL
);
433 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
437 r
= add_rtattr(m
, type
, data
, FAMILY_ADDRESS_SIZE(family
));
444 int sd_netlink_message_append_in_addr(sd_netlink_message
*m
, unsigned short type
, const struct in_addr
*data
) {
445 return netlink_message_append_in_addr_union(m
, type
, AF_INET
, (const union in_addr_union
*) data
);
448 int sd_netlink_message_append_in6_addr(sd_netlink_message
*m
, unsigned short type
, const struct in6_addr
*data
) {
449 return netlink_message_append_in_addr_union(m
, type
, AF_INET6
, (const union in_addr_union
*) data
);
452 int netlink_message_append_sockaddr_union(sd_netlink_message
*m
, unsigned short type
, const union sockaddr_union
*data
) {
455 assert_return(m
, -EINVAL
);
456 assert_return(!m
->sealed
, -EPERM
);
457 assert_return(data
, -EINVAL
);
458 assert_return(IN_SET(data
->sa
.sa_family
, AF_INET
, AF_INET6
), -EINVAL
);
460 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_SOCKADDR
);
464 r
= add_rtattr(m
, type
, data
, data
->sa
.sa_family
== AF_INET
? sizeof(struct sockaddr_in
) : sizeof(struct sockaddr_in6
));
471 int sd_netlink_message_append_sockaddr_in(sd_netlink_message
*m
, unsigned short type
, const struct sockaddr_in
*data
) {
472 return netlink_message_append_sockaddr_union(m
, type
, (const union sockaddr_union
*) data
);
475 int sd_netlink_message_append_sockaddr_in6(sd_netlink_message
*m
, unsigned short type
, const struct sockaddr_in6
*data
) {
476 return netlink_message_append_sockaddr_union(m
, type
, (const union sockaddr_union
*) data
);
479 int sd_netlink_message_append_ether_addr(sd_netlink_message
*m
, unsigned short type
, const struct ether_addr
*data
) {
482 assert_return(m
, -EINVAL
);
483 assert_return(!m
->sealed
, -EPERM
);
484 assert_return(data
, -EINVAL
);
486 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
490 r
= add_rtattr(m
, type
, data
, ETH_ALEN
);
497 int netlink_message_append_hw_addr(sd_netlink_message
*m
, unsigned short type
, const struct hw_addr_data
*data
) {
500 assert_return(m
, -EINVAL
);
501 assert_return(!m
->sealed
, -EPERM
);
502 assert_return(data
, -EINVAL
);
503 assert_return(data
->length
> 0, -EINVAL
);
505 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
509 r
= add_rtattr(m
, type
, data
->bytes
, data
->length
);
516 int sd_netlink_message_append_cache_info(sd_netlink_message
*m
, unsigned short type
, const struct ifa_cacheinfo
*info
) {
519 assert_return(m
, -EINVAL
);
520 assert_return(!m
->sealed
, -EPERM
);
521 assert_return(info
, -EINVAL
);
523 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
527 r
= add_rtattr(m
, type
, info
, sizeof(struct ifa_cacheinfo
));
534 int sd_netlink_message_open_container(sd_netlink_message
*m
, unsigned short type
) {
538 assert_return(m
, -EINVAL
);
539 assert_return(!m
->sealed
, -EPERM
);
540 /* m->containers[m->n_containers + 1] is accessed both in read and write. Prevent access out of bound */
541 assert_return(m
->n_containers
< (RTNL_CONTAINER_DEPTH
- 1), -ERANGE
);
543 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_NESTED
);
545 const NLTypeSystemUnion
*type_system_union
;
548 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_UNION
);
552 r
= sd_rtnl_message_get_family(m
, &family
);
556 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
560 r
= type_system_union_protocol_get_type_system(type_system_union
,
561 &m
->containers
[m
->n_containers
+ 1].type_system
,
566 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
567 &m
->containers
[m
->n_containers
+ 1].type_system
,
573 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, size
);
577 m
->containers
[m
->n_containers
++].offset
= r
;
582 int sd_netlink_message_open_container_union(sd_netlink_message
*m
, unsigned short type
, const char *key
) {
583 const NLTypeSystemUnion
*type_system_union
;
586 assert_return(m
, -EINVAL
);
587 assert_return(!m
->sealed
, -EPERM
);
588 assert_return(m
->n_containers
< (RTNL_CONTAINER_DEPTH
- 1), -ERANGE
);
590 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
594 r
= type_system_union_get_type_system(type_system_union
,
595 &m
->containers
[m
->n_containers
+ 1].type_system
,
600 r
= sd_netlink_message_append_string(m
, type_system_union
->match
, key
);
604 /* do we ever need non-null size */
605 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, 0);
609 m
->containers
[m
->n_containers
++].offset
= r
;
614 int sd_netlink_message_close_container(sd_netlink_message
*m
) {
615 assert_return(m
, -EINVAL
);
616 assert_return(!m
->sealed
, -EPERM
);
617 assert_return(m
->n_containers
> 0, -EINVAL
);
619 m
->containers
[m
->n_containers
].type_system
= NULL
;
620 m
->containers
[m
->n_containers
].offset
= 0;
626 int sd_netlink_message_open_array(sd_netlink_message
*m
, uint16_t type
) {
629 assert_return(m
, -EINVAL
);
630 assert_return(!m
->sealed
, -EPERM
);
631 assert_return(m
->n_containers
< (RTNL_CONTAINER_DEPTH
- 1), -ERANGE
);
633 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, 0);
637 m
->containers
[m
->n_containers
].offset
= r
;
639 m
->containers
[m
->n_containers
].type_system
= m
->containers
[m
->n_containers
- 1].type_system
;
644 int sd_netlink_message_cancel_array(sd_netlink_message
*m
) {
647 assert_return(m
, -EINVAL
);
648 assert_return(!m
->sealed
, -EPERM
);
649 assert_return(m
->n_containers
> 1, -EINVAL
);
651 rta_len
= GET_CONTAINER(m
, (m
->n_containers
- 1))->rta_len
;
653 for (unsigned i
= 0; i
< m
->n_containers
; i
++)
654 GET_CONTAINER(m
, i
)->rta_len
-= rta_len
;
656 m
->hdr
->nlmsg_len
-= rta_len
;
659 m
->containers
[m
->n_containers
].type_system
= NULL
;
664 static int netlink_message_read_internal(
665 sd_netlink_message
*m
,
668 bool *ret_net_byteorder
) {
670 struct netlink_attribute
*attribute
;
673 assert_return(m
, -EINVAL
);
674 assert_return(m
->sealed
, -EPERM
);
676 assert(m
->n_containers
< RTNL_CONTAINER_DEPTH
);
678 if (!m
->containers
[m
->n_containers
].attributes
)
681 if (type
>= m
->containers
[m
->n_containers
].n_attributes
)
684 attribute
= &m
->containers
[m
->n_containers
].attributes
[type
];
686 if (attribute
->offset
== 0)
689 rta
= (struct rtattr
*)((uint8_t *) m
->hdr
+ attribute
->offset
);
692 *ret_data
= RTA_DATA(rta
);
694 if (ret_net_byteorder
)
695 *ret_net_byteorder
= attribute
->net_byteorder
;
697 return RTA_PAYLOAD(rta
);
700 int sd_netlink_message_read(sd_netlink_message
*m
, unsigned short type
, size_t size
, void *data
) {
704 assert_return(m
, -EINVAL
);
706 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
710 if ((size_t) r
< size
)
714 memcpy(data
, attr_data
, size
);
719 int sd_netlink_message_read_data(sd_netlink_message
*m
, unsigned short type
, size_t *ret_size
, void **ret_data
) {
720 void *attr_data
, *data
;
723 assert_return(m
, -EINVAL
);
725 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
730 data
= memdup(attr_data
, r
);
743 int sd_netlink_message_read_string_strdup(sd_netlink_message
*m
, unsigned short type
, char **data
) {
748 assert_return(m
, -EINVAL
);
750 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_STRING
);
754 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
759 str
= strndup(attr_data
, r
);
769 int sd_netlink_message_read_string(sd_netlink_message
*m
, unsigned short type
, const char **data
) {
773 assert_return(m
, -EINVAL
);
775 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_STRING
);
779 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
782 else if (strnlen(attr_data
, r
) >= (size_t) r
)
786 *data
= (const char *) attr_data
;
791 int sd_netlink_message_read_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t *data
) {
795 assert_return(m
, -EINVAL
);
797 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
801 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
804 else if ((size_t) r
< sizeof(uint8_t))
808 *data
= *(uint8_t *) attr_data
;
813 int sd_netlink_message_read_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t *data
) {
818 assert_return(m
, -EINVAL
);
820 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
824 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
827 else if ((size_t) r
< sizeof(uint16_t))
832 *data
= be16toh(*(uint16_t *) attr_data
);
834 *data
= *(uint16_t *) attr_data
;
840 int sd_netlink_message_read_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t *data
) {
845 assert_return(m
, -EINVAL
);
847 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
851 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
854 else if ((size_t) r
< sizeof(uint32_t))
859 *data
= be32toh(*(uint32_t *) attr_data
);
861 *data
= *(uint32_t *) attr_data
;
867 int sd_netlink_message_read_ether_addr(sd_netlink_message
*m
, unsigned short type
, struct ether_addr
*data
) {
871 assert_return(m
, -EINVAL
);
873 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
877 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
880 else if ((size_t) r
< sizeof(struct ether_addr
))
884 memcpy(data
, attr_data
, sizeof(struct ether_addr
));
889 int netlink_message_read_hw_addr(sd_netlink_message
*m
, unsigned short type
, struct hw_addr_data
*data
) {
893 assert_return(m
, -EINVAL
);
895 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
899 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
902 else if (r
> HW_ADDR_MAX_SIZE
)
906 memcpy(data
->bytes
, attr_data
, r
);
913 int sd_netlink_message_read_cache_info(sd_netlink_message
*m
, unsigned short type
, struct ifa_cacheinfo
*info
) {
917 assert_return(m
, -EINVAL
);
919 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
923 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
926 else if ((size_t) r
< sizeof(struct ifa_cacheinfo
))
930 memcpy(info
, attr_data
, sizeof(struct ifa_cacheinfo
));
935 int netlink_message_read_in_addr_union(sd_netlink_message
*m
, unsigned short type
, int family
, union in_addr_union
*data
) {
939 assert_return(m
, -EINVAL
);
940 assert_return(IN_SET(family
, AF_INET
, AF_INET6
), -EINVAL
);
942 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
946 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
949 else if ((size_t) r
< FAMILY_ADDRESS_SIZE(family
))
953 memcpy(data
, attr_data
, FAMILY_ADDRESS_SIZE(family
));
958 int sd_netlink_message_read_in_addr(sd_netlink_message
*m
, unsigned short type
, struct in_addr
*data
) {
959 union in_addr_union u
;
962 r
= netlink_message_read_in_addr_union(m
, type
, AF_INET
, &u
);
969 int sd_netlink_message_read_in6_addr(sd_netlink_message
*m
, unsigned short type
, struct in6_addr
*data
) {
970 union in_addr_union u
;
973 r
= netlink_message_read_in_addr_union(m
, type
, AF_INET6
, &u
);
980 int sd_netlink_message_has_flag(sd_netlink_message
*m
, unsigned short type
) {
984 assert_return(m
, -EINVAL
);
986 /* This returns 1 when the flag is set, 0 when not set, negative errno on error. */
988 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_FLAG
);
992 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
1001 int sd_netlink_message_read_strv(sd_netlink_message
*m
, unsigned short container_type
, unsigned short type_id
, char ***ret
) {
1002 _cleanup_strv_free_
char **s
= NULL
;
1003 const NLTypeSystem
*type_system
;
1004 const NLType
*nl_type
;
1010 assert_return(m
, -EINVAL
);
1011 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -EINVAL
);
1013 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
,
1019 if (type_get_type(nl_type
) != NETLINK_TYPE_NESTED
)
1022 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
1028 r
= type_system_get_type(type_system
, &nl_type
, type_id
);
1032 if (type_get_type(nl_type
) != NETLINK_TYPE_STRING
)
1035 r
= netlink_message_read_internal(m
, container_type
, &container
, NULL
);
1039 rt_len
= (size_t) r
;
1042 /* RTA_OK() macro compares with rta->rt_len, which is unsigned short, and
1043 * LGTM.com analysis does not like the type difference. Hence, here we
1044 * introduce an unsigned short variable as a workaround. */
1045 unsigned short len
= rt_len
;
1046 for (; RTA_OK(rta
, len
); rta
= RTA_NEXT(rta
, len
)) {
1047 unsigned short type
;
1049 type
= RTA_TYPE(rta
);
1050 if (type
!= type_id
)
1053 r
= strv_extend(&s
, RTA_DATA(rta
));
1062 static int netlink_container_parse(sd_netlink_message
*m
,
1063 struct netlink_container
*container
,
1066 _cleanup_free_
struct netlink_attribute
*attributes
= NULL
;
1069 /* RTA_OK() macro compares with rta->rt_len, which is unsigned short, and
1070 * LGTM.com analysis does not like the type difference. Hence, here we
1071 * introduce an unsigned short variable as a workaround. */
1072 unsigned short len
= rt_len
;
1073 for (; RTA_OK(rta
, len
); rta
= RTA_NEXT(rta
, len
)) {
1074 unsigned short type
;
1076 type
= RTA_TYPE(rta
);
1078 if (!GREEDY_REALLOC0(attributes
, type
+ 1))
1081 if (attributes
[type
].offset
!= 0)
1082 log_debug("rtnl: message parse - overwriting repeated attribute");
1084 attributes
[type
].offset
= (uint8_t *) rta
- (uint8_t *) m
->hdr
;
1085 attributes
[type
].nested
= RTA_FLAGS(rta
) & NLA_F_NESTED
;
1086 attributes
[type
].net_byteorder
= RTA_FLAGS(rta
) & NLA_F_NET_BYTEORDER
;
1092 container
->attributes
= TAKE_PTR(attributes
);
1093 container
->n_attributes
= n
;
1098 int sd_netlink_message_enter_container(sd_netlink_message
*m
, unsigned short type_id
) {
1099 const NLType
*nl_type
;
1100 const NLTypeSystem
*type_system
;
1106 assert_return(m
, -EINVAL
);
1107 assert_return(m
->n_containers
< (RTNL_CONTAINER_DEPTH
- 1), -EINVAL
);
1109 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
,
1115 type
= type_get_type(nl_type
);
1117 if (type
== NETLINK_TYPE_NESTED
) {
1118 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
1123 } else if (type
== NETLINK_TYPE_UNION
) {
1124 const NLTypeSystemUnion
*type_system_union
;
1126 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
,
1132 switch (type_system_union
->match_type
) {
1133 case NL_MATCH_SIBLING
:
1137 r
= sd_netlink_message_read_string(m
, type_system_union
->match
, &key
);
1141 r
= type_system_union_get_type_system(type_system_union
,
1149 case NL_MATCH_PROTOCOL
:
1153 r
= sd_rtnl_message_get_family(m
, &family
);
1157 r
= type_system_union_protocol_get_type_system(type_system_union
,
1166 assert_not_reached("sd-netlink: invalid type system union type");
1171 r
= netlink_message_read_internal(m
, type_id
, &container
, NULL
);
1178 r
= netlink_container_parse(m
,
1179 &m
->containers
[m
->n_containers
],
1187 m
->containers
[m
->n_containers
].type_system
= type_system
;
1192 int sd_netlink_message_enter_array(sd_netlink_message
*m
, unsigned short type_id
) {
1197 assert_return(m
, -EINVAL
);
1198 assert_return(m
->n_containers
< (RTNL_CONTAINER_DEPTH
- 1), -EINVAL
);
1200 r
= netlink_message_read_internal(m
, type_id
, &container
, NULL
);
1207 r
= netlink_container_parse(m
,
1208 &m
->containers
[m
->n_containers
],
1216 m
->containers
[m
->n_containers
].type_system
= m
->containers
[m
->n_containers
- 1].type_system
;
1221 int sd_netlink_message_exit_container(sd_netlink_message
*m
) {
1222 assert_return(m
, -EINVAL
);
1223 assert_return(m
->sealed
, -EINVAL
);
1224 assert_return(m
->n_containers
> 0, -EINVAL
);
1226 m
->containers
[m
->n_containers
].attributes
= mfree(m
->containers
[m
->n_containers
].attributes
);
1227 m
->containers
[m
->n_containers
].type_system
= NULL
;
1234 uint32_t rtnl_message_get_serial(sd_netlink_message
*m
) {
1238 return m
->hdr
->nlmsg_seq
;
1241 int sd_netlink_message_is_error(sd_netlink_message
*m
) {
1242 assert_return(m
, 0);
1243 assert_return(m
->hdr
, 0);
1245 return m
->hdr
->nlmsg_type
== NLMSG_ERROR
;
1248 int sd_netlink_message_get_errno(sd_netlink_message
*m
) {
1249 struct nlmsgerr
*err
;
1251 assert_return(m
, -EINVAL
);
1252 assert_return(m
->hdr
, -EINVAL
);
1254 if (!sd_netlink_message_is_error(m
))
1257 err
= NLMSG_DATA(m
->hdr
);
1262 static int netlink_message_parse_error(sd_netlink_message
*m
) {
1263 struct nlmsgerr
*err
= NLMSG_DATA(m
->hdr
);
1264 size_t hlen
= sizeof(struct nlmsgerr
);
1266 /* no TLVs, nothing to do here */
1267 if (!(m
->hdr
->nlmsg_flags
& NLM_F_ACK_TLVS
))
1270 /* if NLM_F_CAPPED is set then the inner err msg was capped */
1271 if (!(m
->hdr
->nlmsg_flags
& NLM_F_CAPPED
))
1272 hlen
+= err
->msg
.nlmsg_len
- sizeof(struct nlmsghdr
);
1274 if (m
->hdr
->nlmsg_len
<= NLMSG_SPACE(hlen
))
1277 return netlink_container_parse(m
,
1278 &m
->containers
[m
->n_containers
],
1279 (struct rtattr
*)((uint8_t*) NLMSG_DATA(m
->hdr
) + hlen
),
1280 NLMSG_PAYLOAD(m
->hdr
, hlen
));
1283 int sd_netlink_message_rewind(sd_netlink_message
*m
, sd_netlink
*genl
) {
1284 const NLType
*nl_type
;
1289 assert_return(m
, -EINVAL
);
1290 assert_return(genl
|| m
->protocol
!= NETLINK_GENERIC
, -EINVAL
);
1292 /* don't allow appending to message once parsed */
1294 rtnl_message_seal(m
);
1296 for (unsigned i
= 1; i
<= m
->n_containers
; i
++)
1297 m
->containers
[i
].attributes
= mfree(m
->containers
[i
].attributes
);
1299 m
->n_containers
= 0;
1301 if (m
->containers
[0].attributes
)
1302 /* top-level attributes have already been parsed */
1307 r
= type_system_root_get_type(genl
, &nl_type
, m
->hdr
->nlmsg_type
);
1311 type
= type_get_type(nl_type
);
1312 size
= type_get_size(nl_type
);
1314 if (type
== NETLINK_TYPE_NESTED
) {
1315 const NLTypeSystem
*type_system
;
1317 type_get_type_system(nl_type
, &type_system
);
1319 m
->containers
[0].type_system
= type_system
;
1321 if (sd_netlink_message_is_error(m
))
1322 r
= netlink_message_parse_error(m
);
1324 r
= netlink_container_parse(m
,
1325 &m
->containers
[m
->n_containers
],
1326 (struct rtattr
*)((uint8_t*) NLMSG_DATA(m
->hdr
) + NLMSG_ALIGN(size
)),
1327 NLMSG_PAYLOAD(m
->hdr
, size
));
1335 void rtnl_message_seal(sd_netlink_message
*m
) {
1342 sd_netlink_message
*sd_netlink_message_next(sd_netlink_message
*m
) {
1343 assert_return(m
, NULL
);