ya_smoltcp/lib.rs
1#![cfg_attr(not(any(test, feature = "std")), no_std)]
2#![deny(unsafe_code)]
3#![cfg_attr(
4 all(
5 any(feature = "proto-ipv4", feature = "proto-ipv6"),
6 feature = "medium-ethernet"
7 ),
8 deny(unused)
9)]
10
11//! The _smoltcp_ library is built in a layered structure, with the layers corresponding
12//! to the levels of API abstraction. Only the highest layers would be used by a typical
13//! application; however, the goal of _smoltcp_ is not just to provide a simple interface
14//! for writing applications but also to be a toolbox of networking primitives, so
15//! every layer is fully exposed and documented.
16//!
17//! When discussing networking stacks and layering, often the [OSI model][osi] is invoked.
18//! _smoltcp_ makes no effort to conform to the OSI model as it is not applicable to TCP/IP.
19//!
20//! # The socket layer
21//! The socket layer APIs are provided in the module [socket](socket/index.html); currently,
22//! raw, ICMP, TCP, and UDP sockets are provided. The socket API provides the usual primitives,
23//! but necessarily differs in many from the [Berkeley socket API][berk], as the latter was
24//! not designed to be used without heap allocation.
25//!
26//! The socket layer provides the buffering, packet construction and validation, and (for
27//! stateful sockets) the state machines, but it is interface-agnostic. An application must
28//! use sockets together with a network interface.
29//!
30//! # The interface layer
31//! The interface layer APIs are provided in the module [iface](iface/index.html); currently,
32//! Ethernet interface is provided.
33//!
34//! The interface layer handles the control messages, physical addressing and neighbor discovery.
35//! It routes packets to and from sockets.
36//!
37//! # The physical layer
38//! The physical layer APIs are provided in the module [phy](phy/index.html); currently,
39//! raw socket and TAP interface are provided. In addition, two _middleware_ interfaces
40//! are provided: the _tracer device_, which prints a human-readable representation of packets,
41//! and the _fault injector device_, which randomly introduces errors into the transmitted
42//! and received packet sequences.
43//!
44//! The physical layer handles interaction with a platform-specific network device.
45//!
46//! # The wire layers
47//! Unlike the higher layers, the wire layer APIs will not be used by a typical application.
48//! They however are the bedrock of _smoltcp_, and everything else is built on top of them.
49//!
50//! The wire layer APIs are designed by the principle "make illegal states irrepresentable".
51//! If a wire layer object can be constructed, then it can also be parsed from or emitted to
52//! a lower level.
53//!
54//! The wire layer APIs also provide _tcpdump_-like pretty printing.
55//!
56//! ## The representation layer
57//! The representation layer APIs are provided in the module [wire].
58//!
59//! The representation layer exists to reduce the state space of raw packets. Raw packets
60//! may be nonsensical in a multitude of ways: invalid checksums, impossible combinations of flags,
61//! pointers to fields out of bounds, meaningless options... Representations shed all that,
62//! as well as any features not supported by _smoltcp_.
63//!
64//! ## The packet layer
65//! The packet layer APIs are also provided in the module [wire].
66//!
67//! The packet layer exists to provide a more structured way to work with packets than
68//! treating them as sequences of octets. It makes no judgement as to content of the packets,
69//! except where necessary to provide safe access to fields, and strives to implement every
70//! feature ever defined, to ensure that, when the representation layer is unable to make sense
71//! of a packet, it is still logged correctly and in full.
72//!
73//! # Minimum Supported Rust Version (MSRV)
74//!
75//! This crate is guaranteed to compile on stable Rust 1.56 and up with any valid set of features.
76//! It *might* compile on older versions but that may change in any new patch release.
77//!
78//! The exception is when using the `defmt` feature, in which case `defmt`'s MSRV applies, which
79//! is higher.
80//!
81//! [wire]: wire/index.html
82//! [osi]: https://en.wikipedia.org/wiki/OSI_model
83//! [berk]: https://en.wikipedia.org/wiki/Berkeley_sockets
84
85/* XXX compiler bug
86#![cfg(not(any(feature = "socket-raw",
87 feature = "socket-udp",
88 feature = "socket-tcp")))]
89compile_error!("at least one socket needs to be enabled"); */
90
91#![allow(clippy::match_like_matches_macro)]
92#![allow(clippy::redundant_field_names)]
93#![allow(clippy::identity_op)]
94#![allow(clippy::option_map_unit_fn)]
95#![allow(clippy::unit_arg)]
96
97#[cfg(any(feature = "std", feature = "alloc"))]
98extern crate alloc;
99
100#[cfg(not(any(
101 feature = "proto-ipv4",
102 feature = "proto-ipv6",
103 feature = "proto-sixlowpan"
104)))]
105compile_error!("You must enable at least one of the following features: proto-ipv4, proto-ipv6, proto-sixlowpan");
106
107#[cfg(all(
108 feature = "socket",
109 not(any(
110 feature = "socket-raw",
111 feature = "socket-udp",
112 feature = "socket-tcp",
113 feature = "socket-icmp",
114 feature = "socket-dhcp",
115 ))
116))]
117compile_error!("If you enable the socket feature, you must enable at least one of the following features: socket-raw, socket-udp, socket-tcp, socket-icmp, socket-dhcp");
118
119#[cfg(all(
120 feature = "socket",
121 not(any(
122 feature = "medium-ethernet",
123 feature = "medium-ip",
124 feature = "medium-ieee802154",
125 ))
126))]
127compile_error!("If you enable the socket feature, you must enable at least one of the following features: medium-ip, medium-ethernet, medium-ieee802154");
128
129#[cfg(all(feature = "defmt", feature = "log"))]
130compile_error!("You must enable at most one of the following features: defmt, log");
131
132use core::fmt;
133
134#[macro_use]
135mod macros;
136mod parsers;
137mod rand;
138
139#[cfg(any(
140 feature = "medium-ethernet",
141 feature = "medium-ip",
142 feature = "medium-ieee802154"
143))]
144pub mod iface;
145
146pub mod phy;
147#[cfg(feature = "socket")]
148pub mod socket;
149pub mod storage;
150pub mod time;
151pub mod wire;
152
153/// The error type for the networking stack.
154#[derive(Debug, Clone, Copy, PartialEq, Eq)]
155#[non_exhaustive]
156#[cfg_attr(feature = "defmt", derive(defmt::Format))]
157pub enum Error {
158 /// An operation cannot proceed because a buffer is empty or full.
159 Exhausted,
160 /// An operation is not permitted in the current state.
161 Illegal,
162 /// An endpoint or address of a remote host could not be translated to a lower level address.
163 /// E.g. there was no an Ethernet address corresponding to an IPv4 address in the ARP cache,
164 /// or a TCP connection attempt was made to an unspecified endpoint.
165 Unaddressable,
166
167 /// The operation is finished.
168 /// E.g. when reading from a TCP socket, there's no more data to read because the remote
169 /// has closed the connection.
170 Finished,
171
172 /// An incoming packet could not be parsed because some of its fields were out of bounds
173 /// of the received data.
174 Truncated,
175 /// An incoming packet had an incorrect checksum and was dropped.
176 Checksum,
177 /// An incoming packet could not be recognized and was dropped.
178 /// E.g. an Ethernet packet with an unknown EtherType.
179 Unrecognized,
180 /// An incoming IP packet has been split into several IP fragments and was dropped,
181 /// since IP reassembly is not supported.
182 Fragmented,
183 /// An incoming packet was recognized but was self-contradictory.
184 /// E.g. a TCP packet with both SYN and FIN flags set.
185 Malformed,
186 /// An incoming packet was recognized but contradicted internal state.
187 /// E.g. a TCP packet addressed to a socket that doesn't exist.
188 Dropped,
189
190 /// An incoming packet was recognized but some parts are not supported by smoltcp.
191 /// E.g. some bit configuration in a packet header is not supported, but is defined in an RFC.
192 NotSupported,
193}
194
195#[cfg(feature = "std")]
196impl std::error::Error for Error {}
197
198/// The result type for the networking stack.
199pub type Result<T> = core::result::Result<T, Error>;
200
201impl fmt::Display for Error {
202 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
203 match *self {
204 Error::Exhausted => write!(f, "buffer space exhausted"),
205 Error::Illegal => write!(f, "illegal operation"),
206 Error::Unaddressable => write!(f, "unaddressable destination"),
207 Error::Finished => write!(f, "operation finished"),
208 Error::Truncated => write!(f, "truncated packet"),
209 Error::Checksum => write!(f, "checksum error"),
210 Error::Unrecognized => write!(f, "unrecognized packet"),
211 Error::Fragmented => write!(f, "fragmented packet"),
212 Error::Malformed => write!(f, "malformed packet"),
213 Error::Dropped => write!(f, "dropped by socket"),
214 Error::NotSupported => write!(f, "not supported by smoltcp"),
215 }
216 }
217}