blob: f7d20f72ae29f7a070f7e3a48c5f1dd53f73957b [file] [log] [blame]
use crate::*;
/// Deprecated use [`crate::NetSlice`] or [`crate::IpSlice`] instead.
#[cfg(feature = "std")]
#[deprecated(
since = "0.14.0",
note = "Deprecated use crate::NetSlice or crate::IpSlice instead"
)]
pub use NetSlice as InternetSlice;
/// Slice containing the network headers & payloads (e.g. IPv4, IPv6, ARP).
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum NetSlice<'a> {
/// The ipv4 header & the decoded extension headers.
Ipv4(Ipv4Slice<'a>),
/// The ipv6 header & the decoded extension headers.
Ipv6(Ipv6Slice<'a>),
/// The arp header & the decoded extension headers.
Arp(ArpPacketSlice<'a>),
}
impl<'a> NetSlice<'a> {
/// Returns true if the NetSlice contains either IPv4 or IPv6.
#[inline]
pub fn is_ip(&self) -> bool {
use NetSlice::*;
matches!(self, Ipv4(_) | Ipv6(_))
}
/// Returns true if the NetSlice contains IPv4.
#[inline]
pub fn is_ipv4(&self) -> bool {
use NetSlice::*;
matches!(self, Ipv4(_))
}
/// Returns true if the NetSlice contains IPv6.
#[inline]
pub fn is_ipv6(&self) -> bool {
use NetSlice::*;
matches!(self, Ipv6(_))
}
/// Returns true if the NetSlice contains ARP.
#[inline]
pub fn is_arp(&self) -> bool {
use NetSlice::*;
matches!(self, Arp(_))
}
/// Returns references to the IPv4 slice if the slice contains an IPv4 values.
#[inline]
pub fn ipv4_ref(&self) -> Option<&Ipv4Slice<'a>> {
if let NetSlice::Ipv4(s) = self {
Some(s)
} else {
None
}
}
/// Returns references to the IPv6 slice if the slice contains an IPv6 values.
#[inline]
pub fn ipv6_ref(&self) -> Option<&Ipv6Slice<'a>> {
if let NetSlice::Ipv6(s) = self {
Some(s)
} else {
None
}
}
/// Returns references to the ARP packet slice if the slice contains an ARP values.
#[inline]
pub fn arp_ref(&self) -> Option<&ArpPacketSlice> {
if let NetSlice::Arp(arp) = self {
Some(arp)
} else {
None
}
}
/// Returns a reference to ip payload if the net slice contains
/// an ipv4 or ipv6 slice.
#[inline]
pub fn ip_payload_ref(&self) -> Option<&IpPayloadSlice<'a>> {
match self {
NetSlice::Ipv4(s) => Some(&s.payload),
NetSlice::Ipv6(s) => Some(&s.payload),
NetSlice::Arp(_) => None,
}
}
}
impl<'a> From<IpSlice<'a>> for NetSlice<'a> {
#[inline]
fn from(value: IpSlice<'a>) -> NetSlice<'a> {
match value {
IpSlice::Ipv4(ipv4) => NetSlice::Ipv4(ipv4),
IpSlice::Ipv6(ipv6) => NetSlice::Ipv6(ipv6),
}
}
}
impl<'a> From<Ipv4Slice<'a>> for NetSlice<'a> {
#[inline]
fn from(value: Ipv4Slice<'a>) -> NetSlice<'a> {
NetSlice::Ipv4(value)
}
}
impl<'a> From<Ipv6Slice<'a>> for NetSlice<'a> {
#[inline]
fn from(value: Ipv6Slice<'a>) -> NetSlice<'a> {
NetSlice::Ipv6(value)
}
}
#[cfg(test)]
mod tests {
use crate::*;
use alloc::{format, vec::Vec};
#[test]
fn debug() {
let bytes = Ipv6Header {
next_header: IpNumber::UDP,
..Default::default()
}
.to_bytes();
let s = Ipv6Slice::from_slice(&bytes).unwrap();
let n = NetSlice::Ipv6(s.clone());
assert_eq!(format!("{n:?}"), format!("Ipv6({s:?})"));
}
#[test]
fn clone_eq() {
let bytes = Ipv6Header {
next_header: IpNumber::UDP,
..Default::default()
}
.to_bytes();
let s = NetSlice::Ipv6(Ipv6Slice::from_slice(&bytes).unwrap());
assert_eq!(s, s.clone())
}
#[test]
fn ip_payload_ref_and_is_ip() {
// ipv4
{
let payload = [1, 2, 3, 4];
let bytes = {
let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
bytes.extend_from_slice(
&(Ipv4Header {
total_len: Ipv4Header::MIN_LEN_U16 + 4,
protocol: IpNumber::UDP,
..Default::default()
})
.to_bytes(),
);
bytes.extend_from_slice(&payload);
bytes
};
let p = Ipv4Slice::from_slice(&bytes).unwrap();
let s = NetSlice::Ipv4(p.clone());
assert_eq!(
s.ip_payload_ref(),
Some(&IpPayloadSlice {
ip_number: IpNumber::UDP,
fragmented: false,
len_source: LenSource::Ipv4HeaderTotalLen,
payload: &payload
})
);
assert!(s.is_ip());
assert!(s.is_ipv4());
assert_eq!(false, s.is_ipv6());
assert_eq!(false, s.is_arp());
assert_eq!(Some(&p), s.ipv4_ref());
assert_eq!(None, s.ipv6_ref());
assert_eq!(None, s.arp_ref());
}
// ipv6
{
let payload = [1, 2, 3, 4];
let bytes = {
let mut bytes = Vec::with_capacity(Ipv6Header::LEN + 4);
bytes.extend_from_slice(
&(Ipv6Header {
next_header: IpNumber::UDP,
payload_length: 4,
..Default::default()
})
.to_bytes(),
);
bytes.extend_from_slice(&payload);
bytes
};
let p = Ipv6Slice::from_slice(&bytes).unwrap();
let s = NetSlice::Ipv6(p.clone());
assert_eq!(
s.ip_payload_ref(),
Some(&IpPayloadSlice {
ip_number: IpNumber::UDP,
fragmented: false,
len_source: LenSource::Ipv6HeaderPayloadLen,
payload: &payload
})
);
assert!(s.is_ip());
assert_eq!(false, s.is_ipv4());
assert!(s.is_ipv6());
assert_eq!(false, s.is_arp());
assert_eq!(None, s.ipv4_ref());
assert_eq!(Some(&p), s.ipv6_ref());
assert_eq!(None, s.arp_ref());
}
// arp
{
let arp = ArpPacket::new(
ArpHardwareId::ETHERNET,
EtherType::IPV4,
ArpOperation::REPLY,
&[0; 6],
&[0; 4],
&[0; 6],
&[0; 4],
)
.unwrap();
let bytes = arp.to_bytes();
let p = ArpPacketSlice::from_slice(&bytes).unwrap();
let s = NetSlice::Arp(p.clone());
assert_eq!(None, s.ip_payload_ref());
assert_eq!(false, s.is_ip());
assert_eq!(false, s.is_ipv4());
assert_eq!(false, s.is_ipv6());
assert!(s.is_arp());
assert_eq!(None, s.ipv4_ref());
assert_eq!(None, s.ipv6_ref());
assert_eq!(Some(&p), s.arp_ref());
}
}
#[test]
fn from() {
// IpSlice::Ipv4
{
let payload = [1, 2, 3, 4];
let bytes = {
let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
bytes.extend_from_slice(
&(Ipv4Header {
total_len: Ipv4Header::MIN_LEN_U16 + 4,
protocol: IpNumber::UDP,
..Default::default()
})
.to_bytes(),
);
bytes.extend_from_slice(&payload);
bytes
};
let i = Ipv4Slice::from_slice(&bytes).unwrap();
let actual: NetSlice = IpSlice::Ipv4(i.clone()).into();
assert_eq!(NetSlice::Ipv4(i.clone()), actual);
}
// Ipv4Slice
{
let payload = [1, 2, 3, 4];
let bytes = {
let mut bytes = Vec::with_capacity(Ipv4Header::MIN_LEN + 4);
bytes.extend_from_slice(
&(Ipv4Header {
total_len: Ipv4Header::MIN_LEN_U16 + 4,
protocol: IpNumber::UDP,
..Default::default()
})
.to_bytes(),
);
bytes.extend_from_slice(&payload);
bytes
};
let i = Ipv4Slice::from_slice(&bytes).unwrap();
let actual: NetSlice = i.clone().into();
assert_eq!(NetSlice::Ipv4(i.clone()), actual);
}
// IpSlice::Ipv6
{
let payload = [1, 2, 3, 4];
let bytes = {
let mut bytes = Vec::with_capacity(Ipv6Header::LEN + 4);
bytes.extend_from_slice(
&(Ipv6Header {
next_header: IpNumber::UDP,
payload_length: 4,
..Default::default()
})
.to_bytes(),
);
bytes.extend_from_slice(&payload);
bytes
};
let i = Ipv6Slice::from_slice(&bytes).unwrap();
let actual: NetSlice = i.clone().into();
assert_eq!(NetSlice::Ipv6(i.clone()), actual);
}
}
}