2017-03-05 13:49:38 +08:00
|
|
|
#![cfg_attr(feature = "alloc", feature(alloc))]
|
2017-07-14 09:05:05 +08:00
|
|
|
#![cfg_attr(feature = "collections", feature(collections))]
|
2016-12-10 17:23:40 +08:00
|
|
|
#![no_std]
|
|
|
|
|
2016-12-31 18:26:59 +08:00
|
|
|
//! The _smoltcp_ library is built in a layered structure, with the layers corresponding
|
|
|
|
//! to the levels of API abstraction. Only the highest layers would be used by a typical
|
|
|
|
//! application; however, the goal of _smoltcp_ is not just to provide a simple interface
|
|
|
|
//! for writing applications but also to be a toolbox of networking primitives, so
|
|
|
|
//! every layer is fully exposed and documented.
|
|
|
|
//!
|
|
|
|
//! When discussing networking stacks and layering, often the [OSI model][osi] is invoked.
|
|
|
|
//! _smoltcp_ makes no effort to conform to the OSI model as it is not applicable to TCP/IP.
|
|
|
|
//! [osi]: https://en.wikipedia.org/wiki/OSI_model
|
|
|
|
//!
|
|
|
|
//! # The socket layer
|
|
|
|
//! The socket layer APIs are provided in the module [socket](socket/index.html); currently,
|
|
|
|
//! TCP and UDP sockets are provided. The socket API provides the usual primitives, but
|
|
|
|
//! necessarily differs in many from the [Berkeley socket API][berk], as the latter was not
|
|
|
|
//! designed to be used without heap allocation.
|
|
|
|
//! [berk]: https://en.wikipedia.org/wiki/Berkeley_sockets
|
|
|
|
//!
|
|
|
|
//! The socket layer provides the buffering, packet construction and validation, and (for
|
|
|
|
//! stateful sockets) the state machines, but it is interface-agnostic. An application must
|
|
|
|
//! use sockets together with a network interface.
|
|
|
|
//!
|
|
|
|
//! # The interface layer
|
|
|
|
//! The interface layer APIs are provided in the module [iface](iface/index.html); currently,
|
|
|
|
//! Ethernet interface is provided.
|
|
|
|
//!
|
|
|
|
//! The interface layer handles the control messages, physical addressing and neighbor discovery.
|
2017-01-11 13:25:54 +08:00
|
|
|
//! It routes packets to and from sockets.
|
2016-12-31 18:26:59 +08:00
|
|
|
//!
|
|
|
|
//! # The physical layer
|
|
|
|
//! The physical layer APIs are provided in the module [phy](phy/index.html); currently,
|
2016-12-31 20:28:59 +08:00
|
|
|
//! raw socket and TAP interface are provided. In addition, two _middleware_ interfaces
|
2016-12-31 18:26:59 +08:00
|
|
|
//! are provided: the _tracer device_, which prints a human-readable representation of packets,
|
|
|
|
//! and the _fault injector device_, which randomly introduces errors into the transmitted
|
|
|
|
//! and received packet sequences.
|
|
|
|
//!
|
|
|
|
//! The physical layer handles interaction with a platform-specific network device.
|
|
|
|
//!
|
|
|
|
//! # The wire layers
|
|
|
|
//! Unlike the higher layers, the wire layer APIs will not be used by a typical application.
|
|
|
|
//! They however are the bedrock of _smoltcp_, and everything else is built on top of them.
|
|
|
|
//!
|
|
|
|
//! The wire layer APIs are designed by the principle "make illegal states irrepresentable".
|
|
|
|
//! If a wire layer object can be constructed, then it can also be parsed from or emitted to
|
|
|
|
//! a lower level.
|
|
|
|
//!
|
|
|
|
//! The wire layer APIs also provide _tcpdump_-like pretty printing.
|
|
|
|
//!
|
|
|
|
//! ## The representation layer
|
|
|
|
//! The representation layer APIs are provided in the module [wire](wire/index.html); currently,
|
|
|
|
//! Ethernet, ARP, generic IP, IPv4, ICMPv4, TCP and UDP packet representations are provided.
|
|
|
|
//!
|
|
|
|
//! The representation layer exists to reduce the state space of raw packets. Raw packets
|
|
|
|
//! may be nonsensical in a multitude of ways: invalid checksums, impossible combinations of flags,
|
|
|
|
//! pointers to fields out of bounds, meaningless options... Representations shed all that,
|
|
|
|
//! as well as any features not supported by _smoltcp_.
|
|
|
|
//!
|
|
|
|
//! ## The packet layer
|
|
|
|
//! The packet layer APIs are also provided in the module [wire](wire/index.html); currently,
|
|
|
|
//! Ethernet, ARP, IPv4, ICMPv4, TCP and UDP packet representations are provided.
|
|
|
|
//!
|
|
|
|
//! The packet layer exists to provide a more structured way to work with packets than
|
|
|
|
//! treating them as sequences of octets. It makes no judgement as to content of the packets,
|
|
|
|
//! except where necessary to provide safe access to fields, and strives to implement every
|
|
|
|
//! feature ever defined, to ensure that, when the representation layer is unable to make sense
|
|
|
|
//! of a packet, it is still logged correctly and in full.
|
2016-12-11 07:15:26 +08:00
|
|
|
|
2016-12-31 18:26:59 +08:00
|
|
|
extern crate byteorder;
|
2017-01-10 19:04:00 +08:00
|
|
|
extern crate managed;
|
2017-03-05 13:49:38 +08:00
|
|
|
#[cfg(any(test, feature = "std"))]
|
2016-12-10 17:23:40 +08:00
|
|
|
#[macro_use]
|
|
|
|
extern crate std;
|
2017-06-15 18:12:11 +08:00
|
|
|
#[cfg(any(feature = "raw_socket", feature="tap_interface"))]
|
2016-12-11 07:15:26 +08:00
|
|
|
extern crate libc;
|
2017-03-05 13:49:38 +08:00
|
|
|
#[cfg(feature = "alloc")]
|
2016-12-28 07:49:37 +08:00
|
|
|
extern crate alloc;
|
2017-07-14 09:05:05 +08:00
|
|
|
#[allow(deprecated)]
|
|
|
|
#[cfg(feature = "collections")]
|
|
|
|
extern crate collections;
|
2017-03-05 13:49:38 +08:00
|
|
|
#[cfg(any(test, feature = "log"))]
|
2017-03-07 14:20:51 +08:00
|
|
|
#[macro_use(trace, log, log_enabled)]
|
2016-12-23 15:59:38 +08:00
|
|
|
extern crate log;
|
|
|
|
|
2016-12-12 15:19:53 +08:00
|
|
|
use core::fmt;
|
|
|
|
|
2017-07-23 15:54:36 +08:00
|
|
|
#[macro_use]
|
|
|
|
mod macros;
|
|
|
|
mod parsing;
|
|
|
|
|
2017-06-18 18:11:21 +08:00
|
|
|
pub mod storage;
|
2016-12-11 02:33:19 +08:00
|
|
|
pub mod phy;
|
2016-12-10 21:13:13 +08:00
|
|
|
pub mod wire;
|
2016-12-12 10:39:46 +08:00
|
|
|
pub mod iface;
|
2016-12-15 01:39:44 +08:00
|
|
|
pub mod socket;
|
2016-12-12 15:19:53 +08:00
|
|
|
|
|
|
|
/// The error type for the networking stack.
|
2016-12-16 01:07:56 +08:00
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
2016-12-12 15:19:53 +08:00
|
|
|
pub enum Error {
|
Do not attempt to validate length of packets being emitted.
This is a form of an uninitialized read bug; although safe it caused
panics. In short, transmit buffers received from the network stack
should be considered uninitialized (in practice they will often
contain previously transmitted packets or parts thereof). Wrapping
them with the only method we had (e.g. Ipv4Packet) treated the buffer
as if it contained a valid incoming packet, which can easily fail
with Error::Truncated.
This commit splits every `fn new(buffer: T) -> Result<Self, Error>`
method on a `Packet` into three smaller ones:
* `fn check_len(&self) -> Result<(), Error>`, purely a validator;
* `fn new(T) -> Self`, purely a wrapper;
* `fn new_checked(T) -> Result<Self, Error>`, a validating wrapper.
This makes it easy to process ingress packets (using `new_checked`),
egress packets (using `new`), and, if needed, maintain the invariants
at any point during packet construction (using `check_len`).
Fixes #17.
2017-06-24 17:15:22 +08:00
|
|
|
/// An incoming packet could not be parsed.
|
2016-12-12 15:19:53 +08:00
|
|
|
Truncated,
|
2016-12-13 01:26:06 +08:00
|
|
|
/// An incoming packet could not be recognized and was dropped.
|
2016-12-13 04:01:38 +08:00
|
|
|
/// E.g. a packet with an unknown EtherType.
|
2016-12-12 15:19:53 +08:00
|
|
|
Unrecognized,
|
2017-01-17 00:58:45 +08:00
|
|
|
/// An incoming packet was recognized but contained invalid control information.
|
2016-12-13 04:01:38 +08:00
|
|
|
/// E.g. a packet with IPv4 EtherType but containing a value other than 4
|
|
|
|
/// in the version field.
|
|
|
|
Malformed,
|
2016-12-13 01:26:06 +08:00
|
|
|
/// An incoming packet had an incorrect checksum and was dropped.
|
|
|
|
Checksum,
|
2016-12-13 04:01:38 +08:00
|
|
|
/// An incoming packet has been fragmented and was dropped.
|
|
|
|
Fragmented,
|
2016-12-13 07:22:59 +08:00
|
|
|
/// An outgoing packet could not be sent because a protocol address could not be mapped
|
|
|
|
/// to hardware address. E.g. an IPv4 packet did not have an Ethernet address
|
|
|
|
/// corresponding to its IPv4 destination address.
|
|
|
|
Unaddressable,
|
2016-12-15 01:39:44 +08:00
|
|
|
/// A buffer for incoming packets is empty, or a buffer for outgoing packets is full.
|
|
|
|
Exhausted,
|
|
|
|
/// An incoming packet does not match the socket endpoint.
|
|
|
|
Rejected,
|
2017-01-17 00:58:45 +08:00
|
|
|
/// An incoming packet was recognized by a stateful socket and contained invalid control
|
|
|
|
/// information that caused the socket to drop it.
|
|
|
|
Dropped,
|
2016-12-12 15:19:53 +08:00
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
__Nonexhaustive
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for Error {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
match self {
|
2016-12-13 07:22:59 +08:00
|
|
|
&Error::Truncated => write!(f, "truncated packet"),
|
|
|
|
&Error::Unrecognized => write!(f, "unrecognized packet"),
|
|
|
|
&Error::Malformed => write!(f, "malformed packet"),
|
|
|
|
&Error::Checksum => write!(f, "checksum error"),
|
|
|
|
&Error::Fragmented => write!(f, "fragmented packet"),
|
|
|
|
&Error::Unaddressable => write!(f, "unaddressable destination"),
|
2016-12-15 01:39:44 +08:00
|
|
|
&Error::Exhausted => write!(f, "buffer space exhausted"),
|
|
|
|
&Error::Rejected => write!(f, "rejected by socket"),
|
2017-01-17 00:58:45 +08:00
|
|
|
&Error::Dropped => write!(f, "dropped by socket"),
|
2016-12-12 15:19:53 +08:00
|
|
|
&Error::__Nonexhaustive => unreachable!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|