1#![allow(unreachable_patterns)]
2
3use std::net::{Ipv4Addr, Ipv6Addr};
4
5use futures::TryStreamExt;
6
7use ftth_common::channel::{AsyncWorldClient, AsyncWorldServer};
8
9pub(crate) type Client = AsyncWorldClient<RtnlAddressRequest, RtnlAddressResponse>;
10pub(crate) type Server = AsyncWorldServer<RtnlAddressRequest, RtnlAddressResponse>;
11
12#[derive(Debug, Clone, PartialEq)]
13#[non_exhaustive]
14pub enum RtnlAddressRequest {
15 Ipv4AddrsGet {
16 if_id: u32,
17 },
18 Ipv6AddrsGet {
19 if_id: u32,
20 },
21 Ipv4AddrSet {
22 prefix: crate::Ipv4Net,
23 if_id: u32,
24 },
25 Ipv6AddrSet {
26 prefix: crate::Ipv6Net,
27 if_id: u32,
28 },
29 Ipv4AddrDel {
30 prefix: crate::Ipv4Net,
31 if_id: u32,
32 },
33 Ipv6AddrDel {
34 prefix: crate::Ipv6Net,
35 if_id: u32,
36 },
37}
38
39#[derive(Debug, Clone, PartialEq)]
40#[non_exhaustive]
41pub enum RtnlAddressResponse {
42 Success,
43 Failed,
44 NotImplemented,
45 NotFound,
46 Ipv4Addrs(Vec<Ipv4Addr>),
47 Ipv6Addrs(Vec<Ipv6Addr>),
48}
49
50#[derive(Debug, Clone, PartialEq, Eq, Hash)]
51pub struct RtnlAddressClient {
52 client: Client,
53}
54
55impl RtnlAddressClient {
56 pub(crate) fn new(client: Client) -> Self {
57 Self {
58 client,
59 }
60 }
61
62 pub fn ipv4_addrs_get(&self, if_id: Option<u32>) -> std::io::Result<Vec<Ipv4Addr>> {
63 let res = self.client.send_request(RtnlAddressRequest::Ipv4AddrsGet { if_id: if_id.unwrap_or(0) })?;
64 match res {
65 RtnlAddressResponse::Ipv4Addrs(addrs) => {
66 return Ok(addrs);
67 },
68 _ => {},
69 }
70 Err(std::io::Error::other("Failed to get IPv4 addresses"))
71 }
72
73 pub fn ipv6_addrs_get(&self, if_id: Option<u32>) -> std::io::Result<Vec<Ipv6Addr>> {
74 let res = self.client.send_request(RtnlAddressRequest::Ipv6AddrsGet { if_id: if_id.unwrap_or(0) })?;
75 match res {
76 RtnlAddressResponse::Ipv6Addrs(addrs) => {
77 return Ok(addrs);
78 },
79 _ => {},
80 }
81 Err(std::io::Error::other("Failed to get IPv6 addresses"))
82 }
83}
84
85pub(crate) async fn run_server(mut server: Server, handle: rtnetlink::AddressHandle) {
86 while let Some((req, respond)) = server.accept().await {
87 match req {
88 RtnlAddressRequest::Ipv4AddrsGet { if_id } => {
89 let if_index = if_id;
90 let mut addrs = Vec::new();
91 let mut req = handle.get();
92 if if_index != 0 {
93 req = req.set_link_index_filter(if_index);
94 }
95 let response = req.execute();
96
97 futures::pin_mut!(response);
98 while let Ok(Some(response)) = response.try_next().await {
99 if response.header.family != netlink_packet_route::AddressFamily::Inet {
100 continue;
101 }
102 for addr in response.attributes.iter() {
103 if let netlink_packet_route::address::AddressAttribute::Address(std::net::IpAddr::V4(addr)) = addr {
104 addrs.push(*addr);
105 }
106 }
107 }
108 respond(RtnlAddressResponse::Ipv4Addrs(addrs));
109 },
110 RtnlAddressRequest::Ipv6AddrsGet { if_id } => {
111 let if_index = if_id;
112 let mut addrs = Vec::new();
113 let mut req = handle.get();
114 if if_index != 0 {
115 req = req.set_link_index_filter(if_index);
116 }
117 let response = req.execute();
118
119 futures::pin_mut!(response);
120 while let Ok(Some(response)) = response.try_next().await {
121 if response.header.family != netlink_packet_route::AddressFamily::Inet6 {
122 continue;
123 }
124 for addr in response.attributes.iter() {
125 if let netlink_packet_route::address::AddressAttribute::Address(std::net::IpAddr::V6(addr)) = addr {
126 addrs.push(*addr);
127 }
128 }
129 }
130 respond(RtnlAddressResponse::Ipv6Addrs(addrs));
131 },
132 _ => respond(RtnlAddressResponse::NotImplemented),
133 }
134 }
135}