1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
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.
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.
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/>.
23 #include <sys/socket.h>
25 #include "sd-netlink.h"
30 #include "netlink-internal.h"
31 #include "netlink-util.h"
34 static int sd_netlink_new(sd_netlink
**ret
) {
35 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
37 assert_return(ret
, -EINVAL
);
39 rtnl
= new0(sd_netlink
, 1);
43 rtnl
->n_ref
= REFCNT_INIT
;
47 rtnl
->sockaddr
.nl
.nl_family
= AF_NETLINK
;
49 rtnl
->original_pid
= getpid();
51 LIST_HEAD_INIT(rtnl
->match_callbacks
);
53 /* We guarantee that the read buffer has at least space for
55 if (!greedy_realloc((void**)&rtnl
->rbuffer
, &rtnl
->rbuffer_allocated
,
56 sizeof(struct nlmsghdr
), sizeof(uint8_t)))
59 /* Change notification responses have sequence 0, so we must
60 * start our request sequence numbers at 1, or we may confuse our
61 * responses with notifications from the kernel */
70 int sd_netlink_new_from_netlink(sd_netlink
**ret
, int fd
) {
71 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
75 assert_return(ret
, -EINVAL
);
77 r
= sd_netlink_new(&rtnl
);
81 addrlen
= sizeof(rtnl
->sockaddr
);
83 r
= getsockname(fd
, &rtnl
->sockaddr
.sa
, &addrlen
);
95 static bool rtnl_pid_changed(sd_netlink
*rtnl
) {
98 /* We don't support people creating an rtnl connection and
99 * keeping it around over a fork(). Let's complain. */
101 return rtnl
->original_pid
!= getpid();
104 int sd_netlink_open_fd(sd_netlink
**ret
, int fd
) {
105 _cleanup_netlink_unref_ sd_netlink
*rtnl
= NULL
;
108 assert_return(ret
, -EINVAL
);
109 assert_return(fd
>= 0, -EBADF
);
111 r
= sd_netlink_new(&rtnl
);
117 r
= socket_bind(rtnl
);
127 int sd_netlink_open(sd_netlink
**ret
) {
128 _cleanup_close_
int fd
= -1;
131 fd
= socket_open(NETLINK_ROUTE
);
135 r
= sd_netlink_open_fd(ret
, fd
);
144 int sd_netlink_inc_rcvbuf(const sd_netlink
*const rtnl
, const int size
) {
145 return fd_inc_rcvbuf(rtnl
->fd
, size
);
148 sd_netlink
*sd_netlink_ref(sd_netlink
*rtnl
) {
149 assert_return(rtnl
, NULL
);
150 assert_return(!rtnl_pid_changed(rtnl
), NULL
);
153 assert_se(REFCNT_INC(rtnl
->n_ref
) >= 2);
158 sd_netlink
*sd_netlink_unref(sd_netlink
*rtnl
) {
162 assert_return(!rtnl_pid_changed(rtnl
), NULL
);
164 if (REFCNT_DEC(rtnl
->n_ref
) == 0) {
165 struct match_callback
*f
;
168 for (i
= 0; i
< rtnl
->rqueue_size
; i
++)
169 sd_netlink_message_unref(rtnl
->rqueue
[i
]);
172 for (i
= 0; i
< rtnl
->rqueue_partial_size
; i
++)
173 sd_netlink_message_unref(rtnl
->rqueue_partial
[i
]);
174 free(rtnl
->rqueue_partial
);
178 hashmap_free_free(rtnl
->reply_callbacks
);
179 prioq_free(rtnl
->reply_callbacks_prioq
);
181 sd_event_source_unref(rtnl
->io_event_source
);
182 sd_event_source_unref(rtnl
->time_event_source
);
183 sd_event_unref(rtnl
->event
);
185 while ((f
= rtnl
->match_callbacks
)) {
186 sd_netlink_remove_match(rtnl
, f
->type
, f
->callback
, f
->userdata
);
189 hashmap_free(rtnl
->broadcast_group_refs
);
191 safe_close(rtnl
->fd
);
198 static void rtnl_seal_message(sd_netlink
*rtnl
, sd_netlink_message
*m
) {
200 assert(!rtnl_pid_changed(rtnl
));
204 /* don't use seq == 0, as that is used for broadcasts, so we
205 would get confused by replies to such messages */
206 m
->hdr
->nlmsg_seq
= rtnl
->serial
++ ? : rtnl
->serial
++;
208 rtnl_message_seal(m
);
213 int sd_netlink_send(sd_netlink
*nl
,
214 sd_netlink_message
*message
,
218 assert_return(nl
, -EINVAL
);
219 assert_return(!rtnl_pid_changed(nl
), -ECHILD
);
220 assert_return(message
, -EINVAL
);
221 assert_return(!message
->sealed
, -EPERM
);
223 rtnl_seal_message(nl
, message
);
225 r
= socket_write_message(nl
, message
);
230 *serial
= rtnl_message_get_serial(message
);
235 int rtnl_rqueue_make_room(sd_netlink
*rtnl
) {
238 if (rtnl
->rqueue_size
>= RTNL_RQUEUE_MAX
) {
239 log_debug("rtnl: exhausted the read queue size (%d)", RTNL_RQUEUE_MAX
);
243 if (!GREEDY_REALLOC(rtnl
->rqueue
, rtnl
->rqueue_allocated
, rtnl
->rqueue_size
+ 1))
249 int rtnl_rqueue_partial_make_room(sd_netlink
*rtnl
) {
252 if (rtnl
->rqueue_partial_size
>= RTNL_RQUEUE_MAX
) {
253 log_debug("rtnl: exhausted the partial read queue size (%d)", RTNL_RQUEUE_MAX
);
257 if (!GREEDY_REALLOC(rtnl
->rqueue_partial
, rtnl
->rqueue_partial_allocated
,
258 rtnl
->rqueue_partial_size
+ 1))
264 static int dispatch_rqueue(sd_netlink
*rtnl
, sd_netlink_message
**message
) {
270 if (rtnl
->rqueue_size
<= 0) {
271 /* Try to read a new message */
272 r
= socket_read_message(rtnl
);
277 /* Dispatch a queued message */
278 *message
= rtnl
->rqueue
[0];
279 rtnl
->rqueue_size
--;
280 memmove(rtnl
->rqueue
, rtnl
->rqueue
+ 1, sizeof(sd_netlink_message
*) * rtnl
->rqueue_size
);
285 static int process_timeout(sd_netlink
*rtnl
) {
286 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
287 struct reply_callback
*c
;
293 c
= prioq_peek(rtnl
->reply_callbacks_prioq
);
297 n
= now(CLOCK_MONOTONIC
);
301 r
= rtnl_message_new_synthetic_error(-ETIMEDOUT
, c
->serial
, &m
);
305 assert_se(prioq_pop(rtnl
->reply_callbacks_prioq
) == c
);
306 hashmap_remove(rtnl
->reply_callbacks
, &c
->serial
);
308 r
= c
->callback(rtnl
, m
, c
->userdata
);
310 log_debug_errno(r
, "sd-netlink: timedout callback failed: %m");
317 static int process_reply(sd_netlink
*rtnl
, sd_netlink_message
*m
) {
318 _cleanup_free_
struct reply_callback
*c
= NULL
;
326 serial
= rtnl_message_get_serial(m
);
327 c
= hashmap_remove(rtnl
->reply_callbacks
, &serial
);
332 prioq_remove(rtnl
->reply_callbacks_prioq
, c
, &c
->prioq_idx
);
334 r
= sd_netlink_message_get_type(m
, &type
);
338 if (type
== NLMSG_DONE
)
341 r
= c
->callback(rtnl
, m
, c
->userdata
);
343 log_debug_errno(r
, "sd-netlink: callback failed: %m");
348 static int process_match(sd_netlink
*rtnl
, sd_netlink_message
*m
) {
349 struct match_callback
*c
;
356 r
= sd_netlink_message_get_type(m
, &type
);
360 LIST_FOREACH(match_callbacks
, c
, rtnl
->match_callbacks
) {
361 if (type
== c
->type
) {
362 r
= c
->callback(rtnl
, m
, c
->userdata
);
365 log_debug_errno(r
, "sd-netlink: match callback failed: %m");
375 static int process_running(sd_netlink
*rtnl
, sd_netlink_message
**ret
) {
376 _cleanup_netlink_message_unref_ sd_netlink_message
*m
= NULL
;
381 r
= process_timeout(rtnl
);
385 r
= dispatch_rqueue(rtnl
, &m
);
391 if (sd_netlink_message_is_broadcast(m
)) {
392 r
= process_match(rtnl
, m
);
396 r
= process_reply(rtnl
, m
);
417 int sd_netlink_process(sd_netlink
*rtnl
, sd_netlink_message
**ret
) {
418 RTNL_DONT_DESTROY(rtnl
);
421 assert_return(rtnl
, -EINVAL
);
422 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
423 assert_return(!rtnl
->processing
, -EBUSY
);
425 rtnl
->processing
= true;
426 r
= process_running(rtnl
, ret
);
427 rtnl
->processing
= false;
432 static usec_t
calc_elapse(uint64_t usec
) {
433 if (usec
== (uint64_t) -1)
437 usec
= RTNL_DEFAULT_TIMEOUT
;
439 return now(CLOCK_MONOTONIC
) + usec
;
442 static int rtnl_poll(sd_netlink
*rtnl
, bool need_more
, uint64_t timeout_usec
) {
443 struct pollfd p
[1] = {};
445 usec_t m
= USEC_INFINITY
;
450 e
= sd_netlink_get_events(rtnl
);
455 /* Caller wants more data, and doesn't care about
456 * what's been read or any other timeouts. */
460 /* Caller wants to process if there is something to
461 * process, but doesn't care otherwise */
463 r
= sd_netlink_get_timeout(rtnl
, &until
);
468 nw
= now(CLOCK_MONOTONIC
);
469 m
= until
> nw
? until
- nw
: 0;
473 if (timeout_usec
!= (uint64_t) -1 && (m
== (uint64_t) -1 || timeout_usec
< m
))
479 r
= ppoll(p
, 1, m
== (uint64_t) -1 ? NULL
: timespec_store(&ts
, m
), NULL
);
483 return r
> 0 ? 1 : 0;
486 int sd_netlink_wait(sd_netlink
*nl
, uint64_t timeout_usec
) {
487 assert_return(nl
, -EINVAL
);
488 assert_return(!rtnl_pid_changed(nl
), -ECHILD
);
490 if (nl
->rqueue_size
> 0)
493 return rtnl_poll(nl
, false, timeout_usec
);
496 static int timeout_compare(const void *a
, const void *b
) {
497 const struct reply_callback
*x
= a
, *y
= b
;
499 if (x
->timeout
!= 0 && y
->timeout
== 0)
502 if (x
->timeout
== 0 && y
->timeout
!= 0)
505 if (x
->timeout
< y
->timeout
)
508 if (x
->timeout
> y
->timeout
)
514 int sd_netlink_call_async(sd_netlink
*nl
,
515 sd_netlink_message
*m
,
516 sd_netlink_message_handler_t callback
,
520 struct reply_callback
*c
;
524 assert_return(nl
, -EINVAL
);
525 assert_return(m
, -EINVAL
);
526 assert_return(callback
, -EINVAL
);
527 assert_return(!rtnl_pid_changed(nl
), -ECHILD
);
529 r
= hashmap_ensure_allocated(&nl
->reply_callbacks
, &uint64_hash_ops
);
533 if (usec
!= (uint64_t) -1) {
534 r
= prioq_ensure_allocated(&nl
->reply_callbacks_prioq
, timeout_compare
);
539 c
= new0(struct reply_callback
, 1);
543 c
->callback
= callback
;
544 c
->userdata
= userdata
;
545 c
->timeout
= calc_elapse(usec
);
547 k
= sd_netlink_send(nl
, m
, &s
);
555 r
= hashmap_put(nl
->reply_callbacks
, &c
->serial
, c
);
561 if (c
->timeout
!= 0) {
562 r
= prioq_put(nl
->reply_callbacks_prioq
, c
, &c
->prioq_idx
);
565 sd_netlink_call_async_cancel(nl
, c
->serial
);
576 int sd_netlink_call_async_cancel(sd_netlink
*nl
, uint32_t serial
) {
577 struct reply_callback
*c
;
580 assert_return(nl
, -EINVAL
);
581 assert_return(serial
!= 0, -EINVAL
);
582 assert_return(!rtnl_pid_changed(nl
), -ECHILD
);
584 c
= hashmap_remove(nl
->reply_callbacks
, &s
);
589 prioq_remove(nl
->reply_callbacks_prioq
, c
, &c
->prioq_idx
);
595 int sd_netlink_call(sd_netlink
*rtnl
,
596 sd_netlink_message
*message
,
598 sd_netlink_message
**ret
) {
603 assert_return(rtnl
, -EINVAL
);
604 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
605 assert_return(message
, -EINVAL
);
607 r
= sd_netlink_send(rtnl
, message
, &serial
);
611 timeout
= calc_elapse(usec
);
617 for (i
= 0; i
< rtnl
->rqueue_size
; i
++) {
618 uint32_t received_serial
;
620 received_serial
= rtnl_message_get_serial(rtnl
->rqueue
[i
]);
622 if (received_serial
== serial
) {
623 _cleanup_netlink_message_unref_ sd_netlink_message
*incoming
= NULL
;
626 incoming
= rtnl
->rqueue
[i
];
628 /* found a match, remove from rqueue and return it */
629 memmove(rtnl
->rqueue
+ i
,rtnl
->rqueue
+ i
+ 1,
630 sizeof(sd_netlink_message
*) * (rtnl
->rqueue_size
- i
- 1));
633 r
= sd_netlink_message_get_errno(incoming
);
637 r
= sd_netlink_message_get_type(incoming
, &type
);
641 if (type
== NLMSG_DONE
) {
655 r
= socket_read_message(rtnl
);
659 /* received message, so try to process straight away */
665 n
= now(CLOCK_MONOTONIC
);
671 left
= (uint64_t) -1;
673 r
= rtnl_poll(rtnl
, true, left
);
681 int sd_netlink_get_events(sd_netlink
*rtnl
) {
682 assert_return(rtnl
, -EINVAL
);
683 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
685 if (rtnl
->rqueue_size
== 0)
691 int sd_netlink_get_timeout(sd_netlink
*rtnl
, uint64_t *timeout_usec
) {
692 struct reply_callback
*c
;
694 assert_return(rtnl
, -EINVAL
);
695 assert_return(timeout_usec
, -EINVAL
);
696 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
698 if (rtnl
->rqueue_size
> 0) {
703 c
= prioq_peek(rtnl
->reply_callbacks_prioq
);
705 *timeout_usec
= (uint64_t) -1;
709 *timeout_usec
= c
->timeout
;
714 static int io_callback(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
715 sd_netlink
*rtnl
= userdata
;
720 r
= sd_netlink_process(rtnl
, NULL
);
727 static int time_callback(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
728 sd_netlink
*rtnl
= userdata
;
733 r
= sd_netlink_process(rtnl
, NULL
);
740 static int prepare_callback(sd_event_source
*s
, void *userdata
) {
741 sd_netlink
*rtnl
= userdata
;
748 e
= sd_netlink_get_events(rtnl
);
752 r
= sd_event_source_set_io_events(rtnl
->io_event_source
, e
);
756 r
= sd_netlink_get_timeout(rtnl
, &until
);
762 j
= sd_event_source_set_time(rtnl
->time_event_source
, until
);
767 r
= sd_event_source_set_enabled(rtnl
->time_event_source
, r
> 0);
774 int sd_netlink_attach_event(sd_netlink
*rtnl
, sd_event
*event
, int priority
) {
777 assert_return(rtnl
, -EINVAL
);
778 assert_return(!rtnl
->event
, -EBUSY
);
780 assert(!rtnl
->io_event_source
);
781 assert(!rtnl
->time_event_source
);
784 rtnl
->event
= sd_event_ref(event
);
786 r
= sd_event_default(&rtnl
->event
);
791 r
= sd_event_add_io(rtnl
->event
, &rtnl
->io_event_source
, rtnl
->fd
, 0, io_callback
, rtnl
);
795 r
= sd_event_source_set_priority(rtnl
->io_event_source
, priority
);
799 r
= sd_event_source_set_description(rtnl
->io_event_source
, "rtnl-receive-message");
803 r
= sd_event_source_set_prepare(rtnl
->io_event_source
, prepare_callback
);
807 r
= sd_event_add_time(rtnl
->event
, &rtnl
->time_event_source
, CLOCK_MONOTONIC
, 0, 0, time_callback
, rtnl
);
811 r
= sd_event_source_set_priority(rtnl
->time_event_source
, priority
);
815 r
= sd_event_source_set_description(rtnl
->time_event_source
, "rtnl-timer");
822 sd_netlink_detach_event(rtnl
);
826 int sd_netlink_detach_event(sd_netlink
*rtnl
) {
827 assert_return(rtnl
, -EINVAL
);
828 assert_return(rtnl
->event
, -ENXIO
);
830 rtnl
->io_event_source
= sd_event_source_unref(rtnl
->io_event_source
);
832 rtnl
->time_event_source
= sd_event_source_unref(rtnl
->time_event_source
);
834 rtnl
->event
= sd_event_unref(rtnl
->event
);
839 int sd_netlink_add_match(sd_netlink
*rtnl
,
841 sd_netlink_message_handler_t callback
,
843 _cleanup_free_
struct match_callback
*c
= NULL
;
846 assert_return(rtnl
, -EINVAL
);
847 assert_return(callback
, -EINVAL
);
848 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
850 c
= new0(struct match_callback
, 1);
854 c
->callback
= callback
;
856 c
->userdata
= userdata
;
861 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_LINK
);
868 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_IPV4_IFADDR
);
872 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_IPV6_IFADDR
);
879 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_IPV4_ROUTE
);
883 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_IPV6_ROUTE
);
891 LIST_PREPEND(match_callbacks
, rtnl
->match_callbacks
, c
);
898 int sd_netlink_remove_match(sd_netlink
*rtnl
,
900 sd_netlink_message_handler_t callback
,
902 struct match_callback
*c
;
905 assert_return(rtnl
, -EINVAL
);
906 assert_return(callback
, -EINVAL
);
907 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
909 LIST_FOREACH(match_callbacks
, c
, rtnl
->match_callbacks
)
910 if (c
->callback
== callback
&& c
->type
== type
&& c
->userdata
== userdata
) {
911 LIST_REMOVE(match_callbacks
, rtnl
->match_callbacks
, c
);
917 r
= socket_broadcast_group_unref(rtnl
, RTNLGRP_LINK
);
924 r
= socket_broadcast_group_unref(rtnl
, RTNLGRP_IPV4_IFADDR
);
928 r
= socket_broadcast_group_unref(rtnl
, RTNLGRP_IPV6_IFADDR
);
935 r
= socket_broadcast_group_unref(rtnl
, RTNLGRP_IPV4_ROUTE
);
939 r
= socket_broadcast_group_unref(rtnl
, RTNLGRP_IPV6_ROUTE
);