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