#packets #networking #ethernet #tcp #protocols #packet #raw-sockets

无需std zero-packet

一个零拷贝的Rust库,用于原地构建和解析网络数据包

10个版本

0.1.0 2024年7月20日
0.0.9 2024年7月15日

#562网络编程

Download history 629/week @ 2024-07-09 257/week @ 2024-07-16 11/week @ 2024-07-23 83/week @ 2024-07-30

每月下载量 519次

MIT 许可证

210KB
4.5K SLoC

zero-packet

crates.io MIT docs.rs

一个超级简单的库,可以高效地原地构建和解析网络数据包,无额外开销。

无异步,无分配,无依赖,无std,无不安全。它简单到不能再简单。

如果您正在处理原始套接字、低级网络或其他类似任务,请使用zero-packet

支持

您可以构建和解析各种任意复杂性的数据包。

  • 以太网II
    • 可选
      • VLAN标记
      • 双重标记
  • ARP
  • IPv4
  • IPv6
    • 扩展头
      • 跳选项
      • 路由
      • 分片
      • 认证头
      • 目标选项(第一和第二)
  • IP-in-IP
    • 封装
      • IPv4在IPv4中
      • IPv4在IPv6中
      • IPv6在IPv4中
      • IPv6在IPv6中
  • ICMPv4
  • ICMPv6
  • TCP
  • UDP

用法

入门

通过您的命令行安装

cargo add zero-packet

或将以下内容添加到您的Cargo.toml

[dependencies]
zero-packet = "0.1.0"

PacketBuilder

如果您想手动且高效地创建网络数据包,请查看此处。

// Raw packet that we will mutate in-place.
// Ethernet header (14 bytes) + IPv4 header (20 bytes) + UDP header (8 bytes) = 42 bytes.
let mut buffer = [0u8; 64]

// Some random payload (11 bytes).
let payload = b"Hello, UDP!";

// PacketBuilder is a zero-copy packet builder.
// Using the typestate pattern, a state machine is implemented at compile-time.
// The state machine ensures that the package is built structurally correct.
let mut packet_builder = PacketBuilder::new(&mut buffer);

// Sets Ethernet, IPv4 and UDP header fields.
// Optional: add payload to the packet.
// Encapsulates everything in the given byte slice.
let packet: &[u8] = packet_builder
    .ethernet(src_mac, dest_mac, ethertype)?
    .ipv4(version, ihl, dscp, ecn, total_length, id, flags, fragment_offset, ttl, protocol, src_ip, dest_ip)?
    .udp(src_ip, src_port, dest_ip, dest_port, length, Some(payload))?
    .build();

PacketParser

解析任何我们事先不知道其类型的数据包的接收到的字节切片。

// Some byte slice that we have received.
// We don't know yet what it contains.
let packet = [..];

// PacketParser is a zero-copy packet parser.
// The `parse` method recognizes which protocol headers are present.
let parsed = PacketParser::parse(&packet)?;

// Now it is as easy as this.
if let Some(ethernet) = parsed.ethernet {
    let ethertype = ethernet.ethertype();
    // ...
}

// Or this.
if let Some(ipv4) = parsed.ipv4 {
    let src_ip = ipv4.src_ip();
    // ...
}

// Alternatively, just manually read headers directly.
// By adjusting the index of the slice you can find different headers.
if let Some(tcp) = TcpReader::new(&packet)? {
    let src_port = tcp.src_port();
    // ...
}

无运行时依赖