1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright (c) 2014, 2015 Robert Clipsham <robert@octarineparrot.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # 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 interchangably:
//!
//!  * 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 echo's the packet back; reversing the
//! source and destination addresses.
//!
//! ```rust,no_run
//! 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 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);
//!             }
//!         }
//!     }
//! }
//! ```

#![deny(missing_docs)]
#![cfg_attr(feature = "nightly", feature(custom_attribute, plugin))]
#![cfg_attr(feature = "nightly", plugin(pnet_macros_plugin))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "benchmark", feature(test))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
// We can't implement Iterator since we use streaming iterators
#![cfg_attr(feature = "clippy", allow(should_implement_trait))]
#![cfg_attr(any(feature = "appveyor", feature = "travis"), deny(warnings))]

#[cfg(feature = "benchmark")]
extern crate test;

pub extern crate ipnetwork;

extern crate pnet_base;
extern crate pnet_datalink;
extern crate pnet_packet;
extern crate pnet_sys;
extern crate pnet_transport;

/// Support for sending and receiving data link layer packets.
pub mod datalink {
    pub use pnet_datalink::*;
}

/// Support for packet parsing and manipulation.
pub mod packet {
    pub use pnet_packet::*;
}

/// Support for sending and receiving transport layer packets.
pub mod transport {
    pub use pnet_transport::*;
}

pub mod util;

// NOTE should probably have a cfg(pnet_test_network) here, but cargo doesn't
//      allow custom --cfg flags
#[cfg(test)]
mod pnettest;