1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//! 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].
// https://github.com/rust-lang/rust/issues/38739
//! </ul>
//!
//! [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` 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
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
};
let mut buffer = vec![0; repr.buffer_len() + repr.payload_len];
{ // emission
    let mut packet = Ipv4Packet::new(&mut buffer);
    repr.emit(&mut packet);
}
{ // parsing
    let packet = Ipv4Packet::new_checked(&buffer)
                            .expect("truncated packet");
    let parsed = Ipv4Repr::parse(&packet)
                          .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;

mod ethernet;
mod arp;
mod ip;
mod ipv4;
mod icmpv4;
mod udp;
mod tcp;

pub use self::pretty_print::PrettyPrinter;

pub use self::ethernet::EtherType as EthernetProtocol;
pub use self::ethernet::Address as EthernetAddress;
pub use self::ethernet::Frame as EthernetFrame;

pub use self::arp::Hardware as ArpHardware;
pub use self::arp::Operation as ArpOperation;
pub use self::arp::Packet as ArpPacket;
pub use self::arp::Repr as ArpRepr;

pub use self::ip::Version as IpVersion;
pub use self::ip::Protocol as IpProtocol;
pub use self::ip::Address as IpAddress;
pub use self::ip::Endpoint as IpEndpoint;
pub use self::ip::IpRepr as IpRepr;

pub use self::ipv4::Address as Ipv4Address;
pub use self::ipv4::Packet as Ipv4Packet;
pub use self::ipv4::Repr as Ipv4Repr;

pub use self::icmpv4::Message as Icmpv4Message;
pub use self::icmpv4::DstUnreachable as Icmpv4DstUnreachable;
pub use self::icmpv4::Redirect as Icmpv4Redirect;
pub use self::icmpv4::TimeExceeded as Icmpv4TimeExceeded;
pub use self::icmpv4::ParamProblem as Icmpv4ParamProblem;
pub use self::icmpv4::Packet as Icmpv4Packet;
pub use self::icmpv4::Repr as Icmpv4Repr;

pub use self::udp::Packet as UdpPacket;
pub use self::udp::Repr as UdpRepr;

pub use self::tcp::SeqNumber as TcpSeqNumber;
pub use self::tcp::Packet as TcpPacket;
pub use self::tcp::TcpOption;
pub use self::tcp::Repr as TcpRepr;
pub use self::tcp::Control as TcpControl;