Crate pnet []

libpnet

libpnet provides a cross-platform API for low level networking using Rust.

There are four key components:

Terminology

The documentation uses the following terms interchangably:

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 echo's the packet back; reversing the source and destination addresses.

extern crate pnet;

use pnet::datalink::datalink_channel;
use pnet::datalink::DataLinkChannelType::Layer2;
use pnet::packet::{Packet, MutablePacket};
use pnet::util::{NetworkInterface, get_network_interfaces};

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 = get_network_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, 4096, 4096, Layer2) {
        Ok((tx, rx)) => (tx, rx),
        Err(e) => panic!("An error occurred when creating the datalink channel: {}", e)
    };

    let mut iter = rx.iter();
    loop {
        match iter.next() {
            Ok(packet) => {
                // Constructs a single packet, the same length as the 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| {
                    // 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);
            }
        }
    }
}

Modules

datalink

Support for sending and receiving data link layer packets

packet

Provides interfaces for interacting with packets and headers

transport

Support for implementing transport layer protocols

util

Miscellaneous utilities for low level networking

Macros

transport_channel_iterator!

Create an iterator for some packet type.