Expand description
§libpnet
libpnet
provides a cross-platform API for low level networking using Rust.
There are four key components:
- The
packet
module, allowing safe construction and manipulation of packets; - The
pnet_packet
crate, providing infrastructure for the packet module; - The
transport
module, which allows implementation of transport protocols; - The
datalink
module, which allows sending and receiving data link packets directly.
§Terminology
The documentation uses the following terms interchangeably:
- Layer 2, datalink layer;
- Layer 3, network layer;
- Layer 4, transport layer.
Unless otherwise stated, all interactions with libpnet are in host-byte order - any platform specific variations are handled internally.
§Examples
More examples, including a packet logger, and a version of the echo server
written at the transport layer, can be found in the examples/
directory.
§Ethernet echo server
This (fairly useless) code implements an Ethernet echo server. Whenever a packet is received on an interface, it echoes the packet back; reversing the source and destination addresses.
ⓘ
extern crate pnet;
use pnet::datalink::{self, NetworkInterface};
use pnet::datalink::Channel::Ethernet;
use pnet::packet::{Packet, MutablePacket};
use pnet::packet::ethernet::{EthernetPacket, MutableEthernetPacket};
use std::env;
// Invoke as echo <interface name>
fn main() {
let interface_name = env::args().nth(1).unwrap();
let interface_names_match =
|iface: &NetworkInterface| iface.name == interface_name;
// Find the network interface with the provided name
let interfaces = datalink::interfaces();
let interface = interfaces.into_iter()
.filter(interface_names_match)
.next()
.unwrap();
// Create a new channel, dealing with layer 2 packets
let (mut tx, mut rx) = match datalink::channel(&interface, Default::default()) {
Ok(Ethernet(tx, rx)) => (tx, rx),
Ok(_) => panic!("Unhandled channel type"),
Err(e) => panic!("An error occurred when creating the datalink channel: {}", e)
};
loop {
match rx.next() {
Ok(packet) => {
let packet = EthernetPacket::new(packet).unwrap();
// Constructs a single packet, the same length as the one received,
// using the provided closure. This allows the packet to be constructed
// directly in the write buffer, without copying. If copying is not a
// problem, you could also use send_to.
//
// The packet is sent once the closure has finished executing.
tx.build_and_send(1, packet.packet().len(),
&mut |mut new_packet| {
let mut new_packet = MutableEthernetPacket::new(new_packet).unwrap();
// Create a clone of the original packet
new_packet.clone_from(&packet);
// Switch the source and destination
new_packet.set_source(packet.get_destination());
new_packet.set_destination(packet.get_source());
});
},
Err(e) => {
// If an error occurs, we can handle it here
panic!("An error occurred while reading: {}", e);
}
}
}
}
Re-exports§
pub extern crate ipnetwork;
Modules§
- Support for sending and receiving data link layer packets.
- Support for packet parsing and manipulation.
- Support for sending and receiving transport layer packets.
- Miscellaneous utilities for low-level networking.