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