tcp_ip 0.1.10

User-space TCP/IP stack
Documentation
use std::io;
use std::net::IpAddr;
use std::ops::Deref;

use pnet_packet::ip::IpNextHeaderProtocols;

use crate::ip::IpSocket;
use crate::ip_stack::{IpStack, UNSPECIFIED_ADDR_V4, UNSPECIFIED_ADDR_V6};

pub struct IcmpSocket {
    raw_ip_socket: IpSocket,
}
#[cfg(feature = "global-ip-stack")]
impl IcmpSocket {
    pub async fn bind_all() -> io::Result<Self> {
        Self::bind(UNSPECIFIED_ADDR_V4.ip()).await
    }
    pub async fn bind(local_ip: IpAddr) -> io::Result<Self> {
        if local_ip.is_ipv6() {
            return Err(io::Error::new(io::ErrorKind::Unsupported, "need to use IcmpV6Socket"));
        }
        let ip_stack = IpStack::get()?;
        let raw_ip_socket = IpSocket::bind0(
            ip_stack.config.icmp_channel_size,
            Some(IpNextHeaderProtocols::Icmp),
            ip_stack,
            Some(local_ip),
        )
        .await?;
        Ok(Self { raw_ip_socket })
    }
}
#[cfg(not(feature = "global-ip-stack"))]
impl IcmpSocket {
    pub async fn bind_all(ip_stack: IpStack) -> io::Result<Self> {
        Self::bind(ip_stack, UNSPECIFIED_ADDR_V4.ip()).await
    }
    pub async fn bind(ip_stack: IpStack, local_ip: IpAddr) -> io::Result<Self> {
        if local_ip.is_ipv6() {
            return Err(io::Error::new(io::ErrorKind::Unsupported, "need to use IcmpV6Socket"));
        }
        let raw_ip_socket = IpSocket::bind0(
            ip_stack.config.icmp_channel_size,
            Some(IpNextHeaderProtocols::Icmp),
            ip_stack,
            Some(local_ip),
        )
        .await?;
        Ok(Self { raw_ip_socket })
    }
}

impl Deref for IcmpSocket {
    type Target = IpSocket;

    fn deref(&self) -> &Self::Target {
        &self.raw_ip_socket
    }
}

pub struct IcmpV6Socket {
    raw_ip_socket: IpSocket,
}
#[cfg(feature = "global-ip-stack")]
impl IcmpV6Socket {
    pub async fn bind_all() -> io::Result<Self> {
        Self::bind(UNSPECIFIED_ADDR_V6.ip()).await
    }
    pub async fn bind(local_ip: IpAddr) -> io::Result<Self> {
        if local_ip.is_ipv4() {
            return Err(io::Error::new(io::ErrorKind::Unsupported, "need to use IcmpSocket"));
        }
        let ip_stack = IpStack::get()?;
        let raw_ip_socket = IpSocket::bind0(
            ip_stack.config.icmp_channel_size,
            Some(IpNextHeaderProtocols::Icmpv6),
            ip_stack,
            Some(local_ip),
        )
        .await?;
        Ok(Self { raw_ip_socket })
    }
}
#[cfg(not(feature = "global-ip-stack"))]
impl IcmpV6Socket {
    pub async fn bind_all(ip_stack: IpStack) -> io::Result<Self> {
        Self::bind(ip_stack, UNSPECIFIED_ADDR_V6.ip()).await
    }
    pub async fn bind(ip_stack: IpStack, local_ip: IpAddr) -> io::Result<Self> {
        if local_ip.is_ipv4() {
            return Err(io::Error::new(io::ErrorKind::Unsupported, "need to use IcmpSocket"));
        }
        let raw_ip_socket = IpSocket::bind0(
            ip_stack.config.icmp_channel_size,
            Some(IpNextHeaderProtocols::Icmpv6),
            ip_stack,
            Some(local_ip),
        )
        .await?;
        Ok(Self { raw_ip_socket })
    }
}

impl Deref for IcmpV6Socket {
    type Target = IpSocket;

    fn deref(&self) -> &Self::Target {
        &self.raw_ip_socket
    }
}