rd-std 0.1.0

std for rabbit-digger
Documentation
use std::{io, net::SocketAddr};

pub trait OriginAddrExt {
    fn origin_addr(&self) -> io::Result<SocketAddr>;
}

#[cfg(target_os = "linux")]
use std::os::unix::prelude::AsRawFd;

#[cfg(target_os = "linux")]
impl<T: AsRawFd> OriginAddrExt for T {
    fn origin_addr(&self) -> io::Result<SocketAddr> {
        use socket2::SockAddr;

        let fd = self.as_raw_fd();

        unsafe {
            let (_, origin_addr) = SockAddr::init(|origin_addr, origin_addr_len| {
                let ret = if libc::getsockopt(
                    fd,
                    libc::SOL_IP,
                    libc::SO_ORIGINAL_DST,
                    origin_addr as *mut _,
                    origin_addr_len,
                ) == 0
                {
                    0
                } else {
                    libc::getsockopt(
                        fd,
                        libc::SOL_IPV6,
                        libc::IP6T_SO_ORIGINAL_DST,
                        origin_addr as *mut _,
                        origin_addr_len,
                    )
                };
                if ret != 0 {
                    let err = io::Error::last_os_error();
                    return Err(err);
                }
                Ok(())
            })?;
            Ok(origin_addr.as_socket().expect("SocketAddr"))
        }
    }
}