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>
32 #include "rtnl-util.h"
33 #include "rtnl-internal.h"
34 #include "rtnl-types.h"
36 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : 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)
41 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
44 assert_return(ret, -EINVAL);
46 /* Note that 'rtnl' is curretly unused, if we start using it internally
47 we must take care to avoid problems due to mutual references between
48 busses and their queued messages. See sd-bus.
51 m = new0(sd_rtnl_message, 1);
55 m->n_ref = REFCNT_INIT;
64 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
65 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
66 const NLType *nl_type;
70 r = type_system_get_type(NULL, &nl_type, type);
74 assert(nl_type->type == NLA_NESTED);
76 r = message_new_empty(rtnl, &m);
80 size = NLMSG_SPACE(nl_type->size);
82 assert(size >= sizeof(struct nlmsghdr));
83 m->hdr = malloc0(size);
87 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
89 m->container_type_system[0] = nl_type->type_system;
90 m->hdr->nlmsg_len = size;
91 m->hdr->nlmsg_type = type;
99 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
102 assert_return(m, -EINVAL);
103 assert_return(m->hdr, -EINVAL);
104 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
106 rtm = NLMSG_DATA(m->hdr);
108 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
109 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
112 rtm->rtm_dst_len = prefixlen;
117 int sd_rtnl_message_route_set_src_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
120 assert_return(m, -EINVAL);
121 assert_return(m->hdr, -EINVAL);
122 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
124 rtm = NLMSG_DATA(m->hdr);
126 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
127 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
130 rtm->rtm_src_len = prefixlen;
135 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
138 assert_return(m, -EINVAL);
139 assert_return(m->hdr, -EINVAL);
140 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
142 rtm = NLMSG_DATA(m->hdr);
144 rtm->rtm_scope = scope;
149 int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) {
152 assert_return(m, -EINVAL);
153 assert_return(m->hdr, -EINVAL);
154 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
155 assert_return(family, -EINVAL);
157 rtm = NLMSG_DATA(m->hdr);
159 *family = rtm->rtm_family;
164 int sd_rtnl_message_route_get_dst_prefixlen(sd_rtnl_message *m, unsigned char *dst_len) {
167 assert_return(m, -EINVAL);
168 assert_return(m->hdr, -EINVAL);
169 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
170 assert_return(dst_len, -EINVAL);
172 rtm = NLMSG_DATA(m->hdr);
174 *dst_len = rtm->rtm_dst_len;
179 int sd_rtnl_message_route_get_src_prefixlen(sd_rtnl_message *m, unsigned char *src_len) {
182 assert_return(m, -EINVAL);
183 assert_return(m->hdr, -EINVAL);
184 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
185 assert_return(src_len, -EINVAL);
187 rtm = NLMSG_DATA(m->hdr);
189 *src_len = rtm->rtm_src_len;
194 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
195 uint16_t nlmsg_type, int rtm_family,
196 unsigned char rtm_protocol) {
200 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
201 assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
202 rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
203 assert_return(ret, -EINVAL);
205 r = message_new(rtnl, ret, nlmsg_type);
209 if (nlmsg_type == RTM_NEWROUTE)
210 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
212 rtm = NLMSG_DATA((*ret)->hdr);
214 rtm->rtm_family = rtm_family;
215 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
216 rtm->rtm_type = RTN_UNICAST;
217 rtm->rtm_table = RT_TABLE_MAIN;
218 rtm->rtm_protocol = rtm_protocol;
223 int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
226 assert_return(m, -EINVAL);
227 assert_return(m->hdr, -EINVAL);
228 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
229 assert_return(family, -EINVAL);
231 ndm = NLMSG_DATA(m->hdr);
233 *family = ndm->ndm_family;
238 int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
241 assert_return(m, -EINVAL);
242 assert_return(m->hdr, -EINVAL);
243 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
244 assert_return(index, -EINVAL);
246 ndm = NLMSG_DATA(m->hdr);
248 *index = ndm->ndm_ifindex;
253 int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
257 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
258 assert_return(ndm_family == AF_INET || ndm_family == AF_INET6, -EINVAL);
259 assert_return(ret, -EINVAL);
261 r = message_new(rtnl, ret, nlmsg_type);
265 if (nlmsg_type == RTM_NEWNEIGH)
266 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
268 ndm = NLMSG_DATA((*ret)->hdr);
270 ndm->ndm_family = ndm_family;
271 ndm->ndm_ifindex = index;
276 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
277 struct ifinfomsg *ifi;
279 assert_return(m, -EINVAL);
280 assert_return(m->hdr, -EINVAL);
281 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
282 assert_return(change, -EINVAL);
284 ifi = NLMSG_DATA(m->hdr);
286 ifi->ifi_flags = flags;
287 ifi->ifi_change = change;
292 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
293 struct ifinfomsg *ifi;
295 assert_return(m, -EINVAL);
296 assert_return(m->hdr, -EINVAL);
297 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
299 ifi = NLMSG_DATA(m->hdr);
301 ifi->ifi_type = type;
306 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
307 struct ifinfomsg *ifi;
309 assert_return(m, -EINVAL);
310 assert_return(m->hdr, -EINVAL);
311 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
313 ifi = NLMSG_DATA(m->hdr);
315 ifi->ifi_family = family;
320 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
321 uint16_t nlmsg_type, int index) {
322 struct ifinfomsg *ifi;
325 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
326 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
327 assert_return(ret, -EINVAL);
329 r = message_new(rtnl, ret, nlmsg_type);
333 if (nlmsg_type == RTM_NEWLINK)
334 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
336 ifi = NLMSG_DATA((*ret)->hdr);
338 ifi->ifi_family = AF_UNSPEC;
339 ifi->ifi_index = index;
344 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
345 assert_return(m, -EINVAL);
346 assert_return(m->hdr, -EINVAL);
347 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
348 m->hdr->nlmsg_type == RTM_GETADDR ||
349 m->hdr->nlmsg_type == RTM_GETROUTE ||
350 m->hdr->nlmsg_type == RTM_GETNEIGH,
354 m->hdr->nlmsg_flags |= NLM_F_DUMP;
356 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
361 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
362 struct ifaddrmsg *ifa;
364 assert_return(m, -EINVAL);
365 assert_return(m->hdr, -EINVAL);
366 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
368 ifa = NLMSG_DATA(m->hdr);
370 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
371 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
374 ifa->ifa_prefixlen = prefixlen;
379 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
380 struct ifaddrmsg *ifa;
382 assert_return(m, -EINVAL);
383 assert_return(m->hdr, -EINVAL);
384 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
386 ifa = NLMSG_DATA(m->hdr);
388 ifa->ifa_flags = flags;
393 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
394 struct ifaddrmsg *ifa;
396 assert_return(m, -EINVAL);
397 assert_return(m->hdr, -EINVAL);
398 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
400 ifa = NLMSG_DATA(m->hdr);
402 ifa->ifa_scope = scope;
407 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
408 struct ifaddrmsg *ifa;
410 assert_return(m, -EINVAL);
411 assert_return(m->hdr, -EINVAL);
412 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
413 assert_return(family, -EINVAL);
415 ifa = NLMSG_DATA(m->hdr);
417 *family = ifa->ifa_family;
422 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
423 struct ifaddrmsg *ifa;
425 assert_return(m, -EINVAL);
426 assert_return(m->hdr, -EINVAL);
427 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
428 assert_return(prefixlen, -EINVAL);
430 ifa = NLMSG_DATA(m->hdr);
432 *prefixlen = ifa->ifa_prefixlen;
437 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
438 struct ifaddrmsg *ifa;
440 assert_return(m, -EINVAL);
441 assert_return(m->hdr, -EINVAL);
442 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
443 assert_return(scope, -EINVAL);
445 ifa = NLMSG_DATA(m->hdr);
447 *scope = ifa->ifa_scope;
452 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
453 struct ifaddrmsg *ifa;
455 assert_return(m, -EINVAL);
456 assert_return(m->hdr, -EINVAL);
457 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
458 assert_return(flags, -EINVAL);
460 ifa = NLMSG_DATA(m->hdr);
462 *flags = ifa->ifa_flags;
467 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
468 struct ifaddrmsg *ifa;
470 assert_return(m, -EINVAL);
471 assert_return(m->hdr, -EINVAL);
472 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
473 assert_return(ifindex, -EINVAL);
475 ifa = NLMSG_DATA(m->hdr);
477 *ifindex = ifa->ifa_index;
482 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
483 uint16_t nlmsg_type, int index,
485 struct ifaddrmsg *ifa;
488 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
489 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
491 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
492 family == AF_INET || family == AF_INET6, -EINVAL);
493 assert_return(ret, -EINVAL);
495 r = message_new(rtnl, ret, nlmsg_type);
499 if (nlmsg_type == RTM_GETADDR)
500 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
502 ifa = NLMSG_DATA((*ret)->hdr);
504 ifa->ifa_index = index;
505 ifa->ifa_family = family;
506 if (family == AF_INET)
507 ifa->ifa_prefixlen = 32;
508 else if (family == AF_INET6)
509 ifa->ifa_prefixlen = 128;
514 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
515 int index, int family) {
518 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
522 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
527 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
529 assert_se(REFCNT_INC(m->n_ref) >= 2);
534 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
535 if (m && REFCNT_DEC(m->n_ref) <= 0) {
540 for (i = 0; i <= m->n_containers; i++)
541 free(m->rta_offset_tb[i]);
543 sd_rtnl_message_unref(m->next);
551 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
552 assert_return(m, -EINVAL);
553 assert_return(type, -EINVAL);
555 *type = m->hdr->nlmsg_type;
560 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
561 assert_return(m, -EINVAL);
563 return !m->hdr->nlmsg_pid;
566 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
567 struct ifinfomsg *ifi;
569 assert_return(m, -EINVAL);
570 assert_return(m->hdr, -EINVAL);
571 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
572 assert_return(ifindex, -EINVAL);
574 ifi = NLMSG_DATA(m->hdr);
576 *ifindex = ifi->ifi_index;
581 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
582 struct ifinfomsg *ifi;
584 assert_return(m, -EINVAL);
585 assert_return(m->hdr, -EINVAL);
586 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
587 assert_return(flags, -EINVAL);
589 ifi = NLMSG_DATA(m->hdr);
591 *flags = ifi->ifi_flags;
596 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
597 struct ifinfomsg *ifi;
599 assert_return(m, -EINVAL);
600 assert_return(m->hdr, -EINVAL);
601 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
602 assert_return(type, -EINVAL);
604 ifi = NLMSG_DATA(m->hdr);
606 *type = ifi->ifi_type;
611 /* If successful the updated message will be correctly aligned, if
612 unsuccessful the old message is untouched. */
613 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
615 size_t message_length, padding_length;
616 struct nlmsghdr *new_hdr;
625 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
626 assert(!data || data_length);
628 /* get offset of the new attribute */
629 offset = m->hdr->nlmsg_len;
631 /* get the size of the new rta attribute (with padding at the end) */
632 rta_length = RTA_LENGTH(data_length);
634 /* get the new message size (with padding at the end) */
635 message_length = offset + RTA_ALIGN(rta_length);
637 /* realloc to fit the new attribute */
638 new_hdr = realloc(m->hdr, message_length);
643 /* get pointer to the attribute we are about to add */
644 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
646 /* if we are inside containers, extend them */
647 for (i = 0; i < m->n_containers; i++)
648 GET_CONTAINER(m, i)->rta_len += message_length - offset;
650 /* fill in the attribute */
651 rta->rta_type = type;
652 rta->rta_len = rta_length;
654 /* we don't deal with the case where the user lies about the type
655 * and gives us too little data (so don't do that)
657 padding = mempcpy(RTA_DATA(rta), data, data_length);
659 /* if no data was passed, make sure we still initialize the padding
660 note that we can have data_length > 0 (used by some containers) */
661 padding = RTA_DATA(rta);
664 /* make sure also the padding at the end of the message is initialized */
665 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
666 memzero(padding, padding_length);
668 /* update message size */
669 m->hdr->nlmsg_len = message_length;
674 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
678 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
682 if (type->type != data_type)
688 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
692 assert_return(m, -EINVAL);
693 assert_return(!m->sealed, -EPERM);
694 assert_return(data, -EINVAL);
696 r = message_attribute_has_type(m, type, NLA_STRING);
703 length = strnlen(data, size+1);
707 length = strlen(data);
709 r = add_rtattr(m, type, data, length + 1);
716 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
719 assert_return(m, -EINVAL);
720 assert_return(!m->sealed, -EPERM);
722 r = message_attribute_has_type(m, type, NLA_U8);
726 r = add_rtattr(m, type, &data, sizeof(uint8_t));
734 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
737 assert_return(m, -EINVAL);
738 assert_return(!m->sealed, -EPERM);
740 r = message_attribute_has_type(m, type, NLA_U16);
744 r = add_rtattr(m, type, &data, sizeof(uint16_t));
751 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
754 assert_return(m, -EINVAL);
755 assert_return(!m->sealed, -EPERM);
757 r = message_attribute_has_type(m, type, NLA_U32);
761 r = add_rtattr(m, type, &data, sizeof(uint32_t));
768 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
771 assert_return(m, -EINVAL);
772 assert_return(!m->sealed, -EPERM);
773 assert_return(data, -EINVAL);
775 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
779 r = add_rtattr(m, type, data, sizeof(struct in_addr));
786 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
789 assert_return(m, -EINVAL);
790 assert_return(!m->sealed, -EPERM);
791 assert_return(data, -EINVAL);
793 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
797 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
804 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
807 assert_return(m, -EINVAL);
808 assert_return(!m->sealed, -EPERM);
809 assert_return(data, -EINVAL);
811 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
815 r = add_rtattr(m, type, data, ETH_ALEN);
822 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
825 assert_return(m, -EINVAL);
826 assert_return(!m->sealed, -EPERM);
827 assert_return(info, -EINVAL);
829 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
833 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
840 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
844 assert_return(m, -EINVAL);
845 assert_return(!m->sealed, -EPERM);
846 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
848 r = message_attribute_has_type(m, type, NLA_NESTED);
854 r = type_system_get_type_system(m->container_type_system[m->n_containers],
855 &m->container_type_system[m->n_containers + 1],
860 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
864 m->container_offsets[m->n_containers ++] = r;
869 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
870 const NLTypeSystemUnion *type_system_union;
873 assert_return(m, -EINVAL);
874 assert_return(!m->sealed, -EPERM);
876 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
880 r = type_system_union_get_type_system(type_system_union,
881 &m->container_type_system[m->n_containers + 1],
886 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
890 /* do we evere need non-null size */
891 r = add_rtattr(m, type, NULL, 0);
895 m->container_offsets[m->n_containers ++] = r;
901 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
902 assert_return(m, -EINVAL);
903 assert_return(!m->sealed, -EPERM);
904 assert_return(m->n_containers > 0, -EINVAL);
906 m->container_type_system[m->n_containers] = NULL;
912 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
915 assert_return(m, -EINVAL);
916 assert_return(m->sealed, -EPERM);
917 assert_return(data, -EINVAL);
918 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
919 assert(m->rta_offset_tb[m->n_containers]);
920 assert(type < m->rta_tb_size[m->n_containers]);
922 if(!m->rta_offset_tb[m->n_containers][type])
925 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
927 *data = RTA_DATA(rta);
929 return RTA_PAYLOAD(rta);
932 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
936 assert_return(m, -EINVAL);
938 r = message_attribute_has_type(m, type, NLA_STRING);
942 r = rtnl_message_read_internal(m, type, &attr_data);
945 else if (strnlen(attr_data, r) >= (size_t) r)
949 *data = (const char *) attr_data;
954 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
958 assert_return(m, -EINVAL);
960 r = message_attribute_has_type(m, type, NLA_U8);
964 r = rtnl_message_read_internal(m, type, &attr_data);
967 else if ((size_t) r < sizeof(uint8_t))
971 *data = *(uint8_t *) attr_data;
976 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
980 assert_return(m, -EINVAL);
982 r = message_attribute_has_type(m, type, NLA_U16);
986 r = rtnl_message_read_internal(m, type, &attr_data);
989 else if ((size_t) r < sizeof(uint16_t))
993 *data = *(uint16_t *) attr_data;
998 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
1002 assert_return(m, -EINVAL);
1004 r = message_attribute_has_type(m, type, NLA_U32);
1008 r = rtnl_message_read_internal(m, type, &attr_data);
1011 else if ((size_t)r < sizeof(uint32_t))
1015 *data = *(uint32_t *) attr_data;
1020 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
1024 assert_return(m, -EINVAL);
1026 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
1030 r = rtnl_message_read_internal(m, type, &attr_data);
1033 else if ((size_t)r < sizeof(struct ether_addr))
1037 memcpy(data, attr_data, sizeof(struct ether_addr));
1042 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
1046 assert_return(m, -EINVAL);
1048 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
1052 r = rtnl_message_read_internal(m, type, &attr_data);
1055 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
1059 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
1064 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
1068 assert_return(m, -EINVAL);
1070 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1074 r = rtnl_message_read_internal(m, type, &attr_data);
1077 else if ((size_t)r < sizeof(struct in_addr))
1081 memcpy(data, attr_data, sizeof(struct in_addr));
1086 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
1090 assert_return(m, -EINVAL);
1092 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1096 r = rtnl_message_read_internal(m, type, &attr_data);
1099 else if ((size_t)r < sizeof(struct in6_addr))
1103 memcpy(data, attr_data, sizeof(struct in6_addr));
1108 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
1109 const NLType *nl_type;
1110 const NLTypeSystem *type_system;
1115 assert_return(m, -EINVAL);
1116 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1118 r = type_system_get_type(m->container_type_system[m->n_containers],
1124 if (nl_type->type == NLA_NESTED) {
1125 r = type_system_get_type_system(m->container_type_system[m->n_containers],
1130 } else if (nl_type->type == NLA_UNION) {
1131 const NLTypeSystemUnion *type_system_union;
1134 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1140 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1144 r = type_system_union_get_type_system(type_system_union,
1152 r = rtnl_message_read_internal(m, type, &container);
1160 r = rtnl_message_parse(m,
1161 &m->rta_offset_tb[m->n_containers],
1162 &m->rta_tb_size[m->n_containers],
1171 m->container_type_system[m->n_containers] = type_system;
1176 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1177 assert_return(m, -EINVAL);
1178 assert_return(m->sealed, -EINVAL);
1179 assert_return(m->n_containers > 0, -EINVAL);
1181 free(m->rta_offset_tb[m->n_containers]);
1182 m->rta_offset_tb[m->n_containers] = NULL;
1183 m->container_type_system[m->n_containers] = NULL;
1190 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1194 return m->hdr->nlmsg_seq;
1197 int sd_rtnl_message_is_error(sd_rtnl_message *m) {
1198 assert_return(m, 0);
1199 assert_return(m->hdr, 0);
1201 return m->hdr->nlmsg_type == NLMSG_ERROR;
1204 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1205 struct nlmsgerr *err;
1207 assert_return(m, -EINVAL);
1208 assert_return(m->hdr, -EINVAL);
1210 if (!sd_rtnl_message_is_error(m))
1213 err = NLMSG_DATA(m->hdr);
1218 int rtnl_message_parse(sd_rtnl_message *m,
1219 size_t **rta_offset_tb,
1220 unsigned short *rta_tb_size,
1223 unsigned int rt_len) {
1224 unsigned short type;
1227 tb = new0(size_t, max + 1);
1231 *rta_tb_size = max + 1;
1233 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1234 type = RTA_TYPE(rta);
1236 /* if the kernel is newer than the headers we used
1237 when building, we ignore out-of-range attributes
1243 log_debug("rtnl: message parse - overwriting repeated attribute");
1245 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1248 *rta_offset_tb = tb;
1253 /* returns the number of bytes sent, or a negative error code */
1254 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1257 struct sockaddr_nl nl;
1259 .nl.nl_family = AF_NETLINK,
1267 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1268 0, &addr.sa, sizeof(addr));
1270 return (errno == EAGAIN) ? 0 : -errno;
1275 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1276 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1277 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1278 struct msghdr msg = {
1281 .msg_control = cred_buffer,
1282 .msg_controllen = sizeof(cred_buffer),
1284 struct cmsghdr *cmsg;
1292 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1295 if (errno == ENOBUFS)
1296 log_debug("rtnl: kernel receive buffer overrun");
1298 return (errno == EAGAIN) ? 0 : -errno;
1300 /* connection was closed by the kernel */
1303 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1304 if (cmsg->cmsg_level == SOL_SOCKET &&
1305 cmsg->cmsg_type == SCM_CREDENTIALS &&
1306 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1307 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1309 /* from the kernel */
1310 if (ucred->uid == 0 && ucred->pid == 0)
1312 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1313 cmsg->cmsg_type == NETLINK_PKTINFO &&
1314 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1315 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1317 /* multi-cast group */
1318 group = pktinfo->group;
1323 /* not from the kernel, ignore */
1332 /* On success, the number of bytes received is returned and *ret points to the received message
1333 * which has a valid header and the correct size.
1334 * If nothing useful was received 0 is returned.
1335 * On failure, a negative error code is returned.
1337 int socket_read_message(sd_rtnl *rtnl) {
1338 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1339 struct iovec iov = {};
1341 bool multi_part = false, done = false;
1342 struct nlmsghdr *new_msg;
1348 assert(rtnl->rbuffer);
1349 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1351 /* read nothing, just get the pending message size */
1352 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1358 /* make room for the pending message */
1359 if (!greedy_realloc((void **)&rtnl->rbuffer,
1360 &rtnl->rbuffer_allocated,
1361 len, sizeof(uint8_t)))
1364 iov.iov_base = rtnl->rbuffer;
1365 iov.iov_len = rtnl->rbuffer_allocated;
1367 /* read the pending message */
1368 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1374 if (len > rtnl->rbuffer_allocated)
1375 /* message did not fit in read buffer */
1378 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1381 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1382 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1383 rtnl->rbuffer->nlmsg_seq) {
1384 first = rtnl->rqueue_partial[i];
1390 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
1391 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1392 const NLType *nl_type;
1394 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1395 /* not broadcast and not for us */
1398 if (new_msg->nlmsg_type == NLMSG_NOOP)
1399 /* silently drop noop messages */
1402 if (new_msg->nlmsg_type == NLMSG_DONE) {
1403 /* finished reading multi-part message */
1409 /* check that we support this message type */
1410 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1413 log_debug("sd-rtnl: ignored message with unknown type: %u",
1414 new_msg->nlmsg_type);
1419 /* check that the size matches the message type */
1420 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
1421 log_debug("sd-rtnl: message larger than expected, dropping");
1425 r = message_new_empty(rtnl, &m);
1429 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1433 /* seal and parse the top-level message */
1434 r = sd_rtnl_message_rewind(m);
1438 /* push the message onto the multi-part message stack */
1446 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1451 if (!multi_part || done) {
1452 /* we got a complete message, push it on the read queue */
1453 r = rtnl_rqueue_make_room(rtnl);
1457 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1460 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1461 /* remove the message form the partial read queue */
1462 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1463 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1464 rtnl->rqueue_partial_size --;
1469 /* we only got a partial multi-part message, push it on the
1470 partial read queue */
1471 if (i < rtnl->rqueue_partial_size) {
1472 rtnl->rqueue_partial[i] = first;
1474 r = rtnl_rqueue_partial_make_room(rtnl);
1478 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1486 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1491 assert_return(m, -EINVAL);
1493 /* don't allow appending to message once parsed */
1495 rtnl_message_seal(m);
1497 for (i = 1; i <= m->n_containers; i++) {
1498 free(m->rta_offset_tb[i]);
1499 m->rta_offset_tb[i] = NULL;
1500 m->rta_tb_size[i] = 0;
1501 m->container_type_system[i] = NULL;
1504 m->n_containers = 0;
1506 if (m->rta_offset_tb[0]) {
1507 /* top-level attributes have already been parsed */
1513 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1517 if (type->type == NLA_NESTED) {
1518 const NLTypeSystem *type_system = type->type_system;
1520 assert(type_system);
1522 m->container_type_system[0] = type_system;
1524 r = rtnl_message_parse(m,
1525 &m->rta_offset_tb[m->n_containers],
1526 &m->rta_tb_size[m->n_containers],
1528 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1529 NLMSG_ALIGN(type->size)),
1530 NLMSG_PAYLOAD(m->hdr, type->size));
1538 void rtnl_message_seal(sd_rtnl_message *m) {
1545 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1546 assert_return(m, NULL);