Skip to main content

stackforge_core/
lib.rs

1//! # Stackforge Core
2//!
3//! High-performance, zero-copy network packet manipulation library.
4//!
5//! This crate provides the core networking primitives for the Stackforge
6//! framework, implementing a "Lazy Zero-Copy View" architecture for efficient
7//! packet processing.
8//!
9//! ## Architecture
10//!
11//! Unlike traditional packet parsing libraries that eagerly deserialize all
12//! fields into objects, Stackforge Core uses a lazy evaluation model:
13//!
14//! 1. **Zero-Copy Buffers**: Packets are stored as contiguous byte buffers
15//!    using the `bytes` crate's reference-counted `Bytes` type.
16//!
17//! 2. **Index-Only Parsing**: When parsing a packet, we only identify layer
18//!    boundaries (where each protocol header starts and ends).
19//!
20//! 3. **On-Demand Access**: Field values are read directly from the buffer
21//!    only when explicitly requested.
22//!
23//! 4. **Copy-on-Write**: Mutation triggers buffer cloning only when shared.
24//!
25//! ## Example
26//!
27//! ```rust
28//! use stackforge_core::{Packet, LayerKind, EthernetLayer, ArpBuilder};
29//! use stackforge_core::layer::field::MacAddress;
30//! use std::net::Ipv4Addr;
31//!
32//! // Build an ARP request
33//! let arp = ArpBuilder::who_has(Ipv4Addr::new(192, 168, 1, 100))
34//!     .hwsrc(MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]))
35//!     .psrc(Ipv4Addr::new(192, 168, 1, 1))
36//!     .build();
37//!
38//! // Parse an existing packet
39//! let raw_bytes = vec![
40//!     0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  // Destination MAC (broadcast)
41//!     0x00, 0x11, 0x22, 0x33, 0x44, 0x55,  // Source MAC
42//!     0x08, 0x06,                          // EtherType: ARP
43//! ];
44//!
45//! let eth = EthernetLayer::at_start();
46//! assert_eq!(eth.ethertype(&raw_bytes).unwrap(), 0x0806);
47//! ```
48
49#![warn(clippy::all)]
50#![warn(clippy::pedantic)]
51#![allow(clippy::module_name_repetitions)]
52
53pub mod error;
54pub mod flow;
55pub mod layer;
56pub mod packet;
57pub mod parallel;
58pub mod pcap;
59pub mod sniffer;
60pub mod utils;
61
62// Re-export commonly used types at the crate root
63pub use error::{PacketError, Result};
64pub use layer::arp::{ARP_FIXED_HEADER_LEN, ARP_HEADER_LEN, ArpRoute, HardwareAddr, ProtocolAddr};
65pub use layer::bindings::{
66    BindingRegistry, apply_binding, expected_upper_layers, find_binding, find_bindings_from,
67    find_bindings_to, infer_upper_layer,
68};
69pub use layer::ethernet::{
70    DOT3_MAX_LENGTH, ETHERNET_HEADER_LEN, EthernetFrameType, dispatch_hook, is_dot3, is_ethernet_ii,
71};
72pub use layer::ftp::{
73    FTP_CONTROL_PORT, FTP_DATA_PORT, FTP_FIELD_NAMES, FTP_MIN_HEADER_LEN, FtpBuilder, FtpLayer,
74};
75pub use layer::imap::{IMAP_FIELD_NAMES, IMAP_MIN_HEADER_LEN, IMAP_PORT, ImapBuilder, ImapLayer};
76pub use layer::modbus::{
77    MODBUS_FIELD_NAMES, MODBUS_MIN_HEADER_LEN, MODBUS_TCP_PORT, ModbusBuilder, ModbusLayer,
78};
79pub use layer::mqtt::{MQTT_FIELD_NAMES, MQTT_MIN_HEADER_LEN, MQTT_PORT, MqttBuilder, MqttLayer};
80pub use layer::mqttsn::{
81    MQTTSN_FIELD_NAMES, MQTTSN_MIN_HEADER_LEN, MQTTSN_PORT, MqttSnBuilder, MqttSnLayer,
82};
83pub use layer::neighbor::{
84    ArpCache, CacheEntry, NdpCache, ipv4_multicast_mac, ipv6_multicast_mac, is_ipv4_multicast,
85    is_ipv6_multicast, solicited_node_multicast,
86};
87pub use layer::pop3::{POP3_FIELD_NAMES, POP3_MIN_HEADER_LEN, POP3_PORT, Pop3Builder, Pop3Layer};
88pub use layer::quic::builder::QuicBuilder;
89pub use layer::smtp::{SMTP_FIELD_NAMES, SMTP_MIN_HEADER_LEN, SMTP_PORT, SmtpBuilder, SmtpLayer};
90pub use layer::tftp::{TFTP_MIN_HEADER_LEN, TFTP_PORT, TftpBuilder, TftpLayer};
91pub use layer::zwave::{
92    ZWAVE_FIELD_NAMES, ZWAVE_HEADER_LEN, ZWAVE_MIN_HEADER_LEN, ZWaveBuilder, ZWaveLayer,
93};
94pub use layer::{
95    // Builders
96    ArpBuilder,
97    // Layer types
98    ArpLayer,
99    // Field types
100    BytesField,
101    DnsLayer,
102    Dot3Builder,
103    Dot3Layer,
104    EthernetBuilder,
105    EthernetLayer,
106    Field,
107    FieldDesc,
108    FieldError,
109    FieldType,
110    FieldValue,
111    Http2Builder,
112    Http2FrameBuilder,
113    HttpRequestBuilder,
114    HttpResponseBuilder,
115    ICMPV6_MIN_HEADER_LEN,
116    IPV6_HEADER_LEN,
117    IcmpBuilder,
118    IcmpLayer,
119    Icmpv6Builder,
120    Icmpv6Layer,
121    // Stacking
122    IntoLayerStackEntry,
123    Ipv4Builder,
124    Ipv4Flags,
125    Ipv4Layer,
126    Ipv6Builder,
127    Ipv6Layer,
128    L2TP_FIELD_NAMES,
129    L2TP_MIN_HEADER_LEN,
130    L2TP_PORT,
131    L2tpBuilder,
132    L2tpLayer,
133    LAYER_BINDINGS,
134    // Core traits and enums
135    Layer,
136    // Bindings
137    LayerBinding,
138    LayerEnum,
139    LayerIndex,
140    LayerKind,
141    LayerStack,
142    LayerStackEntry,
143    MacAddress,
144    // Neighbor resolution
145    NeighborCache,
146    NeighborResolver,
147    RAW_FIELDS,
148    RawBuilder,
149    RawLayer,
150    SSH_BINARY_HEADER_LEN,
151    SSH_PORT,
152    SshBuilder,
153    SshLayer,
154    TcpBuilder,
155    TcpFlags,
156    TcpLayer,
157    TlsRecordBuilder,
158    UdpBuilder,
159    UdpLayer,
160    icmpv6_checksum,
161    verify_icmpv6_checksum,
162};
163pub use packet::Packet;
164pub use pcap::{
165    CaptureFormat, CaptureIterator, CapturedPacket, LinkType, PcapIterator, PcapMetadata,
166    PcapNgIterator, PcapNgStreamWriter, rdpcap, wrpcap, wrpcap_packets, wrpcapng, wrpcapng_packets,
167};
168
169// Flow extraction re-exports
170pub use flow::{
171    CanonicalKey, ConversationState, ConversationStatus, ConversationTable, DirectionStats,
172    FlowConfig, FlowDirection, FlowError, ProtocolState, TransportProtocol, ZWaveFlowState,
173    ZWaveKey, extract_flows, extract_flows_from_file, extract_flows_streaming,
174    extract_flows_with_config, extract_zwave_flows,
175};
176
177// Sniffer re-exports
178pub use sniffer::{
179    CaptureStats, InterfaceInfo, ParsedPacket, RawPacket, SnifferConfig, SnifferError,
180    SnifferHandle, WorkerPoolConfig, WorkerPoolSniffer, list_interfaces, validate_filter,
181};
182
183// Utils re-exports
184pub use utils::{
185    align_to, ethernet_min_frame, extract_bits, hexdump, hexstr, hexstr_sep, internet_checksum,
186    pad_to, parse_hex, set_bits, transport_checksum, verify_checksum,
187};
188
189/// Protocol constants for `EtherType` field.
190pub mod ethertype {
191    pub use crate::layer::ethertype::*;
192}
193
194/// Protocol constants for IP protocol numbers.
195pub mod ip_protocol {
196    pub use crate::layer::ip_protocol::*;
197}
198
199/// ARP operation codes.
200pub mod arp_opcode {
201    pub use crate::layer::arp::opcode::*;
202}
203
204/// ARP hardware types.
205pub mod arp_hardware {
206    pub use crate::layer::arp::hardware_type::*;
207}
208
209/// ARP protocol types.
210pub mod arp_protocol {
211    pub use crate::layer::arp::protocol_type::*;
212}
213
214/// Prelude module for convenient imports.
215pub mod prelude {
216    pub use crate::arp_hardware;
217    pub use crate::arp_opcode;
218    pub use crate::ethertype;
219    pub use crate::{
220        ARP_HEADER_LEN,
221        ArpBuilder,
222        ArpCache,
223        // ARP
224        ArpLayer,
225        BindingRegistry,
226        BytesField,
227        Dot3Builder,
228        Dot3Layer,
229        ETHERNET_HEADER_LEN,
230        EthernetBuilder,
231        // Ethernet
232        EthernetLayer,
233        Field,
234        FieldDesc,
235        FieldError,
236        FieldType,
237        FieldValue,
238        HardwareAddr,
239        // Stacking
240        IntoLayerStackEntry,
241        Ipv4Builder,
242        Ipv4Flags,
243        Layer,
244        // Bindings
245        LayerBinding,
246        LayerEnum,
247        LayerIndex,
248        LayerKind,
249        LayerStack,
250        LayerStackEntry,
251        // Fields
252        MacAddress,
253        NdpCache,
254        // Neighbor
255        NeighborCache,
256        // Core types
257        Packet,
258        PacketError,
259        ProtocolAddr,
260        // Raw
261        RawBuilder,
262        RawLayer,
263        Result,
264        TcpBuilder,
265        TcpFlags,
266        apply_binding,
267        find_binding,
268        ipv4_multicast_mac,
269        ipv6_multicast_mac,
270        is_dot3,
271        is_ethernet_ii,
272    };
273    pub use std::net::{Ipv4Addr, Ipv6Addr};
274}
275
276/// Version information
277pub const VERSION: &str = env!("CARGO_PKG_VERSION");
278
279/// Get library version
280#[must_use]
281pub fn version() -> &'static str {
282    VERSION
283}
284
285#[cfg(test)]
286mod tests {
287    use super::prelude::*;
288
289    #[test]
290    fn test_basic_packet_creation() {
291        // Build Ethernet header
292        let eth = EthernetBuilder::new()
293            .dst(MacAddress::BROADCAST)
294            .src(MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]))
295            .build_with_payload(LayerKind::Arp);
296
297        // Build ARP payload
298        let arp = ArpBuilder::who_has(Ipv4Addr::new(192, 168, 1, 100))
299            .hwsrc(MacAddress::new([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]))
300            .psrc(Ipv4Addr::new(192, 168, 1, 1))
301            .build();
302
303        // Combine
304        let mut packet_data = eth;
305        packet_data.extend_from_slice(&arp);
306
307        // Parse and verify
308        let mut packet = Packet::from_bytes(packet_data);
309        packet.parse().unwrap();
310
311        assert_eq!(packet.layer_count(), 2);
312
313        let eth_layer = packet.ethernet().unwrap();
314        assert_eq!(
315            eth_layer.ethertype(packet.as_bytes()).unwrap(),
316            ethertype::ARP
317        );
318
319        let arp_layer = packet.arp().unwrap();
320        assert!(arp_layer.is_request(packet.as_bytes()));
321    }
322
323    #[test]
324    fn test_layer_bindings() {
325        // Test that bindings are correctly defined
326        let binding = find_binding(LayerKind::Ethernet, LayerKind::Arp);
327        assert!(binding.is_some());
328        assert_eq!(binding.unwrap().field_value, 0x0806);
329
330        // Test apply_binding helper
331        let (field, value) = apply_binding(LayerKind::Ethernet, LayerKind::Ipv4).unwrap();
332        assert_eq!(field, "type");
333        assert_eq!(value, 0x0800);
334    }
335
336    #[test]
337    fn test_neighbor_resolution() {
338        let _cache = NeighborCache::new();
339
340        // Test multicast resolution
341        let mcast_ip = Ipv4Addr::new(224, 0, 0, 1);
342        let mcast_mac = ipv4_multicast_mac(mcast_ip);
343        assert!(mcast_mac.is_multicast());
344        assert!(mcast_mac.is_ipv4_multicast());
345    }
346
347    #[test]
348    fn test_frame_type_dispatch() {
349        // Ethernet II frame (type > 1500)
350        let eth2 = vec![
351            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x08,
352            0x00, // IPv4 = 0x0800
353        ];
354        assert!(!is_dot3(&eth2, 0));
355        assert!(is_ethernet_ii(&eth2, 0));
356
357        // 802.3 frame (length <= 1500)
358        let dot3 = vec![
359            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x00,
360            0x64, // Length = 100
361        ];
362        assert!(is_dot3(&dot3, 0));
363        assert!(!is_ethernet_ii(&dot3, 0));
364    }
365}