1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/in.h>
27 #include "formats-util.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 currently unused, if we start using it internally
47 we must take care to avoid problems due to mutual references between
48 buses 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 r = message_new_empty(rtnl, &m);
78 size = NLMSG_SPACE(nl_type->size);
80 assert(size >= sizeof(struct nlmsghdr));
81 m->hdr = malloc0(size);
85 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
87 m->container_type_system[0] = nl_type->type_system;
88 m->hdr->nlmsg_len = size;
89 m->hdr->nlmsg_type = type;
97 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
100 assert_return(m, -EINVAL);
101 assert_return(m->hdr, -EINVAL);
102 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
104 rtm = NLMSG_DATA(m->hdr);
106 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
107 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
110 rtm->rtm_dst_len = prefixlen;
115 int sd_rtnl_message_route_set_src_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
118 assert_return(m, -EINVAL);
119 assert_return(m->hdr, -EINVAL);
120 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
122 rtm = NLMSG_DATA(m->hdr);
124 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
125 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
128 rtm->rtm_src_len = prefixlen;
133 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
136 assert_return(m, -EINVAL);
137 assert_return(m->hdr, -EINVAL);
138 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
140 rtm = NLMSG_DATA(m->hdr);
142 rtm->rtm_scope = scope;
147 int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) {
150 assert_return(m, -EINVAL);
151 assert_return(m->hdr, -EINVAL);
152 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
153 assert_return(family, -EINVAL);
155 rtm = NLMSG_DATA(m->hdr);
157 *family = rtm->rtm_family;
162 int sd_rtnl_message_route_get_dst_prefixlen(sd_rtnl_message *m, unsigned char *dst_len) {
165 assert_return(m, -EINVAL);
166 assert_return(m->hdr, -EINVAL);
167 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
168 assert_return(dst_len, -EINVAL);
170 rtm = NLMSG_DATA(m->hdr);
172 *dst_len = rtm->rtm_dst_len;
177 int sd_rtnl_message_route_get_src_prefixlen(sd_rtnl_message *m, unsigned char *src_len) {
180 assert_return(m, -EINVAL);
181 assert_return(m->hdr, -EINVAL);
182 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
183 assert_return(src_len, -EINVAL);
185 rtm = NLMSG_DATA(m->hdr);
187 *src_len = rtm->rtm_src_len;
192 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
193 uint16_t nlmsg_type, int rtm_family,
194 unsigned char rtm_protocol) {
198 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
199 assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
200 rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
201 assert_return(ret, -EINVAL);
203 r = message_new(rtnl, ret, nlmsg_type);
207 if (nlmsg_type == RTM_NEWROUTE)
208 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
210 rtm = NLMSG_DATA((*ret)->hdr);
212 rtm->rtm_family = rtm_family;
213 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
214 rtm->rtm_type = RTN_UNICAST;
215 rtm->rtm_table = RT_TABLE_MAIN;
216 rtm->rtm_protocol = rtm_protocol;
221 int sd_rtnl_message_neigh_set_flags(sd_rtnl_message *m, uint8_t flags) {
224 assert_return(m, -EINVAL);
225 assert_return(m->hdr, -EINVAL);
226 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
228 ndm = NLMSG_DATA(m->hdr);
229 ndm->ndm_flags |= flags;
234 int sd_rtnl_message_neigh_set_state(sd_rtnl_message *m, uint16_t state) {
237 assert_return(m, -EINVAL);
238 assert_return(m->hdr, -EINVAL);
239 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
241 ndm = NLMSG_DATA(m->hdr);
242 ndm->ndm_state |= state;
247 int sd_rtnl_message_neigh_get_flags(sd_rtnl_message *m, uint8_t *flags) {
250 assert_return(m, -EINVAL);
251 assert_return(m->hdr, -EINVAL);
252 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
254 ndm = NLMSG_DATA(m->hdr);
255 *flags = ndm->ndm_flags;
260 int sd_rtnl_message_neigh_get_state(sd_rtnl_message *m, uint16_t *state) {
263 assert_return(m, -EINVAL);
264 assert_return(m->hdr, -EINVAL);
265 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
267 ndm = NLMSG_DATA(m->hdr);
268 *state = ndm->ndm_state;
273 int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
276 assert_return(m, -EINVAL);
277 assert_return(m->hdr, -EINVAL);
278 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
279 assert_return(family, -EINVAL);
281 ndm = NLMSG_DATA(m->hdr);
283 *family = ndm->ndm_family;
288 int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
291 assert_return(m, -EINVAL);
292 assert_return(m->hdr, -EINVAL);
293 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
294 assert_return(index, -EINVAL);
296 ndm = NLMSG_DATA(m->hdr);
298 *index = ndm->ndm_ifindex;
303 int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
307 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
308 assert_return(ndm_family == AF_INET ||
309 ndm_family == AF_INET6 ||
310 ndm_family == PF_BRIDGE, -EINVAL);
311 assert_return(ret, -EINVAL);
313 r = message_new(rtnl, ret, nlmsg_type);
317 if (nlmsg_type == RTM_NEWNEIGH)
318 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
320 ndm = NLMSG_DATA((*ret)->hdr);
322 ndm->ndm_family = ndm_family;
323 ndm->ndm_ifindex = index;
328 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
329 struct ifinfomsg *ifi;
331 assert_return(m, -EINVAL);
332 assert_return(m->hdr, -EINVAL);
333 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
334 assert_return(change, -EINVAL);
336 ifi = NLMSG_DATA(m->hdr);
338 ifi->ifi_flags = flags;
339 ifi->ifi_change = change;
344 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
345 struct ifinfomsg *ifi;
347 assert_return(m, -EINVAL);
348 assert_return(m->hdr, -EINVAL);
349 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
351 ifi = NLMSG_DATA(m->hdr);
353 ifi->ifi_type = type;
358 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
359 struct ifinfomsg *ifi;
361 assert_return(m, -EINVAL);
362 assert_return(m->hdr, -EINVAL);
363 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
365 ifi = NLMSG_DATA(m->hdr);
367 ifi->ifi_family = family;
372 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
373 uint16_t nlmsg_type, int index) {
374 struct ifinfomsg *ifi;
377 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
378 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
379 assert_return(ret, -EINVAL);
381 r = message_new(rtnl, ret, nlmsg_type);
385 if (nlmsg_type == RTM_NEWLINK)
386 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
388 ifi = NLMSG_DATA((*ret)->hdr);
390 ifi->ifi_family = AF_UNSPEC;
391 ifi->ifi_index = index;
396 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
397 assert_return(m, -EINVAL);
398 assert_return(m->hdr, -EINVAL);
399 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
400 m->hdr->nlmsg_type == RTM_GETADDR ||
401 m->hdr->nlmsg_type == RTM_GETROUTE ||
402 m->hdr->nlmsg_type == RTM_GETNEIGH,
406 m->hdr->nlmsg_flags |= NLM_F_DUMP;
408 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
413 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
414 struct ifaddrmsg *ifa;
416 assert_return(m, -EINVAL);
417 assert_return(m->hdr, -EINVAL);
418 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
420 ifa = NLMSG_DATA(m->hdr);
422 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
423 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
426 ifa->ifa_prefixlen = prefixlen;
431 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
432 struct ifaddrmsg *ifa;
434 assert_return(m, -EINVAL);
435 assert_return(m->hdr, -EINVAL);
436 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
438 ifa = NLMSG_DATA(m->hdr);
440 ifa->ifa_flags = flags;
445 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
446 struct ifaddrmsg *ifa;
448 assert_return(m, -EINVAL);
449 assert_return(m->hdr, -EINVAL);
450 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
452 ifa = NLMSG_DATA(m->hdr);
454 ifa->ifa_scope = scope;
459 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
460 struct ifaddrmsg *ifa;
462 assert_return(m, -EINVAL);
463 assert_return(m->hdr, -EINVAL);
464 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
465 assert_return(family, -EINVAL);
467 ifa = NLMSG_DATA(m->hdr);
469 *family = ifa->ifa_family;
474 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
475 struct ifaddrmsg *ifa;
477 assert_return(m, -EINVAL);
478 assert_return(m->hdr, -EINVAL);
479 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
480 assert_return(prefixlen, -EINVAL);
482 ifa = NLMSG_DATA(m->hdr);
484 *prefixlen = ifa->ifa_prefixlen;
489 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
490 struct ifaddrmsg *ifa;
492 assert_return(m, -EINVAL);
493 assert_return(m->hdr, -EINVAL);
494 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
495 assert_return(scope, -EINVAL);
497 ifa = NLMSG_DATA(m->hdr);
499 *scope = ifa->ifa_scope;
504 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
505 struct ifaddrmsg *ifa;
507 assert_return(m, -EINVAL);
508 assert_return(m->hdr, -EINVAL);
509 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
510 assert_return(flags, -EINVAL);
512 ifa = NLMSG_DATA(m->hdr);
514 *flags = ifa->ifa_flags;
519 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
520 struct ifaddrmsg *ifa;
522 assert_return(m, -EINVAL);
523 assert_return(m->hdr, -EINVAL);
524 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
525 assert_return(ifindex, -EINVAL);
527 ifa = NLMSG_DATA(m->hdr);
529 *ifindex = ifa->ifa_index;
534 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
535 uint16_t nlmsg_type, int index,
537 struct ifaddrmsg *ifa;
540 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
541 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
543 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
544 family == AF_INET || family == AF_INET6, -EINVAL);
545 assert_return(ret, -EINVAL);
547 r = message_new(rtnl, ret, nlmsg_type);
551 if (nlmsg_type == RTM_GETADDR)
552 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
554 ifa = NLMSG_DATA((*ret)->hdr);
556 ifa->ifa_index = index;
557 ifa->ifa_family = family;
558 if (family == AF_INET)
559 ifa->ifa_prefixlen = 32;
560 else if (family == AF_INET6)
561 ifa->ifa_prefixlen = 128;
566 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
567 int index, int family) {
570 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
574 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
579 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
581 assert_se(REFCNT_INC(m->n_ref) >= 2);
586 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
587 if (m && REFCNT_DEC(m->n_ref) == 0) {
592 for (i = 0; i <= m->n_containers; i++)
593 free(m->rta_offset_tb[i]);
595 sd_rtnl_message_unref(m->next);
603 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
604 assert_return(m, -EINVAL);
605 assert_return(type, -EINVAL);
607 *type = m->hdr->nlmsg_type;
612 int sd_rtnl_message_get_family(sd_rtnl_message *m, int *family) {
613 assert_return(m, -EINVAL);
614 assert_return(family, -EINVAL);
618 if (rtnl_message_type_is_link(m->hdr->nlmsg_type)) {
619 struct ifinfomsg *ifi;
621 ifi = NLMSG_DATA(m->hdr);
623 *family = ifi->ifi_family;
626 } else if (rtnl_message_type_is_route(m->hdr->nlmsg_type)) {
629 rtm = NLMSG_DATA(m->hdr);
631 *family = rtm->rtm_family;
634 } else if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type)) {
637 ndm = NLMSG_DATA(m->hdr);
639 *family = ndm->ndm_family;
642 } else if (rtnl_message_type_is_addr(m->hdr->nlmsg_type)) {
643 struct ifaddrmsg *ifa;
645 ifa = NLMSG_DATA(m->hdr);
647 *family = ifa->ifa_family;
655 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
656 assert_return(m, -EINVAL);
661 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
662 struct ifinfomsg *ifi;
664 assert_return(m, -EINVAL);
665 assert_return(m->hdr, -EINVAL);
666 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
667 assert_return(ifindex, -EINVAL);
669 ifi = NLMSG_DATA(m->hdr);
671 *ifindex = ifi->ifi_index;
676 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
677 struct ifinfomsg *ifi;
679 assert_return(m, -EINVAL);
680 assert_return(m->hdr, -EINVAL);
681 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
682 assert_return(flags, -EINVAL);
684 ifi = NLMSG_DATA(m->hdr);
686 *flags = ifi->ifi_flags;
691 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
692 struct ifinfomsg *ifi;
694 assert_return(m, -EINVAL);
695 assert_return(m->hdr, -EINVAL);
696 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
697 assert_return(type, -EINVAL);
699 ifi = NLMSG_DATA(m->hdr);
701 *type = ifi->ifi_type;
706 /* If successful the updated message will be correctly aligned, if
707 unsuccessful the old message is untouched. */
708 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
710 size_t message_length, padding_length;
711 struct nlmsghdr *new_hdr;
720 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
721 assert(!data || data_length);
723 /* get offset of the new attribute */
724 offset = m->hdr->nlmsg_len;
726 /* get the size of the new rta attribute (with padding at the end) */
727 rta_length = RTA_LENGTH(data_length);
729 /* get the new message size (with padding at the end) */
730 message_length = offset + RTA_ALIGN(rta_length);
732 /* realloc to fit the new attribute */
733 new_hdr = realloc(m->hdr, message_length);
738 /* get pointer to the attribute we are about to add */
739 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
741 /* if we are inside containers, extend them */
742 for (i = 0; i < m->n_containers; i++)
743 GET_CONTAINER(m, i)->rta_len += message_length - offset;
745 /* fill in the attribute */
746 rta->rta_type = type;
747 rta->rta_len = rta_length;
749 /* we don't deal with the case where the user lies about the type
750 * and gives us too little data (so don't do that)
752 padding = mempcpy(RTA_DATA(rta), data, data_length);
754 /* if no data was passed, make sure we still initialize the padding
755 note that we can have data_length > 0 (used by some containers) */
756 padding = RTA_DATA(rta);
759 /* make sure also the padding at the end of the message is initialized */
760 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
761 memzero(padding, padding_length);
763 /* update message size */
764 m->hdr->nlmsg_len = message_length;
769 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
773 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
777 if (type->type != data_type)
783 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
787 assert_return(m, -EINVAL);
788 assert_return(!m->sealed, -EPERM);
789 assert_return(data, -EINVAL);
791 r = message_attribute_has_type(m, type, NLA_STRING);
798 length = strnlen(data, size+1);
802 length = strlen(data);
804 r = add_rtattr(m, type, data, length + 1);
811 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
814 assert_return(m, -EINVAL);
815 assert_return(!m->sealed, -EPERM);
817 r = message_attribute_has_type(m, type, NLA_U8);
821 r = add_rtattr(m, type, &data, sizeof(uint8_t));
829 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
832 assert_return(m, -EINVAL);
833 assert_return(!m->sealed, -EPERM);
835 r = message_attribute_has_type(m, type, NLA_U16);
839 r = add_rtattr(m, type, &data, sizeof(uint16_t));
846 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
849 assert_return(m, -EINVAL);
850 assert_return(!m->sealed, -EPERM);
852 r = message_attribute_has_type(m, type, NLA_U32);
856 r = add_rtattr(m, type, &data, sizeof(uint32_t));
863 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
866 assert_return(m, -EINVAL);
867 assert_return(!m->sealed, -EPERM);
868 assert_return(data, -EINVAL);
870 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
874 r = add_rtattr(m, type, data, sizeof(struct in_addr));
881 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
884 assert_return(m, -EINVAL);
885 assert_return(!m->sealed, -EPERM);
886 assert_return(data, -EINVAL);
888 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
892 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
899 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
902 assert_return(m, -EINVAL);
903 assert_return(!m->sealed, -EPERM);
904 assert_return(data, -EINVAL);
906 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
910 r = add_rtattr(m, type, data, ETH_ALEN);
917 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
920 assert_return(m, -EINVAL);
921 assert_return(!m->sealed, -EPERM);
922 assert_return(info, -EINVAL);
924 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
928 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
935 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
939 assert_return(m, -EINVAL);
940 assert_return(!m->sealed, -EPERM);
941 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
943 r = message_attribute_has_type(m, type, NLA_NESTED);
945 const NLTypeSystemUnion *type_system_union;
948 r = message_attribute_has_type(m, type, NLA_UNION);
953 r = sd_rtnl_message_get_family(m, &family);
957 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
961 r = type_system_union_protocol_get_type_system(type_system_union,
962 &m->container_type_system[m->n_containers + 1],
969 r = type_system_get_type_system(m->container_type_system[m->n_containers],
970 &m->container_type_system[m->n_containers + 1],
976 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
980 m->container_offsets[m->n_containers ++] = r;
985 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
986 const NLTypeSystemUnion *type_system_union;
989 assert_return(m, -EINVAL);
990 assert_return(!m->sealed, -EPERM);
992 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
996 r = type_system_union_get_type_system(type_system_union,
997 &m->container_type_system[m->n_containers + 1],
1002 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
1006 /* do we evere need non-null size */
1007 r = add_rtattr(m, type, NULL, 0);
1011 m->container_offsets[m->n_containers ++] = r;
1017 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
1018 assert_return(m, -EINVAL);
1019 assert_return(!m->sealed, -EPERM);
1020 assert_return(m->n_containers > 0, -EINVAL);
1022 m->container_type_system[m->n_containers] = NULL;
1028 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
1031 assert_return(m, -EINVAL);
1032 assert_return(m->sealed, -EPERM);
1033 assert_return(data, -EINVAL);
1034 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
1035 assert(m->rta_offset_tb[m->n_containers]);
1036 assert(type < m->rta_tb_size[m->n_containers]);
1038 if(!m->rta_offset_tb[m->n_containers][type])
1041 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
1043 *data = RTA_DATA(rta);
1045 return RTA_PAYLOAD(rta);
1048 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
1052 assert_return(m, -EINVAL);
1054 r = message_attribute_has_type(m, type, NLA_STRING);
1058 r = rtnl_message_read_internal(m, type, &attr_data);
1061 else if (strnlen(attr_data, r) >= (size_t) r)
1065 *data = (const char *) attr_data;
1070 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
1074 assert_return(m, -EINVAL);
1076 r = message_attribute_has_type(m, type, NLA_U8);
1080 r = rtnl_message_read_internal(m, type, &attr_data);
1083 else if ((size_t) r < sizeof(uint8_t))
1087 *data = *(uint8_t *) attr_data;
1092 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
1096 assert_return(m, -EINVAL);
1098 r = message_attribute_has_type(m, type, NLA_U16);
1102 r = rtnl_message_read_internal(m, type, &attr_data);
1105 else if ((size_t) r < sizeof(uint16_t))
1109 *data = *(uint16_t *) attr_data;
1114 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
1118 assert_return(m, -EINVAL);
1120 r = message_attribute_has_type(m, type, NLA_U32);
1124 r = rtnl_message_read_internal(m, type, &attr_data);
1127 else if ((size_t)r < sizeof(uint32_t))
1131 *data = *(uint32_t *) attr_data;
1136 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
1140 assert_return(m, -EINVAL);
1142 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
1146 r = rtnl_message_read_internal(m, type, &attr_data);
1149 else if ((size_t)r < sizeof(struct ether_addr))
1153 memcpy(data, attr_data, sizeof(struct ether_addr));
1158 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
1162 assert_return(m, -EINVAL);
1164 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
1168 r = rtnl_message_read_internal(m, type, &attr_data);
1171 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
1175 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
1180 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
1184 assert_return(m, -EINVAL);
1186 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1190 r = rtnl_message_read_internal(m, type, &attr_data);
1193 else if ((size_t)r < sizeof(struct in_addr))
1197 memcpy(data, attr_data, sizeof(struct in_addr));
1202 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
1206 assert_return(m, -EINVAL);
1208 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1212 r = rtnl_message_read_internal(m, type, &attr_data);
1215 else if ((size_t)r < sizeof(struct in6_addr))
1219 memcpy(data, attr_data, sizeof(struct in6_addr));
1224 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
1225 const NLType *nl_type;
1226 const NLTypeSystem *type_system;
1231 assert_return(m, -EINVAL);
1232 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1234 r = type_system_get_type(m->container_type_system[m->n_containers],
1240 if (nl_type->type == NLA_NESTED) {
1241 r = type_system_get_type_system(m->container_type_system[m->n_containers],
1246 } else if (nl_type->type == NLA_UNION) {
1247 const NLTypeSystemUnion *type_system_union;
1249 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1255 switch (type_system_union->match_type) {
1256 case NL_MATCH_SIBLING:
1260 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1264 r = type_system_union_get_type_system(type_system_union,
1272 case NL_MATCH_PROTOCOL:
1276 r = sd_rtnl_message_get_family(m, &family);
1280 r = type_system_union_protocol_get_type_system(type_system_union,
1289 assert_not_reached("sd-rtnl: invalid type system union type");
1294 r = rtnl_message_read_internal(m, type, &container);
1302 r = rtnl_message_parse(m,
1303 &m->rta_offset_tb[m->n_containers],
1304 &m->rta_tb_size[m->n_containers],
1313 m->container_type_system[m->n_containers] = type_system;
1318 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1319 assert_return(m, -EINVAL);
1320 assert_return(m->sealed, -EINVAL);
1321 assert_return(m->n_containers > 0, -EINVAL);
1323 free(m->rta_offset_tb[m->n_containers]);
1324 m->rta_offset_tb[m->n_containers] = NULL;
1325 m->container_type_system[m->n_containers] = NULL;
1332 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1336 return m->hdr->nlmsg_seq;
1339 int sd_rtnl_message_is_error(sd_rtnl_message *m) {
1340 assert_return(m, 0);
1341 assert_return(m->hdr, 0);
1343 return m->hdr->nlmsg_type == NLMSG_ERROR;
1346 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1347 struct nlmsgerr *err;
1349 assert_return(m, -EINVAL);
1350 assert_return(m->hdr, -EINVAL);
1352 if (!sd_rtnl_message_is_error(m))
1355 err = NLMSG_DATA(m->hdr);
1360 int rtnl_message_parse(sd_rtnl_message *m,
1361 size_t **rta_offset_tb,
1362 unsigned short *rta_tb_size,
1365 unsigned int rt_len) {
1366 unsigned short type;
1369 tb = new0(size_t, max + 1);
1373 *rta_tb_size = max + 1;
1375 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1376 type = RTA_TYPE(rta);
1378 /* if the kernel is newer than the headers we used
1379 when building, we ignore out-of-range attributes
1385 log_debug("rtnl: message parse - overwriting repeated attribute");
1387 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1390 *rta_offset_tb = tb;
1395 /* returns the number of bytes sent, or a negative error code */
1396 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1399 struct sockaddr_nl nl;
1401 .nl.nl_family = AF_NETLINK,
1409 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1410 0, &addr.sa, sizeof(addr));
1412 return (errno == EAGAIN) ? 0 : -errno;
1417 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1418 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1419 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1420 struct msghdr msg = {
1423 .msg_control = cred_buffer,
1424 .msg_controllen = sizeof(cred_buffer),
1426 struct cmsghdr *cmsg;
1434 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1437 if (errno == ENOBUFS)
1438 log_debug("rtnl: kernel receive buffer overrun");
1439 else if (errno == EAGAIN)
1440 log_debug("rtnl: no data in socket");
1442 return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
1445 CMSG_FOREACH(cmsg, &msg) {
1446 if (cmsg->cmsg_level == SOL_SOCKET &&
1447 cmsg->cmsg_type == SCM_CREDENTIALS &&
1448 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1449 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1451 /* from the kernel */
1452 if (ucred->pid == 0)
1455 log_debug("rtnl: ignoring message from PID "PID_FMT, ucred->pid);
1456 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1457 cmsg->cmsg_type == NETLINK_PKTINFO &&
1458 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1459 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1461 /* multi-cast group */
1462 group = pktinfo->group;
1467 /* not from the kernel, ignore */
1469 /* drop the message */
1470 r = recvmsg(fd, &msg, 0);
1472 return (errno == EAGAIN || errno == EINTR) ? 0 : -errno;
1484 /* On success, the number of bytes received is returned and *ret points to the received message
1485 * which has a valid header and the correct size.
1486 * If nothing useful was received 0 is returned.
1487 * On failure, a negative error code is returned.
1489 int socket_read_message(sd_rtnl *rtnl) {
1490 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1491 struct iovec iov = {};
1493 bool multi_part = false, done = false;
1494 struct nlmsghdr *new_msg;
1500 assert(rtnl->rbuffer);
1501 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1503 /* read nothing, just get the pending message size */
1504 r = socket_recv_message(rtnl->fd, &iov, NULL, true);
1510 /* make room for the pending message */
1511 if (!greedy_realloc((void **)&rtnl->rbuffer,
1512 &rtnl->rbuffer_allocated,
1513 len, sizeof(uint8_t)))
1516 iov.iov_base = rtnl->rbuffer;
1517 iov.iov_len = rtnl->rbuffer_allocated;
1519 /* read the pending message */
1520 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1526 if (len > rtnl->rbuffer_allocated)
1527 /* message did not fit in read buffer */
1530 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1533 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1534 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1535 rtnl->rbuffer->nlmsg_seq) {
1536 first = rtnl->rqueue_partial[i];
1542 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
1543 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1544 const NLType *nl_type;
1546 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1547 /* not broadcast and not for us */
1550 if (new_msg->nlmsg_type == NLMSG_NOOP)
1551 /* silently drop noop messages */
1554 if (new_msg->nlmsg_type == NLMSG_DONE) {
1555 /* finished reading multi-part message */
1558 /* if first is not defined, put NLMSG_DONE into the receive queue. */
1563 /* check that we support this message type */
1564 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1566 if (r == -EOPNOTSUPP)
1567 log_debug("sd-rtnl: ignored message with unknown type: %i",
1568 new_msg->nlmsg_type);
1573 /* check that the size matches the message type */
1574 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
1575 log_debug("sd-rtnl: message larger than expected, dropping");
1579 r = message_new_empty(rtnl, &m);
1583 m->broadcast = !!group;
1585 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1589 /* seal and parse the top-level message */
1590 r = sd_rtnl_message_rewind(m);
1594 /* push the message onto the multi-part message stack */
1602 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1607 if (!multi_part || done) {
1608 /* we got a complete message, push it on the read queue */
1609 r = rtnl_rqueue_make_room(rtnl);
1613 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1616 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1617 /* remove the message form the partial read queue */
1618 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1619 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1620 rtnl->rqueue_partial_size --;
1625 /* we only got a partial multi-part message, push it on the
1626 partial read queue */
1627 if (i < rtnl->rqueue_partial_size) {
1628 rtnl->rqueue_partial[i] = first;
1630 r = rtnl_rqueue_partial_make_room(rtnl);
1634 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1642 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1647 assert_return(m, -EINVAL);
1649 /* don't allow appending to message once parsed */
1651 rtnl_message_seal(m);
1653 for (i = 1; i <= m->n_containers; i++) {
1654 free(m->rta_offset_tb[i]);
1655 m->rta_offset_tb[i] = NULL;
1656 m->rta_tb_size[i] = 0;
1657 m->container_type_system[i] = NULL;
1660 m->n_containers = 0;
1662 if (m->rta_offset_tb[0]) {
1663 /* top-level attributes have already been parsed */
1669 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1673 if (type->type == NLA_NESTED) {
1674 const NLTypeSystem *type_system = type->type_system;
1676 assert(type_system);
1678 m->container_type_system[0] = type_system;
1680 r = rtnl_message_parse(m,
1681 &m->rta_offset_tb[m->n_containers],
1682 &m->rta_tb_size[m->n_containers],
1684 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1685 NLMSG_ALIGN(type->size)),
1686 NLMSG_PAYLOAD(m->hdr, type->size));
1694 void rtnl_message_seal(sd_rtnl_message *m) {
1701 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1702 assert_return(m, NULL);