]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-rtnl/rtnl-message.c
journal: Fix navigating backwards missing entries
[thirdparty/systemd.git] / src / libsystemd / sd-rtnl / rtnl-message.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <netinet/in.h>
23 #include <netinet/ether.h>
24 #include <stdbool.h>
25 #include <unistd.h>
26
27 #include "util.h"
28 #include "refcnt.h"
29 #include "missing.h"
30
31 #include "sd-rtnl.h"
32 #include "rtnl-util.h"
33 #include "rtnl-internal.h"
34 #include "rtnl-types.h"
35
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;
38
39 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
40
41 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
42 sd_rtnl_message *m;
43
44 assert_return(ret, -EINVAL);
45
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.
49 */
50
51 m = new0(sd_rtnl_message, 1);
52 if (!m)
53 return -ENOMEM;
54
55 m->n_ref = REFCNT_INIT;
56
57 m->sealed = false;
58
59 *ret = m;
60
61 return 0;
62 }
63
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;
67 size_t size;
68 int r;
69
70 r = type_system_get_type(NULL, &nl_type, type);
71 if (r < 0)
72 return r;
73
74 assert(nl_type->type == NLA_NESTED);
75
76 r = message_new_empty(rtnl, &m);
77 if (r < 0)
78 return r;
79
80 size = NLMSG_SPACE(nl_type->size);
81
82 assert(size >= sizeof(struct nlmsghdr));
83 m->hdr = malloc0(size);
84 if (!m->hdr)
85 return -ENOMEM;
86
87 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
88
89 m->container_type_system[0] = nl_type->type_system;
90 m->hdr->nlmsg_len = size;
91 m->hdr->nlmsg_type = type;
92
93 *ret = m;
94 m = NULL;
95
96 return 0;
97 }
98
99 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
100 struct rtmsg *rtm;
101
102 assert_return(m, -EINVAL);
103 assert_return(m->hdr, -EINVAL);
104 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
105
106 rtm = NLMSG_DATA(m->hdr);
107
108 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
109 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
110 return -ERANGE;
111
112 rtm->rtm_dst_len = prefixlen;
113
114 return 0;
115 }
116
117 int sd_rtnl_message_route_set_src_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
118 struct rtmsg *rtm;
119
120 assert_return(m, -EINVAL);
121 assert_return(m->hdr, -EINVAL);
122 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
123
124 rtm = NLMSG_DATA(m->hdr);
125
126 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
127 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
128 return -ERANGE;
129
130 rtm->rtm_src_len = prefixlen;
131
132 return 0;
133 }
134
135 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
136 struct rtmsg *rtm;
137
138 assert_return(m, -EINVAL);
139 assert_return(m->hdr, -EINVAL);
140 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
141
142 rtm = NLMSG_DATA(m->hdr);
143
144 rtm->rtm_scope = scope;
145
146 return 0;
147 }
148
149 int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) {
150 struct rtmsg *rtm;
151
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);
156
157 rtm = NLMSG_DATA(m->hdr);
158
159 *family = rtm->rtm_family;
160
161 return 0;
162 }
163
164 int sd_rtnl_message_route_get_dst_prefixlen(sd_rtnl_message *m, unsigned char *dst_len) {
165 struct rtmsg *rtm;
166
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);
171
172 rtm = NLMSG_DATA(m->hdr);
173
174 *dst_len = rtm->rtm_dst_len;
175
176 return 0;
177 }
178
179 int sd_rtnl_message_route_get_src_prefixlen(sd_rtnl_message *m, unsigned char *src_len) {
180 struct rtmsg *rtm;
181
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);
186
187 rtm = NLMSG_DATA(m->hdr);
188
189 *src_len = rtm->rtm_src_len;
190
191 return 0;
192 }
193
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) {
197 struct rtmsg *rtm;
198 int r;
199
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);
204
205 r = message_new(rtnl, ret, nlmsg_type);
206 if (r < 0)
207 return r;
208
209 if (nlmsg_type == RTM_NEWROUTE)
210 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
211
212 rtm = NLMSG_DATA((*ret)->hdr);
213
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;
219
220 return 0;
221 }
222
223 int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
224 struct ndmsg *ndm;
225
226 assert_return(m, -EINVAL);
227 assert_return(m->hdr, -EINVAL);
228 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
229 assert_return(family, -EINVAL);
230
231 ndm = NLMSG_DATA(m->hdr);
232
233 *family = ndm->ndm_family;
234
235 return 0;
236 }
237
238 int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
239 struct ndmsg *ndm;
240
241 assert_return(m, -EINVAL);
242 assert_return(m->hdr, -EINVAL);
243 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
244 assert_return(index, -EINVAL);
245
246 ndm = NLMSG_DATA(m->hdr);
247
248 *index = ndm->ndm_ifindex;
249
250 return 0;
251 }
252
253 int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
254 struct ndmsg *ndm;
255 int r;
256
257 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
258 assert_return(ndm_family == AF_INET || ndm_family == AF_INET6, -EINVAL);
259 assert_return(ret, -EINVAL);
260
261 r = message_new(rtnl, ret, nlmsg_type);
262 if (r < 0)
263 return r;
264
265 if (nlmsg_type == RTM_NEWNEIGH)
266 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
267
268 ndm = NLMSG_DATA((*ret)->hdr);
269
270 ndm->ndm_family = ndm_family;
271 ndm->ndm_ifindex = index;
272
273 return 0;
274 }
275
276 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
277 struct ifinfomsg *ifi;
278
279 assert_return(m, -EINVAL);
280 assert_return(m->hdr, -EINVAL);
281 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
282 assert_return(change, -EINVAL);
283
284 ifi = NLMSG_DATA(m->hdr);
285
286 ifi->ifi_flags = flags;
287 ifi->ifi_change = change;
288
289 return 0;
290 }
291
292 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
293 struct ifinfomsg *ifi;
294
295 assert_return(m, -EINVAL);
296 assert_return(m->hdr, -EINVAL);
297 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
298
299 ifi = NLMSG_DATA(m->hdr);
300
301 ifi->ifi_type = type;
302
303 return 0;
304 }
305
306 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
307 struct ifinfomsg *ifi;
308
309 assert_return(m, -EINVAL);
310 assert_return(m->hdr, -EINVAL);
311 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
312
313 ifi = NLMSG_DATA(m->hdr);
314
315 ifi->ifi_family = family;
316
317 return 0;
318 }
319
320 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
321 uint16_t nlmsg_type, int index) {
322 struct ifinfomsg *ifi;
323 int r;
324
325 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
326 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
327 assert_return(ret, -EINVAL);
328
329 r = message_new(rtnl, ret, nlmsg_type);
330 if (r < 0)
331 return r;
332
333 if (nlmsg_type == RTM_NEWLINK)
334 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
335
336 ifi = NLMSG_DATA((*ret)->hdr);
337
338 ifi->ifi_family = AF_UNSPEC;
339 ifi->ifi_index = index;
340
341 return 0;
342 }
343
344 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
345 assert_return(m, -EINVAL);
346 assert_return(m->hdr, -EINVAL);
347 assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
348 m->hdr->nlmsg_type == RTM_GETADDR ||
349 m->hdr->nlmsg_type == RTM_GETROUTE ||
350 m->hdr->nlmsg_type == RTM_GETNEIGH,
351 -EINVAL);
352
353 if (dump)
354 m->hdr->nlmsg_flags |= NLM_F_DUMP;
355 else
356 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
357
358 return 0;
359 }
360
361 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
362 struct ifaddrmsg *ifa;
363
364 assert_return(m, -EINVAL);
365 assert_return(m->hdr, -EINVAL);
366 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
367
368 ifa = NLMSG_DATA(m->hdr);
369
370 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
371 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
372 return -ERANGE;
373
374 ifa->ifa_prefixlen = prefixlen;
375
376 return 0;
377 }
378
379 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
380 struct ifaddrmsg *ifa;
381
382 assert_return(m, -EINVAL);
383 assert_return(m->hdr, -EINVAL);
384 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
385
386 ifa = NLMSG_DATA(m->hdr);
387
388 ifa->ifa_flags = flags;
389
390 return 0;
391 }
392
393 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
394 struct ifaddrmsg *ifa;
395
396 assert_return(m, -EINVAL);
397 assert_return(m->hdr, -EINVAL);
398 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
399
400 ifa = NLMSG_DATA(m->hdr);
401
402 ifa->ifa_scope = scope;
403
404 return 0;
405 }
406
407 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
408 struct ifaddrmsg *ifa;
409
410 assert_return(m, -EINVAL);
411 assert_return(m->hdr, -EINVAL);
412 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
413 assert_return(family, -EINVAL);
414
415 ifa = NLMSG_DATA(m->hdr);
416
417 *family = ifa->ifa_family;
418
419 return 0;
420 }
421
422 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
423 struct ifaddrmsg *ifa;
424
425 assert_return(m, -EINVAL);
426 assert_return(m->hdr, -EINVAL);
427 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
428 assert_return(prefixlen, -EINVAL);
429
430 ifa = NLMSG_DATA(m->hdr);
431
432 *prefixlen = ifa->ifa_prefixlen;
433
434 return 0;
435 }
436
437 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
438 struct ifaddrmsg *ifa;
439
440 assert_return(m, -EINVAL);
441 assert_return(m->hdr, -EINVAL);
442 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
443 assert_return(scope, -EINVAL);
444
445 ifa = NLMSG_DATA(m->hdr);
446
447 *scope = ifa->ifa_scope;
448
449 return 0;
450 }
451
452 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
453 struct ifaddrmsg *ifa;
454
455 assert_return(m, -EINVAL);
456 assert_return(m->hdr, -EINVAL);
457 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
458 assert_return(flags, -EINVAL);
459
460 ifa = NLMSG_DATA(m->hdr);
461
462 *flags = ifa->ifa_flags;
463
464 return 0;
465 }
466
467 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
468 struct ifaddrmsg *ifa;
469
470 assert_return(m, -EINVAL);
471 assert_return(m->hdr, -EINVAL);
472 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
473 assert_return(ifindex, -EINVAL);
474
475 ifa = NLMSG_DATA(m->hdr);
476
477 *ifindex = ifa->ifa_index;
478
479 return 0;
480 }
481
482 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
483 uint16_t nlmsg_type, int index,
484 int family) {
485 struct ifaddrmsg *ifa;
486 int r;
487
488 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
489 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
490 index > 0, -EINVAL);
491 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
492 family == AF_INET || family == AF_INET6, -EINVAL);
493 assert_return(ret, -EINVAL);
494
495 r = message_new(rtnl, ret, nlmsg_type);
496 if (r < 0)
497 return r;
498
499 if (nlmsg_type == RTM_GETADDR)
500 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
501
502 ifa = NLMSG_DATA((*ret)->hdr);
503
504 ifa->ifa_index = index;
505 ifa->ifa_family = family;
506 if (family == AF_INET)
507 ifa->ifa_prefixlen = 32;
508 else if (family == AF_INET6)
509 ifa->ifa_prefixlen = 128;
510
511 return 0;
512 }
513
514 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
515 int index, int family) {
516 int r;
517
518 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
519 if (r < 0)
520 return r;
521
522 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
523
524 return 0;
525 }
526
527 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
528 if (m)
529 assert_se(REFCNT_INC(m->n_ref) >= 2);
530
531 return m;
532 }
533
534 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
535 if (m && REFCNT_DEC(m->n_ref) <= 0) {
536 unsigned i;
537
538 free(m->hdr);
539
540 for (i = 0; i <= m->n_containers; i++)
541 free(m->rta_offset_tb[i]);
542
543 sd_rtnl_message_unref(m->next);
544
545 free(m);
546 }
547
548 return NULL;
549 }
550
551 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
552 assert_return(m, -EINVAL);
553 assert_return(type, -EINVAL);
554
555 *type = m->hdr->nlmsg_type;
556
557 return 0;
558 }
559
560 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
561 assert_return(m, -EINVAL);
562
563 return !m->hdr->nlmsg_pid;
564 }
565
566 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
567 struct ifinfomsg *ifi;
568
569 assert_return(m, -EINVAL);
570 assert_return(m->hdr, -EINVAL);
571 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
572 assert_return(ifindex, -EINVAL);
573
574 ifi = NLMSG_DATA(m->hdr);
575
576 *ifindex = ifi->ifi_index;
577
578 return 0;
579 }
580
581 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
582 struct ifinfomsg *ifi;
583
584 assert_return(m, -EINVAL);
585 assert_return(m->hdr, -EINVAL);
586 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
587 assert_return(flags, -EINVAL);
588
589 ifi = NLMSG_DATA(m->hdr);
590
591 *flags = ifi->ifi_flags;
592
593 return 0;
594 }
595
596 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
597 struct ifinfomsg *ifi;
598
599 assert_return(m, -EINVAL);
600 assert_return(m->hdr, -EINVAL);
601 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
602 assert_return(type, -EINVAL);
603
604 ifi = NLMSG_DATA(m->hdr);
605
606 *type = ifi->ifi_type;
607
608 return 0;
609 }
610
611 /* If successful the updated message will be correctly aligned, if
612 unsuccessful the old message is untouched. */
613 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
614 uint32_t rta_length;
615 size_t message_length, padding_length;
616 struct nlmsghdr *new_hdr;
617 struct rtattr *rta;
618 char *padding;
619 unsigned i;
620 int offset;
621
622 assert(m);
623 assert(m->hdr);
624 assert(!m->sealed);
625 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
626 assert(!data || data_length);
627
628 /* get offset of the new attribute */
629 offset = m->hdr->nlmsg_len;
630
631 /* get the size of the new rta attribute (with padding at the end) */
632 rta_length = RTA_LENGTH(data_length);
633
634 /* get the new message size (with padding at the end) */
635 message_length = offset + RTA_ALIGN(rta_length);
636
637 /* realloc to fit the new attribute */
638 new_hdr = realloc(m->hdr, message_length);
639 if (!new_hdr)
640 return -ENOMEM;
641 m->hdr = new_hdr;
642
643 /* get pointer to the attribute we are about to add */
644 rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
645
646 /* if we are inside containers, extend them */
647 for (i = 0; i < m->n_containers; i++)
648 GET_CONTAINER(m, i)->rta_len += message_length - offset;
649
650 /* fill in the attribute */
651 rta->rta_type = type;
652 rta->rta_len = rta_length;
653 if (data)
654 /* we don't deal with the case where the user lies about the type
655 * and gives us too little data (so don't do that)
656 */
657 padding = mempcpy(RTA_DATA(rta), data, data_length);
658 else {
659 /* if no data was passed, make sure we still initialize the padding
660 note that we can have data_length > 0 (used by some containers) */
661 padding = RTA_DATA(rta);
662 }
663
664 /* make sure also the padding at the end of the message is initialized */
665 padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
666 memzero(padding, padding_length);
667
668 /* update message size */
669 m->hdr->nlmsg_len = message_length;
670
671 return offset;
672 }
673
674 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
675 const NLType *type;
676 int r;
677
678 r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
679 if (r < 0)
680 return r;
681
682 if (type->type != data_type)
683 return -EINVAL;
684
685 return type->size;
686 }
687
688 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
689 size_t length, size;
690 int r;
691
692 assert_return(m, -EINVAL);
693 assert_return(!m->sealed, -EPERM);
694 assert_return(data, -EINVAL);
695
696 r = message_attribute_has_type(m, type, NLA_STRING);
697 if (r < 0)
698 return r;
699 else
700 size = (size_t)r;
701
702 if (size) {
703 length = strnlen(data, size);
704 if (length >= size)
705 return -EINVAL;
706 } else
707 length = strlen(data);
708
709 r = add_rtattr(m, type, data, length + 1);
710 if (r < 0)
711 return r;
712
713 return 0;
714 }
715
716 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
717 int r;
718
719 assert_return(m, -EINVAL);
720 assert_return(!m->sealed, -EPERM);
721
722 r = message_attribute_has_type(m, type, NLA_U8);
723 if (r < 0)
724 return r;
725
726 r = add_rtattr(m, type, &data, sizeof(uint8_t));
727 if (r < 0)
728 return r;
729
730 return 0;
731 }
732
733
734 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
735 int r;
736
737 assert_return(m, -EINVAL);
738 assert_return(!m->sealed, -EPERM);
739
740 r = message_attribute_has_type(m, type, NLA_U16);
741 if (r < 0)
742 return r;
743
744 r = add_rtattr(m, type, &data, sizeof(uint16_t));
745 if (r < 0)
746 return r;
747
748 return 0;
749 }
750
751 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
752 int r;
753
754 assert_return(m, -EINVAL);
755 assert_return(!m->sealed, -EPERM);
756
757 r = message_attribute_has_type(m, type, NLA_U32);
758 if (r < 0)
759 return r;
760
761 r = add_rtattr(m, type, &data, sizeof(uint32_t));
762 if (r < 0)
763 return r;
764
765 return 0;
766 }
767
768 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
769 int r;
770
771 assert_return(m, -EINVAL);
772 assert_return(!m->sealed, -EPERM);
773 assert_return(data, -EINVAL);
774
775 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
776 if (r < 0)
777 return r;
778
779 r = add_rtattr(m, type, data, sizeof(struct in_addr));
780 if (r < 0)
781 return r;
782
783 return 0;
784 }
785
786 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
787 int r;
788
789 assert_return(m, -EINVAL);
790 assert_return(!m->sealed, -EPERM);
791 assert_return(data, -EINVAL);
792
793 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
794 if (r < 0)
795 return r;
796
797 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
798 if (r < 0)
799 return r;
800
801 return 0;
802 }
803
804 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
805 int r;
806
807 assert_return(m, -EINVAL);
808 assert_return(!m->sealed, -EPERM);
809 assert_return(data, -EINVAL);
810
811 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
812 if (r < 0)
813 return r;
814
815 r = add_rtattr(m, type, data, ETH_ALEN);
816 if (r < 0)
817 return r;
818
819 return 0;
820 }
821
822 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
823 int r;
824
825 assert_return(m, -EINVAL);
826 assert_return(!m->sealed, -EPERM);
827 assert_return(info, -EINVAL);
828
829 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
830 if (r < 0)
831 return r;
832
833 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
834 if (r < 0)
835 return r;
836
837 return 0;
838 }
839
840 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
841 size_t size;
842 int r;
843
844 assert_return(m, -EINVAL);
845 assert_return(!m->sealed, -EPERM);
846 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
847
848 r = message_attribute_has_type(m, type, NLA_NESTED);
849 if (r < 0)
850 return r;
851 else
852 size = (size_t)r;
853
854 r = type_system_get_type_system(m->container_type_system[m->n_containers],
855 &m->container_type_system[m->n_containers + 1],
856 type);
857 if (r < 0)
858 return r;
859
860 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
861 if (r < 0)
862 return r;
863
864 m->container_offsets[m->n_containers ++] = r;
865
866 return 0;
867 }
868
869 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
870 const NLTypeSystemUnion *type_system_union;
871 int r;
872
873 assert_return(m, -EINVAL);
874 assert_return(!m->sealed, -EPERM);
875
876 r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
877 if (r < 0)
878 return r;
879
880 r = type_system_union_get_type_system(type_system_union,
881 &m->container_type_system[m->n_containers + 1],
882 key);
883 if (r < 0)
884 return r;
885
886 r = sd_rtnl_message_append_string(m, type_system_union->match, key);
887 if (r < 0)
888 return r;
889
890 /* do we evere need non-null size */
891 r = add_rtattr(m, type, NULL, 0);
892 if (r < 0)
893 return r;
894
895 m->container_offsets[m->n_containers ++] = r;
896
897 return 0;
898 }
899
900
901 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
902 assert_return(m, -EINVAL);
903 assert_return(!m->sealed, -EPERM);
904 assert_return(m->n_containers > 0, -EINVAL);
905
906 m->container_type_system[m->n_containers] = NULL;
907 m->n_containers --;
908
909 return 0;
910 }
911
912 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
913 struct rtattr *rta;
914
915 assert_return(m, -EINVAL);
916 assert_return(m->sealed, -EPERM);
917 assert_return(data, -EINVAL);
918 assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
919 assert(m->rta_offset_tb[m->n_containers]);
920 assert(type < m->rta_tb_size[m->n_containers]);
921
922 if(!m->rta_offset_tb[m->n_containers][type])
923 return -ENODATA;
924
925 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
926
927 *data = RTA_DATA(rta);
928
929 return RTA_PAYLOAD(rta);
930 }
931
932 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
933 int r;
934 void *attr_data;
935
936 assert_return(m, -EINVAL);
937
938 r = message_attribute_has_type(m, type, NLA_STRING);
939 if (r < 0)
940 return r;
941
942 r = rtnl_message_read_internal(m, type, &attr_data);
943 if (r < 0)
944 return r;
945 else if (strnlen(attr_data, r) >= (size_t) r)
946 return -EIO;
947
948 if (data)
949 *data = (const char *) attr_data;
950
951 return 0;
952 }
953
954 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
955 int r;
956 void *attr_data;
957
958 assert_return(m, -EINVAL);
959
960 r = message_attribute_has_type(m, type, NLA_U8);
961 if (r < 0)
962 return r;
963
964 r = rtnl_message_read_internal(m, type, &attr_data);
965 if (r < 0)
966 return r;
967 else if ((size_t) r < sizeof(uint8_t))
968 return -EIO;
969
970 if (data)
971 *data = *(uint8_t *) attr_data;
972
973 return 0;
974 }
975
976 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
977 int r;
978 void *attr_data;
979
980 assert_return(m, -EINVAL);
981
982 r = message_attribute_has_type(m, type, NLA_U16);
983 if (r < 0)
984 return r;
985
986 r = rtnl_message_read_internal(m, type, &attr_data);
987 if (r < 0)
988 return r;
989 else if ((size_t) r < sizeof(uint16_t))
990 return -EIO;
991
992 if (data)
993 *data = *(uint16_t *) attr_data;
994
995 return 0;
996 }
997
998 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
999 int r;
1000 void *attr_data;
1001
1002 assert_return(m, -EINVAL);
1003
1004 r = message_attribute_has_type(m, type, NLA_U32);
1005 if (r < 0)
1006 return r;
1007
1008 r = rtnl_message_read_internal(m, type, &attr_data);
1009 if (r < 0)
1010 return r;
1011 else if ((size_t)r < sizeof(uint32_t))
1012 return -EIO;
1013
1014 if (data)
1015 *data = *(uint32_t *) attr_data;
1016
1017 return 0;
1018 }
1019
1020 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
1021 int r;
1022 void *attr_data;
1023
1024 assert_return(m, -EINVAL);
1025
1026 r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
1027 if (r < 0)
1028 return r;
1029
1030 r = rtnl_message_read_internal(m, type, &attr_data);
1031 if (r < 0)
1032 return r;
1033 else if ((size_t)r < sizeof(struct ether_addr))
1034 return -EIO;
1035
1036 if (data)
1037 memcpy(data, attr_data, sizeof(struct ether_addr));
1038
1039 return 0;
1040 }
1041
1042 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
1043 int r;
1044 void *attr_data;
1045
1046 assert_return(m, -EINVAL);
1047
1048 r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
1049 if (r < 0)
1050 return r;
1051
1052 r = rtnl_message_read_internal(m, type, &attr_data);
1053 if (r < 0)
1054 return r;
1055 else if ((size_t)r < sizeof(struct ifa_cacheinfo))
1056 return -EIO;
1057
1058 if (info)
1059 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
1060
1061 return 0;
1062 }
1063
1064 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
1065 int r;
1066 void *attr_data;
1067
1068 assert_return(m, -EINVAL);
1069
1070 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1071 if (r < 0)
1072 return r;
1073
1074 r = rtnl_message_read_internal(m, type, &attr_data);
1075 if (r < 0)
1076 return r;
1077 else if ((size_t)r < sizeof(struct in_addr))
1078 return -EIO;
1079
1080 if (data)
1081 memcpy(data, attr_data, sizeof(struct in_addr));
1082
1083 return 0;
1084 }
1085
1086 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
1087 int r;
1088 void *attr_data;
1089
1090 assert_return(m, -EINVAL);
1091
1092 r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1093 if (r < 0)
1094 return r;
1095
1096 r = rtnl_message_read_internal(m, type, &attr_data);
1097 if (r < 0)
1098 return r;
1099 else if ((size_t)r < sizeof(struct in6_addr))
1100 return -EIO;
1101
1102 if (data)
1103 memcpy(data, attr_data, sizeof(struct in6_addr));
1104
1105 return 0;
1106 }
1107
1108 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
1109 const NLType *nl_type;
1110 const NLTypeSystem *type_system;
1111 void *container;
1112 size_t size;
1113 int r;
1114
1115 assert_return(m, -EINVAL);
1116 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1117
1118 r = type_system_get_type(m->container_type_system[m->n_containers],
1119 &nl_type,
1120 type);
1121 if (r < 0)
1122 return r;
1123
1124 if (nl_type->type == NLA_NESTED) {
1125 r = type_system_get_type_system(m->container_type_system[m->n_containers],
1126 &type_system,
1127 type);
1128 if (r < 0)
1129 return r;
1130 } else if (nl_type->type == NLA_UNION) {
1131 const NLTypeSystemUnion *type_system_union;
1132 const char *key;
1133
1134 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1135 &type_system_union,
1136 type);
1137 if (r < 0)
1138 return r;
1139
1140 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1141 if (r < 0)
1142 return r;
1143
1144 r = type_system_union_get_type_system(type_system_union,
1145 &type_system,
1146 key);
1147 if (r < 0)
1148 return r;
1149 } else
1150 return -EINVAL;
1151
1152 r = rtnl_message_read_internal(m, type, &container);
1153 if (r < 0)
1154 return r;
1155 else
1156 size = (size_t)r;
1157
1158 m->n_containers ++;
1159
1160 r = rtnl_message_parse(m,
1161 &m->rta_offset_tb[m->n_containers],
1162 &m->rta_tb_size[m->n_containers],
1163 type_system->max,
1164 container,
1165 size);
1166 if (r < 0) {
1167 m->n_containers --;
1168 return r;
1169 }
1170
1171 m->container_type_system[m->n_containers] = type_system;
1172
1173 return 0;
1174 }
1175
1176 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1177 assert_return(m, -EINVAL);
1178 assert_return(m->sealed, -EINVAL);
1179 assert_return(m->n_containers > 0, -EINVAL);
1180
1181 free(m->rta_offset_tb[m->n_containers]);
1182 m->rta_offset_tb[m->n_containers] = NULL;
1183 m->container_type_system[m->n_containers] = NULL;
1184
1185 m->n_containers --;
1186
1187 return 0;
1188 }
1189
1190 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1191 assert(m);
1192 assert(m->hdr);
1193
1194 return m->hdr->nlmsg_seq;
1195 }
1196
1197 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1198 struct nlmsgerr *err;
1199
1200 assert_return(m, -EINVAL);
1201 assert_return(m->hdr, -EINVAL);
1202
1203 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1204 return 0;
1205
1206 err = NLMSG_DATA(m->hdr);
1207
1208 return err->error;
1209 }
1210
1211 int rtnl_message_parse(sd_rtnl_message *m,
1212 size_t **rta_offset_tb,
1213 unsigned short *rta_tb_size,
1214 int max,
1215 struct rtattr *rta,
1216 unsigned int rt_len) {
1217 unsigned short type;
1218 size_t *tb;
1219
1220 tb = new0(size_t, max + 1);
1221 if(!tb)
1222 return -ENOMEM;
1223
1224 *rta_tb_size = max + 1;
1225
1226 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1227 type = RTA_TYPE(rta);
1228
1229 /* if the kernel is newer than the headers we used
1230 when building, we ignore out-of-range attributes
1231 */
1232 if (type > max)
1233 continue;
1234
1235 if (tb[type])
1236 log_debug("rtnl: message parse - overwriting repeated attribute");
1237
1238 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1239 }
1240
1241 *rta_offset_tb = tb;
1242
1243 return 0;
1244 }
1245
1246 /* returns the number of bytes sent, or a negative error code */
1247 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1248 union {
1249 struct sockaddr sa;
1250 struct sockaddr_nl nl;
1251 } addr = {
1252 .nl.nl_family = AF_NETLINK,
1253 };
1254 ssize_t k;
1255
1256 assert(nl);
1257 assert(m);
1258 assert(m->hdr);
1259
1260 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1261 0, &addr.sa, sizeof(addr));
1262 if (k < 0)
1263 return (errno == EAGAIN) ? 0 : -errno;
1264
1265 return k;
1266 }
1267
1268 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1269 uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1270 CMSG_SPACE(sizeof(struct nl_pktinfo))];
1271 struct msghdr msg = {
1272 .msg_iov = iov,
1273 .msg_iovlen = 1,
1274 .msg_control = cred_buffer,
1275 .msg_controllen = sizeof(cred_buffer),
1276 };
1277 struct cmsghdr *cmsg;
1278 uint32_t group = 0;
1279 bool auth = false;
1280 int r;
1281
1282 assert(fd >= 0);
1283 assert(iov);
1284
1285 r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1286 if (r < 0) {
1287 /* no data */
1288 if (errno == ENOBUFS)
1289 log_debug("rtnl: kernel receive buffer overrun");
1290
1291 return (errno == EAGAIN) ? 0 : -errno;
1292 } else if (r == 0)
1293 /* connection was closed by the kernel */
1294 return -ECONNRESET;
1295
1296 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1297 if (cmsg->cmsg_level == SOL_SOCKET &&
1298 cmsg->cmsg_type == SCM_CREDENTIALS &&
1299 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1300 struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1301
1302 /* from the kernel */
1303 if (ucred->uid == 0 && ucred->pid == 0)
1304 auth = true;
1305 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1306 cmsg->cmsg_type == NETLINK_PKTINFO &&
1307 cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1308 struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1309
1310 /* multi-cast group */
1311 group = pktinfo->group;
1312 }
1313 }
1314
1315 if (!auth)
1316 /* not from the kernel, ignore */
1317 return 0;
1318
1319 if (group)
1320 *_group = group;
1321
1322 return r;
1323 }
1324
1325 /* On success, the number of bytes received is returned and *ret points to the received message
1326 * which has a valid header and the correct size.
1327 * If nothing useful was received 0 is returned.
1328 * On failure, a negative error code is returned.
1329 */
1330 int socket_read_message(sd_rtnl *rtnl) {
1331 _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1332 struct iovec iov = {};
1333 uint32_t group = 0;
1334 bool multi_part = false, done = false;
1335 struct nlmsghdr *new_msg;
1336 size_t len;
1337 int r;
1338 unsigned i = 0;
1339
1340 assert(rtnl);
1341 assert(rtnl->rbuffer);
1342 assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1343
1344 /* read nothing, just get the pending message size */
1345 r = socket_recv_message(rtnl->fd, &iov, &group, true);
1346 if (r <= 0)
1347 return r;
1348 else
1349 len = (size_t)r;
1350
1351 /* make room for the pending message */
1352 if (!greedy_realloc((void **)&rtnl->rbuffer,
1353 &rtnl->rbuffer_allocated,
1354 len, sizeof(uint8_t)))
1355 return -ENOMEM;
1356
1357 iov.iov_base = rtnl->rbuffer;
1358 iov.iov_len = rtnl->rbuffer_allocated;
1359
1360 /* read the pending message */
1361 r = socket_recv_message(rtnl->fd, &iov, &group, false);
1362 if (r <= 0)
1363 return r;
1364 else
1365 len = (size_t)r;
1366
1367 if (len > rtnl->rbuffer_allocated)
1368 /* message did not fit in read buffer */
1369 return -EIO;
1370
1371 if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1372 multi_part = true;
1373
1374 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1375 if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1376 rtnl->rbuffer->nlmsg_seq) {
1377 first = rtnl->rqueue_partial[i];
1378 break;
1379 }
1380 }
1381 }
1382
1383 for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
1384 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1385 const NLType *nl_type;
1386
1387 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1388 /* not broadcast and not for us */
1389 continue;
1390
1391 if (new_msg->nlmsg_type == NLMSG_NOOP)
1392 /* silently drop noop messages */
1393 continue;
1394
1395 if (new_msg->nlmsg_type == NLMSG_DONE) {
1396 /* finished reading multi-part message */
1397 done = true;
1398
1399 continue;
1400 }
1401
1402 /* check that we support this message type */
1403 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1404 if (r < 0) {
1405 if (r == -ENOTSUP)
1406 log_debug("sd-rtnl: ignored message with unknown type: %u",
1407 new_msg->nlmsg_type);
1408
1409 continue;
1410 }
1411
1412 /* check that the size matches the message type */
1413 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
1414 log_debug("sd-rtnl: message larger than expected, dropping");
1415 continue;
1416 }
1417
1418 r = message_new_empty(rtnl, &m);
1419 if (r < 0)
1420 return r;
1421
1422 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1423 if (!m->hdr)
1424 return -ENOMEM;
1425
1426 /* seal and parse the top-level message */
1427 r = sd_rtnl_message_rewind(m);
1428 if (r < 0)
1429 return r;
1430
1431 /* push the message onto the multi-part message stack */
1432 if (first)
1433 m->next = first;
1434 first = m;
1435 m = NULL;
1436 }
1437
1438 if (len)
1439 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1440
1441 if (!first)
1442 return 0;
1443
1444 if (!multi_part || done) {
1445 /* we got a complete message, push it on the read queue */
1446 r = rtnl_rqueue_make_room(rtnl);
1447 if (r < 0)
1448 return r;
1449
1450 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1451 first = NULL;
1452
1453 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1454 /* remove the message form the partial read queue */
1455 memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1456 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1457 rtnl->rqueue_partial_size --;
1458 }
1459
1460 return 1;
1461 } else {
1462 /* we only got a partial multi-part message, push it on the
1463 partial read queue */
1464 if (i < rtnl->rqueue_partial_size) {
1465 rtnl->rqueue_partial[i] = first;
1466 } else {
1467 r = rtnl_rqueue_partial_make_room(rtnl);
1468 if (r < 0)
1469 return r;
1470
1471 rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1472 }
1473 first = NULL;
1474
1475 return 0;
1476 }
1477 }
1478
1479 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1480 const NLType *type;
1481 unsigned i;
1482 int r;
1483
1484 assert_return(m, -EINVAL);
1485
1486 /* don't allow appending to message once parsed */
1487 if (!m->sealed)
1488 rtnl_message_seal(m);
1489
1490 for (i = 1; i <= m->n_containers; i++) {
1491 free(m->rta_offset_tb[i]);
1492 m->rta_offset_tb[i] = NULL;
1493 m->rta_tb_size[i] = 0;
1494 m->container_type_system[i] = NULL;
1495 }
1496
1497 m->n_containers = 0;
1498
1499 if (m->rta_offset_tb[0]) {
1500 /* top-level attributes have already been parsed */
1501 return 0;
1502 }
1503
1504 assert(m->hdr);
1505
1506 r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1507 if (r < 0)
1508 return r;
1509
1510 if (type->type == NLA_NESTED) {
1511 const NLTypeSystem *type_system = type->type_system;
1512
1513 assert(type_system);
1514
1515 m->container_type_system[0] = type_system;
1516
1517 r = rtnl_message_parse(m,
1518 &m->rta_offset_tb[m->n_containers],
1519 &m->rta_tb_size[m->n_containers],
1520 type_system->max,
1521 (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1522 NLMSG_ALIGN(type->size)),
1523 NLMSG_PAYLOAD(m->hdr, type->size));
1524 if (r < 0)
1525 return r;
1526 }
1527
1528 return 0;
1529 }
1530
1531 void rtnl_message_seal(sd_rtnl_message *m) {
1532 assert(m);
1533 assert(!m->sealed);
1534
1535 m->sealed = true;
1536 }
1537
1538 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1539 assert_return(m, NULL);
1540
1541 return m->next;
1542 }