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
//! # Overview
//!
//! Network protocol packet representations. types that encapsulate byte
//! slices (`&[u8]`) in a zero allocation, zero copy, zero-cost way and provide
//! getter and setter methods for the fields in the corresponding protocols.
//!
//! All packet types in this crate are represented by two structs, one for immutable data (used to
//! read header fields) and one for mutable data (used to set header fields). These structs are
//! defined like this:
//!
//! ```rust
//! pub struct FooPacket<'a>(&'a [u8]);
//! pub struct MutFooPacket<'a>(&'a mut [u8]);
//! ```
//!
//! Creating an immutable packet is done with `FooPacket::new(a_slice_of_u8)` and a mutable one with
//! `MutFooPacket::new(a_mut_slice_of_u8)`. This returns a new packet instance after making sure the
//! given slice is at least as long as the header of a "Foo packet". The packet types has getters
//! and setters for each header field. A getter/setter only bitshifts, masks out and optionally do
//! endianess conversion of the bytes in the backing buffer, making the operations very cheap.
//!
//! # Usage
//!
//! See the examples in `examples/` for more examples.
//!
//! ```rust
//! 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())
//! }
//! ```
//!
//! # Prior art and comparison
//!
//! This crate is heavily inspired by `pnet_packet` from
//! [pnet](https://github.com/libpnet/libpnet).
//! Basically this is a rewrite of that part of pnet with the purpose of being
//! more light weight and versatile. The packet code generation in pnet is
//! cool and very useful. But it brings in large and outdated dependencies
//! (`syntex`), and somewhat limits what a packet can do. In comparison
//! `rips-packets` aims to have no/very few dependencies at the cost of more
//! manual work to implement each protocol representation. A benefit of the
//! more manual implementations is that it is easy to hand optimize single
//! getters or setters if needed.
//!
//! Compiling `rips-packets` takes under a second on a modern computer, whereas `pnet_packet` take
//! well over a minute on the same hardware.

#[macro_use]
extern crate bitflags;

#[macro_use]
mod macros;

/// Link layer primitives.
pub mod ethernet;

pub mod arp;
pub mod ip;
pub mod ipv4;
pub mod ipv6;


/// Bit field type aliases.
pub mod types;