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