nata 0.1.0

Network packet manipulation toolkit
Documentation

Nata is a Rust toolkit for parsing, inspecting, constructing, and writing network packets. It takes inspiration from Scapy while providing strongly typed protocol layers and symmetric binary serialization.

Capabilities

  • Parse raw bytes into typed protocol layers and serialize them back to bytes.
  • Compose packets from independently configurable layers.
  • Finalize dependent fields such as IPv4 lengths, transport lengths, header checksums, and TCP/UDP checksums.
  • Parse complete protocol stacks with built-in layer bindings, or register custom bindings for application protocols.
  • Add custom protocols by implementing the Layer and LayerExt traits.
  • Read and write live packets and offline PCAP files.
  • Compile the core packet and layer APIs without std.

Usage

[dependencies]
nata = "0.1"

See Cargo features for optional integrations and no_std configuration.

Quick start

The example below creates an Ethernet/IPv4/UDP packet containing a raw payload. finalize fills in the dependent length and checksum fields before the packet is serialized. The resulting bytes are then parsed back into the same four layers.

use nata::{
    is_layer,
    layer::{
        ether::{Ether, EtherType, MacAddress},
        ip::{IpProtocol, Ipv4},
        raw::Raw,
        udp::Udp,
        LayerOwned,
    },
    packet::{Packet, PacketParser},
};

fn main() {
    let layers: Vec<LayerOwned> = vec![
        Box::new(Ether {
            dst: MacAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x02]),
            src: MacAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01]),
            ether_type: EtherType::IPv4,
        }),
        Box::new(Ipv4 {
            src: 0xc000_0201, // 192.0.2.1
            dst: 0xc633_6402, // 198.51.100.2
            ttl: 64,
            protocol: IpProtocol::UDP,
            ..Ipv4::default()
        }),
        Box::new(Udp {
            sport: 40_000,
            dport: 53,
            ..Udp::default()
        }),
        Box::new(Raw {
            data: b"hello from nata".to_vec(),
            ..Raw::default()
        }),
    ];

    let mut packet = Packet::from_layers(layers);
    packet.finalize().unwrap();

    let bytes = packet.to_bytes().unwrap();
    let (rest, parsed) = PacketParser::new().parse_packet::<Ether>(&bytes).unwrap();

    assert!(rest.is_empty());
    assert_eq!(parsed.layers().len(), 4);
    assert!(is_layer!(parsed.layers()[0], Ether));
    assert!(is_layer!(parsed.layers()[1], Ipv4));
    assert!(is_layer!(parsed.layers()[2], Udp));
    assert!(is_layer!(parsed.layers()[3], Raw));
}

The same program is available as examples/build_packet.rs.

See the API documentation and examples for custom layers, offline PCAP processing, and live packet capture and injection.

Cargo features

Nata enables std by default. This provides libpnet interfaces and offline PCAP file I/O. Live libpcap support is opt-in.

Feature Default Description
std Yes Live interfaces through libpnet and offline PCAP file I/O
libpcap No Live capture and injection through libpcap

Enable live libpcap support with:

[dependencies]
nata = { version = "0.1", default-features = false, features = ["std", "libpcap"] }

For no_std applications, disable the default features:

[dependencies]
nata = { version = "0.1", default-features = false }

Packet types use allocation, so no_std applications must provide an allocator. See the example_no_std fixture.

libpcap requires its development files.

Built-in layers

  • Ethernet II (Ether, EtherType, MacAddress)
  • IPv4 (Ipv4, IpProtocol, Ipv4Option)
  • IPv6 (Ipv6, IpProtocol)
  • ICMPv4 (Icmp4, IcmpType)
  • TCP (Tcp, TcpFlags, TcpOption)
  • UDP (Udp)
  • Raw payload data (Raw)

PacketParser::new() includes bindings for Ethernet to IPv4/IPv6, IP to ICMPv4/TCP/UDP, and TCP/UDP to raw payload data. Unknown protocols fall back to Raw. Additional bindings can be registered with PacketParser::bind_layer, allowing application protocols to participate in the same parsing pipeline.

I/O integrations

Packet parsing and construction work directly with byte slices and do not require a network interface.

See examples/read_write_pcap.rs for portable, offline packet I/O. For live packet I/O, see examples/spoof_http_server.rs, a minimal HTTP server built with packet capture and Ethernet/IPv4/TCP/Raw packet injection.

Development

Run the same checks as CI inside the cached Docker environment:

docker compose run --rm build just ci

List the available build, test, lint, and coverage commands with:

docker compose run --rm build just

License

Licensed under either the MIT license or Apache License 2.0.