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