use core::mem;
use core::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
use core::ptr;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct sockaddr {
pub sa_family: u16,
pub sa_data: [u8; 14],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct sockaddr_in {
pub sin_family: u16,
pub sin_port: u16,
pub sin_addr: in_addr,
pub sin_zero: [u8; 8],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
pub sin6_family: u16,
pub sin6_port: u16,
pub sin6_flowinfo: u32,
pub sin6_addr: in6_addr,
pub sin6_scope_id: u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union SocketAddrStorage {
pub sa: sockaddr,
pub sin: sockaddr_in,
pub sin6: sockaddr_in6,
pub storage: [u8; 128], }
pub const AF_INET: u16 = 2;
pub const AF_INET6: u16 = 10;
impl SocketAddrStorage {
pub const fn new() -> Self {
Self { storage: [0; 128] }
}
pub fn from_socket_addr(addr: SocketAddr) -> (Self, usize) {
let mut storage = Self::new();
match addr {
SocketAddr::V4(v4) => {
let sin = sockaddr_in {
sin_family: AF_INET,
sin_port: v4.port().to_be(),
sin_addr: in_addr {
s_addr: u32::from_ne_bytes(v4.ip().octets()),
},
sin_zero: [0; 8],
};
storage.sin = sin;
(storage, mem::size_of::<sockaddr_in>())
}
SocketAddr::V6(v6) => {
let sin6 = sockaddr_in6 {
sin6_family: AF_INET6,
sin6_port: v6.port().to_be(),
sin6_flowinfo: v6.flowinfo(),
sin6_addr: in6_addr {
s6_addr: v6.ip().octets(),
},
sin6_scope_id: v6.scope_id(),
};
storage.sin6 = sin6;
(storage, mem::size_of::<sockaddr_in6>())
}
}
}
pub fn to_socket_addr(&self, len: usize) -> Option<SocketAddr> {
unsafe {
match self.sa.sa_family {
AF_INET if len >= mem::size_of::<sockaddr_in>() => {
let sin = &self.sin;
let ip = Ipv4Addr::from(sin.sin_addr.s_addr.to_ne_bytes());
let port = u16::from_be(sin.sin_port);
Some(SocketAddr::V4(SocketAddrV4::new(ip, port)))
}
AF_INET6 if len >= mem::size_of::<sockaddr_in6>() => {
let sin6 = &self.sin6;
let ip = Ipv6Addr::from(sin6.sin6_addr.s6_addr);
let port = u16::from_be(sin6.sin6_port);
Some(SocketAddr::V6(SocketAddrV6::new(
ip,
port,
sin6.sin6_flowinfo,
sin6.sin6_scope_id,
)))
}
_ => None,
}
}
}
pub fn as_ptr(&self) -> *const sockaddr {
unsafe { &self.sa as *const sockaddr }
}
pub fn as_mut_ptr(&mut self) -> *mut sockaddr {
unsafe { &mut self.sa as *mut sockaddr }
}
}
#[repr(C)]
pub struct MsgHdr {
pub msg_name: *mut u8, pub msg_namelen: u32, pub msg_iov: *mut IoVec, pub msg_iovlen: usize, pub msg_control: *mut u8, pub msg_controllen: usize, pub msg_flags: i32, }
#[repr(C)]
pub struct IoVec {
pub iov_base: *mut u8,
pub iov_len: usize,
}
impl MsgHdr {
pub fn new() -> Self {
Self {
msg_name: ptr::null_mut(),
msg_namelen: 0,
msg_iov: ptr::null_mut(),
msg_iovlen: 0,
msg_control: ptr::null_mut(),
msg_controllen: 0,
msg_flags: 0,
}
}
pub fn with_addr_and_iov(
addr: &mut SocketAddrStorage,
addr_len: &mut u32,
iov: &mut [IoVec],
) -> Self {
Self {
msg_name: addr as *mut _ as *mut u8,
msg_namelen: *addr_len,
msg_iov: iov.as_mut_ptr(),
msg_iovlen: iov.len(),
msg_control: ptr::null_mut(),
msg_controllen: 0,
msg_flags: 0,
}
}
}
pub fn socket_addr_to_dual_stack(addr: SocketAddr) -> (SocketAddrStorage, usize) {
match addr {
SocketAddr::V4(v4) => {
let octets = v4.ip().octets();
let ipv6_mapped = Ipv6Addr::new(
0,
0,
0,
0,
0,
0xffff,
u16::from_be_bytes([octets[0], octets[1]]),
u16::from_be_bytes([octets[2], octets[3]]),
);
let v6_addr = SocketAddrV6::new(ipv6_mapped, v4.port(), 0, 0);
SocketAddrStorage::from_socket_addr(SocketAddr::V6(v6_addr))
}
SocketAddr::V6(_) => SocketAddrStorage::from_socket_addr(addr),
}
}