@@ -2,22 +2,16 @@ use std::borrow::Cow;
22use std:: io:: { BufReader , BufWriter , Read , Write } ;
33use std:: mem:: size_of;
44use std:: num:: NonZeroU32 ;
5- use std:: ops:: Deref ;
65use std:: sync:: Arc ;
7- use std:: time:: { SystemTime , Duration } ;
6+ use std:: time:: Duration ;
87
98use anyhow:: { Context , Error , anyhow} ;
10- use byteorder_slice:: {
11- ByteOrder , BigEndian , LittleEndian ,
12- result:: ReadSlice
13- } ;
149use pcap_file:: {
1510 pcap:: { PcapReader , PcapHeader , PcapWriter , RawPcapPacket } ,
1611 pcapng:: {
17- PcapNgReader , PcapNgWriter , PcapNgBlock ,
12+ PcapNgReader , PcapNgWriter ,
1813 blocks:: {
19- Block , RawBlock ,
20- ENHANCED_PACKET_BLOCK ,
14+ Block ,
2115 section_header:: {
2216 SectionHeaderBlock ,
2317 SectionHeaderOption ,
@@ -34,7 +28,6 @@ use pcap_file::{
3428 } ,
3529 } ,
3630 DataLink ,
37- Endianness ,
3831 TsResolution ,
3932} ;
4033use once_cell:: sync:: Lazy ;
@@ -207,47 +200,26 @@ impl GenericPacket for PacketWrapper<RawPcapPacket<'_>> {
207200pub struct PcapNgLoader < Source : Read > {
208201 pcap : PcapNgReader < BufReader < Source > > ,
209202 initial_metadata : Option < CaptureMetadata > ,
210- bytes_read : u64 ,
211- endianness : Endianness ,
212- interface_ts_units : Vec < u64 > ,
213- ts_start : Option < u64 > ,
203+ interface_seen : bool ,
204+ ts_start : Option < Duration > ,
214205}
215206
216207/// Saver for pcap-ng format.
217- pub struct PcapNgSaver < Dest : Write > {
218- pcap : PcapNgWriter < BufWriter < Dest > > ,
208+ pub struct PcapNgSaver < ' s , Dest : Write > {
209+ pcap : PcapNgWriter < ' s , BufWriter < Dest > > ,
219210 meta : Arc < CaptureMetadata > ,
220211}
221212
222- /// Helper for parsing Enhanced Packet Blocks.
223- fn parse_epb < B : ByteOrder > ( raw_block : & RawBlock < ' _ > )
224- -> Result < ( usize , u64 , usize ) , Error >
225- {
226- let mut slice = raw_block. body . deref ( ) ;
227- let interface_id = slice. read_u32 :: < B > ( ) ? as usize ;
228- let timestamp_hi = slice. read_u32 :: < B > ( ) ? as u64 ;
229- let timestamp_lo = slice. read_u32 :: < B > ( ) ? as u64 ;
230- let length = slice. read_u32 :: < B > ( ) ? as usize ;
231- let timestamp = ( timestamp_hi << 32 ) + timestamp_lo;
232- Ok ( ( interface_id, timestamp, length) )
233- }
234-
235213impl < Source > GenericLoader < Source >
236214for PcapNgLoader < Source >
237215where Source : Read
238216{
239- type PacketData < ' p > = PacketWrapper < ( RawBlock < ' p > , usize ) > ;
217+ type PacketData < ' p > = PacketWrapper < EnhancedPacketBlock < ' p > > ;
240218
241219 fn new ( source : Source ) -> Result < Self , Error > {
242220 let reader = BufReader :: new ( source) ;
243221 let pcap = PcapNgReader :: new ( reader) ?;
244222 let section_header = pcap. section ( ) ;
245- let endianness = section_header. endianness ;
246- let header_length = {
247- let mut tmp = Vec :: < u8 > :: new ( ) ;
248- section_header. write_to :: < LittleEndian , Vec < u8 > > ( & mut tmp) ?;
249- tmp. len ( )
250- } ;
251223 let initial_metadata = Some ( {
252224 let mut meta = CaptureMetadata :: default ( ) ;
253225 for option in & section_header. options {
@@ -273,70 +245,54 @@ where Source: Read
273245 Ok ( PcapNgLoader {
274246 pcap,
275247 initial_metadata,
276- endianness,
277- interface_ts_units : vec ! [ ] ,
278- bytes_read : header_length as u64 ,
248+ interface_seen : false ,
279249 ts_start : None
280250 } )
281251 }
282252
283253 fn next ( & mut self ) -> LoaderItem < impl GenericPacket > {
284- use Endianness :: * ;
285254 use DataLink :: * ;
286255 use LoaderItem :: * ;
287256 if let Some ( meta) = self . initial_metadata . take ( ) {
288257 return Metadata ( Box :: new ( meta) )
289258 }
290- let raw_block = match self . pcap . next_raw_block ( ) {
259+ let total_bytes_read = self . pcap . bytes_parsed ( ) ;
260+ let block = match self . pcap . next_block ( ) {
291261 None => return End ,
292262 Some ( Err ( e) ) => return LoadError ( anyhow ! ( e) ) ,
293263 Some ( Ok ( block) ) => block
294264 } ;
295- self . bytes_read += raw_block. initial_len as u64 ;
296- if raw_block. type_ == ENHANCED_PACKET_BLOCK {
297- let parse_result = match self . endianness {
298- Big => parse_epb :: < BigEndian > ( & raw_block) ,
299- Little => parse_epb :: < LittleEndian > ( & raw_block) ,
300- } ;
301- let ( interface_id, ts_value, length) = match parse_result {
302- Ok ( values) => values,
303- Err ( e) => return LoadError ( anyhow ! ( e) ) ,
304- } ;
305- let ts_unit = match self . interface_ts_units . get ( interface_id) {
306- Some ( unit) => unit,
307- None => return LoadError ( anyhow ! (
308- "Missing block for interface {interface_id}"
309- ) )
310- } ;
311- let timestamp_ns = if let Some ( ts_start) = self . ts_start {
312- ts_unit * ( ts_value - ts_start)
313- } else {
314- self . ts_start = Some ( ts_value) ;
315- 0
316- } ;
317- return Packet (
318- PacketWrapper {
319- packet_data : ( raw_block, length) ,
320- timestamp_ns,
321- total_bytes_read : self . bytes_read ,
322- }
323- )
324- }
325- let parsed_block = match self . endianness {
326- Big => raw_block. try_into_block :: < BigEndian > ( ) ,
327- Little => raw_block. try_into_block :: < LittleEndian > ( ) ,
328- } ;
329- match parsed_block {
330- Err ( e) => return LoadError ( anyhow ! ( e) ) ,
331- Ok ( Block :: SectionHeader ( _) ) =>
332- return LoadError ( anyhow ! (
265+ match block {
266+ Block :: EnhancedPacket ( epb) => {
267+ let timestamp_ns: u128 = if let Some ( ts_start) = self . ts_start {
268+ ( epb. timestamp - ts_start) . as_nanos ( )
269+ } else {
270+ self . ts_start = Some ( epb. timestamp ) ;
271+ 0
272+ } ;
273+ let timestamp_ns: u64 = match timestamp_ns. try_into ( ) {
274+ Ok ( ns) => ns,
275+ Err ( e) => return LoadError ( anyhow ! ( e) )
276+ } ;
277+ Packet (
278+ PacketWrapper {
279+ packet_data : epb,
280+ timestamp_ns,
281+ total_bytes_read,
282+ }
283+ )
284+ } ,
285+ Block :: SectionHeader ( _) =>
286+ LoadError ( anyhow ! (
333287 "Multiple sections are not supported." ) ) ,
334- Ok ( Block :: InterfaceDescription ( interface) ) => {
288+ Block :: InterfaceDescription ( interface) => {
335289 use InterfaceDescriptionOption :: * ;
336290 use Speed :: * ;
337- if ! self . interface_ts_units . is_empty ( ) {
291+ if self . interface_seen {
338292 return LoadError ( anyhow ! (
339293 "Multiple interfaces are not supported" ) )
294+ } else {
295+ self . interface_seen = true ;
340296 }
341297 let mut meta = CaptureMetadata :: default ( ) ;
342298 match interface. linktype {
@@ -355,17 +311,8 @@ where Source: Read
355311 interface. linktype) ) ,
356312 } ;
357313 meta. iface_snaplen = NonZeroU32 :: new ( interface. snaplen ) ;
358- let mut ts_units_specified = false ;
359314 for option in interface. options {
360315 match option {
361- IfTsResol ( res) => {
362- let ts_unit = 1_000_000_000 / match res {
363- 0x00 ..=0x7f => 10u64 . pow ( res as u32 ) ,
364- 0x80 ..=0xff => 2u64 . pow ( ( res & 0x7f ) as u32 )
365- } ;
366- self . interface_ts_units . push ( ts_unit) ;
367- ts_units_specified = true ;
368- } ,
369316 IfDescription ( desc) => {
370317 meta. iface_desc . replace ( desc. to_string ( ) ) ;
371318 } ,
@@ -378,41 +325,23 @@ where Source: Read
378325 _ => { }
379326 } ;
380327 }
381- if !ts_units_specified {
382- self . interface_ts_units . push ( 1000 ) ;
383- }
384- return Metadata ( Box :: new ( meta) )
328+ Metadata ( Box :: new ( meta) )
385329 } ,
386- Ok ( Block :: InterfaceStatistics ( stats) ) => {
330+ Block :: InterfaceStatistics ( stats) => {
387331 use InterfaceStatisticsOption :: * ;
388332 let mut meta = CaptureMetadata :: default ( ) ;
389333 for option in stats. options {
390334 match option {
391- IsbStartTime ( time) => {
392- meta. start_time . replace (
393- SystemTime :: UNIX_EPOCH + Duration :: from_nanos (
394- time * self . interface_ts_units [ 0 ]
395- )
396- ) ;
397- } ,
398- IsbEndTime ( time) => {
399- meta. end_time . replace (
400- SystemTime :: UNIX_EPOCH + Duration :: from_nanos (
401- time * self . interface_ts_units [ 0 ]
402- )
403- ) ;
404- } ,
405- IsbIfDrop ( pkts) => {
406- meta. dropped . replace ( pkts) ;
407- } ,
335+ IsbStartTime ( time) => { meta. start_time . replace ( time) ; } ,
336+ IsbEndTime ( time) => { meta. end_time . replace ( time) ; } ,
337+ IsbIfDrop ( pkts) => { meta. dropped . replace ( pkts) ; } ,
408338 _ => { }
409339 } ;
410340 }
411- return Metadata ( Box :: new ( meta) )
341+ Metadata ( Box :: new ( meta) )
412342 } ,
413- _ => { }
414- } ;
415- Ignore
343+ _ => Ignore
344+ }
416345 }
417346}
418347
@@ -430,10 +359,8 @@ fn speed_bps(speed: &Speed) -> Option<u64> {
430359 }
431360}
432361
433- fn time_nanos ( time : & SystemTime ) -> Option < u64 > {
434- time. duration_since ( SystemTime :: UNIX_EPOCH )
435- . ok ( )
436- . and_then ( |duration| duration. as_nanos ( ) . try_into ( ) . ok ( ) )
362+ fn duration ( duration : & Duration ) -> Option < Duration > {
363+ Some ( * duration)
437364}
438365
439366macro_rules! option {
@@ -468,16 +395,16 @@ fn stats_options(meta: &CaptureMetadata)
468395{
469396 use InterfaceStatisticsOption :: * ;
470397 let mut opt = Vec :: new ( ) ;
471- option ! ( meta, opt, start_time, IsbStartTime , time_nanos ) ;
472- option ! ( meta, opt, end_time, IsbEndTime , time_nanos ) ;
398+ option ! ( meta, opt, start_time, IsbStartTime , duration ) ;
399+ option ! ( meta, opt, end_time, IsbEndTime , duration ) ;
473400 if let Some ( pkts) = meta. dropped {
474401 opt. push ( IsbIfDrop ( pkts) ) ;
475402 }
476403 opt
477404}
478405
479406impl < Dest > GenericSaver < Dest >
480- for PcapNgSaver < Dest >
407+ for PcapNgSaver < ' _ , Dest >
481408where Self : Sized , Dest : Write
482409{
483410 fn new ( dest : Dest , meta : Arc < CaptureMetadata > ) -> Result < Self , Error > {
@@ -538,12 +465,8 @@ where Self: Sized, Dest: Write
538465 InterfaceStatisticsBlock {
539466 interface_id : 0 ,
540467 timestamp : match self . meta . end_time {
541- Some ( end) => end
542- . duration_since ( SystemTime :: UNIX_EPOCH ) ?
543- . as_nanos ( )
544- . try_into ( )
545- . context ( "Timestamp overflow" ) ?,
546- None => 0
468+ Some ( end) => end,
469+ None => Duration :: from_nanos ( 0 ) ,
547470 } ,
548471 options : stats_options ( & self . meta )
549472 }
@@ -553,11 +476,8 @@ where Self: Sized, Dest: Write
553476 }
554477}
555478
556- impl GenericPacket for PacketWrapper < ( RawBlock < ' _ > , usize ) > {
557- fn bytes ( & self ) -> & [ u8 ] {
558- let ( raw_block, length) = & self . packet_data ;
559- & raw_block. body [ 20 ..] [ ..* length]
560- }
479+ impl GenericPacket for PacketWrapper < EnhancedPacketBlock < ' _ > > {
480+ fn bytes ( & self ) -> & [ u8 ] { & self . packet_data . data }
561481 fn timestamp_ns ( & self ) -> u64 { self . timestamp_ns }
562482 fn total_bytes_read ( & self ) -> u64 { self . total_bytes_read }
563483}
0 commit comments