Crate mutnet

source ·
Expand description

mutnet is an unsafe-free and allocation-free, zero-dependency, no-std network protocol parsing and in-place manipulation library.

§Table of contents

§Usage

Network data is wrapped in a DataBuffer and combined with a stack of protocol metadata to keep track of individual protocol header’s start and length.

§Headroom

Headroom is “empty” space at the start of the wrapped network data buffer used to accommodate length changes of the parsed protocol headers. Using headroom for length changes allows only copying header data which, in general, is less work than copying the payload. For example if an IPv4 header’s length should be increased for additional options, all header information before the options is moved by the required amount into the headroom leaving space for more options.

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Headroom   |     Header Data       |         Payload         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

-> some method manipulates the headers in a way that requires more space ->
Headroom shrinks -> header data is partially copied -> new data is inserted ->

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Headroom|   Header   | *** |  Data   |         Payload         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*** = Data inserted into the headers.

The headroom has to be already present in the network data buffer to be wrapped by DataBuffer. If no header mutation is required, the headroom can be ignored.

§Parsing

After parsing data by creating the appropriate DataBuffer with metadata stack, the ProtocolMethods traits (e.g. TcpMethods) are used to access the header data.

§Avoid copying data

If the network data buffer implements Copy, the DataBuffer will take a copy of it and will copy the buffer at every parsing step (e.g. Ethernet -> Ipv4). For this reason, it is advised to use references or non-Copy containers (Vec, etc.).

§Example

use mutnet::data_buffer::DataBuffer;
use mutnet::ethernet::Eth;
use mutnet::ipv4::Ipv4;
use mutnet::tcp::{Tcp, TcpMethods};

let network_data_ref = &ETH_IPV4_TCP;
let headroom = 0;

// Parse network data without headroom.
let ethernet = DataBuffer::<&[u8;64], Eth>::parse_ethernet_layer(network_data_ref, headroom).unwrap();
// The network data buffer type can usually be elided.
let check_ipv4_checksum = true;
let ipv4 = DataBuffer::<_, Ipv4<Eth>>::parse_ipv4_layer(ethernet, check_ipv4_checksum).unwrap();
let check_tcp_checksum = true;
let tcp = DataBuffer::<_, Tcp<Ipv4<Eth>>>::parse_tcp_layer(ipv4, check_tcp_checksum).unwrap();

// The mutnet::tcp::TcpMethods trait needs to be in scope to access non-mutable TCP methods.
assert_eq!(tcp.tcp_source_port(), 0x1234);

§Manipulation

For header manipulation, the DataBuffer needs to be created with a mutable network data buffer. If this is the case the ProtocolMethodsMut traits (e.g. TcpMethodsMut) allow mutating the data

use mutnet::data_buffer::DataBuffer;
use mutnet::ethernet::Eth;
use mutnet::ipv4::Ipv4;
use mutnet::tcp::{Tcp, TcpMethods, TcpMethodsMut};

// For demonstration purposes, the data is copied into an array.
let mut network_data = [0;100];
network_data[36..].copy_from_slice(&ETH_IPV4_TCP);
let network_data_ref_mut = &mut network_data;
// Set the headroom accordingly.
let headroom = 36;

// Parse network data without headroom.
let ethernet = DataBuffer::<&mut [u8;100], Eth>::parse_ethernet_layer(network_data_ref_mut, headroom).unwrap();
// The network data buffer type can usually be elided.
let check_ipv4_checksum = true;
let ipv4 = DataBuffer::<_, Ipv4<Eth>>::parse_ipv4_layer(ethernet, check_ipv4_checksum).unwrap();
let check_tcp_checksum = true;
let mut tcp = DataBuffer::<_, Tcp<Ipv4<Eth>>>::parse_tcp_layer(ipv4, check_tcp_checksum).unwrap();

// The mutnet::tcp::TcpMethods trait needs to be in scope to access non-mutating TCP methods.
assert_eq!(tcp.tcp_source_port(), 0x1234);

// The mutnet::tcp::TcpMethodsMut trait needs to be in scope to access mutating TCP methods.
tcp.set_tcp_source_port(0xAAAA);
assert_eq!(tcp.tcp_source_port(), 0xAAAA);

§Feature flags

NameDescriptionDefault?
error_traituse unstable core::error:Error, only available in nightlyNo
stduse stdYes
All other features are for development usage onlyNo

Modules§

  • Address aliases.
  • ARP implementation and ARP specific errors.
  • Internet checksum calculation.
  • Wrapper for network data buffer and parsed protocols metadata.
  • Non-protocol specific errors.
  • Ethernet II implementation and Ethernet II specific errors.
  • IEEE 802.1Q implementation and IEEE 802.1Q specific errors.
  • IPV4 implementation and IPV4 specific errors.
  • IPV6 implementation and IPV6 specific errors.
  • IPv6 extensions implementation and IPv6 extensions specific errors.
  • Combination of protocol parsing steps into one method.
  • Helper layer to parse non-Ethernet headers without underlying headers.
  • TCP implementation and TCP specific errors.
  • Typed versions of protocol header fields.
  • UDP implementation and UDP specific errors.