mod field {
pub type Field = ::core::ops::Range<usize>;
pub type Rest = ::core::ops::RangeFrom<usize>;
}
pub mod pretty_print;
#[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
mod arp;
#[cfg(feature = "proto-dhcpv4")]
pub(crate) mod dhcpv4;
#[cfg(feature = "proto-dns")]
pub(crate) mod dns;
#[cfg(feature = "medium-ethernet")]
mod ethernet;
#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
mod icmp;
#[cfg(feature = "proto-ipv4")]
mod icmpv4;
#[cfg(feature = "proto-ipv6")]
mod icmpv6;
#[cfg(feature = "medium-ieee802154")]
pub mod ieee802154;
#[cfg(feature = "proto-igmp")]
mod igmp;
pub(crate) mod ip;
#[cfg(feature = "proto-ipv4")]
mod ipv4;
#[cfg(feature = "proto-ipv6")]
mod ipv6;
#[cfg(feature = "proto-ipv6")]
mod ipv6ext_header;
#[cfg(feature = "proto-ipv6")]
mod ipv6fragment;
#[cfg(feature = "proto-ipv6")]
mod ipv6hbh;
#[cfg(feature = "proto-ipv6")]
mod ipv6option;
#[cfg(feature = "proto-ipv6")]
mod ipv6routing;
#[cfg(feature = "proto-ipv6")]
mod mld;
#[cfg(all(
feature = "proto-ipv6",
any(feature = "medium-ethernet", feature = "medium-ieee802154")
))]
mod ndisc;
#[cfg(all(
feature = "proto-ipv6",
any(feature = "medium-ethernet", feature = "medium-ieee802154")
))]
mod ndiscoption;
#[cfg(feature = "proto-rpl")]
mod rpl;
#[cfg(all(feature = "proto-sixlowpan", feature = "medium-ieee802154"))]
mod sixlowpan;
mod tcp;
mod udp;
#[cfg(feature = "proto-ipsec-ah")]
mod ipsec_ah;
#[cfg(feature = "proto-ipsec-esp")]
mod ipsec_esp;
use core::fmt;
use crate::phy::Medium;
pub use self::pretty_print::PrettyPrinter;
#[cfg(feature = "medium-ethernet")]
pub use self::ethernet::{
Address as EthernetAddress, EtherType as EthernetProtocol, Frame as EthernetFrame,
Repr as EthernetRepr, HEADER_LEN as ETHERNET_HEADER_LEN,
};
#[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
pub use self::arp::{
Hardware as ArpHardware, Operation as ArpOperation, Packet as ArpPacket, Repr as ArpRepr,
};
#[cfg(feature = "proto-rpl")]
pub use self::rpl::{
data::HopByHopOption as RplHopByHopRepr, data::Packet as RplHopByHopPacket,
options::Packet as RplOptionPacket, options::Repr as RplOptionRepr,
InstanceId as RplInstanceId, Repr as RplRepr,
};
#[cfg(all(feature = "proto-sixlowpan", feature = "medium-ieee802154"))]
pub use self::sixlowpan::{
frag::{Key as SixlowpanFragKey, Packet as SixlowpanFragPacket, Repr as SixlowpanFragRepr},
iphc::{Packet as SixlowpanIphcPacket, Repr as SixlowpanIphcRepr},
nhc::{
ExtHeaderId as SixlowpanExtHeaderId, ExtHeaderPacket as SixlowpanExtHeaderPacket,
ExtHeaderRepr as SixlowpanExtHeaderRepr, NhcPacket as SixlowpanNhcPacket,
UdpNhcPacket as SixlowpanUdpNhcPacket, UdpNhcRepr as SixlowpanUdpNhcRepr,
},
AddressContext as SixlowpanAddressContext, NextHeader as SixlowpanNextHeader, SixlowpanPacket,
};
#[cfg(feature = "medium-ieee802154")]
pub use self::ieee802154::{
Address as Ieee802154Address, AddressingMode as Ieee802154AddressingMode,
Frame as Ieee802154Frame, FrameType as Ieee802154FrameType,
FrameVersion as Ieee802154FrameVersion, Pan as Ieee802154Pan, Repr as Ieee802154Repr,
};
pub use self::ip::{
Address as IpAddress, Cidr as IpCidr, Endpoint as IpEndpoint,
ListenEndpoint as IpListenEndpoint, Protocol as IpProtocol, Repr as IpRepr,
Version as IpVersion,
};
#[cfg(feature = "proto-ipv4")]
pub use self::ipv4::{
Address as Ipv4Address, Cidr as Ipv4Cidr, Key as Ipv4FragKey, Packet as Ipv4Packet,
Repr as Ipv4Repr, HEADER_LEN as IPV4_HEADER_LEN, MIN_MTU as IPV4_MIN_MTU,
};
#[cfg(feature = "proto-ipv6")]
pub(crate) use self::ipv6::Scope as Ipv6AddressScope;
#[cfg(feature = "proto-ipv6")]
pub use self::ipv6::{
Address as Ipv6Address, Cidr as Ipv6Cidr, Packet as Ipv6Packet, Repr as Ipv6Repr,
HEADER_LEN as IPV6_HEADER_LEN, MIN_MTU as IPV6_MIN_MTU,
};
#[cfg(feature = "proto-ipv6")]
pub use self::ipv6option::{
FailureType as Ipv6OptionFailureType, Ipv6Option, Ipv6OptionsIterator, Repr as Ipv6OptionRepr,
Type as Ipv6OptionType,
};
#[cfg(feature = "proto-ipv6")]
pub use self::ipv6ext_header::{Header as Ipv6ExtHeader, Repr as Ipv6ExtHeaderRepr};
#[cfg(feature = "proto-ipv6")]
pub use self::ipv6fragment::{Header as Ipv6FragmentHeader, Repr as Ipv6FragmentRepr};
#[cfg(feature = "proto-ipv6")]
pub use self::ipv6hbh::{Header as Ipv6HopByHopHeader, Repr as Ipv6HopByHopRepr};
#[cfg(feature = "proto-ipv6")]
pub use self::ipv6routing::{
Header as Ipv6RoutingHeader, Repr as Ipv6RoutingRepr, Type as Ipv6RoutingType,
};
#[cfg(feature = "proto-ipv4")]
pub use self::icmpv4::{
DstUnreachable as Icmpv4DstUnreachable, Message as Icmpv4Message, Packet as Icmpv4Packet,
ParamProblem as Icmpv4ParamProblem, Redirect as Icmpv4Redirect, Repr as Icmpv4Repr,
TimeExceeded as Icmpv4TimeExceeded,
};
#[cfg(feature = "proto-igmp")]
pub use self::igmp::{IgmpVersion, Packet as IgmpPacket, Repr as IgmpRepr};
#[cfg(feature = "proto-ipv6")]
pub use self::icmpv6::{
DstUnreachable as Icmpv6DstUnreachable, Message as Icmpv6Message, Packet as Icmpv6Packet,
ParamProblem as Icmpv6ParamProblem, Repr as Icmpv6Repr, TimeExceeded as Icmpv6TimeExceeded,
};
#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
pub use self::icmp::Repr as IcmpRepr;
#[cfg(all(
feature = "proto-ipv6",
any(feature = "medium-ethernet", feature = "medium-ieee802154")
))]
pub use self::ndisc::{
NeighborFlags as NdiscNeighborFlags, Repr as NdiscRepr, RouterFlags as NdiscRouterFlags,
};
#[cfg(all(
feature = "proto-ipv6",
any(feature = "medium-ethernet", feature = "medium-ieee802154")
))]
pub use self::ndiscoption::{
NdiscOption, PrefixInfoFlags as NdiscPrefixInfoFlags,
PrefixInformation as NdiscPrefixInformation, RedirectedHeader as NdiscRedirectedHeader,
Repr as NdiscOptionRepr, Type as NdiscOptionType,
};
#[cfg(feature = "proto-ipv6")]
pub use self::mld::{AddressRecord as MldAddressRecord, Repr as MldRepr};
pub use self::udp::{Packet as UdpPacket, Repr as UdpRepr, HEADER_LEN as UDP_HEADER_LEN};
pub use self::tcp::{
Control as TcpControl, Packet as TcpPacket, Repr as TcpRepr, SeqNumber as TcpSeqNumber,
TcpOption, HEADER_LEN as TCP_HEADER_LEN,
};
#[cfg(feature = "proto-dhcpv4")]
pub use self::dhcpv4::{
DhcpOption, DhcpOptionWriter, MessageType as DhcpMessageType, Packet as DhcpPacket,
Repr as DhcpRepr, CLIENT_PORT as DHCP_CLIENT_PORT,
MAX_DNS_SERVER_COUNT as DHCP_MAX_DNS_SERVER_COUNT, SERVER_PORT as DHCP_SERVER_PORT,
};
#[cfg(feature = "proto-dns")]
pub use self::dns::{
Flags as DnsFlags, Opcode as DnsOpcode, Packet as DnsPacket, Rcode as DnsRcode,
Repr as DnsRepr, Type as DnsQueryType,
};
#[cfg(feature = "proto-ipsec-ah")]
pub use self::ipsec_ah::{Packet as IpSecAuthHeaderPacket, Repr as IpSecAuthHeaderRepr};
#[cfg(feature = "proto-ipsec-esp")]
pub use self::ipsec_esp::{Packet as IpSecEspPacket, Repr as IpSecEspRepr};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Error;
#[cfg(feature = "std")]
impl std::error::Error for Error {}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "wire::Error")
}
}
pub type Result<T> = core::result::Result<T, Error>;
#[cfg(any(
feature = "medium-ip",
feature = "medium-ethernet",
feature = "medium-ieee802154"
))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum HardwareAddress {
#[cfg(feature = "medium-ip")]
Ip,
#[cfg(feature = "medium-ethernet")]
Ethernet(EthernetAddress),
#[cfg(feature = "medium-ieee802154")]
Ieee802154(Ieee802154Address),
}
#[cfg(any(
feature = "medium-ip",
feature = "medium-ethernet",
feature = "medium-ieee802154"
))]
impl HardwareAddress {
pub const fn as_bytes(&self) -> &[u8] {
match self {
#[cfg(feature = "medium-ip")]
HardwareAddress::Ip => unreachable!(),
#[cfg(feature = "medium-ethernet")]
HardwareAddress::Ethernet(addr) => addr.as_bytes(),
#[cfg(feature = "medium-ieee802154")]
HardwareAddress::Ieee802154(addr) => addr.as_bytes(),
}
}
pub fn is_unicast(&self) -> bool {
match self {
#[cfg(feature = "medium-ip")]
HardwareAddress::Ip => unreachable!(),
#[cfg(feature = "medium-ethernet")]
HardwareAddress::Ethernet(addr) => addr.is_unicast(),
#[cfg(feature = "medium-ieee802154")]
HardwareAddress::Ieee802154(addr) => addr.is_unicast(),
}
}
pub fn is_broadcast(&self) -> bool {
match self {
#[cfg(feature = "medium-ip")]
HardwareAddress::Ip => unreachable!(),
#[cfg(feature = "medium-ethernet")]
HardwareAddress::Ethernet(addr) => addr.is_broadcast(),
#[cfg(feature = "medium-ieee802154")]
HardwareAddress::Ieee802154(addr) => addr.is_broadcast(),
}
}
#[cfg(feature = "medium-ethernet")]
pub(crate) fn ethernet_or_panic(&self) -> EthernetAddress {
match self {
HardwareAddress::Ethernet(addr) => *addr,
#[allow(unreachable_patterns)]
_ => panic!("HardwareAddress is not Ethernet."),
}
}
#[cfg(feature = "medium-ieee802154")]
pub(crate) fn ieee802154_or_panic(&self) -> Ieee802154Address {
match self {
HardwareAddress::Ieee802154(addr) => *addr,
#[allow(unreachable_patterns)]
_ => panic!("HardwareAddress is not Ethernet."),
}
}
#[inline]
pub(crate) fn medium(&self) -> Medium {
match self {
#[cfg(feature = "medium-ip")]
HardwareAddress::Ip => Medium::Ip,
#[cfg(feature = "medium-ethernet")]
HardwareAddress::Ethernet(_) => Medium::Ethernet,
#[cfg(feature = "medium-ieee802154")]
HardwareAddress::Ieee802154(_) => Medium::Ieee802154,
}
}
}
#[cfg(any(
feature = "medium-ip",
feature = "medium-ethernet",
feature = "medium-ieee802154"
))]
impl core::fmt::Display for HardwareAddress {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
#[cfg(feature = "medium-ip")]
HardwareAddress::Ip => write!(f, "no hardware addr"),
#[cfg(feature = "medium-ethernet")]
HardwareAddress::Ethernet(addr) => write!(f, "{addr}"),
#[cfg(feature = "medium-ieee802154")]
HardwareAddress::Ieee802154(addr) => write!(f, "{addr}"),
}
}
}
#[cfg(feature = "medium-ethernet")]
impl From<EthernetAddress> for HardwareAddress {
fn from(addr: EthernetAddress) -> Self {
HardwareAddress::Ethernet(addr)
}
}
#[cfg(feature = "medium-ieee802154")]
impl From<Ieee802154Address> for HardwareAddress {
fn from(addr: Ieee802154Address) -> Self {
HardwareAddress::Ieee802154(addr)
}
}
#[cfg(not(feature = "medium-ieee802154"))]
pub const MAX_HARDWARE_ADDRESS_LEN: usize = 6;
#[cfg(feature = "medium-ieee802154")]
pub const MAX_HARDWARE_ADDRESS_LEN: usize = 8;
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct RawHardwareAddress {
len: u8,
data: [u8; MAX_HARDWARE_ADDRESS_LEN],
}
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
impl RawHardwareAddress {
pub fn from_bytes(addr: &[u8]) -> Self {
let mut data = [0u8; MAX_HARDWARE_ADDRESS_LEN];
data[..addr.len()].copy_from_slice(addr);
Self {
len: addr.len() as u8,
data,
}
}
pub fn as_bytes(&self) -> &[u8] {
&self.data[..self.len as usize]
}
pub const fn len(&self) -> usize {
self.len as usize
}
pub const fn is_empty(&self) -> bool {
self.len == 0
}
pub fn parse(&self, medium: Medium) -> Result<HardwareAddress> {
match medium {
#[cfg(feature = "medium-ethernet")]
Medium::Ethernet => {
if self.len() < 6 {
return Err(Error);
}
Ok(HardwareAddress::Ethernet(EthernetAddress::from_bytes(
self.as_bytes(),
)))
}
#[cfg(feature = "medium-ieee802154")]
Medium::Ieee802154 => {
if self.len() < 8 {
return Err(Error);
}
Ok(HardwareAddress::Ieee802154(Ieee802154Address::from_bytes(
self.as_bytes(),
)))
}
#[cfg(feature = "medium-ip")]
Medium::Ip => unreachable!(),
}
}
}
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
impl core::fmt::Display for RawHardwareAddress {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
for (i, &b) in self.as_bytes().iter().enumerate() {
if i != 0 {
write!(f, ":")?;
}
write!(f, "{b:02x}")?;
}
Ok(())
}
}
#[cfg(feature = "medium-ethernet")]
impl From<EthernetAddress> for RawHardwareAddress {
fn from(addr: EthernetAddress) -> Self {
Self::from_bytes(addr.as_bytes())
}
}
#[cfg(feature = "medium-ieee802154")]
impl From<Ieee802154Address> for RawHardwareAddress {
fn from(addr: Ieee802154Address) -> Self {
Self::from_bytes(addr.as_bytes())
}
}
#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
impl From<HardwareAddress> for RawHardwareAddress {
fn from(addr: HardwareAddress) -> Self {
Self::from_bytes(addr.as_bytes())
}
}