1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "sd-netlink.h"
7 #include "alloc-util.h"
11 #include "netlink-internal.h"
12 #include "netlink-slot.h"
13 #include "netlink-util.h"
14 #include "process-util.h"
15 #include "socket-util.h"
16 #include "string-util.h"
19 static int sd_netlink_new(sd_netlink
**ret
) {
20 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
22 assert_return(ret
, -EINVAL
);
24 rtnl
= new(sd_netlink
, 1);
28 *rtnl
= (sd_netlink
) {
31 .sockaddr
.nl
.nl_family
= AF_NETLINK
,
32 .original_pid
= getpid_cached(),
35 /* Change notification responses have sequence 0, so we must
36 * start our request sequence numbers at 1, or we may confuse our
37 * responses with notifications from the kernel */
42 /* We guarantee that the read buffer has at least space for
44 if (!greedy_realloc((void**)&rtnl
->rbuffer
, &rtnl
->rbuffer_allocated
,
45 sizeof(struct nlmsghdr
), sizeof(uint8_t)))
48 *ret
= TAKE_PTR(rtnl
);
53 int sd_netlink_new_from_netlink(sd_netlink
**ret
, int fd
) {
54 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
58 assert_return(ret
, -EINVAL
);
60 r
= sd_netlink_new(&rtnl
);
64 addrlen
= sizeof(rtnl
->sockaddr
);
66 r
= getsockname(fd
, &rtnl
->sockaddr
.sa
, &addrlen
);
70 if (rtnl
->sockaddr
.nl
.nl_family
!= AF_NETLINK
)
75 *ret
= TAKE_PTR(rtnl
);
80 static bool rtnl_pid_changed(const sd_netlink
*rtnl
) {
83 /* We don't support people creating an rtnl connection and
84 * keeping it around over a fork(). Let's complain. */
86 return rtnl
->original_pid
!= getpid_cached();
89 int sd_netlink_open_fd(sd_netlink
**ret
, int fd
) {
90 _cleanup_(sd_netlink_unrefp
) sd_netlink
*rtnl
= NULL
;
95 assert_return(ret
, -EINVAL
);
96 assert_return(fd
>= 0, -EBADF
);
98 r
= sd_netlink_new(&rtnl
);
102 l
= sizeof(protocol
);
103 r
= getsockopt(fd
, SOL_SOCKET
, SO_PROTOCOL
, &protocol
, &l
);
108 rtnl
->protocol
= protocol
;
110 r
= socket_bind(rtnl
);
112 rtnl
->fd
= -1; /* on failure, the caller remains owner of the fd, hence don't close it here */
117 *ret
= TAKE_PTR(rtnl
);
122 int netlink_open_family(sd_netlink
**ret
, int family
) {
123 _cleanup_close_
int fd
= -1;
126 fd
= socket_open(family
);
130 r
= sd_netlink_open_fd(ret
, fd
);
139 int sd_netlink_open(sd_netlink
**ret
) {
140 return netlink_open_family(ret
, NETLINK_ROUTE
);
143 int sd_netlink_inc_rcvbuf(sd_netlink
*rtnl
, size_t size
) {
144 assert_return(rtnl
, -EINVAL
);
145 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
147 return fd_inc_rcvbuf(rtnl
->fd
, size
);
150 static sd_netlink
*netlink_free(sd_netlink
*rtnl
) {
156 for (i
= 0; i
< rtnl
->rqueue_size
; i
++)
157 sd_netlink_message_unref(rtnl
->rqueue
[i
]);
160 for (i
= 0; i
< rtnl
->rqueue_partial_size
; i
++)
161 sd_netlink_message_unref(rtnl
->rqueue_partial
[i
]);
162 free(rtnl
->rqueue_partial
);
166 while ((s
= rtnl
->slots
)) {
168 netlink_slot_disconnect(s
, true);
170 hashmap_free(rtnl
->reply_callbacks
);
171 prioq_free(rtnl
->reply_callbacks_prioq
);
173 sd_event_source_unref(rtnl
->io_event_source
);
174 sd_event_source_unref(rtnl
->time_event_source
);
175 sd_event_unref(rtnl
->event
);
177 hashmap_free(rtnl
->broadcast_group_refs
);
179 hashmap_free(rtnl
->genl_family_to_nlmsg_type
);
180 hashmap_free(rtnl
->nlmsg_type_to_genl_family
);
182 safe_close(rtnl
->fd
);
186 DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_netlink
, sd_netlink
, netlink_free
);
188 static void rtnl_seal_message(sd_netlink
*rtnl
, sd_netlink_message
*m
) {
190 assert(!rtnl_pid_changed(rtnl
));
194 /* don't use seq == 0, as that is used for broadcasts, so we
195 would get confused by replies to such messages */
196 m
->hdr
->nlmsg_seq
= rtnl
->serial
++ ? : rtnl
->serial
++;
198 rtnl_message_seal(m
);
203 int sd_netlink_send(sd_netlink
*nl
,
204 sd_netlink_message
*message
,
208 assert_return(nl
, -EINVAL
);
209 assert_return(!rtnl_pid_changed(nl
), -ECHILD
);
210 assert_return(message
, -EINVAL
);
211 assert_return(!message
->sealed
, -EPERM
);
213 rtnl_seal_message(nl
, message
);
215 r
= socket_write_message(nl
, message
);
220 *serial
= rtnl_message_get_serial(message
);
225 int rtnl_rqueue_make_room(sd_netlink
*rtnl
) {
228 if (rtnl
->rqueue_size
>= RTNL_RQUEUE_MAX
)
229 return log_debug_errno(SYNTHETIC_ERRNO(ENOBUFS
),
230 "rtnl: exhausted the read queue size (%d)",
233 if (!GREEDY_REALLOC(rtnl
->rqueue
, rtnl
->rqueue_allocated
, rtnl
->rqueue_size
+ 1))
239 int rtnl_rqueue_partial_make_room(sd_netlink
*rtnl
) {
242 if (rtnl
->rqueue_partial_size
>= RTNL_RQUEUE_MAX
)
243 return log_debug_errno(SYNTHETIC_ERRNO(ENOBUFS
),
244 "rtnl: exhausted the partial read queue size (%d)",
247 if (!GREEDY_REALLOC(rtnl
->rqueue_partial
, rtnl
->rqueue_partial_allocated
,
248 rtnl
->rqueue_partial_size
+ 1))
254 static int dispatch_rqueue(sd_netlink
*rtnl
, sd_netlink_message
**message
) {
260 if (rtnl
->rqueue_size
<= 0) {
261 /* Try to read a new message */
262 r
= socket_read_message(rtnl
);
263 if (r
== -ENOBUFS
) { /* FIXME: ignore buffer overruns for now */
264 log_debug_errno(r
, "Got ENOBUFS from netlink socket, ignoring.");
271 /* Dispatch a queued message */
272 *message
= rtnl
->rqueue
[0];
274 memmove(rtnl
->rqueue
, rtnl
->rqueue
+ 1, sizeof(sd_netlink_message
*) * rtnl
->rqueue_size
);
279 static int process_timeout(sd_netlink
*rtnl
) {
280 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
281 struct reply_callback
*c
;
282 sd_netlink_slot
*slot
;
288 c
= prioq_peek(rtnl
->reply_callbacks_prioq
);
292 n
= now(CLOCK_MONOTONIC
);
296 r
= rtnl_message_new_synthetic_error(rtnl
, -ETIMEDOUT
, c
->serial
, &m
);
300 assert_se(prioq_pop(rtnl
->reply_callbacks_prioq
) == c
);
302 hashmap_remove(rtnl
->reply_callbacks
, &c
->serial
);
304 slot
= container_of(c
, sd_netlink_slot
, reply_callback
);
306 r
= c
->callback(rtnl
, m
, slot
->userdata
);
308 log_debug_errno(r
, "sd-netlink: timedout callback %s%s%sfailed: %m",
309 slot
->description
? "'" : "",
310 strempty(slot
->description
),
311 slot
->description
? "' " : "");
314 netlink_slot_disconnect(slot
, true);
319 static int process_reply(sd_netlink
*rtnl
, sd_netlink_message
*m
) {
320 struct reply_callback
*c
;
321 sd_netlink_slot
*slot
;
329 serial
= rtnl_message_get_serial(m
);
330 c
= hashmap_remove(rtnl
->reply_callbacks
, &serial
);
334 if (c
->timeout
!= 0) {
335 prioq_remove(rtnl
->reply_callbacks_prioq
, c
, &c
->prioq_idx
);
339 r
= sd_netlink_message_get_type(m
, &type
);
343 if (type
== NLMSG_DONE
)
346 slot
= container_of(c
, sd_netlink_slot
, reply_callback
);
348 r
= c
->callback(rtnl
, m
, slot
->userdata
);
350 log_debug_errno(r
, "sd-netlink: reply callback %s%s%sfailed: %m",
351 slot
->description
? "'" : "",
352 strempty(slot
->description
),
353 slot
->description
? "' " : "");
356 netlink_slot_disconnect(slot
, true);
361 static int process_match(sd_netlink
*rtnl
, sd_netlink_message
*m
) {
362 struct match_callback
*c
;
363 sd_netlink_slot
*slot
;
370 r
= sd_netlink_message_get_type(m
, &type
);
374 LIST_FOREACH(match_callbacks
, c
, rtnl
->match_callbacks
) {
375 if (type
== c
->type
) {
376 slot
= container_of(c
, sd_netlink_slot
, match_callback
);
378 r
= c
->callback(rtnl
, m
, slot
->userdata
);
381 log_debug_errno(r
, "sd-netlink: match callback %s%s%sfailed: %m",
382 slot
->description
? "'" : "",
383 strempty(slot
->description
),
384 slot
->description
? "' " : "");
394 static int process_running(sd_netlink
*rtnl
, sd_netlink_message
**ret
) {
395 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*m
= NULL
;
400 r
= process_timeout(rtnl
);
404 r
= dispatch_rqueue(rtnl
, &m
);
410 if (sd_netlink_message_is_broadcast(m
)) {
411 r
= process_match(rtnl
, m
);
415 r
= process_reply(rtnl
, m
);
435 int sd_netlink_process(sd_netlink
*rtnl
, sd_netlink_message
**ret
) {
436 NETLINK_DONT_DESTROY(rtnl
);
439 assert_return(rtnl
, -EINVAL
);
440 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
441 assert_return(!rtnl
->processing
, -EBUSY
);
443 rtnl
->processing
= true;
444 r
= process_running(rtnl
, ret
);
445 rtnl
->processing
= false;
450 static usec_t
calc_elapse(uint64_t usec
) {
451 if (usec
== (uint64_t) -1)
455 usec
= RTNL_DEFAULT_TIMEOUT
;
457 return now(CLOCK_MONOTONIC
) + usec
;
460 static int rtnl_poll(sd_netlink
*rtnl
, bool need_more
, uint64_t timeout_usec
) {
461 struct pollfd p
[1] = {};
463 usec_t m
= USEC_INFINITY
;
468 e
= sd_netlink_get_events(rtnl
);
473 /* Caller wants more data, and doesn't care about
474 * what's been read or any other timeouts. */
478 /* Caller wants to process if there is something to
479 * process, but doesn't care otherwise */
481 r
= sd_netlink_get_timeout(rtnl
, &until
);
486 nw
= now(CLOCK_MONOTONIC
);
487 m
= until
> nw
? until
- nw
: 0;
491 if (timeout_usec
!= (uint64_t) -1 && (m
== (uint64_t) -1 || timeout_usec
< m
))
497 r
= ppoll(p
, 1, m
== (uint64_t) -1 ? NULL
: timespec_store(&ts
, m
), NULL
);
501 return r
> 0 ? 1 : 0;
504 int sd_netlink_wait(sd_netlink
*nl
, uint64_t timeout_usec
) {
505 assert_return(nl
, -EINVAL
);
506 assert_return(!rtnl_pid_changed(nl
), -ECHILD
);
508 if (nl
->rqueue_size
> 0)
511 return rtnl_poll(nl
, false, timeout_usec
);
514 static int timeout_compare(const void *a
, const void *b
) {
515 const struct reply_callback
*x
= a
, *y
= b
;
517 if (x
->timeout
!= 0 && y
->timeout
== 0)
520 if (x
->timeout
== 0 && y
->timeout
!= 0)
523 return CMP(x
->timeout
, y
->timeout
);
526 int sd_netlink_call_async(
528 sd_netlink_slot
**ret_slot
,
529 sd_netlink_message
*m
,
530 sd_netlink_message_handler_t callback
,
531 sd_netlink_destroy_t destroy_callback
,
534 const char *description
) {
535 _cleanup_free_ sd_netlink_slot
*slot
= NULL
;
539 assert_return(nl
, -EINVAL
);
540 assert_return(m
, -EINVAL
);
541 assert_return(callback
, -EINVAL
);
542 assert_return(!rtnl_pid_changed(nl
), -ECHILD
);
544 r
= hashmap_ensure_allocated(&nl
->reply_callbacks
, &uint64_hash_ops
);
548 if (usec
!= (uint64_t) -1) {
549 r
= prioq_ensure_allocated(&nl
->reply_callbacks_prioq
, timeout_compare
);
554 r
= netlink_slot_allocate(nl
, !ret_slot
, NETLINK_REPLY_CALLBACK
, sizeof(struct reply_callback
), userdata
, description
, &slot
);
558 slot
->reply_callback
.callback
= callback
;
559 slot
->reply_callback
.timeout
= calc_elapse(usec
);
561 k
= sd_netlink_send(nl
, m
, &s
);
565 slot
->reply_callback
.serial
= s
;
567 r
= hashmap_put(nl
->reply_callbacks
, &slot
->reply_callback
.serial
, &slot
->reply_callback
);
571 if (slot
->reply_callback
.timeout
!= 0) {
572 r
= prioq_put(nl
->reply_callbacks_prioq
, &slot
->reply_callback
, &slot
->reply_callback
.prioq_idx
);
574 (void) hashmap_remove(nl
->reply_callbacks
, &slot
->reply_callback
.serial
);
579 /* Set this at last. Otherwise, some failures in above call the destroy callback but some do not. */
580 slot
->destroy_callback
= destroy_callback
;
590 int sd_netlink_call(sd_netlink
*rtnl
,
591 sd_netlink_message
*message
,
593 sd_netlink_message
**ret
) {
598 assert_return(rtnl
, -EINVAL
);
599 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
600 assert_return(message
, -EINVAL
);
602 r
= sd_netlink_send(rtnl
, message
, &serial
);
606 timeout
= calc_elapse(usec
);
612 for (i
= 0; i
< rtnl
->rqueue_size
; i
++) {
613 uint32_t received_serial
;
615 received_serial
= rtnl_message_get_serial(rtnl
->rqueue
[i
]);
617 if (received_serial
== serial
) {
618 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*incoming
= NULL
;
621 incoming
= rtnl
->rqueue
[i
];
623 /* found a match, remove from rqueue and return it */
624 memmove(rtnl
->rqueue
+ i
,rtnl
->rqueue
+ i
+ 1,
625 sizeof(sd_netlink_message
*) * (rtnl
->rqueue_size
- i
- 1));
628 r
= sd_netlink_message_get_errno(incoming
);
632 r
= sd_netlink_message_get_type(incoming
, &type
);
636 if (type
== NLMSG_DONE
) {
642 *ret
= TAKE_PTR(incoming
);
648 r
= socket_read_message(rtnl
);
652 /* received message, so try to process straight away */
658 n
= now(CLOCK_MONOTONIC
);
664 left
= (uint64_t) -1;
666 r
= rtnl_poll(rtnl
, true, left
);
674 int sd_netlink_get_events(const sd_netlink
*rtnl
) {
675 assert_return(rtnl
, -EINVAL
);
676 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
678 if (rtnl
->rqueue_size
== 0)
684 int sd_netlink_get_timeout(const sd_netlink
*rtnl
, uint64_t *timeout_usec
) {
685 struct reply_callback
*c
;
687 assert_return(rtnl
, -EINVAL
);
688 assert_return(timeout_usec
, -EINVAL
);
689 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
691 if (rtnl
->rqueue_size
> 0) {
696 c
= prioq_peek(rtnl
->reply_callbacks_prioq
);
698 *timeout_usec
= (uint64_t) -1;
702 *timeout_usec
= c
->timeout
;
707 static int io_callback(sd_event_source
*s
, int fd
, uint32_t revents
, void *userdata
) {
708 sd_netlink
*rtnl
= userdata
;
713 r
= sd_netlink_process(rtnl
, NULL
);
720 static int time_callback(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
721 sd_netlink
*rtnl
= userdata
;
726 r
= sd_netlink_process(rtnl
, NULL
);
733 static int prepare_callback(sd_event_source
*s
, void *userdata
) {
734 sd_netlink
*rtnl
= userdata
;
741 e
= sd_netlink_get_events(rtnl
);
745 r
= sd_event_source_set_io_events(rtnl
->io_event_source
, e
);
749 r
= sd_netlink_get_timeout(rtnl
, &until
);
755 j
= sd_event_source_set_time(rtnl
->time_event_source
, until
);
760 r
= sd_event_source_set_enabled(rtnl
->time_event_source
, r
> 0);
767 int sd_netlink_attach_event(sd_netlink
*rtnl
, sd_event
*event
, int64_t priority
) {
770 assert_return(rtnl
, -EINVAL
);
771 assert_return(!rtnl
->event
, -EBUSY
);
773 assert(!rtnl
->io_event_source
);
774 assert(!rtnl
->time_event_source
);
777 rtnl
->event
= sd_event_ref(event
);
779 r
= sd_event_default(&rtnl
->event
);
784 r
= sd_event_add_io(rtnl
->event
, &rtnl
->io_event_source
, rtnl
->fd
, 0, io_callback
, rtnl
);
788 r
= sd_event_source_set_priority(rtnl
->io_event_source
, priority
);
792 r
= sd_event_source_set_description(rtnl
->io_event_source
, "rtnl-receive-message");
796 r
= sd_event_source_set_prepare(rtnl
->io_event_source
, prepare_callback
);
800 r
= sd_event_add_time(rtnl
->event
, &rtnl
->time_event_source
, CLOCK_MONOTONIC
, 0, 0, time_callback
, rtnl
);
804 r
= sd_event_source_set_priority(rtnl
->time_event_source
, priority
);
808 r
= sd_event_source_set_description(rtnl
->time_event_source
, "rtnl-timer");
815 sd_netlink_detach_event(rtnl
);
819 int sd_netlink_detach_event(sd_netlink
*rtnl
) {
820 assert_return(rtnl
, -EINVAL
);
821 assert_return(rtnl
->event
, -ENXIO
);
823 rtnl
->io_event_source
= sd_event_source_unref(rtnl
->io_event_source
);
825 rtnl
->time_event_source
= sd_event_source_unref(rtnl
->time_event_source
);
827 rtnl
->event
= sd_event_unref(rtnl
->event
);
832 int sd_netlink_add_match(
834 sd_netlink_slot
**ret_slot
,
836 sd_netlink_message_handler_t callback
,
837 sd_netlink_destroy_t destroy_callback
,
839 const char *description
) {
840 _cleanup_free_ sd_netlink_slot
*slot
= NULL
;
843 assert_return(rtnl
, -EINVAL
);
844 assert_return(callback
, -EINVAL
);
845 assert_return(!rtnl_pid_changed(rtnl
), -ECHILD
);
847 r
= netlink_slot_allocate(rtnl
, !ret_slot
, NETLINK_MATCH_CALLBACK
, sizeof(struct match_callback
), userdata
, description
, &slot
);
851 slot
->match_callback
.callback
= callback
;
852 slot
->match_callback
.type
= type
;
857 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_LINK
);
864 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_IPV4_IFADDR
);
868 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_IPV6_IFADDR
);
875 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_NEIGH
);
882 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_IPV4_ROUTE
);
886 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_IPV6_ROUTE
);
892 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_IPV4_RULE
);
896 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_IPV6_RULE
);
902 r
= socket_broadcast_group_ref(rtnl
, RTNLGRP_NEXTHOP
);
911 LIST_PREPEND(match_callbacks
, rtnl
->match_callbacks
, &slot
->match_callback
);
913 /* Set this at last. Otherwise, some failures in above call the destroy callback but some do not. */
914 slot
->destroy_callback
= destroy_callback
;