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