]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-netlink/sd-netlink.c
log: minimize includes in log.h
[thirdparty/systemd.git] / src / libsystemd / sd-netlink / sd-netlink.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2013 Tom Gundersen <teg@jklm.no>
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <poll.h>
22 #include <sys/socket.h>
23
24 #include "sd-netlink.h"
25
26 #include "alloc-util.h"
27 #include "fd-util.h"
28 #include "hashmap.h"
29 #include "macro.h"
30 #include "missing.h"
31 #include "netlink-internal.h"
32 #include "netlink-util.h"
33 #include "process-util.h"
34 #include "socket-util.h"
35 #include "util.h"
36
37 static int sd_netlink_new(sd_netlink **ret) {
38 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
39
40 assert_return(ret, -EINVAL);
41
42 rtnl = new0(sd_netlink, 1);
43 if (!rtnl)
44 return -ENOMEM;
45
46 rtnl->n_ref = REFCNT_INIT;
47 rtnl->fd = -1;
48 rtnl->sockaddr.nl.nl_family = AF_NETLINK;
49 rtnl->original_pid = getpid_cached();
50 rtnl->protocol = -1;
51
52 LIST_HEAD_INIT(rtnl->match_callbacks);
53
54 /* We guarantee that the read buffer has at least space for
55 * a message header */
56 if (!greedy_realloc((void**)&rtnl->rbuffer, &rtnl->rbuffer_allocated,
57 sizeof(struct nlmsghdr), sizeof(uint8_t)))
58 return -ENOMEM;
59
60 /* Change notification responses have sequence 0, so we must
61 * start our request sequence numbers at 1, or we may confuse our
62 * responses with notifications from the kernel */
63 rtnl->serial = 1;
64
65 *ret = rtnl;
66 rtnl = NULL;
67
68 return 0;
69 }
70
71 int sd_netlink_new_from_netlink(sd_netlink **ret, int fd) {
72 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
73 socklen_t addrlen;
74 int r;
75
76 assert_return(ret, -EINVAL);
77
78 r = sd_netlink_new(&rtnl);
79 if (r < 0)
80 return r;
81
82 addrlen = sizeof(rtnl->sockaddr);
83
84 r = getsockname(fd, &rtnl->sockaddr.sa, &addrlen);
85 if (r < 0)
86 return -errno;
87
88 if (rtnl->sockaddr.nl.nl_family != AF_NETLINK)
89 return -EINVAL;
90
91 rtnl->fd = fd;
92
93 *ret = rtnl;
94 rtnl = NULL;
95
96 return 0;
97 }
98
99 static bool rtnl_pid_changed(sd_netlink *rtnl) {
100 assert(rtnl);
101
102 /* We don't support people creating an rtnl connection and
103 * keeping it around over a fork(). Let's complain. */
104
105 return rtnl->original_pid != getpid_cached();
106 }
107
108 int sd_netlink_open_fd(sd_netlink **ret, int fd) {
109 _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
110 int r;
111 int protocol;
112 socklen_t l;
113
114 assert_return(ret, -EINVAL);
115 assert_return(fd >= 0, -EBADF);
116
117 r = sd_netlink_new(&rtnl);
118 if (r < 0)
119 return r;
120
121 l = sizeof(protocol);
122 r = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &l);
123 if (r < 0)
124 return r;
125
126 rtnl->fd = fd;
127 rtnl->protocol = protocol;
128
129 r = socket_bind(rtnl);
130 if (r < 0) {
131 rtnl->fd = -1; /* on failure, the caller remains owner of the fd, hence don't close it here */
132 rtnl->protocol = -1;
133 return r;
134 }
135
136 *ret = rtnl;
137 rtnl = NULL;
138
139 return 0;
140 }
141
142 int netlink_open_family(sd_netlink **ret, int family) {
143 _cleanup_close_ int fd = -1;
144 int r;
145
146 fd = socket_open(family);
147 if (fd < 0)
148 return fd;
149
150 r = sd_netlink_open_fd(ret, fd);
151 if (r < 0)
152 return r;
153
154 fd = -1;
155
156 return 0;
157 }
158
159 int sd_netlink_open(sd_netlink **ret) {
160 return netlink_open_family(ret, NETLINK_ROUTE);
161 }
162
163 int sd_netlink_inc_rcvbuf(sd_netlink *rtnl, size_t size) {
164 assert_return(rtnl, -EINVAL);
165 assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
166
167 return fd_inc_rcvbuf(rtnl->fd, size);
168 }
169
170 sd_netlink *sd_netlink_ref(sd_netlink *rtnl) {
171 assert_return(rtnl, NULL);
172 assert_return(!rtnl_pid_changed(rtnl), NULL);
173
174 if (rtnl)
175 assert_se(REFCNT_INC(rtnl->n_ref) >= 2);
176
177 return rtnl;
178 }
179
180 sd_netlink *sd_netlink_unref(sd_netlink *rtnl) {
181 if (!rtnl)
182 return NULL;
183
184 assert_return(!rtnl_pid_changed(rtnl), NULL);
185
186 if (REFCNT_DEC(rtnl->n_ref) == 0) {
187 struct match_callback *f;
188 unsigned i;
189
190 for (i = 0; i < rtnl->rqueue_size; i++)
191 sd_netlink_message_unref(rtnl->rqueue[i]);
192 free(rtnl->rqueue);
193
194 for (i = 0; i < rtnl->rqueue_partial_size; i++)
195 sd_netlink_message_unref(rtnl->rqueue_partial[i]);
196 free(rtnl->rqueue_partial);
197
198 free(rtnl->rbuffer);
199
200 hashmap_free_free(rtnl->reply_callbacks);
201 prioq_free(rtnl->reply_callbacks_prioq);
202
203 sd_event_source_unref(rtnl->io_event_source);
204 sd_event_source_unref(rtnl->time_event_source);
205 sd_event_unref(rtnl->event);
206
207 while ((f = rtnl->match_callbacks)) {
208 sd_netlink_remove_match(rtnl, f->type, f->callback, f->userdata);
209 }
210
211 hashmap_free(rtnl->broadcast_group_refs);
212
213 safe_close(rtnl->fd);
214 free(rtnl);
215 }
216
217 return NULL;
218 }
219
220 static void rtnl_seal_message(sd_netlink *rtnl, sd_netlink_message *m) {
221 assert(rtnl);
222 assert(!rtnl_pid_changed(rtnl));
223 assert(m);
224 assert(m->hdr);
225
226 /* don't use seq == 0, as that is used for broadcasts, so we
227 would get confused by replies to such messages */
228 m->hdr->nlmsg_seq = rtnl->serial++ ? : rtnl->serial++;
229
230 rtnl_message_seal(m);
231
232 return;
233 }
234
235 int sd_netlink_send(sd_netlink *nl,
236 sd_netlink_message *message,
237 uint32_t *serial) {
238 int r;
239
240 assert_return(nl, -EINVAL);
241 assert_return(!rtnl_pid_changed(nl), -ECHILD);
242 assert_return(message, -EINVAL);
243 assert_return(!message->sealed, -EPERM);
244
245 rtnl_seal_message(nl, message);
246
247 r = socket_write_message(nl, message);
248 if (r < 0)
249 return r;
250
251 if (serial)
252 *serial = rtnl_message_get_serial(message);
253
254 return 1;
255 }
256
257 int rtnl_rqueue_make_room(sd_netlink *rtnl) {
258 assert(rtnl);
259
260 if (rtnl->rqueue_size >= RTNL_RQUEUE_MAX) {
261 log_debug("rtnl: exhausted the read queue size (%d)", RTNL_RQUEUE_MAX);
262 return -ENOBUFS;
263 }
264
265 if (!GREEDY_REALLOC(rtnl->rqueue, rtnl->rqueue_allocated, rtnl->rqueue_size + 1))
266 return -ENOMEM;
267
268 return 0;
269 }
270
271 int rtnl_rqueue_partial_make_room(sd_netlink *rtnl) {
272 assert(rtnl);
273
274 if (rtnl->rqueue_partial_size >= RTNL_RQUEUE_MAX) {
275 log_debug("rtnl: exhausted the partial read queue size (%d)", RTNL_RQUEUE_MAX);
276 return -ENOBUFS;
277 }
278
279 if (!GREEDY_REALLOC(rtnl->rqueue_partial, rtnl->rqueue_partial_allocated,
280 rtnl->rqueue_partial_size + 1))
281 return -ENOMEM;
282
283 return 0;
284 }
285
286 static int dispatch_rqueue(sd_netlink *rtnl, sd_netlink_message **message) {
287 int r;
288
289 assert(rtnl);
290 assert(message);
291
292 if (rtnl->rqueue_size <= 0) {
293 /* Try to read a new message */
294 r = socket_read_message(rtnl);
295 if (r == -ENOBUFS) { /* FIXME: ignore buffer overruns for now */
296 log_debug_errno(r, "Got ENOBUFS from netlink socket, ignoring.");
297 return 1;
298 }
299 if (r <= 0)
300 return r;
301 }
302
303 /* Dispatch a queued message */
304 *message = rtnl->rqueue[0];
305 rtnl->rqueue_size--;
306 memmove(rtnl->rqueue, rtnl->rqueue + 1, sizeof(sd_netlink_message*) * rtnl->rqueue_size);
307
308 return 1;
309 }
310
311 static int process_timeout(sd_netlink *rtnl) {
312 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
313 struct reply_callback *c;
314 usec_t n;
315 int r;
316
317 assert(rtnl);
318
319 c = prioq_peek(rtnl->reply_callbacks_prioq);
320 if (!c)
321 return 0;
322
323 n = now(CLOCK_MONOTONIC);
324 if (c->timeout > n)
325 return 0;
326
327 r = rtnl_message_new_synthetic_error(rtnl, -ETIMEDOUT, c->serial, &m);
328 if (r < 0)
329 return r;
330
331 assert_se(prioq_pop(rtnl->reply_callbacks_prioq) == c);
332 hashmap_remove(rtnl->reply_callbacks, &c->serial);
333
334 r = c->callback(rtnl, m, c->userdata);
335 if (r < 0)
336 log_debug_errno(r, "sd-netlink: timedout callback failed: %m");
337
338 free(c);
339
340 return 1;
341 }
342
343 static int process_reply(sd_netlink *rtnl, sd_netlink_message *m) {
344 _cleanup_free_ struct reply_callback *c = NULL;
345 uint64_t serial;
346 uint16_t type;
347 int r;
348
349 assert(rtnl);
350 assert(m);
351
352 serial = rtnl_message_get_serial(m);
353 c = hashmap_remove(rtnl->reply_callbacks, &serial);
354 if (!c)
355 return 0;
356
357 if (c->timeout != 0)
358 prioq_remove(rtnl->reply_callbacks_prioq, c, &c->prioq_idx);
359
360 r = sd_netlink_message_get_type(m, &type);
361 if (r < 0)
362 return 0;
363
364 if (type == NLMSG_DONE)
365 m = NULL;
366
367 r = c->callback(rtnl, m, c->userdata);
368 if (r < 0)
369 log_debug_errno(r, "sd-netlink: callback failed: %m");
370
371 return 1;
372 }
373
374 static int process_match(sd_netlink *rtnl, sd_netlink_message *m) {
375 struct match_callback *c;
376 uint16_t type;
377 int r;
378
379 assert(rtnl);
380 assert(m);
381
382 r = sd_netlink_message_get_type(m, &type);
383 if (r < 0)
384 return r;
385
386 LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) {
387 if (type == c->type) {
388 r = c->callback(rtnl, m, c->userdata);
389 if (r != 0) {
390 if (r < 0)
391 log_debug_errno(r, "sd-netlink: match callback failed: %m");
392
393 break;
394 }
395 }
396 }
397
398 return 1;
399 }
400
401 static int process_running(sd_netlink *rtnl, sd_netlink_message **ret) {
402 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
403 int r;
404
405 assert(rtnl);
406
407 r = process_timeout(rtnl);
408 if (r != 0)
409 goto null_message;
410
411 r = dispatch_rqueue(rtnl, &m);
412 if (r < 0)
413 return r;
414 if (!m)
415 goto null_message;
416
417 if (sd_netlink_message_is_broadcast(m)) {
418 r = process_match(rtnl, m);
419 if (r != 0)
420 goto null_message;
421 } else {
422 r = process_reply(rtnl, m);
423 if (r != 0)
424 goto null_message;
425 }
426
427 if (ret) {
428 *ret = m;
429 m = NULL;
430
431 return 1;
432 }
433
434 return 1;
435
436 null_message:
437 if (r >= 0 && ret)
438 *ret = NULL;
439
440 return r;
441 }
442
443 int sd_netlink_process(sd_netlink *rtnl, sd_netlink_message **ret) {
444 NETLINK_DONT_DESTROY(rtnl);
445 int r;
446
447 assert_return(rtnl, -EINVAL);
448 assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
449 assert_return(!rtnl->processing, -EBUSY);
450
451 rtnl->processing = true;
452 r = process_running(rtnl, ret);
453 rtnl->processing = false;
454
455 return r;
456 }
457
458 static usec_t calc_elapse(uint64_t usec) {
459 if (usec == (uint64_t) -1)
460 return 0;
461
462 if (usec == 0)
463 usec = RTNL_DEFAULT_TIMEOUT;
464
465 return now(CLOCK_MONOTONIC) + usec;
466 }
467
468 static int rtnl_poll(sd_netlink *rtnl, bool need_more, uint64_t timeout_usec) {
469 struct pollfd p[1] = {};
470 struct timespec ts;
471 usec_t m = USEC_INFINITY;
472 int r, e;
473
474 assert(rtnl);
475
476 e = sd_netlink_get_events(rtnl);
477 if (e < 0)
478 return e;
479
480 if (need_more)
481 /* Caller wants more data, and doesn't care about
482 * what's been read or any other timeouts. */
483 e |= POLLIN;
484 else {
485 usec_t until;
486 /* Caller wants to process if there is something to
487 * process, but doesn't care otherwise */
488
489 r = sd_netlink_get_timeout(rtnl, &until);
490 if (r < 0)
491 return r;
492 if (r > 0) {
493 usec_t nw;
494 nw = now(CLOCK_MONOTONIC);
495 m = until > nw ? until - nw : 0;
496 }
497 }
498
499 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
500 m = timeout_usec;
501
502 p[0].fd = rtnl->fd;
503 p[0].events = e;
504
505 r = ppoll(p, 1, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
506 if (r < 0)
507 return -errno;
508
509 return r > 0 ? 1 : 0;
510 }
511
512 int sd_netlink_wait(sd_netlink *nl, uint64_t timeout_usec) {
513 assert_return(nl, -EINVAL);
514 assert_return(!rtnl_pid_changed(nl), -ECHILD);
515
516 if (nl->rqueue_size > 0)
517 return 0;
518
519 return rtnl_poll(nl, false, timeout_usec);
520 }
521
522 static int timeout_compare(const void *a, const void *b) {
523 const struct reply_callback *x = a, *y = b;
524
525 if (x->timeout != 0 && y->timeout == 0)
526 return -1;
527
528 if (x->timeout == 0 && y->timeout != 0)
529 return 1;
530
531 if (x->timeout < y->timeout)
532 return -1;
533
534 if (x->timeout > y->timeout)
535 return 1;
536
537 return 0;
538 }
539
540 int sd_netlink_call_async(sd_netlink *nl,
541 sd_netlink_message *m,
542 sd_netlink_message_handler_t callback,
543 void *userdata,
544 uint64_t usec,
545 uint32_t *serial) {
546 struct reply_callback *c;
547 uint32_t s;
548 int r, k;
549
550 assert_return(nl, -EINVAL);
551 assert_return(m, -EINVAL);
552 assert_return(callback, -EINVAL);
553 assert_return(!rtnl_pid_changed(nl), -ECHILD);
554
555 r = hashmap_ensure_allocated(&nl->reply_callbacks, &uint64_hash_ops);
556 if (r < 0)
557 return r;
558
559 if (usec != (uint64_t) -1) {
560 r = prioq_ensure_allocated(&nl->reply_callbacks_prioq, timeout_compare);
561 if (r < 0)
562 return r;
563 }
564
565 c = new0(struct reply_callback, 1);
566 if (!c)
567 return -ENOMEM;
568
569 c->callback = callback;
570 c->userdata = userdata;
571 c->timeout = calc_elapse(usec);
572
573 k = sd_netlink_send(nl, m, &s);
574 if (k < 0) {
575 free(c);
576 return k;
577 }
578
579 c->serial = s;
580
581 r = hashmap_put(nl->reply_callbacks, &c->serial, c);
582 if (r < 0) {
583 free(c);
584 return r;
585 }
586
587 if (c->timeout != 0) {
588 r = prioq_put(nl->reply_callbacks_prioq, c, &c->prioq_idx);
589 if (r > 0) {
590 c->timeout = 0;
591 sd_netlink_call_async_cancel(nl, c->serial);
592 return r;
593 }
594 }
595
596 if (serial)
597 *serial = s;
598
599 return k;
600 }
601
602 int sd_netlink_call_async_cancel(sd_netlink *nl, uint32_t serial) {
603 struct reply_callback *c;
604 uint64_t s = serial;
605
606 assert_return(nl, -EINVAL);
607 assert_return(serial != 0, -EINVAL);
608 assert_return(!rtnl_pid_changed(nl), -ECHILD);
609
610 c = hashmap_remove(nl->reply_callbacks, &s);
611 if (!c)
612 return 0;
613
614 if (c->timeout != 0)
615 prioq_remove(nl->reply_callbacks_prioq, c, &c->prioq_idx);
616
617 free(c);
618 return 1;
619 }
620
621 int sd_netlink_call(sd_netlink *rtnl,
622 sd_netlink_message *message,
623 uint64_t usec,
624 sd_netlink_message **ret) {
625 usec_t timeout;
626 uint32_t serial;
627 int r;
628
629 assert_return(rtnl, -EINVAL);
630 assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
631 assert_return(message, -EINVAL);
632
633 r = sd_netlink_send(rtnl, message, &serial);
634 if (r < 0)
635 return r;
636
637 timeout = calc_elapse(usec);
638
639 for (;;) {
640 usec_t left;
641 unsigned i;
642
643 for (i = 0; i < rtnl->rqueue_size; i++) {
644 uint32_t received_serial;
645
646 received_serial = rtnl_message_get_serial(rtnl->rqueue[i]);
647
648 if (received_serial == serial) {
649 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *incoming = NULL;
650 uint16_t type;
651
652 incoming = rtnl->rqueue[i];
653
654 /* found a match, remove from rqueue and return it */
655 memmove(rtnl->rqueue + i,rtnl->rqueue + i + 1,
656 sizeof(sd_netlink_message*) * (rtnl->rqueue_size - i - 1));
657 rtnl->rqueue_size--;
658
659 r = sd_netlink_message_get_errno(incoming);
660 if (r < 0)
661 return r;
662
663 r = sd_netlink_message_get_type(incoming, &type);
664 if (r < 0)
665 return r;
666
667 if (type == NLMSG_DONE) {
668 *ret = NULL;
669 return 0;
670 }
671
672 if (ret) {
673 *ret = incoming;
674 incoming = NULL;
675 }
676
677 return 1;
678 }
679 }
680
681 r = socket_read_message(rtnl);
682 if (r < 0)
683 return r;
684 if (r > 0)
685 /* received message, so try to process straight away */
686 continue;
687
688 if (timeout > 0) {
689 usec_t n;
690
691 n = now(CLOCK_MONOTONIC);
692 if (n >= timeout)
693 return -ETIMEDOUT;
694
695 left = timeout - n;
696 } else
697 left = (uint64_t) -1;
698
699 r = rtnl_poll(rtnl, true, left);
700 if (r < 0)
701 return r;
702 else if (r == 0)
703 return -ETIMEDOUT;
704 }
705 }
706
707 int sd_netlink_get_events(sd_netlink *rtnl) {
708 assert_return(rtnl, -EINVAL);
709 assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
710
711 if (rtnl->rqueue_size == 0)
712 return POLLIN;
713 else
714 return 0;
715 }
716
717 int sd_netlink_get_timeout(sd_netlink *rtnl, uint64_t *timeout_usec) {
718 struct reply_callback *c;
719
720 assert_return(rtnl, -EINVAL);
721 assert_return(timeout_usec, -EINVAL);
722 assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
723
724 if (rtnl->rqueue_size > 0) {
725 *timeout_usec = 0;
726 return 1;
727 }
728
729 c = prioq_peek(rtnl->reply_callbacks_prioq);
730 if (!c) {
731 *timeout_usec = (uint64_t) -1;
732 return 0;
733 }
734
735 *timeout_usec = c->timeout;
736
737 return 1;
738 }
739
740 static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
741 sd_netlink *rtnl = userdata;
742 int r;
743
744 assert(rtnl);
745
746 r = sd_netlink_process(rtnl, NULL);
747 if (r < 0)
748 return r;
749
750 return 1;
751 }
752
753 static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
754 sd_netlink *rtnl = userdata;
755 int r;
756
757 assert(rtnl);
758
759 r = sd_netlink_process(rtnl, NULL);
760 if (r < 0)
761 return r;
762
763 return 1;
764 }
765
766 static int prepare_callback(sd_event_source *s, void *userdata) {
767 sd_netlink *rtnl = userdata;
768 int r, e;
769 usec_t until;
770
771 assert(s);
772 assert(rtnl);
773
774 e = sd_netlink_get_events(rtnl);
775 if (e < 0)
776 return e;
777
778 r = sd_event_source_set_io_events(rtnl->io_event_source, e);
779 if (r < 0)
780 return r;
781
782 r = sd_netlink_get_timeout(rtnl, &until);
783 if (r < 0)
784 return r;
785 if (r > 0) {
786 int j;
787
788 j = sd_event_source_set_time(rtnl->time_event_source, until);
789 if (j < 0)
790 return j;
791 }
792
793 r = sd_event_source_set_enabled(rtnl->time_event_source, r > 0);
794 if (r < 0)
795 return r;
796
797 return 1;
798 }
799
800 int sd_netlink_attach_event(sd_netlink *rtnl, sd_event *event, int64_t priority) {
801 int r;
802
803 assert_return(rtnl, -EINVAL);
804 assert_return(!rtnl->event, -EBUSY);
805
806 assert(!rtnl->io_event_source);
807 assert(!rtnl->time_event_source);
808
809 if (event)
810 rtnl->event = sd_event_ref(event);
811 else {
812 r = sd_event_default(&rtnl->event);
813 if (r < 0)
814 return r;
815 }
816
817 r = sd_event_add_io(rtnl->event, &rtnl->io_event_source, rtnl->fd, 0, io_callback, rtnl);
818 if (r < 0)
819 goto fail;
820
821 r = sd_event_source_set_priority(rtnl->io_event_source, priority);
822 if (r < 0)
823 goto fail;
824
825 r = sd_event_source_set_description(rtnl->io_event_source, "rtnl-receive-message");
826 if (r < 0)
827 goto fail;
828
829 r = sd_event_source_set_prepare(rtnl->io_event_source, prepare_callback);
830 if (r < 0)
831 goto fail;
832
833 r = sd_event_add_time(rtnl->event, &rtnl->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, rtnl);
834 if (r < 0)
835 goto fail;
836
837 r = sd_event_source_set_priority(rtnl->time_event_source, priority);
838 if (r < 0)
839 goto fail;
840
841 r = sd_event_source_set_description(rtnl->time_event_source, "rtnl-timer");
842 if (r < 0)
843 goto fail;
844
845 return 0;
846
847 fail:
848 sd_netlink_detach_event(rtnl);
849 return r;
850 }
851
852 int sd_netlink_detach_event(sd_netlink *rtnl) {
853 assert_return(rtnl, -EINVAL);
854 assert_return(rtnl->event, -ENXIO);
855
856 rtnl->io_event_source = sd_event_source_unref(rtnl->io_event_source);
857
858 rtnl->time_event_source = sd_event_source_unref(rtnl->time_event_source);
859
860 rtnl->event = sd_event_unref(rtnl->event);
861
862 return 0;
863 }
864
865 int sd_netlink_add_match(sd_netlink *rtnl,
866 uint16_t type,
867 sd_netlink_message_handler_t callback,
868 void *userdata) {
869 _cleanup_free_ struct match_callback *c = NULL;
870 int r;
871
872 assert_return(rtnl, -EINVAL);
873 assert_return(callback, -EINVAL);
874 assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
875
876 c = new0(struct match_callback, 1);
877 if (!c)
878 return -ENOMEM;
879
880 c->callback = callback;
881 c->type = type;
882 c->userdata = userdata;
883
884 switch (type) {
885 case RTM_NEWLINK:
886 case RTM_DELLINK:
887 r = socket_broadcast_group_ref(rtnl, RTNLGRP_LINK);
888 if (r < 0)
889 return r;
890
891 break;
892 case RTM_NEWADDR:
893 case RTM_DELADDR:
894 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_IFADDR);
895 if (r < 0)
896 return r;
897
898 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_IFADDR);
899 if (r < 0)
900 return r;
901
902 break;
903 case RTM_NEWROUTE:
904 case RTM_DELROUTE:
905 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_ROUTE);
906 if (r < 0)
907 return r;
908
909 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_ROUTE);
910 if (r < 0)
911 return r;
912 break;
913 case RTM_NEWRULE:
914 case RTM_DELRULE:
915 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV4_RULE);
916 if (r < 0)
917 return r;
918
919 r = socket_broadcast_group_ref(rtnl, RTNLGRP_IPV6_RULE);
920 if (r < 0)
921 return r;
922 break;
923 default:
924 return -EOPNOTSUPP;
925 }
926
927 LIST_PREPEND(match_callbacks, rtnl->match_callbacks, c);
928
929 c = NULL;
930
931 return 0;
932 }
933
934 int sd_netlink_remove_match(sd_netlink *rtnl,
935 uint16_t type,
936 sd_netlink_message_handler_t callback,
937 void *userdata) {
938 struct match_callback *c;
939 int r;
940
941 assert_return(rtnl, -EINVAL);
942 assert_return(callback, -EINVAL);
943 assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
944
945 LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks)
946 if (c->callback == callback && c->type == type && c->userdata == userdata) {
947 LIST_REMOVE(match_callbacks, rtnl->match_callbacks, c);
948 free(c);
949
950 switch (type) {
951 case RTM_NEWLINK:
952 case RTM_DELLINK:
953 r = socket_broadcast_group_unref(rtnl, RTNLGRP_LINK);
954 if (r < 0)
955 return r;
956
957 break;
958 case RTM_NEWADDR:
959 case RTM_DELADDR:
960 r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_IFADDR);
961 if (r < 0)
962 return r;
963
964 r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_IFADDR);
965 if (r < 0)
966 return r;
967
968 break;
969 case RTM_NEWROUTE:
970 case RTM_DELROUTE:
971 r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV4_ROUTE);
972 if (r < 0)
973 return r;
974
975 r = socket_broadcast_group_unref(rtnl, RTNLGRP_IPV6_ROUTE);
976 if (r < 0)
977 return r;
978 break;
979 default:
980 return -EOPNOTSUPP;
981 }
982
983 return 1;
984 }
985
986 return 0;
987 }