2 This file is part of systemd.
4 Copyright 2013 Tom Gundersen <teg@jklm.no>
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include <netinet/in.h>
24 #include "sd-netlink.h"
26 #include "alloc-util.h"
27 #include "formats-util.h"
29 #include "netlink-internal.h"
30 #include "netlink-types.h"
31 #include "netlink-util.h"
33 #include "socket-util.h"
36 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL)
37 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
39 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
40 #define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
42 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_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
67 const NLType
*nl_type
;
71 r
= type_system_get_type(&type_system_root
, &nl_type
, type
);
75 if (type_get_type(nl_type
) != NETLINK_TYPE_NESTED
)
78 r
= message_new_empty(rtnl
, &m
);
82 size
= NLMSG_SPACE(type_get_size(nl_type
));
84 assert(size
>= sizeof(struct nlmsghdr
));
85 m
->hdr
= malloc0(size
);
89 m
->hdr
->nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
;
91 type_get_type_system(nl_type
, &m
->containers
[0].type_system
);
92 m
->hdr
->nlmsg_len
= size
;
93 m
->hdr
->nlmsg_type
= type
;
101 int sd_netlink_message_request_dump(sd_netlink_message
*m
, int dump
) {
102 assert_return(m
, -EINVAL
);
103 assert_return(m
->hdr
, -EINVAL
);
104 assert_return(m
->hdr
->nlmsg_type
== RTM_GETLINK
||
105 m
->hdr
->nlmsg_type
== RTM_GETADDR
||
106 m
->hdr
->nlmsg_type
== RTM_GETROUTE
||
107 m
->hdr
->nlmsg_type
== RTM_GETNEIGH
,
110 SET_FLAG(m
->hdr
->nlmsg_flags
, NLM_F_DUMP
, dump
);
115 sd_netlink_message
*sd_netlink_message_ref(sd_netlink_message
*m
) {
117 assert_se(REFCNT_INC(m
->n_ref
) >= 2);
122 sd_netlink_message
*sd_netlink_message_unref(sd_netlink_message
*m
) {
123 sd_netlink_message
*t
;
125 while (m
&& REFCNT_DEC(m
->n_ref
) == 0) {
130 for (i
= 0; i
<= m
->n_containers
; i
++)
131 free(m
->containers
[i
].attributes
);
141 int sd_netlink_message_get_type(sd_netlink_message
*m
, uint16_t *type
) {
142 assert_return(m
, -EINVAL
);
143 assert_return(type
, -EINVAL
);
145 *type
= m
->hdr
->nlmsg_type
;
150 int sd_netlink_message_set_flags(sd_netlink_message
*m
, uint16_t flags
) {
151 assert_return(m
, -EINVAL
);
152 assert_return(flags
, -EINVAL
);
154 m
->hdr
->nlmsg_flags
= flags
;
159 int sd_netlink_message_is_broadcast(sd_netlink_message
*m
) {
160 assert_return(m
, -EINVAL
);
165 /* If successful the updated message will be correctly aligned, if
166 unsuccessful the old message is untouched. */
167 static int add_rtattr(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t data_length
) {
169 size_t message_length
, padding_length
;
170 struct nlmsghdr
*new_hdr
;
179 assert(NLMSG_ALIGN(m
->hdr
->nlmsg_len
) == m
->hdr
->nlmsg_len
);
180 assert(!data
|| data_length
);
182 /* get offset of the new attribute */
183 offset
= m
->hdr
->nlmsg_len
;
185 /* get the size of the new rta attribute (with padding at the end) */
186 rta_length
= RTA_LENGTH(data_length
);
188 /* get the new message size (with padding at the end) */
189 message_length
= offset
+ RTA_ALIGN(rta_length
);
191 /* realloc to fit the new attribute */
192 new_hdr
= realloc(m
->hdr
, message_length
);
197 /* get pointer to the attribute we are about to add */
198 rta
= (struct rtattr
*) ((uint8_t *) m
->hdr
+ offset
);
200 /* if we are inside containers, extend them */
201 for (i
= 0; i
< m
->n_containers
; i
++)
202 GET_CONTAINER(m
, i
)->rta_len
+= message_length
- offset
;
204 /* fill in the attribute */
205 rta
->rta_type
= type
;
206 rta
->rta_len
= rta_length
;
208 /* we don't deal with the case where the user lies about the type
209 * and gives us too little data (so don't do that)
211 padding
= mempcpy(RTA_DATA(rta
), data
, data_length
);
214 /* if no data was passed, make sure we still initialize the padding
215 note that we can have data_length > 0 (used by some containers) */
216 padding
= RTA_DATA(rta
);
218 /* make sure also the padding at the end of the message is initialized */
219 padding_length
= (uint8_t*)m
->hdr
+ message_length
- (uint8_t*)padding
;
220 memzero(padding
, padding_length
);
222 /* update message size */
223 m
->hdr
->nlmsg_len
= message_length
;
228 static int message_attribute_has_type(sd_netlink_message
*m
, size_t *out_size
, uint16_t attribute_type
, uint16_t data_type
) {
234 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
, &type
, attribute_type
);
238 if (type_get_type(type
) != data_type
)
242 *out_size
= type_get_size(type
);
246 int sd_netlink_message_append_string(sd_netlink_message
*m
, unsigned short type
, const char *data
) {
250 assert_return(m
, -EINVAL
);
251 assert_return(!m
->sealed
, -EPERM
);
252 assert_return(data
, -EINVAL
);
254 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_STRING
);
259 length
= strnlen(data
, size
+1);
263 length
= strlen(data
);
265 r
= add_rtattr(m
, type
, data
, length
+ 1);
272 int sd_netlink_message_append_flag(sd_netlink_message
*m
, unsigned short type
) {
276 assert_return(m
, -EINVAL
);
277 assert_return(!m
->sealed
, -EPERM
);
279 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_FLAG
);
283 r
= add_rtattr(m
, type
, NULL
, 0);
290 int sd_netlink_message_append_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t data
) {
293 assert_return(m
, -EINVAL
);
294 assert_return(!m
->sealed
, -EPERM
);
296 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
300 r
= add_rtattr(m
, type
, &data
, sizeof(uint8_t));
308 int sd_netlink_message_append_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t data
) {
311 assert_return(m
, -EINVAL
);
312 assert_return(!m
->sealed
, -EPERM
);
314 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
318 r
= add_rtattr(m
, type
, &data
, sizeof(uint16_t));
325 int sd_netlink_message_append_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t data
) {
328 assert_return(m
, -EINVAL
);
329 assert_return(!m
->sealed
, -EPERM
);
331 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
335 r
= add_rtattr(m
, type
, &data
, sizeof(uint32_t));
342 int sd_netlink_message_append_data(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t len
) {
345 assert_return(m
, -EINVAL
);
346 assert_return(!m
->sealed
, -EPERM
);
348 r
= add_rtattr(m
, type
, data
, len
);
355 int sd_netlink_message_append_in_addr(sd_netlink_message
*m
, unsigned short type
, const struct in_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 in_addr
));
373 int sd_netlink_message_append_in6_addr(sd_netlink_message
*m
, unsigned short type
, const struct in6_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_IN_ADDR
);
384 r
= add_rtattr(m
, type
, data
, sizeof(struct in6_addr
));
391 int sd_netlink_message_append_ether_addr(sd_netlink_message
*m
, unsigned short type
, const struct ether_addr
*data
) {
394 assert_return(m
, -EINVAL
);
395 assert_return(!m
->sealed
, -EPERM
);
396 assert_return(data
, -EINVAL
);
398 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
402 r
= add_rtattr(m
, type
, data
, ETH_ALEN
);
409 int sd_netlink_message_append_cache_info(sd_netlink_message
*m
, unsigned short type
, const struct ifa_cacheinfo
*info
) {
412 assert_return(m
, -EINVAL
);
413 assert_return(!m
->sealed
, -EPERM
);
414 assert_return(info
, -EINVAL
);
416 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
420 r
= add_rtattr(m
, type
, info
, sizeof(struct ifa_cacheinfo
));
427 int sd_netlink_message_open_container(sd_netlink_message
*m
, unsigned short type
) {
431 assert_return(m
, -EINVAL
);
432 assert_return(!m
->sealed
, -EPERM
);
433 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -ERANGE
);
435 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_NESTED
);
437 const NLTypeSystemUnion
*type_system_union
;
440 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_UNION
);
444 r
= sd_rtnl_message_get_family(m
, &family
);
448 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
452 r
= type_system_union_protocol_get_type_system(type_system_union
,
453 &m
->containers
[m
->n_containers
+ 1].type_system
,
458 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
459 &m
->containers
[m
->n_containers
+ 1].type_system
,
465 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, size
);
469 m
->containers
[m
->n_containers
++].offset
= r
;
474 int sd_netlink_message_open_container_union(sd_netlink_message
*m
, unsigned short type
, const char *key
) {
475 const NLTypeSystemUnion
*type_system_union
;
478 assert_return(m
, -EINVAL
);
479 assert_return(!m
->sealed
, -EPERM
);
481 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
485 r
= type_system_union_get_type_system(type_system_union
,
486 &m
->containers
[m
->n_containers
+ 1].type_system
,
491 r
= sd_netlink_message_append_string(m
, type_system_union
->match
, key
);
495 /* do we evere need non-null size */
496 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, 0);
500 m
->containers
[m
->n_containers
++].offset
= r
;
506 int sd_netlink_message_close_container(sd_netlink_message
*m
) {
507 assert_return(m
, -EINVAL
);
508 assert_return(!m
->sealed
, -EPERM
);
509 assert_return(m
->n_containers
> 0, -EINVAL
);
511 m
->containers
[m
->n_containers
].type_system
= NULL
;
517 static int netlink_message_read_internal(sd_netlink_message
*m
, unsigned short type
, void **data
, bool *net_byteorder
) {
518 struct netlink_attribute
*attribute
;
521 assert_return(m
, -EINVAL
);
522 assert_return(m
->sealed
, -EPERM
);
523 assert_return(data
, -EINVAL
);
524 assert(m
->n_containers
< RTNL_CONTAINER_DEPTH
);
525 assert(m
->containers
[m
->n_containers
].attributes
);
526 assert(type
< m
->containers
[m
->n_containers
].n_attributes
);
528 attribute
= &m
->containers
[m
->n_containers
].attributes
[type
];
530 if (!attribute
->offset
)
533 rta
= (struct rtattr
*)((uint8_t *) m
->hdr
+ attribute
->offset
);
535 *data
= RTA_DATA(rta
);
538 *net_byteorder
= attribute
->net_byteorder
;
540 return RTA_PAYLOAD(rta
);
543 int sd_netlink_message_read_string(sd_netlink_message
*m
, unsigned short type
, const char **data
) {
547 assert_return(m
, -EINVAL
);
549 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_STRING
);
553 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
556 else if (strnlen(attr_data
, r
) >= (size_t) r
)
560 *data
= (const char *) attr_data
;
565 int sd_netlink_message_read_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t *data
) {
569 assert_return(m
, -EINVAL
);
571 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
575 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
578 else if ((size_t) r
< sizeof(uint8_t))
582 *data
= *(uint8_t *) attr_data
;
587 int sd_netlink_message_read_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t *data
) {
592 assert_return(m
, -EINVAL
);
594 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
598 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
601 else if ((size_t) r
< sizeof(uint16_t))
606 *data
= be16toh(*(uint16_t *) attr_data
);
608 *data
= *(uint16_t *) attr_data
;
614 int sd_netlink_message_read_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t *data
) {
619 assert_return(m
, -EINVAL
);
621 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
625 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
628 else if ((size_t)r
< sizeof(uint32_t))
633 *data
= be32toh(*(uint32_t *) attr_data
);
635 *data
= *(uint32_t *) attr_data
;
641 int sd_netlink_message_read_ether_addr(sd_netlink_message
*m
, unsigned short type
, struct ether_addr
*data
) {
645 assert_return(m
, -EINVAL
);
647 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
651 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
654 else if ((size_t)r
< sizeof(struct ether_addr
))
658 memcpy(data
, attr_data
, sizeof(struct ether_addr
));
663 int sd_netlink_message_read_cache_info(sd_netlink_message
*m
, unsigned short type
, struct ifa_cacheinfo
*info
) {
667 assert_return(m
, -EINVAL
);
669 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
673 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
676 else if ((size_t)r
< sizeof(struct ifa_cacheinfo
))
680 memcpy(info
, attr_data
, sizeof(struct ifa_cacheinfo
));
685 int sd_netlink_message_read_in_addr(sd_netlink_message
*m
, unsigned short type
, struct in_addr
*data
) {
689 assert_return(m
, -EINVAL
);
691 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
695 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
698 else if ((size_t)r
< sizeof(struct in_addr
))
702 memcpy(data
, attr_data
, sizeof(struct in_addr
));
707 int sd_netlink_message_read_in6_addr(sd_netlink_message
*m
, unsigned short type
, struct in6_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 in6_addr
))
724 memcpy(data
, attr_data
, sizeof(struct in6_addr
));
729 static int netlink_container_parse(sd_netlink_message
*m
,
730 struct netlink_container
*container
,
733 unsigned int rt_len
) {
734 _cleanup_free_
struct netlink_attribute
*attributes
= NULL
;
736 attributes
= new0(struct netlink_attribute
, count
);
740 for (; RTA_OK(rta
, rt_len
); rta
= RTA_NEXT(rta
, rt_len
)) {
743 type
= RTA_TYPE(rta
);
745 /* if the kernel is newer than the headers we used
746 when building, we ignore out-of-range attributes */
750 if (attributes
[type
].offset
)
751 log_debug("rtnl: message parse - overwriting repeated attribute");
753 attributes
[type
].offset
= (uint8_t *) rta
- (uint8_t *) m
->hdr
;
754 attributes
[type
].nested
= RTA_FLAGS(rta
) & NLA_F_NESTED
;
755 attributes
[type
].net_byteorder
= RTA_FLAGS(rta
) & NLA_F_NET_BYTEORDER
;
758 container
->attributes
= attributes
;
760 container
->n_attributes
= count
;
765 int sd_netlink_message_enter_container(sd_netlink_message
*m
, unsigned short type_id
) {
766 const NLType
*nl_type
;
767 const NLTypeSystem
*type_system
;
773 assert_return(m
, -EINVAL
);
774 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -EINVAL
);
776 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
,
782 type
= type_get_type(nl_type
);
784 if (type
== NETLINK_TYPE_NESTED
) {
785 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
790 } else if (type
== NETLINK_TYPE_UNION
) {
791 const NLTypeSystemUnion
*type_system_union
;
793 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
,
799 switch (type_system_union
->match_type
) {
800 case NL_MATCH_SIBLING
:
804 r
= sd_netlink_message_read_string(m
, type_system_union
->match
, &key
);
808 r
= type_system_union_get_type_system(type_system_union
,
816 case NL_MATCH_PROTOCOL
:
820 r
= sd_rtnl_message_get_family(m
, &family
);
824 r
= type_system_union_protocol_get_type_system(type_system_union
,
833 assert_not_reached("sd-netlink: invalid type system union type");
838 r
= netlink_message_read_internal(m
, type_id
, &container
, NULL
);
846 r
= netlink_container_parse(m
,
847 &m
->containers
[m
->n_containers
],
848 type_system_get_count(type_system
),
856 m
->containers
[m
->n_containers
].type_system
= type_system
;
861 int sd_netlink_message_exit_container(sd_netlink_message
*m
) {
862 assert_return(m
, -EINVAL
);
863 assert_return(m
->sealed
, -EINVAL
);
864 assert_return(m
->n_containers
> 0, -EINVAL
);
866 m
->containers
[m
->n_containers
].attributes
= mfree(m
->containers
[m
->n_containers
].attributes
);
867 m
->containers
[m
->n_containers
].type_system
= NULL
;
874 uint32_t rtnl_message_get_serial(sd_netlink_message
*m
) {
878 return m
->hdr
->nlmsg_seq
;
881 int sd_netlink_message_is_error(sd_netlink_message
*m
) {
883 assert_return(m
->hdr
, 0);
885 return m
->hdr
->nlmsg_type
== NLMSG_ERROR
;
888 int sd_netlink_message_get_errno(sd_netlink_message
*m
) {
889 struct nlmsgerr
*err
;
891 assert_return(m
, -EINVAL
);
892 assert_return(m
->hdr
, -EINVAL
);
894 if (!sd_netlink_message_is_error(m
))
897 err
= NLMSG_DATA(m
->hdr
);
902 int sd_netlink_message_rewind(sd_netlink_message
*m
) {
903 const NLType
*nl_type
;
909 assert_return(m
, -EINVAL
);
911 /* don't allow appending to message once parsed */
913 rtnl_message_seal(m
);
915 for (i
= 1; i
<= m
->n_containers
; i
++)
916 m
->containers
[i
].attributes
= mfree(m
->containers
[i
].attributes
);
920 if (m
->containers
[0].attributes
)
921 /* top-level attributes have already been parsed */
926 r
= type_system_get_type(&type_system_root
, &nl_type
, m
->hdr
->nlmsg_type
);
930 type
= type_get_type(nl_type
);
931 size
= type_get_size(nl_type
);
933 if (type
== NETLINK_TYPE_NESTED
) {
934 const NLTypeSystem
*type_system
;
936 type_get_type_system(nl_type
, &type_system
);
938 m
->containers
[0].type_system
= type_system
;
940 r
= netlink_container_parse(m
,
941 &m
->containers
[m
->n_containers
],
942 type_system_get_count(type_system
),
943 (struct rtattr
*)((uint8_t*)NLMSG_DATA(m
->hdr
) + NLMSG_ALIGN(size
)),
944 NLMSG_PAYLOAD(m
->hdr
, size
));
952 void rtnl_message_seal(sd_netlink_message
*m
) {
959 sd_netlink_message
*sd_netlink_message_next(sd_netlink_message
*m
) {
960 assert_return(m
, NULL
);