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_scope(sd_rtnl_message *m, unsigned char scope) {
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 rtm->rtm_scope = scope;
131 int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) {
134 assert_return(m, -EINVAL);
135 assert_return(m->hdr, -EINVAL);
136 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
137 assert_return(family, -EINVAL);
139 rtm = NLMSG_DATA(m->hdr);
141 *family = rtm->rtm_family;
146 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
147 uint16_t nlmsg_type, int rtm_family,
148 unsigned char rtm_protocol) {
152 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
153 assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
154 rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
155 assert_return(ret, -EINVAL);
157 r = message_new(rtnl, ret, nlmsg_type);
161 if (nlmsg_type == RTM_NEWROUTE)
162 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
164 rtm = NLMSG_DATA((*ret)->hdr);
166 rtm->rtm_family = rtm_family;
167 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
168 rtm->rtm_type = RTN_UNICAST;
169 rtm->rtm_table = RT_TABLE_MAIN;
170 rtm->rtm_protocol = rtm_protocol;
175 int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
178 assert_return(m, -EINVAL);
179 assert_return(m->hdr, -EINVAL);
180 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
181 assert_return(family, -EINVAL);
183 ndm = NLMSG_DATA(m->hdr);
185 *family = ndm->ndm_family;
190 int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
193 assert_return(m, -EINVAL);
194 assert_return(m->hdr, -EINVAL);
195 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
196 assert_return(index, -EINVAL);
198 ndm = NLMSG_DATA(m->hdr);
200 *index = ndm->ndm_ifindex;
205 int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
209 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
210 assert_return(ndm_family == AF_INET || ndm_family == AF_INET6, -EINVAL);
211 assert_return(ret, -EINVAL);
213 r = message_new(rtnl, ret, nlmsg_type);
217 if (nlmsg_type == RTM_NEWNEIGH)
218 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
220 ndm = NLMSG_DATA((*ret)->hdr);
222 ndm->ndm_family = ndm_family;
223 ndm->ndm_ifindex = index;
228 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
229 struct ifinfomsg *ifi;
231 assert_return(m, -EINVAL);
232 assert_return(m->hdr, -EINVAL);
233 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
234 assert_return(change, -EINVAL);
236 ifi = NLMSG_DATA(m->hdr);
238 ifi->ifi_flags = flags;
239 ifi->ifi_change = change;
244 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
245 struct ifinfomsg *ifi;
247 assert_return(m, -EINVAL);
248 assert_return(m->hdr, -EINVAL);
249 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
251 ifi = NLMSG_DATA(m->hdr);
253 ifi->ifi_type = type;
258 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
259 struct ifinfomsg *ifi;
261 assert_return(m, -EINVAL);
262 assert_return(m->hdr, -EINVAL);
263 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
265 ifi = NLMSG_DATA(m->hdr);
267 ifi->ifi_family = family;
272 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
273 uint16_t nlmsg_type, int index) {
274 struct ifinfomsg *ifi;
277 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
278 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
279 assert_return(ret, -EINVAL);
281 r = message_new(rtnl, ret, nlmsg_type);
285 if (nlmsg_type == RTM_NEWLINK)
286 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
288 ifi = NLMSG_DATA((*ret)->hdr);
290 ifi->ifi_family = AF_UNSPEC;
291 ifi->ifi_index = index;
296 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
297 assert_return(m, -EINVAL);
298 assert_return(m->hdr, -EINVAL);
299 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
300 m->hdr->nlmsg_type == RTM_GETADDR ||
301 m->hdr->nlmsg_type == RTM_GETROUTE ||
302 m->hdr->nlmsg_type == RTM_GETNEIGH,
306 m->hdr->nlmsg_flags |= NLM_F_DUMP;
308 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
313 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
314 struct ifaddrmsg *ifa;
316 assert_return(m, -EINVAL);
317 assert_return(m->hdr, -EINVAL);
318 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
320 ifa = NLMSG_DATA(m->hdr);
322 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
323 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
326 ifa->ifa_prefixlen = prefixlen;
331 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
332 struct ifaddrmsg *ifa;
334 assert_return(m, -EINVAL);
335 assert_return(m->hdr, -EINVAL);
336 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
338 ifa = NLMSG_DATA(m->hdr);
340 ifa->ifa_flags = flags;
345 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
346 struct ifaddrmsg *ifa;
348 assert_return(m, -EINVAL);
349 assert_return(m->hdr, -EINVAL);
350 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
352 ifa = NLMSG_DATA(m->hdr);
354 ifa->ifa_scope = scope;
359 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
360 struct ifaddrmsg *ifa;
362 assert_return(m, -EINVAL);
363 assert_return(m->hdr, -EINVAL);
364 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
365 assert_return(family, -EINVAL);
367 ifa = NLMSG_DATA(m->hdr);
369 *family = ifa->ifa_family;
374 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
375 struct ifaddrmsg *ifa;
377 assert_return(m, -EINVAL);
378 assert_return(m->hdr, -EINVAL);
379 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
380 assert_return(prefixlen, -EINVAL);
382 ifa = NLMSG_DATA(m->hdr);
384 *prefixlen = ifa->ifa_prefixlen;
389 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
390 struct ifaddrmsg *ifa;
392 assert_return(m, -EINVAL);
393 assert_return(m->hdr, -EINVAL);
394 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
395 assert_return(scope, -EINVAL);
397 ifa = NLMSG_DATA(m->hdr);
399 *scope = ifa->ifa_scope;
404 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
405 struct ifaddrmsg *ifa;
407 assert_return(m, -EINVAL);
408 assert_return(m->hdr, -EINVAL);
409 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
410 assert_return(flags, -EINVAL);
412 ifa = NLMSG_DATA(m->hdr);
414 *flags = ifa->ifa_flags;
419 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
420 struct ifaddrmsg *ifa;
422 assert_return(m, -EINVAL);
423 assert_return(m->hdr, -EINVAL);
424 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
425 assert_return(ifindex, -EINVAL);
427 ifa = NLMSG_DATA(m->hdr);
429 *ifindex = ifa->ifa_index;
434 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
435 uint16_t nlmsg_type, int index,
437 struct ifaddrmsg *ifa;
440 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
441 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
443 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
444 family == AF_INET || family == AF_INET6, -EINVAL);
445 assert_return(ret, -EINVAL);
447 r = message_new(rtnl, ret, nlmsg_type);
451 if (nlmsg_type == RTM_GETADDR)
452 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
454 ifa = NLMSG_DATA((*ret)->hdr);
456 ifa->ifa_index = index;
457 ifa->ifa_family = family;
458 if (family == AF_INET)
459 ifa->ifa_prefixlen = 32;
460 else if (family == AF_INET6)
461 ifa->ifa_prefixlen = 128;
466 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
467 int index, int family) {
470 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
474 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
479 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
481 assert_se(REFCNT_INC(m->n_ref) >= 2);
486 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
487 if (m && REFCNT_DEC(m->n_ref) <= 0) {
492 for (i = 0; i <= m->n_containers; i++)
493 free(m->rta_offset_tb[i]);
495 sd_rtnl_message_unref(m->next);
503 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
504 assert_return(m, -EINVAL);
505 assert_return(type, -EINVAL);
507 *type = m->hdr->nlmsg_type;
512 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
513 assert_return(m, -EINVAL);
515 return !m->hdr->nlmsg_pid;
518 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
519 struct ifinfomsg *ifi;
521 assert_return(m, -EINVAL);
522 assert_return(m->hdr, -EINVAL);
523 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
524 assert_return(ifindex, -EINVAL);
526 ifi = NLMSG_DATA(m->hdr);
528 *ifindex = ifi->ifi_index;
533 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
534 struct ifinfomsg *ifi;
536 assert_return(m, -EINVAL);
537 assert_return(m->hdr, -EINVAL);
538 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
539 assert_return(flags, -EINVAL);
541 ifi = NLMSG_DATA(m->hdr);
543 *flags = ifi->ifi_flags;
548 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
549 struct ifinfomsg *ifi;
551 assert_return(m, -EINVAL);
552 assert_return(m->hdr, -EINVAL);
553 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
554 assert_return(type, -EINVAL);
556 ifi = NLMSG_DATA(m->hdr);
558 *type = ifi->ifi_type;
563 /* If successful the updated message will be correctly aligned, if
564 unsuccessful the old message is untouched. */
565 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
567 size_t message_length, padding_length;
568 struct nlmsghdr *new_hdr;
577 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
578 assert(!data || data_length);
580 /* get offset of the new attribute */
581 offset = m->hdr->nlmsg_len;
583 /* get the size of the new rta attribute (with padding at the end) */
584 rta_length = RTA_LENGTH(data_length);
586 /* get the new message size (with padding at the end) */
587 message_length = offset + RTA_ALIGN(rta_length);
589 /* realloc to fit the new attribute */
590 new_hdr = realloc(m->hdr, message_length);
595 /* get pointer to the attribute we are about to add */
596 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
598 /* if we are inside containers, extend them */
599 for (i = 0; i < m->n_containers; i++)
600 GET_CONTAINER(m, i)->rta_len += message_length - offset;
602 /* fill in the attribute */
603 rta->rta_type = type;
604 rta->rta_len = rta_length;
606 /* we don't deal with the case where the user lies about the type
607 * and gives us too little data (so don't do that)
609 padding = mempcpy(RTA_DATA(rta), data, data_length);
611 /* if no data was passed, make sure we still initialize the padding
612 note that we can have data_length > 0 (used by some containers) */
613 padding = RTA_DATA(rta);
616 /* make sure also the padding at the end of the message is initialized */
617 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
618 memzero(padding, padding_length);
620 /* update message size */
621 m->hdr->nlmsg_len = message_length;
626 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
630 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
634 if (type->type != data_type)
640 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
644 assert_return(m, -EINVAL);
645 assert_return(!m->sealed, -EPERM);
646 assert_return(data, -EINVAL);
648 r = message_attribute_has_type(m, type, NLA_STRING);
655 length = strnlen(data, size);
659 length = strlen(data);
661 r = add_rtattr(m, type, data, length + 1);
668 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
671 assert_return(m, -EINVAL);
672 assert_return(!m->sealed, -EPERM);
674 r = message_attribute_has_type(m, type, NLA_U8);
678 r = add_rtattr(m, type, &data, sizeof(uint8_t));
686 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
689 assert_return(m, -EINVAL);
690 assert_return(!m->sealed, -EPERM);
692 r = message_attribute_has_type(m, type, NLA_U16);
696 r = add_rtattr(m, type, &data, sizeof(uint16_t));
703 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
706 assert_return(m, -EINVAL);
707 assert_return(!m->sealed, -EPERM);
709 r = message_attribute_has_type(m, type, NLA_U32);
713 r = add_rtattr(m, type, &data, sizeof(uint32_t));
720 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
723 assert_return(m, -EINVAL);
724 assert_return(!m->sealed, -EPERM);
725 assert_return(data, -EINVAL);
727 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
731 r = add_rtattr(m, type, data, sizeof(struct in_addr));
738 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
741 assert_return(m, -EINVAL);
742 assert_return(!m->sealed, -EPERM);
743 assert_return(data, -EINVAL);
745 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
749 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
756 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
759 assert_return(m, -EINVAL);
760 assert_return(!m->sealed, -EPERM);
761 assert_return(data, -EINVAL);
763 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
767 r = add_rtattr(m, type, data, ETH_ALEN);
774 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
777 assert_return(m, -EINVAL);
778 assert_return(!m->sealed, -EPERM);
779 assert_return(info, -EINVAL);
781 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
785 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
792 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
796 assert_return(m, -EINVAL);
797 assert_return(!m->sealed, -EPERM);
798 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
800 r = message_attribute_has_type(m, type, NLA_NESTED);
806 r = type_system_get_type_system(m->container_type_system[m->n_containers],
807 &m->container_type_system[m->n_containers + 1],
812 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
816 m->container_offsets[m->n_containers ++] = r;
821 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
822 const NLTypeSystemUnion *type_system_union;
825 assert_return(m, -EINVAL);
826 assert_return(!m->sealed, -EPERM);
828 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
832 r = type_system_union_get_type_system(type_system_union,
833 &m->container_type_system[m->n_containers + 1],
838 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
842 /* do we evere need non-null size */
843 r = add_rtattr(m, type, NULL, 0);
847 m->container_offsets[m->n_containers ++] = r;
853 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
854 assert_return(m, -EINVAL);
855 assert_return(!m->sealed, -EPERM);
856 assert_return(m->n_containers > 0, -EINVAL);
858 m->container_type_system[m->n_containers] = NULL;
864 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
867 assert_return(m, -EINVAL);
868 assert_return(m->sealed, -EPERM);
869 assert_return(data, -EINVAL);
870 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
871 assert(m->rta_offset_tb[m->n_containers]);
872 assert(type < m->rta_tb_size[m->n_containers]);
874 if(!m->rta_offset_tb[m->n_containers][type])
877 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
879 *data = RTA_DATA(rta);
881 return RTA_PAYLOAD(rta);
884 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
888 assert_return(m, -EINVAL);
890 r = message_attribute_has_type(m, type, NLA_STRING);
894 r = rtnl_message_read_internal(m, type, &attr_data);
897 else if (strnlen(attr_data, r) >= (size_t) r)
901 *data = (const char *) attr_data;
906 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
910 assert_return(m, -EINVAL);
912 r = message_attribute_has_type(m, type, NLA_U8);
916 r = rtnl_message_read_internal(m, type, &attr_data);
919 else if ((size_t) r < sizeof(uint8_t))
923 *data = *(uint8_t *) attr_data;
928 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
932 assert_return(m, -EINVAL);
934 r = message_attribute_has_type(m, type, NLA_U16);
938 r = rtnl_message_read_internal(m, type, &attr_data);
941 else if ((size_t) r < sizeof(uint16_t))
945 *data = *(uint16_t *) attr_data;
950 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
954 assert_return(m, -EINVAL);
956 r = message_attribute_has_type(m, type, NLA_U32);
960 r = rtnl_message_read_internal(m, type, &attr_data);
963 else if ((size_t)r < sizeof(uint32_t))
967 *data = *(uint32_t *) attr_data;
972 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
976 assert_return(m, -EINVAL);
978 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
982 r = rtnl_message_read_internal(m, type, &attr_data);
985 else if ((size_t)r < sizeof(struct ether_addr))
989 memcpy(data, attr_data, sizeof(struct ether_addr));
994 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
998 assert_return(m, -EINVAL);
1000 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
1004 r = rtnl_message_read_internal(m, type, &attr_data);
1007 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
1011 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
1016 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
1020 assert_return(m, -EINVAL);
1022 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1026 r = rtnl_message_read_internal(m, type, &attr_data);
1029 else if ((size_t)r < sizeof(struct in_addr))
1033 memcpy(data, attr_data, sizeof(struct in_addr));
1038 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
1042 assert_return(m, -EINVAL);
1044 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1048 r = rtnl_message_read_internal(m, type, &attr_data);
1051 else if ((size_t)r < sizeof(struct in6_addr))
1055 memcpy(data, attr_data, sizeof(struct in6_addr));
1060 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
1061 const NLType *nl_type;
1062 const NLTypeSystem *type_system;
1067 assert_return(m, -EINVAL);
1068 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1070 r = type_system_get_type(m->container_type_system[m->n_containers],
1076 if (nl_type->type == NLA_NESTED) {
1077 r = type_system_get_type_system(m->container_type_system[m->n_containers],
1082 } else if (nl_type->type == NLA_UNION) {
1083 const NLTypeSystemUnion *type_system_union;
1086 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1092 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1096 r = type_system_union_get_type_system(type_system_union,
1104 r = rtnl_message_read_internal(m, type, &container);
1112 r = rtnl_message_parse(m,
1113 &m->rta_offset_tb[m->n_containers],
1114 &m->rta_tb_size[m->n_containers],
1123 m->container_type_system[m->n_containers] = type_system;
1128 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1129 assert_return(m, -EINVAL);
1130 assert_return(m->sealed, -EINVAL);
1131 assert_return(m->n_containers > 0, -EINVAL);
1133 free(m->rta_offset_tb[m->n_containers]);
1134 m->rta_offset_tb[m->n_containers] = NULL;
1135 m->container_type_system[m->n_containers] = NULL;
1142 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1146 return m->hdr->nlmsg_seq;
1149 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1150 struct nlmsgerr *err;
1152 assert_return(m, -EINVAL);
1153 assert_return(m->hdr, -EINVAL);
1155 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1158 err = NLMSG_DATA(m->hdr);
1163 int rtnl_message_parse(sd_rtnl_message *m,
1164 size_t **rta_offset_tb,
1165 unsigned short *rta_tb_size,
1168 unsigned int rt_len) {
1169 unsigned short type;
1172 tb = new0(size_t, max + 1);
1176 *rta_tb_size = max + 1;
1178 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1179 type = RTA_TYPE(rta);
1181 /* if the kernel is newer than the headers we used
1182 when building, we ignore out-of-range attributes
1188 log_debug("rtnl: message parse - overwriting repeated attribute");
1190 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1193 *rta_offset_tb = tb;
1198 /* returns the number of bytes sent, or a negative error code */
1199 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1202 struct sockaddr_nl nl;
1204 .nl.nl_family = AF_NETLINK,
1212 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1213 0, &addr.sa, sizeof(addr));
1215 return (errno == EAGAIN) ? 0 : -errno;
1220 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1221 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1222 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1223 struct msghdr msg = {
1226 .msg_control = cred_buffer,
1227 .msg_controllen = sizeof(cred_buffer),
1229 struct cmsghdr *cmsg;
1237 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1240 if (errno == ENOBUFS)
1241 log_debug("rtnl: kernel receive buffer overrun");
1243 return (errno == EAGAIN) ? 0 : -errno;
1245 /* connection was closed by the kernel */
1248 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1249 if (cmsg->cmsg_level == SOL_SOCKET &&
1250 cmsg->cmsg_type == SCM_CREDENTIALS &&
1251 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1252 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1254 /* from the kernel */
1255 if (ucred->uid == 0 && ucred->pid == 0)
1257 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1258 cmsg->cmsg_type == NETLINK_PKTINFO &&
1259 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1260 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1262 /* multi-cast group */
1263 group = pktinfo->group;
1268 /* not from the kernel, ignore */
1277 /* On success, the number of bytes received is returned and *ret points to the received message
1278 * which has a valid header and the correct size.
1279 * If nothing useful was received 0 is returned.
1280 * On failure, a negative error code is returned.
1282 int socket_read_message(sd_rtnl *rtnl) {
1283 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1284 struct iovec iov = {};
1286 bool multi_part = false, done = false;
1287 struct nlmsghdr *new_msg;
1293 assert(rtnl->rbuffer);
1294 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1296 /* read nothing, just get the pending message size */
1297 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1303 /* make room for the pending message */
1304 if (!greedy_realloc((void **)&rtnl->rbuffer,
1305 &rtnl->rbuffer_allocated,
1306 len, sizeof(uint8_t)))
1309 iov.iov_base = rtnl->rbuffer;
1310 iov.iov_len = rtnl->rbuffer_allocated;
1312 /* read the pending message */
1313 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1319 if (len > rtnl->rbuffer_allocated)
1320 /* message did not fit in read buffer */
1323 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1326 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1327 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1328 rtnl->rbuffer->nlmsg_seq) {
1329 first = rtnl->rqueue_partial[i];
1335 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1336 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1337 const NLType *nl_type;
1339 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1340 /* not broadcast and not for us */
1343 if (new_msg->nlmsg_type == NLMSG_NOOP)
1344 /* silently drop noop messages */
1347 if (new_msg->nlmsg_type == NLMSG_DONE) {
1348 /* finished reading multi-part message */
1353 /* check that we support this message type */
1354 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1357 log_debug("sd-rtnl: ignored message with unknown type: %u",
1358 new_msg->nlmsg_type);
1363 /* check that the size matches the message type */
1364 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
1365 log_debug("sd-rtnl: message larger than expected, dropping");
1369 r = message_new_empty(rtnl, &m);
1373 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1377 /* seal and parse the top-level message */
1378 r = sd_rtnl_message_rewind(m);
1382 /* push the message onto the multi-part message stack */
1390 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1395 if (!multi_part || done) {
1396 /* we got a complete message, push it on the read queue */
1397 r = rtnl_rqueue_make_room(rtnl);
1401 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1404 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1405 /* remove the message form the partial read queue */
1406 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1407 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1408 rtnl->rqueue_partial_size --;
1413 /* we only got a partial multi-part message, push it on the
1414 partial read queue */
1415 if (i < rtnl->rqueue_partial_size) {
1416 rtnl->rqueue_partial[i] = first;
1418 r = rtnl_rqueue_partial_make_room(rtnl);
1422 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1430 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1435 assert_return(m, -EINVAL);
1437 /* don't allow appending to message once parsed */
1439 rtnl_message_seal(m);
1441 for (i = 1; i <= m->n_containers; i++) {
1442 free(m->rta_offset_tb[i]);
1443 m->rta_offset_tb[i] = NULL;
1444 m->rta_tb_size[i] = 0;
1445 m->container_type_system[i] = NULL;
1448 m->n_containers = 0;
1450 if (m->rta_offset_tb[0]) {
1451 /* top-level attributes have already been parsed */
1457 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1461 if (type->type == NLA_NESTED) {
1462 const NLTypeSystem *type_system = type->type_system;
1464 assert(type_system);
1466 m->container_type_system[0] = type_system;
1468 r = rtnl_message_parse(m,
1469 &m->rta_offset_tb[m->n_containers],
1470 &m->rta_tb_size[m->n_containers],
1472 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1473 NLMSG_ALIGN(type->size)),
1474 NLMSG_PAYLOAD(m->hdr, type->size));
1482 void rtnl_message_seal(sd_rtnl_message *m) {
1489 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1490 assert_return(m, NULL);