@@ -1652,7 +1652,7 @@ class RawPcapNgReader(RawPcapReader):
1652
1652
PacketMetadata = collections .namedtuple ("PacketMetadataNg" , # type: ignore
1653
1653
["linktype" , "tsresol" ,
1654
1654
"tshigh" , "tslow" , "wirelen" ,
1655
- "comment " , "ifname" , "direction" ,
1655
+ "comments " , "ifname" , "direction" ,
1656
1656
"process_information" ])
1657
1657
1658
1658
def __init__ (self , filename , fdesc = None , magic = None ): # type: ignore
@@ -1796,8 +1796,8 @@ def _read_packet(self, size=MTU): # type: ignore
1796
1796
return res
1797
1797
1798
1798
def _read_options (self , options ):
1799
- # type: (bytes) -> Dict[int, bytes]
1800
- opts = dict ()
1799
+ # type: (bytes) -> Dict[int, Union[ bytes, List[bytes]] ]
1800
+ opts = dict () # type: Dict[int, Union[bytes, List[bytes]]]
1801
1801
while len (options ) >= 4 :
1802
1802
try :
1803
1803
code , length = struct .unpack (self .endian + "HH" , options [:4 ])
@@ -1806,7 +1806,13 @@ def _read_options(self, options):
1806
1806
"%d !" % len (options ))
1807
1807
raise EOFError
1808
1808
if code != 0 and 4 + length <= len (options ):
1809
- opts [code ] = options [4 :4 + length ]
1809
+ # https://www.ietf.org/archive/id/draft-tuexen-opsawg-pcapng-05.html#name-options-format
1810
+ if code in [1 , 2988 , 2989 , 19372 , 19373 ]:
1811
+ if code not in opts :
1812
+ opts [code ] = []
1813
+ opts [code ].append (options [4 :4 + length ]) # type: ignore
1814
+ else :
1815
+ opts [code ] = options [4 :4 + length ]
1810
1816
if code == 0 :
1811
1817
if length != 0 :
1812
1818
warning ("PcapNg: invalid option "
@@ -1825,6 +1831,12 @@ def _read_block_idb(self, block, _):
1825
1831
options_raw = self ._read_options (block [8 :])
1826
1832
options = self .default_options .copy () # type: Dict[str, Any]
1827
1833
for c , v in options_raw .items ():
1834
+ if isinstance (v , list ):
1835
+ # Spec allows multiple occurrences (see
1836
+ # https://www.ietf.org/archive/id/draft-tuexen-opsawg-pcapng-05.html#section-4.2-8.6)
1837
+ # but does not define which to use. We take the first for
1838
+ # backward compatibility.
1839
+ v = v [0 ]
1828
1840
if c == 9 :
1829
1841
length = len (v )
1830
1842
if length == 1 :
@@ -1880,11 +1892,13 @@ def _read_block_epb(self, block, size):
1880
1892
1881
1893
process_information = {}
1882
1894
for code , value in options .items ():
1883
- if code in [0x8001 , 0x8003 ]: # PCAPNG_EPB_PIB_INDEX, PCAPNG_EPB_E_PIB_INDEX
1895
+ # PCAPNG_EPB_PIB_INDEX, PCAPNG_EPB_E_PIB_INDEX
1896
+ if code in [0x8001 , 0x8003 ]:
1884
1897
try :
1885
- proc_index = struct .unpack (self .endian + "I" , value )[0 ]
1898
+ proc_index = struct .unpack (
1899
+ self .endian + "I" , value )[0 ] # type: ignore
1886
1900
except struct .error :
1887
- warning ("PcapNg: EPB invalid proc index"
1901
+ warning ("PcapNg: EPB invalid proc index "
1888
1902
"(expected 4 bytes, got %d) !" % len (value ))
1889
1903
raise EOFError
1890
1904
if proc_index < len (self .process_information ):
@@ -1894,9 +1908,9 @@ def _read_block_epb(self, block, size):
1894
1908
warning ("PcapNg: EPB invalid process information index "
1895
1909
"(%d/%d) !" % (proc_index , len (self .process_information )))
1896
1910
1897
- comment = options .get (1 , None )
1911
+ comments = options .get (1 , None )
1898
1912
epb_flags_raw = options .get (2 , None )
1899
- if epb_flags_raw :
1913
+ if epb_flags_raw and isinstance ( epb_flags_raw , bytes ) :
1900
1914
try :
1901
1915
epb_flags , = struct .unpack (self .endian + "I" , epb_flags_raw )
1902
1916
except struct .error :
@@ -1917,10 +1931,10 @@ def _read_block_epb(self, block, size):
1917
1931
tshigh = tshigh ,
1918
1932
tslow = tslow ,
1919
1933
wirelen = wirelen ,
1920
- comment = comment ,
1921
1934
ifname = ifname ,
1922
1935
direction = direction ,
1923
- process_information = process_information ))
1936
+ process_information = process_information ,
1937
+ comments = comments ))
1924
1938
1925
1939
def _read_block_spb (self , block , size ):
1926
1940
# type: (bytes, int) -> Tuple[bytes, RawPcapNgReader.PacketMetadata]
@@ -1944,10 +1958,10 @@ def _read_block_spb(self, block, size):
1944
1958
tshigh = None ,
1945
1959
tslow = None ,
1946
1960
wirelen = wirelen ,
1947
- comment = None ,
1948
1961
ifname = None ,
1949
1962
direction = None ,
1950
- process_information = {}))
1963
+ process_information = {},
1964
+ comments = None ))
1951
1965
1952
1966
def _read_block_pkt (self , block , size ):
1953
1967
# type: (bytes, int) -> Tuple[bytes, RawPcapNgReader.PacketMetadata]
@@ -1968,10 +1982,10 @@ def _read_block_pkt(self, block, size):
1968
1982
tshigh = tshigh ,
1969
1983
tslow = tslow ,
1970
1984
wirelen = wirelen ,
1971
- comment = None ,
1972
1985
ifname = None ,
1973
1986
direction = None ,
1974
- process_information = {}))
1987
+ process_information = {},
1988
+ comments = None ))
1975
1989
1976
1990
def _read_block_dsb (self , block , size ):
1977
1991
# type: (bytes, int) -> None
@@ -2043,10 +2057,11 @@ def _read_block_pib(self, block, _):
2043
2057
options = self ._read_options (block )
2044
2058
for code , value in options .items ():
2045
2059
if code == 2 :
2046
- process_information ["name" ] = value .decode ("ascii" , "backslashreplace" )
2060
+ process_information ["name" ] = value .decode ( # type: ignore
2061
+ "ascii" , "backslashreplace" )
2047
2062
elif code == 4 :
2048
2063
if len (value ) == 16 :
2049
- process_information ["uuid" ] = str (UUID (bytes = value ))
2064
+ process_information ["uuid" ] = str (UUID (bytes = value )) # type: ignore
2050
2065
else :
2051
2066
warning ("PcapNg: DPEB UUID length is invalid (%d)!" ,
2052
2067
len (value ))
@@ -2072,7 +2087,7 @@ def read_packet(self, size=MTU, **kwargs):
2072
2087
rp = super (PcapNgReader , self )._read_packet (size = size )
2073
2088
if rp is None :
2074
2089
raise EOFError
2075
- s , (linktype , tsresol , tshigh , tslow , wirelen , comment , ifname , direction , process_information ) = rp # noqa: E501
2090
+ s , (linktype , tsresol , tshigh , tslow , wirelen , comments , ifname , direction , process_information ) = rp # noqa: E501
2076
2091
try :
2077
2092
cls = conf .l2types .num2layer [linktype ] # type: Type[Packet]
2078
2093
p = cls (s , ** kwargs ) # type: Packet
@@ -2088,7 +2103,7 @@ def read_packet(self, size=MTU, **kwargs):
2088
2103
if tshigh is not None :
2089
2104
p .time = EDecimal ((tshigh << 32 ) + tslow ) / tsresol
2090
2105
p .wirelen = wirelen
2091
- p .comment = comment
2106
+ p .comments = comments
2092
2107
p .direction = direction
2093
2108
p .process_information = process_information .copy ()
2094
2109
if ifname is not None :
@@ -2114,9 +2129,9 @@ def _write_packet(self,
2114
2129
usec = None , # type: Optional[int]
2115
2130
caplen = None , # type: Optional[int]
2116
2131
wirelen = None , # type: Optional[int]
2117
- comment = None , # type: Optional[bytes]
2118
2132
ifname = None , # type: Optional[bytes]
2119
2133
direction = None , # type: Optional[int]
2134
+ comments = None , # type: Optional[List[bytes]]
2120
2135
):
2121
2136
# type: (...) -> None
2122
2137
raise NotImplementedError
@@ -2197,7 +2212,7 @@ def write_packet(self,
2197
2212
if wirelen is None :
2198
2213
wirelen = caplen
2199
2214
2200
- comment = getattr (packet , "comment " , None )
2215
+ comments = getattr (packet , "comments " , None )
2201
2216
ifname = getattr (packet , "sniffed_on" , None )
2202
2217
direction = getattr (packet , "direction" , None )
2203
2218
if not isinstance (packet , bytes ):
@@ -2212,10 +2227,10 @@ def write_packet(self,
2212
2227
rawpkt ,
2213
2228
sec = f_sec , usec = usec ,
2214
2229
caplen = caplen , wirelen = wirelen ,
2215
- comment = comment ,
2216
2230
ifname = ifname ,
2217
2231
direction = direction ,
2218
- linktype = linktype
2232
+ linktype = linktype ,
2233
+ comments = comments ,
2219
2234
)
2220
2235
2221
2236
@@ -2367,9 +2382,9 @@ def _write_packet(self,
2367
2382
usec = None , # type: Optional[int]
2368
2383
caplen = None , # type: Optional[int]
2369
2384
wirelen = None , # type: Optional[int]
2370
- comment = None , # type: Optional[bytes]
2371
2385
ifname = None , # type: Optional[bytes]
2372
2386
direction = None , # type: Optional[int]
2387
+ comments = None , # type: Optional[List[bytes]]
2373
2388
):
2374
2389
# type: (...) -> None
2375
2390
"""
@@ -2545,7 +2560,7 @@ def _write_block_epb(self,
2545
2560
timestamp = None , # type: Optional[Union[EDecimal, float]] # noqa: E501
2546
2561
caplen = None , # type: Optional[int]
2547
2562
orglen = None , # type: Optional[int]
2548
- comment = None , # type: Optional[bytes]
2563
+ comments = None , # type: Optional[List[ bytes] ]
2549
2564
flags = None , # type: Optional[int]
2550
2565
):
2551
2566
# type: (...) -> None
@@ -2580,11 +2595,12 @@ def _write_block_epb(self,
2580
2595
2581
2596
# Options
2582
2597
opts = b''
2583
- if comment is not None :
2584
- comment = bytes_encode (comment )
2585
- opts += struct .pack (self .endian + "HH" , 1 , len (comment ))
2586
- # Pad Option Value to 32 bits
2587
- opts += self ._add_padding (comment )
2598
+ if comments and len (comments ):
2599
+ for c in comments :
2600
+ comment = bytes_encode (c )
2601
+ opts += struct .pack (self .endian + "HH" , 1 , len (comment ))
2602
+ # Pad Option Value to 32 bits
2603
+ opts += self ._add_padding (comment )
2588
2604
if type (flags ) == int :
2589
2605
opts += struct .pack (self .endian + "HH" , 2 , 4 )
2590
2606
opts += struct .pack (self .endian + "I" , flags )
@@ -2601,9 +2617,9 @@ def _write_packet(self, # type: ignore
2601
2617
usec = None , # type: Optional[int]
2602
2618
caplen = None , # type: Optional[int]
2603
2619
wirelen = None , # type: Optional[int]
2604
- comment = None , # type: Optional[bytes]
2605
2620
ifname = None , # type: Optional[bytes]
2606
2621
direction = None , # type: Optional[int]
2622
+ comments = None , # type: Optional[List[bytes]]
2607
2623
):
2608
2624
# type: (...) -> None
2609
2625
"""
@@ -2659,7 +2675,7 @@ def _write_packet(self, # type: ignore
2659
2675
flags = None
2660
2676
2661
2677
self ._write_block_epb (packet , timestamp = sec , caplen = caplen ,
2662
- orglen = wirelen , comment = comment , ifid = ifid , flags = flags )
2678
+ orglen = wirelen , comments = comments , ifid = ifid , flags = flags )
2663
2679
if self .sync :
2664
2680
self .f .flush ()
2665
2681
0 commit comments