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_set_flags(sd_rtnl_message *m, uint8_t flags) {
226 assert_return(m, -EINVAL);
227 assert_return(m->hdr, -EINVAL);
228 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
230 ndm = NLMSG_DATA(m->hdr);
231 ndm->ndm_flags |= flags;
236 int sd_rtnl_message_neigh_set_state(sd_rtnl_message *m, uint16_t state) {
239 assert_return(m, -EINVAL);
240 assert_return(m->hdr, -EINVAL);
241 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
243 ndm = NLMSG_DATA(m->hdr);
244 ndm->ndm_state |= state;
249 int sd_rtnl_message_neigh_get_flags(sd_rtnl_message *m, uint8_t *flags) {
252 assert_return(m, -EINVAL);
253 assert_return(m->hdr, -EINVAL);
254 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
256 ndm = NLMSG_DATA(m->hdr);
257 *flags = ndm->ndm_flags;
262 int sd_rtnl_message_neigh_get_state(sd_rtnl_message *m, uint16_t *state) {
265 assert_return(m, -EINVAL);
266 assert_return(m->hdr, -EINVAL);
267 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
269 ndm = NLMSG_DATA(m->hdr);
270 *state = ndm->ndm_state;
275 int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
278 assert_return(m, -EINVAL);
279 assert_return(m->hdr, -EINVAL);
280 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
281 assert_return(family, -EINVAL);
283 ndm = NLMSG_DATA(m->hdr);
285 *family = ndm->ndm_family;
290 int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
293 assert_return(m, -EINVAL);
294 assert_return(m->hdr, -EINVAL);
295 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
296 assert_return(index, -EINVAL);
298 ndm = NLMSG_DATA(m->hdr);
300 *index = ndm->ndm_ifindex;
305 int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
309 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
310 assert_return(ndm_family == AF_INET ||
311 ndm_family == AF_INET6 ||
312 ndm_family == PF_BRIDGE, -EINVAL);
313 assert_return(ret, -EINVAL);
315 r = message_new(rtnl, ret, nlmsg_type);
319 if (nlmsg_type == RTM_NEWNEIGH)
320 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
322 ndm = NLMSG_DATA((*ret)->hdr);
324 ndm->ndm_family = ndm_family;
325 ndm->ndm_ifindex = index;
330 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
331 struct ifinfomsg *ifi;
333 assert_return(m, -EINVAL);
334 assert_return(m->hdr, -EINVAL);
335 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
336 assert_return(change, -EINVAL);
338 ifi = NLMSG_DATA(m->hdr);
340 ifi->ifi_flags = flags;
341 ifi->ifi_change = change;
346 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
347 struct ifinfomsg *ifi;
349 assert_return(m, -EINVAL);
350 assert_return(m->hdr, -EINVAL);
351 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
353 ifi = NLMSG_DATA(m->hdr);
355 ifi->ifi_type = type;
360 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
361 struct ifinfomsg *ifi;
363 assert_return(m, -EINVAL);
364 assert_return(m->hdr, -EINVAL);
365 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
367 ifi = NLMSG_DATA(m->hdr);
369 ifi->ifi_family = family;
374 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
375 uint16_t nlmsg_type, int index) {
376 struct ifinfomsg *ifi;
379 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
380 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
381 assert_return(ret, -EINVAL);
383 r = message_new(rtnl, ret, nlmsg_type);
387 if (nlmsg_type == RTM_NEWLINK)
388 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
390 ifi = NLMSG_DATA((*ret)->hdr);
392 ifi->ifi_family = AF_UNSPEC;
393 ifi->ifi_index = index;
398 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
399 assert_return(m, -EINVAL);
400 assert_return(m->hdr, -EINVAL);
401 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
402 m->hdr->nlmsg_type == RTM_GETADDR ||
403 m->hdr->nlmsg_type == RTM_GETROUTE ||
404 m->hdr->nlmsg_type == RTM_GETNEIGH,
408 m->hdr->nlmsg_flags |= NLM_F_DUMP;
410 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
415 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
416 struct ifaddrmsg *ifa;
418 assert_return(m, -EINVAL);
419 assert_return(m->hdr, -EINVAL);
420 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
422 ifa = NLMSG_DATA(m->hdr);
424 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
425 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
428 ifa->ifa_prefixlen = prefixlen;
433 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
434 struct ifaddrmsg *ifa;
436 assert_return(m, -EINVAL);
437 assert_return(m->hdr, -EINVAL);
438 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
440 ifa = NLMSG_DATA(m->hdr);
442 ifa->ifa_flags = flags;
447 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
448 struct ifaddrmsg *ifa;
450 assert_return(m, -EINVAL);
451 assert_return(m->hdr, -EINVAL);
452 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
454 ifa = NLMSG_DATA(m->hdr);
456 ifa->ifa_scope = scope;
461 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
462 struct ifaddrmsg *ifa;
464 assert_return(m, -EINVAL);
465 assert_return(m->hdr, -EINVAL);
466 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
467 assert_return(family, -EINVAL);
469 ifa = NLMSG_DATA(m->hdr);
471 *family = ifa->ifa_family;
476 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
477 struct ifaddrmsg *ifa;
479 assert_return(m, -EINVAL);
480 assert_return(m->hdr, -EINVAL);
481 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
482 assert_return(prefixlen, -EINVAL);
484 ifa = NLMSG_DATA(m->hdr);
486 *prefixlen = ifa->ifa_prefixlen;
491 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
492 struct ifaddrmsg *ifa;
494 assert_return(m, -EINVAL);
495 assert_return(m->hdr, -EINVAL);
496 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
497 assert_return(scope, -EINVAL);
499 ifa = NLMSG_DATA(m->hdr);
501 *scope = ifa->ifa_scope;
506 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
507 struct ifaddrmsg *ifa;
509 assert_return(m, -EINVAL);
510 assert_return(m->hdr, -EINVAL);
511 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
512 assert_return(flags, -EINVAL);
514 ifa = NLMSG_DATA(m->hdr);
516 *flags = ifa->ifa_flags;
521 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
522 struct ifaddrmsg *ifa;
524 assert_return(m, -EINVAL);
525 assert_return(m->hdr, -EINVAL);
526 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
527 assert_return(ifindex, -EINVAL);
529 ifa = NLMSG_DATA(m->hdr);
531 *ifindex = ifa->ifa_index;
536 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
537 uint16_t nlmsg_type, int index,
539 struct ifaddrmsg *ifa;
542 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
543 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
545 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
546 family == AF_INET || family == AF_INET6, -EINVAL);
547 assert_return(ret, -EINVAL);
549 r = message_new(rtnl, ret, nlmsg_type);
553 if (nlmsg_type == RTM_GETADDR)
554 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
556 ifa = NLMSG_DATA((*ret)->hdr);
558 ifa->ifa_index = index;
559 ifa->ifa_family = family;
560 if (family == AF_INET)
561 ifa->ifa_prefixlen = 32;
562 else if (family == AF_INET6)
563 ifa->ifa_prefixlen = 128;
568 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
569 int index, int family) {
572 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
576 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
581 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
583 assert_se(REFCNT_INC(m->n_ref) >= 2);
588 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
589 if (m && REFCNT_DEC(m->n_ref) <= 0) {
594 for (i = 0; i <= m->n_containers; i++)
595 free(m->rta_offset_tb[i]);
597 sd_rtnl_message_unref(m->next);
605 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
606 assert_return(m, -EINVAL);
607 assert_return(type, -EINVAL);
609 *type = m->hdr->nlmsg_type;
614 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
615 assert_return(m, -EINVAL);
617 return !m->hdr->nlmsg_pid;
620 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
621 struct ifinfomsg *ifi;
623 assert_return(m, -EINVAL);
624 assert_return(m->hdr, -EINVAL);
625 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
626 assert_return(ifindex, -EINVAL);
628 ifi = NLMSG_DATA(m->hdr);
630 *ifindex = ifi->ifi_index;
635 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
636 struct ifinfomsg *ifi;
638 assert_return(m, -EINVAL);
639 assert_return(m->hdr, -EINVAL);
640 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
641 assert_return(flags, -EINVAL);
643 ifi = NLMSG_DATA(m->hdr);
645 *flags = ifi->ifi_flags;
650 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
651 struct ifinfomsg *ifi;
653 assert_return(m, -EINVAL);
654 assert_return(m->hdr, -EINVAL);
655 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
656 assert_return(type, -EINVAL);
658 ifi = NLMSG_DATA(m->hdr);
660 *type = ifi->ifi_type;
665 /* If successful the updated message will be correctly aligned, if
666 unsuccessful the old message is untouched. */
667 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
669 size_t message_length, padding_length;
670 struct nlmsghdr *new_hdr;
679 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
680 assert(!data || data_length);
682 /* get offset of the new attribute */
683 offset = m->hdr->nlmsg_len;
685 /* get the size of the new rta attribute (with padding at the end) */
686 rta_length = RTA_LENGTH(data_length);
688 /* get the new message size (with padding at the end) */
689 message_length = offset + RTA_ALIGN(rta_length);
691 /* realloc to fit the new attribute */
692 new_hdr = realloc(m->hdr, message_length);
697 /* get pointer to the attribute we are about to add */
698 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
700 /* if we are inside containers, extend them */
701 for (i = 0; i < m->n_containers; i++)
702 GET_CONTAINER(m, i)->rta_len += message_length - offset;
704 /* fill in the attribute */
705 rta->rta_type = type;
706 rta->rta_len = rta_length;
708 /* we don't deal with the case where the user lies about the type
709 * and gives us too little data (so don't do that)
711 padding = mempcpy(RTA_DATA(rta), data, data_length);
713 /* if no data was passed, make sure we still initialize the padding
714 note that we can have data_length > 0 (used by some containers) */
715 padding = RTA_DATA(rta);
718 /* make sure also the padding at the end of the message is initialized */
719 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
720 memzero(padding, padding_length);
722 /* update message size */
723 m->hdr->nlmsg_len = message_length;
728 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
732 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
736 if (type->type != data_type)
742 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
746 assert_return(m, -EINVAL);
747 assert_return(!m->sealed, -EPERM);
748 assert_return(data, -EINVAL);
750 r = message_attribute_has_type(m, type, NLA_STRING);
757 length = strnlen(data, size+1);
761 length = strlen(data);
763 r = add_rtattr(m, type, data, length + 1);
770 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
773 assert_return(m, -EINVAL);
774 assert_return(!m->sealed, -EPERM);
776 r = message_attribute_has_type(m, type, NLA_U8);
780 r = add_rtattr(m, type, &data, sizeof(uint8_t));
788 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
791 assert_return(m, -EINVAL);
792 assert_return(!m->sealed, -EPERM);
794 r = message_attribute_has_type(m, type, NLA_U16);
798 r = add_rtattr(m, type, &data, sizeof(uint16_t));
805 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
808 assert_return(m, -EINVAL);
809 assert_return(!m->sealed, -EPERM);
811 r = message_attribute_has_type(m, type, NLA_U32);
815 r = add_rtattr(m, type, &data, sizeof(uint32_t));
822 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
825 assert_return(m, -EINVAL);
826 assert_return(!m->sealed, -EPERM);
827 assert_return(data, -EINVAL);
829 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
833 r = add_rtattr(m, type, data, sizeof(struct in_addr));
840 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
843 assert_return(m, -EINVAL);
844 assert_return(!m->sealed, -EPERM);
845 assert_return(data, -EINVAL);
847 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
851 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
858 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
861 assert_return(m, -EINVAL);
862 assert_return(!m->sealed, -EPERM);
863 assert_return(data, -EINVAL);
865 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
869 r = add_rtattr(m, type, data, ETH_ALEN);
876 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
879 assert_return(m, -EINVAL);
880 assert_return(!m->sealed, -EPERM);
881 assert_return(info, -EINVAL);
883 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
887 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
894 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
898 assert_return(m, -EINVAL);
899 assert_return(!m->sealed, -EPERM);
900 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
902 r = message_attribute_has_type(m, type, NLA_NESTED);
908 r = type_system_get_type_system(m->container_type_system[m->n_containers],
909 &m->container_type_system[m->n_containers + 1],
914 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
918 m->container_offsets[m->n_containers ++] = r;
923 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
924 const NLTypeSystemUnion *type_system_union;
927 assert_return(m, -EINVAL);
928 assert_return(!m->sealed, -EPERM);
930 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
934 r = type_system_union_get_type_system(type_system_union,
935 &m->container_type_system[m->n_containers + 1],
940 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
944 /* do we evere need non-null size */
945 r = add_rtattr(m, type, NULL, 0);
949 m->container_offsets[m->n_containers ++] = r;
955 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
956 assert_return(m, -EINVAL);
957 assert_return(!m->sealed, -EPERM);
958 assert_return(m->n_containers > 0, -EINVAL);
960 m->container_type_system[m->n_containers] = NULL;
966 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
969 assert_return(m, -EINVAL);
970 assert_return(m->sealed, -EPERM);
971 assert_return(data, -EINVAL);
972 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
973 assert(m->rta_offset_tb[m->n_containers]);
974 assert(type < m->rta_tb_size[m->n_containers]);
976 if(!m->rta_offset_tb[m->n_containers][type])
979 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
981 *data = RTA_DATA(rta);
983 return RTA_PAYLOAD(rta);
986 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
990 assert_return(m, -EINVAL);
992 r = message_attribute_has_type(m, type, NLA_STRING);
996 r = rtnl_message_read_internal(m, type, &attr_data);
999 else if (strnlen(attr_data, r) >= (size_t) r)
1003 *data = (const char *) attr_data;
1008 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
1012 assert_return(m, -EINVAL);
1014 r = message_attribute_has_type(m, type, NLA_U8);
1018 r = rtnl_message_read_internal(m, type, &attr_data);
1021 else if ((size_t) r < sizeof(uint8_t))
1025 *data = *(uint8_t *) attr_data;
1030 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
1034 assert_return(m, -EINVAL);
1036 r = message_attribute_has_type(m, type, NLA_U16);
1040 r = rtnl_message_read_internal(m, type, &attr_data);
1043 else if ((size_t) r < sizeof(uint16_t))
1047 *data = *(uint16_t *) attr_data;
1052 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
1056 assert_return(m, -EINVAL);
1058 r = message_attribute_has_type(m, type, NLA_U32);
1062 r = rtnl_message_read_internal(m, type, &attr_data);
1065 else if ((size_t)r < sizeof(uint32_t))
1069 *data = *(uint32_t *) attr_data;
1074 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
1078 assert_return(m, -EINVAL);
1080 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
1084 r = rtnl_message_read_internal(m, type, &attr_data);
1087 else if ((size_t)r < sizeof(struct ether_addr))
1091 memcpy(data, attr_data, sizeof(struct ether_addr));
1096 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
1100 assert_return(m, -EINVAL);
1102 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
1106 r = rtnl_message_read_internal(m, type, &attr_data);
1109 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
1113 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
1118 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
1122 assert_return(m, -EINVAL);
1124 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1128 r = rtnl_message_read_internal(m, type, &attr_data);
1131 else if ((size_t)r < sizeof(struct in_addr))
1135 memcpy(data, attr_data, sizeof(struct in_addr));
1140 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
1144 assert_return(m, -EINVAL);
1146 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1150 r = rtnl_message_read_internal(m, type, &attr_data);
1153 else if ((size_t)r < sizeof(struct in6_addr))
1157 memcpy(data, attr_data, sizeof(struct in6_addr));
1162 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
1163 const NLType *nl_type;
1164 const NLTypeSystem *type_system;
1169 assert_return(m, -EINVAL);
1170 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1172 r = type_system_get_type(m->container_type_system[m->n_containers],
1178 if (nl_type->type == NLA_NESTED) {
1179 r = type_system_get_type_system(m->container_type_system[m->n_containers],
1184 } else if (nl_type->type == NLA_UNION) {
1185 const NLTypeSystemUnion *type_system_union;
1188 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1194 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1198 r = type_system_union_get_type_system(type_system_union,
1206 r = rtnl_message_read_internal(m, type, &container);
1214 r = rtnl_message_parse(m,
1215 &m->rta_offset_tb[m->n_containers],
1216 &m->rta_tb_size[m->n_containers],
1225 m->container_type_system[m->n_containers] = type_system;
1230 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1231 assert_return(m, -EINVAL);
1232 assert_return(m->sealed, -EINVAL);
1233 assert_return(m->n_containers > 0, -EINVAL);
1235 free(m->rta_offset_tb[m->n_containers]);
1236 m->rta_offset_tb[m->n_containers] = NULL;
1237 m->container_type_system[m->n_containers] = NULL;
1244 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1248 return m->hdr->nlmsg_seq;
1251 int sd_rtnl_message_is_error(sd_rtnl_message *m) {
1252 assert_return(m, 0);
1253 assert_return(m->hdr, 0);
1255 return m->hdr->nlmsg_type == NLMSG_ERROR;
1258 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1259 struct nlmsgerr *err;
1261 assert_return(m, -EINVAL);
1262 assert_return(m->hdr, -EINVAL);
1264 if (!sd_rtnl_message_is_error(m))
1267 err = NLMSG_DATA(m->hdr);
1272 int rtnl_message_parse(sd_rtnl_message *m,
1273 size_t **rta_offset_tb,
1274 unsigned short *rta_tb_size,
1277 unsigned int rt_len) {
1278 unsigned short type;
1281 tb = new0(size_t, max + 1);
1285 *rta_tb_size = max + 1;
1287 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1288 type = RTA_TYPE(rta);
1290 /* if the kernel is newer than the headers we used
1291 when building, we ignore out-of-range attributes
1297 log_debug("rtnl: message parse - overwriting repeated attribute");
1299 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1302 *rta_offset_tb = tb;
1307 /* returns the number of bytes sent, or a negative error code */
1308 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1311 struct sockaddr_nl nl;
1313 .nl.nl_family = AF_NETLINK,
1321 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1322 0, &addr.sa, sizeof(addr));
1324 return (errno == EAGAIN) ? 0 : -errno;
1329 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1330 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1331 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1332 struct msghdr msg = {
1335 .msg_control = cred_buffer,
1336 .msg_controllen = sizeof(cred_buffer),
1338 struct cmsghdr *cmsg;
1346 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1349 if (errno == ENOBUFS)
1350 log_debug("rtnl: kernel receive buffer overrun");
1352 return (errno == EAGAIN) ? 0 : -errno;
1354 /* connection was closed by the kernel */
1357 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1358 if (cmsg->cmsg_level == SOL_SOCKET &&
1359 cmsg->cmsg_type == SCM_CREDENTIALS &&
1360 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1361 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1363 /* from the kernel */
1364 if (ucred->uid == 0 && ucred->pid == 0)
1366 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1367 cmsg->cmsg_type == NETLINK_PKTINFO &&
1368 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1369 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1371 /* multi-cast group */
1372 group = pktinfo->group;
1377 /* not from the kernel, ignore */
1386 /* On success, the number of bytes received is returned and *ret points to the received message
1387 * which has a valid header and the correct size.
1388 * If nothing useful was received 0 is returned.
1389 * On failure, a negative error code is returned.
1391 int socket_read_message(sd_rtnl *rtnl) {
1392 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1393 struct iovec iov = {};
1395 bool multi_part = false, done = false;
1396 struct nlmsghdr *new_msg;
1402 assert(rtnl->rbuffer);
1403 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1405 /* read nothing, just get the pending message size */
1406 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1412 /* make room for the pending message */
1413 if (!greedy_realloc((void **)&rtnl->rbuffer,
1414 &rtnl->rbuffer_allocated,
1415 len, sizeof(uint8_t)))
1418 iov.iov_base = rtnl->rbuffer;
1419 iov.iov_len = rtnl->rbuffer_allocated;
1421 /* read the pending message */
1422 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1428 if (len > rtnl->rbuffer_allocated)
1429 /* message did not fit in read buffer */
1432 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1435 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1436 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1437 rtnl->rbuffer->nlmsg_seq) {
1438 first = rtnl->rqueue_partial[i];
1444 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
1445 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1446 const NLType *nl_type;
1448 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1449 /* not broadcast and not for us */
1452 if (new_msg->nlmsg_type == NLMSG_NOOP)
1453 /* silently drop noop messages */
1456 if (new_msg->nlmsg_type == NLMSG_DONE) {
1457 /* finished reading multi-part message */
1463 /* check that we support this message type */
1464 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1467 log_debug("sd-rtnl: ignored message with unknown type: %u",
1468 new_msg->nlmsg_type);
1473 /* check that the size matches the message type */
1474 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
1475 log_debug("sd-rtnl: message larger than expected, dropping");
1479 r = message_new_empty(rtnl, &m);
1483 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1487 /* seal and parse the top-level message */
1488 r = sd_rtnl_message_rewind(m);
1492 /* push the message onto the multi-part message stack */
1500 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1505 if (!multi_part || done) {
1506 /* we got a complete message, push it on the read queue */
1507 r = rtnl_rqueue_make_room(rtnl);
1511 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1514 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1515 /* remove the message form the partial read queue */
1516 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1517 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1518 rtnl->rqueue_partial_size --;
1523 /* we only got a partial multi-part message, push it on the
1524 partial read queue */
1525 if (i < rtnl->rqueue_partial_size) {
1526 rtnl->rqueue_partial[i] = first;
1528 r = rtnl_rqueue_partial_make_room(rtnl);
1532 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1540 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1545 assert_return(m, -EINVAL);
1547 /* don't allow appending to message once parsed */
1549 rtnl_message_seal(m);
1551 for (i = 1; i <= m->n_containers; i++) {
1552 free(m->rta_offset_tb[i]);
1553 m->rta_offset_tb[i] = NULL;
1554 m->rta_tb_size[i] = 0;
1555 m->container_type_system[i] = NULL;
1558 m->n_containers = 0;
1560 if (m->rta_offset_tb[0]) {
1561 /* top-level attributes have already been parsed */
1567 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1571 if (type->type == NLA_NESTED) {
1572 const NLTypeSystem *type_system = type->type_system;
1574 assert(type_system);
1576 m->container_type_system[0] = type_system;
1578 r = rtnl_message_parse(m,
1579 &m->rta_offset_tb[m->n_containers],
1580 &m->rta_tb_size[m->n_containers],
1582 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1583 NLMSG_ALIGN(type->size)),
1584 NLMSG_PAYLOAD(m->hdr, type->size));
1592 void rtnl_message_seal(sd_rtnl_message *m) {
1599 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1600 assert_return(m, NULL);