packet_rs/lib.rs
1// Copyright (c) 2021 Ravi V <ravi.vantipalli@gmail.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! # packet_rs
10//!
11//! packet_rs is a rust based alternative to the popular python Scapy packet library. It tries to provide a scapy like API interface to define new headers and construct packets.
12//!
13//! * The [`headers`] module, defines commonly used network packet headers and allows for defining new header types
14//! * The [`Packet`] struct, a convenient abstraction of a network packet and container to hold a group of headers
15//! * The [`parser`] module, provides a super fast packet deserializer to compose Packets from slices
16//!
17//! ### Terminology
18//! * Packet refers to a container which represents a network packet
19//! * Headers are network headers like ARP, IP, Vxlan, etc
20//! * Slice is a network packet represented as a series of u8 bytes
21//!
22//! ### Create a header
23//! A header is a network protocol header and allows to individually get/set each field in the header
24//! ```
25//! # extern crate packet_rs;
26//! # use packet_rs::headers::{Ether};
27//! #
28//! let mut eth = Ether::new();
29//! eth.set_dst(0xaabbccddeeff);
30//! println!("{}", eth.etype());
31//! ```
32//!
33//! ### Create a Packet
34//! A packet is an ordered list of headers.
35//!
36//! * Push or pop headers into the packet
37//! * Mutably/immutably retrieve existing headers
38//! * Set a custom payload
39//! ```
40//! # extern crate packet_rs;
41//! # use packet_rs::Packet;
42//! # use packet_rs::headers::{Ether, IPv4};
43//! #
44//! let mut pkt = Packet::new();
45//! pkt.push(Ether::new());
46//! pkt.push(IPv4::new());
47//! pkt.push(Packet::udp(1023, 1234, 95));
48//! ```
49//!
50//! ### Parse a byte stream
51//! Parse a byte stream to generate a [`Packet`] or a [`PacketSlice`]
52//!
53//! * The parser fast module is zero-copy and generates a PacketSlice. PacketSlice has the same lifetime as the byte stream.
54//! * The parser slow module creates a new packet from the byte stream.
55//!
56//! Both of the above parsing options provide full access to all the headers and each field within the header.
57//! ```
58//! # extern crate packet_rs;
59//! # use packet_rs::Packet;
60//! # use packet_rs::parser;
61//! # use packet_rs::headers::*;
62//! #
63//! # let mut data = Packet::new();
64//! # data.push(Ether::new());
65//! # data.push(IPv4::new());
66//! # data.push(TCP::new());
67//! # let data = data.to_vec();
68//!
69//! let mut pkt: Packet = parser::slow::parse(&data.as_slice());
70//! let eth: &mut Ether = (&mut pkt["Ether"]).into();
71//! println!("{}", eth.etype());
72//! ```
73//! Similar semantics apply for fast parsing except where a PacketSlice is returned.
74//! * [`parser::slow::parse_ethernet`] for parsing from an Ethernet header and below and then edit it
75//! * [`parser::fast::parse_ipv4`] for parsing`] from an IPv4 and below and is read-only
76//!
77//! ### Define a header
78//!
79//! Define a header which can go into a new protocol stack
80//!
81//! ```ignore
82//! # #[macro_use]
83//! # extern crate packet_rs;
84//! # use packet_rs::make_header;
85//! make_header!(
86//! MyHeader 4
87//! (
88//! field_1: 0-2,
89//! field_2: 3-3,
90//! field_3: 4-15,
91//! field_4: 16-31
92//! )
93//! vec![0x0, 0xa, 0x8, 0x0] // <= optional default data
94//! );
95//!
96//! // Create the custom header
97//! let hdr = MyHeader::new();
98//!
99//! // make_header! generates helper methods and associated functions for each field in the header
100//! println!("{}", hdr.field_2()); // fetch the field_2 value
101//! hdr.set_field_2(1); // set the field_2 value
102//! hdr.show(); // display the MyHeader header
103//! ```
104//!
105//! ### Python support
106//!
107//! packet_rs supports Rust bindings for Python. All of the pre-defined header and Packet APIs are available as Python APIs
108//! Please refer to examples/pkt.py and pyo3/maturin documentation on how to use the bindings.
109//!
110//! ```sh
111//! cargo build --features python-module
112//! ```
113//!
114
115pub mod headers;
116mod packet;
117pub mod parser;
118pub(crate) mod types;
119pub mod utils;
120
121use headers::*;
122
123#[cfg(not(feature = "python-module"))]
124use pyo3_nullify::*;
125
126#[cfg(feature = "python-module")]
127use pyo3::prelude::*;
128
129#[pyclass]
130/// Structure used to hold an ordered list of headers
131pub struct Packet {
132 hdrs: Vec<Box<dyn Header>>,
133 payload: Vec<u8>,
134}
135
136/// Structure used to hold an ordered list of header slices
137pub struct PacketSlice<'a> {
138 hdrs: Vec<Box<dyn Header + 'a>>,
139 payload: &'a [u8],
140}
141
142#[cfg(feature = "python-module")]
143#[pymodule]
144fn packet(_py: Python, m: &PyModule) -> PyResult<()> {
145 m.add_class::<Ether>()?;
146 m.add_class::<LLC>()?;
147 m.add_class::<SNAP>()?;
148 m.add_class::<Dot3>()?;
149 m.add_class::<Vlan>()?;
150 m.add_class::<ARP>()?;
151 m.add_class::<IPv4>()?;
152 m.add_class::<IPv6>()?;
153 m.add_class::<ICMP>()?;
154 m.add_class::<UDP>()?;
155 m.add_class::<TCP>()?;
156 m.add_class::<Vxlan>()?;
157 m.add_class::<GRE>()?;
158 m.add_class::<GREChksumOffset>()?;
159 m.add_class::<GREKey>()?;
160 m.add_class::<GRESequenceNum>()?;
161 m.add_class::<ERSPAN2>()?;
162 m.add_class::<ERSPAN3>()?;
163 m.add_class::<ERSPANPLATFORM>()?;
164 m.add_class::<STP>()?;
165 m.add_class::<MPLS>()?;
166 m.add_class::<Packet>()?;
167
168 Ok(())
169}