TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / wiretap / vwr.c
blob3bd47759eda511c72d673e3a791d2635ca6f1719
1 /* vwr.c
2 * Copyright (c) 2011 by Tom Alexander <talexander@ixiacom.com>
4 * Wiretap Library
5 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10 #include "config.h"
11 #include "vwr.h"
13 #include <string.h>
15 #include "wtap-int.h"
16 #include "file_wrappers.h"
18 #include <wsutil/ws_assert.h>
20 /* platform-specific definitions for portability */
22 /* unsigned long long constants */
23 # define NS_IN_US UINT64_C(1000) /* nanoseconds-to-microseconds */
24 # define NS_IN_SEC UINT64_C(1000000000) /* nanoseconds-to-seconds */
25 # define US_IN_SEC UINT64_C(1000000) /* microseconds-to-seconds */
26 # define LL_ZERO UINT64_C(0) /* zero in unsigned long long */
29 * Fetch a 64-bit value in "Corey-endian" form.
31 #define pcoreytohll(p) ((uint64_t)*((const uint8_t *)(p)+4)<<56| \
32 (uint64_t)*((const uint8_t *)(p)+5)<<48| \
33 (uint64_t)*((const uint8_t *)(p)+6)<<40| \
34 (uint64_t)*((const uint8_t *)(p)+7)<<32| \
35 (uint64_t)*((const uint8_t *)(p)+0)<<24| \
36 (uint64_t)*((const uint8_t *)(p)+1)<<16| \
37 (uint64_t)*((const uint8_t *)(p)+2)<<8| \
38 (uint64_t)*((const uint8_t *)(p)+3)<<0)
41 * Fetch a 48-bit value in "Corey-endian" form; it's stored as
42 * a 64-bit Corey-endian value, with the upper 16 bits ignored.
44 #define pcorey48tohll(p) ((uint64_t)*((const uint8_t *)(p)+6)<<40| \
45 (uint64_t)*((const uint8_t *)(p)+7)<<32| \
46 (uint64_t)*((const uint8_t *)(p)+0)<<24| \
47 (uint64_t)*((const uint8_t *)(p)+1)<<16| \
48 (uint64_t)*((const uint8_t *)(p)+2)<<8| \
49 (uint64_t)*((const uint8_t *)(p)+3)<<0)
51 /* .vwr log file defines */
52 #define B_SIZE 32768 /* max var len message = 32 kB */
53 #define VT_FRAME 0 /* varlen msg is a frame */
54 #define VT_CPMSG 1 /* varlen msg is a CP<->PP msg */
55 #define VT_UNKNOWN -1 /* varlen msg is unknown */
56 #define MAX_TRACKED_CLIENTS 1024 /* track 1024 clients */
57 #define MAX_TRACKED_FLOWS 65536 /* and 64K flows */
60 * The file consists of a sequence of records.
61 * A record begins with a 16-byte header, the first 8 bytes of which
62 * begin with a byte containing a command plus transmit-receive flags.
64 * Following that are two big-endian 32-bit quantities; for some records
65 * one or the other of them is the length of the rest of the record.
66 * Other records contain only the header.
68 #define VW_RECORD_HEADER_LENGTH 16
71 * Maximum number of bytes to read looking for a valid frame starting
72 * with a command byte to determine if this is our file type. Arbitrary.
74 #define VW_BYTES_TO_CHECK 0x3FFFFFFFU
76 /* Command byte values */
77 #define COMMAND_RX 0x21
78 #define COMMAND_TX 0x31
79 #define COMMAND_RFN 0x30
80 #define COMMAND_RF 0x38
81 #define COMMAND_RFRX 0x39
84 * The data in packet records begins with a sequence of metadata headers.
86 * For packet records from FPGA versions < 48:
88 * The first header is the IxVeriWave common header, and that's
89 * followed either by a WLAN metadata header or an Ethernet
90 * metadata header. The port type field indicates whether it's
91 * a WLAN packet or an Ethernet packet. Following that may, for
92 * WLAN, be 1 octet of information from the FPGA and 16 bytes of
93 * data including the PLCP header. After that comes the WLAN or
94 * Ethernet frame, beginning with the MAC header.
96 * For packet records from FPGA versions >= 48:
98 * The first header contains only a 1-octet port type value, which
99 * has a packet type value in the upper 4 bits and zero in the lower
100 * 4 bits. NOTE: this is indistinguishable from an old FPGA header
101 * if the packet type value is 0.
103 * If the packet type value isn't 3, the port type value is followed
104 * by a 1-octet FPGA version number, which is followed by a timestamp
105 * header.
107 * If the packet type value is 3 or 4, the next item is an RF metadata
108 * header. For type 3, that immediately follows the port number octet,
109 * otherwise it immediately follows the timestamp header.
111 * If the packet type isn't 3, the next item is a WLAN metadata header,
112 * in a format different from the WLAN metadata header for FPGA versions
113 * < 48. That is followed by a PLCP header, which is followed by a
114 * header giving additional layer 2 through 4 metadata.
116 * Following those headers is the WLAN or Ethernet frame, beginning with
117 * the MAC header.
121 * IxVeriWave common header:
123 * 1 octet - port type
124 * 1 octet - FPGA version, or 0
125 * 2 octets - length of the common header
126 * 2 octets - MSDU length
127 * 4 octets - flow ID
128 * 2 octets - VC ID
129 * 2 octets - flow sequence number
130 * 4 octets - latency or 0
131 * 4 octets - lower 32 bits of signature time stamp
132 * 8 octets - start time
133 * 8 octets - end time
134 * 4 octets - delta(?) time
137 /* Size of the IxVeriWave common header */
138 #define STATS_COMMON_FIELDS_LEN (1+1+2+2+4+2+2+4+4+8+8+4)
140 /* Port type */
141 #define WLAN_PORT 0
142 #define ETHERNET_PORT 1
144 /* For VeriWave WLAN and Ethernet metadata headers vw_flags field */
145 #define VW_FLAGS_TXF 0x01 /* frame was transmitted */
146 #define VW_FLAGS_FCSERR 0x02 /* FCS error detected */
149 * VeriWave WLAN metadata header:
151 * 2 octets - header length
152 * 2 octets - rflags
153 * 2 octets - channel flags
154 * 2 octets - PHY rate
155 * 1 octet - PLCP type
156 * 1 octet - MCS index
157 * 1 octet - number of spatial streams
158 * 1 octet - RSSI
159 * 1 octet - antenna b signal power, or 100 if missing
160 * 1 octet - antenna c signal power, or 100 if missing
161 * 1 octet - antenna d signal power, or 100 if missing
162 * 1 octet - padding
163 * 2 octets - VeriWave flags
164 * 2 octets - HT len
165 * 2 octets - info
166 * 2 octets - errors
169 /* Size of the VeriWave WLAN metadata header */
170 #define EXT_WLAN_FIELDS_LEN (2+2+2+2+1+1+1+1+1+1+1+1+2+2+2+4)
172 /* Flags, for rflags field */
173 #define FLAGS_SHORTPRE 0x0002 /* sent/received with short preamble */
174 #define FLAGS_WEP 0x0004 /* sent/received with WEP encryption */
175 #define FLAGS_CHAN_HT 0x0040 /* In HT mode */
176 #define FLAGS_CHAN_VHT 0x0080 /* VHT Mode */
177 #define FLAGS_CHAN_SHORTGI 0x0100 /* Short guard interval */
178 #define FLAGS_CHAN_40MHZ 0x0200 /* 40 Mhz channel bandwidth */
179 #define FLAGS_CHAN_80MHZ 0x0400 /* 80 Mhz channel bandwidth */
180 #define FLAGS_CHAN_160MHZ 0x0800 /* 160 Mhz channel bandwidth */
182 /* Channel flags, for channel flags field */
183 #define CHAN_CCK 0x0020 /* CCK channel */
184 #define CHAN_OFDM 0x0040 /* OFDM channel */
186 /* For VeriWave WLAN metadata header vw_flags field */
187 #define VW_FLAGS_RETRERR 0x04 /* excess retry error detected */
188 #define VW_FLAGS_DCRERR 0x10 /* decrypt error detected (WLAN) */
189 #define VW_FLAGS_ENCMSK 0x60 /* encryption type mask */
190 /* 0 = none, 1 = WEP, 2 = TKIP, 3 = CCKM */
191 #define VW_FLAGS_IS_WEP 0x20 /* WEP */
192 #define VW_FLAGS_IS_TKIP 0x40 /* TKIP */
193 #define VW_FLAGS_IS_CCMP 0x60 /* CCMP */
196 * VeriWave Ethernet metadata header:
198 * 2 octets - header length
199 * 2 octets - VeriWave flags
200 * 2 octets - info
201 * 4 octets - errors
202 * 4 octets - layer 4 ID
203 * 4 octets - pad
205 * Ethernet frame follows, beginning with the MAC header
208 /* Size of the VeriWave Ethernet metadata header */
209 #define EXT_ETHERNET_FIELDS_LEN (2+2+2+4+4+4)
212 * OCTO timestamp header.
214 * 4 octets - latency or 0
215 * 4 octets - lower 32 bits of signature time stamp
216 * 8 octets - start time
217 * 8 octets - end time
218 * 4 octets - delta(?) time
221 /* Size of Timestamp header */
222 #define OCTO_TIMESTAMP_FIELDS_LEN (4+4+8+8+4+4)
225 * OCTO layer 1-4 header:
227 * 2 octets - header length
228 * 1 octet - l1p_1
229 * 1 octet - number of spatial streams
230 * 2 octets - PHY rate
231 * 1 octet - l1p_2
232 * 1 octet - RSSI
233 * 1 octet - antenna b signal power, or 100 if missing
234 * 1 octet - antenna c signal power, or 100 if missing
235 * 1 octet - antenna d signal power, or 100 if missing
236 * 1 octet - signal bandwidth mask
237 * 1 octet - antenna port energy detect and VU_MASK
238 * 1 octet - L1InfoC or 0
239 * 2 octets - MSDU length
240 * 16 octets - PLCP?
241 * 4 octets - BM, BV, CV, BSSID and ClientID
242 * 2 octets - FV, QT, HT, L4V, TID and WLAN type
243 * 1 octets - flow sequence number
244 * 3 octets - flow ID
245 * 2 octets - layer 4 ID
246 * 4 octets - payload decode
247 * 3 octets - info
248 * 4 octets - errors
251 /* Size of Layer-1, PLCP, and Layer-2/4 header in case of OCTO version FPGA */
252 #define OCTO_LAYER1TO4_LEN (2+14+16+23)
255 * OCTO modified RF layer:
257 * 1 octet - RF ID
258 * 3 octets - unused (zero)
259 * 8 octets - noise for 4 ports
260 * 8 octets - signal/noise ration for 4 ports
261 * 8 octets - PFE for 4 ports
262 * 8 octets - EVM SIG data for 4 ports
263 * 8 octets - EVM SIG pilot for 4 ports
264 * 8 octets - EVM Data data for 4 ports
265 * 8 octets - EVM Data pilot for 4 ports
266 * 8 octets - EVM worst symbol for 4 ports
267 * 8 octets - CONTEXT_P for 4 ports
269 * Not supplied:
270 * 24 octets of additional data
273 /* Size of RF header, if all fields were supplied */
274 #define OCTO_RF_MOD_ACTUAL_LEN 100 /* */
276 /* Size of RF header with the fields we do supply */
277 #define OCTO_MODIFIED_RF_LEN 76 /* 24 bytes of RF are not displayed*/
279 /*Offset of different parameters of RF header for port-1*/
280 #define RF_PORT_1_NOISE_OFF 4
281 #define RF_PORT_1_SNR_OFF 6
282 #define RF_PORT_1_PFE_OFF 8
283 #define RF_PORT_1_CONTEXT_OFF 10
284 #define RF_PORT_1_EVM_SD_SIG_OFF 12
285 #define RF_PORT_1_EVM_SP_SIG_OFF 14
286 #define RF_PORT_1_EVM_SD_DATA_OFF 16
287 #define RF_PORT_1_EVM_SP_DATA_OFF 18
288 #define RF_PORT_1_DSYMBOL_IDX_OFF 22
289 #define RF_INTER_PORT_GAP_OFF 24 /*As size of RF information per port is 24 bytes*/
290 #define RF_NUMBER_OF_PORTS 4
292 /* FPGA-generated frame buffer STATS block offsets and definitions */
294 /* definitions for v2.2 frames, Ethernet format */
295 #define v22_E_STATS_LEN 44 /* length of stats block trailer */
296 #define v22_E_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
297 #define v22_E_MTYPE_OFF 1 /* offset of modulation type */
298 #define v22_E_VCID_OFF 2 /* offset of VC ID */
299 #define v22_E_FLOWSEQ_OFF 4 /* offset of signature sequence number */
300 #define v22_E_FLOWID_OFF 5 /* offset of flow ID */
301 #define v22_E_OCTET_OFF 8 /* offset of octets */
302 #define v22_E_ERRORS_OFF 10 /* offset of error vector */
303 #define v22_E_PATN_OFF 12 /* offset of pattern match vector */
304 #define v22_E_L4ID_OFF 12
305 #define v22_E_IPLEN_OFF 14
306 #define v22_E_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
307 #define v22_E_RSSI_OFF 21 /* RSSI (NOTE: invalid for Ethernet) */
308 #define v22_E_STARTT_OFF 20 /* offset of start time, 64 bits */
309 #define v22_E_ENDT_OFF 28 /* offset of end time, 64 bits */
310 #define v22_E_LATVAL_OFF 36 /* offset of latency, 32 bits */
311 #define v22_E_INFO_OFF 40 /* NO INFO FIELD IN ETHERNET STATS! */
312 #define v22_E_DIFFERENTIATOR_OFF 0 /* offset to determine whether */
313 /* eth/802.11, 8 bits */
314 /* Media types */
315 #define v22_E_MT_10_HALF 0 /* 10 Mb/s half-duplex */
316 #define v22_E_MT_10_FULL 1 /* 10 Mb/s full-duplex */
317 #define v22_E_MT_100_HALF 2 /* 100 Mb/s half-duplex */
318 #define v22_E_MT_100_FULL 3 /* 100 Mb/s full-duplex */
319 #define v22_E_MT_1G_HALF 4 /* 1 Gb/s half-duplex */
320 #define v22_E_MT_1G_FULL 5 /* 1 Gb/s full-duplex */
322 /* Error flags */
323 #define v22_E_FCS_ERROR 0x0002 /* FCS error flag in error vector */
324 #define v22_E_CRYPTO_ERR 0x1f00 /* RX decrypt error flags (UNUSED) */
325 #define v22_E_SIG_ERR 0x0004 /* signature magic byte mismatch */
326 #define v22_E_PAYCHK_ERR 0x0008 /* payload checksum failure */
327 #define v22_E_RETRY_ERR 0x0400 /* excessive retries on TX fail (UNUSED)*/
329 /* Masks and defines */
330 #define v22_E_IS_RX 0x08 /* TX/RX bit in STATS block */
331 #define v22_E_MT_MASK 0x07 /* modulation type mask (UNUSED) */
333 #define v22_E_VCID_MASK 0x03ff /* VC ID is only 10 bits */
335 #define v22_E_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
337 #define v22_E_DIFFERENTIATOR_MASK 0x3F /* mask to differentiate ethernet from */
339 /* Bits in FRAME_TYPE field */
340 #define v22_E_IS_TCP 0x00000040 /* TCP bit in FRAME_TYPE field */
341 #define v22_E_IS_UDP 0x00000010 /* UDP bit in FRAME_TYPE field */
342 #define v22_E_IS_ICMP 0x00000020 /* ICMP bit in FRAME_TYPE field */
343 #define v22_E_IS_IGMP 0x00000080 /* IGMP bit in FRAME_TYPE field */
345 /* Bits in MTYPE field (WLAN only) */
346 #define v22_E_IS_QOS 0x80 /* QoS bit in MTYPE field (WLAN only) */
348 #define v22_E_IS_VLAN 0x00200000
350 #define v22_E_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted (UNUSED) */
351 #define v22_E_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted (UNUSED) */
353 #define v22_E_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
355 #define v22_E_IS_ETHERNET 0x00700000 /* bits set in frame type if ethernet */
356 #define v22_E_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
358 /* definitions for v2.2 frames, WLAN format for VW510006 FPGA*/
359 #define v22_W_STATS_LEN 64 /* length of stats block trailer */
360 #define v22_W_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
361 #define v22_W_MTYPE_OFF 1 /* offset of modulation type */
362 #define v22_W_VCID_OFF 2 /* offset of VC ID */
363 #define v22_W_FLOWSEQ_OFF 4 /* offset of signature sequence number */
364 #define v22_W_FLOWID_OFF 5 /* offset of flow ID */
365 #define v22_W_OCTET_OFF 8 /* offset of octets */
366 #define v22_W_ERRORS_OFF 10 /* offset of error vector */
367 #define v22_W_PATN_OFF 12
368 #define v22_W_L4ID_OFF 12
369 #define v22_W_IPLEN_OFF 14
370 #define v22_W_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
371 #define v22_W_RSSI_OFF 21 /* RSSI (NOTE: RSSI must be negated!) */
372 #define v22_W_STARTT_OFF 24 /* offset of start time, 64 bits */
373 #define v22_W_ENDT_OFF 32 /* offset of end time, 64 bits */
374 #define v22_W_LATVAL_OFF 40 /* offset of latency, 32 bits */
375 #define v22_W_INFO_OFF 54 /* offset of INFO field, 16 LSBs */
376 #define v22_W_DIFFERENTIATOR_OFF 20 /* offset to determine whether */
377 /* eth/802.11, 32 bits */
379 #define v22_W_PLCP_LENGTH_OFF 4 /* LENGTH field in the plcp header */
381 /* Modulation types */
382 #define v22_W_MT_CCKL 0 /* CCK modulation, long preamble */
383 #define v22_W_MT_CCKS 1 /* CCK modulation, short preamble */
384 #define v22_W_MT_OFDM 2 /* OFDM modulation */
386 /* Bits in FRAME_TYPE field */
387 #define v22_W_IS_TCP 0x00000040 /* TCP bit in FRAME_TYPE field */
388 #define v22_W_IS_UDP 0x00000010 /* UDP bit in FRAME_TYPE field */
389 #define v22_W_IS_ICMP 0x00000020 /* ICMP bit in FRAME_TYPE field */
390 #define v22_W_IS_IGMP 0x00000080 /* IGMP bit in FRAME_TYPE field */
392 /* Bits in MTYPE field (WLAN only) */
393 #define v22_W_IS_QOS 0x80 /* QoS */
395 /* Error flags */
396 #define v22_W_FCS_ERROR 0x0002 /* FCS error flag in error vector */
397 #define v22_W_CRYPTO_ERR 0x1f00 /* RX decrypt error flags */
398 #define v22_W_SIG_ERR 0x0004 /* signature magic byte mismatch */
399 #define v22_W_PAYCHK_ERR 0x0008 /* payload checksum failure */
400 #define v22_W_RETRY_ERR 0x0400 /* excessive retries on TX failure */
402 /* Masks and defines */
403 #define v22_W_IS_RX 0x08 /* TX/RX bit in STATS block */
404 #define v22_W_MT_MASK 0x07 /* modulation type mask */
406 #define v22_W_VCID_MASK 0x01ff /* VC ID is only 9 bits */
408 #define v22_W_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
410 #define v22_W_DIFFERENTIATOR_MASK 0xf0ff /* mask to differentiate ethernet from */
411 /* 802.11 capture */
413 #define v22_W_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted bits */
414 #define v22_W_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted bits */
416 /* Info bits */
417 #define v22_W_WEPTYPE 0x0001 /* WEP frame */
418 #define v22_W_TKIPTYPE 0x0002 /* TKIP frame */
419 #define v22_W_CCMPTYPE 0x0004 /* CCMP frame */
420 #define v22_W_MPDU_OF_A_MPDU 0x0400 /* MPDU of A-MPDU */
421 #define v22_W_FIRST_MPDU_OF_A_MPDU 0x0800 /* first MPDU of A-MPDU */
422 #define v22_W_LAST_MPDU_OF_A_MPDU 0x1000 /* last MPDU of A-MPDU */
423 #define v22_W_MSDU_OF_A_MSDU 0x2000 /* MSDU of A-MSDU */
424 #define v22_W_FIRST_MSDU_OF_A_MSDU 0x4000 /* first MSDU of A-MSDU */
425 #define v22_W_LAST_MSDU_OF_A_MSDU 0x8000 /* last MSDU of A-MSDU */
427 /* All aggregation flags */
428 #define v22_W_AGGREGATE_FLAGS \
429 (v22_W_MPDU_OF_A_MPDU | \
430 v22_W_FIRST_MPDU_OF_A_MPDU | \
431 v22_W_LAST_MPDU_OF_A_MPDU | \
432 v22_W_MSDU_OF_A_MSDU | \
433 v22_W_FIRST_MSDU_OF_A_MSDU | \
434 v22_W_LAST_MSDU_OF_A_MSDU)
436 #define v22_W_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
438 #define v22_W_IS_ETHERNET 0x00100000 /* bits set in frame type if ethernet */
439 #define v22_W_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
441 /* definitions for VW510021 FPGA, WLAN format */
442 /* FORMAT:
443 16 BYTE header
444 8 bytes of stat block
445 plcp stuff (11 bytes plcp + 1 byte pad)
446 data
447 remaining 48 bytes of stat block
449 /* offsets in the stats block */
450 #define vVW510021_W_STATS_HEADER_LEN 8 /* length of stats block header at beginning of record data */
451 #define vVW510021_W_STATS_TRAILER_LEN 48 /* length of stats block trailer after the plcp portion*/
452 #define vVW510021_W_STARTT_OFF 0 /* offset of start time, 64 bits */
453 #define vVW510021_W_ENDT_OFF 8 /* offset of end time, 64 bits */
454 #define vVW510021_W_ERRORS_OFF 16 /* offset of error vector */
455 #define vVW510021_W_VALID_OFF 20 /* 2 Bytes with different validity bits */
456 #define vVW510021_W_INFO_OFF 22 /* offset of INFO field, 16 LSBs */
457 #define vVW510021_W_FRAME_TYPE_OFF 24
458 #define vVW510021_W_L4ID_OFF 28
459 #define vVW510021_W_IPLEN_OFF 30 /* offset of IP Total Length field */
460 #define vVW510021_W_FLOWSEQ_OFF 32 /* offset of signature sequence number */
461 #define vVW510021_W_FLOWID_OFF 33 /* offset of flow ID */
462 #define vVW510021_W_LATVAL_OFF 36 /* offset of delay/flowtimestamp, 32b */
463 #define vVW510021_W_DEBUG_OFF 40 /* offset of debug, 16 bits */
464 #define S2_W_FPGA_VERSION_OFF 44 /* offset of fpga version, 16 bits */
465 #define vVW510021_W_MATCH_OFF 47 /* offset of pattern match vector */
467 /* offsets in the header block */
468 #define vVW510021_W_HEADER_LEN 16 /* length of FRAME header */
469 #define vVW510021_W_RXTX_OFF 0 /* rxtx offset, cmd byte of header */
470 #define vVW510021_W_HEADER_VERSION_OFF 9 /* version, 2bytes */
471 #define vVW510021_MSG_LENGTH_OFF 10 /* MSG LENGTH, 2bytes */
472 #define vVW510021_W_DEVICE_TYPE_OFF 8 /* version, 2bytes */
474 /* offsets that occur right after the header */
475 #define vVW510021_W_AFTERHEADER_LEN 8 /* length of STATs info directly after header */
476 #define vVW510021_W_L1P_1_OFF 0 /* offset of 1st byte of layer one info */
477 #define vVW510021_W_L1P_2_OFF 1 /* offset of 2nd byte of layer one info */
478 #define vVW510021_W_MTYPE_OFF vVW510021_W_L1P_2_OFF
479 #define vVW510021_W_PREAMBLE_OFF vVW510021_W_L1P_1_OFF
480 #define vVW510021_W_RSSI_TXPOWER_OFF 2 /* RSSI (NOTE: RSSI must be negated!) */
481 #define vVW510021_W_MSDU_LENGTH_OFF 3 /* 7:0 of length, next byte 11:8 in top 4 bits */
482 #define vVW510021_W_BVCV_VALID_OFF 4 /* BV,CV Determine validity of bssid and txpower */
483 #define vVW510021_W_VCID_OFF 6 /* offset of VC (client) ID */
484 #define vVW510021_W_PLCP_LENGTH_OFF 12 /* LENGTH field in the plcp header */
486 /* Masks and defines */
487 #define vVW510021_W_IS_BV 0x04 /* BV bit in STATS block */
488 #define vVW510021_W_IS_CV 0x02 /* BV bit in STATS block */
489 #define vVW510021_W_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else 0) */
490 #define vVW510021_W_QOS_VALID 0x4000
491 #define vVW510021_W_HT_VALID 0x2000
492 #define vVW510021_W_L4ID_VALID 0x1000
493 #define vVW510021_W_MCS_MASK 0x3f /* mcs index (a/b) type mask */
494 #define vVW510021_W_MOD_SCHEME_MASK 0x3f /* modulation type mask */
495 #define vVW510021_W_PLCPC_MASK 0x03 /* PLPCP type mask */
496 #define vVW510021_W_SEL_MASK 0x80
497 #define vVW510021_W_WEP_MASK 0x0001
498 #define vVW510021_W_CBW_MASK 0xC0
500 #define vVW510024_W_VCID_MASK 0x03ff /* VC ID is only 10 bits */
502 #define vVW510021_W_MT_SEL_LEGACY 0x00
504 #define vVW510021_W_IS_WEP 0x0001
506 /* L1p byte 1 info */
508 /* Common to Series II and Series III */
510 #define vVW510021_W_IS_LONGPREAMBLE 0x40 /* short/long preamble bit */
511 #define vVW510021_W_IS_LONGGI 0x40 /* short/long guard interval bit */
513 /* Series II */
516 * Pre-HT - contains rate index.
518 #define vVW510021_W_S2_RATE_INDEX(l1p_1) ((l1p_1) & 0x3f) /* rate index for pre-HT */
521 * HT - contains MCS index.
523 * XXX - MCS indices for HT go up to 76, which doesn't fit in 6 bits;
524 * either the mask is wrong, or the hardware can't receive packets
525 * with an MCS of 64 through 76, or the hardware can but misreports
526 * the MCS.
528 #define vVW510021_W_S2_MCS_INDEX_HT(l1p_1) ((l1p_1) & 0x3f)
531 * VHT - contains MCS index and number of spatial streams.
532 * The number of spatial streams from the FPGA is zero-based, so we add
533 * 1 to it.
535 #define vVW510021_W_S2_MCS_INDEX_VHT(l1p_1) ((l1p_1) & 0x0f) /* MCS index for VHT */
536 #define vVW510021_W_S2_NSS_VHT(l1p_1) (((l1p_1) >> 4) + 1) /* NSS */
538 /* Series III */
541 * Pre-HT - contains rate index.
543 #define vVW510021_W_S3_RATE_INDEX(l1p_1) ((l1p_1) & 0x3f)
546 * HT - contains MCS index.
548 * XXX - MCS indices for HT go up to 76, which doesn't fit in 6 bits;
549 * either the mask is wrong, or the hardware can't receive packets
550 * with an MCS of 64 through 76, or the hardware can but misreports
551 * the MCS.
553 #define vVW510021_W_S3_MCS_INDEX_HT(l1p_1) ((l1p_1) & 0x3f)
556 * VHT - contains MCS index and number of spatial streams.
557 * The number of spatial streams from the FPGA is zero-based, so we add
558 * 1 to it.
560 #define vVW510021_W_S3_MCS_INDEX_VHT(l1p_1) ((l1p_1) & 0x0f) /* MCS index */
561 #define vVW510021_W_S3_NSS_VHT(l1p_1) ((((l1p_1) >> 4) & 0x03) + 1) /* NSS */
563 /* L1p byte 2 info */
565 /* Common to Series II and Series III */
566 #define vVW510021_W_BANDWIDTH_VHT(l1p_2) (((l1p_2) >> 4) & 0xf)
567 /* 3 = 40 MHz, 4 = 80 MHz; what about 20 and 160 MHz? */
569 /* Series II */
570 #define vVW510021_W_S2_PLCP_TYPE(l1p_2) ((l1p_2) & 0x03) /* PLCP type */
572 /* Series III */
573 #define vVW510021_W_S3_PLCP_TYPE(l1p_2) ((l1p_2) & 0x0f) /* PLCP type */
575 /* PLCP types */
576 #define vVW510021_W_PLCP_LEGACY 0x00 /* pre-HT (11b/a/g) */
577 #define vVW510021_W_PLCP_MIXED 0x01 /* HT, mixed (11n) */
578 #define vVW510021_W_PLCP_GREENFIELD 0x02 /* HT, greenfield (11n) */
579 #define vVW510021_W_PLCP_VHT_MIXED 0x03 /* VHT (11ac) */
581 /* Bits in FRAME_TYPE field */
582 #define vVW510021_W_IS_TCP 0x01000000 /* TCP */
583 #define vVW510021_W_IS_UDP 0x00100000 /* UDP */
584 #define vVW510021_W_IS_ICMP 0x00001000 /* ICMP */
585 #define vVW510021_W_IS_IGMP 0x00010000 /* IGMP */
587 #define vVW510021_W_HEADER_VERSION 0x00
588 #define vVW510021_W_DEVICE_TYPE 0x15
589 #define vVW510021_W_11n_DEVICE_TYPE 0x20
590 #define S2_W_FPGA_VERSION 0x000C
591 #define vVW510021_W_11n_FPGA_VERSION 0x000D
593 /* Error flags */
594 #define vVW510021_W_FCS_ERROR 0x01
596 #define vVW510021_W_CRYPTO_ERROR 0x50000
598 #define vVW510021_W_WEPTYPE 0x0001 /* WEP frame */
599 #define vVW510021_W_TKIPTYPE 0x0002 /* TKIP frame */
600 #define vVW510021_W_CCMPTYPE 0x0004 /* CCMP frame */
602 /* definitions for VW510024 FPGA, wired ethernet format */
603 /* FORMAT:
604 16 BYTE header
605 52 bytes of stats block trailer
607 /* offsets in the stats block */
608 #define vVW510024_E_STATS_LEN 48 /* length of stats block trailer */
609 #define vVW510024_E_MSDU_LENGTH_OFF 0 /* MSDU 16 BITS */
610 #define vVW510024_E_BMCV_VALID_OFF 2 /* BM,CV Determine validITY */
611 #define vVW510024_E_VCID_OFF 2 /* offset of VC (client) ID 13:8, */
612 /* 7:0 IN offset 7*/
613 #define vVW510024_E_STARTT_OFF 4 /* offset of start time, 64 bits */
614 #define vVW510024_E_ENDT_OFF 12 /* offset of end time, 64 bits */
615 #define vVW510024_E_ERRORS_OFF 22 /* offset of error vector */
616 #define vVW510024_E_VALID_OFF 24 /* 2 Bytes with different validity bits */
617 #define vVW510024_E_INFO_OFF 26 /* offset of INFO field, 16 LSBs */
618 #define vVW510024_E_FRAME_TYPE_OFF 28
619 #define vVW510024_E_L4ID_OFF 32
620 #define vVW510024_E_IPLEN_OFF 34
621 #define vVW510024_E_FLOWSEQ_OFF 36 /* offset of signature sequence number */
622 #define vVW510024_E_FLOWID_OFF 37 /* offset of flow ID */
623 #define vVW510024_E_LATVAL_OFF 40 /* offset of delay/flowtimestamp, 32 bits */
624 #define vVW510024_E_FPGA_VERSION_OFF 20 /* offset of fpga version, 16 bits */
625 #define vVW510024_E_MATCH_OFF 51 /* offset of pattern match vector */
627 /* offsets in the header block */
628 #define vVW510024_E_HEADER_LEN vVW510021_W_HEADER_LEN /* length of FRAME header */
629 #define vVW510024_E_RXTX_OFF vVW510021_W_RXTX_OFF /* rxtx offset, cmd byte */
630 #define vVW510024_E_HEADER_VERSION_OFF 16 /* version, 2bytes */
631 #define vVW510024_E_MSG_LENGTH_OFF vVW510021_MSG_LENGTH_OFF /* MSG LENGTH, 2bytes */
632 #define vVW510024_E_DEVICE_TYPE_OFF vVW510021_W_DEVICE_TYPE_OFF /* Device Type, 2bytes */
634 /* Masks and defines */
635 #define vVW510024_E_IS_BV 0x80 /* Bm bit in STATS block */
636 #define vVW510024_E_IS_CV 0x40 /* cV bit in STATS block */
637 #define vVW510024_E_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else force to 0) */
638 #define vVW510024_E_QOS_VALID 0x0000 /** not valid for ethernet **/
639 #define vVW510024_E_L4ID_VALID 0x1000
640 #define vVW510024_E_CBW_MASK 0xC0
641 #define vVW510024_E_VCID_MASK 0x3FFF /* VCID is only 14 bits */
643 #define vVW510024_E_IS_TCP 0x01000000 /* TCP bit in FRAME_TYPE field */
644 #define vVW510024_E_IS_UDP 0x00100000 /* UDP bit in FRAME_TYPE field */
645 #define vVW510024_E_IS_ICMP 0x00001000 /* ICMP bit in FRAME_TYPE field */
646 #define vVW510024_E_IS_IGMP 0x00010000
647 #define vVW510024_E_IS_VLAN 0x00004000
649 #define vVW510024_E_HEADER_VERSION 0x00
650 #define vVW510024_E_DEVICE_TYPE 0x18
651 #define vVW510024_E_FPGA_VERSION 0x0001
653 #define FPGA_VER_NOT_APPLICABLE 0
655 #define UNKNOWN_FPGA 0
656 #define S2_W_FPGA 1
657 #define S1_W_FPGA 2
658 #define vVW510012_E_FPGA 3
659 #define vVW510024_E_FPGA 4
660 #define S3_W_FPGA 5
662 /* the flow signature is:
663 Byte Description
664 0 Magic Number (0xDD)
665 1 Chassis Number[7:0]
666 2 Slot Number[7:0]
667 3 Port Number[7:0]
668 4 Flow ID[7:0]
669 5 Flow ID[15:8]
670 6 Flow ID[23:16]
671 7 Flow Sequence Number[7:0]
672 8 Timestamp[7:0]
673 9 Timestamp[15:8]
674 10 Timestamp[23:16]
675 11 Timestamp[31:24]
676 12 Timestamp[39:32]
677 13 Timestamp[47:40]
678 14 CRC16
679 15 CRC16
682 #define SIG_SIZE 16 /* size of signature field, bytes */
683 #define SIG_FID_OFF 4 /* offset of flow ID in signature */
684 #define SIG_FSQ_OFF 7 /* offset of flow seqnum in signature */
685 #define SIG_TS_OFF 8 /* offset of flow seqnum in signature */
689 /*--------------------------------------------------------------------------------------*/
690 /* Per-capture file private data structure */
692 typedef struct {
693 /* offsets in stats block; these are dependent on the frame type (Ethernet/WLAN) and */
694 /* version number of .vwr file, and are set up by setup_defaults() */
695 uint32_t STATS_LEN; /* length of stats block trailer */
696 uint32_t STATS_START_OFF; /* STATS OFF AFTER HEADER */
697 uint32_t VALID_OFF; /* bit 6 (0x40) is flow-is-valid flag */
698 uint32_t MTYPE_OFF; /* offset of modulation type */
699 uint32_t VCID_OFF; /* offset of VC ID */
700 uint32_t FLOWSEQ_OFF; /* offset of signature sequence number */
701 uint32_t FLOWID_OFF; /* offset of flow ID */
702 uint32_t OCTET_OFF; /* offset of octets */
703 uint32_t ERRORS_OFF; /* offset of error vector */
704 uint32_t PATN_OFF; /* offset of pattern match vector */
705 uint32_t RSSI_OFF; /* RSSI (NOTE: RSSI must be negated!) */
706 uint32_t STARTT_OFF; /* offset of start time, 64 bits */
707 uint32_t ENDT_OFF; /* offset of end time, 64 bits */
708 uint32_t LATVAL_OFF; /* offset of latency, 32 bits */
709 uint32_t INFO_OFF; /* offset of INFO field, 16 bits */
710 uint32_t L1P_1_OFF; /* offset 1ST Byte of l1params */
711 uint32_t L1P_2_OFF; /* offset 2nd Byte of l1params */
712 uint32_t L4ID_OFF; /* LAYER 4 id offset*/
713 uint32_t IPLEN_OFF; /* */
714 uint32_t PLCP_LENGTH_OFF; /* offset of length field in the PLCP header */
715 uint32_t FPGA_VERSION_OFF; /* offset of fpga version field, 16 bits */
716 uint32_t HEADER_VERSION_OFF; /* offset of header version, 16 bits */
717 uint32_t RXTX_OFF; /* offset of CMD bit, rx or tx */
718 uint32_t FRAME_TYPE_OFF;
720 /* other information about the file in question */
721 uint32_t MT_10_HALF; /* 10 Mb/s half-duplex */
722 uint32_t MT_10_FULL; /* 10 Mb/s full-duplex */
723 uint32_t MT_100_HALF; /* 100 Mb/s half-duplex */
724 uint32_t MT_100_FULL; /* 100 Mb/s full-duplex */
725 uint32_t MT_1G_HALF; /* 1 Gb/s half-duplex */
726 uint32_t MT_1G_FULL; /* 1 Gb/s full-duplex */
727 uint32_t FCS_ERROR; /* FCS error in frame */
728 uint32_t CRYPTO_ERR; /* RX decrypt error flags */
729 uint32_t PAYCHK_ERR; /* payload checksum failure */
730 uint32_t RETRY_ERR; /* excessive retries on TX failure */
731 uint8_t IS_RX; /* TX/RX bit in STATS block */
732 uint8_t MT_MASK; /* modulation type mask */
733 uint16_t VCID_MASK; /* VC ID might not be a full 16 bits */
734 uint32_t FLOW_VALID; /* flow-is-valid flag (else force to 0) */
735 uint16_t QOS_VALID;
736 uint32_t RX_DECRYPTS; /* RX-frame-was-decrypted bits */
737 uint32_t TX_DECRYPTS; /* TX-frame-was-decrypted bits */
738 uint32_t FC_PROT_BIT; /* Protected Frame bit in FC1 of frame */
739 uint32_t MT_CCKL; /* CCK modulation, long preamble */
740 uint32_t MT_CCKS; /* CCK modulation, short preamble */
741 uint32_t MT_OFDM; /* OFDM modulation */
742 uint32_t MCS_INDEX_MASK; /* mcs index type mask */
743 uint32_t FPGA_VERSION;
744 uint32_t WEPTYPE; /* frame is WEP */
745 uint32_t TKIPTYPE; /* frame is TKIP */
746 uint32_t CCMPTYPE; /* frame is CCMP */
747 uint32_t IS_TCP;
748 uint32_t IS_UDP;
749 uint32_t IS_ICMP;
750 uint32_t IS_IGMP;
751 uint16_t IS_QOS;
752 uint32_t IS_VLAN;
753 uint32_t MPDU_OFF;
754 uint32_t OCTO_VERSION;
755 } vwr_t;
758 * NSS for various MCS values.
760 #define MAX_HT_MCS 76
761 static unsigned nss_for_mcs[MAX_HT_MCS+1] = {
762 1, 1, 1, 1, 1, 1, 1, 1, /* 0-7 */
763 2, 2, 2, 2, 2, 2, 2, 2, /* 8-15 */
764 3, 3, 3, 3, 3, 3, 3, 3, /* 16-23 */
765 4, 4, 4, 4, 4, 4, 4, 4, /* 24-31 */
766 1, /* 32 */
767 2, 2, 2, 2, 2, 2, /* 33-38 */
768 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 39-52 */
769 4, 4, 4, 4, 4, 4, /* 53-58 */
770 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 /* 59-76 */
773 /* internal utility functions */
774 static int decode_msg(vwr_t *vwr, register uint8_t *, int *, int *, int *);
775 static uint8_t get_ofdm_rate(const uint8_t *);
776 static uint8_t get_cck_rate(const uint8_t *plcp);
777 static void setup_defaults(vwr_t *, uint16_t);
779 static bool vwr_read(wtap *, wtap_rec *, Buffer *, int *,
780 char **, int64_t *);
781 static bool vwr_seek_read(wtap *, int64_t, wtap_rec *,
782 Buffer *, int *, char **);
784 static bool vwr_read_rec_header(vwr_t *, FILE_T, int *, int *, int *, int *, char **);
785 static bool vwr_process_rec_data(FILE_T fh, int rec_size,
786 wtap_rec *record, Buffer *buf,
787 vwr_t *vwr, int IS_TX, int log_mode, int *err,
788 char **err_info);
790 static int vwr_get_fpga_version(wtap *, int *, char **);
792 static bool vwr_read_s1_W_rec(vwr_t *, wtap_rec *, Buffer *,
793 const uint8_t *, int, int *, char **);
794 static bool vwr_read_s2_W_rec(vwr_t *, wtap_rec *, Buffer *,
795 const uint8_t *, int, int, int *,
796 char **);
797 /* For FPGA version >= 48 (OCTO Platform), following function will be used */
798 static bool vwr_read_s3_W_rec(vwr_t *, wtap_rec *, Buffer *,
799 const uint8_t *, int, int, int, int *,
800 char **);
801 static bool vwr_read_rec_data_ethernet(vwr_t *, wtap_rec *,
802 Buffer *, const uint8_t *, int,
803 int, int *, char **);
805 static int find_signature(const uint8_t *, int, int, register uint32_t, register uint8_t);
806 static uint64_t get_signature_ts(const uint8_t *, int, int);
807 static float get_legacy_rate(uint8_t);
808 static float get_ht_rate(uint8_t, uint16_t);
809 static float get_vht_rate(uint8_t, uint16_t, uint8_t);
811 static int vwr_80211_file_type_subtype = -1;
812 static int vwr_eth_file_type_subtype = -1;
814 void register_vwr(void);
816 /* Open a .vwr file for reading */
817 /* This does very little, except setting the wiretap header for a VWR file type */
818 /* and setting the timestamp precision to microseconds. */
820 wtap_open_return_val vwr_open(wtap *wth, int *err, char **err_info)
822 int fpgaVer;
823 vwr_t *vwr;
825 *err = 0;
827 fpgaVer = vwr_get_fpga_version(wth, err, err_info);
828 if (fpgaVer == -1) {
829 return WTAP_OPEN_ERROR; /* I/O error */
831 if (fpgaVer == UNKNOWN_FPGA) {
832 return WTAP_OPEN_NOT_MINE; /* not a VWR file */
835 /* This is a vwr file */
836 vwr = g_new0(vwr_t, 1);
837 wth->priv = (void *)vwr;
839 vwr->FPGA_VERSION = fpgaVer;
840 /* set the local module options first */
841 setup_defaults(vwr, fpgaVer);
843 wth->snapshot_length = 0;
844 wth->subtype_read = vwr_read;
845 wth->subtype_seek_read = vwr_seek_read;
846 wth->file_tsprec = WTAP_TSPREC_USEC;
847 wth->file_encap = WTAP_ENCAP_IXVERIWAVE;
849 if (fpgaVer == S2_W_FPGA || fpgaVer == S1_W_FPGA || fpgaVer == S3_W_FPGA)
850 wth->file_type_subtype = vwr_80211_file_type_subtype;
851 else if (fpgaVer == vVW510012_E_FPGA || fpgaVer == vVW510024_E_FPGA)
852 wth->file_type_subtype = vwr_eth_file_type_subtype;
855 * Add an IDB; we don't know how many interfaces were
856 * involved, so we just say one interface, about which
857 * we only know the link-layer type, snapshot length,
858 * and time stamp resolution.
860 wtap_add_generated_idb(wth);
862 return WTAP_OPEN_MINE;
866 /* Read the next packet */
867 /* Note that the VWR file format consists of a sequence of fixed 16-byte record headers of */
868 /* different types; some types, including frame record headers, are followed by */
869 /* variable-length data. */
870 /* A frame record consists of: the above 16-byte record header, a 1-16384 byte raw PLCP */
871 /* frame, and a 64-byte statistics block trailer. */
872 /* The PLCP frame consists of a 4-byte or 6-byte PLCP header, followed by the MAC frame */
874 static bool vwr_read(wtap *wth, wtap_rec *rec, Buffer *buf,
875 int *err, char **err_info, int64_t *data_offset)
877 vwr_t *vwr = (vwr_t *)wth->priv;
878 int rec_size = 0, IS_TX = 0, log_mode = 0;
880 /* read the next frame record header in the capture file; if no more frames, return */
881 if (!vwr_read_rec_header(vwr, wth->fh, &rec_size, &IS_TX, &log_mode, err, err_info))
882 return false; /* Read error or EOF */
885 * We're past the header; return the offset of the header, not of
886 * the data past the header.
888 *data_offset = (file_tell(wth->fh) - VW_RECORD_HEADER_LENGTH);
890 /* got a frame record; read and process it */
891 if (!vwr_process_rec_data(wth->fh, rec_size, rec, buf, vwr, IS_TX,
892 log_mode, err, err_info))
893 return false;
895 return true;
898 /* read a random record in the middle of a file; the start of the record is @ seek_off */
900 static bool vwr_seek_read(wtap *wth, int64_t seek_off,
901 wtap_rec *record, Buffer *buf, int *err, char **err_info)
903 vwr_t *vwr = (vwr_t *)wth->priv;
904 int rec_size, IS_TX = 0, log_mode = 0;
906 /* first seek to the indicated record header */
907 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
908 return false;
910 /* read in the record header */
911 if (!vwr_read_rec_header(vwr, wth->random_fh, &rec_size, &IS_TX, &log_mode, err, err_info))
912 return false; /* Read error or EOF */
914 return vwr_process_rec_data(wth->random_fh, rec_size, record, buf,
915 vwr, IS_TX, log_mode, err, err_info);
918 /* Scan down in the input capture file to find the next frame header. */
919 /* Decode and skip over all non-frame messages that are in the way. */
920 /* Return true on success, false on EOF or error. */
921 /* Also return the frame size in bytes and the "is transmitted frame" flag. */
923 static bool vwr_read_rec_header(vwr_t *vwr, FILE_T fh, int *rec_size, int *IS_TX, int *log_mode, int *err, char **err_info)
925 int f_len, v_type;
926 uint8_t header[VW_RECORD_HEADER_LENGTH];
928 *rec_size = 0;
930 /* Read out the file data in 16-byte messages, stopping either after we find a frame, */
931 /* or if we run out of data. */
932 /* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
933 /* variable-length item, we read the variable length item out and discard it. */
934 /* If we find a frame, we return (with the header in the passed buffer). */
935 while (1) {
936 if (!wtap_read_bytes_or_eof(fh, header, VW_RECORD_HEADER_LENGTH, err, err_info))
937 return false;
939 /* Got a header; invoke decode-message function to parse and process it. */
940 /* If the function returns a length, then a frame or variable-length message */
941 /* follows the 16-byte message. */
942 /* If the variable length message is not a frame, simply skip over it. */
943 if ((f_len = decode_msg(vwr, header, &v_type, IS_TX, log_mode)) != 0) {
944 if (f_len > B_SIZE) {
945 *err = WTAP_ERR_BAD_FILE;
946 *err_info = ws_strdup_printf("vwr: Invalid message record length %d", f_len);
947 return false;
949 else if (v_type != VT_FRAME) {
950 if (!wtap_read_bytes(fh, NULL, f_len, err, err_info))
951 return false;
953 else {
954 *rec_size = f_len;
955 return true;
961 /* Figure out the FPGA version (and also see whether this is a VWR file type. */
962 /* Return FPGA version if it's a known version, UNKNOWN_FPGA if it's not, */
963 /* and -1 on an I/O error. */
965 static int vwr_get_fpga_version(wtap *wth, int *err, char **err_info)
967 uint8_t *rec; /* local buffer (holds input record) */
968 uint8_t header[VW_RECORD_HEADER_LENGTH];
969 int rec_size = 0;
970 uint8_t i;
971 uint8_t *s_510006_ptr = NULL;
972 uint8_t *s_510024_ptr = NULL;
973 uint8_t *s_510012_ptr = NULL; /* stats pointers */
974 int64_t filePos = -1;
975 uint64_t bytes_read = 0;
976 uint32_t frame_type = 0;
977 int f_len, v_type;
978 uint16_t data_length = 0;
979 uint16_t fpga_version;
980 bool valid_but_empty_file = false;
982 filePos = file_tell(wth->fh);
983 if (filePos == -1) {
984 *err = file_error(wth->fh, err_info);
985 return -1;
988 fpga_version = 1000;
989 rec = (uint8_t*)g_malloc(B_SIZE);
990 /* Got a frame record; see if it is vwr */
991 /* If we don't get it all, then declare an error, we can't process the frame. */
992 /* Read out the file data in 16-byte messages, stopping either after we find a frame, */
993 /* or if we run out of data. */
994 /* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
995 /* variable-length item, we read the variable length item out and discard it. */
996 /* If we find a frame, we return (with the header in the passed buffer). */
997 while (wtap_read_bytes(wth->fh, header, VW_RECORD_HEADER_LENGTH, err, err_info)) {
998 /* Got a header; invoke decode-message function to parse and process it. */
999 /* If the function returns a length, then a frame or variable-length message */
1000 /* follows the 16-byte message. */
1001 /* If the variable length message is not a frame, simply skip over it. */
1002 if ((f_len = decode_msg(NULL, header, &v_type, NULL, NULL)) != 0) {
1003 if (f_len > B_SIZE) {
1004 g_free(rec);
1005 /* Treat this here as an indication that the file probably */
1006 /* isn't a vwr file. */
1007 return UNKNOWN_FPGA;
1009 else if (v_type != VT_FRAME) {
1010 if (!wtap_read_bytes(wth->fh, NULL, f_len, err, err_info)) {
1011 g_free(rec);
1012 if (*err == WTAP_ERR_SHORT_READ)
1013 return UNKNOWN_FPGA; /* short read - not a vwr file */
1014 return -1;
1016 else if (v_type == VT_CPMSG)
1017 valid_but_empty_file = true;
1019 else {
1020 rec_size = f_len;
1021 /* Got a frame record; read over entire record (frame + trailer) into a local buffer */
1022 /* If we don't get it all, assume this isn't a vwr file */
1023 if (!wtap_read_bytes(wth->fh, rec, rec_size, err, err_info)) {
1024 g_free(rec);
1025 if (*err == WTAP_ERR_SHORT_READ)
1026 return UNKNOWN_FPGA; /* short read - not a vwr file */
1027 return -1;
1030 /* I'll grab the bytes where the Ethernet "octets" field should be and the bytes where */
1031 /* the 802.11 "octets" field should be. Then if I do rec_size - octets - */
1032 /* size_of_stats_block and it's 0, I can select the correct type. */
1033 /* octets + stats_len = rec_size only when octets have been incremented to nearest */
1034 /* number divisible by 4. */
1036 /* First check for series I WLAN since the check is more rigorous. */
1037 if (rec_size > v22_W_STATS_LEN) {
1038 s_510006_ptr = &(rec[rec_size - v22_W_STATS_LEN]); /* point to 510006 WLAN */
1039 /* stats block */
1041 data_length = pntoh16(&s_510006_ptr[v22_W_OCTET_OFF]);
1042 i = 0;
1043 while (((data_length + i) % 4) != 0)
1044 i = i + 1;
1046 frame_type = pntoh32(&s_510006_ptr[v22_W_FRAME_TYPE_OFF]);
1048 if (rec_size == (data_length + v22_W_STATS_LEN + i) && (frame_type & v22_W_IS_80211) == 0x1000000) {
1049 fpga_version = S1_W_FPGA;
1053 /* Next for the series I Ethernet */
1054 if ((rec_size > v22_E_STATS_LEN) && (fpga_version == 1000)) {
1055 s_510012_ptr = &(rec[rec_size - v22_E_STATS_LEN]); /* point to 510012 enet */
1056 /* stats block */
1057 data_length = pntoh16(&s_510012_ptr[v22_E_OCTET_OFF]);
1058 i = 0;
1059 while (((data_length + i) % 4) != 0)
1060 i = i + 1;
1062 if (rec_size == (data_length + v22_E_STATS_LEN + i))
1063 fpga_version = vVW510012_E_FPGA;
1067 /* Next the series II WLAN */
1068 if ((rec_size > vVW510021_W_STATS_TRAILER_LEN) && (fpga_version == 1000)) {
1069 /* stats block */
1071 if ((header[8] == 48) || (header[8] == 61) || (header[8] == 68))
1072 fpga_version = S3_W_FPGA;
1073 else {
1074 data_length = (256 * (rec[vVW510021_W_MSDU_LENGTH_OFF + 1] & 0x1f)) + rec[vVW510021_W_MSDU_LENGTH_OFF];
1076 i = 0;
1077 while (((data_length + i) % 4) != 0)
1078 i = i + 1;
1080 /*the 12 is from the 12 bytes of plcp header */
1081 if (rec_size == (data_length + vVW510021_W_STATS_TRAILER_LEN +vVW510021_W_AFTERHEADER_LEN+12+i))
1082 fpga_version = S2_W_FPGA;
1086 /* Finally the Series II Ethernet */
1087 if ((rec_size > vVW510024_E_STATS_LEN) && (fpga_version == 1000)) {
1088 s_510024_ptr = &(rec[rec_size - vVW510024_E_STATS_LEN]); /* point to 510024 ENET */
1089 data_length = pntoh16(&s_510024_ptr[vVW510024_E_MSDU_LENGTH_OFF]);
1091 i = 0;
1092 while (((data_length + i) % 4) != 0)
1093 i = i + 1;
1095 if (rec_size == (data_length + vVW510024_E_STATS_LEN + i))
1096 fpga_version = vVW510024_E_FPGA;
1099 if (fpga_version != 1000)
1101 /* reset the file position offset */
1102 if (file_seek (wth->fh, filePos, SEEK_SET, err) == -1) {
1103 g_free(rec);
1104 return (-1);
1107 /* We found an FPGA that works */
1108 g_free(rec);
1109 return fpga_version;
1113 bytes_read += VW_RECORD_HEADER_LENGTH;
1114 if (bytes_read > VW_BYTES_TO_CHECK) {
1115 /* no frame found in VW_BYTES_TO_CHECK - not a vwr file */
1116 g_free(rec);
1117 return UNKNOWN_FPGA;
1121 /* Is this a valid but empty file? If so, claim it's the S3_W_FPGA FPGA. */
1122 if (valid_but_empty_file) {
1123 g_free(rec);
1124 return(S3_W_FPGA);
1127 if (*err == WTAP_ERR_SHORT_READ) {
1128 g_free(rec);
1129 return UNKNOWN_FPGA; /* short read - not a vwr file */
1133 * Read error.
1135 g_free(rec);
1136 return -1;
1139 /* Copy the actual packet data from the capture file into the target data block. */
1140 /* The packet is constructed as a 38-byte VeriWave metadata header plus the raw */
1141 /* MAC octets. */
1143 static bool vwr_read_s1_W_rec(vwr_t *vwr, wtap_rec *record,
1144 Buffer *buf, const uint8_t *rec, int rec_size,
1145 int *err, char **err_info)
1147 uint8_t *data_ptr;
1148 int bytes_written = 0; /* bytes output to buf so far */
1149 const uint8_t *s_ptr, *m_ptr; /* stats pointer */
1150 uint16_t msdu_length, actual_octets; /* octets in frame */
1151 uint16_t plcp_hdr_len; /* PLCP header length */
1152 uint16_t rflags;
1153 uint8_t m_type; /* mod type (CCK-L/CCK-S/OFDM), seqnum */
1154 unsigned flow_seq;
1155 uint64_t s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
1156 /* times, nsec */
1157 uint32_t latency;
1158 uint64_t start_time, s_sec, s_usec = LL_ZERO; /* start time, sec + usec */
1159 uint64_t end_time; /* end time */
1160 uint32_t info; /* INFO/ERRORS fields in stats blk */
1161 int8_t rssi; /* RSSI, signed 8-bit number */
1162 int f_tx; /* flag: if set, is a TX frame */
1163 uint8_t rate_index; /* pre-HT only */
1164 uint16_t vc_id, ht_len=0; /* VC ID, total ip length */
1165 unsigned flow_id; /* flow ID */
1166 uint32_t d_time, errors; /* packet duration & errors */
1167 int sig_off, pay_off; /* MAC+SNAP header len, signature offset */
1168 uint64_t sig_ts; /* 32 LSBs of timestamp in signature */
1169 uint16_t phyRate;
1170 uint16_t vw_flags; /* VeriWave-specific packet flags */
1173 * The record data must be large enough to hold the statistics trailer.
1175 if (rec_size < v22_W_STATS_LEN) {
1176 *err_info = ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1177 rec_size, v22_W_STATS_LEN);
1178 *err = WTAP_ERR_BAD_FILE;
1179 return false;
1182 /* Calculate the start of the statistics block in the buffer */
1183 /* Also get a bunch of fields from the stats block */
1184 s_ptr = &(rec[rec_size - v22_W_STATS_LEN]); /* point to it */
1185 m_type = s_ptr[v22_W_MTYPE_OFF] & v22_E_MT_MASK;
1186 f_tx = !(s_ptr[v22_W_MTYPE_OFF] & v22_E_IS_RX);
1187 actual_octets = pntoh16(&s_ptr[v22_W_OCTET_OFF]);
1188 vc_id = pntoh16(&s_ptr[v22_W_VCID_OFF]) & v22_E_VCID_MASK;
1189 flow_seq = s_ptr[v22_W_FLOWSEQ_OFF];
1191 latency = (uint32_t)pcorey48tohll(&s_ptr[v22_W_LATVAL_OFF]);
1193 flow_id = pntoh16(&s_ptr[v22_W_FLOWID_OFF+1]); /* only 16 LSBs kept */
1194 errors = pntoh16(&s_ptr[v22_W_ERRORS_OFF]);
1196 info = pntoh16(&s_ptr[v22_W_INFO_OFF]);
1197 rssi = (s_ptr[v22_W_RSSI_OFF] & 0x80) ? (-1 * (s_ptr[v22_W_RSSI_OFF] & 0x7f)) : s_ptr[v22_W_RSSI_OFF];
1200 * Sanity check the octets field to determine if it's greater than
1201 * the packet data available in the record - i.e., the record size
1202 * minus the length of the statistics block.
1204 * Report an error if it is.
1206 if (actual_octets > rec_size - v22_W_STATS_LEN) {
1207 *err_info = ws_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
1208 actual_octets);
1209 *err = WTAP_ERR_BAD_FILE;
1210 return false;
1213 /* Decode OFDM or CCK PLCP header and determine rate and short preamble flag. */
1214 /* The SIGNAL byte is always the first byte of the PLCP header in the frame. */
1215 if (m_type == vwr->MT_OFDM)
1216 rate_index = get_ofdm_rate(rec);
1217 else if ((m_type == vwr->MT_CCKL) || (m_type == vwr->MT_CCKS))
1218 rate_index = get_cck_rate(rec);
1219 else
1220 rate_index = 1;
1221 rflags = (m_type == vwr->MT_CCKS) ? FLAGS_SHORTPRE : 0;
1222 /* Calculate the MPDU size/ptr stuff; MPDU starts at 4 or 6 depending on OFDM/CCK. */
1223 /* Note that the number of octets in the frame also varies depending on OFDM/CCK, */
1224 /* because the PLCP header is prepended to the actual MPDU. */
1225 plcp_hdr_len = (m_type == vwr->MT_OFDM) ? 4 : 6;
1226 if (actual_octets >= plcp_hdr_len)
1227 actual_octets -= plcp_hdr_len;
1228 else {
1229 *err_info = ws_strdup_printf("vwr: Invalid data length %u (too short to include %u-byte PLCP header)",
1230 actual_octets, plcp_hdr_len);
1231 *err = WTAP_ERR_BAD_FILE;
1232 return false;
1234 m_ptr = &rec[plcp_hdr_len];
1235 msdu_length = actual_octets;
1238 * The MSDU length includes the FCS.
1240 * The packet data does *not* include the FCS - it's just 4 bytes
1241 * of junk - so we have to remove it.
1243 * We'll be stripping off that junk, so make sure we have at least
1244 * 4 octets worth of packet data.
1246 * There seems to be a special case of a length of 0.
1248 if (actual_octets < 4) {
1249 if (actual_octets != 0) {
1250 *err_info = ws_strdup_printf("vwr: Invalid data length %u (too short to include %u-byte PLCP header and 4 bytes of FCS)",
1251 actual_octets, plcp_hdr_len);
1252 *err = WTAP_ERR_BAD_FILE;
1253 return false;
1255 } else {
1256 actual_octets -= 4;
1259 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1260 /* 64-bit times are "Corey-endian" */
1261 s_time = pcoreytohll(&s_ptr[v22_W_STARTT_OFF]);
1262 e_time = pcoreytohll(&s_ptr[v22_W_ENDT_OFF]);
1264 /* find the packet duration (difference between start and end times) */
1265 d_time = (uint32_t)((e_time - s_time) / NS_IN_US); /* find diff, converting to usec */
1267 /* also convert the packet start time to seconds and microseconds */
1268 start_time = s_time / NS_IN_US; /* convert to microseconds first */
1269 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
1270 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
1272 /* also convert the packet end time to seconds and microseconds */
1273 end_time = e_time / NS_IN_US; /* convert to microseconds first */
1275 /* extract the 32 LSBs of the signature timestamp field from the data block*/
1276 pay_off = 42; /* 24 (MAC) + 8 (SNAP) + IP */
1277 sig_off = find_signature(m_ptr, rec_size - 6, pay_off, flow_id, flow_seq);
1278 if (m_ptr[sig_off] == 0xdd)
1279 sig_ts = get_signature_ts(m_ptr, sig_off, rec_size - v22_W_STATS_LEN);
1280 else
1281 sig_ts = 0;
1284 * Fill up the per-packet header.
1286 * We include the length of the metadata headers in the packet lengths.
1288 * The maximum value of actual_octets is 8191, which, even after
1289 * adding the lengths of the metadata headers, is less than
1290 * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
1292 record->rec_header.packet_header.len = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + actual_octets;
1293 record->rec_header.packet_header.caplen = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + actual_octets;
1295 record->ts.secs = (time_t)s_sec;
1296 record->ts.nsecs = (int)(s_usec * 1000);
1297 record->rec_header.packet_header.pkt_encap = WTAP_ENCAP_IXVERIWAVE;
1299 record->rec_type = REC_TYPE_PACKET;
1300 record->block = wtap_block_create(WTAP_BLOCK_PACKET);
1301 record->presence_flags = WTAP_HAS_TS;
1303 ws_buffer_assure_space(buf, record->rec_header.packet_header.caplen);
1304 data_ptr = ws_buffer_start_ptr(buf);
1307 * Generate and copy out the common metadata headers,
1308 * set the port type to 0 (WLAN).
1310 * All values are copied out in little-endian byte order.
1312 /* 1st octet of record for port_type and command (command is 0, hence RX) */
1313 phtole8(&data_ptr[bytes_written], WLAN_PORT);
1314 bytes_written += 1;
1315 /* 2nd octet of record for fpga version (0, hence pre-OCTO) */
1316 phtole8(&data_ptr[bytes_written], 0);
1317 bytes_written += 1;
1319 phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN); /* it_len */
1320 bytes_written += 2;
1321 phtoles(&data_ptr[bytes_written], msdu_length);
1322 bytes_written += 2;
1323 phtolel(&data_ptr[bytes_written], flow_id);
1324 bytes_written += 4;
1325 phtoles(&data_ptr[bytes_written], vc_id);
1326 bytes_written += 2;
1327 phtoles(&data_ptr[bytes_written], flow_seq);
1328 bytes_written += 2;
1329 if (!f_tx && sig_ts != 0) {
1330 phtolel(&data_ptr[bytes_written], latency);
1331 } else {
1332 phtolel(&data_ptr[bytes_written], 0);
1334 bytes_written += 4;
1335 phtolel(&data_ptr[bytes_written], sig_ts); /* 32 LSBs of signature timestamp (nsec) */
1336 bytes_written += 4;
1337 phtolell(&data_ptr[bytes_written], start_time); /* record start & end times of frame */
1338 bytes_written += 8;
1339 phtolell(&data_ptr[bytes_written], end_time);
1340 bytes_written += 8;
1341 phtolel(&data_ptr[bytes_written], d_time);
1342 bytes_written += 4;
1345 * Generate and copy out the WLAN metadata headers.
1347 * All values are copied out in little-endian byte order.
1349 phtoles(&data_ptr[bytes_written], EXT_WLAN_FIELDS_LEN);
1350 bytes_written += 2;
1351 phtoles(&data_ptr[bytes_written], rflags);
1352 bytes_written += 2;
1353 if (m_type == vwr->MT_OFDM) {
1354 phtoles(&data_ptr[bytes_written], CHAN_OFDM);
1355 } else {
1356 phtoles(&data_ptr[bytes_written], CHAN_CCK);
1358 bytes_written += 2;
1359 phyRate = (uint16_t)(get_legacy_rate(rate_index) * 10);
1360 phtoles(&data_ptr[bytes_written], phyRate);
1361 bytes_written += 2;
1362 data_ptr[bytes_written] = vVW510021_W_PLCP_LEGACY; /* pre-HT */
1363 bytes_written += 1;
1364 data_ptr[bytes_written] = rate_index;
1365 bytes_written += 1;
1366 data_ptr[bytes_written] = 1; /* pre-VHT, so NSS = 1 */
1367 bytes_written += 1;
1368 data_ptr[bytes_written] = rssi;
1369 bytes_written += 1;
1370 /* antennae b, c, d signal power */
1371 data_ptr[bytes_written] = 100;
1372 bytes_written += 1;
1373 data_ptr[bytes_written] = 100;
1374 bytes_written += 1;
1375 data_ptr[bytes_written] = 100;
1376 bytes_written += 1;
1377 /* padding */
1378 data_ptr[bytes_written] = 0;
1379 bytes_written += 1;
1381 /* fill in the VeriWave flags field */
1382 vw_flags = 0;
1383 if (f_tx)
1384 vw_flags |= VW_FLAGS_TXF;
1385 if (errors & vwr->FCS_ERROR)
1386 vw_flags |= VW_FLAGS_FCSERR;
1387 if (!f_tx && (errors & vwr->CRYPTO_ERR))
1388 vw_flags |= VW_FLAGS_DCRERR;
1389 if (!f_tx && (errors & vwr->RETRY_ERR))
1390 vw_flags |= VW_FLAGS_RETRERR;
1391 if (info & vwr->WEPTYPE)
1392 vw_flags |= VW_FLAGS_IS_WEP;
1393 else if (info & vwr->TKIPTYPE)
1394 vw_flags |= VW_FLAGS_IS_TKIP;
1395 else if (info & vwr->CCMPTYPE)
1396 vw_flags |= VW_FLAGS_IS_CCMP;
1397 phtoles(&data_ptr[bytes_written], vw_flags);
1398 bytes_written += 2;
1400 phtoles(&data_ptr[bytes_written], ht_len);
1401 bytes_written += 2;
1402 phtoles(&data_ptr[bytes_written], info);
1403 bytes_written += 2;
1404 phtolel(&data_ptr[bytes_written], errors);
1405 bytes_written += 4;
1408 * Finally, copy the whole MAC frame to the packet buffer as-is.
1409 * This does not include the PLCP; the MPDU starts at 4 or 6
1410 * depending on OFDM/CCK.
1411 * This also does not include the last 4 bytes, as those don't
1412 * contain an FCS, they just contain junk.
1414 memcpy(&data_ptr[bytes_written], &rec[plcp_hdr_len], actual_octets);
1416 return true;
1420 static bool vwr_read_s2_W_rec(vwr_t *vwr, wtap_rec *record,
1421 Buffer *buf, const uint8_t *rec, int rec_size,
1422 int IS_TX, int *err, char **err_info)
1424 uint8_t *data_ptr;
1425 int bytes_written = 0; /* bytes output to buf so far */
1426 const uint8_t *s_start_ptr,*s_trail_ptr, *plcp_ptr, *m_ptr; /* stats & MPDU ptr */
1427 uint32_t msdu_length, actual_octets; /* octets in frame */
1428 uint8_t l1p_1, l1p_2, plcp_type, rate_mcs_index, nss; /* mod (CCK-L/CCK-S/OFDM) */
1429 unsigned flow_seq;
1430 uint64_t s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
1431 /* times, nsec */
1432 uint64_t latency = LL_ZERO;
1433 uint64_t start_time, s_sec, s_usec = LL_ZERO; /* start time, sec + usec */
1434 uint64_t end_time; /* end time */
1435 uint16_t info; /* INFO/ERRORS fields in stats blk */
1436 uint32_t errors;
1437 int8_t rssi[] = {0,0,0,0}; /* RSSI, signed 8-bit number */
1438 int f_tx; /* flag: if set, is a TX frame */
1439 uint16_t vc_id, ht_len=0; /* VC ID , total ip length*/
1440 uint32_t flow_id, d_time; /* flow ID, packet duration*/
1441 int sig_off, pay_off; /* MAC+SNAP header len, signature offset */
1442 uint64_t sig_ts, tsid; /* 32 LSBs of timestamp in signature */
1443 uint16_t chanflags = 0; /* channel flags for WLAN metadata header */
1444 uint16_t radioflags = 0; /* flags for WLAN metadata header */
1445 uint64_t delta_b; /* Used for calculating latency */
1446 float rate;
1447 uint16_t phyRate;
1448 uint16_t vw_flags; /* VeriWave-specific packet flags */
1451 * The record data must be large enough to hold the statistics header,
1452 * the PLCP, and the statistics trailer.
1454 if ((unsigned)rec_size < vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN) {
1455 *err_info = ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1456 rec_size,
1457 vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN);
1458 *err = WTAP_ERR_BAD_FILE;
1459 return false;
1462 /* Calculate the start of the statistics blocks in the buffer */
1463 /* Also get a bunch of fields from the stats blocks */
1464 s_start_ptr = &(rec[0]); /* point to stats header */
1465 s_trail_ptr = &(rec[rec_size - vVW510021_W_STATS_TRAILER_LEN]); /* point to stats trailer */
1467 l1p_1 = s_start_ptr[vVW510021_W_L1P_1_OFF];
1468 l1p_2 = s_start_ptr[vVW510021_W_L1P_2_OFF];
1469 plcp_type = vVW510021_W_S2_PLCP_TYPE(l1p_2);
1470 /* we do the range checks at the end before copying the values
1471 into the wtap header */
1472 msdu_length = ((s_start_ptr[vVW510021_W_MSDU_LENGTH_OFF+1] & 0x1f) << 8)
1473 + s_start_ptr[vVW510021_W_MSDU_LENGTH_OFF];
1475 vc_id = pntoh16(&s_start_ptr[vVW510021_W_VCID_OFF]);
1476 if (IS_TX)
1478 rssi[0] = (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x80) ?
1479 -1 * (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x7f) :
1480 s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x7f;
1482 else
1484 rssi[0] = (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF] & 0x80) ?
1485 (s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF]- 256) :
1486 s_start_ptr[vVW510021_W_RSSI_TXPOWER_OFF];
1488 rssi[1] = 100;
1489 rssi[2] = 100;
1490 rssi[3] = 100;
1492 plcp_ptr = &(rec[8]);
1494 actual_octets = msdu_length;
1497 * Sanity check the octets field to determine if it's greater than
1498 * the packet data available in the record - i.e., the record size
1499 * minus the sum of (length of statistics header + PLCP) and
1500 * (length of statistics trailer).
1502 * Report an error if it is.
1504 if (actual_octets > rec_size - (vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN)) {
1505 *err_info = ws_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
1506 actual_octets);
1507 *err = WTAP_ERR_BAD_FILE;
1508 return false;
1511 f_tx = IS_TX;
1512 flow_seq = s_trail_ptr[vVW510021_W_FLOWSEQ_OFF];
1514 latency = 0x00000000; /* clear latency */
1515 flow_id = pntoh24(&s_trail_ptr[vVW510021_W_FLOWID_OFF]); /* all 24 bits valid */
1516 /* For tx latency is duration, for rx latency is timestamp */
1517 /* Get 48-bit latency value */
1518 tsid = pcorey48tohll(&s_trail_ptr[vVW510021_W_LATVAL_OFF]);
1520 errors = pntoh32(&s_trail_ptr[vVW510021_W_ERRORS_OFF]);
1521 info = pntoh16(&s_trail_ptr[vVW510021_W_INFO_OFF]);
1522 if ((info & v22_W_AGGREGATE_FLAGS) != 0)
1523 /* this length includes the Start_Spacing + Delimiter + MPDU + Padding for each piece of the aggregate*/
1524 ht_len = pletoh16(&s_start_ptr[vwr->PLCP_LENGTH_OFF]);
1527 /* decode OFDM or CCK PLCP header and determine rate and short preamble flag */
1528 /* the SIGNAL byte is always the first byte of the PLCP header in the frame */
1529 switch (plcp_type)
1531 case vVW510021_W_PLCP_LEGACY:
1533 * From IEEE Std 802.11-2012:
1535 * According to section 17.2.2 "PPDU format", the PLCP header
1536 * for the High Rate DSSS PHY (11b) has a SIGNAL field that's
1537 * 8 bits, followed by a SERVICE field that's 8 bits, followed
1538 * by a LENGTH field that's 16 bits, followed by a CRC field
1539 * that's 16 bits. The PSDU follows it. Section 17.2.3 "PPDU
1540 * field definitions" describes those fields.
1542 * According to sections 18.3.2 "PLCP frame format" and 18.3.4
1543 * "SIGNAL field", the PLCP for the OFDM PHY (11a) has a SIGNAL
1544 * field that's 24 bits, followed by a service field that's
1545 * 16 bits, followed by the PSDU. Section 18.3.5.2 "SERVICE
1546 * field" describes the SERVICE field.
1548 * According to section 19.3.2 "PPDU format", the frames for the
1549 * Extended Rate PHY (11g) either extend the 11b format, using
1550 * additional bits in the SERVICE field, or extend the 11a
1551 * format.
1553 rate_mcs_index = vVW510021_W_S2_RATE_INDEX(l1p_1);
1554 if (rate_mcs_index < 4) {
1555 chanflags |= CHAN_CCK;
1557 else {
1558 chanflags |= CHAN_OFDM;
1560 rate = get_legacy_rate(rate_mcs_index);
1561 nss = 0;
1562 break;
1564 case vVW510021_W_PLCP_MIXED:
1566 * According to section 20.3.2 "PPDU format", the HT-mixed
1567 * PLCP header has a "Non-HT SIGNAL field" (L-SIG), which
1568 * looks like an 11a SIGNAL field, followed by an HT SIGNAL
1569 * field (HT-SIG) described in section 20.3.9.4.3 "HT-SIG
1570 * definition".
1572 * This means that the first octet of HT-SIG is at
1573 * plcp_ptr[3], skipping the 3 octets of the L-SIG field.
1575 * 0x80 is the CBW 20/40 bit of HT-SIG.
1577 /* set the appropriate flags to indicate HT mode and CB */
1578 rate_mcs_index = vVW510021_W_S2_MCS_INDEX_HT(l1p_1);
1579 radioflags |= FLAGS_CHAN_HT | ((plcp_ptr[3] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
1580 ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
1581 chanflags |= CHAN_OFDM;
1582 nss = (rate_mcs_index < MAX_HT_MCS) ? nss_for_mcs[rate_mcs_index] : 0;
1583 rate = get_ht_rate(rate_mcs_index, radioflags);
1584 break;
1586 case vVW510021_W_PLCP_GREENFIELD:
1588 * According to section 20.3.2 "PPDU format", the HT-greenfield
1589 * PLCP header just has the HT SIGNAL field (HT-SIG) above, with
1590 * no L-SIG field.
1592 * This means that the first octet of HT-SIG is at
1593 * plcp_ptr[0], as there's no L-SIG field to skip.
1595 * 0x80 is the CBW 20/40 bit of HT-SIG.
1597 /* set the appropriate flags to indicate HT mode and CB */
1598 rate_mcs_index = vVW510021_W_S2_MCS_INDEX_HT(l1p_1);
1599 radioflags |= FLAGS_CHAN_HT | ((plcp_ptr[0] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
1600 ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
1601 chanflags |= CHAN_OFDM;
1602 nss = (rate_mcs_index < MAX_HT_MCS) ? nss_for_mcs[rate_mcs_index] : 0;
1603 rate = get_ht_rate(rate_mcs_index, radioflags);
1604 break;
1606 case vVW510021_W_PLCP_VHT_MIXED:
1608 * According to section 22.3.2 "VHT PPDU format" of IEEE Std
1609 * 802.11ac-2013, the VHT PLCP header has a "non-HT SIGNAL field"
1610 * (L-SIG), which looks like an 11a SIGNAL field, followed by
1611 * a VHT Signal A field (VHT-SIG-A) described in section
1612 * 22.3.8.3.3 "VHT-SIG-A definition", with training fields
1613 * between it and a VHT Signal B field (VHT-SIG-B) described
1614 * in section 22.3.8.3.6 "VHT-SIG-B definition", followed by
1615 * the PSDU.
1618 uint8_t SBW = vVW510021_W_BANDWIDTH_VHT(l1p_2);
1619 rate_mcs_index = vVW510021_W_S2_MCS_INDEX_VHT(l1p_1);
1620 radioflags |= FLAGS_CHAN_VHT | ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
1621 chanflags |= CHAN_OFDM;
1622 if (SBW == 3)
1623 radioflags |= FLAGS_CHAN_40MHZ;
1624 else if (SBW == 4)
1625 radioflags |= FLAGS_CHAN_80MHZ;
1626 nss = vVW510021_W_S2_NSS_VHT(l1p_1);
1627 rate = get_vht_rate(rate_mcs_index, radioflags, nss);
1629 break;
1631 default:
1632 rate_mcs_index = 0;
1633 nss = 0;
1634 rate = 0.0f;
1635 break;
1639 * The MSDU length includes the FCS.
1641 * The packet data does *not* include the FCS - it's just 4 bytes
1642 * of junk - so we have to remove it.
1644 * We'll be stripping off that junk, so make sure we have at least
1645 * 4 octets worth of packet data.
1647 * There seems to be a special case of a length of 0.
1649 if (actual_octets < 4) {
1650 if (actual_octets != 0) {
1651 *err_info = ws_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
1652 actual_octets);
1653 *err = WTAP_ERR_BAD_FILE;
1654 return false;
1656 } else {
1657 actual_octets -= 4;
1660 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1661 /* 64-bit times are "Corey-endian" */
1662 s_time = pcoreytohll(&s_trail_ptr[vVW510021_W_STARTT_OFF]);
1663 e_time = pcoreytohll(&s_trail_ptr[vVW510021_W_ENDT_OFF]);
1665 /* find the packet duration (difference between start and end times) */
1666 d_time = (uint32_t)((e_time - s_time) / NS_IN_US); /* find diff, converting to usec */
1668 /* also convert the packet start time to seconds and microseconds */
1669 start_time = s_time / NS_IN_US; /* convert to microseconds first */
1670 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
1671 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
1673 /* also convert the packet end time to seconds and microseconds */
1674 end_time = e_time / NS_IN_US; /* convert to microseconds first */
1676 /* extract the 32 LSBs of the signature timestamp field */
1677 m_ptr = &(rec[8+12]);
1678 pay_off = 42; /* 24 (MAC) + 8 (SNAP) + IP */
1679 sig_off = find_signature(m_ptr, rec_size - 20, pay_off, flow_id, flow_seq);
1680 if (m_ptr[sig_off] == 0xdd)
1681 sig_ts = get_signature_ts(m_ptr, sig_off, rec_size - vVW510021_W_STATS_TRAILER_LEN);
1682 else
1683 sig_ts = 0;
1685 /* Set latency based on rx/tx and signature timestamp */
1686 if (!IS_TX) {
1687 if (tsid < s_time) {
1688 latency = s_time - tsid;
1689 } else {
1690 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
1691 /* we look for a large difference between l_time and s_time. */
1692 delta_b = tsid - s_time;
1693 if (delta_b > 0x10000000)
1694 latency = 0;
1695 else
1696 latency = delta_b;
1701 * Fill up the per-packet header.
1703 * We include the length of the metadata headers in the packet lengths.
1705 * The maximum value of actual_octets is 8191, which, even after
1706 * adding the lengths of the metadata headers, is less than
1707 * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
1709 record->rec_header.packet_header.len = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + actual_octets;
1710 record->rec_header.packet_header.caplen = STATS_COMMON_FIELDS_LEN + EXT_WLAN_FIELDS_LEN + actual_octets;
1712 record->ts.secs = (time_t)s_sec;
1713 record->ts.nsecs = (int)(s_usec * 1000);
1715 record->rec_type = REC_TYPE_PACKET;
1716 record->block = wtap_block_create(WTAP_BLOCK_PACKET);
1717 record->presence_flags = WTAP_HAS_TS;
1719 ws_buffer_assure_space(buf, record->rec_header.packet_header.caplen);
1720 data_ptr = ws_buffer_start_ptr(buf);
1723 * Generate and copy out the common metadata headers,
1724 * set the port type to 0 (WLAN).
1726 * All values are copied out in little-endian byte order.
1728 /*** msdu_length = msdu_length + 16; ***/
1729 /* 1st octet of record for port_type and command (command is 0, hence RX) */
1730 phtole8(&data_ptr[bytes_written], WLAN_PORT);
1731 bytes_written += 1;
1732 /* 2nd octet of record for fpga version (0, hence pre-OCTO) */
1733 phtole8(&data_ptr[bytes_written], 0);
1734 bytes_written += 1;
1736 phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN); /* it_len */
1737 bytes_written += 2;
1738 phtoles(&data_ptr[bytes_written], msdu_length);
1739 bytes_written += 2;
1740 phtolel(&data_ptr[bytes_written], flow_id);
1741 bytes_written += 4;
1742 phtoles(&data_ptr[bytes_written], vc_id);
1743 bytes_written += 2;
1744 phtoles(&data_ptr[bytes_written], flow_seq);
1745 bytes_written += 2;
1746 if (!f_tx && sig_ts != 0) {
1747 phtolel(&data_ptr[bytes_written], latency);
1748 } else {
1749 phtolel(&data_ptr[bytes_written], 0);
1751 bytes_written += 4;
1752 phtolel(&data_ptr[bytes_written], sig_ts); /* 32 LSBs of signature timestamp (nsec) */
1753 bytes_written += 4;
1754 phtolell(&data_ptr[bytes_written], start_time); /* record start & end times of frame */
1755 bytes_written += 8;
1756 phtolell(&data_ptr[bytes_written], end_time);
1757 bytes_written += 8;
1758 phtolel(&data_ptr[bytes_written], d_time);
1759 bytes_written += 4;
1762 * Generate and copy out the WLAN metadata headers.
1764 * All values are copied out in little-endian byte order.
1766 phtoles(&data_ptr[bytes_written], EXT_WLAN_FIELDS_LEN);
1767 bytes_written += 2;
1768 if (info & vVW510021_W_IS_WEP)
1769 radioflags |= FLAGS_WEP;
1770 if (!(l1p_1 & vVW510021_W_IS_LONGPREAMBLE) && (plcp_type == vVW510021_W_PLCP_LEGACY))
1771 radioflags |= FLAGS_SHORTPRE;
1772 phtoles(&data_ptr[bytes_written], radioflags);
1773 bytes_written += 2;
1774 phtoles(&data_ptr[bytes_written], chanflags);
1775 bytes_written += 2;
1776 phyRate = (uint16_t)(rate * 10);
1777 phtoles(&data_ptr[bytes_written], phyRate);
1778 bytes_written += 2;
1780 data_ptr[bytes_written] = plcp_type;
1781 bytes_written += 1;
1783 data_ptr[bytes_written] = rate_mcs_index;
1784 bytes_written += 1;
1786 data_ptr[bytes_written] = nss;
1787 bytes_written += 1;
1788 data_ptr[bytes_written] = rssi[0];
1789 bytes_written += 1;
1790 data_ptr[bytes_written] = rssi[1];
1791 bytes_written += 1;
1792 data_ptr[bytes_written] = rssi[2];
1793 bytes_written += 1;
1794 data_ptr[bytes_written] = rssi[3];
1795 bytes_written += 1;
1796 /* padding */
1797 data_ptr[bytes_written] = 0;
1798 bytes_written += 1;
1800 /* fill in the VeriWave flags field */
1801 vw_flags = 0;
1802 if (f_tx)
1803 vw_flags |= VW_FLAGS_TXF;
1804 if (errors & 0x1f) /* If any error is flagged, then set the FCS error bit */
1805 vw_flags |= VW_FLAGS_FCSERR;
1806 if (!f_tx && (errors & vwr->CRYPTO_ERR))
1807 vw_flags |= VW_FLAGS_DCRERR;
1808 if (!f_tx && (errors & vwr->RETRY_ERR))
1809 vw_flags |= VW_FLAGS_RETRERR;
1810 if (info & vwr->WEPTYPE)
1811 vw_flags |= VW_FLAGS_IS_WEP;
1812 else if (info & vwr->TKIPTYPE)
1813 vw_flags |= VW_FLAGS_IS_TKIP;
1814 else if (info & vwr->CCMPTYPE)
1815 vw_flags |= VW_FLAGS_IS_CCMP;
1816 phtoles(&data_ptr[bytes_written], vw_flags);
1817 bytes_written += 2;
1819 phtoles(&data_ptr[bytes_written], ht_len);
1820 bytes_written += 2;
1821 phtoles(&data_ptr[bytes_written], info);
1822 bytes_written += 2;
1823 phtolel(&data_ptr[bytes_written], errors);
1824 bytes_written += 4;
1826 /* Finally, copy the whole MAC frame to the packet buffer as-is.
1827 * This does not include the stats header or the PLCP.
1828 * This also does not include the last 4 bytes, as those don't
1829 * contain an FCS, they just contain junk.
1831 memcpy(&data_ptr[bytes_written], &rec[vwr->MPDU_OFF], actual_octets);
1833 return true;
1836 static bool vwr_read_s3_W_rec(vwr_t *vwr, wtap_rec *record,
1837 Buffer *buf, const uint8_t *rec, int rec_size,
1838 int IS_TX, int log_mode, int *err,
1839 char **err_info)
1841 uint8_t *data_ptr;
1842 int bytes_written = 0; /* bytes output to buf so far */
1843 int i;
1844 int stats_offset = 0;
1845 const uint8_t *s_start_ptr = NULL,*s_trail_ptr = NULL, *plcp_ptr, *m_ptr; /* stats & MPDU ptr */
1846 uint32_t msdu_length = 0, actual_octets = 0; /* octets in frame */
1847 uint8_t l1p_1 = 0,l1p_2 = 0, plcp_type, rate_mcs_index, nss; /* mod (CCK-L/CCK-S/OFDM) */
1848 uint64_t s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
1849 /* times, nsec */
1850 uint64_t latency = LL_ZERO;
1851 uint64_t start_time = 0, s_sec = 0, s_usec = LL_ZERO; /* start time, sec + usec */
1852 uint64_t end_time = 0; /* end time */
1853 uint16_t info = 0; /* INFO/ERRORS fields in stats blk */
1854 uint32_t errors = 0;
1855 int8_t info_2nd = 0,rssi[] = {0,0,0,0}; /* RSSI, signed 8-bit number */
1856 int frame_size;
1857 uint32_t d_time = 0, flow_id = 0; /* packet duration, Flow Signature ID*/
1858 int sig_off, pay_off; /* MAC+SNAP header len, signature offset */
1859 uint64_t sig_ts = 0, tsid; /* 32 LSBs of timestamp in signature */
1860 uint64_t delta_b; /* Used for calculating latency */
1861 uint8_t L1InfoC = 0, port_type, ver_fpga = 0;
1862 uint8_t flow_seq =0,plcp_hdr_flag = 0,rf_id = 0; /* indicates plcp hdr info */
1863 const uint8_t *rf_ptr = NULL;
1864 float rate;
1865 uint16_t phyRate;
1868 * The record data must be large enough to hold the statistics header,
1869 * the PLCP, and the statistics trailer.
1871 if (IS_TX == 3) { /*IS_TX =3, i.e., command type is RF Modified*/
1872 if ((unsigned)rec_size < OCTO_MODIFIED_RF_LEN) {
1873 *err_info = ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1874 rec_size,
1875 OCTO_MODIFIED_RF_LEN);
1876 *err = WTAP_ERR_BAD_FILE;
1877 return false;
1879 rf_ptr = &(rec[0]);
1880 rf_id = rf_ptr[0];
1883 * Fill up the per-packet header.
1885 * We include the length of the metadata headers in the packet lengths.
1887 * OCTO_MODIFIED_RF_LEN + 1 is less than WTAP_MAX_PACKET_SIZE_STANDARD will
1888 * ever be, so we don't need to check it.
1890 record->rec_header.packet_header.len = OCTO_MODIFIED_RF_LEN + 1; /* 1st octet is reserved for detecting type of frame while displaying in wireshark */
1891 record->rec_header.packet_header.caplen = OCTO_MODIFIED_RF_LEN + 1;
1893 record->ts.secs = (time_t)s_sec;
1894 record->ts.nsecs = (int)(s_usec * 1000);
1896 record->rec_type = REC_TYPE_PACKET;
1897 record->block = wtap_block_create(WTAP_BLOCK_PACKET);
1898 record->presence_flags = WTAP_HAS_TS;
1900 ws_buffer_assure_space(buf, record->rec_header.packet_header.caplen);
1901 data_ptr = ws_buffer_start_ptr(buf);
1903 port_type = IS_TX << 4;
1905 nss = 0;
1906 phyRate = 0;
1908 else {
1909 /* Calculate the start of the statistics blocks in the buffer */
1910 /* Also get a bunch of fields from the stats blocks */
1911 /* 'stats_offset' variable is use to locate the exact offset.
1912 * When a RX frame contrains RF,
1913 * the position of Stats, Layer 1-4, PLCP parameters are shifted to
1914 * + OCTO_RF_MOD_ACTUAL_LEN bytes
1916 if (IS_TX == 4) /*IS_TX =4, i.e., command type is RF-RX Modified*/
1918 stats_offset = OCTO_RF_MOD_ACTUAL_LEN;
1919 if ((unsigned)rec_size < stats_offset + vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN) {
1920 *err_info = ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1921 rec_size,
1922 stats_offset + vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN);
1923 *err = WTAP_ERR_BAD_FILE;
1924 return false;
1926 rf_ptr = &(rec[0]);
1927 rf_id = rf_ptr[0];
1929 else
1931 stats_offset = 0;
1932 if ((unsigned)rec_size < vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN) {
1933 *err_info = ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)",
1934 rec_size,
1935 vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN);
1936 *err = WTAP_ERR_BAD_FILE;
1937 return false;
1941 s_start_ptr = &(rec[stats_offset]); /* point to stats header */
1942 s_trail_ptr = &(rec[rec_size - vVW510021_W_STATS_TRAILER_LEN] ); /* point to stats trailer */
1944 l1p_1 = s_start_ptr[vVW510021_W_L1P_1_OFF];
1945 l1p_2 = s_start_ptr[vVW510021_W_L1P_2_OFF];
1947 plcp_type = vVW510021_W_S3_PLCP_TYPE(l1p_2);
1948 switch (plcp_type)
1950 case vVW510021_W_PLCP_LEGACY:
1951 /* pre-HT */
1952 rate_mcs_index = vVW510021_W_S3_RATE_INDEX(l1p_1);
1953 nss = 0;
1954 break;
1956 case vVW510021_W_PLCP_MIXED:
1957 case vVW510021_W_PLCP_GREENFIELD:
1958 rate_mcs_index = vVW510021_W_S3_MCS_INDEX_HT(l1p_1);
1959 nss = (rate_mcs_index < MAX_HT_MCS) ? nss_for_mcs[rate_mcs_index] : 0;
1960 break;
1962 case vVW510021_W_PLCP_VHT_MIXED:
1963 rate_mcs_index = vVW510021_W_S3_MCS_INDEX_VHT(l1p_1);
1964 nss = vVW510021_W_S3_NSS_VHT(l1p_1);
1965 plcp_hdr_flag = 1;
1966 break;
1968 default:
1969 rate_mcs_index = 0;
1970 nss = 0;
1971 plcp_hdr_flag = 0;
1972 break;
1975 for (i = 0; i < 4; i++)
1977 if (IS_TX == 1)
1979 rssi[i] = (s_start_ptr[4+i] & 0x80) ? -1 * (s_start_ptr[4+i] & 0x7f) : s_start_ptr[4+i] & 0x7f;
1981 else
1983 rssi[i] = (s_start_ptr[4+i] >= 128) ? (s_start_ptr[4+i] - 256) : s_start_ptr[4+i];
1987 if (IS_TX == 0 || IS_TX == 4){
1988 L1InfoC = s_start_ptr[8];
1991 msdu_length = pntoh24(&s_start_ptr[9]);
1993 /*** 16 bytes of PLCP header + 1 byte of L1P for user position ***/
1994 plcp_ptr = &(rec[stats_offset+16]);
1996 /*** Add the PLCP length for S3_W_FPGA version VHT frames for Beamforming decode ***/
1997 if (log_mode == 3) {
1998 frame_size = rec_size - (stats_offset + vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN);
1999 if (frame_size > ((int) msdu_length))
2000 actual_octets = msdu_length;
2001 else {
2003 * XXX - does this mean "the packet was cut short during
2004 * capture" or "this is a malformed record"?
2006 actual_octets = frame_size;
2009 else
2011 actual_octets = msdu_length;
2014 * Sanity check the octets field to determine if it's greater than
2015 * the packet data available in the record - i.e., the record size
2016 * minus the sum of (length of statistics header + PLCP) and
2017 * (length of statistics trailer).
2019 * Report an error if it is.
2021 if (actual_octets > rec_size - (stats_offset + vwr->MPDU_OFF + vVW510021_W_STATS_TRAILER_LEN)) {
2022 *err_info = ws_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
2023 actual_octets);
2024 *err = WTAP_ERR_BAD_FILE;
2025 return false;
2028 flow_seq = s_trail_ptr[vVW510021_W_FLOWSEQ_OFF];
2030 latency = 0x00000000; /* clear latency */
2031 flow_id = pntoh24(&s_trail_ptr[vVW510021_W_FLOWID_OFF]); /* all 24 bits valid */
2032 /* For tx latency is duration, for rx latency is timestamp */
2033 /* Get 48-bit latency value */
2034 tsid = pcorey48tohll(&s_trail_ptr[vVW510021_W_LATVAL_OFF]);
2036 errors = pntoh32(&s_trail_ptr[vVW510021_W_ERRORS_OFF]);
2037 info = pntoh16(&s_trail_ptr[vVW510021_W_INFO_OFF]);
2039 if (IS_TX == 0 || IS_TX == 4)
2040 info_2nd = s_trail_ptr[41];
2042 /*** Calculate Data rate based on
2043 * PLCP type, MCS index and number of spatial stream
2044 * radioflags is temporarily calculated, which is used in
2045 * get_ht_rate() and get_vht_rate().
2047 switch (plcp_type)
2049 case vVW510021_W_PLCP_LEGACY:
2050 rate = get_legacy_rate(rate_mcs_index);
2051 break;
2053 case vVW510021_W_PLCP_MIXED:
2055 * According to section 20.3.2 "PPDU format", the HT-mixed
2056 * PLCP header has a "Non-HT SIGNAL field" (L-SIG), which
2057 * looks like an 11a SIGNAL field, followed by an HT SIGNAL
2058 * field (HT-SIG) described in section 20.3.9.4.3 "HT-SIG
2059 * definition".
2061 * This means that the first octet of HT-SIG is at
2062 * plcp_ptr[3], skipping the 3 octets of the L-SIG field.
2064 * 0x80 is the CBW 20/40 bit of HT-SIG.
2067 /* set the appropriate flags to indicate HT mode and CB */
2068 uint16_t radioflags = FLAGS_CHAN_HT | ((plcp_ptr[3] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
2069 ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
2070 rate = get_ht_rate(rate_mcs_index, radioflags);
2072 break;
2074 case vVW510021_W_PLCP_GREENFIELD:
2076 * According to section 20.3.2 "PPDU format", the HT-greenfield
2077 * PLCP header just has the HT SIGNAL field (HT-SIG) above, with
2078 * no L-SIG field.
2080 * This means that the first octet of HT-SIG is at
2081 * plcp_ptr[0], as there's no L-SIG field to skip.
2083 * 0x80 is the CBW 20/40 bit of HT-SIG.
2086 /* set the appropriate flags to indicate HT mode and CB */
2087 uint16_t radioflags = FLAGS_CHAN_HT | ((plcp_ptr[0] & 0x80) ? FLAGS_CHAN_40MHZ : 0) |
2088 ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
2089 rate = get_ht_rate(rate_mcs_index, radioflags);
2091 break;
2093 case vVW510021_W_PLCP_VHT_MIXED:
2095 * According to section 22.3.2 "VHT PPDU format" of IEEE Std
2096 * 802.11ac-2013, the VHT PLCP header has a "non-HT SIGNAL field"
2097 * (L-SIG), which looks like an 11a SIGNAL field, followed by
2098 * a VHT Signal A field (VHT-SIG-A) described in section
2099 * 22.3.8.3.3 "VHT-SIG-A definition", with training fields
2100 * between it and a VHT Signal B field (VHT-SIG-B) described
2101 * in section 22.3.8.3.6 "VHT-SIG-B definition", followed by
2102 * the PSDU.
2105 uint8_t SBW = vVW510021_W_BANDWIDTH_VHT(l1p_2);
2106 uint16_t radioflags = FLAGS_CHAN_VHT | ((l1p_1 & vVW510021_W_IS_LONGGI) ? 0 : FLAGS_CHAN_SHORTGI);
2107 if (SBW == 3)
2108 radioflags |= FLAGS_CHAN_40MHZ;
2109 else if (SBW == 4)
2110 radioflags |= FLAGS_CHAN_80MHZ;
2111 rate = get_vht_rate(rate_mcs_index, radioflags, nss);
2113 break;
2115 default:
2116 rate = 0.0f;
2117 break;
2119 phyRate = (uint16_t)(rate * 10);
2120 /* Calculation of Data rate ends*/
2122 /* 'ver_fpga' is the 2nd Octet of each frame.
2123 * msb/lsb nibble indicates log mode/fpga version respectively.
2124 * where log mode = 0 is normal capture and 1 is reduced capture,
2125 * lsb nibble is set to 1 always as this function is applicable for only FPGA version >= 48
2127 if (log_mode == 3) {
2128 if (frame_size >= (int) msdu_length) {
2130 * The MSDU length includes the FCS.
2132 * The packet data does *not* include the FCS - it's just 4
2133 * bytes of junk - so we have to remove it.
2135 * We'll be stripping off that junk, so make sure we have at
2136 * least 4 octets worth of packet data.
2138 * XXX - is the FCS actually present here, as it appears to be
2139 * if log_mode isn't 3?
2141 * There seems to be a special case of a length of 0.
2143 if (actual_octets < 4) {
2144 if (actual_octets != 0) {
2145 *err_info = ws_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
2146 actual_octets);
2147 *err = WTAP_ERR_BAD_FILE;
2148 return false;
2150 } else {
2151 actual_octets -= 4;
2154 ver_fpga = 0x11;
2155 } else {
2156 ver_fpga = 0x01;
2159 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
2160 /* 64-bit times are "Corey-endian" */
2161 s_time = pcoreytohll(&s_trail_ptr[vVW510021_W_STARTT_OFF]);
2162 e_time = pcoreytohll(&s_trail_ptr[vVW510021_W_ENDT_OFF]);
2164 /* find the packet duration (difference between start and end times) */
2165 d_time = (uint32_t)((e_time - s_time) / NS_IN_US); /* find diff, converting to usec */
2167 /* also convert the packet start time to seconds and microseconds */
2168 start_time = s_time / NS_IN_US; /* convert to microseconds first */
2169 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
2170 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
2172 /* also convert the packet end time to seconds and microseconds */
2173 end_time = e_time / NS_IN_US; /* convert to microseconds first */
2175 /* extract the 32 LSBs of the signature timestamp field */
2176 int m_ptr_offset = stats_offset + 8 + 12;
2177 m_ptr = rec + m_ptr_offset;
2178 pay_off = 42; /* 24 (MAC) + 8 (SNAP) + IP */
2179 sig_off = find_signature(m_ptr, rec_size - m_ptr_offset, pay_off, flow_id, flow_seq);
2180 if (m_ptr[sig_off] == 0xdd)
2181 sig_ts = get_signature_ts(m_ptr, sig_off, rec_size - vVW510021_W_STATS_TRAILER_LEN);
2182 else
2183 sig_ts = 0;
2185 /* Set latency based on rx/tx and signature timestamp */
2186 if (IS_TX == 0 || IS_TX == 4) {
2187 if (tsid < s_time) {
2188 latency = s_time - tsid;
2189 } else {
2190 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
2191 /* we look for a large difference between l_time and s_time. */
2192 delta_b = tsid - s_time;
2193 if (delta_b > 0x10000000)
2194 latency = 0;
2195 else
2196 latency = delta_b;
2200 port_type = IS_TX << 4;
2203 * Fill up the per-packet header.
2205 * We include the length of the metadata headers in the packet lengths.
2207 if (IS_TX == 4) {
2208 record->rec_header.packet_header.len = OCTO_MODIFIED_RF_LEN + OCTO_TIMESTAMP_FIELDS_LEN + OCTO_LAYER1TO4_LEN + actual_octets;
2209 record->rec_header.packet_header.caplen = OCTO_MODIFIED_RF_LEN + OCTO_TIMESTAMP_FIELDS_LEN + OCTO_LAYER1TO4_LEN + actual_octets;
2210 } else {
2211 record->rec_header.packet_header.len = OCTO_TIMESTAMP_FIELDS_LEN + OCTO_LAYER1TO4_LEN + actual_octets;
2212 record->rec_header.packet_header.caplen = OCTO_TIMESTAMP_FIELDS_LEN + OCTO_LAYER1TO4_LEN + actual_octets;
2214 if (record->rec_header.packet_header.caplen > WTAP_MAX_PACKET_SIZE_STANDARD) {
2216 * Probably a corrupt capture file; return an error,
2217 * so that our caller doesn't blow up trying to allocate
2218 * space for an immensely-large packet.
2220 *err_info = ws_strdup_printf("vwr: File has %u-byte packet, bigger than maximum of %u",
2221 record->rec_header.packet_header.caplen, WTAP_MAX_PACKET_SIZE_STANDARD);
2222 *err = WTAP_ERR_BAD_FILE;
2223 return false;
2226 record->ts.secs = (time_t)s_sec;
2227 record->ts.nsecs = (int)(s_usec * 1000);
2229 record->rec_type = REC_TYPE_PACKET;
2230 record->block = wtap_block_create(WTAP_BLOCK_PACKET);
2231 record->presence_flags = WTAP_HAS_TS;
2233 ws_buffer_assure_space(buf, record->rec_header.packet_header.caplen);
2234 data_ptr = ws_buffer_start_ptr(buf);
2238 * Generate and copy out the common metadata headers,
2239 * set the port type to port_type (XXX).
2241 * All values are copied out in little-endian byte order.
2243 /*** msdu_length = msdu_length + 16; ***/
2245 /* 1st octet of record for port_type and other crud */
2246 phtole8(&data_ptr[bytes_written], port_type);
2247 bytes_written += 1;
2249 if (IS_TX != 3) {
2250 phtole8(&data_ptr[bytes_written], ver_fpga); /* 2nd octet of record for FPGA version*/
2251 bytes_written += 1;
2253 phtoles(&data_ptr[bytes_written], OCTO_TIMESTAMP_FIELDS_LEN); /* it_len */
2254 bytes_written += 2;
2256 /*** Time Collapsible header started***/
2257 if (IS_TX == 1 && sig_ts != 0) {
2258 phtolel(&data_ptr[bytes_written], latency);
2259 } else {
2260 phtolel(&data_ptr[bytes_written], 0);
2262 bytes_written += 4;
2263 phtolel(&data_ptr[bytes_written], sig_ts); /* 32 LSBs of signature timestamp (nsec) */
2264 bytes_written += 4;
2265 phtolell(&data_ptr[bytes_written], start_time); /* record start & end times of frame */
2266 bytes_written += 8;
2267 phtolell(&data_ptr[bytes_written], end_time);
2268 bytes_written += 8;
2269 phtolel(&data_ptr[bytes_written], d_time);
2270 bytes_written += 4;
2271 /*** Time Collapsible header ends ***/
2274 /*** RF Collapsible header starts***/
2275 if (IS_TX == 3 || IS_TX == 4) {
2276 phtole8(&data_ptr[bytes_written], rf_id);
2277 bytes_written += 1;
2278 data_ptr[bytes_written] = 0;
2279 bytes_written += 1;
2280 data_ptr[bytes_written] = 0;
2281 bytes_written += 1;
2282 data_ptr[bytes_written] = 0;
2283 bytes_written += 1;
2285 /*** NOISE for all 4 Ports ***/
2286 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2288 if (pntoh16(&rf_ptr[RF_PORT_1_NOISE_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2289 phtoles(&data_ptr[bytes_written], 0);
2290 bytes_written += 2;
2291 } else {
2292 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_NOISE_OFF+i*RF_INTER_PORT_GAP_OFF];
2293 bytes_written += 1;
2294 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_NOISE_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2295 bytes_written += 1;
2299 /*** SNR for all 4 Ports ***/
2300 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2302 if (pntoh16(&rf_ptr[RF_PORT_1_SNR_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2303 phtoles(&data_ptr[bytes_written], 0);
2304 bytes_written += 2;
2305 } else {
2306 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_SNR_OFF+i*RF_INTER_PORT_GAP_OFF];
2307 bytes_written += 1;
2308 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_SNR_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2309 bytes_written += 1;
2313 /*** PFE for all 4 Ports ***/
2314 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2316 if (pntoh16(&rf_ptr[RF_PORT_1_PFE_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2317 phtoles(&data_ptr[bytes_written], 0);
2318 bytes_written += 2;
2319 } else {
2320 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_PFE_OFF+i*RF_INTER_PORT_GAP_OFF];
2321 bytes_written += 1;
2322 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_PFE_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2323 bytes_written += 1;
2327 /*** EVM SIG Data for all 4 Ports ***/
2328 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2330 if (pntoh16(&rf_ptr[RF_PORT_1_EVM_SD_SIG_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2331 phtoles(&data_ptr[bytes_written], 0);
2332 bytes_written += 2;
2333 } else {
2334 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SD_SIG_OFF+i*RF_INTER_PORT_GAP_OFF];
2335 bytes_written += 1;
2336 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SD_SIG_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2337 bytes_written += 1;
2341 /*** EVM SIG PILOT for all 4 Ports ***/
2342 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2344 if (pntoh16(&rf_ptr[RF_PORT_1_EVM_SP_SIG_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2345 phtoles(&data_ptr[bytes_written], 0);
2346 bytes_written += 2;
2347 } else {
2348 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SP_SIG_OFF+i*RF_INTER_PORT_GAP_OFF];
2349 bytes_written += 1;
2350 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SP_SIG_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2351 bytes_written += 1;
2355 /*** EVM Data Data for all 4 Ports ***/
2356 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2358 if (pntoh16(&rf_ptr[RF_PORT_1_EVM_SD_DATA_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2359 phtoles(&data_ptr[bytes_written], 0);
2360 bytes_written += 2;
2361 } else {
2362 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SD_DATA_OFF+i*RF_INTER_PORT_GAP_OFF];
2363 bytes_written += 1;
2364 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SD_DATA_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2365 bytes_written += 1;
2369 /*** EVM Data PILOT for all 4 Ports ***/
2370 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2372 if (pntoh16(&rf_ptr[RF_PORT_1_EVM_SP_DATA_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2373 phtoles(&data_ptr[bytes_written], 0);
2374 bytes_written += 2;
2375 } else {
2376 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SP_DATA_OFF+i*RF_INTER_PORT_GAP_OFF];
2377 bytes_written += 1;
2378 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_EVM_SP_DATA_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2379 bytes_written += 1;
2383 /*** EVM WORST SYMBOL for all 4 Ports ***/
2384 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2386 if (pntoh16(&rf_ptr[RF_PORT_1_DSYMBOL_IDX_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2387 phtoles(&data_ptr[bytes_written], 0);
2388 bytes_written += 2;
2389 } else {
2390 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_DSYMBOL_IDX_OFF+i*RF_INTER_PORT_GAP_OFF];
2391 bytes_written += 1;
2392 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_DSYMBOL_IDX_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2393 bytes_written += 1;
2397 /*** CONTEXT_P for all 4 Ports ***/
2398 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2400 if (pntoh16(&rf_ptr[RF_PORT_1_CONTEXT_OFF+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2401 phtoles(&data_ptr[bytes_written], 0);
2402 bytes_written += 2;
2403 } else {
2404 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_CONTEXT_OFF+i*RF_INTER_PORT_GAP_OFF];
2405 bytes_written += 1;
2406 data_ptr[bytes_written] = rf_ptr[RF_PORT_1_CONTEXT_OFF+1+i*RF_INTER_PORT_GAP_OFF];
2407 bytes_written += 1;
2411 /*** FOR rest 24 RF data bytes are commented for future use ***/
2412 /***
2413 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2415 if (pntoh16(&rf_ptr[20+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2416 phtoles(&data_ptr[bytes_written], 0);
2417 bytes_written += 2;
2418 } else {
2419 data_ptr[bytes_written] = rf_ptr[20+i*RF_INTER_PORT_GAP_OFF];
2420 bytes_written += 1;
2421 data_ptr[bytes_written] = rf_ptr[21+i*RF_INTER_PORT_GAP_OFF];
2422 bytes_written += 1;
2425 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2427 if (pntoh16(&rf_ptr[24+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2428 phtoles(&data_ptr[bytes_written], 0);
2429 bytes_written += 2;
2430 } else {
2431 data_ptr[bytes_written] = rf_ptr[24+i*RF_INTER_PORT_GAP_OFF];
2432 bytes_written += 1;
2433 data_ptr[bytes_written] = rf_ptr[25+i*RF_INTER_PORT_GAP_OFF];
2434 bytes_written += 1;
2437 for (i = 0; i < RF_NUMBER_OF_PORTS; i++)
2439 if (pntoh16(&rf_ptr[26+i*RF_INTER_PORT_GAP_OFF]) == 0) {
2440 phtoles(&data_ptr[bytes_written], 0);
2441 bytes_written += 2;
2442 } else {
2443 data_ptr[bytes_written] = rf_ptr[26+i*RF_INTER_PORT_GAP_OFF];
2444 bytes_written += 1;
2445 data_ptr[bytes_written] = rf_ptr[27+i*RF_INTER_PORT_GAP_OFF];
2446 bytes_written += 1;
2449 ***/
2451 /*** RF Collapsible header ends***/
2453 if (IS_TX != 3) {
2455 * Generate and copy out the WLAN metadata headers.
2457 * All values are copied out in little-endian byte order.
2459 phtoles(&data_ptr[bytes_written], OCTO_LAYER1TO4_LEN);
2460 bytes_written += 2;
2462 /*** Layer-1 Collapsible header started***/
2463 data_ptr[bytes_written] = l1p_1;
2464 bytes_written += 1;
2466 data_ptr[bytes_written] = (nss << 4) | IS_TX;
2467 bytes_written += 1;
2469 phtoles(&data_ptr[bytes_written], phyRate); /* To dosplay Data rate based on the PLCP type & MCS*/
2470 bytes_written += 2;
2472 data_ptr[bytes_written] = l1p_2;
2473 bytes_written += 1;
2475 data_ptr[bytes_written] = rssi[0];
2476 bytes_written += 1;
2477 data_ptr[bytes_written] = rssi[1];
2478 bytes_written += 1;
2479 data_ptr[bytes_written] = rssi[2];
2480 bytes_written += 1;
2481 data_ptr[bytes_written] = rssi[3];
2482 bytes_written += 1;
2484 /* padding may not be required for S3_W*/
2486 data_ptr[bytes_written] = s_start_ptr[2]; /*** For Signal Bandwidth Mask ***/
2487 bytes_written += 1;
2488 data_ptr[bytes_written] = s_start_ptr[3]; /*** For Antenna Port Energy Detect and MU_MASK ***/
2489 bytes_written += 1;
2491 if (plcp_hdr_flag == 1 && (IS_TX == 0 || IS_TX == 4)) {
2492 data_ptr[bytes_written] = L1InfoC; /*** For Other plcp type = VHT ***/
2493 } else {
2494 data_ptr[bytes_written] = 0; /*** For Other plcp type, this offset is set to 0***/
2496 bytes_written += 1;
2498 phtoles(&data_ptr[bytes_written], msdu_length);
2499 bytes_written += 2;
2500 /*** Layer-1 Collapsible header Ends ***/
2502 /*** PLCP Collapsible header Starts ***/
2503 memcpy(&data_ptr[bytes_written], &rec[stats_offset+16], 16);
2504 bytes_written += 16;
2505 /*** PLCP Collapsible header Ends ***/
2507 /*** Layer 2-4 Collapsible header Starts ***/
2509 phtolel(&data_ptr[bytes_written], pntoh32(&s_start_ptr[12])); /*** This 4 bytes includes BM,BV,CV,BSSID and ClientID ***/
2510 bytes_written += 4;
2511 phtoles(&data_ptr[bytes_written], pntoh16(&s_trail_ptr[20])); /*** 2 bytes includes FV,QT,HT,L4V,TID and WLAN type ***/
2512 bytes_written += 2;
2513 data_ptr[bytes_written] = flow_seq;
2514 bytes_written += 1;
2515 phtole24(&data_ptr[bytes_written], flow_id);
2516 bytes_written += 3;
2517 phtoles(&data_ptr[bytes_written], pntoh16(&s_trail_ptr[28])); /*** 2 bytes for Layer 4 ID ***/
2518 bytes_written += 2;
2519 phtolel(&data_ptr[bytes_written], pntoh32(&s_trail_ptr[24])); /*** 4 bytes for Payload Decode ***/
2520 bytes_written += 4;
2522 /*** In case of RX, Info has 3 bytes of data, whereas for TX, 2 bytes ***/
2523 if (IS_TX == 0 || IS_TX == 4) {
2524 phtoles(&data_ptr[bytes_written], info);
2525 bytes_written += 2;
2526 data_ptr[bytes_written] = info_2nd;
2527 bytes_written += 1;
2529 else {
2530 phtoles(&data_ptr[bytes_written], info);
2531 bytes_written += 2;
2532 data_ptr[bytes_written] = 0;
2533 bytes_written += 1;
2536 phtolel(&data_ptr[bytes_written], errors);
2537 bytes_written += 4;
2538 /*** Layer 2-4 Collapsible header Ends ***/
2540 /* Finally, copy the whole MAC frame to the packet buffer as-is.
2541 * This does not include the stats header or the PLCP.
2542 * This also does not include the last 4 bytes, as those don't
2543 * contain an FCS, they just contain junk.
2545 memcpy(&data_ptr[bytes_written], &rec[stats_offset+(vwr->MPDU_OFF)], actual_octets);
2548 return true;
2551 /* read an Ethernet packet */
2552 /* Copy the actual packet data from the capture file into the target data block. */
2553 /* The packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
2554 /* MAC octets. */
2555 static bool vwr_read_rec_data_ethernet(vwr_t *vwr, wtap_rec *record,
2556 Buffer *buf, const uint8_t *rec,
2557 int rec_size, int IS_TX, int *err,
2558 char **err_info)
2560 uint8_t *data_ptr;
2561 int bytes_written = 0; /* bytes output to buf so far */
2562 const uint8_t *s_ptr, *m_ptr; /* stats and MPDU pointers */
2563 uint16_t msdu_length, actual_octets; /* octets in frame */
2564 unsigned flow_seq; /* seqnum */
2565 uint64_t s_time = LL_ZERO, e_time = LL_ZERO; /* start/end */
2566 /* times, nsec */
2567 uint32_t latency = 0;
2568 uint64_t start_time, s_sec = LL_ZERO, s_usec = LL_ZERO; /* start time, sec + usec */
2569 uint64_t end_time; /* end time */
2570 unsigned l4id;
2571 uint16_t info, validityBits; /* INFO/ERRORS fields in stats */
2572 uint32_t errors;
2573 uint16_t vc_id; /* VC ID, total (incl of aggregates) */
2574 uint32_t flow_id, d_time; /* packet duration */
2575 int f_flow; /* flags: flow valid */
2576 uint32_t frame_type; /* frame type field */
2577 int mac_len, sig_off, pay_off; /* MAC header len, signature offset */
2578 /* XXX - the code here fetched tsid, but never used it! */
2579 uint64_t sig_ts/*, tsid*/; /* 32 LSBs of timestamp in signature */
2580 uint64_t delta_b; /* Used for calculating latency */
2581 uint16_t vw_flags; /* VeriWave-specific packet flags */
2583 if ((unsigned)rec_size < vwr->STATS_LEN) {
2584 *err_info = ws_strdup_printf("vwr: Invalid record length %d (must be at least %u)", rec_size, vwr->STATS_LEN);
2585 *err = WTAP_ERR_BAD_FILE;
2586 return false;
2589 /* Calculate the start of the statistics block in the buffer. */
2590 /* Also get a bunch of fields from the stats block. */
2591 m_ptr = &(rec[0]); /* point to the data block */
2592 s_ptr = &(rec[rec_size - vwr->STATS_LEN]); /* point to the stats block */
2594 msdu_length = pntoh16(&s_ptr[vwr->OCTET_OFF]);
2595 actual_octets = msdu_length;
2598 * Sanity check the octets field to determine if it's greater than
2599 * the packet data available in the record - i.e., the record size
2600 * minus the length of the statistics block.
2602 * Report an error if it is.
2604 if (actual_octets > rec_size - vwr->STATS_LEN) {
2605 *err_info = ws_strdup_printf("vwr: Invalid data length %u (runs past the end of the record)",
2606 actual_octets);
2607 *err = WTAP_ERR_BAD_FILE;
2608 return false;
2611 vc_id = pntoh16(&s_ptr[vwr->VCID_OFF]) & vwr->VCID_MASK;
2612 flow_seq = s_ptr[vwr->FLOWSEQ_OFF];
2613 frame_type = pntoh32(&s_ptr[vwr->FRAME_TYPE_OFF]);
2615 if (vwr->FPGA_VERSION == vVW510024_E_FPGA) {
2616 validityBits = pntoh16(&s_ptr[vwr->VALID_OFF]);
2617 f_flow = validityBits & vwr->FLOW_VALID;
2619 mac_len = (validityBits & vwr->IS_VLAN) ? 16 : 14; /* MAC hdr length based on VLAN tag */
2622 errors = pntoh16(&s_ptr[vwr->ERRORS_OFF]);
2624 else {
2625 f_flow = s_ptr[vwr->VALID_OFF] & vwr->FLOW_VALID;
2626 mac_len = (frame_type & vwr->IS_VLAN) ? 16 : 14; /* MAC hdr length based on VLAN tag */
2628 /* for older fpga errors is only represented by 16 bits) */
2629 errors = pntoh16(&s_ptr[vwr->ERRORS_OFF]);
2632 info = pntoh16(&s_ptr[vwr->INFO_OFF]);
2633 /* 24 LSBs */
2634 flow_id = pntoh24(&s_ptr[vwr->FLOWID_OFF]);
2636 #if 0
2637 /* For tx latency is duration, for rx latency is timestamp. */
2638 /* Get 64-bit latency value. */
2639 tsid = pcorey48tohll(&s_ptr[vwr->LATVAL_OFF]);
2640 #endif
2642 l4id = pntoh16(&s_ptr[vwr->L4ID_OFF]);
2645 * The MSDU length includes the FCS.
2647 * The packet data does *not* include the FCS - it's just 4 bytes
2648 * of junk - so we have to remove it.
2650 * We'll be stripping off that junk, so make sure we have at least
2651 * 4 octets worth of packet data.
2653 * There seems to be a special case of a length of 0.
2655 if (actual_octets < 4) {
2656 if (actual_octets != 0) {
2657 *err_info = ws_strdup_printf("vwr: Invalid data length %u (too short to include 4 bytes of FCS)",
2658 actual_octets);
2659 *err = WTAP_ERR_BAD_FILE;
2660 return false;
2662 } else {
2663 actual_octets -= 4;
2666 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
2667 /* 64-bit times are "Corey-endian" */
2668 s_time = pcoreytohll(&s_ptr[vwr->STARTT_OFF]);
2669 e_time = pcoreytohll(&s_ptr[vwr->ENDT_OFF]);
2671 /* find the packet duration (difference between start and end times) */
2672 d_time = (uint32_t)((e_time - s_time)); /* find diff, leaving in nsec for Ethernet */
2674 /* also convert the packet start time to seconds and microseconds */
2675 start_time = s_time / NS_IN_US; /* convert to microseconds first */
2676 s_sec = (start_time / US_IN_SEC); /* get the number of seconds */
2677 s_usec = start_time - (s_sec * US_IN_SEC); /* get the number of microseconds */
2679 /* also convert the packet end time to seconds and microseconds */
2680 end_time = e_time / NS_IN_US; /* convert to microseconds first */
2682 if (frame_type & vwr->IS_TCP) /* signature offset for TCP frame */
2684 pay_off = mac_len + 40;
2686 else if (frame_type & vwr->IS_UDP) /* signature offset for UDP frame */
2688 pay_off = mac_len + 28;
2690 else if (frame_type & vwr->IS_ICMP) /* signature offset for ICMP frame */
2692 pay_off = mac_len + 24;
2694 else if (frame_type & vwr->IS_IGMP) /* signature offset for IGMPv2 frame */
2696 pay_off = mac_len + 28;
2698 else /* signature offset for raw IP frame */
2700 pay_off = mac_len + 20;
2703 sig_off = find_signature(m_ptr, rec_size, pay_off, flow_id, flow_seq);
2704 if ((m_ptr[sig_off] == 0xdd) && (f_flow != 0))
2705 sig_ts = get_signature_ts(m_ptr, sig_off, msdu_length);
2706 else
2707 sig_ts = 0;
2709 /* Set latency based on rx/tx and signature timestamp */
2710 if (!IS_TX) {
2711 if (sig_ts < s_time) {
2712 latency = (uint32_t)(s_time - sig_ts);
2713 } else {
2714 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
2715 /* we look for a large difference between l_time and s_time. */
2716 delta_b = sig_ts - s_time;
2717 if (delta_b > 0x10000000) {
2718 latency = 0;
2719 } else
2720 latency = (uint32_t)delta_b;
2725 * Fill up the per-packet header.
2727 * We include the length of the metadata headers in the packet lengths.
2729 * The maximum value of actual_octets is 65535, which, even after
2730 * adding the lengths of the metadata headers, is less than
2731 * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
2733 record->rec_header.packet_header.len = STATS_COMMON_FIELDS_LEN + EXT_ETHERNET_FIELDS_LEN + actual_octets;
2734 record->rec_header.packet_header.caplen = STATS_COMMON_FIELDS_LEN + EXT_ETHERNET_FIELDS_LEN + actual_octets;
2736 record->ts.secs = (time_t)s_sec;
2737 record->ts.nsecs = (int)(s_usec * 1000);
2739 record->rec_type = REC_TYPE_PACKET;
2740 record->block = wtap_block_create(WTAP_BLOCK_PACKET);
2741 record->presence_flags = WTAP_HAS_TS;
2743 /*etap_hdr.vw_ip_length = (uint16_t)ip_len;*/
2745 ws_buffer_assure_space(buf, record->rec_header.packet_header.caplen);
2746 data_ptr = ws_buffer_start_ptr(buf);
2749 * Generate and copy out the common metadata headers,
2750 * set the port type to 1 (Ethernet).
2752 * All values are copied out in little-endian byte order.
2754 /* 1st octet of record for port_type and command (command is 0, hence RX) */
2755 phtole8(&data_ptr[bytes_written], ETHERNET_PORT);
2756 bytes_written += 1;
2757 /* 2nd octet of record for fpga version (Ethernet, hence non-OCTO) */
2758 phtole8(&data_ptr[bytes_written], 0);
2759 bytes_written += 1;
2761 phtoles(&data_ptr[bytes_written], STATS_COMMON_FIELDS_LEN);
2762 bytes_written += 2;
2763 phtoles(&data_ptr[bytes_written], msdu_length);
2764 bytes_written += 2;
2765 phtolel(&data_ptr[bytes_written], flow_id);
2766 bytes_written += 4;
2767 phtoles(&data_ptr[bytes_written], vc_id);
2768 bytes_written += 2;
2769 phtoles(&data_ptr[bytes_written], flow_seq);
2770 bytes_written += 2;
2771 if (!IS_TX && (sig_ts != 0)) {
2772 phtolel(&data_ptr[bytes_written], latency);
2773 } else {
2774 phtolel(&data_ptr[bytes_written], 0);
2776 bytes_written += 4;
2777 phtolel(&data_ptr[bytes_written], sig_ts);
2778 bytes_written += 4;
2779 phtolell(&data_ptr[bytes_written], start_time) /* record start & end times of frame */
2780 bytes_written += 8;
2781 phtolell(&data_ptr[bytes_written], end_time);
2782 bytes_written += 8;
2783 phtolel(&data_ptr[bytes_written], d_time);
2784 bytes_written += 4;
2787 * Generate and copy out the Ethernet metadata headers.
2789 * All values are copied out in little-endian byte order.
2791 phtoles(&data_ptr[bytes_written], EXT_ETHERNET_FIELDS_LEN);
2792 bytes_written += 2;
2793 vw_flags = 0;
2794 if (IS_TX)
2795 vw_flags |= VW_FLAGS_TXF;
2796 if (errors & vwr->FCS_ERROR)
2797 vw_flags |= VW_FLAGS_FCSERR;
2798 phtoles(&data_ptr[bytes_written], vw_flags);
2799 bytes_written += 2;
2800 phtoles(&data_ptr[bytes_written], info);
2801 bytes_written += 2;
2802 phtolel(&data_ptr[bytes_written], errors);
2803 bytes_written += 4;
2804 phtolel(&data_ptr[bytes_written], l4id);
2805 bytes_written += 4;
2807 /* Add in pad */
2808 phtolel(&data_ptr[bytes_written], 0);
2809 bytes_written += 4;
2812 * Finally, copy the whole MAC frame to the packet buffer as-is.
2813 * This also does not include the last 4 bytes, as those don't
2814 * contain an FCS, they just contain junk.
2816 memcpy(&data_ptr[bytes_written], m_ptr, actual_octets);
2818 return true;
2821 /*--------------------------------------------------------------------------------------*/
2822 /* utility to split up and decode a 16-byte message record */
2824 static int decode_msg(vwr_t *vwr, uint8_t *rec, int *v_type, int *IS_TX, int *log_mode)
2826 uint8_t cmd,fpga_log_mode; /* components of message */
2827 uint32_t wd2, wd3;
2828 int v_size; /* size of var-len message */
2830 /* break up the message record into its pieces */
2831 cmd = rec[0];
2832 fpga_log_mode = rec[1];
2833 fpga_log_mode = ((fpga_log_mode & 0x30) >> 4);
2835 wd2 = pntoh32(&rec[8]);
2836 wd3 = pntoh32(&rec[12]);
2838 if (vwr != NULL)
2839 *log_mode = fpga_log_mode; /* Log mode = 3, when MPDU data is reduced */
2841 /* now decode based on the command byte */
2842 switch (cmd) {
2843 case COMMAND_RX:
2844 if (vwr != NULL) {
2845 *IS_TX = 0;
2847 v_size = (int)(wd2 & 0xffff);
2848 *v_type = VT_FRAME;
2849 break;
2851 case COMMAND_TX:
2852 if (vwr != NULL) {
2853 *IS_TX = 1;
2855 v_size = (int)(wd2 & 0xffff);
2856 *v_type = VT_FRAME;
2857 break;
2860 case COMMAND_RFN:
2861 if (vwr != NULL) {
2862 *IS_TX = 3;
2864 v_size = (int)(wd2 & 0xffff);
2865 *v_type = VT_FRAME;
2866 break;
2869 case COMMAND_RF: /* For RF Modified only */
2870 if (vwr != NULL) {
2871 *IS_TX = 3;
2873 v_size = (int)(wd2 & 0xffff);
2874 *v_type = VT_FRAME;
2875 break;
2877 case COMMAND_RFRX: /* For RF_RX Modified only */
2878 if (vwr != NULL) {
2879 *IS_TX = 4;
2881 v_size = (int)(wd2 & 0xffff);
2882 *v_type = VT_FRAME;
2883 break;
2885 case 0xc1:
2886 case 0x8b:
2887 case 0xbb:
2888 if (vwr != NULL) {
2889 *IS_TX = 2;
2891 v_size = (int)(wd2 & 0xffff);
2892 *v_type = VT_CPMSG;
2893 break;
2895 case 0xfe:
2896 if (vwr != NULL) {
2897 *IS_TX = 2;
2899 v_size = (int)(wd3 & 0xffff);
2900 *v_type = VT_CPMSG;
2901 break;
2903 default:
2904 if (vwr != NULL) {
2905 *IS_TX = 2;
2907 v_size = 0;
2908 *v_type = VT_UNKNOWN;
2909 break;
2912 return v_size;
2916 /*---------------------------------------------------------------------------------------*/
2917 /* Utilities to extract and decode the PHY bit rate from 802.11 PLCP headers (OFDM/CCK). */
2918 /* They are passed a pointer to 4 or 6 consecutive bytes of PLCP header. */
2919 /* The integer returned by the get_xxx_rate() functions is in units of 0.5 Mb/s. */
2920 /* The string returned by the decode_xxx_rate() functions is 3 characters wide. */
2922 static uint8_t get_ofdm_rate(const uint8_t *plcp)
2924 /* extract the RATE field (LS nibble of first byte) then convert it to the MCS index used by the L1p fields */
2925 switch (plcp[0] & 0x0f) {
2926 case 0x0b: return 4;
2927 case 0x0f: return 5;
2928 case 0x0a: return 6;
2929 case 0x0e: return 7;
2930 case 0x09: return 8;
2931 case 0x0d: return 9;
2932 case 0x08: return 10;
2933 case 0x0c: return 11;
2934 default: return 0;
2938 static uint8_t get_cck_rate(const uint8_t *plcp)
2940 /* extract rate from the SIGNAL field then convert it to the MCS index used by the L1p fields */
2941 switch (plcp[0]) {
2942 case 0x0a: return 0;
2943 case 0x14: return 1;
2944 case 0x37: return 2;
2945 case 0x6e: return 3;
2946 default: return 0;
2950 /*--------------------------------------------------------------------------------------*/
2951 /* utility to set up offsets and bitmasks for decoding the stats blocks */
2953 static void setup_defaults(vwr_t *vwr, uint16_t fpga)
2955 switch (fpga) {
2956 /* WLAN frames */
2957 case S2_W_FPGA:
2958 vwr->STATS_LEN = vVW510021_W_STATS_TRAILER_LEN;
2960 vwr->VALID_OFF = vVW510021_W_VALID_OFF;
2961 vwr->MTYPE_OFF = vVW510021_W_MTYPE_OFF;
2962 vwr->VCID_OFF = vVW510021_W_VCID_OFF;
2963 vwr->FLOWSEQ_OFF = vVW510021_W_FLOWSEQ_OFF;
2964 vwr->FLOWID_OFF = vVW510021_W_FLOWID_OFF;
2966 /*vwr->OCTET_OFF = v22_W_OCTET_OFF;*/
2968 vwr->ERRORS_OFF = vVW510021_W_ERRORS_OFF;
2969 vwr->PATN_OFF = vVW510021_W_MATCH_OFF;
2970 vwr->RSSI_OFF = vVW510021_W_RSSI_TXPOWER_OFF;
2971 vwr->STARTT_OFF = vVW510021_W_STARTT_OFF;
2972 vwr->ENDT_OFF = vVW510021_W_ENDT_OFF;
2973 vwr->LATVAL_OFF = vVW510021_W_LATVAL_OFF;
2974 vwr->INFO_OFF = vVW510021_W_INFO_OFF;
2975 vwr->FPGA_VERSION_OFF = S2_W_FPGA_VERSION_OFF;
2976 vwr->HEADER_VERSION_OFF = vVW510021_W_HEADER_VERSION_OFF;
2977 vwr->OCTET_OFF = vVW510021_W_MSDU_LENGTH_OFF;
2978 vwr->L1P_1_OFF = vVW510021_W_L1P_1_OFF;
2979 vwr->L1P_2_OFF = vVW510021_W_L1P_2_OFF;
2980 vwr->L4ID_OFF = vVW510021_W_L4ID_OFF;
2981 vwr->IPLEN_OFF = vVW510021_W_IPLEN_OFF;
2982 vwr->PLCP_LENGTH_OFF = vVW510021_W_PLCP_LENGTH_OFF;
2984 vwr->MT_MASK = vVW510021_W_SEL_MASK;
2985 vwr->MCS_INDEX_MASK = vVW510021_W_MCS_MASK;
2986 vwr->VCID_MASK = 0xffff;
2987 vwr->FLOW_VALID = vVW510021_W_FLOW_VALID;
2988 vwr->STATS_START_OFF = vVW510021_W_HEADER_LEN;
2989 vwr->FCS_ERROR = vVW510021_W_FCS_ERROR;
2990 vwr->CRYPTO_ERR = v22_W_CRYPTO_ERR;
2991 vwr->RETRY_ERR = v22_W_RETRY_ERR;
2993 /*vwr->STATS_START_OFF = 0;*/
2995 vwr->RXTX_OFF = vVW510021_W_RXTX_OFF;
2997 vwr->MT_10_HALF = 0;
2998 vwr->MT_10_FULL = 0;
2999 vwr->MT_100_HALF = 0;
3000 vwr->MT_100_FULL = 0;
3001 vwr->MT_1G_HALF = 0;
3002 vwr->MT_1G_FULL = 0;
3003 vwr->MT_CCKL = v22_W_MT_CCKL;
3004 vwr->MT_CCKS = v22_W_MT_CCKS;
3005 /*vwr->MT_OFDM = vVW510021_W_MT_OFDM;*/
3007 vwr->WEPTYPE = vVW510021_W_WEPTYPE;
3008 vwr->TKIPTYPE = vVW510021_W_TKIPTYPE;
3009 vwr->CCMPTYPE = vVW510021_W_CCMPTYPE;
3011 vwr->FRAME_TYPE_OFF = vVW510021_W_FRAME_TYPE_OFF;
3012 vwr->IS_TCP = vVW510021_W_IS_TCP;
3013 vwr->IS_UDP = vVW510021_W_IS_UDP;
3014 vwr->IS_ICMP = vVW510021_W_IS_ICMP;
3015 vwr->IS_IGMP = vVW510021_W_IS_IGMP;
3016 vwr->IS_QOS = vVW510021_W_QOS_VALID;
3019 * vVW510021_W_STATS_HEADER_LEN = 8 is:
3021 * 2 bytes of l1p_1/l1p_2;
3022 * 1 byte of RSSI;
3023 * 2 bytes of MSDU length + other bits
3024 * 1 byte of XXX;
3025 * 2 bytes of VCID.
3027 * The 12 is for 11 bytes of PLCP and 1 byte of pad
3028 * before the data.
3030 vwr->MPDU_OFF = vVW510021_W_STATS_HEADER_LEN + 12;
3032 break;
3034 case S3_W_FPGA:
3035 vwr->STATS_LEN = vVW510021_W_STATS_TRAILER_LEN;
3036 vwr->PLCP_LENGTH_OFF = 16;
3039 * The 16 + 16 is:
3041 * 2 bytes of l1p_1/l1p_2;
3042 * 1 byte of signal bandwidth mask;
3043 * 1 byte of antenna port energy;
3044 * 4 bytes of per-antenna RSSI;
3045 * 1 byte of L1InfoC;
3046 * 3 bytes of MSDU length;
3047 * 4 bytes of something;
3048 * 16 bytes of PLCP.
3050 vwr->MPDU_OFF = 16 + 16;
3052 break;
3054 case vVW510012_E_FPGA:
3055 vwr->STATS_LEN = v22_E_STATS_LEN;
3057 vwr->VALID_OFF = v22_E_VALID_OFF;
3058 vwr->MTYPE_OFF = v22_E_MTYPE_OFF;
3059 vwr->VCID_OFF = v22_E_VCID_OFF;
3060 vwr->FLOWSEQ_OFF = v22_E_FLOWSEQ_OFF;
3061 vwr->FLOWID_OFF = v22_E_FLOWID_OFF;
3062 vwr->OCTET_OFF = v22_E_OCTET_OFF;
3063 vwr->ERRORS_OFF = v22_E_ERRORS_OFF;
3064 vwr->PATN_OFF = v22_E_PATN_OFF;
3065 vwr->RSSI_OFF = v22_E_RSSI_OFF;
3066 vwr->STARTT_OFF = v22_E_STARTT_OFF;
3067 vwr->ENDT_OFF = v22_E_ENDT_OFF;
3068 vwr->LATVAL_OFF = v22_E_LATVAL_OFF;
3069 vwr->INFO_OFF = v22_E_INFO_OFF;
3070 vwr->L4ID_OFF = v22_E_L4ID_OFF;
3072 vwr->IS_RX = v22_E_IS_RX;
3073 vwr->MT_MASK = v22_E_MT_MASK;
3074 vwr->VCID_MASK = v22_E_VCID_MASK;
3075 vwr->FLOW_VALID = v22_E_FLOW_VALID;
3076 vwr->FCS_ERROR = v22_E_FCS_ERROR;
3078 vwr->RX_DECRYPTS = v22_E_RX_DECRYPTS;
3079 vwr->TX_DECRYPTS = v22_E_TX_DECRYPTS;
3080 vwr->FC_PROT_BIT = v22_E_FC_PROT_BIT;
3082 vwr->MT_10_HALF = v22_E_MT_10_HALF;
3083 vwr->MT_10_FULL = v22_E_MT_10_FULL;
3084 vwr->MT_100_HALF = v22_E_MT_100_HALF;
3085 vwr->MT_100_FULL = v22_E_MT_100_FULL;
3086 vwr->MT_1G_HALF = v22_E_MT_1G_HALF;
3087 vwr->MT_1G_FULL = v22_E_MT_1G_FULL;
3088 vwr->MT_CCKL = 0;
3089 vwr->MT_CCKS = 0;
3090 vwr->MT_OFDM = 0;
3092 vwr->FRAME_TYPE_OFF = v22_E_FRAME_TYPE_OFF;
3093 vwr->IS_TCP = v22_E_IS_TCP;
3094 vwr->IS_UDP = v22_E_IS_UDP;
3095 vwr->IS_ICMP = v22_E_IS_ICMP;
3096 vwr->IS_IGMP = v22_E_IS_IGMP;
3097 vwr->IS_QOS = v22_E_IS_QOS;
3098 vwr->IS_VLAN = v22_E_IS_VLAN;
3100 break;
3102 /* WLAN frames */
3103 case S1_W_FPGA:
3104 vwr->STATS_LEN = v22_W_STATS_LEN;
3106 vwr->MTYPE_OFF = v22_W_MTYPE_OFF;
3107 vwr->VALID_OFF = v22_W_VALID_OFF;
3108 vwr->VCID_OFF = v22_W_VCID_OFF;
3109 vwr->FLOWSEQ_OFF = v22_W_FLOWSEQ_OFF;
3110 vwr->FLOWID_OFF = v22_W_FLOWID_OFF;
3111 vwr->OCTET_OFF = v22_W_OCTET_OFF;
3112 vwr->ERRORS_OFF = v22_W_ERRORS_OFF;
3113 vwr->PATN_OFF = v22_W_PATN_OFF;
3114 vwr->RSSI_OFF = v22_W_RSSI_OFF;
3115 vwr->STARTT_OFF = v22_W_STARTT_OFF;
3116 vwr->ENDT_OFF = v22_W_ENDT_OFF;
3117 vwr->LATVAL_OFF = v22_W_LATVAL_OFF;
3118 vwr->INFO_OFF = v22_W_INFO_OFF;
3119 vwr->L4ID_OFF = v22_W_L4ID_OFF;
3120 vwr->IPLEN_OFF = v22_W_IPLEN_OFF;
3121 vwr->PLCP_LENGTH_OFF = v22_W_PLCP_LENGTH_OFF;
3123 vwr->FCS_ERROR = v22_W_FCS_ERROR;
3124 vwr->CRYPTO_ERR = v22_W_CRYPTO_ERR;
3125 vwr->PAYCHK_ERR = v22_W_PAYCHK_ERR;
3126 vwr->RETRY_ERR = v22_W_RETRY_ERR;
3127 vwr->IS_RX = v22_W_IS_RX;
3128 vwr->MT_MASK = v22_W_MT_MASK;
3129 vwr->VCID_MASK = v22_W_VCID_MASK;
3130 vwr->FLOW_VALID = v22_W_FLOW_VALID;
3132 vwr->RX_DECRYPTS = v22_W_RX_DECRYPTS;
3133 vwr->TX_DECRYPTS = v22_W_TX_DECRYPTS;
3134 vwr->FC_PROT_BIT = v22_W_FC_PROT_BIT;
3136 vwr->MT_10_HALF = 0;
3137 vwr->MT_10_FULL = 0;
3138 vwr->MT_100_HALF = 0;
3139 vwr->MT_100_FULL = 0;
3140 vwr->MT_1G_HALF = 0;
3141 vwr->MT_1G_FULL = 0;
3142 vwr->MT_CCKL = v22_W_MT_CCKL;
3143 vwr->MT_CCKS = v22_W_MT_CCKS;
3144 vwr->MT_OFDM = v22_W_MT_OFDM;
3146 vwr->WEPTYPE = v22_W_WEPTYPE;
3147 vwr->TKIPTYPE = v22_W_TKIPTYPE;
3148 vwr->CCMPTYPE = v22_W_CCMPTYPE;
3150 vwr->FRAME_TYPE_OFF = v22_W_FRAME_TYPE_OFF;
3151 vwr->IS_TCP = v22_W_IS_TCP;
3152 vwr->IS_UDP = v22_W_IS_UDP;
3153 vwr->IS_ICMP = v22_W_IS_ICMP;
3154 vwr->IS_IGMP = v22_W_IS_IGMP;
3155 vwr->IS_QOS = v22_W_IS_QOS;
3157 break;
3159 /* Ethernet frames */
3160 case vVW510024_E_FPGA:
3161 vwr->STATS_LEN = vVW510024_E_STATS_LEN;
3163 vwr->VALID_OFF = vVW510024_E_VALID_OFF;
3164 vwr->VCID_OFF = vVW510024_E_VCID_OFF;
3165 vwr->FLOWSEQ_OFF = vVW510024_E_FLOWSEQ_OFF;
3166 vwr->FLOWID_OFF = vVW510024_E_FLOWID_OFF;
3167 vwr->OCTET_OFF = vVW510024_E_MSDU_LENGTH_OFF;
3168 vwr->ERRORS_OFF = vVW510024_E_ERRORS_OFF;
3169 vwr->PATN_OFF = vVW510024_E_MATCH_OFF;
3170 vwr->STARTT_OFF = vVW510024_E_STARTT_OFF;
3171 vwr->ENDT_OFF = vVW510024_E_ENDT_OFF;
3172 vwr->LATVAL_OFF = vVW510024_E_LATVAL_OFF;
3173 vwr->INFO_OFF = vVW510024_E_INFO_OFF;
3174 vwr->L4ID_OFF = vVW510024_E_L4ID_OFF;
3175 vwr->IPLEN_OFF = vVW510024_E_IPLEN_OFF;
3177 vwr->FPGA_VERSION_OFF = vVW510024_E_FPGA_VERSION_OFF;
3178 vwr->HEADER_VERSION_OFF = vVW510024_E_HEADER_VERSION_OFF;
3180 vwr->VCID_MASK = vVW510024_E_VCID_MASK;
3181 vwr->FLOW_VALID = vVW510024_E_FLOW_VALID;
3182 vwr->FCS_ERROR = v22_E_FCS_ERROR;
3184 vwr->FRAME_TYPE_OFF = vVW510024_E_FRAME_TYPE_OFF;
3185 vwr->IS_TCP = vVW510024_E_IS_TCP;
3186 vwr->IS_UDP = vVW510024_E_IS_UDP;
3187 vwr->IS_ICMP = vVW510024_E_IS_ICMP;
3188 vwr->IS_IGMP = vVW510024_E_IS_IGMP;
3189 vwr->IS_QOS = vVW510024_E_QOS_VALID;
3190 vwr->IS_VLAN = vVW510024_E_IS_VLAN;
3192 break;
3195 #define SIG_SCAN_RANGE 64 /* range of signature scanning region */
3197 /* Utility routine: check that signature is at specified location; scan for it if not. */
3198 /* If we can't find a signature at all, then simply return the originally supplied offset. */
3199 int find_signature(const uint8_t *m_ptr, int rec_size, int pay_off, uint32_t flow_id, uint8_t flow_seq)
3201 int tgt; /* temps */
3202 uint32_t fid;
3204 /* initial check is very simple: look for a '0xdd' at the target location */
3205 if (m_ptr[pay_off] == 0xdd) /* if magic byte is present */
3206 return pay_off; /* got right offset, return it */
3208 /* Hmmm, signature magic byte is not where it is supposed to be; scan from start of */
3209 /* payload until maximum scan range exhausted to see if we can find it. */
3210 /* The scanning process consists of looking for a '0xdd', then checking for the correct */
3211 /* flow ID and sequence number at the appropriate offsets. */
3212 for (tgt = pay_off; tgt < (rec_size); tgt++) {
3213 if (m_ptr[tgt] == 0xdd) { /* found magic byte? check fields */
3214 if ((tgt + 15 < rec_size) && (m_ptr[tgt + 15] == 0xe2)) {
3215 if (m_ptr[tgt + 4] != flow_seq)
3216 continue;
3218 fid = pletoh24(&m_ptr[tgt + 1]);
3220 if (fid != flow_id)
3221 continue;
3223 return (tgt);
3225 else if (tgt + SIG_FSQ_OFF < rec_size)
3226 { /* out which one... */
3227 if (m_ptr[tgt + SIG_FSQ_OFF] != flow_seq) /* check sequence number */
3228 continue; /* if failed, keep scanning */
3230 fid = pletoh24(&m_ptr[tgt + SIG_FID_OFF]); /* assemble flow ID from signature */
3231 if (fid != flow_id) /* check flow ID against expected */
3232 continue; /* if failed, keep scanning */
3234 /* matched magic byte, sequence number, flow ID; found the signature */
3235 return (tgt); /* return offset of signature */
3240 /* failed to find the signature, return the original offset as default */
3241 return pay_off;
3244 /* utility routine: harvest the signature time stamp from the data frame */
3245 uint64_t get_signature_ts(const uint8_t *m_ptr,int sig_off, int sig_max)
3247 int ts_offset;
3248 uint64_t sig_ts;
3250 if (sig_off + 15 >= sig_max)
3251 return 0;
3253 if (m_ptr[sig_off + 15] == 0xe2)
3254 ts_offset = 5;
3255 else
3256 ts_offset = 8;
3258 sig_ts = pletoh32(&m_ptr[sig_off + ts_offset]);
3260 return (sig_ts & 0xffffffff);
3263 static float
3264 get_legacy_rate(uint8_t rate_index)
3266 /* Rate conversion data */
3267 static const float canonical_rate_legacy[] = {1.0f, 2.0f, 5.5f, 11.0f, 6.0f, 9.0f, 12.0f, 18.0f, 24.0f, 36.0f, 48.0f, 54.0f};
3269 float bitrate = 0.0f;
3271 if (rate_index < G_N_ELEMENTS(canonical_rate_legacy))
3272 bitrate = canonical_rate_legacy[rate_index];
3274 return bitrate;
3277 static float
3278 get_ht_rate(uint8_t mcs_index, uint16_t rflags)
3280 /* Rate conversion data */
3281 static const int canonical_ndbps_20_ht[8] = {26, 52, 78, 104, 156, 208, 234, 260};
3282 static const int canonical_ndbps_40_ht[8] = {54, 108, 162, 216, 324, 432, 486, 540};
3284 float symbol_tx_time, bitrate;
3285 int ndbps;
3287 if (rflags & FLAGS_CHAN_SHORTGI)
3288 symbol_tx_time = 3.6f;
3289 else
3290 symbol_tx_time = 4.0f;
3292 if (rflags & FLAGS_CHAN_40MHZ)
3293 ndbps = canonical_ndbps_40_ht[mcs_index - 8*(int)(mcs_index/8)];
3294 else
3295 ndbps = canonical_ndbps_20_ht[mcs_index - 8*(int)(mcs_index/8)];
3297 bitrate = (ndbps * (((int)(mcs_index >> 3) + 1))) / symbol_tx_time;
3299 return bitrate;
3302 static float
3303 get_vht_rate(uint8_t mcs_index, uint16_t rflags, uint8_t nss)
3305 /* Rate conversion data */
3306 static const int canonical_ndbps_20_vht[9] = {26, 52, 78, 104, 156, 208, 234, 260, 312};
3307 static const int canonical_ndbps_40_vht[10] = {54, 108, 162, 216, 324, 432, 486, 540, 648, 720};
3308 static const int canonical_ndbps_80_vht[10] = {117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560};
3310 float symbol_tx_time, bitrate;
3312 if (rflags & FLAGS_CHAN_SHORTGI)
3313 symbol_tx_time = 3.6f;
3314 else
3315 symbol_tx_time = 4.0f;
3318 * Check for the out of range mcs_index.
3319 * Should never happen, but if mcs index is greater than 9 just
3320 * return 0.
3322 if (mcs_index > 9)
3323 return 0.0f;
3324 if (rflags & FLAGS_CHAN_40MHZ)
3325 bitrate = (canonical_ndbps_40_vht[mcs_index] * nss) / symbol_tx_time;
3326 else if (rflags & FLAGS_CHAN_80MHZ)
3327 bitrate = (canonical_ndbps_80_vht[mcs_index] * nss) / symbol_tx_time;
3328 else
3330 if (mcs_index == 9)
3332 /* This is a special case for 20 MHz. */
3333 if (nss == 3)
3334 bitrate = 1040 / symbol_tx_time;
3335 else if (nss == 6)
3336 bitrate = 2080 / symbol_tx_time;
3337 else
3338 bitrate = 0.0f;
3340 else
3341 bitrate = (canonical_ndbps_20_vht[mcs_index] * nss) / symbol_tx_time;
3344 return bitrate;
3347 static bool
3348 vwr_process_rec_data(FILE_T fh, int rec_size,
3349 wtap_rec *record, Buffer *buf, vwr_t *vwr,
3350 int IS_TX, int log_mode, int *err, char **err_info)
3352 uint8_t* rec; /* local buffer (holds input record) */
3353 bool ret = false;
3355 rec = (uint8_t*)g_malloc(B_SIZE);
3357 /* Read over the entire record (frame + trailer) into a local buffer. */
3358 /* If we don't get it all, then declare an error, we can't process the frame. */
3359 if (!wtap_read_bytes(fh, rec, rec_size, err, err_info))
3361 g_free(rec);
3362 return false;
3365 /* now format up the frame data */
3366 switch (vwr->FPGA_VERSION)
3368 case S1_W_FPGA:
3369 ret = vwr_read_s1_W_rec(vwr, record, buf, rec, rec_size, err, err_info);
3370 break;
3371 case S2_W_FPGA:
3372 ret = vwr_read_s2_W_rec(vwr, record, buf, rec, rec_size, IS_TX, err, err_info);
3373 break;
3374 case S3_W_FPGA:
3375 ret = vwr_read_s3_W_rec(vwr, record, buf, rec, rec_size, IS_TX, log_mode, err, err_info);
3376 break;
3377 case vVW510012_E_FPGA:
3378 case vVW510024_E_FPGA:
3379 ret = vwr_read_rec_data_ethernet(vwr, record, buf, rec, rec_size, IS_TX, err, err_info);
3380 break;
3381 default:
3382 g_free(rec);
3383 ws_assert_not_reached();
3384 return ret;
3387 g_free(rec);
3388 return ret;
3391 static const struct supported_block_type vwr_80211_blocks_supported[] = {
3393 * We support packet blocks, with no comments or other options.
3395 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
3398 static const struct file_type_subtype_info vwr_80211_info = {
3399 "Ixia IxVeriWave .vwr Raw 802.11 Capture", "vwr80211", "vwr", NULL,
3400 false, BLOCKS_SUPPORTED(vwr_80211_blocks_supported),
3401 NULL, NULL, NULL
3404 static const struct supported_block_type vwr_eth_blocks_supported[] = {
3406 * We support packet blocks, with no comments or other options.
3408 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
3411 static const struct file_type_subtype_info vwr_eth_info = {
3412 "Ixia IxVeriWave .vwr Raw Ethernet Capture", "vwreth", "vwr", NULL,
3413 false, BLOCKS_SUPPORTED(vwr_eth_blocks_supported),
3414 NULL, NULL, NULL
3417 void register_vwr(void)
3419 vwr_80211_file_type_subtype = wtap_register_file_type_subtype(&vwr_80211_info);
3420 vwr_eth_file_type_subtype = wtap_register_file_type_subtype(&vwr_eth_info);
3423 * Register names for backwards compatibility with the
3424 * wtap_filetypes table in Lua.
3426 wtap_register_backwards_compatibility_lua_name("VWR_80211",
3427 vwr_80211_file_type_subtype);
3428 wtap_register_backwards_compatibility_lua_name("VWR_ETH",
3429 vwr_eth_file_type_subtype);
3433 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3435 * Local variables:
3436 * c-basic-offset: 4
3437 * tab-width: 8
3438 * indent-tabs-mode: nil
3439 * End:
3441 * vi: set shiftwidth=4 tabstop=8 expandtab:
3442 * :indentSize=4:tabSize=8:noTabs=true: