chiark / gitweb /
e4d436bb175c22d2df7cbf51ad4442294deb6041
[elogind.git] / src / libsystemd / sd-rtnl / sd-rtnl.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 <sys/socket.h>
23 #include <poll.h>
24
25 #include "macro.h"
26 #include "util.h"
27 #include "hashmap.h"
28
29 #include "sd-rtnl.h"
30 #include "rtnl-internal.h"
31 #include "rtnl-util.h"
32
33 static int sd_rtnl_new(sd_rtnl **ret) {
34         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
35
36         assert_return(ret, -EINVAL);
37
38         rtnl = new0(sd_rtnl, 1);
39         if (!rtnl)
40                 return -ENOMEM;
41
42         rtnl->n_ref = REFCNT_INIT;
43
44         rtnl->fd = -1;
45
46         rtnl->sockaddr.nl.nl_family = AF_NETLINK;
47
48         rtnl->original_pid = getpid();
49
50         LIST_HEAD_INIT(rtnl->match_callbacks);
51
52         /* We guarantee that wqueue always has space for at least
53          * one entry */
54         if (!GREEDY_REALLOC(rtnl->wqueue, rtnl->wqueue_allocated, 1))
55                 return -ENOMEM;
56
57         /* We guarantee that the read buffer has at least space for
58          * a message header */
59         if (!greedy_realloc((void**)&rtnl->rbuffer, &rtnl->rbuffer_allocated,
60                             sizeof(struct nlmsghdr), sizeof(uint8_t)))
61                 return -ENOMEM;
62
63         *ret = rtnl;
64         rtnl = NULL;
65
66         return 0;
67 }
68
69 static bool rtnl_pid_changed(sd_rtnl *rtnl) {
70         assert(rtnl);
71
72         /* We don't support people creating an rtnl connection and
73          * keeping it around over a fork(). Let's complain. */
74
75         return rtnl->original_pid != getpid();
76 }
77
78 int sd_rtnl_open(sd_rtnl **ret, uint32_t groups) {
79         _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
80         socklen_t addrlen;
81         int r, one = 1;
82
83         assert_return(ret, -EINVAL);
84
85         r = sd_rtnl_new(&rtnl);
86         if (r < 0)
87                 return r;
88
89         rtnl->fd = socket(PF_NETLINK, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, NETLINK_ROUTE);
90         if (rtnl->fd < 0)
91                 return -errno;
92
93         if (setsockopt(rtnl->fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0)
94                 return -errno;
95
96         rtnl->sockaddr.nl.nl_groups = groups;
97
98         addrlen = sizeof(rtnl->sockaddr);
99
100         r = bind(rtnl->fd, &rtnl->sockaddr.sa, addrlen);
101         if (r < 0)
102                 return -errno;
103
104         r = getsockname(rtnl->fd, &rtnl->sockaddr.sa, &addrlen);
105         if (r < 0)
106                 return r;
107
108         *ret = rtnl;
109         rtnl = NULL;
110
111         return 0;
112 }
113
114 sd_rtnl *sd_rtnl_ref(sd_rtnl *rtnl) {
115         assert_return(rtnl, NULL);
116         assert_return(!rtnl_pid_changed(rtnl), NULL);
117
118         if (rtnl)
119                 assert_se(REFCNT_INC(rtnl->n_ref) >= 2);
120
121         return rtnl;
122 }
123
124 sd_rtnl *sd_rtnl_unref(sd_rtnl *rtnl) {
125         if (!rtnl)
126                 return NULL;
127
128         assert_return(!rtnl_pid_changed(rtnl), NULL);
129
130         if (REFCNT_DEC(rtnl->n_ref) <= 0) {
131                 struct match_callback *f;
132                 unsigned i;
133
134                 for (i = 0; i < rtnl->rqueue_size; i++)
135                         sd_rtnl_message_unref(rtnl->rqueue[i]);
136                 free(rtnl->rqueue);
137
138                 for (i = 0; i < rtnl->wqueue_size; i++)
139                         sd_rtnl_message_unref(rtnl->wqueue[i]);
140                 free(rtnl->wqueue);
141
142                 free(rtnl->rbuffer);
143
144                 hashmap_free_free(rtnl->reply_callbacks);
145                 prioq_free(rtnl->reply_callbacks_prioq);
146
147                 sd_event_source_unref(rtnl->io_event_source);
148                 sd_event_source_unref(rtnl->time_event_source);
149                 sd_event_source_unref(rtnl->exit_event_source);
150                 sd_event_unref(rtnl->event);
151
152                 while ((f = rtnl->match_callbacks)) {
153                         LIST_REMOVE(match_callbacks, rtnl->match_callbacks, f);
154                         free(f);
155                 }
156
157                 safe_close(rtnl->fd);
158                 free(rtnl);
159         }
160
161         return NULL;
162 }
163
164 static void rtnl_seal_message(sd_rtnl *rtnl, sd_rtnl_message *m) {
165         assert(rtnl);
166         assert(!rtnl_pid_changed(rtnl));
167         assert(m);
168         assert(m->hdr);
169
170         m->hdr->nlmsg_seq = rtnl->serial++;
171
172         rtnl_message_seal(m);
173
174         return;
175 }
176
177 int sd_rtnl_send(sd_rtnl *nl,
178                  sd_rtnl_message *message,
179                  uint32_t *serial) {
180         int r;
181
182         assert_return(nl, -EINVAL);
183         assert_return(!rtnl_pid_changed(nl), -ECHILD);
184         assert_return(message, -EINVAL);
185         assert_return(!message->sealed, -EPERM);
186
187         rtnl_seal_message(nl, message);
188
189         if (nl->wqueue_size <= 0) {
190                 /* send directly */
191                 r = socket_write_message(nl, message);
192                 if (r < 0)
193                         return r;
194                 else if (r == 0) {
195                         /* nothing was sent, so let's put it on
196                          * the queue */
197                         nl->wqueue[0] = sd_rtnl_message_ref(message);
198                         nl->wqueue_size = 1;
199                 }
200         } else {
201                 /* append to queue */
202                 if (nl->wqueue_size >= RTNL_WQUEUE_MAX)
203                         return -ENOBUFS;
204
205                 if (!GREEDY_REALLOC(nl->wqueue, nl->wqueue_allocated, nl->wqueue_size + 1))
206                         return -ENOMEM;
207
208                 nl->wqueue[nl->wqueue_size ++] = sd_rtnl_message_ref(message);
209         }
210
211         if (serial)
212                 *serial = rtnl_message_get_serial(message);
213
214         return 1;
215 }
216
217 int rtnl_rqueue_make_room(sd_rtnl *rtnl) {
218         assert(rtnl);
219
220         if (rtnl->rqueue_size >= RTNL_RQUEUE_MAX)
221                 return -ENOBUFS;
222
223         if (!GREEDY_REALLOC(rtnl->rqueue, rtnl->rqueue_allocated, rtnl->rqueue_size + 1))
224                 return -ENOMEM;
225
226         return 0;
227 }
228
229 static int dispatch_rqueue(sd_rtnl *rtnl, sd_rtnl_message **message) {
230         int r;
231
232         assert(rtnl);
233         assert(message);
234
235         if (rtnl->rqueue_size <= 0) {
236                 /* Try to read a new message */
237                 r = socket_read_message(rtnl);
238                 if (r <= 0)
239                         return r;
240         }
241
242         /* Dispatch a queued message */
243         *message = rtnl->rqueue[0];
244         rtnl->rqueue_size --;
245         memmove(rtnl->rqueue, rtnl->rqueue + 1, sizeof(sd_rtnl_message*) * rtnl->rqueue_size);
246
247         return 1;
248 }
249
250 static int dispatch_wqueue(sd_rtnl *rtnl) {
251         int r, ret = 0;
252
253         assert(rtnl);
254
255         while (rtnl->wqueue_size > 0) {
256                 r = socket_write_message(rtnl, rtnl->wqueue[0]);
257                 if (r < 0)
258                         return r;
259                 else if (r == 0)
260                         /* Didn't do anything this time */
261                         return ret;
262                 else {
263                         /* see equivalent in sd-bus.c */
264                         sd_rtnl_message_unref(rtnl->wqueue[0]);
265                         rtnl->wqueue_size --;
266                         memmove(rtnl->wqueue, rtnl->wqueue + 1, sizeof(sd_rtnl_message*) * rtnl->wqueue_size);
267
268                         ret = 1;
269                 }
270         }
271
272         return ret;
273 }
274
275 static int process_timeout(sd_rtnl *rtnl) {
276         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
277         struct reply_callback *c;
278         usec_t n;
279         int r;
280
281         assert(rtnl);
282
283         c = prioq_peek(rtnl->reply_callbacks_prioq);
284         if (!c)
285                 return 0;
286
287         n = now(CLOCK_MONOTONIC);
288         if (c->timeout > n)
289                 return 0;
290
291         r = rtnl_message_new_synthetic_error(-ETIMEDOUT, c->serial, &m);
292         if (r < 0)
293                 return r;
294
295         assert_se(prioq_pop(rtnl->reply_callbacks_prioq) == c);
296         hashmap_remove(rtnl->reply_callbacks, &c->serial);
297
298         r = c->callback(rtnl, m, c->userdata);
299         free(c);
300
301         return r < 0 ? r : 1;
302 }
303
304 static int process_reply(sd_rtnl *rtnl, sd_rtnl_message *m) {
305         struct reply_callback *c;
306         uint64_t serial;
307         int r;
308
309         assert(rtnl);
310         assert(m);
311
312         if (sd_rtnl_message_is_broadcast(m))
313                 return 0;
314
315         serial = rtnl_message_get_serial(m);
316         c = hashmap_remove(rtnl->reply_callbacks, &serial);
317         if (!c)
318                 return 0;
319
320         if (c->timeout != 0)
321                 prioq_remove(rtnl->reply_callbacks_prioq, c, &c->prioq_idx);
322
323         r = c->callback(rtnl, m, c->userdata);
324         free(c);
325
326         return r;
327 }
328
329 static int process_match(sd_rtnl *rtnl, sd_rtnl_message *m) {
330         struct match_callback *c;
331         uint16_t type;
332         int r;
333
334         assert(rtnl);
335         assert(m);
336
337         r = sd_rtnl_message_get_type(m, &type);
338         if (r < 0)
339                 return r;
340
341         LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks) {
342                 if (type == c->type) {
343                         r = c->callback(rtnl, m, c->userdata);
344                         if (r != 0)
345                                 return r;
346                 }
347         }
348
349         return 0;
350 }
351
352 static int process_running(sd_rtnl *rtnl, sd_rtnl_message **ret) {
353         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
354         int r;
355
356         assert(rtnl);
357
358         r = process_timeout(rtnl);
359         if (r != 0)
360                 goto null_message;
361
362         r = dispatch_wqueue(rtnl);
363         if (r != 0)
364                 goto null_message;
365
366         r = dispatch_rqueue(rtnl, &m);
367         if (r < 0)
368                 return r;
369         if (!m)
370                 goto null_message;
371
372         r = process_reply(rtnl, m);
373         if (r != 0)
374                 goto null_message;
375
376         r = process_match(rtnl, m);
377         if (r != 0)
378                 goto null_message;
379
380         if (ret) {
381                 *ret = m;
382                 m = NULL;
383
384                 return 1;
385         }
386
387         return 1;
388
389 null_message:
390         if (r >= 0 && ret)
391                 *ret = NULL;
392
393         return r;
394 }
395
396 int sd_rtnl_process(sd_rtnl *rtnl, sd_rtnl_message **ret) {
397         RTNL_DONT_DESTROY(rtnl);
398         int r;
399
400         assert_return(rtnl, -EINVAL);
401         assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
402         assert_return(!rtnl->processing, -EBUSY);
403
404         rtnl->processing = true;
405         r = process_running(rtnl, ret);
406         rtnl->processing = false;
407
408         return r;
409 }
410
411 static usec_t calc_elapse(uint64_t usec) {
412         if (usec == (uint64_t) -1)
413                 return 0;
414
415         if (usec == 0)
416                 usec = RTNL_DEFAULT_TIMEOUT;
417
418         return now(CLOCK_MONOTONIC) + usec;
419 }
420
421 static int rtnl_poll(sd_rtnl *rtnl, bool need_more, uint64_t timeout_usec) {
422         struct pollfd p[1] = {};
423         struct timespec ts;
424         usec_t m = (usec_t) -1;
425         int r, e;
426
427         assert(rtnl);
428
429         e = sd_rtnl_get_events(rtnl);
430         if (e < 0)
431                 return e;
432
433         if (need_more)
434                 /* Caller wants more data, and doesn't care about
435                  * what's been read or any other timeouts. */
436                 return e |= POLLIN;
437         else {
438                 usec_t until;
439                 /* Caller wants to process if there is something to
440                  * process, but doesn't care otherwise */
441
442                 r = sd_rtnl_get_timeout(rtnl, &until);
443                 if (r < 0)
444                         return r;
445                 if (r > 0) {
446                         usec_t nw;
447                         nw = now(CLOCK_MONOTONIC);
448                         m = until > nw ? until - nw : 0;
449                 }
450         }
451
452         if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
453                 m = timeout_usec;
454
455         p[0].fd = rtnl->fd;
456         p[0].events = e;
457
458         r = ppoll(p, 1, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
459         if (r < 0)
460                 return -errno;
461
462         return r > 0 ? 1 : 0;
463 }
464
465 int sd_rtnl_wait(sd_rtnl *nl, uint64_t timeout_usec) {
466         assert_return(nl, -EINVAL);
467         assert_return(!rtnl_pid_changed(nl), -ECHILD);
468
469         if (nl->rqueue_size > 0)
470                 return 0;
471
472         return rtnl_poll(nl, false, timeout_usec);
473 }
474
475 static int timeout_compare(const void *a, const void *b) {
476         const struct reply_callback *x = a, *y = b;
477
478         if (x->timeout != 0 && y->timeout == 0)
479                 return -1;
480
481         if (x->timeout == 0 && y->timeout != 0)
482                 return 1;
483
484         if (x->timeout < y->timeout)
485                 return -1;
486
487         if (x->timeout > y->timeout)
488                 return 1;
489
490         return 0;
491 }
492
493 int sd_rtnl_call_async(sd_rtnl *nl,
494                        sd_rtnl_message *m,
495                        sd_rtnl_message_handler_t callback,
496                        void *userdata,
497                        uint64_t usec,
498                        uint32_t *serial) {
499         struct reply_callback *c;
500         uint32_t s;
501         int r, k;
502
503         assert_return(nl, -EINVAL);
504         assert_return(m, -EINVAL);
505         assert_return(callback, -EINVAL);
506         assert_return(!rtnl_pid_changed(nl), -ECHILD);
507
508         r = hashmap_ensure_allocated(&nl->reply_callbacks, uint64_hash_func, uint64_compare_func);
509         if (r < 0)
510                 return r;
511
512         if (usec != (uint64_t) -1) {
513                 r = prioq_ensure_allocated(&nl->reply_callbacks_prioq, timeout_compare);
514                 if (r < 0)
515                         return r;
516         }
517
518         c = new0(struct reply_callback, 1);
519         if (!c)
520                 return -ENOMEM;
521
522         c->callback = callback;
523         c->userdata = userdata;
524         c->timeout = calc_elapse(usec);
525
526         k = sd_rtnl_send(nl, m, &s);
527         if (k < 0) {
528                 free(c);
529                 return k;
530         }
531
532         c->serial = s;
533
534         r = hashmap_put(nl->reply_callbacks, &c->serial, c);
535         if (r < 0) {
536                 free(c);
537                 return r;
538         }
539
540         if (c->timeout != 0) {
541                 r = prioq_put(nl->reply_callbacks_prioq, c, &c->prioq_idx);
542                 if (r > 0) {
543                         c->timeout = 0;
544                         sd_rtnl_call_async_cancel(nl, c->serial);
545                         return r;
546                 }
547         }
548
549         if (serial)
550                 *serial = s;
551
552         return k;
553 }
554
555 int sd_rtnl_call_async_cancel(sd_rtnl *nl, uint32_t serial) {
556         struct reply_callback *c;
557         uint64_t s = serial;
558
559         assert_return(nl, -EINVAL);
560         assert_return(serial != 0, -EINVAL);
561         assert_return(!rtnl_pid_changed(nl), -ECHILD);
562
563         c = hashmap_remove(nl->reply_callbacks, &s);
564         if (!c)
565                 return 0;
566
567         if (c->timeout != 0)
568                 prioq_remove(nl->reply_callbacks_prioq, c, &c->prioq_idx);
569
570         free(c);
571         return 1;
572 }
573
574 int sd_rtnl_call(sd_rtnl *rtnl,
575                 sd_rtnl_message *message,
576                 uint64_t usec,
577                 sd_rtnl_message **ret) {
578         usec_t timeout;
579         uint32_t serial;
580         unsigned i = 0;
581         int r;
582
583         assert_return(rtnl, -EINVAL);
584         assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
585         assert_return(message, -EINVAL);
586
587         r = sd_rtnl_send(rtnl, message, &serial);
588         if (r < 0)
589                 return r;
590
591         timeout = calc_elapse(usec);
592
593         for (;;) {
594                 usec_t left;
595
596                 while (i < rtnl->rqueue_size) {
597                         sd_rtnl_message *incoming;
598                         uint32_t received_serial;
599
600                         incoming = rtnl->rqueue[i];
601                         received_serial = rtnl_message_get_serial(incoming);
602
603                         if (received_serial == serial) {
604                                 /* found a match, remove from rqueue and return it */
605                                 memmove(rtnl->rqueue + i,rtnl->rqueue + i + 1,
606                                         sizeof(sd_rtnl_message*) * (rtnl->rqueue_size - i - 1));
607                                 rtnl->rqueue_size--;
608
609                                 r = sd_rtnl_message_get_errno(incoming);
610                                 if (r < 0) {
611                                         sd_rtnl_message_unref(incoming);
612                                         return r;
613                                 }
614
615                                 if (ret) {
616                                         *ret = incoming;
617                                 } else
618                                         sd_rtnl_message_unref(incoming);
619
620                                 return 1;
621                         }
622
623                         /* Try to read more, right away */
624                         i ++;
625                 }
626
627                 r = socket_read_message(rtnl);
628                 if (r < 0)
629                         return r;
630                 if (r > 0)
631                         /* receieved message, so try to process straight away */
632                         continue;
633
634                 if (timeout > 0) {
635                         usec_t n;
636
637                         n = now(CLOCK_MONOTONIC);
638                         if (n >= timeout)
639                                 return -ETIMEDOUT;
640
641                         left = timeout - n;
642                 } else
643                         left = (uint64_t) -1;
644
645                 r = rtnl_poll(rtnl, true, left);
646                 if (r < 0)
647                         return r;
648
649                 r = dispatch_wqueue(rtnl);
650                 if (r < 0)
651                         return r;
652         }
653 }
654
655 int sd_rtnl_flush(sd_rtnl *rtnl) {
656         int r;
657
658         assert_return(rtnl, -EINVAL);
659         assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
660
661         if (rtnl->wqueue_size <= 0)
662                 return 0;
663
664         for (;;) {
665                 r = dispatch_wqueue(rtnl);
666                 if (r < 0)
667                         return r;
668
669                 if (rtnl->wqueue_size <= 0)
670                         return 0;
671
672                 r = rtnl_poll(rtnl, false, (uint64_t) -1);
673                 if (r < 0)
674                         return r;
675         }
676 }
677
678 int sd_rtnl_get_events(sd_rtnl *rtnl) {
679         int flags = 0;
680
681         assert_return(rtnl, -EINVAL);
682         assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
683
684         if (rtnl->rqueue_size <= 0)
685                 flags |= POLLIN;
686         if (rtnl->wqueue_size > 0)
687                 flags |= POLLOUT;
688
689         return flags;
690 }
691
692 int sd_rtnl_get_timeout(sd_rtnl *rtnl, uint64_t *timeout_usec) {
693         struct reply_callback *c;
694
695         assert_return(rtnl, -EINVAL);
696         assert_return(timeout_usec, -EINVAL);
697         assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
698
699         if (rtnl->rqueue_size > 0) {
700                 *timeout_usec = 0;
701                 return 1;
702         }
703
704         c = prioq_peek(rtnl->reply_callbacks_prioq);
705         if (!c) {
706                 *timeout_usec = (uint64_t) -1;
707                 return 0;
708         }
709
710         *timeout_usec = c->timeout;
711
712         return 1;
713 }
714
715 static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
716         sd_rtnl *rtnl = userdata;
717         int r;
718
719         assert(rtnl);
720
721         r = sd_rtnl_process(rtnl, NULL);
722         if (r < 0)
723                 return r;
724
725         return 1;
726 }
727
728 static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
729         sd_rtnl *rtnl = userdata;
730         int r;
731
732         assert(rtnl);
733
734         r = sd_rtnl_process(rtnl, NULL);
735         if (r < 0)
736                 return r;
737
738         return 1;
739 }
740
741 static int prepare_callback(sd_event_source *s, void *userdata) {
742         sd_rtnl *rtnl = userdata;
743         int r, e;
744         usec_t until;
745
746         assert(s);
747         assert(rtnl);
748
749         e = sd_rtnl_get_events(rtnl);
750         if (e < 0)
751                 return e;
752
753         r = sd_event_source_set_io_events(rtnl->io_event_source, e);
754         if (r < 0)
755                 return r;
756
757         r = sd_rtnl_get_timeout(rtnl, &until);
758         if (r < 0)
759                 return r;
760         if (r > 0) {
761                 int j;
762
763                 j = sd_event_source_set_time(rtnl->time_event_source, until);
764                 if (j < 0)
765                         return j;
766         }
767
768         r = sd_event_source_set_enabled(rtnl->time_event_source, r > 0);
769         if (r < 0)
770                 return r;
771
772         return 1;
773 }
774
775 static int exit_callback(sd_event_source *event, void *userdata) {
776         sd_rtnl *rtnl = userdata;
777
778         assert(event);
779
780         sd_rtnl_flush(rtnl);
781
782         return 1;
783 }
784
785 int sd_rtnl_attach_event(sd_rtnl *rtnl, sd_event *event, int priority) {
786         int r;
787
788         assert_return(rtnl, -EINVAL);
789         assert_return(!rtnl->event, -EBUSY);
790
791         assert(!rtnl->io_event_source);
792         assert(!rtnl->time_event_source);
793
794         if (event)
795                 rtnl->event = sd_event_ref(event);
796         else {
797                 r = sd_event_default(&rtnl->event);
798                 if (r < 0)
799                         return r;
800         }
801
802         r = sd_event_add_io(rtnl->event, &rtnl->io_event_source, rtnl->fd, 0, io_callback, rtnl);
803         if (r < 0)
804                 goto fail;
805
806         r = sd_event_source_set_priority(rtnl->io_event_source, priority);
807         if (r < 0)
808                 goto fail;
809
810         r = sd_event_source_set_prepare(rtnl->io_event_source, prepare_callback);
811         if (r < 0)
812                 goto fail;
813
814         r = sd_event_add_time(rtnl->event, &rtnl->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, rtnl);
815         if (r < 0)
816                 goto fail;
817
818         r = sd_event_source_set_priority(rtnl->time_event_source, priority);
819         if (r < 0)
820                 goto fail;
821
822         r = sd_event_add_exit(rtnl->event, &rtnl->exit_event_source, exit_callback, rtnl);
823         if (r < 0)
824                 goto fail;
825
826         return 0;
827
828 fail:
829         sd_rtnl_detach_event(rtnl);
830         return r;
831 }
832
833 int sd_rtnl_detach_event(sd_rtnl *rtnl) {
834         assert_return(rtnl, -EINVAL);
835         assert_return(rtnl->event, -ENXIO);
836
837         if (rtnl->io_event_source)
838                 rtnl->io_event_source = sd_event_source_unref(rtnl->io_event_source);
839
840         if (rtnl->time_event_source)
841                 rtnl->time_event_source = sd_event_source_unref(rtnl->time_event_source);
842
843         if (rtnl->exit_event_source)
844                 rtnl->exit_event_source = sd_event_source_unref(rtnl->exit_event_source);
845
846         if (rtnl->event)
847                 rtnl->event = sd_event_unref(rtnl->event);
848
849         return 0;
850 }
851
852 int sd_rtnl_add_match(sd_rtnl *rtnl,
853                       uint16_t type,
854                       sd_rtnl_message_handler_t callback,
855                       void *userdata) {
856         struct match_callback *c;
857
858         assert_return(rtnl, -EINVAL);
859         assert_return(callback, -EINVAL);
860         assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
861         assert_return(rtnl_message_type_is_link(type) ||
862                       rtnl_message_type_is_addr(type) ||
863                       rtnl_message_type_is_route(type), -ENOTSUP);
864
865         c = new0(struct match_callback, 1);
866         if (!c)
867                 return -ENOMEM;
868
869         c->callback = callback;
870         c->type = type;
871         c->userdata = userdata;
872
873         LIST_PREPEND(match_callbacks, rtnl->match_callbacks, c);
874
875         return 0;
876 }
877
878 int sd_rtnl_remove_match(sd_rtnl *rtnl,
879                          uint16_t type,
880                          sd_rtnl_message_handler_t callback,
881                          void *userdata) {
882         struct match_callback *c;
883
884         assert_return(rtnl, -EINVAL);
885         assert_return(callback, -EINVAL);
886         assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
887
888         LIST_FOREACH(match_callbacks, c, rtnl->match_callbacks)
889                 if (c->callback == callback && c->type == type && c->userdata == userdata) {
890                         LIST_REMOVE(match_callbacks, rtnl->match_callbacks, c);
891                         free(c);
892
893                         return 1;
894                 }
895
896         return 0;
897 }