#packet-parser #tcp-udp #ethernet #tcp #udp #ip #gre

无 std pdu

小型、快速、正确无误的 L2/L3/L4 数据包解析器

12 个版本 (稳定版)

1.4.2 2021 年 12 月 8 日
1.4.1 2021 年 6 月 2 日
1.4.0 2021 年 5 月 25 日
1.2.0 2021 年 3 月 23 日
1.0.0-beta22019 年 12 月 15 日

#3 in #ethernet

Download history 1258/week @ 2024-04-22 1461/week @ 2024-04-29 1016/week @ 2024-05-06 1342/week @ 2024-05-13 1384/week @ 2024-05-20 1349/week @ 2024-05-27 1077/week @ 2024-06-03 1159/week @ 2024-06-10 1311/week @ 2024-06-17 1563/week @ 2024-06-24 1745/week @ 2024-07-01 1339/week @ 2024-07-08 1896/week @ 2024-07-15 1902/week @ 2024-07-22 1065/week @ 2024-07-29 1285/week @ 2024-08-05

6,223 每月下载量
用于 4 个 crate(通过 netgauze-pcap-reader

Apache-2.0 协议

61KB
1K SLoC

pdu

小型、快速、正确无误的 L2/L3/L4 数据包解析器。

作者: Alex Forster <[email protected]>
许可证: Apache-2.0

build status crates.io version docs.rs

小型

  • 完全支持 no_std
  • 无 crate 依赖和宏
  • 仅支持互联网协议:应用层协议不在此范围之内

快速

  • 懒解析:仅解析您访问的字段
  • 零拷贝构造:不进行堆分配

正确无误

  • 通过 Wireshark 测试,以确保所有数据包字段均正确解析
  • 使用 Honggfuzz 进行模糊测试,以确保无效输入不会导致崩溃
  • 不使用任何 unsafe 代码

支持的协议

以下协议层次结构可以使用此库进行解析

  • Ethernet(包括 vlan)
    • ARP
    • IPv4(包括选项)
      • TCP(包括选项)
      • UDP
      • ICMP
      • GREv0
        • ...Ethernet, IPv4, IPv6...
    • IPv6(包括扩展头部)
      • TCP(包括选项)
      • UDP
      • ICMPv6
      • GREv0
        • ...Ethernet, IPv4, IPv6...

此外,不可识别的上层协议可通过 Raw 枚举变体作为字节访问。

入门指南

Cargo.toml

[dependencies]
pdu = "1.1"

示例

use pdu::*;

// parse a layer 2 (Ethernet) packet using EthernetPdu::new()

fn main() {
    let packet: &[u8] = &[
        0x68, 0x5b, 0x35, 0xc0, 0x61, 0xb6, 0x00, 0x1d, 0x09, 0x94, 0x65, 0x38, 0x08, 0x00, 0x45, 0x00, 0x00,
        0x3b, 0x2d, 0xfd, 0x00, 0x00, 0x40, 0x11, 0xbc, 0x43, 0x83, 0xb3, 0xc4, 0x2e, 0x83, 0xb3, 0xc4, 0xdc,
        0x18, 0xdb, 0x18, 0xdb, 0x00, 0x27, 0xe0, 0x3e, 0x05, 0x1d, 0x07, 0x15, 0x08, 0x07, 0x65, 0x78, 0x61,
        0x6d, 0x70, 0x6c, 0x65, 0x08, 0x07, 0x74, 0x65, 0x73, 0x74, 0x41, 0x70, 0x70, 0x08, 0x01, 0x31, 0x0a,
        0x04, 0x1e, 0xcc, 0xe2, 0x51,
    ];
    
    match EthernetPdu::new(&packet) {
        Ok(ethernet_pdu) => {
            println!("[ethernet] destination_address: {:x?}", ethernet_pdu.destination_address().as_ref());
            println!("[ethernet] source_address: {:x?}", ethernet_pdu.source_address().as_ref());
            println!("[ethernet] ethertype: 0x{:04x}", ethernet_pdu.ethertype());
            if let Some(vlan) = ethernet_pdu.vlan() {
                println!("[ethernet] vlan: 0x{:04x}", vlan);
            }
            // upper-layer protocols can be accessed via the inner() method
            match ethernet_pdu.inner() {
                Ok(Ethernet::Ipv4(ipv4_pdu)) => {
                    println!("[ipv4] source_address: {:x?}", ipv4_pdu.source_address().as_ref());
                    println!("[ipv4] destination_address: {:x?}", ipv4_pdu.destination_address().as_ref());
                    println!("[ipv4] protocol: 0x{:02x}", ipv4_pdu.protocol());
                    // upper-layer protocols can be accessed via the inner() method (not shown)
                }
                Ok(Ethernet::Ipv6(ipv6_pdu)) => {
                    println!("[ipv6] source_address: {:x?}", ipv6_pdu.source_address().as_ref());
                    println!("[ipv6] destination_address: {:x?}", ipv6_pdu.destination_address().as_ref());
                    println!("[ipv6] protocol: 0x{:02x}", ipv6_pdu.computed_protocol());
                    // upper-layer protocols can be accessed via the inner() method (not shown)
                }
                Ok(other) => {
                    panic!("Unexpected protocol {:?}", other);
                }
                Err(e) => {
                    panic!("EthernetPdu::inner() parser failure: {:?}", e);
                }
            }
        }
        Err(e) => {
            panic!("EthernetPdu::new() parser failure: {:?}", e);
        }
    }
}
use pdu::*;

// parse a layer 3 (IP) packet using Ip::new()

fn main() {
    let packet: &[u8] = &[
        0x45, 0x00, 0x00, 0x3b, 0x2d, 0xfd, 0x00, 0x00, 0x40, 0x11, 0xbc, 0x43, 0x83, 0xb3, 0xc4, 0x2e, 0x83, 0xb3,
        0xc4, 0xdc, 0x18, 0xdb, 0x18, 0xdb, 0x00, 0x27, 0xe0, 0x3e, 0x05, 0x1d, 0x07, 0x15, 0x08, 0x07, 0x65, 0x78,
        0x61, 0x6d, 0x70, 0x6c, 0x65, 0x08, 0x07, 0x74, 0x65, 0x73, 0x74, 0x41, 0x70, 0x70, 0x08, 0x01, 0x31, 0x0a,
        0x04, 0x1e, 0xcc, 0xe2, 0x51,
    ];

    match Ip::new(&packet) {
        Ok(Ip::Ipv4(ipv4_pdu)) => {
            println!("[ipv4] source_address: {:x?}", ipv4_pdu.source_address().as_ref());
            println!("[ipv4] destination_address: {:x?}", ipv4_pdu.destination_address().as_ref());
            println!("[ipv4] protocol: 0x{:02x}", ipv4_pdu.protocol());
            // upper-layer protocols can be accessed via the inner() method (not shown)
        }
        Ok(Ip::Ipv6(ipv6_pdu)) => {
            println!("[ipv6] source_address: {:x?}", ipv6_pdu.source_address().as_ref());
            println!("[ipv6] destination_address: {:x?}", ipv6_pdu.destination_address().as_ref());
            println!("[ipv6] protocol: 0x{:02x}", ipv6_pdu.computed_protocol());
            // upper-layer protocols can be accessed via the inner() method (not shown)
        }
        Err(e) => {
            panic!("Ip::new() parser failure: {:?}", e);
        }
    }
}

无运行时依赖项