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-ipv4")]
97mod igmp;
98pub(crate) mod ip;
99#[cfg(feature = "proto-ipv4")]
100pub(crate) mod ipv4;
101#[cfg(feature = "proto-ipv6")]
102pub(crate) mod 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 MULTICAST_ALL_ROUTERS as IPV4_MULTICAST_ALL_ROUTERS,
192 MULTICAST_ALL_SYSTEMS as IPV4_MULTICAST_ALL_SYSTEMS,
193};
194
195#[cfg(feature = "proto-ipv4")]
196pub(crate) use self::ipv4::AddressExt as Ipv4AddressExt;
197
198#[cfg(feature = "proto-ipv6")]
199pub use self::ipv6::{
200 Address as Ipv6Address, Cidr as Ipv6Cidr, Packet as Ipv6Packet, Repr as Ipv6Repr,
201 HEADER_LEN as IPV6_HEADER_LEN,
202 LINK_LOCAL_ALL_MLDV2_ROUTERS as IPV6_LINK_LOCAL_ALL_MLDV2_ROUTERS,
203 LINK_LOCAL_ALL_NODES as IPV6_LINK_LOCAL_ALL_NODES,
204 LINK_LOCAL_ALL_ROUTERS as IPV6_LINK_LOCAL_ALL_ROUTERS,
205 LINK_LOCAL_ALL_RPL_NODES as IPV6_LINK_LOCAL_ALL_RPL_NODES, MIN_MTU as IPV6_MIN_MTU,
206};
207#[cfg(feature = "proto-ipv6")]
208pub(crate) use self::ipv6::{AddressExt as Ipv6AddressExt, MulticastScope as Ipv6MulticastScope};
209
210#[cfg(feature = "proto-ipv6")]
211pub use self::ipv6option::{
212 FailureType as Ipv6OptionFailureType, Ipv6Option, Ipv6OptionsIterator, Repr as Ipv6OptionRepr,
213 RouterAlert as Ipv6OptionRouterAlert, Type as Ipv6OptionType,
214};
215
216#[cfg(feature = "proto-ipv6")]
217pub use self::ipv6ext_header::{Header as Ipv6ExtHeader, Repr as Ipv6ExtHeaderRepr};
218
219#[cfg(feature = "proto-ipv6")]
220pub use self::ipv6fragment::{Header as Ipv6FragmentHeader, Repr as Ipv6FragmentRepr};
221
222#[cfg(feature = "proto-ipv6")]
223pub use self::ipv6hbh::{Header as Ipv6HopByHopHeader, Repr as Ipv6HopByHopRepr};
224
225#[cfg(feature = "proto-ipv6")]
226pub use self::ipv6routing::{
227 Header as Ipv6RoutingHeader, Repr as Ipv6RoutingRepr, Type as Ipv6RoutingType,
228};
229
230#[cfg(feature = "proto-ipv4")]
231pub use self::icmpv4::{
232 DstUnreachable as Icmpv4DstUnreachable, Message as Icmpv4Message, Packet as Icmpv4Packet,
233 ParamProblem as Icmpv4ParamProblem, Redirect as Icmpv4Redirect, Repr as Icmpv4Repr,
234 TimeExceeded as Icmpv4TimeExceeded,
235};
236
237#[cfg(feature = "proto-ipv4")]
238pub use self::igmp::{IgmpVersion, Packet as IgmpPacket, Repr as IgmpRepr};
239
240#[cfg(feature = "proto-ipv6")]
241pub use self::icmpv6::{
242 DstUnreachable as Icmpv6DstUnreachable, Message as Icmpv6Message, Packet as Icmpv6Packet,
243 ParamProblem as Icmpv6ParamProblem, Repr as Icmpv6Repr, TimeExceeded as Icmpv6TimeExceeded,
244};
245
246#[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
247pub use self::icmp::Repr as IcmpRepr;
248
249#[cfg(all(
250 feature = "proto-ipv6",
251 any(feature = "medium-ethernet", feature = "medium-ieee802154")
252))]
253pub use self::ndisc::{
254 NeighborFlags as NdiscNeighborFlags, Repr as NdiscRepr, RouterFlags as NdiscRouterFlags,
255};
256
257#[cfg(all(
258 feature = "proto-ipv6",
259 any(feature = "medium-ethernet", feature = "medium-ieee802154")
260))]
261pub use self::ndiscoption::{
262 NdiscOption, PrefixInfoFlags as NdiscPrefixInfoFlags,
263 PrefixInformation as NdiscPrefixInformation, RedirectedHeader as NdiscRedirectedHeader,
264 Repr as NdiscOptionRepr, Type as NdiscOptionType,
265};
266
267#[cfg(feature = "proto-ipv6")]
268pub use self::mld::{
269 AddressRecord as MldAddressRecord, AddressRecordRepr as MldAddressRecordRepr,
270 RecordType as MldRecordType, Repr as MldRepr,
271};
272
273pub use self::udp::{Packet as UdpPacket, Repr as UdpRepr, HEADER_LEN as UDP_HEADER_LEN};
274
275pub use self::tcp::{
276 Control as TcpControl, Packet as TcpPacket, Repr as TcpRepr, SeqNumber as TcpSeqNumber,
277 TcpOption, TcpTimestampGenerator, TcpTimestampRepr, HEADER_LEN as TCP_HEADER_LEN,
278};
279
280#[cfg(feature = "proto-dhcpv4")]
281pub use self::dhcpv4::{
282 DhcpOption, DhcpOptionWriter, Flags as DhcpFlags, MessageType as DhcpMessageType,
283 OpCode as DhcpOpCode, Packet as DhcpPacket, Repr as DhcpRepr, CLIENT_PORT as DHCP_CLIENT_PORT,
284 MAX_DNS_SERVER_COUNT as DHCP_MAX_DNS_SERVER_COUNT, SERVER_PORT as DHCP_SERVER_PORT,
285};
286
287#[cfg(feature = "proto-dns")]
288pub use self::dns::{
289 Flags as DnsFlags, Opcode as DnsOpcode, Packet as DnsPacket, Question as DnsQuestion,
290 Rcode as DnsRcode, Record as DnsRecord, RecordData as DnsRecordData, Repr as DnsRepr,
291 Type as DnsQueryType,
292};
293
294#[cfg(feature = "proto-ipsec-ah")]
295pub use self::ipsec_ah::{Packet as IpSecAuthHeaderPacket, Repr as IpSecAuthHeaderRepr};
296
297#[cfg(feature = "proto-ipsec-esp")]
298pub use self::ipsec_esp::{Packet as IpSecEspPacket, Repr as IpSecEspRepr};
299
300#[derive(Debug, Clone, Copy, PartialEq, Eq)]
304#[cfg_attr(feature = "defmt", derive(defmt::Format))]
305pub struct Error;
306
307#[cfg(feature = "std")]
308impl std::error::Error for Error {}
309
310impl fmt::Display for Error {
311 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
312 write!(f, "wire::Error")
313 }
314}
315
316pub type Result<T> = core::result::Result<T, Error>;
317
318#[cfg(any(
320 feature = "medium-ip",
321 feature = "medium-ethernet",
322 feature = "medium-ieee802154"
323))]
324#[derive(Debug, Clone, Copy, PartialEq, Eq)]
325#[cfg_attr(feature = "defmt", derive(defmt::Format))]
326pub enum HardwareAddress {
327 #[cfg(feature = "medium-ip")]
328 Ip,
329 #[cfg(feature = "medium-ethernet")]
330 Ethernet(EthernetAddress),
331 #[cfg(feature = "medium-ieee802154")]
332 Ieee802154(Ieee802154Address),
333}
334
335#[cfg(any(
336 feature = "medium-ip",
337 feature = "medium-ethernet",
338 feature = "medium-ieee802154"
339))]
340#[cfg(test)]
341impl Default for HardwareAddress {
342 fn default() -> Self {
343 #![allow(unreachable_code)]
344 #[cfg(feature = "medium-ethernet")]
345 {
346 return Self::Ethernet(EthernetAddress::default());
347 }
348 #[cfg(feature = "medium-ip")]
349 {
350 return Self::Ip;
351 }
352 #[cfg(feature = "medium-ieee802154")]
353 {
354 Self::Ieee802154(Ieee802154Address::default())
355 }
356 }
357}
358
359#[cfg(any(
360 feature = "medium-ip",
361 feature = "medium-ethernet",
362 feature = "medium-ieee802154"
363))]
364impl HardwareAddress {
365 pub const fn as_bytes(&self) -> &[u8] {
366 match self {
367 #[cfg(feature = "medium-ip")]
368 HardwareAddress::Ip => unreachable!(),
369 #[cfg(feature = "medium-ethernet")]
370 HardwareAddress::Ethernet(addr) => addr.as_bytes(),
371 #[cfg(feature = "medium-ieee802154")]
372 HardwareAddress::Ieee802154(addr) => addr.as_bytes(),
373 }
374 }
375
376 pub fn is_unicast(&self) -> bool {
378 match self {
379 #[cfg(feature = "medium-ip")]
380 HardwareAddress::Ip => unreachable!(),
381 #[cfg(feature = "medium-ethernet")]
382 HardwareAddress::Ethernet(addr) => addr.is_unicast(),
383 #[cfg(feature = "medium-ieee802154")]
384 HardwareAddress::Ieee802154(addr) => addr.is_unicast(),
385 }
386 }
387
388 pub fn is_broadcast(&self) -> bool {
390 match self {
391 #[cfg(feature = "medium-ip")]
392 HardwareAddress::Ip => unreachable!(),
393 #[cfg(feature = "medium-ethernet")]
394 HardwareAddress::Ethernet(addr) => addr.is_broadcast(),
395 #[cfg(feature = "medium-ieee802154")]
396 HardwareAddress::Ieee802154(addr) => addr.is_broadcast(),
397 }
398 }
399
400 #[cfg(feature = "medium-ethernet")]
401 pub(crate) fn ethernet_or_panic(&self) -> EthernetAddress {
402 match self {
403 HardwareAddress::Ethernet(addr) => *addr,
404 #[allow(unreachable_patterns)]
405 _ => panic!("HardwareAddress is not Ethernet."),
406 }
407 }
408
409 #[cfg(feature = "medium-ieee802154")]
410 pub(crate) fn ieee802154_or_panic(&self) -> Ieee802154Address {
411 match self {
412 HardwareAddress::Ieee802154(addr) => *addr,
413 #[allow(unreachable_patterns)]
414 _ => panic!("HardwareAddress is not Ethernet."),
415 }
416 }
417
418 #[inline]
419 pub(crate) fn medium(&self) -> Medium {
420 match self {
421 #[cfg(feature = "medium-ip")]
422 HardwareAddress::Ip => Medium::Ip,
423 #[cfg(feature = "medium-ethernet")]
424 HardwareAddress::Ethernet(_) => Medium::Ethernet,
425 #[cfg(feature = "medium-ieee802154")]
426 HardwareAddress::Ieee802154(_) => Medium::Ieee802154,
427 }
428 }
429}
430
431#[cfg(any(
432 feature = "medium-ip",
433 feature = "medium-ethernet",
434 feature = "medium-ieee802154"
435))]
436impl core::fmt::Display for HardwareAddress {
437 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
438 match self {
439 #[cfg(feature = "medium-ip")]
440 HardwareAddress::Ip => write!(f, "no hardware addr"),
441 #[cfg(feature = "medium-ethernet")]
442 HardwareAddress::Ethernet(addr) => write!(f, "{addr}"),
443 #[cfg(feature = "medium-ieee802154")]
444 HardwareAddress::Ieee802154(addr) => write!(f, "{addr}"),
445 }
446 }
447}
448
449#[cfg(feature = "medium-ethernet")]
450impl From<EthernetAddress> for HardwareAddress {
451 fn from(addr: EthernetAddress) -> Self {
452 HardwareAddress::Ethernet(addr)
453 }
454}
455
456#[cfg(feature = "medium-ieee802154")]
457impl From<Ieee802154Address> for HardwareAddress {
458 fn from(addr: Ieee802154Address) -> Self {
459 HardwareAddress::Ieee802154(addr)
460 }
461}
462
463#[cfg(not(feature = "medium-ieee802154"))]
464pub const MAX_HARDWARE_ADDRESS_LEN: usize = 6;
465#[cfg(feature = "medium-ieee802154")]
466pub const MAX_HARDWARE_ADDRESS_LEN: usize = 8;
467
468#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
472#[derive(Debug, PartialEq, Eq, Clone, Copy)]
473#[cfg_attr(feature = "defmt", derive(defmt::Format))]
474pub struct RawHardwareAddress {
475 len: u8,
476 data: [u8; MAX_HARDWARE_ADDRESS_LEN],
477}
478
479#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
480impl RawHardwareAddress {
481 pub fn from_bytes(addr: &[u8]) -> Self {
482 let mut data = [0u8; MAX_HARDWARE_ADDRESS_LEN];
483 data[..addr.len()].copy_from_slice(addr);
484
485 Self {
486 len: addr.len() as u8,
487 data,
488 }
489 }
490
491 pub fn as_bytes(&self) -> &[u8] {
492 &self.data[..self.len as usize]
493 }
494
495 pub const fn len(&self) -> usize {
496 self.len as usize
497 }
498
499 pub const fn is_empty(&self) -> bool {
500 self.len == 0
501 }
502
503 pub fn parse(&self, medium: Medium) -> Result<HardwareAddress> {
504 match medium {
505 #[cfg(feature = "medium-ethernet")]
506 Medium::Ethernet => {
507 if self.len() < 6 {
508 return Err(Error);
509 }
510 Ok(HardwareAddress::Ethernet(EthernetAddress::from_bytes(
511 self.as_bytes(),
512 )))
513 }
514 #[cfg(feature = "medium-ieee802154")]
515 Medium::Ieee802154 => {
516 if self.len() < 8 {
517 return Err(Error);
518 }
519 Ok(HardwareAddress::Ieee802154(Ieee802154Address::from_bytes(
520 self.as_bytes(),
521 )))
522 }
523 #[cfg(feature = "medium-ip")]
524 Medium::Ip => unreachable!(),
525 }
526 }
527}
528
529#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
530impl core::fmt::Display for RawHardwareAddress {
531 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
532 for (i, &b) in self.as_bytes().iter().enumerate() {
533 if i != 0 {
534 write!(f, ":")?;
535 }
536 write!(f, "{b:02x}")?;
537 }
538 Ok(())
539 }
540}
541
542#[cfg(feature = "medium-ethernet")]
543impl From<EthernetAddress> for RawHardwareAddress {
544 fn from(addr: EthernetAddress) -> Self {
545 Self::from_bytes(addr.as_bytes())
546 }
547}
548
549#[cfg(feature = "medium-ieee802154")]
550impl From<Ieee802154Address> for RawHardwareAddress {
551 fn from(addr: Ieee802154Address) -> Self {
552 Self::from_bytes(addr.as_bytes())
553 }
554}
555
556#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))]
557impl From<HardwareAddress> for RawHardwareAddress {
558 fn from(addr: HardwareAddress) -> Self {
559 Self::from_bytes(addr.as_bytes())
560 }
561}