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
,
111 m
->hdr
->nlmsg_flags
|= NLM_F_DUMP
;
113 m
->hdr
->nlmsg_flags
&= ~NLM_F_DUMP
;
118 sd_netlink_message
*sd_netlink_message_ref(sd_netlink_message
*m
) {
120 assert_se(REFCNT_INC(m
->n_ref
) >= 2);
125 sd_netlink_message
*sd_netlink_message_unref(sd_netlink_message
*m
) {
126 if (m
&& REFCNT_DEC(m
->n_ref
) == 0) {
131 for (i
= 0; i
<= m
->n_containers
; i
++)
132 free(m
->containers
[i
].attributes
);
134 sd_netlink_message_unref(m
->next
);
142 int sd_netlink_message_get_type(sd_netlink_message
*m
, uint16_t *type
) {
143 assert_return(m
, -EINVAL
);
144 assert_return(type
, -EINVAL
);
146 *type
= m
->hdr
->nlmsg_type
;
151 int sd_netlink_message_set_flags(sd_netlink_message
*m
, uint16_t flags
) {
152 assert_return(m
, -EINVAL
);
153 assert_return(flags
, -EINVAL
);
155 m
->hdr
->nlmsg_flags
= flags
;
160 int sd_netlink_message_is_broadcast(sd_netlink_message
*m
) {
161 assert_return(m
, -EINVAL
);
166 /* If successful the updated message will be correctly aligned, if
167 unsuccessful the old message is untouched. */
168 static int add_rtattr(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t data_length
) {
170 size_t message_length
, padding_length
;
171 struct nlmsghdr
*new_hdr
;
180 assert(NLMSG_ALIGN(m
->hdr
->nlmsg_len
) == m
->hdr
->nlmsg_len
);
181 assert(!data
|| data_length
);
183 /* get offset of the new attribute */
184 offset
= m
->hdr
->nlmsg_len
;
186 /* get the size of the new rta attribute (with padding at the end) */
187 rta_length
= RTA_LENGTH(data_length
);
189 /* get the new message size (with padding at the end) */
190 message_length
= offset
+ RTA_ALIGN(rta_length
);
192 /* realloc to fit the new attribute */
193 new_hdr
= realloc(m
->hdr
, message_length
);
198 /* get pointer to the attribute we are about to add */
199 rta
= (struct rtattr
*) ((uint8_t *) m
->hdr
+ offset
);
201 /* if we are inside containers, extend them */
202 for (i
= 0; i
< m
->n_containers
; i
++)
203 GET_CONTAINER(m
, i
)->rta_len
+= message_length
- offset
;
205 /* fill in the attribute */
206 rta
->rta_type
= type
;
207 rta
->rta_len
= rta_length
;
209 /* we don't deal with the case where the user lies about the type
210 * and gives us too little data (so don't do that)
212 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
);
219 /* make sure also the padding at the end of the message is initialized */
220 padding_length
= (uint8_t*)m
->hdr
+ message_length
- (uint8_t*)padding
;
221 memzero(padding
, padding_length
);
223 /* update message size */
224 m
->hdr
->nlmsg_len
= message_length
;
229 static int message_attribute_has_type(sd_netlink_message
*m
, size_t *out_size
, uint16_t attribute_type
, uint16_t data_type
) {
235 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
, &type
, attribute_type
);
239 if (type_get_type(type
) != data_type
)
243 *out_size
= type_get_size(type
);
247 int sd_netlink_message_append_string(sd_netlink_message
*m
, unsigned short type
, const char *data
) {
251 assert_return(m
, -EINVAL
);
252 assert_return(!m
->sealed
, -EPERM
);
253 assert_return(data
, -EINVAL
);
255 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_STRING
);
260 length
= strnlen(data
, size
+1);
264 length
= strlen(data
);
266 r
= add_rtattr(m
, type
, data
, length
+ 1);
273 int sd_netlink_message_append_flag(sd_netlink_message
*m
, unsigned short type
) {
277 assert_return(m
, -EINVAL
);
278 assert_return(!m
->sealed
, -EPERM
);
280 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_FLAG
);
284 r
= add_rtattr(m
, type
, NULL
, 0);
291 int sd_netlink_message_append_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t data
) {
294 assert_return(m
, -EINVAL
);
295 assert_return(!m
->sealed
, -EPERM
);
297 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
301 r
= add_rtattr(m
, type
, &data
, sizeof(uint8_t));
309 int sd_netlink_message_append_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t data
) {
312 assert_return(m
, -EINVAL
);
313 assert_return(!m
->sealed
, -EPERM
);
315 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
319 r
= add_rtattr(m
, type
, &data
, sizeof(uint16_t));
326 int sd_netlink_message_append_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t data
) {
329 assert_return(m
, -EINVAL
);
330 assert_return(!m
->sealed
, -EPERM
);
332 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
336 r
= add_rtattr(m
, type
, &data
, sizeof(uint32_t));
343 int sd_netlink_message_append_data(sd_netlink_message
*m
, unsigned short type
, const void *data
, size_t len
) {
346 assert_return(m
, -EINVAL
);
347 assert_return(!m
->sealed
, -EPERM
);
349 r
= add_rtattr(m
, type
, &data
, len
);
356 int sd_netlink_message_append_in_addr(sd_netlink_message
*m
, unsigned short type
, const struct in_addr
*data
) {
359 assert_return(m
, -EINVAL
);
360 assert_return(!m
->sealed
, -EPERM
);
361 assert_return(data
, -EINVAL
);
363 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
367 r
= add_rtattr(m
, type
, data
, sizeof(struct in_addr
));
374 int sd_netlink_message_append_in6_addr(sd_netlink_message
*m
, unsigned short type
, const struct in6_addr
*data
) {
377 assert_return(m
, -EINVAL
);
378 assert_return(!m
->sealed
, -EPERM
);
379 assert_return(data
, -EINVAL
);
381 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
385 r
= add_rtattr(m
, type
, data
, sizeof(struct in6_addr
));
392 int sd_netlink_message_append_ether_addr(sd_netlink_message
*m
, unsigned short type
, const struct ether_addr
*data
) {
395 assert_return(m
, -EINVAL
);
396 assert_return(!m
->sealed
, -EPERM
);
397 assert_return(data
, -EINVAL
);
399 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
403 r
= add_rtattr(m
, type
, data
, ETH_ALEN
);
410 int sd_netlink_message_append_cache_info(sd_netlink_message
*m
, unsigned short type
, const struct ifa_cacheinfo
*info
) {
413 assert_return(m
, -EINVAL
);
414 assert_return(!m
->sealed
, -EPERM
);
415 assert_return(info
, -EINVAL
);
417 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
421 r
= add_rtattr(m
, type
, info
, sizeof(struct ifa_cacheinfo
));
428 int sd_netlink_message_open_container(sd_netlink_message
*m
, unsigned short type
) {
432 assert_return(m
, -EINVAL
);
433 assert_return(!m
->sealed
, -EPERM
);
434 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -ERANGE
);
436 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_NESTED
);
438 const NLTypeSystemUnion
*type_system_union
;
441 r
= message_attribute_has_type(m
, &size
, type
, NETLINK_TYPE_UNION
);
445 r
= sd_rtnl_message_get_family(m
, &family
);
449 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
453 r
= type_system_union_protocol_get_type_system(type_system_union
,
454 &m
->containers
[m
->n_containers
+ 1].type_system
,
459 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
460 &m
->containers
[m
->n_containers
+ 1].type_system
,
466 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, size
);
470 m
->containers
[m
->n_containers
++].offset
= r
;
475 int sd_netlink_message_open_container_union(sd_netlink_message
*m
, unsigned short type
, const char *key
) {
476 const NLTypeSystemUnion
*type_system_union
;
479 assert_return(m
, -EINVAL
);
480 assert_return(!m
->sealed
, -EPERM
);
482 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
, &type_system_union
, type
);
486 r
= type_system_union_get_type_system(type_system_union
,
487 &m
->containers
[m
->n_containers
+ 1].type_system
,
492 r
= sd_netlink_message_append_string(m
, type_system_union
->match
, key
);
496 /* do we evere need non-null size */
497 r
= add_rtattr(m
, type
| NLA_F_NESTED
, NULL
, 0);
501 m
->containers
[m
->n_containers
++].offset
= r
;
507 int sd_netlink_message_close_container(sd_netlink_message
*m
) {
508 assert_return(m
, -EINVAL
);
509 assert_return(!m
->sealed
, -EPERM
);
510 assert_return(m
->n_containers
> 0, -EINVAL
);
512 m
->containers
[m
->n_containers
].type_system
= NULL
;
518 static int netlink_message_read_internal(sd_netlink_message
*m
, unsigned short type
, void **data
, bool *net_byteorder
) {
519 struct netlink_attribute
*attribute
;
522 assert_return(m
, -EINVAL
);
523 assert_return(m
->sealed
, -EPERM
);
524 assert_return(data
, -EINVAL
);
525 assert(m
->n_containers
< RTNL_CONTAINER_DEPTH
);
526 assert(m
->containers
[m
->n_containers
].attributes
);
527 assert(type
< m
->containers
[m
->n_containers
].n_attributes
);
529 attribute
= &m
->containers
[m
->n_containers
].attributes
[type
];
531 if(!attribute
->offset
)
534 rta
= (struct rtattr
*)((uint8_t *) m
->hdr
+ attribute
->offset
);
536 *data
= RTA_DATA(rta
);
539 *net_byteorder
= attribute
->net_byteorder
;
541 return RTA_PAYLOAD(rta
);
544 int sd_netlink_message_read_string(sd_netlink_message
*m
, unsigned short type
, const char **data
) {
548 assert_return(m
, -EINVAL
);
550 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_STRING
);
554 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
557 else if (strnlen(attr_data
, r
) >= (size_t) r
)
561 *data
= (const char *) attr_data
;
566 int sd_netlink_message_read_u8(sd_netlink_message
*m
, unsigned short type
, uint8_t *data
) {
570 assert_return(m
, -EINVAL
);
572 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U8
);
576 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
579 else if ((size_t) r
< sizeof(uint8_t))
583 *data
= *(uint8_t *) attr_data
;
588 int sd_netlink_message_read_u16(sd_netlink_message
*m
, unsigned short type
, uint16_t *data
) {
593 assert_return(m
, -EINVAL
);
595 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U16
);
599 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
602 else if ((size_t) r
< sizeof(uint16_t))
607 *data
= be16toh(*(uint16_t *) attr_data
);
609 *data
= *(uint16_t *) attr_data
;
615 int sd_netlink_message_read_u32(sd_netlink_message
*m
, unsigned short type
, uint32_t *data
) {
620 assert_return(m
, -EINVAL
);
622 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_U32
);
626 r
= netlink_message_read_internal(m
, type
, &attr_data
, &net_byteorder
);
629 else if ((size_t)r
< sizeof(uint32_t))
634 *data
= be32toh(*(uint32_t *) attr_data
);
636 *data
= *(uint32_t *) attr_data
;
642 int sd_netlink_message_read_ether_addr(sd_netlink_message
*m
, unsigned short type
, struct ether_addr
*data
) {
646 assert_return(m
, -EINVAL
);
648 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_ETHER_ADDR
);
652 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
655 else if ((size_t)r
< sizeof(struct ether_addr
))
659 memcpy(data
, attr_data
, sizeof(struct ether_addr
));
664 int sd_netlink_message_read_cache_info(sd_netlink_message
*m
, unsigned short type
, struct ifa_cacheinfo
*info
) {
668 assert_return(m
, -EINVAL
);
670 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_CACHE_INFO
);
674 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
677 else if ((size_t)r
< sizeof(struct ifa_cacheinfo
))
681 memcpy(info
, attr_data
, sizeof(struct ifa_cacheinfo
));
686 int sd_netlink_message_read_in_addr(sd_netlink_message
*m
, unsigned short type
, struct in_addr
*data
) {
690 assert_return(m
, -EINVAL
);
692 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
696 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
699 else if ((size_t)r
< sizeof(struct in_addr
))
703 memcpy(data
, attr_data
, sizeof(struct in_addr
));
708 int sd_netlink_message_read_in6_addr(sd_netlink_message
*m
, unsigned short type
, struct in6_addr
*data
) {
712 assert_return(m
, -EINVAL
);
714 r
= message_attribute_has_type(m
, NULL
, type
, NETLINK_TYPE_IN_ADDR
);
718 r
= netlink_message_read_internal(m
, type
, &attr_data
, NULL
);
721 else if ((size_t)r
< sizeof(struct in6_addr
))
725 memcpy(data
, attr_data
, sizeof(struct in6_addr
));
730 static int netlink_container_parse(sd_netlink_message
*m
,
731 struct netlink_container
*container
,
734 unsigned int rt_len
) {
735 _cleanup_free_
struct netlink_attribute
*attributes
= NULL
;
737 attributes
= new0(struct netlink_attribute
, count
);
741 for (; RTA_OK(rta
, rt_len
); rta
= RTA_NEXT(rta
, rt_len
)) {
744 type
= RTA_TYPE(rta
);
746 /* if the kernel is newer than the headers we used
747 when building, we ignore out-of-range attributes */
751 if (attributes
[type
].offset
)
752 log_debug("rtnl: message parse - overwriting repeated attribute");
754 attributes
[type
].offset
= (uint8_t *) rta
- (uint8_t *) m
->hdr
;
755 attributes
[type
].nested
= RTA_FLAGS(rta
) & NLA_F_NESTED
;
756 attributes
[type
].net_byteorder
= RTA_FLAGS(rta
) & NLA_F_NET_BYTEORDER
;
759 container
->attributes
= attributes
;
761 container
->n_attributes
= count
;
766 int sd_netlink_message_enter_container(sd_netlink_message
*m
, unsigned short type_id
) {
767 const NLType
*nl_type
;
768 const NLTypeSystem
*type_system
;
774 assert_return(m
, -EINVAL
);
775 assert_return(m
->n_containers
< RTNL_CONTAINER_DEPTH
, -EINVAL
);
777 r
= type_system_get_type(m
->containers
[m
->n_containers
].type_system
,
783 type
= type_get_type(nl_type
);
785 if (type
== NETLINK_TYPE_NESTED
) {
786 r
= type_system_get_type_system(m
->containers
[m
->n_containers
].type_system
,
791 } else if (type
== NETLINK_TYPE_UNION
) {
792 const NLTypeSystemUnion
*type_system_union
;
794 r
= type_system_get_type_system_union(m
->containers
[m
->n_containers
].type_system
,
800 switch (type_system_union
->match_type
) {
801 case NL_MATCH_SIBLING
:
805 r
= sd_netlink_message_read_string(m
, type_system_union
->match
, &key
);
809 r
= type_system_union_get_type_system(type_system_union
,
817 case NL_MATCH_PROTOCOL
:
821 r
= sd_rtnl_message_get_family(m
, &family
);
825 r
= type_system_union_protocol_get_type_system(type_system_union
,
834 assert_not_reached("sd-netlink: invalid type system union type");
839 r
= netlink_message_read_internal(m
, type_id
, &container
, NULL
);
847 r
= netlink_container_parse(m
,
848 &m
->containers
[m
->n_containers
],
849 type_system_get_count(type_system
),
857 m
->containers
[m
->n_containers
].type_system
= type_system
;
862 int sd_netlink_message_exit_container(sd_netlink_message
*m
) {
863 assert_return(m
, -EINVAL
);
864 assert_return(m
->sealed
, -EINVAL
);
865 assert_return(m
->n_containers
> 0, -EINVAL
);
867 m
->containers
[m
->n_containers
].attributes
= mfree(m
->containers
[m
->n_containers
].attributes
);
868 m
->containers
[m
->n_containers
].type_system
= NULL
;
875 uint32_t rtnl_message_get_serial(sd_netlink_message
*m
) {
879 return m
->hdr
->nlmsg_seq
;
882 int sd_netlink_message_is_error(sd_netlink_message
*m
) {
884 assert_return(m
->hdr
, 0);
886 return m
->hdr
->nlmsg_type
== NLMSG_ERROR
;
889 int sd_netlink_message_get_errno(sd_netlink_message
*m
) {
890 struct nlmsgerr
*err
;
892 assert_return(m
, -EINVAL
);
893 assert_return(m
->hdr
, -EINVAL
);
895 if (!sd_netlink_message_is_error(m
))
898 err
= NLMSG_DATA(m
->hdr
);
903 int sd_netlink_message_rewind(sd_netlink_message
*m
) {
904 const NLType
*nl_type
;
910 assert_return(m
, -EINVAL
);
912 /* don't allow appending to message once parsed */
914 rtnl_message_seal(m
);
916 for (i
= 1; i
<= m
->n_containers
; i
++)
917 m
->containers
[i
].attributes
= mfree(m
->containers
[i
].attributes
);
921 if (m
->containers
[0].attributes
)
922 /* top-level attributes have already been parsed */
927 r
= type_system_get_type(&type_system_root
, &nl_type
, m
->hdr
->nlmsg_type
);
931 type
= type_get_type(nl_type
);
932 size
= type_get_size(nl_type
);
934 if (type
== NETLINK_TYPE_NESTED
) {
935 const NLTypeSystem
*type_system
;
937 type_get_type_system(nl_type
, &type_system
);
939 m
->containers
[0].type_system
= type_system
;
941 r
= netlink_container_parse(m
,
942 &m
->containers
[m
->n_containers
],
943 type_system_get_count(type_system
),
944 (struct rtattr
*)((uint8_t*)NLMSG_DATA(m
->hdr
) + NLMSG_ALIGN(size
)),
945 NLMSG_PAYLOAD(m
->hdr
, size
));
953 void rtnl_message_seal(sd_netlink_message
*m
) {
960 sd_netlink_message
*sd_netlink_message_next(sd_netlink_message
*m
) {
961 assert_return(m
, NULL
);