timestamped_socket/
networkaddress.rs1use std::{
2 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
3 os::fd::RawFd,
4};
5
6use crate::{control_message::zeroed_sockaddr_storage, interface::InterfaceName};
7
8use self::sealed::{PrivateToken, SealedMC, SealedNA};
9
10#[cfg(target_os = "linux")]
11pub use self::linux::*;
12
13#[cfg(target_os = "linux")]
14mod linux;
15
16pub(crate) mod sealed {
17 pub trait SealedNA {}
19
20 pub trait SealedMC {}
22
23 pub struct PrivateToken;
25}
26
27pub trait NetworkAddress: Copy + Sized + SealedNA {
28 #[doc(hidden)]
29 fn to_sockaddr(&self, _token: PrivateToken) -> libc::sockaddr_storage;
30 #[doc(hidden)]
31 fn from_sockaddr(addr: libc::sockaddr_storage, _token: PrivateToken) -> Option<Self>;
32 #[doc(hidden)]
33 fn from_ip_and_port(addr: IpAddr, port: u16) -> Option<Self>;
34 #[doc(hidden)]
35 fn port(&self) -> u16;
36}
37
38pub trait MulticastJoinable: NetworkAddress + SealedMC {
39 #[doc(hidden)]
40 fn join_multicast(
41 &self,
42 socket: RawFd,
43 interface: InterfaceName,
44 _token: PrivateToken,
45 ) -> std::io::Result<()>;
46 #[doc(hidden)]
47 fn leave_multicast(
48 &self,
49 socket: RawFd,
50 interface: InterfaceName,
51 _token: PrivateToken,
52 ) -> std::io::Result<()>;
53}
54
55impl SealedNA for SocketAddrV4 {}
56
57impl NetworkAddress for SocketAddrV4 {
58 fn to_sockaddr(&self, _token: PrivateToken) -> libc::sockaddr_storage {
59 const _: () = assert!(
60 std::mem::size_of::<libc::sockaddr_storage>()
61 >= std::mem::size_of::<libc::sockaddr_in>()
62 );
63 const _: () = assert!(
64 std::mem::align_of::<libc::sockaddr_storage>()
65 >= std::mem::align_of::<libc::sockaddr_in>()
66 );
67
68 let mut result = zeroed_sockaddr_storage();
69 let out = unsafe { &mut (*(&mut result as *mut _ as *mut libc::sockaddr_in)) };
73 out.sin_family = libc::AF_INET as _;
74 out.sin_port = u16::from_ne_bytes(self.port().to_be_bytes());
75 out.sin_addr = libc::in_addr {
76 s_addr: u32::from_ne_bytes(self.ip().octets()),
77 };
78
79 result
80 }
81
82 fn from_sockaddr(addr: libc::sockaddr_storage, _token: PrivateToken) -> Option<Self> {
83 const _: () = assert!(
84 std::mem::size_of::<libc::sockaddr_storage>()
85 >= std::mem::size_of::<libc::sockaddr_in>()
86 );
87 const _: () = assert!(
88 std::mem::align_of::<libc::sockaddr_storage>()
89 >= std::mem::align_of::<libc::sockaddr_in>()
90 );
91
92 if addr.ss_family != libc::AF_INET as _ {
93 return None;
94 }
95
96 let input = unsafe { &(*(&addr as *const _ as *const libc::sockaddr_in)) };
100 Some(SocketAddrV4::new(
101 Ipv4Addr::from(input.sin_addr.s_addr.to_ne_bytes()),
102 u16::from_be_bytes(input.sin_port.to_ne_bytes()),
103 ))
104 }
105
106 fn from_ip_and_port(addr: IpAddr, port: u16) -> Option<Self> {
107 match addr {
108 IpAddr::V4(addr) => Some(SocketAddrV4::new(addr, port)),
109 IpAddr::V6(_) => None,
110 }
111 }
112
113 fn port(&self) -> u16 {
114 self.port()
115 }
116}
117
118impl SealedNA for SocketAddrV6 {}
119
120impl NetworkAddress for SocketAddrV6 {
121 fn to_sockaddr(&self, _token: PrivateToken) -> libc::sockaddr_storage {
122 const _: () = assert!(
123 std::mem::size_of::<libc::sockaddr_storage>()
124 >= std::mem::size_of::<libc::sockaddr_in6>()
125 );
126 const _: () = assert!(
127 std::mem::align_of::<libc::sockaddr_storage>()
128 >= std::mem::align_of::<libc::sockaddr_in6>()
129 );
130
131 let mut result = zeroed_sockaddr_storage();
132 let out = unsafe { &mut (*(&mut result as *mut _ as *mut libc::sockaddr_in6)) };
136 out.sin6_family = libc::AF_INET6 as _;
137 out.sin6_port = u16::from_ne_bytes(self.port().to_be_bytes());
138 out.sin6_addr = libc::in6_addr {
139 s6_addr: self.ip().octets(),
140 };
141 out.sin6_flowinfo = self.flowinfo();
142 out.sin6_scope_id = self.scope_id();
143
144 result
145 }
146
147 fn from_sockaddr(addr: libc::sockaddr_storage, _token: PrivateToken) -> Option<Self> {
148 const _: () = assert!(
149 std::mem::size_of::<libc::sockaddr_storage>()
150 >= std::mem::size_of::<libc::sockaddr_in6>()
151 );
152 const _: () = assert!(
153 std::mem::align_of::<libc::sockaddr_storage>()
154 >= std::mem::align_of::<libc::sockaddr_in6>()
155 );
156
157 if addr.ss_family != libc::AF_INET6 as _ {
158 return None;
159 }
160
161 let input = unsafe { &(*(&addr as *const _ as *const libc::sockaddr_in6)) };
165 Some(SocketAddrV6::new(
166 Ipv6Addr::from(input.sin6_addr.s6_addr),
167 u16::from_be_bytes(input.sin6_port.to_ne_bytes()),
168 input.sin6_flowinfo,
169 input.sin6_scope_id,
170 ))
171 }
172
173 fn from_ip_and_port(addr: IpAddr, port: u16) -> Option<Self> {
174 match addr {
175 IpAddr::V4(_) => None,
176 IpAddr::V6(addr) => Some(SocketAddrV6::new(addr, port, 0, 0)),
177 }
178 }
179
180 fn port(&self) -> u16 {
181 self.port()
182 }
183}
184
185impl SealedNA for SocketAddr {}
186
187impl NetworkAddress for SocketAddr {
188 fn to_sockaddr(&self, _token: PrivateToken) -> libc::sockaddr_storage {
189 match self {
190 SocketAddr::V4(addr) => addr.to_sockaddr(PrivateToken),
191 SocketAddr::V6(addr) => addr.to_sockaddr(PrivateToken),
192 }
193 }
194
195 fn from_sockaddr(addr: libc::sockaddr_storage, _token: PrivateToken) -> Option<Self> {
196 match addr.ss_family as _ {
197 libc::AF_INET => Some(SocketAddr::V4(SocketAddrV4::from_sockaddr(
198 addr,
199 PrivateToken,
200 )?)),
201 libc::AF_INET6 => Some(SocketAddr::V6(SocketAddrV6::from_sockaddr(
202 addr,
203 PrivateToken,
204 )?)),
205 _ => None,
206 }
207 }
208
209 fn from_ip_and_port(addr: IpAddr, port: u16) -> Option<Self> {
210 Some(SocketAddr::new(addr, port))
211 }
212
213 fn port(&self) -> u16 {
214 self.port()
215 }
216}