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