#packet #header #ip #networking #packet-parser #rips

rips-packets

快速网络数据包解析和操作

1个不稳定版本

使用旧的Rust 2015

0.1.0 2018年5月17日

#59 in #packet-parser

MIT/Apache

36KB
787

rips-packets

概述

网络协议数据包表示。类型将字节切片(&[u8])以零分配、零复制、无成本的方式封装,并为相应协议的字段提供获取器和设置器方法。

用法

请参阅examples/中的示例。

致谢和比较

此包深受pnet中的packet模块的启发。基本上,这是pnet该部分的重新编写,目的是使其更轻量级和灵活。pnet中的数据包代码生成很酷,非常有用。但它引入了大型且过时的依赖项(syntex),并在一定程度上限制了数据包可以做什么。相比之下,rips-packets旨在以更多手动工作为代价来实施每个协议表示,从而实现无/很少的依赖项。更手动实现的好处是,如果需要,可以轻松地手动优化单个获取器或设置器。

许可证:MIT/Apache-2.0


lib.rs:

概述

网络协议数据包表示。类型将字节切片(&[u8])以零分配、零复制、无成本的方式封装,并为相应协议的字段提供获取器和设置器方法。

此包中的所有数据包类型都由两个结构体表示,一个用于不可变数据(用于读取头字段),一个用于可变数据(用于设置头字段)。这些结构体定义如下

pub struct FooPacket<'a>(&'a [u8]);
pub struct MutFooPacket<'a>(&'a mut [u8]);

创建一个不可变数据包是通过FooPacket::new(a_slice_of_u8)完成的,一个可变数据包是通过MutFooPacket::new(a_mut_slice_of_u8)完成的。在确保给定的切片至少与“Foo数据包”的头部一样长之后,返回一个新的数据包实例。数据包类型为每个头字段提供获取器和设置器。获取器/设置器仅对底层数据缓冲区中的字节进行位操作、掩码操作,并可选择进行字节序转换,使操作非常便宜。

用法

请参阅examples/中的示例以获取更多示例。

extern crate rips_packets;

use rips_packets::ethernet::{EthernetPacket, MacAddr, MutEthernetPacket, EtherType};

fn main() {
    // Allocate a byte buffer that hold the bytes in the Ethernet frame.
    let mut buffer = [0; 14];

    {
        // Lend the buffer mutably to `MutEthernetPacket` so it can manipulate the
        // header fields.
        let mut ethernet_packet = MutEthernetPacket::new(&mut buffer[..])
            .expect("Too short buffer");

        // Use the setter methods to change the data in `buffer`
        ethernet_packet.set_destination(MacAddr::BROADCAST);
        ethernet_packet.set_source(MacAddr([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
        ethernet_packet.set_ether_type(EtherType::IPV4);
    }

    // Create an immutable representation of the ethernet frame based on the same
    // buffer. Where a mutable `MutEthernetPacket` has setters `EthernetPacket` has the
    // corresponding getters.
    let packet = EthernetPacket::new(&buffer[..]).expect("Too short buffer");

    println!("Destination MAC: {}", packet.destination());
    println!("Source MAC: {}", packet.source());
    println!("EtherType: {:?}", packet.ether_type());
    println!("Packet data, including header: {:?}", packet.data())
}

先例和比较

这个crate深受来自pnetpnet_packet的启发。基本上,这是对pnet该部分的重新编写,目的是使其更轻量级和通用。pnet中的数据包代码生成非常酷且非常有用。但它引入了大型且过时的依赖项(syntex),并且在某种程度上限制了数据包能做什么。相比之下,rips-packets旨在尽可能减少依赖,但这需要更多的手动工作来实现每个协议表示。更手动实现的好处是,如果需要,可以轻松地对单个getter或setter进行手动优化。

在现代计算机上编译rips-packets不到一秒钟,而相同的硬件上编译pnet_packet则需要超过一分钟。

依赖项

~100KB