timestamped_socket/
networkaddress.rs1use std::{
2 net::{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: 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}
33
34pub trait MulticastJoinable: NetworkAddress + SealedMC {
35 #[doc(hidden)]
36 fn join_multicast(
37 &self,
38 socket: RawFd,
39 interface: InterfaceName,
40 _token: PrivateToken,
41 ) -> std::io::Result<()>;
42 #[doc(hidden)]
43 fn leave_multicast(
44 &self,
45 socket: RawFd,
46 interface: InterfaceName,
47 _token: PrivateToken,
48 ) -> std::io::Result<()>;
49}
50
51impl SealedNA for SocketAddrV4 {}
52
53impl NetworkAddress for SocketAddrV4 {
54 fn to_sockaddr(&self, _token: PrivateToken) -> libc::sockaddr_storage {
55 const _: () = assert!(
56 std::mem::size_of::<libc::sockaddr_storage>()
57 >= std::mem::size_of::<libc::sockaddr_in>()
58 );
59 const _: () = assert!(
60 std::mem::align_of::<libc::sockaddr_storage>()
61 >= std::mem::align_of::<libc::sockaddr_in>()
62 );
63
64 let mut result = zeroed_sockaddr_storage();
65 let out = unsafe { &mut (*(&mut result as *mut _ as *mut libc::sockaddr_in)) };
69 out.sin_family = libc::AF_INET as _;
70 out.sin_port = u16::from_ne_bytes(self.port().to_be_bytes());
71 out.sin_addr = libc::in_addr {
72 s_addr: u32::from_ne_bytes(self.ip().octets()),
73 };
74
75 result
76 }
77
78 fn from_sockaddr(addr: libc::sockaddr_storage, _token: PrivateToken) -> Option<Self> {
79 const _: () = assert!(
80 std::mem::size_of::<libc::sockaddr_storage>()
81 >= std::mem::size_of::<libc::sockaddr_in>()
82 );
83 const _: () = assert!(
84 std::mem::align_of::<libc::sockaddr_storage>()
85 >= std::mem::align_of::<libc::sockaddr_in>()
86 );
87
88 if addr.ss_family != libc::AF_INET as _ {
89 return None;
90 }
91
92 let input = unsafe { &(*(&addr as *const _ as *const libc::sockaddr_in)) };
96 Some(SocketAddrV4::new(
97 Ipv4Addr::from(input.sin_addr.s_addr.to_ne_bytes()),
98 u16::from_be_bytes(input.sin_port.to_ne_bytes()),
99 ))
100 }
101}
102
103impl SealedNA for SocketAddrV6 {}
104
105impl NetworkAddress for SocketAddrV6 {
106 fn to_sockaddr(&self, _token: PrivateToken) -> libc::sockaddr_storage {
107 const _: () = assert!(
108 std::mem::size_of::<libc::sockaddr_storage>()
109 >= std::mem::size_of::<libc::sockaddr_in6>()
110 );
111 const _: () = assert!(
112 std::mem::align_of::<libc::sockaddr_storage>()
113 >= std::mem::align_of::<libc::sockaddr_in6>()
114 );
115
116 let mut result = zeroed_sockaddr_storage();
117 let out = unsafe { &mut (*(&mut result as *mut _ as *mut libc::sockaddr_in6)) };
121 out.sin6_family = libc::AF_INET6 as _;
122 out.sin6_port = u16::from_ne_bytes(self.port().to_be_bytes());
123 out.sin6_addr = libc::in6_addr {
124 s6_addr: self.ip().octets(),
125 };
126 out.sin6_flowinfo = self.flowinfo();
127 out.sin6_scope_id = self.scope_id();
128
129 result
130 }
131
132 fn from_sockaddr(addr: libc::sockaddr_storage, _token: PrivateToken) -> Option<Self> {
133 const _: () = assert!(
134 std::mem::size_of::<libc::sockaddr_storage>()
135 >= std::mem::size_of::<libc::sockaddr_in6>()
136 );
137 const _: () = assert!(
138 std::mem::align_of::<libc::sockaddr_storage>()
139 >= std::mem::align_of::<libc::sockaddr_in6>()
140 );
141
142 if addr.ss_family != libc::AF_INET6 as _ {
143 return None;
144 }
145
146 let input = unsafe { &(*(&addr as *const _ as *const libc::sockaddr_in6)) };
150 Some(SocketAddrV6::new(
151 Ipv6Addr::from(input.sin6_addr.s6_addr),
152 u16::from_be_bytes(input.sin6_port.to_ne_bytes()),
153 input.sin6_flowinfo,
154 input.sin6_scope_id,
155 ))
156 }
157}
158
159impl SealedNA for SocketAddr {}
160
161impl NetworkAddress for SocketAddr {
162 fn to_sockaddr(&self, _token: PrivateToken) -> libc::sockaddr_storage {
163 match self {
164 SocketAddr::V4(addr) => addr.to_sockaddr(PrivateToken),
165 SocketAddr::V6(addr) => addr.to_sockaddr(PrivateToken),
166 }
167 }
168
169 fn from_sockaddr(addr: libc::sockaddr_storage, _token: PrivateToken) -> Option<Self> {
170 match addr.ss_family as _ {
171 libc::AF_INET => Some(SocketAddr::V4(SocketAddrV4::from_sockaddr(
172 addr,
173 PrivateToken,
174 )?)),
175 libc::AF_INET6 => Some(SocketAddr::V6(SocketAddrV6::from_sockaddr(
176 addr,
177 PrivateToken,
178 )?)),
179 _ => None,
180 }
181 }
182}