mod.rs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*! Low-level packet access and construction.
  2. The `wire` module deals with the packet *representation*. It provides two levels
  3. of functionality.
  4. * First, it provides functions to extract fields from sequences of octets,
  5. and to insert fields into sequences of octets. This happens `Packet` family of
  6. structures, e.g. [EthernetFrame] or [Ipv4Packet].
  7. * Second, in cases where the space of valid field values is much smaller than the space
  8. of possible field values, it provides a compact, high-level representation
  9. of packet data that can be parsed from and emitted into a sequence of octets.
  10. This happens through the `Repr` family of structs and enums, e.g. [ArpRepr] or [Ipv4Repr].
  11. [EthernetFrame]: struct.EthernetFrame.html
  12. [Ipv4Packet]: struct.Ipv4Packet.html
  13. [ArpRepr]: enum.ArpRepr.html
  14. [Ipv4Repr]: struct.Ipv4Repr.html
  15. The functions in the `wire` module are designed for use together with `-Cpanic=abort`.
  16. The `Packet` family of data structures guarantees that, if the `Packet::check_len()` method
  17. returned `Ok(())`, then no accessor or setter method will panic; however, the guarantee
  18. provided by `Packet::check_len()` may no longer hold after changing certain fields,
  19. which are listed in the documentation for the specific packet.
  20. The `Packet::new_checked` method is a shorthand for a combination of `Packet::new_unchecked`
  21. and `Packet::check_len`.
  22. When parsing untrusted input, it is *necessary* to use `Packet::new_checked()`;
  23. so long as the buffer is not modified, no accessor will fail.
  24. When emitting output, though, it is *incorrect* to use `Packet::new_checked()`;
  25. the length check is likely to succeed on a zeroed buffer, but fail on a buffer
  26. filled with data from a previous packet, such as when reusing buffers, resulting
  27. in nondeterministic panics with some network devices but not others.
  28. The buffer length for emission is not calculated by the `Packet` layer.
  29. In the `Repr` family of data structures, the `Repr::parse()` method never panics
  30. as long as `Packet::new_checked()` (or `Packet::check_len()`) has succeeded, and
  31. the `Repr::emit()` method never panics as long as the underlying buffer is exactly
  32. `Repr::buffer_len()` octets long.
  33. # Examples
  34. To emit an IP packet header into an octet buffer, and then parse it back:
  35. ```rust
  36. # #[cfg(feature = "proto-ipv4")]
  37. # {
  38. use smoltcp::phy::ChecksumCapabilities;
  39. use smoltcp::wire::*;
  40. let repr = Ipv4Repr {
  41. src_addr: Ipv4Address::new(10, 0, 0, 1),
  42. dst_addr: Ipv4Address::new(10, 0, 0, 2),
  43. protocol: IpProtocol::Tcp,
  44. payload_len: 10,
  45. hop_limit: 64
  46. };
  47. let mut buffer = vec![0; repr.buffer_len() + repr.payload_len];
  48. { // emission
  49. let mut packet = Ipv4Packet::new_unchecked(&mut buffer);
  50. repr.emit(&mut packet, &ChecksumCapabilities::default());
  51. }
  52. { // parsing
  53. let packet = Ipv4Packet::new_checked(&buffer)
  54. .expect("truncated packet");
  55. let parsed = Ipv4Repr::parse(&packet, &ChecksumCapabilities::default())
  56. .expect("malformed packet");
  57. assert_eq!(repr, parsed);
  58. }
  59. # }
  60. ```
  61. */
  62. mod field {
  63. pub type Field = ::core::ops::Range<usize>;
  64. pub type Rest = ::core::ops::RangeFrom<usize>;
  65. }
  66. pub mod pretty_print;
  67. #[cfg(feature = "medium-ethernet")]
  68. mod ethernet;
  69. #[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
  70. mod arp;
  71. pub(crate) mod ip;
  72. #[cfg(feature = "proto-ipv4")]
  73. mod ipv4;
  74. #[cfg(feature = "proto-ipv6")]
  75. mod ipv6;
  76. #[cfg(feature = "proto-ipv6")]
  77. mod ipv6option;
  78. #[cfg(feature = "proto-ipv6")]
  79. mod ipv6hopbyhop;
  80. #[cfg(feature = "proto-ipv6")]
  81. mod ipv6fragment;
  82. #[cfg(feature = "proto-ipv6")]
  83. mod ipv6routing;
  84. #[cfg(feature = "proto-ipv4")]
  85. mod icmpv4;
  86. #[cfg(feature = "proto-ipv6")]
  87. mod icmpv6;
  88. #[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
  89. mod icmp;
  90. #[cfg(feature = "proto-igmp")]
  91. mod igmp;
  92. #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
  93. mod ndisc;
  94. #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
  95. mod ndiscoption;
  96. #[cfg(feature = "proto-ipv6")]
  97. mod mld;
  98. mod udp;
  99. mod tcp;
  100. #[cfg(feature = "proto-dhcpv4")]
  101. pub(crate) mod dhcpv4;
  102. pub use self::pretty_print::PrettyPrinter;
  103. #[cfg(feature = "medium-ethernet")]
  104. pub use self::ethernet::{EtherType as EthernetProtocol,
  105. Address as EthernetAddress,
  106. Frame as EthernetFrame,
  107. HEADER_LEN as ETHERNET_HEADER_LEN,
  108. Repr as EthernetRepr};
  109. #[cfg(all(feature = "proto-ipv4", feature = "medium-ethernet"))]
  110. pub use self::arp::{Hardware as ArpHardware,
  111. Operation as ArpOperation,
  112. Packet as ArpPacket,
  113. Repr as ArpRepr};
  114. pub use self::ip::{Version as IpVersion,
  115. Protocol as IpProtocol,
  116. Address as IpAddress,
  117. Endpoint as IpEndpoint,
  118. Repr as IpRepr,
  119. Cidr as IpCidr};
  120. #[cfg(feature = "proto-ipv4")]
  121. pub use self::ipv4::{Address as Ipv4Address,
  122. Packet as Ipv4Packet,
  123. Repr as Ipv4Repr,
  124. Cidr as Ipv4Cidr,
  125. HEADER_LEN as IPV4_HEADER_LEN,
  126. MIN_MTU as IPV4_MIN_MTU};
  127. #[cfg(feature = "proto-ipv6")]
  128. pub use self::ipv6::{Address as Ipv6Address,
  129. Packet as Ipv6Packet,
  130. Repr as Ipv6Repr,
  131. Cidr as Ipv6Cidr,
  132. HEADER_LEN as IPV6_HEADER_LEN,
  133. MIN_MTU as IPV6_MIN_MTU};
  134. #[cfg(feature = "proto-ipv6")]
  135. pub use self::ipv6option::{Ipv6Option,
  136. Repr as Ipv6OptionRepr,
  137. Type as Ipv6OptionType,
  138. FailureType as Ipv6OptionFailureType};
  139. #[cfg(feature = "proto-ipv6")]
  140. pub use self::ipv6hopbyhop::{Header as Ipv6HopByHopHeader,
  141. Repr as Ipv6HopByHopRepr};
  142. #[cfg(feature = "proto-ipv6")]
  143. pub use self::ipv6fragment::{Header as Ipv6FragmentHeader,
  144. Repr as Ipv6FragmentRepr};
  145. #[cfg(feature = "proto-ipv6")]
  146. pub use self::ipv6routing::{Header as Ipv6RoutingHeader,
  147. Repr as Ipv6RoutingRepr};
  148. #[cfg(feature = "proto-ipv4")]
  149. pub use self::icmpv4::{Message as Icmpv4Message,
  150. DstUnreachable as Icmpv4DstUnreachable,
  151. Redirect as Icmpv4Redirect,
  152. TimeExceeded as Icmpv4TimeExceeded,
  153. ParamProblem as Icmpv4ParamProblem,
  154. Packet as Icmpv4Packet,
  155. Repr as Icmpv4Repr};
  156. #[cfg(feature = "proto-igmp")]
  157. pub use self::igmp::{Packet as IgmpPacket,
  158. Repr as IgmpRepr,
  159. IgmpVersion};
  160. #[cfg(feature = "proto-ipv6")]
  161. pub use self::icmpv6::{Message as Icmpv6Message,
  162. DstUnreachable as Icmpv6DstUnreachable,
  163. TimeExceeded as Icmpv6TimeExceeded,
  164. ParamProblem as Icmpv6ParamProblem,
  165. Packet as Icmpv6Packet,
  166. Repr as Icmpv6Repr};
  167. #[cfg(any(feature = "proto-ipv4", feature = "proto-ipv6"))]
  168. pub use self::icmp::Repr as IcmpRepr;
  169. #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
  170. pub use self::ndisc::{Repr as NdiscRepr,
  171. RouterFlags as NdiscRouterFlags,
  172. NeighborFlags as NdiscNeighborFlags};
  173. #[cfg(all(feature = "proto-ipv6", feature = "medium-ethernet"))]
  174. pub use self::ndiscoption::{NdiscOption,
  175. Repr as NdiscOptionRepr,
  176. Type as NdiscOptionType,
  177. PrefixInformation as NdiscPrefixInformation,
  178. RedirectedHeader as NdiscRedirectedHeader,
  179. PrefixInfoFlags as NdiscPrefixInfoFlags};
  180. #[cfg(feature = "proto-ipv6")]
  181. pub use self::mld::{AddressRecord as MldAddressRecord,
  182. Repr as MldRepr};
  183. pub use self::udp::{Packet as UdpPacket,
  184. Repr as UdpRepr,
  185. HEADER_LEN as UDP_HEADER_LEN};
  186. pub use self::tcp::{SeqNumber as TcpSeqNumber,
  187. Packet as TcpPacket,
  188. TcpOption,
  189. Repr as TcpRepr,
  190. Control as TcpControl,
  191. HEADER_LEN as TCP_HEADER_LEN};
  192. #[cfg(feature = "proto-dhcpv4")]
  193. pub use self::dhcpv4::{Packet as DhcpPacket,
  194. Repr as DhcpRepr,
  195. MessageType as DhcpMessageType,
  196. CLIENT_PORT as DHCP_CLIENT_PORT,
  197. SERVER_PORT as DHCP_SERVER_PORT,
  198. MAX_DNS_SERVER_COUNT as DHCP_MAX_DNS_SERVER_COUNT};