1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Tom Gundersen <teg@jklm.no>
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <netinet/in.h>
25 #include "sd-netlink.h"
27 #include "alloc-util.h"
28 #include "format-util.h"
30 #include "netlink-internal.h"
31 #include "netlink-types.h"
32 #include "netlink-util.h"
34 #include "socket-util.h"
37 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : 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)
41 #define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
43 int message_new_empty(sd_netlink
*rtnl
, sd_netlink_message
**ret
) {
44 sd_netlink_message
*m
;
46 assert_return(ret
, -EINVAL
);
48 /* Note that 'rtnl' is currently unused, if we start using it internally
49 we must take care to avoid problems due to mutual references between
50 buses and their queued messages. See sd-bus.
53 m
= new0(sd_netlink_message
, 1);
57 m
->n_ref
= REFCNT_INIT
;
66 int message_new(sd_netlink
*rtnl
, sd_netlink_message
**ret
, uint16_t type
) {
67 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
68 const NLType
*nl_type
;
72 r
= type_system_get_type(&type_system_root
, &nl_type
, type
);
76 if (type_get_type(nl_type
) != NETLINK_TYPE_NESTED
)
79 r
= message_new_empty(rtnl
, &m
);
83 size
= NLMSG_SPACE(type_get_size(nl_type
));
85 assert(size
>= sizeof(struct nlmsghdr
));
86 m
->hdr
= malloc0(size
);
90 m
->hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
92 type_get_type_system(nl_type
, &m
->containers
[0].type_system
);
93 m
->hdr
->nlmsg_len
= size
;
94 m
->hdr
->nlmsg_type
= type
;
102 int sd_netlink_message_request_dump(sd_netlink_message
*m
, int dump
) {
103 assert_return(m
, -EINVAL
);
104 assert_return(m
->hdr
, -EINVAL
);
106 assert_return(IN_SET(m
->hdr
->nlmsg_type
, RTM_GETLINK
, RTM_GETADDR
, RTM_GETROUTE
, RTM_GETNEIGH
, RTM_GETRULE
, RTM_GETADDRLABEL
), -EINVAL
);
108 SET_FLAG(m
->hdr
->nlmsg_flags
, NLM_F_DUMP
, dump
);
113 sd_netlink_message
*sd_netlink_message_ref(sd_netlink_message
*m
) {
115 assert_se(REFCNT_INC(m
->n_ref
) >= 2);
120 sd_netlink_message
*sd_netlink_message_unref(sd_netlink_message
*m
) {
121 sd_netlink_message
*t
;
123 while (m
&& REFCNT_DEC(m
->n_ref
) == 0) {
128 for (i
= 0; i
<= m
->n_containers
; i
++)
129 free(m
->containers
[i
].attributes
);
139 int sd_netlink_message_get_type(sd_netlink_message
*m
, uint16_t *type
) {
140 assert_return(m
, -EINVAL
);
141 assert_return(type
, -EINVAL
);
143 *type
= m
->hdr
->nlmsg_type
;
148 int sd_netlink_message_set_flags(sd_netlink_message
*m
, uint16_t flags
) {
149 assert_return(m
, -EINVAL
);
150 assert_return(flags
, -EINVAL
);
152 m
->hdr
->nlmsg_flags
= flags
;
157 int sd_netlink_message_is_broadcast(sd_netlink_message
*m
) {
158 assert_return(m
, -EINVAL
);
163 /* If successful the updated message will be correctly aligned, if
164 unsuccessful the old message is untouched. */
165 static int add_rtattr(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t data_length
) {
167 size_t message_length
, padding_length
;
168 struct nlmsghdr
*new_hdr
;
177 assert(NLMSG_ALIGN(m
->hdr
->nlmsg_len
) == m
->hdr
->nlmsg_len
);
178 assert(!data
|| data_length
);
180 /* get offset of the new attribute */
181 offset
= m
->hdr
->nlmsg_len
;
183 /* get the size of the new rta attribute (with padding at the end) */
184 rta_length
= RTA_LENGTH(data_length
);
186 /* get the new message size (with padding at the end) */
187 message_length
= offset
+ RTA_ALIGN(rta_length
);
189 /* realloc to fit the new attribute */
190 new_hdr
= realloc(m
->hdr
, message_length
);
195 /* get pointer to the attribute we are about to add */
196 rta
= (struct rtattr
*) ((uint8_t *) m
->hdr
+ offset
);
198 /* if we are inside containers, extend them */
199 for (i
= 0; i
< m
->n_containers
; i
++)
200 GET_CONTAINER(m
, i
)->rta_len
+= message_length
- offset
;
202 /* fill in the attribute */
203 rta
->rta_type
= type
;
204 rta
->rta_len
= rta_length
;
206 /* we don't deal with the case where the user lies about the type
207 * and gives us too little data (so don't do that)
209 padding
= mempcpy(RTA_DATA(rta
), data
, data_length
);
212 /* if no data was passed, make sure we still initialize the padding
213 note that we can have data_length > 0 (used by some containers) */
214 padding
= RTA_DATA(rta
);
216 /* make sure also the padding at the end of the message is initialized */
217 padding_length
= (uint8_t*)m
->hdr
+ message_length
- (uint8_t*)padding
;
218 memzero(padding
, padding_length
);
220 /* update message size */
221 m
->hdr
->nlmsg_len
= message_length
;
226 static int message_attribute_has_type(sd_netlink_message
*m
, size_t *out_size
, uint16_t attribute_type
, uint16_t data_type
) {
232 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
, &type
, attribute_type
);
236 if (type_get_type(type
) != data_type
)
240 *out_size
= type_get_size(type
);
244 int sd_netlink_message_append_string(sd_netlink_message
*m
, unsigned short type
, const char *data
) {
248 assert_return(m
, -EINVAL
);
249 assert_return(!m
->sealed
, -EPERM
);
250 assert_return(data
, -EINVAL
);
252 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_STRING
);
257 length
= strnlen(data
, size
+1);
261 length
= strlen(data
);
263 r
= add_rtattr(m
, type
, data
, length
+ 1);
270 int sd_netlink_message_append_flag(sd_netlink_message
*m
, unsigned short type
) {
274 assert_return(m
, -EINVAL
);
275 assert_return(!m
->sealed
, -EPERM
);
277 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_FLAG
);
281 r
= add_rtattr(m
, type
, NULL
, 0);
288 int sd_netlink_message_append_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t data
) {
291 assert_return(m
, -EINVAL
);
292 assert_return(!m
->sealed
, -EPERM
);
294 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
298 r
= add_rtattr(m
, type
, &data
, sizeof(uint8_t));
306 int sd_netlink_message_append_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t data
) {
309 assert_return(m
, -EINVAL
);
310 assert_return(!m
->sealed
, -EPERM
);
312 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
316 r
= add_rtattr(m
, type
, &data
, sizeof(uint16_t));
323 int sd_netlink_message_append_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t data
) {
326 assert_return(m
, -EINVAL
);
327 assert_return(!m
->sealed
, -EPERM
);
329 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
333 r
= add_rtattr(m
, type
, &data
, sizeof(uint32_t));
340 int sd_netlink_message_append_data(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t len
) {
343 assert_return(m
, -EINVAL
);
344 assert_return(!m
->sealed
, -EPERM
);
346 r
= add_rtattr(m
, type
, data
, len
);
353 int sd_netlink_message_append_in_addr(sd_netlink_message
*m
, unsigned short type
, const struct in_addr
*data
) {
356 assert_return(m
, -EINVAL
);
357 assert_return(!m
->sealed
, -EPERM
);
358 assert_return(data
, -EINVAL
);
360 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
364 r
= add_rtattr(m
, type
, data
, sizeof(struct in_addr
));
371 int sd_netlink_message_append_in6_addr(sd_netlink_message
*m
, unsigned short type
, const struct in6_addr
*data
) {
374 assert_return(m
, -EINVAL
);
375 assert_return(!m
->sealed
, -EPERM
);
376 assert_return(data
, -EINVAL
);
378 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
382 r
= add_rtattr(m
, type
, data
, sizeof(struct in6_addr
));
389 int sd_netlink_message_append_ether_addr(sd_netlink_message
*m
, unsigned short type
, const struct ether_addr
*data
) {
392 assert_return(m
, -EINVAL
);
393 assert_return(!m
->sealed
, -EPERM
);
394 assert_return(data
, -EINVAL
);
396 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
400 r
= add_rtattr(m
, type
, data
, ETH_ALEN
);
407 int sd_netlink_message_append_cache_info(sd_netlink_message
*m
, unsigned short type
, const struct ifa_cacheinfo
*info
) {
410 assert_return(m
, -EINVAL
);
411 assert_return(!m
->sealed
, -EPERM
);
412 assert_return(info
, -EINVAL
);
414 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
418 r
= add_rtattr(m
, type
, info
, sizeof(struct ifa_cacheinfo
));
425 int sd_netlink_message_open_container(sd_netlink_message
*m
, unsigned short type
) {
429 assert_return(m
, -EINVAL
);
430 assert_return(!m
->sealed
, -EPERM
);
431 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -ERANGE
);
433 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_NESTED
);
435 const NLTypeSystemUnion
*type_system_union
;
438 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_UNION
);
442 r
= sd_rtnl_message_get_family(m
, &family
);
446 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
450 r
= type_system_union_protocol_get_type_system(type_system_union
,
451 &m
->containers
[m
->n_containers
+ 1].type_system
,
456 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
457 &m
->containers
[m
->n_containers
+ 1].type_system
,
463 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, size
);
467 m
->containers
[m
->n_containers
++].offset
= r
;
472 int sd_netlink_message_open_container_union(sd_netlink_message
*m
, unsigned short type
, const char *key
) {
473 const NLTypeSystemUnion
*type_system_union
;
476 assert_return(m
, -EINVAL
);
477 assert_return(!m
->sealed
, -EPERM
);
479 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
483 r
= type_system_union_get_type_system(type_system_union
,
484 &m
->containers
[m
->n_containers
+ 1].type_system
,
489 r
= sd_netlink_message_append_string(m
, type_system_union
->match
, key
);
493 /* do we evere need non-null size */
494 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, 0);
498 m
->containers
[m
->n_containers
++].offset
= r
;
504 int sd_netlink_message_close_container(sd_netlink_message
*m
) {
505 assert_return(m
, -EINVAL
);
506 assert_return(!m
->sealed
, -EPERM
);
507 assert_return(m
->n_containers
> 0, -EINVAL
);
509 m
->containers
[m
->n_containers
].type_system
= NULL
;
515 static int netlink_message_read_internal(sd_netlink_message
*m
, unsigned short type
, void **data
, bool *net_byteorder
) {
516 struct netlink_attribute
*attribute
;
519 assert_return(m
, -EINVAL
);
520 assert_return(m
->sealed
, -EPERM
);
521 assert_return(data
, -EINVAL
);
522 assert(m
->n_containers
< RTNL_CONTAINER_DEPTH
);
523 assert(m
->containers
[m
->n_containers
].attributes
);
524 assert(type
< m
->containers
[m
->n_containers
].n_attributes
);
526 attribute
= &m
->containers
[m
->n_containers
].attributes
[type
];
528 if (!attribute
->offset
)
531 rta
= (struct rtattr
*)((uint8_t *) m
->hdr
+ attribute
->offset
);
533 *data
= RTA_DATA(rta
);
536 *net_byteorder
= attribute
->net_byteorder
;
538 return RTA_PAYLOAD(rta
);
541 int sd_netlink_message_read_string(sd_netlink_message
*m
, unsigned short type
, const char **data
) {
545 assert_return(m
, -EINVAL
);
547 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_STRING
);
551 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
554 else if (strnlen(attr_data
, r
) >= (size_t) r
)
558 *data
= (const char *) attr_data
;
563 int sd_netlink_message_read_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t *data
) {
567 assert_return(m
, -EINVAL
);
569 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
573 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
576 else if ((size_t) r
< sizeof(uint8_t))
580 *data
= *(uint8_t *) attr_data
;
585 int sd_netlink_message_read_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t *data
) {
590 assert_return(m
, -EINVAL
);
592 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
596 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
599 else if ((size_t) r
< sizeof(uint16_t))
604 *data
= be16toh(*(uint16_t *) attr_data
);
606 *data
= *(uint16_t *) attr_data
;
612 int sd_netlink_message_read_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t *data
) {
617 assert_return(m
, -EINVAL
);
619 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
623 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
626 else if ((size_t)r
< sizeof(uint32_t))
631 *data
= be32toh(*(uint32_t *) attr_data
);
633 *data
= *(uint32_t *) attr_data
;
639 int sd_netlink_message_read_ether_addr(sd_netlink_message
*m
, unsigned short type
, struct ether_addr
*data
) {
643 assert_return(m
, -EINVAL
);
645 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
649 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
652 else if ((size_t)r
< sizeof(struct ether_addr
))
656 memcpy(data
, attr_data
, sizeof(struct ether_addr
));
661 int sd_netlink_message_read_cache_info(sd_netlink_message
*m
, unsigned short type
, struct ifa_cacheinfo
*info
) {
665 assert_return(m
, -EINVAL
);
667 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
671 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
674 else if ((size_t)r
< sizeof(struct ifa_cacheinfo
))
678 memcpy(info
, attr_data
, sizeof(struct ifa_cacheinfo
));
683 int sd_netlink_message_read_in_addr(sd_netlink_message
*m
, unsigned short type
, struct in_addr
*data
) {
687 assert_return(m
, -EINVAL
);
689 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
693 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
696 else if ((size_t)r
< sizeof(struct in_addr
))
700 memcpy(data
, attr_data
, sizeof(struct in_addr
));
705 int sd_netlink_message_read_in6_addr(sd_netlink_message
*m
, unsigned short type
, struct in6_addr
*data
) {
709 assert_return(m
, -EINVAL
);
711 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
715 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
718 else if ((size_t)r
< sizeof(struct in6_addr
))
722 memcpy(data
, attr_data
, sizeof(struct in6_addr
));
727 static int netlink_container_parse(sd_netlink_message
*m
,
728 struct netlink_container
*container
,
731 unsigned int rt_len
) {
732 _cleanup_free_
struct netlink_attribute
*attributes
= NULL
;
734 attributes
= new0(struct netlink_attribute
, count
);
738 for (; RTA_OK(rta
, rt_len
); rta
= RTA_NEXT(rta
, rt_len
)) {
741 type
= RTA_TYPE(rta
);
743 /* if the kernel is newer than the headers we used
744 when building, we ignore out-of-range attributes */
748 if (attributes
[type
].offset
)
749 log_debug("rtnl: message parse - overwriting repeated attribute");
751 attributes
[type
].offset
= (uint8_t *) rta
- (uint8_t *) m
->hdr
;
752 attributes
[type
].nested
= RTA_FLAGS(rta
) & NLA_F_NESTED
;
753 attributes
[type
].net_byteorder
= RTA_FLAGS(rta
) & NLA_F_NET_BYTEORDER
;
756 container
->attributes
= attributes
;
758 container
->n_attributes
= count
;
763 int sd_netlink_message_enter_container(sd_netlink_message
*m
, unsigned short type_id
) {
764 const NLType
*nl_type
;
765 const NLTypeSystem
*type_system
;
771 assert_return(m
, -EINVAL
);
772 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -EINVAL
);
774 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
,
780 type
= type_get_type(nl_type
);
782 if (type
== NETLINK_TYPE_NESTED
) {
783 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
788 } else if (type
== NETLINK_TYPE_UNION
) {
789 const NLTypeSystemUnion
*type_system_union
;
791 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
,
797 switch (type_system_union
->match_type
) {
798 case NL_MATCH_SIBLING
:
802 r
= sd_netlink_message_read_string(m
, type_system_union
->match
, &key
);
806 r
= type_system_union_get_type_system(type_system_union
,
814 case NL_MATCH_PROTOCOL
:
818 r
= sd_rtnl_message_get_family(m
, &family
);
822 r
= type_system_union_protocol_get_type_system(type_system_union
,
831 assert_not_reached("sd-netlink: invalid type system union type");
836 r
= netlink_message_read_internal(m
, type_id
, &container
, NULL
);
844 r
= netlink_container_parse(m
,
845 &m
->containers
[m
->n_containers
],
846 type_system_get_count(type_system
),
854 m
->containers
[m
->n_containers
].type_system
= type_system
;
859 int sd_netlink_message_exit_container(sd_netlink_message
*m
) {
860 assert_return(m
, -EINVAL
);
861 assert_return(m
->sealed
, -EINVAL
);
862 assert_return(m
->n_containers
> 0, -EINVAL
);
864 m
->containers
[m
->n_containers
].attributes
= mfree(m
->containers
[m
->n_containers
].attributes
);
865 m
->containers
[m
->n_containers
].type_system
= NULL
;
872 uint32_t rtnl_message_get_serial(sd_netlink_message
*m
) {
876 return m
->hdr
->nlmsg_seq
;
879 int sd_netlink_message_is_error(sd_netlink_message
*m
) {
881 assert_return(m
->hdr
, 0);
883 return m
->hdr
->nlmsg_type
== NLMSG_ERROR
;
886 int sd_netlink_message_get_errno(sd_netlink_message
*m
) {
887 struct nlmsgerr
*err
;
889 assert_return(m
, -EINVAL
);
890 assert_return(m
->hdr
, -EINVAL
);
892 if (!sd_netlink_message_is_error(m
))
895 err
= NLMSG_DATA(m
->hdr
);
900 int sd_netlink_message_rewind(sd_netlink_message
*m
) {
901 const NLType
*nl_type
;
907 assert_return(m
, -EINVAL
);
909 /* don't allow appending to message once parsed */
911 rtnl_message_seal(m
);
913 for (i
= 1; i
<= m
->n_containers
; i
++)
914 m
->containers
[i
].attributes
= mfree(m
->containers
[i
].attributes
);
918 if (m
->containers
[0].attributes
)
919 /* top-level attributes have already been parsed */
924 r
= type_system_get_type(&type_system_root
, &nl_type
, m
->hdr
->nlmsg_type
);
928 type
= type_get_type(nl_type
);
929 size
= type_get_size(nl_type
);
931 if (type
== NETLINK_TYPE_NESTED
) {
932 const NLTypeSystem
*type_system
;
934 type_get_type_system(nl_type
, &type_system
);
936 m
->containers
[0].type_system
= type_system
;
938 r
= netlink_container_parse(m
,
939 &m
->containers
[m
->n_containers
],
940 type_system_get_count(type_system
),
941 (struct rtattr
*)((uint8_t*)NLMSG_DATA(m
->hdr
) + NLMSG_ALIGN(size
)),
942 NLMSG_PAYLOAD(m
->hdr
, size
));
950 void rtnl_message_seal(sd_netlink_message
*m
) {
957 sd_netlink_message
*sd_netlink_message_next(sd_netlink_message
*m
) {
958 assert_return(m
, NULL
);