123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- /*! Low-level packet access and construction.
- The `wire` module deals with the packet *representation*. It provides two levels
- of functionality.
- * First, it provides functions to extract fields from sequences of octets,
- and to insert fields into sequences of octets. This happens `Packet` family of
- structures, e.g. [EthernetFrame] or [Ipv4Packet].
- * Second, in cases where the space of valid field values is much smaller than the space
- of possible field values, it provides a compact, high-level representation
- of packet data that can be parsed from and emitted into a sequence of octets.
- This happens through the `Repr` family of structs and enums, e.g. [ArpRepr] or [Ipv4Repr].
- [EthernetFrame]: struct.EthernetFrame.html
- [Ipv4Packet]: struct.Ipv4Packet.html
- [ArpRepr]: enum.ArpRepr.html
- [Ipv4Repr]: struct.Ipv4Repr.html
- The functions in the `wire` module are designed for use together with `-Cpanic=abort`.
- The `Packet` family of data structures guarantees that, if the `Packet::check_len()` method
- returned `Ok(())`, then no accessor or setter method will panic; however, the guarantee
- provided by `Packet::check_len()` may no longer hold after changing certain fields,
- which are listed in the documentation for the specific packet.
- The `Packet::new_checked` method is a shorthand for a combination of `Packet::new_unchecked`
- and `Packet::check_len`.
- When parsing untrusted input, it is *necessary* to use `Packet::new_checked()`;
- so long as the buffer is not modified, no accessor will fail.
- When emitting output, though, it is *incorrect* to use `Packet::new_checked()`;
- the length check is likely to succeed on a zeroed buffer, but fail on a buffer
- filled with data from a previous packet, such as when reusing buffers, resulting
- in nondeterministic panics with some network devices but not others.
- The buffer length for emission is not calculated by the `Packet` layer.
- In the `Repr` family of data structures, the `Repr::parse()` method never panics
- as long as `Packet::new_checked()` (or `Packet::check_len()`) has succeeded, and
- the `Repr::emit()` method never panics as long as the underlying buffer is exactly
- `Repr::buffer_len()` octets long.
- # Examples
- To emit an IP packet header into an octet buffer, and then parse it back:
- ```rust
- # #[cfg(feature = "proto-ipv4")]
- # {
- use smoltcp::phy::ChecksumCapabilities;
- use smoltcp::wire::*;
- let repr = Ipv4Repr {
- src_addr: Ipv4Address::new(10, 0, 0, 1),
- dst_addr: Ipv4Address::new(10, 0, 0, 2),
- protocol: IpProtocol::Tcp,
- payload_len: 10,
- hop_limit: 64
- };
- let mut buffer = vec![0; repr.buffer_len() + repr.payload_len];
- { // emission
- let mut packet = Ipv4Packet::new_unchecked(&mut buffer);
- repr.emit(&mut packet, &ChecksumCapabilities::default());
- }
- { // parsing
- let packet = Ipv4Packet::new_checked(&buffer)
- .expect("truncated packet");
- let parsed = Ipv4Repr::parse(&packet, &ChecksumCapabilities::default())
- .expect("malformed packet");
- assert_eq!(repr, parsed);
- }
- # }
- ```
- */
- 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 = "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 = "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 ipv6fragment;
- #[cfg(feature = "proto-ipv6")]
- mod ipv6hopbyhop;
- #[cfg(feature = "proto-ipv6")]
- mod ipv6option;
- #[cfg(feature = "proto-ipv6")]
- mod ipv6routing;
- #[cfg(feature = "proto-ipv6")]
- mod mld;
- #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
- mod ndisc;
- #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
- mod ndiscoption;
- mod tcp;
- mod udp;
- 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,
- };
- pub use self::ip::{
- Address as IpAddress, Cidr as IpCidr, Endpoint as IpEndpoint, Protocol as IpProtocol,
- Repr as IpRepr, Version as IpVersion,
- };
- #[cfg(feature = "proto-ipv4")]
- pub use self::ipv4::{
- Address as Ipv4Address, Cidr as Ipv4Cidr, Packet as Ipv4Packet, Repr as Ipv4Repr,
- HEADER_LEN as IPV4_HEADER_LEN, MIN_MTU as IPV4_MIN_MTU,
- };
- #[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, Repr as Ipv6OptionRepr,
- Type as Ipv6OptionType,
- };
- #[cfg(feature = "proto-ipv6")]
- pub use self::ipv6hopbyhop::{Header as Ipv6HopByHopHeader, Repr as Ipv6HopByHopRepr};
- #[cfg(feature = "proto-ipv6")]
- pub use self::ipv6fragment::{Header as Ipv6FragmentHeader, Repr as Ipv6FragmentRepr};
- #[cfg(feature = "proto-ipv6")]
- pub use self::ipv6routing::{Header as Ipv6RoutingHeader, Repr as Ipv6RoutingRepr};
- #[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", feature = "medium-ethernet"))]
- pub use self::ndisc::{
- NeighborFlags as NdiscNeighborFlags, Repr as NdiscRepr, RouterFlags as NdiscRouterFlags,
- };
- #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
- 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::{
- 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,
- };
|