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