@@ -359,6 +359,55 @@ class EnhancedPacketBlockLE(EnhancedPacketBlock):
359359 __byte_order__ = '<'
360360
361361
362+ class PacketBlock (EnhancedPacketBlock ):
363+ """Packet block (deprecated)"""
364+
365+ __hdr__ = (
366+ ('type' , 'I' , PCAPNG_BT_PB ),
367+ ('len' , 'I' , 64 ),
368+ ('iface_id' , 'H' , 0 ),
369+ ('drops_count' , 'H' , 0 ), # local drop counter
370+ ('ts_high' , 'I' , 0 ), # timestamp high
371+ ('ts_low' , 'I' , 0 ), # timestamp low
372+ ('caplen' , 'I' , 0 ), # captured len, size of pkt_data
373+ ('pkt_len' , 'I' , 0 ), # actual packet len
374+ # ( pkt_data, variable size )
375+ # ( options, variable size )
376+ ('_len' , 'I' , 64 )
377+ )
378+
379+ def __bytes__ (self ):
380+ pkt_buf = self .pkt_data
381+
382+ pkt_len = len (pkt_buf )
383+ self .caplen = pkt_len
384+ self .pkt_len = pkt_len
385+
386+ opts_buf = self ._do_pack_options ()
387+
388+ n = self .__hdr_len__ + _align32b (self .caplen ) + len (opts_buf )
389+ self .len = n
390+ self ._len = n
391+
392+ hdr_buf = self ._pack_hdr (
393+ self .type ,
394+ n ,
395+ self .iface_id ,
396+ self .drops_count ,
397+ self .ts_high ,
398+ self .ts_low ,
399+ pkt_len ,
400+ pkt_len ,
401+ n
402+ )
403+
404+ return b'' .join ([hdr_buf [:- 4 ], _padded (pkt_buf ), opts_buf , hdr_buf [- 4 :]])
405+
406+
407+ class PacketBlockLE (PacketBlock ):
408+ __byte_order__ = '<'
409+
410+
362411class Writer (object ):
363412 """Simple pcapng dumpfile writer."""
364413
@@ -646,6 +695,10 @@ def __iter__(self):
646695 epb = EnhancedPacketBlockLE (buf ) if self .__le else EnhancedPacketBlock (buf )
647696 ts = self ._tsoffset + (((epb .ts_high << 32 ) | epb .ts_low ) / self ._divisor )
648697 yield (ts , epb .pkt_data )
698+ elif blk_type == PCAPNG_BT_PB :
699+ pb = PacketBlockLE (buf ) if self .__le else PacketBlock (buf )
700+ ts = self ._tsoffset + (((pb .ts_high << 32 ) | pb .ts_low ) / self ._divisor )
701+ yield (ts , pb .pkt_data )
649702
650703 # just ignore other blocks
651704
@@ -765,6 +818,72 @@ def test_epb():
765818 assert len (epb ) == len (buf )
766819
767820
821+ def test_pb ():
822+ """Test PB with a non-ascii comment option"""
823+ buf = (
824+ b'\x02 \x00 \x00 \x00 \x80 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x73 \xe6 \x04 \x00 \xbe \x37 \xe2 \x19 \x4a \x00 '
825+ b'\x00 \x00 \x4a \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x08 \x00 \x45 \x00 '
826+ b'\x00 \x3c \x5d \xb3 \x40 \x00 \x40 \x06 \xdf \x06 \x7f \x00 \x00 \x01 \x7f \x00 \x00 \x01 \x98 \x34 \x11 \x4e '
827+ b'\x95 \xcb \x2d \x3a \x00 \x00 \x00 \x00 \xa0 \x02 \xaa \xaa \xfe \x30 \x00 \x00 \x02 \x04 \xff \xd7 \x04 \x02 '
828+ b'\x08 \x0a \x05 \x8f \x70 \x89 \x00 \x00 \x00 \x00 \x01 \x03 \x03 \x07 \x00 \x00 \x01 \x00 \x0a \x00 \xd0 \xbf '
829+ b'\xd0 \xb0 \xd0 \xba \xd0 \xb5 \xd1 \x82 \x00 \x00 \x00 \x00 \x00 \x00 \x80 \x00 \x00 \x00 ' )
830+
831+ # block unpacking
832+ pb = PacketBlockLE (buf )
833+ assert pb .type == PCAPNG_BT_PB
834+ assert pb .caplen == len (pb .pkt_data )
835+ assert pb .iface_id == 0
836+ assert pb .drops_count == 0
837+ assert pb .pkt_len == len (pb .pkt_data )
838+ assert pb .caplen == 74
839+ assert pb .ts_high == 321139
840+ assert pb .ts_low == 434255806
841+ assert pb .data == ''
842+
843+ # options unpacking
844+ assert len (pb .opts ) == 2
845+ assert pb .opts [0 ].code == PCAPNG_OPT_COMMENT
846+ assert pb .opts [0 ].text == u'\u043f \u0430 \u043a \u0435 \u0442 '
847+
848+ assert pb .opts [1 ].code == PCAPNG_OPT_ENDOFOPT
849+ assert pb .opts [1 ].len == 0
850+
851+ # option packing
852+ assert bytes (pb .opts [0 ]) == b'\x01 \x00 \x0a \x00 \xd0 \xbf \xd0 \xb0 \xd0 \xba \xd0 \xb5 \xd1 \x82 \x00 \x00 '
853+ assert len (pb .opts [0 ]) == 16
854+ assert bytes (pb .opts [1 ]) == b'\x00 \x00 \x00 \x00 '
855+
856+ # block packing
857+ assert bytes (pb ) == bytes (buf )
858+ assert str (pb ) == str (buf )
859+ assert len (pb ) == len (buf )
860+
861+
862+ def test_pb_read ():
863+ """ Test PB parsing as part of file """
864+ pb_packet = (
865+ b'\x02 \x00 \x00 \x00 \x80 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x73 \xe6 \x04 \x00 \xbe \x37 \xe2 \x19 \x4a \x00 '
866+ b'\x00 \x00 \x4a \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x08 \x00 \x45 \x00 '
867+ b'\x00 \x3c \x5d \xb3 \x40 \x00 \x40 \x06 \xdf \x06 \x7f \x00 \x00 \x01 \x7f \x00 \x00 \x01 \x98 \x34 \x11 \x4e '
868+ b'\x95 \xcb \x2d \x3a \x00 \x00 \x00 \x00 \xa0 \x02 \xaa \xaa \xfe \x30 \x00 \x00 \x02 \x04 \xff \xd7 \x04 \x02 '
869+ b'\x08 \x0a \x05 \x8f \x70 \x89 \x00 \x00 \x00 \x00 \x01 \x03 \x03 \x07 \x00 \x00 \x01 \x00 \x0a \x00 \xd0 \xbf '
870+ b'\xd0 \xb0 \xd0 \xba \xd0 \xb5 \xd1 \x82 \x00 \x00 \x00 \x00 \x00 \x00 \x80 \x00 \x00 \x00 ' )
871+
872+ buf = define_testdata ().valid_pcapng + pb_packet
873+ fobj = BytesIO (buf )
874+
875+ # test reading
876+ reader = Reader (fobj )
877+
878+ # first packet is EPB and comes from define_testdata().valid_pcapng
879+ ts , buf1 = next (iter (reader ))
880+ assert ts == 1442984653.210838
881+
882+ # second packet is concatenated PB, pb_packet defined above
883+ ts , buf2 = next (iter (reader ))
884+ assert ts == 1379281936.72595
885+
886+
768887def test_epb_ascii_comment_option ():
769888 """Test EPB with an ascii comment option"""
770889 buf = (
0 commit comments