1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/in.h>
27 #include "socket-util.h"
28 #include "formats-util.h"
32 #include "sd-netlink.h"
33 #include "netlink-util.h"
34 #include "netlink-internal.h"
35 #include "netlink-types.h"
37 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : 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)
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_netlink_message_unref_ sd_netlink_message *m = NULL;
67 const NLType *nl_type;
71 r = type_system_get_type(NULL, &nl_type, type);
75 r = message_new_empty(rtnl, &m);
79 size = NLMSG_SPACE(type_get_size(nl_type));
81 assert(size >= sizeof(struct nlmsghdr));
82 m->hdr = malloc0(size);
86 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
88 if (type_get_type(nl_type) == NETLINK_TYPE_NESTED)
89 type_get_type_system(nl_type, &m->container_type_system[0]);
90 m->hdr->nlmsg_len = size;
91 m->hdr->nlmsg_type = type;
99 int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
100 assert_return(m, -EINVAL);
101 assert_return(m->hdr, -EINVAL);
102 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
103 m->hdr->nlmsg_type == RTM_GETADDR ||
104 m->hdr->nlmsg_type == RTM_GETROUTE ||
105 m->hdr->nlmsg_type == RTM_GETNEIGH,
109 m->hdr->nlmsg_flags |= NLM_F_DUMP;
111 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
116 sd_netlink_message *sd_netlink_message_ref(sd_netlink_message *m) {
118 assert_se(REFCNT_INC(m->n_ref) >= 2);
123 sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) {
124 if (m && REFCNT_DEC(m->n_ref) == 0) {
129 for (i = 0; i <= m->n_containers; i++)
130 free(m->rta_offset_tb[i]);
132 sd_netlink_message_unref(m->next);
140 int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type) {
141 assert_return(m, -EINVAL);
142 assert_return(type, -EINVAL);
144 *type = m->hdr->nlmsg_type;
149 int sd_netlink_message_is_broadcast(sd_netlink_message *m) {
150 assert_return(m, -EINVAL);
155 /* If successful the updated message will be correctly aligned, if
156 unsuccessful the old message is untouched. */
157 static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *data, size_t data_length) {
159 size_t message_length, padding_length;
160 struct nlmsghdr *new_hdr;
169 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
170 assert(!data || data_length);
172 /* get offset of the new attribute */
173 offset = m->hdr->nlmsg_len;
175 /* get the size of the new rta attribute (with padding at the end) */
176 rta_length = RTA_LENGTH(data_length);
178 /* get the new message size (with padding at the end) */
179 message_length = offset + RTA_ALIGN(rta_length);
181 /* realloc to fit the new attribute */
182 new_hdr = realloc(m->hdr, message_length);
187 /* get pointer to the attribute we are about to add */
188 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
190 /* if we are inside containers, extend them */
191 for (i = 0; i < m->n_containers; i++)
192 GET_CONTAINER(m, i)->rta_len += message_length - offset;
194 /* fill in the attribute */
195 rta->rta_type = type;
196 rta->rta_len = rta_length;
198 /* we don't deal with the case where the user lies about the type
199 * and gives us too little data (so don't do that)
201 padding = mempcpy(RTA_DATA(rta), data, data_length);
203 /* if no data was passed, make sure we still initialize the padding
204 note that we can have data_length > 0 (used by some containers) */
205 padding = RTA_DATA(rta);
208 /* make sure also the padding at the end of the message is initialized */
209 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
210 memzero(padding, padding_length);
212 /* update message size */
213 m->hdr->nlmsg_len = message_length;
218 static int message_attribute_has_type(sd_netlink_message *m, uint16_t attribute_type, uint16_t data_type) {
222 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
226 if (type_get_type(type) != data_type)
229 return type_get_size(type);
232 int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data) {
236 assert_return(m, -EINVAL);
237 assert_return(!m->sealed, -EPERM);
238 assert_return(data, -EINVAL);
240 r = message_attribute_has_type(m, type, NETLINK_TYPE_STRING);
247 length = strnlen(data, size+1);
251 length = strlen(data);
253 r = add_rtattr(m, type, data, length + 1);
260 int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data) {
263 assert_return(m, -EINVAL);
264 assert_return(!m->sealed, -EPERM);
266 r = message_attribute_has_type(m, type, NETLINK_TYPE_U8);
270 r = add_rtattr(m, type, &data, sizeof(uint8_t));
278 int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data) {
281 assert_return(m, -EINVAL);
282 assert_return(!m->sealed, -EPERM);
284 r = message_attribute_has_type(m, type, NETLINK_TYPE_U16);
288 r = add_rtattr(m, type, &data, sizeof(uint16_t));
295 int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data) {
298 assert_return(m, -EINVAL);
299 assert_return(!m->sealed, -EPERM);
301 r = message_attribute_has_type(m, type, NETLINK_TYPE_U32);
305 r = add_rtattr(m, type, &data, sizeof(uint32_t));
312 int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data) {
315 assert_return(m, -EINVAL);
316 assert_return(!m->sealed, -EPERM);
317 assert_return(data, -EINVAL);
319 r = message_attribute_has_type(m, type, NETLINK_TYPE_IN_ADDR);
323 r = add_rtattr(m, type, data, sizeof(struct in_addr));
330 int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data) {
333 assert_return(m, -EINVAL);
334 assert_return(!m->sealed, -EPERM);
335 assert_return(data, -EINVAL);
337 r = message_attribute_has_type(m, type, NETLINK_TYPE_IN_ADDR);
341 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
348 int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data) {
351 assert_return(m, -EINVAL);
352 assert_return(!m->sealed, -EPERM);
353 assert_return(data, -EINVAL);
355 r = message_attribute_has_type(m, type, NETLINK_TYPE_ETHER_ADDR);
359 r = add_rtattr(m, type, data, ETH_ALEN);
366 int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
369 assert_return(m, -EINVAL);
370 assert_return(!m->sealed, -EPERM);
371 assert_return(info, -EINVAL);
373 r = message_attribute_has_type(m, type, NETLINK_TYPE_CACHE_INFO);
377 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
384 int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type) {
388 assert_return(m, -EINVAL);
389 assert_return(!m->sealed, -EPERM);
390 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
392 r = message_attribute_has_type(m, type, NETLINK_TYPE_NESTED);
394 const NLTypeSystemUnion *type_system_union;
397 r = message_attribute_has_type(m, type, NETLINK_TYPE_UNION);
402 r = sd_rtnl_message_get_family(m, &family);
406 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
410 r = type_system_union_protocol_get_type_system(type_system_union,
411 &m->container_type_system[m->n_containers + 1],
418 r = type_system_get_type_system(m->container_type_system[m->n_containers],
419 &m->container_type_system[m->n_containers + 1],
425 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
429 m->container_offsets[m->n_containers ++] = r;
434 int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned short type, const char *key) {
435 const NLTypeSystemUnion *type_system_union;
438 assert_return(m, -EINVAL);
439 assert_return(!m->sealed, -EPERM);
441 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
445 r = type_system_union_get_type_system(type_system_union,
446 &m->container_type_system[m->n_containers + 1],
451 r = sd_netlink_message_append_string(m, type_system_union->match, key);
455 /* do we evere need non-null size */
456 r = add_rtattr(m, type, NULL, 0);
460 m->container_offsets[m->n_containers ++] = r;
466 int sd_netlink_message_close_container(sd_netlink_message *m) {
467 assert_return(m, -EINVAL);
468 assert_return(!m->sealed, -EPERM);
469 assert_return(m->n_containers > 0, -EINVAL);
471 m->container_type_system[m->n_containers] = NULL;
477 int rtnl_message_read_internal(sd_netlink_message *m, unsigned short type, void **data) {
480 assert_return(m, -EINVAL);
481 assert_return(m->sealed, -EPERM);
482 assert_return(data, -EINVAL);
483 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
484 assert(m->rta_offset_tb[m->n_containers]);
485 assert(type < m->rta_tb_size[m->n_containers]);
487 if(!m->rta_offset_tb[m->n_containers][type])
490 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
492 *data = RTA_DATA(rta);
494 return RTA_PAYLOAD(rta);
497 int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) {
501 assert_return(m, -EINVAL);
503 r = message_attribute_has_type(m, type, NETLINK_TYPE_STRING);
507 r = rtnl_message_read_internal(m, type, &attr_data);
510 else if (strnlen(attr_data, r) >= (size_t) r)
514 *data = (const char *) attr_data;
519 int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data) {
523 assert_return(m, -EINVAL);
525 r = message_attribute_has_type(m, type, NETLINK_TYPE_U8);
529 r = rtnl_message_read_internal(m, type, &attr_data);
532 else if ((size_t) r < sizeof(uint8_t))
536 *data = *(uint8_t *) attr_data;
541 int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data) {
545 assert_return(m, -EINVAL);
547 r = message_attribute_has_type(m, type, NETLINK_TYPE_U16);
551 r = rtnl_message_read_internal(m, type, &attr_data);
554 else if ((size_t) r < sizeof(uint16_t))
558 *data = *(uint16_t *) attr_data;
563 int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data) {
567 assert_return(m, -EINVAL);
569 r = message_attribute_has_type(m, type, NETLINK_TYPE_U32);
573 r = rtnl_message_read_internal(m, type, &attr_data);
576 else if ((size_t)r < sizeof(uint32_t))
580 *data = *(uint32_t *) attr_data;
585 int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short type, struct ether_addr *data) {
589 assert_return(m, -EINVAL);
591 r = message_attribute_has_type(m, type, NETLINK_TYPE_ETHER_ADDR);
595 r = rtnl_message_read_internal(m, type, &attr_data);
598 else if ((size_t)r < sizeof(struct ether_addr))
602 memcpy(data, attr_data, sizeof(struct ether_addr));
607 int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info) {
611 assert_return(m, -EINVAL);
613 r = message_attribute_has_type(m, type, NETLINK_TYPE_CACHE_INFO);
617 r = rtnl_message_read_internal(m, type, &attr_data);
620 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
624 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
629 int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) {
633 assert_return(m, -EINVAL);
635 r = message_attribute_has_type(m, type, NETLINK_TYPE_IN_ADDR);
639 r = rtnl_message_read_internal(m, type, &attr_data);
642 else if ((size_t)r < sizeof(struct in_addr))
646 memcpy(data, attr_data, sizeof(struct in_addr));
651 int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) {
655 assert_return(m, -EINVAL);
657 r = message_attribute_has_type(m, type, NETLINK_TYPE_IN_ADDR);
661 r = rtnl_message_read_internal(m, type, &attr_data);
664 else if ((size_t)r < sizeof(struct in6_addr))
668 memcpy(data, attr_data, sizeof(struct in6_addr));
673 int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type_id) {
674 const NLType *nl_type;
675 const NLTypeSystem *type_system;
681 assert_return(m, -EINVAL);
682 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
684 r = type_system_get_type(m->container_type_system[m->n_containers],
690 type = type_get_type(nl_type);
692 if (type == NETLINK_TYPE_NESTED) {
693 r = type_system_get_type_system(m->container_type_system[m->n_containers],
698 } else if (type == NETLINK_TYPE_UNION) {
699 const NLTypeSystemUnion *type_system_union;
701 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
707 switch (type_system_union->match_type) {
708 case NL_MATCH_SIBLING:
712 r = sd_netlink_message_read_string(m, type_system_union->match, &key);
716 r = type_system_union_get_type_system(type_system_union,
724 case NL_MATCH_PROTOCOL:
728 r = sd_rtnl_message_get_family(m, &family);
732 r = type_system_union_protocol_get_type_system(type_system_union,
741 assert_not_reached("sd-netlink: invalid type system union type");
746 r = rtnl_message_read_internal(m, type_id, &container);
754 r = rtnl_message_parse(m,
755 &m->rta_offset_tb[m->n_containers],
756 &m->rta_tb_size[m->n_containers],
757 type_system_get_max(type_system),
765 m->container_type_system[m->n_containers] = type_system;
770 int sd_netlink_message_exit_container(sd_netlink_message *m) {
771 assert_return(m, -EINVAL);
772 assert_return(m->sealed, -EINVAL);
773 assert_return(m->n_containers > 0, -EINVAL);
775 free(m->rta_offset_tb[m->n_containers]);
776 m->rta_offset_tb[m->n_containers] = NULL;
777 m->container_type_system[m->n_containers] = NULL;
784 uint32_t rtnl_message_get_serial(sd_netlink_message *m) {
788 return m->hdr->nlmsg_seq;
791 int sd_netlink_message_is_error(sd_netlink_message *m) {
793 assert_return(m->hdr, 0);
795 return m->hdr->nlmsg_type == NLMSG_ERROR;
798 int sd_netlink_message_get_errno(sd_netlink_message *m) {
799 struct nlmsgerr *err;
801 assert_return(m, -EINVAL);
802 assert_return(m->hdr, -EINVAL);
804 if (!sd_netlink_message_is_error(m))
807 err = NLMSG_DATA(m->hdr);
812 int rtnl_message_parse(sd_netlink_message *m,
813 size_t **rta_offset_tb,
814 unsigned short *rta_tb_size,
817 unsigned int rt_len) {
821 tb = new0(size_t, max + 1);
825 *rta_tb_size = max + 1;
827 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
828 type = RTA_TYPE(rta);
830 /* if the kernel is newer than the headers we used
831 when building, we ignore out-of-range attributes
837 log_debug("rtnl: message parse - overwriting repeated attribute");
839 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
847 int sd_netlink_message_rewind(sd_netlink_message *m) {
848 const NLType *nl_type;
854 assert_return(m, -EINVAL);
856 /* don't allow appending to message once parsed */
858 rtnl_message_seal(m);
860 for (i = 1; i <= m->n_containers; i++) {
861 free(m->rta_offset_tb[i]);
862 m->rta_offset_tb[i] = NULL;
863 m->rta_tb_size[i] = 0;
864 m->container_type_system[i] = NULL;
869 if (m->rta_offset_tb[0]) {
870 /* top-level attributes have already been parsed */
876 r = type_system_get_type(NULL, &nl_type, m->hdr->nlmsg_type);
880 type = type_get_type(nl_type);
881 size = type_get_size(nl_type);
883 if (type == NETLINK_TYPE_NESTED) {
884 const NLTypeSystem *type_system;
886 type_get_type_system(nl_type, &type_system);
888 m->container_type_system[0] = type_system;
890 r = rtnl_message_parse(m,
891 &m->rta_offset_tb[m->n_containers],
892 &m->rta_tb_size[m->n_containers],
893 type_system_get_max(type_system),
894 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
895 NLMSG_PAYLOAD(m->hdr, size));
903 void rtnl_message_seal(sd_netlink_message *m) {
910 sd_netlink_message *sd_netlink_message_next(sd_netlink_message *m) {
911 assert_return(m, NULL);