1use crate::pcap::*;
2use crate::pcapng::*;
3use cookie_factory::bytes::{le_i32, le_i64, le_u16, le_u32};
4use cookie_factory::combinator::slice;
5use cookie_factory::multi::many_ref;
6use cookie_factory::sequence::tuple;
7use cookie_factory::{gen, GenError, SerializeFn};
8use rusticata_macros::align32;
9use std::borrow::Cow;
10use std::io::Write;
11
12pub trait ToVec {
14 fn to_vec(&mut self) -> Result<Vec<u8>, GenError> {
17 self.fix();
18 self.to_vec_raw()
19 }
20
21 fn fix(&mut self) {}
23
24 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError>;
26}
27
28impl ToVec for PcapHeader {
29 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
30 let mut v = Vec::with_capacity(24);
31
32 gen(
33 tuple((
34 le_u32(self.magic_number),
35 le_u16(self.version_major),
36 le_u16(self.version_minor),
37 le_i32(self.thiszone),
38 le_u32(self.sigfigs),
39 le_u32(self.snaplen),
40 le_u32(self.network.0 as u32),
41 )),
42 &mut v,
43 )
44 .map(|res| res.0.to_vec())
45 }
46}
47
48impl ToVec for LegacyPcapBlock<'_> {
49 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
50 let mut v = Vec::with_capacity(self.data.len() + 16);
51
52 gen(
53 tuple((
54 le_u32(self.ts_sec),
55 le_u32(self.ts_usec),
56 le_u32(self.caplen),
57 le_u32(self.origlen),
58 slice(self.data),
59 )),
60 &mut v,
61 )
62 .map(|res| res.0.to_vec())
64 }
65}
66
67fn padding_for<'a, W: Write + 'a>(unaligned_length: u32) -> impl SerializeFn<W> + 'a {
68 let length = align32!(unaligned_length) - unaligned_length;
69 slice(if length > 0 {
70 &[0, 0, 0, 0][..length as usize]
71 } else {
72 b""
73 })
74}
75
76impl ToVec for PcapNGOption<'_> {
77 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
78 let mut v = Vec::new();
79 gen(pcapngoption_le(self), &mut v).map(|res| res.0.to_vec())
80 }
81}
82
83fn pcapngoption_le<'a, 'b: 'a, W: Write + 'a>(i: &'b PcapNGOption) -> impl SerializeFn<W> + 'a {
84 tuple((
85 le_u16(i.code.0),
86 le_u16(i.len),
87 slice(&i.value),
88 padding_for(i.value.len() as u32),
89 ))
90}
91
92fn options_length(options: &[PcapNGOption]) -> usize {
93 options.iter().map(|o| align32!(4 + o.value.len())).sum()
94}
95
96fn fix_options(options: &mut Vec<PcapNGOption>) {
97 options.retain(|e| e.code != OptionCode::EndOfOpt);
98 if options.is_empty() {
99 } else {
101 options.push(PcapNGOption {
102 code: OptionCode::EndOfOpt,
103 len: 0,
104 value: Cow::Borrowed(&[]),
105 })
106 }
107}
108
109impl ToVec for SectionHeaderBlock<'_> {
110 fn fix(&mut self) {
112 self.block_type = SHB_MAGIC;
113 self.bom = BOM_MAGIC;
115 self.major_version = 1;
116 self.minor_version = 0;
117 fix_options(&mut self.options);
118 let length = (28 + options_length(&self.options)) as u32;
120 self.block_len1 = length;
121 self.block_len2 = length;
122 }
123
124 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
125 let mut v = Vec::with_capacity(64);
126 gen(
127 tuple((
128 le_u32(self.block_type),
129 le_u32(self.block_len1),
130 le_u32(self.bom),
131 le_u16(self.major_version),
132 le_u16(self.minor_version),
133 le_i64(self.section_len),
134 many_ref(&self.options, pcapngoption_le),
135 le_u32(self.block_len2),
136 )),
137 &mut v,
138 )
139 .map(|res| res.0.to_vec())
140 }
141}
142
143impl ToVec for InterfaceDescriptionBlock<'_> {
144 fn fix(&mut self) {
146 self.block_type = IDB_MAGIC;
147 self.reserved = 0;
148 if !self.options.iter().any(|o| o.code == OptionCode::IfTsresol) {
150 let tsresol_bytes = vec![self.if_tsresol, 0, 0, 0];
151 self.options.push(PcapNGOption {
152 code: OptionCode::IfTsresol,
153 len: 1,
154 value: Cow::Owned(tsresol_bytes),
155 });
156 }
157 if !self
158 .options
159 .iter()
160 .any(|o| o.code == OptionCode::IfTsoffset)
161 {
162 let tsoffset_bytes = self.if_tsoffset.to_le_bytes();
163 self.options.push(PcapNGOption {
164 code: OptionCode::IfTsoffset,
165 len: 8,
166 value: Cow::Owned(tsoffset_bytes.to_vec()),
167 });
168 }
169 fix_options(&mut self.options);
170 let length = (20 + options_length(&self.options)) as u32;
172 self.block_len1 = length;
173 self.block_len2 = length;
174 }
175
176 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
178 let mut v = Vec::with_capacity(64);
179 gen(
180 tuple((
181 le_u32(self.block_type),
182 le_u32(self.block_len1),
183 le_u16(self.linktype.0 as u16),
184 le_u16(self.reserved),
185 le_u32(self.snaplen),
186 many_ref(&self.options, pcapngoption_le),
187 le_u32(self.block_len2),
188 )),
189 &mut v,
190 )
191 .map(|res| res.0.to_vec())
192 }
193}
194
195impl ToVec for EnhancedPacketBlock<'_> {
196 fn fix(&mut self) {
198 self.block_type = EPB_MAGIC;
199 fix_options(&mut self.options);
200 let length = (32 + self.data.len() + options_length(&self.options)) as u32;
202 self.block_len1 = align32!(length);
203 self.block_len2 = self.block_len1;
204 }
205
206 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
207 let mut v = Vec::with_capacity(64);
208 gen(
209 tuple((
210 le_u32(self.block_type),
211 le_u32(self.block_len1),
212 le_u32(self.if_id),
213 le_u32(self.ts_high),
214 le_u32(self.ts_low),
215 le_u32(self.caplen),
216 le_u32(self.origlen),
217 slice(self.data),
218 padding_for(self.data.len() as u32),
219 many_ref(&self.options, pcapngoption_le),
220 le_u32(self.block_len2),
221 )),
222 &mut v,
223 )
224 .map(|res| res.0.to_vec())
225 }
226}
227
228impl ToVec for SimplePacketBlock<'_> {
229 fn fix(&mut self) {
230 self.block_type = SPB_MAGIC;
231 self.block_len1 = (16 + align32!(self.data.len())) as u32;
233 self.block_len2 = self.block_len1;
234 }
235
236 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
237 let mut v = Vec::with_capacity(64);
238 gen(
239 tuple((
240 le_u32(self.block_type),
241 le_u32(self.block_len1),
242 le_u32(self.origlen),
243 slice(self.data),
244 padding_for(self.data.len() as u32),
245 le_u32(self.block_len2),
246 )),
247 &mut v,
248 )
249 .map(|res| res.0.to_vec())
250 }
251}
252
253fn namerecord_le<'a, 'b: 'a, W: Write + 'a>(i: &'b NameRecord) -> impl SerializeFn<W> + 'a {
254 tuple((
255 le_u16(i.record_type.0),
256 le_u16(i.record_value.len() as u16),
257 slice(i.record_value),
258 ))
259}
260
261fn namerecords_length(nr: &[NameRecord]) -> usize {
262 nr.iter().map(|n| align32!(2 + n.record_value.len())).sum()
263}
264
265impl ToVec for NameResolutionBlock<'_> {
266 fn fix(&mut self) {
267 self.block_type = NRB_MAGIC;
268 fix_options(&mut self.options);
269 let length = (12 + namerecords_length(&self.nr) + options_length(&self.options)) as u32;
271 self.block_len1 = align32!(length);
272 self.block_len2 = self.block_len1;
273 }
274
275 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
276 let mut v = Vec::with_capacity(64);
277 gen(
278 tuple((
279 le_u32(self.block_type),
280 le_u32(self.block_len1),
281 many_ref(&self.nr, namerecord_le),
282 many_ref(&self.options, pcapngoption_le),
283 le_u32(self.block_len2),
284 )),
285 &mut v,
286 )
287 .map(|res| res.0.to_vec())
288 }
289}
290
291impl ToVec for InterfaceStatisticsBlock<'_> {
292 fn fix(&mut self) {
293 self.block_type = ISB_MAGIC;
294 fix_options(&mut self.options);
295 self.block_len1 = (24 + align32!(options_length(&self.options))) as u32;
297 self.block_len2 = self.block_len1;
298 }
299
300 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
301 let mut v = Vec::with_capacity(64);
302 gen(
303 tuple((
304 le_u32(self.block_type),
305 le_u32(self.block_len1),
306 le_u32(self.if_id),
307 le_u32(self.ts_high),
308 le_u32(self.ts_low),
309 many_ref(&self.options, pcapngoption_le),
310 le_u32(self.block_len2),
311 )),
312 &mut v,
313 )
314 .map(|res| res.0.to_vec())
315 }
316}
317
318impl ToVec for SystemdJournalExportBlock<'_> {
319 fn fix(&mut self) {
320 if self.block_type != SJE_MAGIC {
321 self.block_type = SJE_MAGIC;
322 }
323 self.block_len1 = (12 + align32!(self.data.len())) as u32;
325 self.block_len2 = self.block_len1;
326 }
327
328 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
329 let mut v = Vec::with_capacity(64);
330 gen(
331 tuple((
332 le_u32(self.block_type),
333 le_u32(self.block_len1),
334 slice(self.data),
335 padding_for(self.data.len() as u32),
336 le_u32(self.block_len2),
337 )),
338 &mut v,
339 )
340 .map(|res| res.0.to_vec())
341 }
342}
343
344impl ToVec for DecryptionSecretsBlock<'_> {
345 fn fix(&mut self) {
346 if self.block_type != DSB_MAGIC {
347 self.block_type = DSB_MAGIC;
348 }
349 fix_options(&mut self.options);
350 self.block_len1 =
352 (20 + align32!(options_length(&self.options)) + align32!(self.data.len())) as u32;
353 self.block_len2 = self.block_len1;
354 }
355
356 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
357 let mut v = Vec::with_capacity(64);
358 gen(
359 tuple((
360 le_u32(self.block_type),
361 le_u32(self.block_len1),
362 le_u32(self.secrets_type.0),
363 le_u32(self.secrets_len),
364 slice(self.data),
365 padding_for(self.data.len() as u32),
366 many_ref(&self.options, pcapngoption_le),
367 le_u32(self.block_len2),
368 )),
369 &mut v,
370 )
371 .map(|res| res.0.to_vec())
372 }
373}
374
375impl ToVec for ProcessInformationBlock<'_> {
376 fn fix(&mut self) {
378 self.block_type = PIB_MAGIC;
379 fix_options(&mut self.options);
380 let length = (16 + options_length(&self.options)) as u32;
382 self.block_len1 = align32!(length);
383 self.block_len2 = self.block_len1;
384 }
385
386 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
387 let mut v = Vec::with_capacity(64);
388 gen(
389 tuple((
390 le_u32(self.block_type),
391 le_u32(self.block_len1),
392 le_u32(self.process_id),
393 many_ref(&self.options, pcapngoption_le),
394 le_u32(self.block_len2),
395 )),
396 &mut v,
397 )
398 .map(|res| res.0.to_vec())
399 }
400}
401
402impl ToVec for CustomBlock<'_> {
403 fn fix(&mut self) {
404 if self.block_type != DCB_MAGIC && self.block_type != CB_MAGIC {
405 self.block_type = CB_MAGIC;
406 }
407 self.block_len1 = (16 + align32!(self.data.len())) as u32;
409 self.block_len2 = self.block_len1;
410 }
411
412 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
413 let mut v = Vec::with_capacity(64);
414 gen(
415 tuple((
416 le_u32(self.block_type),
417 le_u32(self.block_len1),
418 le_u32(self.pen),
419 slice(self.data),
420 padding_for(self.data.len() as u32),
421 le_u32(self.block_len2),
422 )),
423 &mut v,
424 )
425 .map(|res| res.0.to_vec())
426 }
427}
428
429impl ToVec for UnknownBlock<'_> {
430 fn fix(&mut self) {
431 self.block_len1 = (12 + align32!(self.data.len())) as u32;
434 self.block_len2 = self.block_len1;
435 }
436
437 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
438 let mut v = Vec::new();
439 gen(
440 tuple((
441 le_u32(self.block_type),
442 le_u32(self.block_len1),
443 slice(self.data),
444 padding_for(self.data.len() as u32),
445 le_u32(self.block_len2),
446 )),
447 &mut v,
448 )
449 .map(|res| res.0.to_vec())
450 }
451}
452
453impl ToVec for Block<'_> {
454 fn fix(&mut self) {
455 match self {
456 Block::SectionHeader(b) => b.fix(),
457 Block::InterfaceDescription(b) => b.fix(),
458 Block::EnhancedPacket(b) => b.fix(),
459 Block::SimplePacket(b) => b.fix(),
460 Block::NameResolution(b) => b.fix(),
461 Block::InterfaceStatistics(b) => b.fix(),
462 Block::SystemdJournalExport(b) => b.fix(),
463 Block::DecryptionSecrets(b) => b.fix(),
464 Block::ProcessInformation(b) => b.fix(),
465 Block::Custom(b) => b.fix(),
466 Block::Unknown(b) => b.fix(),
467 }
468 }
469
470 fn to_vec_raw(&self) -> Result<Vec<u8>, GenError> {
471 match self {
472 Block::SectionHeader(b) => b.to_vec_raw(),
473 Block::InterfaceDescription(b) => b.to_vec_raw(),
474 Block::EnhancedPacket(b) => b.to_vec_raw(),
475 Block::SimplePacket(b) => b.to_vec_raw(),
476 Block::NameResolution(b) => b.to_vec_raw(),
477 Block::InterfaceStatistics(b) => b.to_vec_raw(),
478 Block::SystemdJournalExport(b) => b.to_vec_raw(),
479 Block::DecryptionSecrets(b) => b.to_vec_raw(),
480 Block::ProcessInformation(b) => b.to_vec_raw(),
481 Block::Custom(b) => b.to_vec_raw(),
482 Block::Unknown(b) => b.to_vec_raw(),
483 }
484 }
485}
486
487#[cfg(test)]
488mod tests {
489 use std::borrow::Cow;
490
491 use crate::pcap::tests::PCAP_HDR;
492 use crate::pcap::{parse_pcap_frame, parse_pcap_header};
493 use crate::pcapng::*;
494 use crate::serialize::ToVec;
495 use crate::traits::tests::{
496 FRAME_PCAP, FRAME_PCAPNG_DSB, FRAME_PCAPNG_EPB, FRAME_PCAPNG_EPB_WITH_OPTIONS,
497 FRAME_PCAPNG_SHB,
498 };
499 use crate::Linktype;
500
501 #[test]
502 fn test_serialize_pcap_header() {
503 let (rem, hdr) = parse_pcap_header(PCAP_HDR).expect("header parsing failed");
504 assert!(rem.is_empty());
505 assert_eq!(hdr.magic_number, 0xa1b2_c3d4);
506 assert_eq!(hdr.version_major, 2);
507 assert_eq!(hdr.version_minor, 4);
508 assert_eq!(hdr.snaplen, 262_144);
509 let v = hdr.to_vec_raw().expect("serialize");
510 assert_eq!(v.len(), PCAP_HDR.len());
511 assert_eq!(v, PCAP_HDR);
512 }
513 #[test]
514 fn test_serialize_pcap_frame() {
515 let (rem, pkt) = parse_pcap_frame(FRAME_PCAP).expect("packet parsing failed");
516 assert!(rem.is_empty());
517 assert_eq!(pkt.origlen, 74);
518 assert_eq!(pkt.ts_usec, 562_913);
519 assert_eq!(pkt.ts_sec, 1_515_933_236);
520 let v = pkt.to_vec_raw().expect("serialize");
521 println!("self.data.len: {}", pkt.data.len());
522 assert_eq!(v.len(), FRAME_PCAP.len());
523 assert_eq!(v, FRAME_PCAP);
524 }
525
526 fn frame_should_not_be_fixed(frame: &[u8]) {
527 let (rem, mut pkt) = parse_block_le(frame).expect("packet parsing failed");
528 assert!(rem.is_empty());
529 assert_eq!(pkt.to_vec().unwrap(), frame);
530 }
531
532 #[test]
533 fn test_dsb_not_fixed() {
534 frame_should_not_be_fixed(FRAME_PCAPNG_DSB);
535 }
536 #[test]
537 fn test_epb_not_fixed() {
538 frame_should_not_be_fixed(FRAME_PCAPNG_EPB);
539 }
540 #[test]
541 fn test_epb_with_options_not_fixed() {
542 frame_should_not_be_fixed(FRAME_PCAPNG_EPB_WITH_OPTIONS);
543 }
544 #[test]
545 fn test_shb_not_fixed() {
546 frame_should_not_be_fixed(FRAME_PCAPNG_SHB);
547 }
548
549 #[test]
550 fn test_serialize_shb() {
551 let shb = SectionHeaderBlock {
552 block_type: SHB_MAGIC,
553 block_len1: 28,
554 bom: BOM_MAGIC,
555 major_version: 1,
556 minor_version: 0,
557 section_len: -1,
558 options: Vec::new(),
559 block_len2: 28,
560 };
561 let v = shb.to_vec_raw().expect("serialize");
562 let res = parse_sectionheaderblock_le(&v);
564 assert!(res.is_ok());
565 }
566 #[test]
567 fn test_serialize_shb_fix() {
568 let mut shb = SectionHeaderBlock {
569 block_type: 0,
570 block_len1: 0,
571 bom: 0,
572 major_version: 0,
573 minor_version: 0,
574 section_len: -1,
575 options: vec![
576 PcapNGOption {
578 code: OptionCode::ShbUserAppl,
579 len: 5,
580 value: Cow::Borrowed(b"meows"),
581 },
582 ],
584 block_len2: 0,
585 };
586
587 let v = shb.to_vec().expect("serialize");
588 let res = parse_sectionheaderblock_le(&v);
590 res.unwrap();
592 }
593 #[test]
594 fn test_serialize_shb_options() {
595 let shb = SectionHeaderBlock {
596 block_type: SHB_MAGIC,
597 block_len1: 28 + 8,
598 bom: BOM_MAGIC,
599 major_version: 1,
600 minor_version: 0,
601 section_len: -1,
602 options: vec![PcapNGOption {
603 code: OptionCode(0),
604 len: 3,
605 value: Cow::Borrowed(&[0, 0, 0, 0]),
606 }],
607 block_len2: 28 + 8,
608 };
609 let v = shb.to_vec_raw().expect("serialize");
610 let res = parse_sectionheaderblock_le(&v);
612 assert!(res.is_ok());
614 }
615 #[test]
616 fn test_serialize_idb() {
617 let mut idb = InterfaceDescriptionBlock {
618 block_type: IDB_MAGIC,
619 block_len1: 20,
620 linktype: Linktype::RAW,
621 reserved: 0,
622 snaplen: 65535,
623 options: vec![],
624 block_len2: 20,
625 if_tsresol: 6,
626 if_tsoffset: 0,
627 };
628 let v = idb.to_vec().expect("serialize");
629 let res = parse_interfacedescriptionblock_le(&v);
631 assert!(res.is_ok());
632 }
633 #[test]
634 fn test_serialize_epb() {
635 let (rem, pkt) = parse_block_le(FRAME_PCAPNG_EPB).expect("packet creation failed");
636 assert!(rem.is_empty());
637 if let Block::EnhancedPacket(mut epb) = pkt {
638 let v = epb.to_vec().expect("serialize");
639 let res = parse_enhancedpacketblock_le(&v);
642 assert!(res.is_ok());
643 }
644 }
645 #[test]
646 fn test_serialize_epb_with_options() {
647 let (rem, pkt) =
648 parse_block_le(FRAME_PCAPNG_EPB_WITH_OPTIONS).expect("packet creation failed");
649 assert!(rem.is_empty());
650 if let Block::EnhancedPacket(mut epb) = pkt {
651 let v = epb.to_vec().expect("serialize");
652 let res = parse_enhancedpacketblock_le(&v);
654 assert!(res.is_ok());
655 }
656 }
657 #[test]
658 fn test_serialize_dsb() {
659 let (rem, pkt) = parse_block_le(FRAME_PCAPNG_DSB).expect("packet creation failed");
660 assert!(rem.is_empty());
661 assert!(pkt.magic() == DSB_MAGIC);
662 if let Block::DecryptionSecrets(mut dsb) = pkt {
663 let v = dsb.to_vec().expect("serialize");
664 let res = parse_decryptionsecretsblock_le(&v);
665 assert!(res.is_ok());
666 }
667 }
668}