Skip to main content

stackforge_core/layer/
raw.rs

1//! Raw Layer Implementation
2//!
3//! The Raw layer represents arbitrary payload data that doesn't match any
4//! known protocol. It's useful for:
5//! - Carrying application-level payloads
6//! - Storing unparsed or unknown protocol data
7//! - Building custom packets with arbitrary content
8//!
9//! ## Example
10//!
11//! ```rust
12//! use stackforge_core::layer::raw::{RawLayer, RawBuilder};
13//! use stackforge_core::LayerIndex;
14//!
15//! // Build a raw payload
16//! let data = RawBuilder::new()
17//!     .load(b"Hello, World!")
18//!     .build();
19//!
20//! assert_eq!(&data, b"Hello, World!");
21//!
22//! // Build from string
23//! let text = RawBuilder::from_str("GET / HTTP/1.1\r\n").build();
24//! assert_eq!(&text, b"GET / HTTP/1.1\r\n");
25//!
26//! // Build with hex data
27//! let hex = RawBuilder::from_hex("deadbeef").unwrap().build();
28//! assert_eq!(&hex, &[0xde, 0xad, 0xbe, 0xef]);
29//! ```
30
31use crate::layer::LayerIndex;
32use crate::layer::field::{FieldError, FieldValue};
33
34/// Field names for the Raw layer.
35pub const RAW_FIELDS: &[&str] = &["load"];
36
37/// A layer representing raw (unparsed) payload data.
38///
39/// The Raw layer is the simplest layer type - it just holds arbitrary bytes
40/// without any protocol-specific parsing. It's typically found at the end of
41/// a packet after all known protocols have been parsed.
42#[derive(Debug, Clone)]
43pub struct RawLayer {
44    /// The layer's position within the packet buffer.
45    pub index: LayerIndex,
46}
47
48impl RawLayer {
49    /// Create a new `RawLayer` with the given index.
50    #[inline]
51    #[must_use]
52    pub fn new(index: LayerIndex) -> Self {
53        Self { index }
54    }
55
56    /// Create a `RawLayer` that spans the entire buffer from `start` to the end.
57    #[inline]
58    #[must_use]
59    pub fn from_start(start: usize) -> Self {
60        Self {
61            index: LayerIndex::new(crate::LayerKind::Raw, start, start),
62        }
63    }
64
65    /// Get the raw bytes of this layer.
66    #[inline]
67    #[must_use]
68    pub fn load<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
69        self.index.slice(buf)
70    }
71
72    /// Get the length of the raw payload.
73    #[inline]
74    #[must_use]
75    pub fn len(&self, buf: &[u8]) -> usize {
76        self.load(buf).len()
77    }
78
79    /// Check if the payload is empty.
80    #[inline]
81    #[must_use]
82    pub fn is_empty(&self, buf: &[u8]) -> bool {
83        self.load(buf).is_empty()
84    }
85
86    /// Get a summary string for this layer.
87    #[must_use]
88    pub fn summary(&self, buf: &[u8]) -> String {
89        let load = self.load(buf);
90        if load.is_empty() {
91            "Raw".to_string()
92        } else {
93            format!("Raw ({} bytes)", load.len())
94        }
95    }
96
97    /// Get the header length (for Raw, this is the entire payload).
98    #[inline]
99    #[must_use]
100    pub fn header_len(&self, buf: &[u8]) -> usize {
101        self.load(buf).len()
102    }
103
104    /// Get a hexdump preview of the payload (first N bytes).
105    #[must_use]
106    pub fn hex_preview(&self, buf: &[u8], max_bytes: usize) -> String {
107        let load = self.load(buf);
108        let preview_len = load.len().min(max_bytes);
109        let hex: String = load[..preview_len]
110            .iter()
111            .map(|b| format!("{b:02x}"))
112            .collect::<Vec<_>>()
113            .join(" ");
114
115        if load.len() > max_bytes {
116            format!("{hex}...")
117        } else {
118            hex
119        }
120    }
121
122    /// Get an ASCII preview of the payload (printable chars only).
123    #[must_use]
124    pub fn ascii_preview(&self, buf: &[u8], max_bytes: usize) -> String {
125        let load = self.load(buf);
126        let preview_len = load.len().min(max_bytes);
127
128        let ascii: String = load[..preview_len]
129            .iter()
130            .map(|&b| {
131                if b.is_ascii_graphic() || b == b' ' {
132                    b as char
133                } else {
134                    '.'
135                }
136            })
137            .collect();
138
139        if load.len() > max_bytes {
140            format!("{ascii}...")
141        } else {
142            ascii
143        }
144    }
145
146    /// Compute a hash for request/response matching.
147    /// For Raw, we just return the first 8 bytes as a simple hash.
148    #[must_use]
149    pub fn hashret(&self, buf: &[u8]) -> Vec<u8> {
150        let load = self.load(buf);
151        load.iter().take(8).copied().collect()
152    }
153
154    /// Check if this Raw layer "answers" another Raw layer.
155    /// For Raw payloads, we consider them matching if they have the same content.
156    #[must_use]
157    pub fn answers(&self, buf: &[u8], other: &RawLayer, other_buf: &[u8]) -> bool {
158        self.load(buf) == other.load(other_buf)
159    }
160
161    /// Get a field value by name.
162    #[must_use]
163    pub fn get_field(&self, buf: &[u8], name: &str) -> Option<Result<FieldValue, FieldError>> {
164        match name {
165            "load" => Some(Ok(FieldValue::Bytes(self.load(buf).to_vec()))),
166            _ => None,
167        }
168    }
169
170    /// Set a field value by name.
171    pub fn set_field(
172        &self,
173        buf: &mut [u8],
174        name: &str,
175        value: FieldValue,
176    ) -> Option<Result<(), FieldError>> {
177        match name {
178            "load" => {
179                let new_data = match value {
180                    FieldValue::Bytes(b) => b,
181                    _ => return Some(Err(FieldError::InvalidValue("load must be bytes".into()))),
182                };
183
184                let slice = self.index.slice_mut(buf);
185                if new_data.len() != slice.len() {
186                    return Some(Err(FieldError::InvalidValue(format!(
187                        "Cannot change Raw payload size: {} != {}",
188                        new_data.len(),
189                        slice.len()
190                    ))));
191                }
192                slice.copy_from_slice(&new_data);
193                Some(Ok(()))
194            },
195            _ => None,
196        }
197    }
198
199    /// Get the list of field names for this layer.
200    #[must_use]
201    pub fn field_names() -> &'static [&'static str] {
202        RAW_FIELDS
203    }
204}
205
206/// Builder for constructing Raw layer payloads.
207///
208/// The builder supports multiple ways to specify payload data:
209/// - Raw bytes via `load()`
210/// - String content via `from_str()`
211/// - Hex-encoded data via `from_hex()`
212/// - Repeated patterns via `repeat()`
213#[derive(Debug, Clone, Default)]
214pub struct RawBuilder {
215    data: Vec<u8>,
216}
217
218impl RawBuilder {
219    /// Create a new empty `RawBuilder`.
220    #[must_use]
221    pub fn new() -> Self {
222        Self { data: Vec::new() }
223    }
224
225    /// Create a `RawBuilder` with the given bytes.
226    #[must_use]
227    pub fn with_bytes(data: Vec<u8>) -> Self {
228        Self { data }
229    }
230
231    /// Create a `RawBuilder` from a string (UTF-8 bytes).
232    #[must_use]
233    pub fn from_str(s: &str) -> Self {
234        Self {
235            data: s.as_bytes().to_vec(),
236        }
237    }
238
239    /// Create a `RawBuilder` from a hex string (e.g., "deadbeef").
240    ///
241    /// Returns None if the hex string is invalid or contains no valid hex digits.
242    #[must_use]
243    pub fn from_hex(hex: &str) -> Option<Self> {
244        // Remove common separators
245        let clean: String = hex.chars().filter(char::is_ascii_hexdigit).collect();
246
247        // Return None for empty input or odd length
248        if clean.is_empty() || !clean.len().is_multiple_of(2) {
249            return None;
250        }
251
252        let bytes: Result<Vec<u8>, _> = (0..clean.len())
253            .step_by(2)
254            .map(|i| u8::from_str_radix(&clean[i..i + 2], 16))
255            .collect();
256
257        bytes.ok().map(|data| Self { data })
258    }
259
260    /// Set the payload data.
261    #[must_use]
262    pub fn load(mut self, data: &[u8]) -> Self {
263        self.data = data.to_vec();
264        self
265    }
266
267    /// Append data to the payload.
268    #[must_use]
269    pub fn append(mut self, data: &[u8]) -> Self {
270        self.data.extend_from_slice(data);
271        self
272    }
273
274    /// Append a string to the payload.
275    #[must_use]
276    pub fn append_str(mut self, s: &str) -> Self {
277        self.data.extend_from_slice(s.as_bytes());
278        self
279    }
280
281    /// Create a payload of `count` repeated `byte` values.
282    #[must_use]
283    pub fn repeat(mut self, byte: u8, count: usize) -> Self {
284        self.data = vec![byte; count];
285        self
286    }
287
288    /// Create a payload of zeros with the given length.
289    #[must_use]
290    pub fn zeros(self, len: usize) -> Self {
291        self.repeat(0, len)
292    }
293
294    /// Create a payload filled with a pattern repeated to reach `len` bytes.
295    #[must_use]
296    pub fn pattern(mut self, pattern: &[u8], len: usize) -> Self {
297        self.data = pattern.iter().cycle().take(len).copied().collect();
298        self
299    }
300
301    /// Pad the payload to a minimum length with zeros.
302    #[must_use]
303    pub fn pad_to(mut self, min_len: usize) -> Self {
304        if self.data.len() < min_len {
305            self.data.resize(min_len, 0);
306        }
307        self
308    }
309
310    /// Pad the payload to a minimum length with a specific byte.
311    #[must_use]
312    pub fn pad_with(mut self, min_len: usize, byte: u8) -> Self {
313        if self.data.len() < min_len {
314            self.data.resize(min_len, byte);
315        }
316        self
317    }
318
319    /// Build the raw payload bytes.
320    #[must_use]
321    pub fn build(self) -> Vec<u8> {
322        self.data
323    }
324
325    /// Get the current length of the payload.
326    #[must_use]
327    pub fn len(&self) -> usize {
328        self.data.len()
329    }
330
331    /// Check if the payload is empty.
332    #[must_use]
333    pub fn is_empty(&self) -> bool {
334        self.data.is_empty()
335    }
336}
337
338/// Display fields for Raw layer in `show()` output.
339#[must_use]
340pub fn raw_show_fields(layer: &RawLayer, buf: &[u8]) -> Vec<(&'static str, String)> {
341    let load = layer.load(buf);
342    let mut fields = Vec::new();
343
344    // Show length
345    fields.push(("load", format!("[{} bytes]", load.len())));
346
347    // If small enough, show hex preview
348    if !load.is_empty() && load.len() <= 64 {
349        fields.push(("hex", layer.hex_preview(buf, 32)));
350
351        // Also show ASCII if mostly printable
352        let printable_count = load
353            .iter()
354            .filter(|&&b| b.is_ascii_graphic() || b == b' ')
355            .count();
356        if printable_count * 2 >= load.len() {
357            // More than half are printable
358            fields.push(("ascii", format!("\"{}\"", layer.ascii_preview(buf, 32))));
359        }
360    }
361
362    fields
363}
364
365#[cfg(test)]
366mod tests {
367    use super::*;
368    use crate::LayerKind;
369
370    #[test]
371    fn test_raw_builder_basic() {
372        let data = RawBuilder::new().load(b"Hello").build();
373        assert_eq!(data, b"Hello");
374    }
375
376    #[test]
377    fn test_raw_builder_from_str() {
378        let data = RawBuilder::from_str("Hello, World!").build();
379        assert_eq!(data, b"Hello, World!");
380    }
381
382    #[test]
383    fn test_raw_builder_from_hex() {
384        let builder = RawBuilder::from_hex("deadbeef").unwrap();
385        assert_eq!(builder.build(), vec![0xde, 0xad, 0xbe, 0xef]);
386
387        let builder = RawBuilder::from_hex("de ad be ef").unwrap();
388        assert_eq!(builder.build(), vec![0xde, 0xad, 0xbe, 0xef]);
389
390        let builder = RawBuilder::from_hex("DE:AD:BE:EF").unwrap();
391        assert_eq!(builder.build(), vec![0xde, 0xad, 0xbe, 0xef]);
392    }
393
394    #[test]
395    fn test_raw_builder_from_hex_invalid() {
396        assert!(RawBuilder::from_hex("xyz").is_none());
397        assert!(RawBuilder::from_hex("abc").is_none()); // Odd length
398    }
399
400    #[test]
401    fn test_raw_builder_append() {
402        let data = RawBuilder::new()
403            .load(b"Hello")
404            .append(b", ")
405            .append_str("World!")
406            .build();
407        assert_eq!(data, b"Hello, World!");
408    }
409
410    #[test]
411    fn test_raw_builder_repeat() {
412        let data = RawBuilder::new().repeat(0x41, 5).build();
413        assert_eq!(data, b"AAAAA");
414    }
415
416    #[test]
417    fn test_raw_builder_zeros() {
418        let data = RawBuilder::new().zeros(10).build();
419        assert_eq!(data, vec![0u8; 10]);
420    }
421
422    #[test]
423    fn test_raw_builder_pattern() {
424        let data = RawBuilder::new().pattern(b"AB", 7).build();
425        assert_eq!(data, b"ABABABA");
426    }
427
428    #[test]
429    fn test_raw_builder_pad() {
430        let data = RawBuilder::new().load(b"Hi").pad_to(5).build();
431        assert_eq!(data, b"Hi\0\0\0");
432
433        let data = RawBuilder::new().load(b"Hello").pad_to(3).build();
434        assert_eq!(data, b"Hello"); // No change, already >= 3
435    }
436
437    #[test]
438    fn test_raw_layer_load() {
439        let buf = b"Hello, World!";
440        let index = LayerIndex::new(LayerKind::Raw, 0, buf.len());
441        let layer = RawLayer::new(index);
442
443        assert_eq!(layer.load(buf), b"Hello, World!");
444        assert_eq!(layer.len(buf), 13);
445        assert!(!layer.is_empty(buf));
446    }
447
448    #[test]
449    fn test_raw_layer_summary() {
450        let buf = b"Test payload";
451        let index = LayerIndex::new(LayerKind::Raw, 0, buf.len());
452        let layer = RawLayer::new(index);
453
454        assert_eq!(layer.summary(buf), "Raw (12 bytes)");
455    }
456
457    #[test]
458    fn test_raw_layer_empty() {
459        let buf: &[u8] = b"";
460        let index = LayerIndex::new(LayerKind::Raw, 0, 0);
461        let layer = RawLayer::new(index);
462
463        assert!(layer.is_empty(buf));
464        assert_eq!(layer.summary(buf), "Raw");
465    }
466
467    #[test]
468    fn test_raw_layer_hex_preview() {
469        let buf = b"\xde\xad\xbe\xef\x00\x01\x02\x03";
470        let index = LayerIndex::new(LayerKind::Raw, 0, buf.len());
471        let layer = RawLayer::new(index);
472
473        let preview = layer.hex_preview(buf, 4);
474        assert_eq!(preview, "de ad be ef...");
475
476        let full = layer.hex_preview(buf, 100);
477        assert_eq!(full, "de ad be ef 00 01 02 03");
478    }
479
480    #[test]
481    fn test_raw_layer_ascii_preview() {
482        let buf = b"Hello\x00World";
483        let index = LayerIndex::new(LayerKind::Raw, 0, buf.len());
484        let layer = RawLayer::new(index);
485
486        let preview = layer.ascii_preview(buf, 100);
487        assert_eq!(preview, "Hello.World");
488    }
489
490    #[test]
491    fn test_raw_layer_get_field() {
492        let buf = b"Test data";
493        let index = LayerIndex::new(LayerKind::Raw, 0, buf.len());
494        let layer = RawLayer::new(index);
495
496        let result = layer.get_field(buf, "load").unwrap().unwrap();
497        assert!(matches!(result, FieldValue::Bytes(b) if b == buf));
498
499        assert!(layer.get_field(buf, "unknown").is_none());
500    }
501
502    #[test]
503    fn test_raw_layer_set_field() {
504        let mut buf = b"Hello".to_vec();
505        let index = LayerIndex::new(LayerKind::Raw, 0, buf.len());
506        let layer = RawLayer::new(index);
507
508        // Same size works
509        let result = layer
510            .set_field(&mut buf, "load", FieldValue::Bytes(b"World".to_vec()))
511            .unwrap();
512        assert!(result.is_ok());
513        assert_eq!(&buf, b"World");
514
515        // Different size fails
516        let result = layer
517            .set_field(&mut buf, "load", FieldValue::Bytes(b"Hi".to_vec()))
518            .unwrap();
519        assert!(result.is_err());
520    }
521
522    #[test]
523    fn test_raw_layer_hashret() {
524        let buf = b"0123456789ABCDEF";
525        let index = LayerIndex::new(LayerKind::Raw, 0, buf.len());
526        let layer = RawLayer::new(index);
527
528        let hash = layer.hashret(buf);
529        assert_eq!(hash, b"01234567");
530    }
531
532    #[test]
533    fn test_raw_layer_answers() {
534        let buf1 = b"Same content";
535        let index1 = LayerIndex::new(LayerKind::Raw, 0, buf1.len());
536        let layer1 = RawLayer::new(index1);
537
538        let buf2 = b"Same content";
539        let index2 = LayerIndex::new(LayerKind::Raw, 0, buf2.len());
540        let layer2 = RawLayer::new(index2);
541
542        let buf3 = b"Different";
543        let index3 = LayerIndex::new(LayerKind::Raw, 0, buf3.len());
544        let layer3 = RawLayer::new(index3);
545
546        assert!(layer1.answers(buf1, &layer2, buf2));
547        assert!(!layer1.answers(buf1, &layer3, buf3));
548    }
549}