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