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