Coverage Report

Created: 2026-11-12 07:01

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