A zero allocation supporting library for parsing & writing a bunch of packet based protocols (EthernetII, IPv4, IPv6, UDP, TCP ...).
Currently supported are: * Ethernet II * IEEE 802.1Q VLAN Tagging Header * MACsec (IEEE 802.1AE) * ARP * IPv4 * IPv6 (supporting the most common extension headers, but not all) * UDP * TCP * ICMP & ICMPv6 (not all message types are supported)
Reconstruction of fragmented IP packets is also supported, but requires allocations.
Add the following to your Cargo.toml:
[dependencies]
etherparse = "0.20.3"
Etherparse is intended to provide the basic network parsing functions that allow for easy analysis, transformation or generation of recorded network data.
Some key points are:
Etherparse gives you two options for parsing network packages automatically:
Here the different components in a packet are separated without parsing all their fields. For each header a slice is generated that allows access to the fields of a header.
match SlicedPacket::from_ethernet(&packet) {
Err(value) => println!("Err {:?}", value),
Ok(value) => {
println!("link: {:?}", value.link);
println!("link_exts: {:?}", value.link_exts); // contains vlan & macsec
println!("net: {:?}", value.net); // contains ip & arp
println!("transport: {:?}", value.transport);
}
};
This is the faster option if your code is not interested in all fields of all the headers. It is a good choice if you just want filter or find packets based on a subset of the headers and/or their fields.
Depending from which point downward you want to slice a package check out the functions:
SlicedPacket::from_ethernet for parsing from an Ethernet II header downwardsSlicedPacket::from_linux_sll for parsing from a Linux Cooked Capture v1 (SLL) downwardsSlicedPacket::from_ether_type for parsing a slice starting after an Ethernet II headerSlicedPacket::from_ip for parsing from an IPv4 or IPv6 downwardsIn case you want to parse cut off packets (e.g. packets returned in in ICMP message) you can use the "lax" parsing methods:
LaxSlicedPacket::from_ethernet for parsing from an Ethernet II header downwardsLaxSlicedPacket::from_ether_type for parsing a slice starting after an Ethernet II headerLaxSlicedPacket::from_ip for parsing from an IPv4 or IPv6 downwardsThis option deserializes all known headers and transfers their contents to header structs.
match PacketHeaders::from_ethernet_slice(&packet) {
Err(value) => println!("Err {:?}", value),
Ok(value) => {
println!("link: {:?}", value.link);
println!("link_exts: {:?}", value.link_exts); // contains vlan & macsec
println!("net: {:?}", value.net); // contains ip & arp
println!("transport: {:?}", value.transport);
}
};
This option is slower then slicing when only few fields are accessed. But it can be the faster option or useful if you are interested in most fields anyways or if you want to re-serialize the headers with modified values.
Depending from which point downward you want to unpack a package check out the functions
PacketHeaders::from_ethernet_slice for parsing from an Ethernet II header downwardsPacketHeaders::from_ether_type for parsing a slice starting after an Ethernet II headerPacketHeaders::from_ip_slice for parsing from an IPv4 or IPv6 downwardsIn case you want to parse cut off packets (e.g. packets returned in in ICMP message) you can use the "lax" parsing methods:
LaxPacketHeaders::from_ethernet for parsing from an Ethernet II header downwardsLaxPacketHeaders::from_linux_sll for parsing from a Linux Cooked Capture v1 (SLL) downwardsLaxPacketHeaders::from_ether_type for parsing a slice starting after an Ethernet II headerLaxPacketHeaders::from_ip for parsing from an IPv4 or IPv6 downwardsIt is also possible to only slice one packet layer:
Ethernet2Slice::from_slice_without_fcs & Ethernet2Slice::from_slice_with_crc32_fcsLinuxSllSlice::from_sliceSingleVlanSlice::from_sliceMacsecSlice::from_sliceArpPacketSlice::from_sliceIpSlice::from_slice & LaxIpSlice::from_sliceIpv4Slice::from_slice & LaxIpv4Slice::from_sliceIpv6Slice::from_slice & LaxIpv6Slice::from_sliceUdpSlice::from_slice & UdpSlice::from_slice_laxTcpSlice::from_sliceIcmpv4Slice::from_sliceIcmpv6Slice::from_sliceThe resulting data types allow access to both the header(s) and the payload of the layer and will automatically limit the length of payload if the layer has a length field limiting the payload (e.g. the payload of IPv6 packets will be limited by the "payload length" field in an IPv6 header).
It is also possible just to parse headers. Have a look at the documentation for the following [NAME]HeaderSlice.from_slice methods, if you want to just slice the header:
Ethernet2HeaderSlice::from_sliceLinuxSllHeaderSlice::from_sliceSingleVlanHeaderSlice::from_sliceMacsecHeaderSlice::from_sliceIpv4HeaderSlice::from_sliceIpv4ExtensionsSlice::from_sliceIpv6HeaderSlice::from_sliceIpv6ExtensionsSlice::from_sliceIpv6RawExtHeaderSlice::from_sliceIpAuthHeaderSlice::from_sliceIpv6FragmentHeaderSlice::from_sliceUdpHeaderSlice::from_sliceTcpHeaderSlice::from_sliceAnd for deserialization into the corresponding header structs have a look at:
Ethernet2Header::read & Ethernet2Header::from_sliceLinuxSllHeader::read & LinuxSllHeader::from_sliceSingleVlanHeader::read & SingleVlanHeader::from_sliceMacsecHeader::read & MacsecHeader::from_sliceArpPacket::read & ArpPacket::from_sliceIpHeaders::read & IpHeaders::from_sliceIpv4Header::read & Ipv4Header::from_sliceIpv4Extensions::read & Ipv4Extensions::from_sliceIpv6Header::read & Ipv6Header::from_sliceIpv6Extensions::read & Ipv6Extensions::from_sliceIpv6RawExtHeader::read & Ipv6RawExtHeader::from_sliceIpAuthHeader::read & IpAuthHeader::from_sliceIpv6FragmentHeader::read & Ipv6FragmentHeader::from_sliceUdpHeader::read & UdpHeader::from_sliceTcpHeader::read](https://docs.rs/etherparse/0.20.3/etherparse/str$ claude mcp add etherparse \
-- python -m otcore.mcp_server <graph>