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, size_t initial_size) {
48 assert_return(ret, -EINVAL);
49 assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
51 /* Note that 'rtnl' is curretly unused, if we start using it internally
52 we must take care to avoid problems due to mutual references between
53 busses and their queued messages. See sd-bus.
56 m = new0(sd_rtnl_message, 1);
60 m->hdr = malloc0(initial_size);
66 m->n_ref = REFCNT_INIT;
68 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
76 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
77 const NLType *nl_type;
81 r = type_system_get_type(NULL, &nl_type, type);
85 assert(nl_type->type == NLA_NESTED);
87 size = NLMSG_SPACE(nl_type->size);
89 r = message_new_empty(rtnl, ret, size);
93 (*ret)->container_type_system[0] = nl_type->type_system;
94 (*ret)->hdr->nlmsg_len = size;
95 (*ret)->hdr->nlmsg_type = type;
100 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
103 assert_return(m, -EINVAL);
104 assert_return(m->hdr, -EINVAL);
105 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
107 rtm = NLMSG_DATA(m->hdr);
109 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
110 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
113 rtm->rtm_dst_len = prefixlen;
118 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
121 assert_return(m, -EINVAL);
122 assert_return(m->hdr, -EINVAL);
123 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
125 rtm = NLMSG_DATA(m->hdr);
127 rtm->rtm_scope = scope;
132 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
133 uint16_t nlmsg_type, unsigned char rtm_family) {
137 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
138 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
139 assert_return(ret, -EINVAL);
141 r = message_new(rtnl, ret, nlmsg_type);
145 if (nlmsg_type == RTM_NEWROUTE)
146 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
148 rtm = NLMSG_DATA((*ret)->hdr);
150 rtm->rtm_family = rtm_family;
151 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
152 rtm->rtm_type = RTN_UNICAST;
153 rtm->rtm_table = RT_TABLE_MAIN;
154 rtm->rtm_protocol = RTPROT_BOOT;
159 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
160 struct ifinfomsg *ifi;
162 assert_return(m, -EINVAL);
163 assert_return(m->hdr, -EINVAL);
164 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
165 assert_return(change, -EINVAL);
167 ifi = NLMSG_DATA(m->hdr);
169 ifi->ifi_flags = flags;
170 ifi->ifi_change = change;
175 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
176 struct ifinfomsg *ifi;
178 assert_return(m, -EINVAL);
179 assert_return(m->hdr, -EINVAL);
180 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
182 ifi = NLMSG_DATA(m->hdr);
184 ifi->ifi_type = type;
189 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
190 uint16_t nlmsg_type, int index) {
191 struct ifinfomsg *ifi;
194 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
195 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
196 assert_return(ret, -EINVAL);
198 r = message_new(rtnl, ret, nlmsg_type);
202 if (nlmsg_type == RTM_NEWLINK)
203 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
205 ifi = NLMSG_DATA((*ret)->hdr);
207 ifi->ifi_family = AF_UNSPEC;
208 ifi->ifi_index = index;
213 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
214 struct ifaddrmsg *ifa;
216 assert_return(m, -EINVAL);
217 assert_return(m->hdr, -EINVAL);
218 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
220 ifa = NLMSG_DATA(m->hdr);
222 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
223 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
226 ifa->ifa_prefixlen = prefixlen;
231 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
232 struct ifaddrmsg *ifa;
234 assert_return(m, -EINVAL);
235 assert_return(m->hdr, -EINVAL);
236 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
238 ifa = NLMSG_DATA(m->hdr);
240 ifa->ifa_flags = flags;
245 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
246 struct ifaddrmsg *ifa;
248 assert_return(m, -EINVAL);
249 assert_return(m->hdr, -EINVAL);
250 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
252 ifa = NLMSG_DATA(m->hdr);
254 ifa->ifa_scope = scope;
259 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
260 uint16_t nlmsg_type, int index,
261 unsigned char family) {
262 struct ifaddrmsg *ifa;
265 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
266 assert_return(index > 0, -EINVAL);
267 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
268 assert_return(ret, -EINVAL);
270 r = message_new(rtnl, ret, nlmsg_type);
274 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
275 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
277 ifa = NLMSG_DATA((*ret)->hdr);
279 ifa->ifa_index = index;
280 ifa->ifa_family = family;
281 if (family == AF_INET)
282 ifa->ifa_prefixlen = 32;
283 else if (family == AF_INET6)
284 ifa->ifa_prefixlen = 128;
289 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
291 assert_se(REFCNT_INC(m->n_ref) >= 2);
296 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
297 if (m && REFCNT_DEC(m->n_ref) <= 0) {
302 for (i = 0; i <= m->n_containers; i++)
303 free(m->rta_offset_tb[i]);
311 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
312 assert_return(m, -EINVAL);
313 assert_return(type, -EINVAL);
315 *type = m->hdr->nlmsg_type;
320 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
321 assert_return(m, -EINVAL);
323 return !m->hdr->nlmsg_pid;
326 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
327 struct ifinfomsg *ifi;
329 assert_return(m, -EINVAL);
330 assert_return(m->hdr, -EINVAL);
331 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
332 assert_return(ifindex, -EINVAL);
334 ifi = NLMSG_DATA(m->hdr);
336 *ifindex = ifi->ifi_index;
341 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
342 struct ifinfomsg *ifi;
344 assert_return(m, -EINVAL);
345 assert_return(m->hdr, -EINVAL);
346 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
347 assert_return(flags, -EINVAL);
349 ifi = NLMSG_DATA(m->hdr);
351 *flags = ifi->ifi_flags;
356 /* If successful the updated message will be correctly aligned, if
357 unsuccessful the old message is untouched. */
358 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
359 uint32_t rta_length, message_length;
360 struct nlmsghdr *new_hdr;
368 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
369 assert(!data || data_length > 0);
370 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
372 /* get the size of the new rta attribute (with padding at the end) */
373 rta_length = RTA_LENGTH(data_length);
375 /* get the new message size (with padding at the end) */
376 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
378 /* realloc to fit the new attribute */
379 new_hdr = realloc(m->hdr, message_length);
384 /* get pointer to the attribute we are about to add */
385 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
387 /* if we are inside containers, extend them */
388 for (i = 0; i < m->n_containers; i++)
389 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
391 /* fill in the attribute */
392 rta->rta_type = type;
393 rta->rta_len = rta_length;
395 //TODO: simply return this value rather than check for !data
396 /* this is the start of a new container */
397 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
399 /* we don't deal with the case where the user lies about the type
400 * and gives us too little data (so don't do that)
402 padding = mempcpy(RTA_DATA(rta), data, data_length);
403 /* make sure also the padding at the end of the message is initialized */
405 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
408 /* update message size */
409 m->hdr->nlmsg_len = message_length;
414 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
418 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
422 if (type->type != data_type)
428 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
432 assert_return(m, -EINVAL);
433 assert_return(!m->sealed, -EPERM);
434 assert_return(data, -EINVAL);
436 r = message_attribute_has_type(m, type, NLA_STRING);
443 length = strnlen(data, size);
447 length = strlen(data);
449 r = add_rtattr(m, type, data, length + 1);
456 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
459 assert_return(m, -EINVAL);
460 assert_return(!m->sealed, -EPERM);
462 r = message_attribute_has_type(m, type, NLA_U8);
466 r = add_rtattr(m, type, &data, sizeof(uint8_t));
474 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
477 assert_return(m, -EINVAL);
478 assert_return(!m->sealed, -EPERM);
480 r = message_attribute_has_type(m, type, NLA_U16);
484 r = add_rtattr(m, type, &data, sizeof(uint16_t));
491 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
494 assert_return(m, -EINVAL);
495 assert_return(!m->sealed, -EPERM);
497 r = message_attribute_has_type(m, type, NLA_U32);
501 r = add_rtattr(m, type, &data, sizeof(uint32_t));
508 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
511 assert_return(m, -EINVAL);
512 assert_return(!m->sealed, -EPERM);
513 assert_return(data, -EINVAL);
515 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
519 r = add_rtattr(m, type, data, sizeof(struct in_addr));
526 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
529 assert_return(m, -EINVAL);
530 assert_return(!m->sealed, -EPERM);
531 assert_return(data, -EINVAL);
533 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
537 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
544 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
547 assert_return(m, -EINVAL);
548 assert_return(!m->sealed, -EPERM);
549 assert_return(data, -EINVAL);
551 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
555 r = add_rtattr(m, type, data, ETH_ALEN);
562 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
566 assert_return(m, -EINVAL);
567 assert_return(!m->sealed, -EPERM);
569 r = message_attribute_has_type(m, type, NLA_NESTED);
575 r = type_system_get_type_system(m->container_type_system[m->n_containers],
576 &m->container_type_system[m->n_containers + 1],
581 r = add_rtattr(m, type, NULL, size);
588 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
589 const NLTypeSystemUnion *type_system_union;
592 assert_return(m, -EINVAL);
593 assert_return(!m->sealed, -EPERM);
595 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
599 r = type_system_union_get_type_system(type_system_union,
600 &m->container_type_system[m->n_containers + 1],
605 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
609 /* do we evere need non-null size */
610 r = add_rtattr(m, type, NULL, 0);
618 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
619 assert_return(m, -EINVAL);
620 assert_return(!m->sealed, -EPERM);
621 assert_return(m->n_containers > 0, -EINVAL);
623 m->container_type_system[m->n_containers] = NULL;
629 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
632 assert_return(m, -EINVAL);
633 assert_return(m->sealed, -EPERM);
634 assert_return(data, -EINVAL);
635 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
636 assert(m->rta_offset_tb[m->n_containers]);
637 assert(type < m->rta_tb_size[m->n_containers]);
639 if(!m->rta_offset_tb[m->n_containers][type])
642 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
644 *data = RTA_DATA(rta);
646 return RTA_PAYLOAD(rta);
649 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
653 r = message_attribute_has_type(m, type, NLA_STRING);
657 r = rtnl_message_read_internal(m, type, &attr_data);
660 else if (strnlen(attr_data, r) >= (size_t) r)
663 *data = (char *) attr_data;
668 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
672 r = message_attribute_has_type(m, type, NLA_U8);
676 r = rtnl_message_read_internal(m, type, &attr_data);
679 else if ((size_t) r < sizeof(uint8_t))
682 *data = *(uint8_t *) attr_data;
687 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
691 r = message_attribute_has_type(m, type, NLA_U16);
695 r = rtnl_message_read_internal(m, type, &attr_data);
698 else if ((size_t) r < sizeof(uint16_t))
701 *data = *(uint16_t *) attr_data;
706 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
710 r = message_attribute_has_type(m, type, NLA_U32);
714 r = rtnl_message_read_internal(m, type, &attr_data);
717 else if ((size_t)r < sizeof(uint32_t))
720 *data = *(uint32_t *) attr_data;
725 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
729 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
733 r = rtnl_message_read_internal(m, type, &attr_data);
736 else if ((size_t)r < sizeof(struct ether_addr))
739 memcpy(data, attr_data, sizeof(struct ether_addr));
744 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
748 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
752 r = rtnl_message_read_internal(m, type, &attr_data);
755 else if ((size_t)r < sizeof(struct in_addr))
758 memcpy(data, attr_data, sizeof(struct in_addr));
763 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
767 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
771 r = rtnl_message_read_internal(m, type, &attr_data);
774 else if ((size_t)r < sizeof(struct in6_addr))
777 memcpy(data, attr_data, sizeof(struct in6_addr));
782 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
783 const NLType *nl_type;
784 const NLTypeSystem *type_system;
789 assert_return(m, -EINVAL);
790 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
792 r = type_system_get_type(m->container_type_system[m->n_containers],
798 if (nl_type->type == NLA_NESTED) {
799 r = type_system_get_type_system(m->container_type_system[m->n_containers],
804 } else if (nl_type->type == NLA_UNION) {
805 const NLTypeSystemUnion *type_system_union;
808 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
814 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
818 r = type_system_union_get_type_system(type_system_union,
826 r = rtnl_message_read_internal(m, type, &container);
834 r = rtnl_message_parse(m,
835 &m->rta_offset_tb[m->n_containers],
836 &m->rta_tb_size[m->n_containers],
845 m->container_type_system[m->n_containers] = type_system;
850 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
851 assert_return(m, -EINVAL);
852 assert_return(m->sealed, -EINVAL);
853 assert_return(m->n_containers > 0, -EINVAL);
855 free(m->rta_offset_tb[m->n_containers]);
856 m->rta_offset_tb[m->n_containers] = NULL;
857 m->container_type_system[m->n_containers] = NULL;
864 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
868 return m->hdr->nlmsg_seq;
871 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
872 struct nlmsgerr *err;
874 assert_return(m, -EINVAL);
875 assert_return(m->hdr, -EINVAL);
877 if (m->hdr->nlmsg_type != NLMSG_ERROR)
880 err = NLMSG_DATA(m->hdr);
885 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
889 /* ioctl(rtnl->fd, FIONREAD, &need)
890 Does not appear to work on netlink sockets. libnl uses
891 MSG_PEEK instead. I don't know if that is worth the
894 For now we simply use the maximum message size the kernel
895 may use (NLMSG_GOODSIZE), and then realloc to the actual
896 size after reading the message (hence avoiding huge memory
897 usage in case many small messages are kept around) */
905 int rtnl_message_parse(sd_rtnl_message *m,
906 size_t **rta_offset_tb,
907 unsigned short *rta_tb_size,
910 unsigned int rt_len) {
914 tb = (size_t *) new0(size_t *, max);
920 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
921 type = rta->rta_type;
923 /* if the kernel is newer than the headers we used
924 when building, we ignore out-of-range attributes
930 log_debug("rtnl: message parse - overwriting repeated attribute");
932 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
940 /* returns the number of bytes sent, or a negative error code */
941 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
944 struct sockaddr_nl nl;
946 .nl.nl_family = AF_NETLINK,
954 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
955 0, &addr.sa, sizeof(addr));
957 return (errno == EAGAIN) ? 0 : -errno;
962 /* On success, the number of bytes received is returned and *ret points to the received message
963 * which has a valid header and the correct size.
964 * If nothing useful was received 0 is returned.
965 * On failure, a negative error code is returned.
967 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
968 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
969 const NLType *nl_type;
970 struct nlmsghdr *new_hdr;
973 struct sockaddr_nl nl;
982 r = message_receive_need(nl, &need);
986 r = message_new_empty(nl, &m, need);
990 addr_len = sizeof(addr);
992 r = recvfrom(nl->fd, m->hdr, need,
993 0, &addr.sa, &addr_len);
995 return (errno == EAGAIN) ? 0 : -errno; /* no data */
997 return -ECONNRESET; /* connection was closed by the kernel */
998 else if (addr_len != sizeof(addr.nl) ||
999 addr.nl.nl_family != AF_NETLINK)
1000 return -EIO; /* not a netlink message */
1001 else if (addr.nl.nl_pid != 0)
1002 return 0; /* not from the kernel */
1003 else if ((size_t) r < sizeof(struct nlmsghdr) ||
1004 (size_t) r < m->hdr->nlmsg_len)
1005 return -EIO; /* too small (we do accept too big though) */
1006 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1007 return 0; /* not broadcast and not for us */
1011 /* silently drop noop messages */
1012 if (m->hdr->nlmsg_type == NLMSG_NOOP)
1015 /* check that we support this message type */
1016 r = type_system_get_type(NULL, &nl_type, m->hdr->nlmsg_type);
1019 log_debug("sd-rtnl: ignored message with unknown type: %u",
1020 m->hdr->nlmsg_type);
1025 /* check that the size matches the message type */
1026 if (len < NLMSG_LENGTH(nl_type->size))
1029 /* we probably allocated way too much memory, give it back */
1030 new_hdr = realloc(m->hdr, len);
1035 /* seal and parse the top-level message */
1036 r = sd_rtnl_message_rewind(m);
1046 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1051 assert_return(m, -EINVAL);
1053 /* don't allow appending to message once parsed */
1055 rtnl_message_seal(m);
1057 for (i = 1; i <= m->n_containers; i++) {
1058 free(m->rta_offset_tb[i]);
1059 m->rta_offset_tb[i] = NULL;
1060 m->rta_tb_size[i] = 0;
1061 m->container_type_system[i] = NULL;
1064 m->n_containers = 0;
1066 if (m->rta_offset_tb[0]) {
1067 /* top-level attributes have already been parsed */
1073 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1077 if (type->type == NLA_NESTED) {
1078 const NLTypeSystem *type_system = type->type_system;
1080 assert(type_system);
1082 m->container_type_system[0] = type_system;
1084 r = rtnl_message_parse(m,
1085 &m->rta_offset_tb[m->n_containers],
1086 &m->rta_tb_size[m->n_containers],
1088 (char*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(type->size),
1089 NLMSG_PAYLOAD(m->hdr, type->size));
1097 void rtnl_message_seal(sd_rtnl_message *m) {