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>
23 #include <netinet/ether.h>
26 #include <linux/netlink.h>
27 #include <linux/veth.h>
30 #include <linux/if_tunnel.h>
31 #include <linux/if_bridge.h>
38 #include "rtnl-util.h"
39 #include "rtnl-internal.h"
40 #include "rtnl-types.h"
42 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
43 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
45 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
48 assert_return(ret, -EINVAL);
50 /* Note that 'rtnl' is curretly unused, if we start using it internally
51 we must take care to avoid problems due to mutual references between
52 busses and their queued messages. See sd-bus.
55 m = new0(sd_rtnl_message, 1);
59 m->n_ref = REFCNT_INIT;
68 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
69 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
70 const NLType *nl_type;
74 r = type_system_get_type(NULL, &nl_type, type);
78 assert(nl_type->type == NLA_NESTED);
80 r = message_new_empty(rtnl, &m);
84 size = NLMSG_SPACE(nl_type->size);
86 assert(size >= sizeof(struct nlmsghdr));
87 m->hdr = malloc0(size);
91 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
93 m->container_type_system[0] = nl_type->type_system;
94 m->hdr->nlmsg_len = size;
95 m->hdr->nlmsg_type = type;
103 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
106 assert_return(m, -EINVAL);
107 assert_return(m->hdr, -EINVAL);
108 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
110 rtm = NLMSG_DATA(m->hdr);
112 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
113 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
116 rtm->rtm_dst_len = prefixlen;
121 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
124 assert_return(m, -EINVAL);
125 assert_return(m->hdr, -EINVAL);
126 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
128 rtm = NLMSG_DATA(m->hdr);
130 rtm->rtm_scope = scope;
135 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
136 uint16_t nlmsg_type, unsigned char rtm_family) {
140 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
141 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
142 assert_return(ret, -EINVAL);
144 r = message_new(rtnl, ret, nlmsg_type);
148 if (nlmsg_type == RTM_NEWROUTE)
149 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
151 rtm = NLMSG_DATA((*ret)->hdr);
153 rtm->rtm_family = rtm_family;
154 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
155 rtm->rtm_type = RTN_UNICAST;
156 rtm->rtm_table = RT_TABLE_MAIN;
157 rtm->rtm_protocol = RTPROT_BOOT;
162 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
163 struct ifinfomsg *ifi;
165 assert_return(m, -EINVAL);
166 assert_return(m->hdr, -EINVAL);
167 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
168 assert_return(change, -EINVAL);
170 ifi = NLMSG_DATA(m->hdr);
172 ifi->ifi_flags = flags;
173 ifi->ifi_change = change;
178 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
179 struct ifinfomsg *ifi;
181 assert_return(m, -EINVAL);
182 assert_return(m->hdr, -EINVAL);
183 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
185 ifi = NLMSG_DATA(m->hdr);
187 ifi->ifi_type = type;
192 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
193 uint16_t nlmsg_type, int index) {
194 struct ifinfomsg *ifi;
197 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
198 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
199 assert_return(ret, -EINVAL);
201 r = message_new(rtnl, ret, nlmsg_type);
205 if (nlmsg_type == RTM_NEWLINK)
206 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
208 ifi = NLMSG_DATA((*ret)->hdr);
210 ifi->ifi_family = AF_UNSPEC;
211 ifi->ifi_index = index;
216 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
217 struct ifaddrmsg *ifa;
219 assert_return(m, -EINVAL);
220 assert_return(m->hdr, -EINVAL);
221 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
223 ifa = NLMSG_DATA(m->hdr);
225 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
226 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
229 ifa->ifa_prefixlen = prefixlen;
234 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
235 struct ifaddrmsg *ifa;
237 assert_return(m, -EINVAL);
238 assert_return(m->hdr, -EINVAL);
239 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
241 ifa = NLMSG_DATA(m->hdr);
243 ifa->ifa_flags = flags;
248 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
249 struct ifaddrmsg *ifa;
251 assert_return(m, -EINVAL);
252 assert_return(m->hdr, -EINVAL);
253 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
255 ifa = NLMSG_DATA(m->hdr);
257 ifa->ifa_scope = scope;
262 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, unsigned char *family) {
263 struct ifaddrmsg *ifa;
265 assert_return(m, -EINVAL);
266 assert_return(m->hdr, -EINVAL);
267 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
268 assert_return(family, -EINVAL);
270 ifa = NLMSG_DATA(m->hdr);
272 *family = ifa->ifa_family;
277 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
278 struct ifaddrmsg *ifa;
280 assert_return(m, -EINVAL);
281 assert_return(m->hdr, -EINVAL);
282 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
283 assert_return(scope, -EINVAL);
285 ifa = NLMSG_DATA(m->hdr);
287 *scope = ifa->ifa_scope;
292 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
293 struct ifaddrmsg *ifa;
295 assert_return(m, -EINVAL);
296 assert_return(m->hdr, -EINVAL);
297 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
298 assert_return(flags, -EINVAL);
300 ifa = NLMSG_DATA(m->hdr);
302 *flags = ifa->ifa_flags;
307 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
308 struct ifaddrmsg *ifa;
310 assert_return(m, -EINVAL);
311 assert_return(m->hdr, -EINVAL);
312 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
313 assert_return(ifindex, -EINVAL);
315 ifa = NLMSG_DATA(m->hdr);
317 *ifindex = ifa->ifa_index;
322 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
323 uint16_t nlmsg_type, int index,
324 unsigned char family) {
325 struct ifaddrmsg *ifa;
328 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
329 assert_return(index > 0, -EINVAL);
330 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
331 assert_return(ret, -EINVAL);
333 r = message_new(rtnl, ret, nlmsg_type);
337 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
338 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
340 ifa = NLMSG_DATA((*ret)->hdr);
342 ifa->ifa_index = index;
343 ifa->ifa_family = family;
344 if (family == AF_INET)
345 ifa->ifa_prefixlen = 32;
346 else if (family == AF_INET6)
347 ifa->ifa_prefixlen = 128;
352 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
353 int index, unsigned char family) {
356 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
360 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
365 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
367 assert_se(REFCNT_INC(m->n_ref) >= 2);
372 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
373 if (m && REFCNT_DEC(m->n_ref) <= 0) {
378 for (i = 0; i <= m->n_containers; i++)
379 free(m->rta_offset_tb[i]);
387 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
388 assert_return(m, -EINVAL);
389 assert_return(type, -EINVAL);
391 *type = m->hdr->nlmsg_type;
396 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
397 assert_return(m, -EINVAL);
399 return !m->hdr->nlmsg_pid;
402 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
403 struct ifinfomsg *ifi;
405 assert_return(m, -EINVAL);
406 assert_return(m->hdr, -EINVAL);
407 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
408 assert_return(ifindex, -EINVAL);
410 ifi = NLMSG_DATA(m->hdr);
412 *ifindex = ifi->ifi_index;
417 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
418 struct ifinfomsg *ifi;
420 assert_return(m, -EINVAL);
421 assert_return(m->hdr, -EINVAL);
422 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
423 assert_return(flags, -EINVAL);
425 ifi = NLMSG_DATA(m->hdr);
427 *flags = ifi->ifi_flags;
432 /* If successful the updated message will be correctly aligned, if
433 unsuccessful the old message is untouched. */
434 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
435 uint32_t rta_length, message_length;
436 struct nlmsghdr *new_hdr;
444 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
445 assert(!data || data_length > 0);
446 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
448 /* get the size of the new rta attribute (with padding at the end) */
449 rta_length = RTA_LENGTH(data_length);
451 /* get the new message size (with padding at the end) */
452 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
454 /* realloc to fit the new attribute */
455 new_hdr = realloc(m->hdr, message_length);
460 /* get pointer to the attribute we are about to add */
461 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
463 /* if we are inside containers, extend them */
464 for (i = 0; i < m->n_containers; i++)
465 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
467 /* fill in the attribute */
468 rta->rta_type = type;
469 rta->rta_len = rta_length;
471 //TODO: simply return this value rather than check for !data
472 /* this is the start of a new container */
473 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
475 /* we don't deal with the case where the user lies about the type
476 * and gives us too little data (so don't do that)
478 padding = mempcpy(RTA_DATA(rta), data, data_length);
479 /* make sure also the padding at the end of the message is initialized */
481 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
484 /* update message size */
485 m->hdr->nlmsg_len = message_length;
490 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
494 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
498 if (type->type != data_type)
504 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
508 assert_return(m, -EINVAL);
509 assert_return(!m->sealed, -EPERM);
510 assert_return(data, -EINVAL);
512 r = message_attribute_has_type(m, type, NLA_STRING);
519 length = strnlen(data, size);
523 length = strlen(data);
525 r = add_rtattr(m, type, data, length + 1);
532 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
535 assert_return(m, -EINVAL);
536 assert_return(!m->sealed, -EPERM);
538 r = message_attribute_has_type(m, type, NLA_U8);
542 r = add_rtattr(m, type, &data, sizeof(uint8_t));
550 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
553 assert_return(m, -EINVAL);
554 assert_return(!m->sealed, -EPERM);
556 r = message_attribute_has_type(m, type, NLA_U16);
560 r = add_rtattr(m, type, &data, sizeof(uint16_t));
567 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
570 assert_return(m, -EINVAL);
571 assert_return(!m->sealed, -EPERM);
573 r = message_attribute_has_type(m, type, NLA_U32);
577 r = add_rtattr(m, type, &data, sizeof(uint32_t));
584 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
587 assert_return(m, -EINVAL);
588 assert_return(!m->sealed, -EPERM);
589 assert_return(data, -EINVAL);
591 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
595 r = add_rtattr(m, type, data, sizeof(struct in_addr));
602 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
605 assert_return(m, -EINVAL);
606 assert_return(!m->sealed, -EPERM);
607 assert_return(data, -EINVAL);
609 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
613 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
620 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
623 assert_return(m, -EINVAL);
624 assert_return(!m->sealed, -EPERM);
625 assert_return(data, -EINVAL);
627 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
631 r = add_rtattr(m, type, data, ETH_ALEN);
638 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
641 assert_return(m, -EINVAL);
642 assert_return(!m->sealed, -EPERM);
643 assert_return(info, -EINVAL);
645 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
649 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
656 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
660 assert_return(m, -EINVAL);
661 assert_return(!m->sealed, -EPERM);
663 r = message_attribute_has_type(m, type, NLA_NESTED);
669 r = type_system_get_type_system(m->container_type_system[m->n_containers],
670 &m->container_type_system[m->n_containers + 1],
675 r = add_rtattr(m, type, NULL, size);
682 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
683 const NLTypeSystemUnion *type_system_union;
686 assert_return(m, -EINVAL);
687 assert_return(!m->sealed, -EPERM);
689 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
693 r = type_system_union_get_type_system(type_system_union,
694 &m->container_type_system[m->n_containers + 1],
699 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
703 /* do we evere need non-null size */
704 r = add_rtattr(m, type, NULL, 0);
712 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
713 assert_return(m, -EINVAL);
714 assert_return(!m->sealed, -EPERM);
715 assert_return(m->n_containers > 0, -EINVAL);
717 m->container_type_system[m->n_containers] = NULL;
723 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
726 assert_return(m, -EINVAL);
727 assert_return(m->sealed, -EPERM);
728 assert_return(data, -EINVAL);
729 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
730 assert(m->rta_offset_tb[m->n_containers]);
731 assert(type < m->rta_tb_size[m->n_containers]);
733 if(!m->rta_offset_tb[m->n_containers][type])
736 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
738 *data = RTA_DATA(rta);
740 return RTA_PAYLOAD(rta);
743 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
747 r = message_attribute_has_type(m, type, NLA_STRING);
751 r = rtnl_message_read_internal(m, type, &attr_data);
754 else if (strnlen(attr_data, r) >= (size_t) r)
757 *data = (char *) attr_data;
762 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
766 r = message_attribute_has_type(m, type, NLA_U8);
770 r = rtnl_message_read_internal(m, type, &attr_data);
773 else if ((size_t) r < sizeof(uint8_t))
776 *data = *(uint8_t *) attr_data;
781 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
785 r = message_attribute_has_type(m, type, NLA_U16);
789 r = rtnl_message_read_internal(m, type, &attr_data);
792 else if ((size_t) r < sizeof(uint16_t))
795 *data = *(uint16_t *) attr_data;
800 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
804 r = message_attribute_has_type(m, type, NLA_U32);
808 r = rtnl_message_read_internal(m, type, &attr_data);
811 else if ((size_t)r < sizeof(uint32_t))
814 *data = *(uint32_t *) attr_data;
819 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
823 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
827 r = rtnl_message_read_internal(m, type, &attr_data);
830 else if ((size_t)r < sizeof(struct ether_addr))
833 memcpy(data, attr_data, sizeof(struct ether_addr));
838 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
842 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
846 r = rtnl_message_read_internal(m, type, &attr_data);
849 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
852 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
857 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
861 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
865 r = rtnl_message_read_internal(m, type, &attr_data);
868 else if ((size_t)r < sizeof(struct in_addr))
871 memcpy(data, attr_data, sizeof(struct in_addr));
876 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
880 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
884 r = rtnl_message_read_internal(m, type, &attr_data);
887 else if ((size_t)r < sizeof(struct in6_addr))
890 memcpy(data, attr_data, sizeof(struct in6_addr));
895 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
896 const NLType *nl_type;
897 const NLTypeSystem *type_system;
902 assert_return(m, -EINVAL);
903 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
905 r = type_system_get_type(m->container_type_system[m->n_containers],
911 if (nl_type->type == NLA_NESTED) {
912 r = type_system_get_type_system(m->container_type_system[m->n_containers],
917 } else if (nl_type->type == NLA_UNION) {
918 const NLTypeSystemUnion *type_system_union;
921 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
927 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
931 r = type_system_union_get_type_system(type_system_union,
939 r = rtnl_message_read_internal(m, type, &container);
947 r = rtnl_message_parse(m,
948 &m->rta_offset_tb[m->n_containers],
949 &m->rta_tb_size[m->n_containers],
958 m->container_type_system[m->n_containers] = type_system;
963 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
964 assert_return(m, -EINVAL);
965 assert_return(m->sealed, -EINVAL);
966 assert_return(m->n_containers > 0, -EINVAL);
968 free(m->rta_offset_tb[m->n_containers]);
969 m->rta_offset_tb[m->n_containers] = NULL;
970 m->container_type_system[m->n_containers] = NULL;
977 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
981 return m->hdr->nlmsg_seq;
984 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
985 struct nlmsgerr *err;
987 assert_return(m, -EINVAL);
988 assert_return(m->hdr, -EINVAL);
990 if (m->hdr->nlmsg_type != NLMSG_ERROR)
993 err = NLMSG_DATA(m->hdr);
998 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
1002 /* ioctl(rtnl->fd, FIONREAD, &need)
1003 Does not appear to work on netlink sockets. libnl uses
1004 MSG_PEEK instead. I don't know if that is worth the
1007 For now we simply use the maximum message size the kernel
1008 may use (NLMSG_GOODSIZE), and then realloc to the actual
1009 size after reading the message (hence avoiding huge memory
1010 usage in case many small messages are kept around) */
1011 *need = page_size();
1018 int rtnl_message_parse(sd_rtnl_message *m,
1019 size_t **rta_offset_tb,
1020 unsigned short *rta_tb_size,
1023 unsigned int rt_len) {
1024 unsigned short type;
1027 tb = new0(size_t, max + 1);
1031 *rta_tb_size = max + 1;
1033 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1034 type = rta->rta_type;
1036 /* if the kernel is newer than the headers we used
1037 when building, we ignore out-of-range attributes
1043 log_debug("rtnl: message parse - overwriting repeated attribute");
1045 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1048 *rta_offset_tb = tb;
1053 /* returns the number of bytes sent, or a negative error code */
1054 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1057 struct sockaddr_nl nl;
1059 .nl.nl_family = AF_NETLINK,
1067 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1068 0, &addr.sa, sizeof(addr));
1070 return (errno == EAGAIN) ? 0 : -errno;
1075 /* On success, the number of bytes received is returned and *ret points to the received message
1076 * which has a valid header and the correct size.
1077 * If nothing useful was received 0 is returned.
1078 * On failure, a negative error code is returned.
1080 int socket_read_message(sd_rtnl *rtnl) {
1081 _cleanup_free_ void *buffer = NULL;
1082 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
1083 struct iovec iov = {};
1084 struct msghdr msg = {
1087 .msg_control = cred_buffer,
1088 .msg_controllen = sizeof(cred_buffer),
1090 struct cmsghdr *cmsg;
1092 struct nlmsghdr *new_msg;
1098 r = message_receive_need(rtnl, &need);
1102 buffer = malloc0(need);
1106 iov.iov_base = buffer;
1109 r = recvmsg(rtnl->fd, &msg, 0);
1112 return (errno == EAGAIN) ? 0 : -errno;
1114 /* connection was closed by the kernel */
1119 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1120 if (cmsg->cmsg_level == SOL_SOCKET &&
1121 cmsg->cmsg_type == SCM_CREDENTIALS &&
1122 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1123 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1125 /* from the kernel */
1126 if (ucred->uid == 0 && ucred->pid == 0) {
1134 /* not from the kernel, ignore */
1137 for (new_msg = buffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1138 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1139 const NLType *nl_type;
1141 if (new_msg->nlmsg_pid && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1142 /* not broadcast and not for us */
1145 /* silently drop noop messages */
1146 if (new_msg->nlmsg_type == NLMSG_NOOP)
1149 /* check that we support this message type */
1150 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1153 log_debug("sd-rtnl: ignored message with unknown type: %u",
1154 new_msg->nlmsg_type);
1159 /* check that the size matches the message type */
1160 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1163 r = message_new_empty(rtnl, &m);
1167 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1171 /* seal and parse the top-level message */
1172 r = sd_rtnl_message_rewind(m);
1176 r = rtnl_rqueue_make_room(rtnl);
1180 rtnl->rqueue[rtnl->rqueue_size ++] = m;
1182 ret += new_msg->nlmsg_len;
1184 /* reached end of multi-part message, or not a multi-part
1186 if (new_msg->nlmsg_type == NLMSG_DONE ||
1187 !(new_msg->nlmsg_flags & NLM_F_MULTI))
1194 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1199 assert_return(m, -EINVAL);
1201 /* don't allow appending to message once parsed */
1203 rtnl_message_seal(m);
1205 for (i = 1; i <= m->n_containers; i++) {
1206 free(m->rta_offset_tb[i]);
1207 m->rta_offset_tb[i] = NULL;
1208 m->rta_tb_size[i] = 0;
1209 m->container_type_system[i] = NULL;
1212 m->n_containers = 0;
1214 if (m->rta_offset_tb[0]) {
1215 /* top-level attributes have already been parsed */
1221 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1225 if (type->type == NLA_NESTED) {
1226 const NLTypeSystem *type_system = type->type_system;
1228 assert(type_system);
1230 m->container_type_system[0] = type_system;
1232 r = rtnl_message_parse(m,
1233 &m->rta_offset_tb[m->n_containers],
1234 &m->rta_tb_size[m->n_containers],
1236 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1237 NLMSG_ALIGN(type->size)),
1238 NLMSG_PAYLOAD(m->hdr, type->size));
1246 void rtnl_message_seal(sd_rtnl_message *m) {