socket9 0.1.0-alpha.1

Extended untilities for the networking/unix sockets and raw network sockets
Documentation
/*-
 * socket9 - A RAW networking sockets manipulation and configration basing on 
 * strong types.
 * 
 * Copyright (C) 2021 Aleksandr Morozov, Lucia Hoffmann
 * Copyright (C) 2025 Aleksandr Morozov
 * 
 * The syslog-rs crate can be redistributed and/or modified
 * under the terms of either of the following licenses:
 *
 *   1. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016 OR
 *
 *   2. the Mozilla Public License Version 2.0 (the “MPL”) OR
 *                     
 *   3. The MIT License (MIT)
 */

 
use std::{ffi::c_int, fmt, io::{self, ErrorKind}, net::{IpAddr, Ipv6Addr, SocketAddr}};

use crate::{AF_INET6, IP6T_SO_ORIGINAL_DST, LocalFrom, OptRMarker, SOL_IPV6, SockOptMarker, sa_family_t, sockaddr_in6, in6_addr};



//nat rdr
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct SoIp6OriginalDst(sockaddr_in6);

#[cfg(unix)]
impl fmt::Debug for SoIp6OriginalDst
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
    {
        f.debug_tuple("SoIp6OriginalDst").field(&self.0).finish()
    }
}

#[cfg(windows)]
impl fmt::Debug for SoIp6OriginalDst
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
    {
        f.debug_tuple("SoIp6OriginalDst").finish()
    }
}

impl SockOptMarker for SoIp6OriginalDst 
{
    const SO_LEVEL: c_int = SOL_IPV6 as i32;   
    const SO_OPTNAME: c_int = IP6T_SO_ORIGINAL_DST as i32;

    type DataType = io::Result<SocketAddr>;
    type InputType = sockaddr_in6;

    #[inline]
    fn from(value: Self::InputType) -> Self 
    {
        return Self(value);
    }

    #[inline]
    fn get(self) -> Self::DataType
    {
        if self.0.sin6_family != AF_INET6 as sa_family_t
        {
            return Err(
                io::Error::new(ErrorKind::Other, 
                    format!("expected IPv6, received sin_family: {}", self.0.sin6_family))
            );
        }

        let ipv6 = <Ipv6Addr as LocalFrom<in6_addr>>::from(self.0.sin6_addr);
        
        return Ok(SocketAddr::new(IpAddr::V6(ipv6), self.0.sin6_port));
    }

    #[inline]
    fn from_user(_: Self::DataType) -> Self where Self: Sized
    {
        panic!("SoIp6OriginalDst cannot write!");
    }
}

impl OptRMarker for SoIp6OriginalDst {}