1mod field {
74 pub type Field = ::core::ops::Range<usize>;
75 pub type Rest = ::core::ops::RangeFrom<usize>;
76}
77
78pub mod pretty_print;
79
80#[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
81mod arp;
82#[cfg(feature = "proto-dhcpv4")]
83pub(crate) mod dhcpv4;
84#[cfg(feature = "proto-dns")]
85pub(crate) mod dns;
86#[cfg(feature = "medium-ethernet")]
87mod ethernet;
88#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
89mod icmp;
90#[cfg(feature = "proto-ipv4")]
91mod icmpv4;
92#[cfg(feature = "proto-ipv6")]
93mod icmpv6;
94#[cfg(feature = "medium-ieee802154")]
95pub mod ieee802154;
96#[cfg(feature = "proto-igmp")]
97mod igmp;
98pub(crate) mod ip;
99#[cfg(feature = "proto-ipv4")]
100mod ipv4;
101#[cfg(feature = "proto-ipv6")]
102mod ipv6;
103#[cfg(feature = "proto-ipv6")]
104mod ipv6ext_header;
105#[cfg(feature = "proto-ipv6")]
106mod ipv6fragment;
107#[cfg(feature = "proto-ipv6")]
108mod ipv6hbh;
109#[cfg(feature = "proto-ipv6")]
110mod ipv6option;
111#[cfg(feature = "proto-ipv6")]
112mod ipv6routing;
113#[cfg(feature = "proto-ipv6")]
114mod mld;
115#[cfg(all(
116 feature = "proto-ipv6",
117 any(feature = "medium-ethernet", feature = "medium-ieee802154")
118))]
119mod ndisc;
120#[cfg(all(
121 feature = "proto-ipv6",
122 any(feature = "medium-ethernet", feature = "medium-ieee802154")
123))]
124mod ndiscoption;
125#[cfg(feature = "proto-rpl")]
126mod rpl;
127#[cfg(all(feature = "proto-sixlowpan", feature = "medium-ieee802154"))]
128mod sixlowpan;
129mod tcp;
130mod udp;
131
132#[cfg(feature = "proto-ipsec-ah")]
133mod ipsec_ah;
134
135#[cfg(feature = "proto-ipsec-esp")]
136mod ipsec_esp;
137
138use core::fmt;
139
140use crate::phy::Medium;
141
142pub use self::pretty_print::PrettyPrinter;
143
144#[cfg(feature = "medium-ethernet")]
145pub use self::ethernet::{
146 Address as EthernetAddress, EtherType as EthernetProtocol, Frame as EthernetFrame,
147 Repr as EthernetRepr, HEADER_LEN as ETHERNET_HEADER_LEN,
148};
149
150#[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
151pub use self::arp::{
152 Hardware as ArpHardware, Operation as ArpOperation, Packet as ArpPacket, Repr as ArpRepr,
153};
154
155#[cfg(feature = "proto-rpl")]
156pub use self::rpl::{
157 data::HopByHopOption as RplHopByHopRepr, data::Packet as RplHopByHopPacket,
158 options::Packet as RplOptionPacket, options::Repr as RplOptionRepr,
159 InstanceId as RplInstanceId, Repr as RplRepr,
160};
161
162#[cfg(all(feature = "proto-sixlowpan", feature = "medium-ieee802154"))]
163pub use self::sixlowpan::{
164 frag::{Key as SixlowpanFragKey, Packet as SixlowpanFragPacket, Repr as SixlowpanFragRepr},
165 iphc::{Packet as SixlowpanIphcPacket, Repr as SixlowpanIphcRepr},
166 nhc::{
167 ExtHeaderId as SixlowpanExtHeaderId, ExtHeaderPacket as SixlowpanExtHeaderPacket,
168 ExtHeaderRepr as SixlowpanExtHeaderRepr, NhcPacket as SixlowpanNhcPacket,
169 UdpNhcPacket as SixlowpanUdpNhcPacket, UdpNhcRepr as SixlowpanUdpNhcRepr,
170 },
171 AddressContext as SixlowpanAddressContext, NextHeader as SixlowpanNextHeader, SixlowpanPacket,
172};
173
174#[cfg(feature = "medium-ieee802154")]
175pub use self::ieee802154::{
176 Address as Ieee802154Address, AddressingMode as Ieee802154AddressingMode,
177 Frame as Ieee802154Frame, FrameType as Ieee802154FrameType,
178 FrameVersion as Ieee802154FrameVersion, Pan as Ieee802154Pan, Repr as Ieee802154Repr,
179};
180
181pub use self::ip::{
182 Address as IpAddress, Cidr as IpCidr, Endpoint as IpEndpoint,
183 ListenEndpoint as IpListenEndpoint, Protocol as IpProtocol, Repr as IpRepr,
184 Version as IpVersion,
185};
186
187#[cfg(feature = "proto-ipv4")]
188pub use self::ipv4::{
189 Address as Ipv4Address, Cidr as Ipv4Cidr, Key as Ipv4FragKey, Packet as Ipv4Packet,
190 Repr as Ipv4Repr, HEADER_LEN as IPV4_HEADER_LEN, MIN_MTU as IPV4_MIN_MTU,
191};
192
193#[cfg(feature = "proto-ipv6")]
194pub(crate) use self::ipv6::Scope as Ipv6AddressScope;
195#[cfg(feature = "proto-ipv6")]
196pub use self::ipv6::{
197 Address as Ipv6Address, Cidr as Ipv6Cidr, Packet as Ipv6Packet, Repr as Ipv6Repr,
198 HEADER_LEN as IPV6_HEADER_LEN, MIN_MTU as IPV6_MIN_MTU,
199};
200
201#[cfg(feature = "proto-ipv6")]
202pub use self::ipv6option::{
203 FailureType as Ipv6OptionFailureType, Ipv6Option, Ipv6OptionsIterator, Repr as Ipv6OptionRepr,
204 Type as Ipv6OptionType,
205};
206
207#[cfg(feature = "proto-ipv6")]
208pub use self::ipv6ext_header::{Header as Ipv6ExtHeader, Repr as Ipv6ExtHeaderRepr};
209
210#[cfg(feature = "proto-ipv6")]
211pub use self::ipv6fragment::{Header as Ipv6FragmentHeader, Repr as Ipv6FragmentRepr};
212
213#[cfg(feature = "proto-ipv6")]
214pub use self::ipv6hbh::{Header as Ipv6HopByHopHeader, Repr as Ipv6HopByHopRepr};
215
216#[cfg(feature = "proto-ipv6")]
217pub use self::ipv6routing::{
218 Header as Ipv6RoutingHeader, Repr as Ipv6RoutingRepr, Type as Ipv6RoutingType,
219};
220
221#[cfg(feature = "proto-ipv4")]
222pub use self::icmpv4::{
223 DstUnreachable as Icmpv4DstUnreachable, Message as Icmpv4Message, Packet as Icmpv4Packet,
224 ParamProblem as Icmpv4ParamProblem, Redirect as Icmpv4Redirect, Repr as Icmpv4Repr,
225 TimeExceeded as Icmpv4TimeExceeded,
226};
227
228#[cfg(feature = "proto-igmp")]
229pub use self::igmp::{IgmpVersion, Packet as IgmpPacket, Repr as IgmpRepr};
230
231#[cfg(feature = "proto-ipv6")]
232pub use self::icmpv6::{
233 DstUnreachable as Icmpv6DstUnreachable, Message as Icmpv6Message, Packet as Icmpv6Packet,
234 ParamProblem as Icmpv6ParamProblem, Repr as Icmpv6Repr, TimeExceeded as Icmpv6TimeExceeded,
235};
236
237#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
238pub use self::icmp::Repr as IcmpRepr;
239
240#[cfg(all(
241 feature = "proto-ipv6",
242 any(feature = "medium-ethernet", feature = "medium-ieee802154")
243))]
244pub use self::ndisc::{
245 NeighborFlags as NdiscNeighborFlags, Repr as NdiscRepr, RouterFlags as NdiscRouterFlags,
246};
247
248#[cfg(all(
249 feature = "proto-ipv6",
250 any(feature = "medium-ethernet", feature = "medium-ieee802154")
251))]
252pub use self::ndiscoption::{
253 NdiscOption, PrefixInfoFlags as NdiscPrefixInfoFlags,
254 PrefixInformation as NdiscPrefixInformation, RedirectedHeader as NdiscRedirectedHeader,
255 Repr as NdiscOptionRepr, Type as NdiscOptionType,
256};
257
258#[cfg(feature = "proto-ipv6")]
259pub use self::mld::{AddressRecord as MldAddressRecord, Repr as MldRepr};
260
261pub use self::udp::{Packet as UdpPacket, Repr as UdpRepr, HEADER_LEN as UDP_HEADER_LEN};
262
263pub use self::tcp::{
264 Control as TcpControl, Packet as TcpPacket, Repr as TcpRepr, SeqNumber as TcpSeqNumber,
265 TcpOption, HEADER_LEN as TCP_HEADER_LEN,
266};
267
268#[cfg(feature = "proto-dhcpv4")]
269pub use self::dhcpv4::{
270 DhcpOption, DhcpOptionWriter, MessageType as DhcpMessageType, Packet as DhcpPacket,
271 Repr as DhcpRepr, CLIENT_PORT as DHCP_CLIENT_PORT,
272 MAX_DNS_SERVER_COUNT as DHCP_MAX_DNS_SERVER_COUNT, SERVER_PORT as DHCP_SERVER_PORT,
273};
274
275#[cfg(feature = "proto-dns")]
276pub use self::dns::{
277 Flags as DnsFlags, Opcode as DnsOpcode, Packet as DnsPacket, Rcode as DnsRcode,
278 Repr as DnsRepr, Type as DnsQueryType,
279};
280
281#[cfg(feature = "proto-ipsec-ah")]
282pub use self::ipsec_ah::{Packet as IpSecAuthHeaderPacket, Repr as IpSecAuthHeaderRepr};
283
284#[cfg(feature = "proto-ipsec-esp")]
285pub use self::ipsec_esp::{Packet as IpSecEspPacket, Repr as IpSecEspRepr};
286
287#[derive(Debug, Clone, Copy, PartialEq, Eq)]
291#[cfg_attr(feature = "defmt", derive(defmt::Format))]
292pub struct Error;
293
294#[cfg(feature = "std")]
295impl std::error::Error for Error {}
296
297impl fmt::Display for Error {
298 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
299 write!(f, "wire::Error")
300 }
301}
302
303pub type Result<T> = core::result::Result<T, Error>;
304
305#[cfg(any(
307 feature = "medium-ip",
308 feature = "medium-ethernet",
309 feature = "medium-ieee802154"
310))]
311#[derive(Debug, Clone, Copy, PartialEq, Eq)]
312#[cfg_attr(feature = "defmt", derive(defmt::Format))]
313pub enum HardwareAddress {
314 #[cfg(feature = "medium-ip")]
315 Ip,
316 #[cfg(feature = "medium-ethernet")]
317 Ethernet(EthernetAddress),
318 #[cfg(feature = "medium-ieee802154")]
319 Ieee802154(Ieee802154Address),
320}
321
322#[cfg(any(
323 feature = "medium-ip",
324 feature = "medium-ethernet",
325 feature = "medium-ieee802154"
326))]
327impl HardwareAddress {
328 pub const fn as_bytes(&self) -> &[u8] {
329 match self {
330 #[cfg(feature = "medium-ip")]
331 HardwareAddress::Ip => unreachable!(),
332 #[cfg(feature = "medium-ethernet")]
333 HardwareAddress::Ethernet(addr) => addr.as_bytes(),
334 #[cfg(feature = "medium-ieee802154")]
335 HardwareAddress::Ieee802154(addr) => addr.as_bytes(),
336 }
337 }
338
339 pub fn is_unicast(&self) -> bool {
341 match self {
342 #[cfg(feature = "medium-ip")]
343 HardwareAddress::Ip => unreachable!(),
344 #[cfg(feature = "medium-ethernet")]
345 HardwareAddress::Ethernet(addr) => addr.is_unicast(),
346 #[cfg(feature = "medium-ieee802154")]
347 HardwareAddress::Ieee802154(addr) => addr.is_unicast(),
348 }
349 }
350
351 pub fn is_broadcast(&self) -> bool {
353 match self {
354 #[cfg(feature = "medium-ip")]
355 HardwareAddress::Ip => unreachable!(),
356 #[cfg(feature = "medium-ethernet")]
357 HardwareAddress::Ethernet(addr) => addr.is_broadcast(),
358 #[cfg(feature = "medium-ieee802154")]
359 HardwareAddress::Ieee802154(addr) => addr.is_broadcast(),
360 }
361 }
362
363 #[cfg(feature = "medium-ethernet")]
364 pub(crate) fn ethernet_or_panic(&self) -> EthernetAddress {
365 match self {
366 HardwareAddress::Ethernet(addr) => *addr,
367 #[allow(unreachable_patterns)]
368 _ => panic!("HardwareAddress is not Ethernet."),
369 }
370 }
371
372 #[cfg(feature = "medium-ieee802154")]
373 pub(crate) fn ieee802154_or_panic(&self) -> Ieee802154Address {
374 match self {
375 HardwareAddress::Ieee802154(addr) => *addr,
376 #[allow(unreachable_patterns)]
377 _ => panic!("HardwareAddress is not Ethernet."),
378 }
379 }
380
381 #[inline]
382 pub(crate) fn medium(&self) -> Medium {
383 match self {
384 #[cfg(feature = "medium-ip")]
385 HardwareAddress::Ip => Medium::Ip,
386 #[cfg(feature = "medium-ethernet")]
387 HardwareAddress::Ethernet(_) => Medium::Ethernet,
388 #[cfg(feature = "medium-ieee802154")]
389 HardwareAddress::Ieee802154(_) => Medium::Ieee802154,
390 }
391 }
392}
393
394#[cfg(any(
395 feature = "medium-ip",
396 feature = "medium-ethernet",
397 feature = "medium-ieee802154"
398))]
399impl core::fmt::Display for HardwareAddress {
400 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
401 match self {
402 #[cfg(feature = "medium-ip")]
403 HardwareAddress::Ip => write!(f, "no hardware addr"),
404 #[cfg(feature = "medium-ethernet")]
405 HardwareAddress::Ethernet(addr) => write!(f, "{addr}"),
406 #[cfg(feature = "medium-ieee802154")]
407 HardwareAddress::Ieee802154(addr) => write!(f, "{addr}"),
408 }
409 }
410}
411
412#[cfg(feature = "medium-ethernet")]
413impl From<EthernetAddress> for HardwareAddress {
414 fn from(addr: EthernetAddress) -> Self {
415 HardwareAddress::Ethernet(addr)
416 }
417}
418
419#[cfg(feature = "medium-ieee802154")]
420impl From<Ieee802154Address> for HardwareAddress {
421 fn from(addr: Ieee802154Address) -> Self {
422 HardwareAddress::Ieee802154(addr)
423 }
424}
425
426#[cfg(not(feature = "medium-ieee802154"))]
427pub const MAX_HARDWARE_ADDRESS_LEN: usize = 6;
428#[cfg(feature = "medium-ieee802154")]
429pub const MAX_HARDWARE_ADDRESS_LEN: usize = 8;
430
431#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
435#[derive(Debug, PartialEq, Eq, Clone, Copy)]
436#[cfg_attr(feature = "defmt", derive(defmt::Format))]
437pub struct RawHardwareAddress {
438 len: u8,
439 data: [u8; MAX_HARDWARE_ADDRESS_LEN],
440}
441
442#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
443impl RawHardwareAddress {
444 pub fn from_bytes(addr: &[u8]) -> Self {
445 let mut data = [0u8; MAX_HARDWARE_ADDRESS_LEN];
446 data[..addr.len()].copy_from_slice(addr);
447
448 Self {
449 len: addr.len() as u8,
450 data,
451 }
452 }
453
454 pub fn as_bytes(&self) -> &[u8] {
455 &self.data[..self.len as usize]
456 }
457
458 pub const fn len(&self) -> usize {
459 self.len as usize
460 }
461
462 pub const fn is_empty(&self) -> bool {
463 self.len == 0
464 }
465
466 pub fn parse(&self, medium: Medium) -> Result<HardwareAddress> {
467 match medium {
468 #[cfg(feature = "medium-ethernet")]
469 Medium::Ethernet => {
470 if self.len() < 6 {
471 return Err(Error);
472 }
473 Ok(HardwareAddress::Ethernet(EthernetAddress::from_bytes(
474 self.as_bytes(),
475 )))
476 }
477 #[cfg(feature = "medium-ieee802154")]
478 Medium::Ieee802154 => {
479 if self.len() < 8 {
480 return Err(Error);
481 }
482 Ok(HardwareAddress::Ieee802154(Ieee802154Address::from_bytes(
483 self.as_bytes(),
484 )))
485 }
486 #[cfg(feature = "medium-ip")]
487 Medium::Ip => unreachable!(),
488 }
489 }
490}
491
492#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
493impl core::fmt::Display for RawHardwareAddress {
494 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
495 for (i, &b) in self.as_bytes().iter().enumerate() {
496 if i != 0 {
497 write!(f, ":")?;
498 }
499 write!(f, "{b:02x}")?;
500 }
501 Ok(())
502 }
503}
504
505#[cfg(feature = "medium-ethernet")]
506impl From<EthernetAddress> for RawHardwareAddress {
507 fn from(addr: EthernetAddress) -> Self {
508 Self::from_bytes(addr.as_bytes())
509 }
510}
511
512#[cfg(feature = "medium-ieee802154")]
513impl From<Ieee802154Address> for RawHardwareAddress {
514 fn from(addr: Ieee802154Address) -> Self {
515 Self::from_bytes(addr.as_bytes())
516 }
517}
518
519#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
520impl From<HardwareAddress> for RawHardwareAddress {
521 fn from(addr: HardwareAddress) -> Self {
522 Self::from_bytes(addr.as_bytes())
523 }
524}