#[allow(unused_imports)]
use alloc::vec::Vec;
use core::cmp::PartialEq;
use core::convert::Infallible as Never;
use core::fmt::{Debug, Display};
use core::hash::Hash;
use net_types::ip::{GenericOverIp, Ip, IpAddr, Ipv4, Ipv4Addr, Ipv6, Ipv6Addr};
use packet::{BufferViewMut, PacketBuilder, ParsablePacket, ParseMetadata};
use zerocopy::{ByteSlice, ByteSliceMut};
use crate::error::{IpParseError, IpParseResult};
use crate::ethernet::EthernetIpExt;
use crate::icmp::IcmpIpExt;
use crate::ipv4::{Ipv4Header, Ipv4OnlyMeta, Ipv4Packet, Ipv4PacketBuilder};
use crate::ipv6::{Ipv6Header, Ipv6Packet, Ipv6PacketBuilder};
use crate::private::Sealed;
pub trait IpProtoExt: Ip {
type Proto: IpProtocol
+ GenericOverIp<Self, Type = Self::Proto>
+ GenericOverIp<Ipv4, Type = Ipv4Proto>
+ GenericOverIp<Ipv6, Type = Ipv6Proto>
+ Copy
+ Clone
+ Hash
+ Debug
+ Display
+ PartialEq
+ Eq;
}
impl IpProtoExt for Ipv4 {
type Proto = Ipv4Proto;
}
impl IpProtoExt for Ipv6 {
type Proto = Ipv6Proto;
}
pub trait IpExt: EthernetIpExt + IcmpIpExt {
type Packet<B: ByteSlice>: IpPacket<B, Self, Builder = Self::PacketBuilder>;
type PacketBuilder: IpPacketBuilder<Self> + Eq;
}
impl IpExt for Ipv4 {
type Packet<B: ByteSlice> = Ipv4Packet<B>;
type PacketBuilder = Ipv4PacketBuilder;
}
impl IpExt for Ipv6 {
type Packet<B: ByteSlice> = Ipv6Packet<B>;
type PacketBuilder = Ipv6PacketBuilder;
}
#[derive(Debug)]
pub enum Nat64Error {
NotImplemented,
}
#[derive(Debug)]
pub enum Nat64TranslationResult<S, E> {
Forward(S),
Drop,
Err(E),
}
pub trait IpPacket<B: ByteSlice, I: IpExt>:
Sized + Debug + ParsablePacket<B, (), Error = IpParseError<I>>
{
type Builder: IpPacketBuilder<I>;
type VersionSpecificMeta;
fn src_ip(&self) -> I::Addr;
fn dst_ip(&self) -> I::Addr;
fn proto(&self) -> I::Proto;
fn ttl(&self) -> u8;
fn set_ttl(&mut self, ttl: u8)
where
B: ByteSliceMut;
fn body(&self) -> &[u8];
fn version_specific_meta(&self) -> Self::VersionSpecificMeta;
fn into_metadata(self) -> (I::Addr, I::Addr, I::Proto, ParseMetadata) {
let src_ip = self.src_ip();
let dst_ip = self.dst_ip();
let proto = self.proto();
let meta = self.parse_metadata();
(src_ip, dst_ip, proto, meta)
}
fn as_ip_addr_ref(&self) -> IpAddr<&'_ Ipv4Packet<B>, &'_ Ipv6Packet<B>>;
fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
buffer: BV,
header: Vec<u8>,
body_fragments: IT,
) -> IpParseResult<I, Self>
where
B: ByteSliceMut;
}
impl<B: ByteSlice> IpPacket<B, Ipv4> for Ipv4Packet<B> {
type Builder = Ipv4PacketBuilder;
type VersionSpecificMeta = Ipv4OnlyMeta;
fn src_ip(&self) -> Ipv4Addr {
Ipv4Header::src_ip(self)
}
fn dst_ip(&self) -> Ipv4Addr {
Ipv4Header::dst_ip(self)
}
fn proto(&self) -> Ipv4Proto {
Ipv4Header::proto(self)
}
fn ttl(&self) -> u8 {
Ipv4Header::ttl(self)
}
fn set_ttl(&mut self, ttl: u8)
where
B: ByteSliceMut,
{
Ipv4Packet::set_ttl(self, ttl)
}
fn body(&self) -> &[u8] {
Ipv4Packet::body(self)
}
fn version_specific_meta(&self) -> Ipv4OnlyMeta {
Ipv4OnlyMeta { id: Ipv4Header::id(self) }
}
fn as_ip_addr_ref(&self) -> IpAddr<&'_ Self, &'_ Ipv6Packet<B>> {
IpAddr::V4(self)
}
fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
buffer: BV,
header: Vec<u8>,
body_fragments: IT,
) -> IpParseResult<Ipv4, Ipv4Packet<B>>
where
B: ByteSliceMut,
{
crate::ipv4::reassemble_fragmented_packet(buffer, header, body_fragments)
}
}
impl<B: ByteSlice> IpPacket<B, Ipv6> for Ipv6Packet<B> {
type Builder = Ipv6PacketBuilder;
type VersionSpecificMeta = ();
fn src_ip(&self) -> Ipv6Addr {
Ipv6Header::src_ip(self)
}
fn dst_ip(&self) -> Ipv6Addr {
Ipv6Header::dst_ip(self)
}
fn proto(&self) -> Ipv6Proto {
Ipv6Packet::proto(self)
}
fn ttl(&self) -> u8 {
Ipv6Header::hop_limit(self)
}
fn set_ttl(&mut self, ttl: u8)
where
B: ByteSliceMut,
{
Ipv6Packet::set_hop_limit(self, ttl)
}
fn body(&self) -> &[u8] {
Ipv6Packet::body(self)
}
fn version_specific_meta(&self) -> () {
()
}
fn as_ip_addr_ref(&self) -> IpAddr<&'_ Ipv4Packet<B>, &'_ Self> {
IpAddr::V6(self)
}
fn reassemble_fragmented_packet<BV: BufferViewMut<B>, IT: Iterator<Item = Vec<u8>>>(
buffer: BV,
header: Vec<u8>,
body_fragments: IT,
) -> IpParseResult<Ipv6, Ipv6Packet<B>>
where
B: ByteSliceMut,
{
crate::ipv6::reassemble_fragmented_packet(buffer, header, body_fragments)
}
}
pub trait IpPacketBuilder<I: IpExt>: PacketBuilder + Clone + Debug {
fn new(src_ip: I::Addr, dst_ip: I::Addr, ttl: u8, proto: I::Proto) -> Self;
fn src_ip(&self) -> I::Addr;
fn dst_ip(&self) -> I::Addr;
fn proto(&self) -> I::Proto;
}
pub trait IpProtocol: From<IpProto> + Sealed + Send + Sync + 'static {}
impl Sealed for Never {}
create_protocol_enum!(
#[allow(missing_docs)]
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub enum IpProto: u8 {
Tcp, 6, "TCP";
Udp, 17, "UDP";
}
);
create_protocol_enum!(
#[allow(missing_docs)]
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub enum Ipv4Proto: u8 {
Icmp, 1, "ICMP";
Igmp, 2, "IGMP";
+ Proto(IpProto);
_, "IPv4 protocol {}";
}
);
impl IpProtocol for Ipv4Proto {}
impl<I: Ip + IpProtoExt> GenericOverIp<I> for Ipv4Proto {
type Type = I::Proto;
}
impl Sealed for Ipv4Proto {}
create_protocol_enum!(
#[allow(missing_docs)]
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub enum Ipv6Proto: u8 {
Icmpv6, 58, "ICMPv6";
NoNextHeader, 59, "NO NEXT HEADER";
+ Proto(IpProto);
_, "IPv6 protocol {}";
}
);
impl IpProtocol for Ipv6Proto {}
impl<I: Ip + IpProtoExt> GenericOverIp<I> for Ipv6Proto {
type Type = I::Proto;
}
impl Sealed for Ipv6Proto {}
create_protocol_enum!(
#[allow(missing_docs)]
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub enum Ipv6ExtHdrType: u8 {
HopByHopOptions, 0, "IPv6 HOP-BY-HOP OPTIONS HEADER";
Routing, 43, "IPv6 ROUTING HEADER";
Fragment, 44, "IPv6 FRAGMENT HEADER";
EncapsulatingSecurityPayload, 50, "ENCAPSULATING SECURITY PAYLOAD";
Authentication, 51, "AUTHENTICATION HEADER";
DestinationOptions, 60, "IPv6 DESTINATION OPTIONS HEADER";
_, "IPv6 EXTENSION HEADER {}";
}
);