rtnetlink/
connection.rs

1// SPDX-License-Identifier: MIT
2
3use std::io;
4
5use futures_channel::mpsc::UnboundedReceiver;
6use netlink_packet_core::NetlinkMessage;
7use netlink_packet_route::RouteNetlinkMessage;
8use netlink_proto::Connection;
9use netlink_sys::{protocols::NETLINK_ROUTE, AsyncSocket, SocketAddr};
10
11use crate::{Handle, MulticastGroup};
12
13#[cfg(feature = "tokio_socket")]
14#[allow(clippy::type_complexity)]
15pub fn new_connection() -> io::Result<(
16    Connection<RouteNetlinkMessage>,
17    Handle,
18    UnboundedReceiver<(NetlinkMessage<RouteNetlinkMessage>, SocketAddr)>,
19)> {
20    new_connection_with_socket()
21}
22
23/// Equal to `ip monitor` command
24#[cfg(feature = "tokio_socket")]
25#[allow(clippy::type_complexity)]
26pub fn new_multicast_connection(
27    groups: &[MulticastGroup],
28) -> io::Result<(
29    Connection<RouteNetlinkMessage>,
30    Handle,
31    UnboundedReceiver<(NetlinkMessage<RouteNetlinkMessage>, SocketAddr)>,
32)> {
33    new_multicast_connection_with_socket(groups)
34}
35
36#[allow(clippy::type_complexity)]
37pub fn new_connection_with_socket<S>() -> io::Result<(
38    Connection<RouteNetlinkMessage, S>,
39    Handle,
40    UnboundedReceiver<(NetlinkMessage<RouteNetlinkMessage>, SocketAddr)>,
41)>
42where
43    S: AsyncSocket,
44{
45    let (conn, handle, messages) =
46        netlink_proto::new_connection_with_socket(NETLINK_ROUTE)?;
47    Ok((conn, Handle::new(handle), messages))
48}
49
50/// Equal to `ip monitor` command
51#[allow(clippy::type_complexity)]
52pub fn new_multicast_connection_with_socket<S>(
53    groups: &[MulticastGroup],
54) -> io::Result<(
55    Connection<RouteNetlinkMessage, S>,
56    Handle,
57    UnboundedReceiver<(NetlinkMessage<RouteNetlinkMessage>, SocketAddr)>,
58)>
59where
60    S: AsyncSocket,
61{
62    let (mut conn, handle, messages) =
63        netlink_proto::new_connection_with_socket::<RouteNetlinkMessage, S>(
64            NETLINK_ROUTE,
65        )?;
66    let mut all_groups: u32 = 0;
67    for group in groups.iter().filter(|g| !g.need_via_add_membership()) {
68        all_groups |= 1 << (*group as u32 - 1);
69    }
70
71    let addr = SocketAddr::new(0, all_groups);
72    conn.socket_mut().socket_mut().bind(&addr)?;
73
74    for group in groups.iter().filter(|g| g.need_via_add_membership()) {
75        conn.socket_mut()
76            .socket_mut()
77            .add_membership(*group as u32)?;
78    }
79
80    Ok((conn, Handle::new(handle), messages))
81}
82
83#[allow(clippy::type_complexity)]
84pub fn from_socket<S>(
85    socket: S,
86) -> (
87    Connection<RouteNetlinkMessage, S>,
88    Handle,
89    UnboundedReceiver<(NetlinkMessage<RouteNetlinkMessage>, SocketAddr)>,
90)
91where
92    S: AsyncSocket,
93{
94    let (conn, handle, messages) =
95        netlink_proto::from_socket_with_codec(socket);
96    (conn, Handle::new(handle), messages)
97}