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