2 * Copyright (c) 2011 by Tom Alexander <talexander@ixiacom.com>
7 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "file_wrappers.h"
35 /* platform-specific definitions for portability */
37 /* unsigned long long constants */
38 # define NS_IN_US G_GINT64_CONSTANT(1000U) /* nanoseconds-to-microseconds */
39 # define NS_IN_SEC G_GINT64_CONSTANT(1000000000U) /* nanoseconds-to-seconds */
40 # define US_IN_SEC G_GINT64_CONSTANT(1000000U) /* microseconds-to-seconds */
41 # define LL_ZERO G_GINT64_CONSTANT(0U) /* zero in unsigned long long */
44 * Fetch a 64-bit value in "Corey-endian" form.
46 #define pcoreytohll(p) ((guint64)*((const guint8 *)(p)+4)<<56| \
47 (guint64)*((const guint8 *)(p)+5)<<48| \
48 (guint64)*((const guint8 *)(p)+6)<<40| \
49 (guint64)*((const guint8 *)(p)+7)<<32| \
50 (guint64)*((const guint8 *)(p)+0)<<24| \
51 (guint64)*((const guint8 *)(p)+1)<<16| \
52 (guint64)*((const guint8 *)(p)+2)<<8| \
53 (guint64)*((const guint8 *)(p)+3)<<0)
55 /* .vwr log file defines */
56 #define B_SIZE 32768 /* max var len message = 32 kB */
57 #define VT_FRAME 0 /* varlen msg is a frame */
58 #define VT_CPMSG 1 /* varlen msg is a CP<->PP msg */
59 #define MAX_TRACKED_CLIENTS 1024 /* track 1024 clients */
60 #define MAX_TRACKED_FLOWS 65536 /* and 64K flows */
62 /* the radiotap header */
64 /* IxVeriwave common header fields */
66 guint16 vw_port_type
; /* 0 for WLAN, 1 for Ethernet */
67 guint16 it_len
; /* WHOLE radiotap header length (incl. */
68 guint16 vw_msdu_length
; /* length of MAC SDU */
69 guint32 vw_flowid
; /* VeriWave-specific flow ID for packet */
70 guint16 vw_vcid
; /* VeriWave-specific vC ID (client id) */
71 guint16 vw_seqnum
; /* VeriWave-specific signature seqnum */
72 guint32 vw_latency
; /* VeriWave-specific packet latency, ns */
73 guint32 vw_sig_ts
; /* signature timestamp, 32 LSBs, nsec */
74 guint64 vw_startt
; /* frame start time (nsec) */
75 guint64 vw_endt
; /* frame end time (nsec) */
76 guint32 vw_pktdur
; /* VeriWave-specific pkt duration, us */
78 } stats_common_fields
;
80 /* Size of those fields - regardless of how the compiler packs them */
81 #define STATS_COMMON_FIELDS_LEN (2+2+2+4+2+2+4+4+8+8+4)
83 /* Veriwave-specific extended radiotap header fields (following vwr_rtap_hdr above) */
84 /* structure elements correspond one-to-one with the RADIOTAP_PRESENT bitmask below */
85 /* NOTE: must ensure that elements are aligned to their "natural" packing */
86 /* NOTE: must ensure that "latency" precedes all other packet timing details, because it */
87 /* is used to start a subtree */
89 guint16 it_len
; /* WHOLE radiotap header length (incl. */
90 guint16 flags
; /* short preamble, WEP, frag */
91 guint16 chanflags
; /* channel flags bitmap */
92 guint16 phyRate
; /* The PHY rate of the packet * 10 (accommodates the 5.5 on CCK) */
93 guint8 plcpType
; /* PLCP type - 0: Legacy, 1: HT Mixed, 2: HT Green field, 3: VHT mixed */
94 guint8 mcsIndex
; /* 0 - 31 possible */
95 guint8 nss
; /* Guard interval */
96 gint8 signal
; /* RF signal power, +/- dBm */
97 gint8 signalb
; /* transmit power, +/- dBm */
98 gint8 signalc
; /* transmit power, +/- dBm */
99 gint8 signald
; /* transmit power, +/- dBm */
101 guint16 vw_flags
; /* VeriWave-specific packet flags */
102 guint16 vw_ht_length
; /* ht length (in plcp header)*/
103 guint16 vw_info
; /* VeriWave-specific information */
104 guint32 vw_errors
; /* VeriWave-specific errors */
108 /* Size of those fields - regardless of how the compiler packs them */
109 #define EXT_RTAP_FIELDS_LEN (2+2+2+2+1+1+1+1+1+1+1+1+2+2+2+4)
111 /* Veriwave-specific Ethernettap header */
113 guint16 it_len
; /* WHOLE radiotap header length (incl. */
114 guint16 vw_flags
; /* Veriwave-specific flags (see above) */
115 guint16 vw_info
; /* VeriWave-specific information */
116 guint32 vw_errors
; /* VeriWave-specific flags */
117 guint32 vw_l4id
; /* layer four id*/
118 guint32 it_pad2
; /* pad out header to 16-byte boundary */
119 } stats_ethernettap_fields
;
121 /* Size of those fields - regardless of how the compiler packs them */
122 #define STATS_ETHERNETTAP_FIELDS_LEN (2+2+2+4+4+4)
124 /* the bitmap offsets of the bits in it_present, above */
125 /* also lists the expected field sizes in bytes */
126 /* MUST BE IN SAME ORDER AS THE STRUCTURE ELEMENTS ABOVE */
128 VW_RADIOTAP_FLAGS
= 0, /* 2 bytes */
129 VW_RADIOTAP_RATE
= 1, /* 1 byte */
130 VW_RADIOTAP_CHANNEL
= 2, /* 4 bytes (mhz + chanflags) */
131 VW_RADIOTAP_DBM_ANTSIGNAL
= 3, /* 1 byte */
132 VW_RADIOTAP_DBM_TX_POWER
= 4, /* 1 byte */
133 /* start of veriwave addition */
134 VW_RADIOTAP_FPGA_VERSION
= 5, /* 2 bytes */
135 VW_RADIOTAP_VW_FLAGS
= 6, /* 2 bytes */
136 VW_RADIOTAP_MSDU_LENGTH
= 7, /* 2 bytes */
137 VW_RADIOTAP_HT_LENGTH
= 8, /* 2 bytes */
138 VW_RADIOTAP_INFO
= 9, /* 2 bytes */
139 VW_RADIOTAP_ERRORS
= 10, /* 4 bytes */
140 VW_RADIOTAP_FLOWID
= 11, /* 4 bytes */
141 VW_RADIOTAP_MCID
= 12, /* 2 bytes */
142 VW_RADIOTAP_SEQNUM
= 13, /* 2 bytes */
143 VW_RADIOTAP_LATENCY
= 14, /* 4 bytes (MUST COME BEFORE OTHER TIMES)*/
144 VW_RADIOTAP_SIG_TS
= 15, /* 4 bytes */
145 VW_RADIOTAP_STARTT
= 16, /* 8 bytes */
146 VW_RADIOTAP_ENDT
= 17, /* 8 bytes */
147 VW_RADIOTAP_PKTDUR
= 18, /* 4 bytes */
148 VW_RADIOTAP_IFG
= 19, /* 4 bytes */
150 /* end of Veriwave addition 6-2007 */
155 /* standard field-present bitmap corresponding to above fixed-size set of fields */
156 /* this produces a 16-byte header */
157 #define VW_RADIOTAP_PRESENT ((1 << VW_RADIOTAP_FLAGS) | \
158 (1 << VW_RADIOTAP_RATE) | \
159 (1 << VW_RADIOTAP_CHANNEL) | \
160 (1 << VW_RADIOTAP_DBM_ANTSIGNAL) | \
161 (1 << VW_RADIOTAP_DBM_TX_POWER))
163 /* extended field-present bitmap corresponding to above fixed-size set of fields */
164 /* this produces a 32-byte header */
165 #define VW_EXT_RTAP_PRESENT ((1 << VW_RADIOTAP_FLAGS) | \
166 (1 << VW_RADIOTAP_RATE) | \
167 (1 << VW_RADIOTAP_CHANNEL) | \
168 (1 << VW_RADIOTAP_DBM_ANTSIGNAL) | \
169 (1 << VW_RADIOTAP_DBM_TX_POWER) | \
170 (1 << VW_RADIOTAP_FPGA_VERSION) | \
171 (1 << VW_RADIOTAP_VW_FLAGS) | \
172 (1 << VW_RADIOTAP_MSDU_LENGTH) | \
173 (1 << VW_RADIOTAP_HT_LENGTH) | \
174 (1 << VW_RADIOTAP_ERRORS) | \
175 (1 << VW_RADIOTAP_INFO) | \
176 (1 << VW_RADIOTAP_MCID) | \
177 (1 << VW_RADIOTAP_FLOWID) | \
178 (1 << VW_RADIOTAP_SEQNUM) | \
179 (1 << VW_RADIOTAP_LATENCY) | \
180 (1 << VW_RADIOTAP_SIG_TS) | \
181 (1 << VW_RADIOTAP_STARTT) | \
182 (1 << VW_RADIOTAP_ENDT) |\
183 (1 << VW_RADIOTAP_PKTDUR) |\
184 (1 << VW_RADIOTAP_IFG))
187 * RADIOTAP_FLAGS u_int8_t bitmap
188 * See flags definitions below
190 * RADIOTAP_RATE u_int8_t 500kb/s
193 * RADIOTAP_CHANNEL 2 x u_int16_t MHz+bitmap
194 * Tx/Rx frequency in MHz, followed by flags (see below).
196 * RADIOTAP_DBM_ANTSIGNAL int8_t dBm
197 * RF signal power at the antenna, dBm
199 * RADIOTAP_DBM_ANTNOISE int8_t dBm
200 * RF noise power at the antenna, dBm
202 * RADIOTAP_BARKER_CODE_LOCK u_int16_t unitless
203 * Quality of Barker code lock. Monotonically nondecreasing with "better" lock strength.
204 * Called "Signal Quality" in datasheets.
206 * RADIOTAP_DBM_TX_POWER int8_t dBm
207 * Transmit power expressed as dBm.
210 /* Channel flags for IEEE80211_RADIOTAP_CHANNEL */
211 #define CHAN_TURBO 0x0010 /* Turbo channel */
212 #define CHAN_CCK 0x0020 /* CCK channel */
213 #define CHAN_OFDM 0x0040 /* OFDM channel */
214 #define CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */
215 #define CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */
216 #define CHAN_PASSIVE 0x0200 /* Only passive scan allowed */
218 /* For RADIOTAP_FLAGS */
219 #define RADIOTAP_F_CFP 0x001 /* sent/received during CFP */
220 #define RADIOTAP_F_SHORTPRE 0x002 /* sent/received with short preamble */
221 #define RADIOTAP_F_WEP 0x004 /* sent/received with WEP encryption */
222 #define RADIOTAP_F_FRAG 0x008 /* sent/received with fragmentation */
223 #define RADIOTAP_F_FCS 0x010 /* frame includes FCS */
224 #define RADIOTAP_F_DATAPAD 0x020 /* padding between 802.11 hdr & payload */
225 #define RADIOTAP_F_CHAN_HT 0x040 /* In HT mode */
226 #define RADIOTAP_F_CHAN_VHT 0x080 /* VHT Mode */
227 #define RADIOTAP_F_CHAN_SHORTGI 0x100 /* Short guard interval */
228 #define RADIOTAP_F_CHAN_40MHZ 0x200 /* 40 Mhz CBW */
229 #define RADIOTAP_F_CHAN_80MHZ 0x400 /* 80 MHz channel bandwidth */
230 #define RADIOTAP_F_CHAN_160MHZ 0x800 /* 160 MHz channel bandwidth */
232 /* For VeriWave-specific RADIOTAP_FLAGS and ETHERNETTAP_FLAGS */
233 #define RADIOTAP_VWF_TXF 0x01 /* frame was transmitted */
234 #define RADIOTAP_VWF_FCSERR 0x02 /* FCS error detected */
235 #define RADIOTAP_VWF_RETRERR 0x04 /* excess retry error detected */
236 #define RADIOTAP_VWF_DCRERR 0x10 /* decrypt error detected (WLAN) */
237 #define RADIOTAP_VWF_ENCMSK 0x60 /* encryption type mask */
238 /* 0 = none, 1 = WEP, 2 = TKIP, 3 = CCKM */
239 #define RADIOTAP_VWF_IS_WEP 0x20 /* WEP */
240 #define RADIOTAP_VWF_IS_TKIP 0x40 /* TKIP */
241 #define RADIOTAP_VWF_IS_CCMP 0x60 /* CCMP */
242 #define RADIOTAP_VWF_SEQ_ERR 0x80 /* flow sequence error detected */
244 #define IEEE80211_PLCP_RATE_MASK 0x7f /* parses out the rate or MCS index from the PLCP header(s) */
245 #define IEEE80211_RADIOTAP_F_40MHZ 0x0200 /* 40 Mhz channel bandwidth */
246 #define IEEE80211_RADIOTAP_F_80MHZ 0x0400 /* 80 Mhz channel bandwidth */
247 #define IEEE80211_RADIOTAP_F_160MHZ 0x0800 /* 80 Mhz channel bandwidth */
248 #define IEEE80211_RADIOTAP_F_SHORTGI 0x0100
250 /* FPGA-generated frame buffer STATS block offsets and definitions */
252 /* definitions for v2.2 frames, Ethernet format */
253 #define v22_E_STATS_LEN 44 /* length of stats block trailer */
254 #define v22_E_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
255 #define v22_E_MTYPE_OFF 1 /* offset of modulation type */
256 #define v22_E_VCID_OFF 2 /* offset of VC ID */
257 #define v22_E_FLOWSEQ_OFF 4 /* offset of signature sequence number */
258 #define v22_E_FLOWID_OFF 5 /* offset of flow ID */
259 #define v22_E_OCTET_OFF 8 /* offset of octets */
260 #define v22_E_ERRORS_OFF 10 /* offset of error vector */
261 #define v22_E_PATN_OFF 12 /* offset of pattern match vector */
262 #define v22_E_L4ID_OFF 12
263 #define v22_E_IPLEN_OFF 14
264 #define v22_E_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
265 #define v22_E_RSSI_OFF 21 /* RSSI (NOTE: invalid for Ethernet) */
266 #define v22_E_STARTT_OFF 20 /* offset of start time, 64 bits */
267 #define v22_E_ENDT_OFF 28 /* offset of end time, 64 bits */
268 #define v22_E_LATVAL_OFF 36 /* offset of latency, 32 bits */
269 #define v22_E_INFO_OFF 40 /* NO INFO FIELD IN ETHERNET STATS! */
270 #define v22_E_DIFFERENTIATOR_OFF 0 /* offset to determine whether */
271 /* eth/802.11, 8 bits */
273 #define v22_E_MT_10_HALF 0 /* 10 Mb/s half-duplex */
274 #define v22_E_MT_10_FULL 1 /* 10 Mb/s full-duplex */
275 #define v22_E_MT_100_HALF 2 /* 100 Mb/s half-duplex */
276 #define v22_E_MT_100_FULL 3 /* 100 Mb/s full-duplex */
277 #define v22_E_MT_1G_HALF 4 /* 1 Gb/s half-duplex */
278 #define v22_E_MT_1G_FULL 5 /* 1 Gb/s full-duplex */
280 #define v22_E_FCS_ERROR 0x0002 /* FCS error flag in error vector */
281 #define v22_E_CRYPTO_ERR 0x1f00 /* RX decrypt error flags (UNUSED) */
282 #define v22_E_SIG_ERR 0x0004 /* signature magic byte mismatch */
283 #define v22_E_PAYCHK_ERR 0x0008 /* payload checksum failure */
284 #define v22_E_RETRY_ERR 0x0400 /* excessive retries on TX fail (UNUSED)*/
285 #define v22_E_IS_RX 0x08 /* TX/RX bit in STATS block */
286 #define v22_E_MT_MASK 0x07 /* modulation type mask (UNUSED) */
287 #define v22_E_VCID_MASK 0x03ff /* VC ID is only 9 bits */
288 #define v22_E_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
289 #define v22_E_DIFFERENTIATOR_MASK 0X3F /* mask to differentiate ethernet from */
290 #define v22_E_IS_TCP 0x00000040 /* TCP bit in FRAME_TYPE field */
291 #define v22_E_IS_UDP 0x00000010 /* UDP bit in FRAME_TYPE field */
292 #define v22_E_IS_ICMP 0x00000020 /* ICMP bit in FRAME_TYPE field */
293 #define v22_E_IS_IGMP 0x00000080 /* IGMP bit in FRAME_TYPE field */
294 #define v22_E_IS_QOS 0x80 /* QoS bit in MTYPE field (WLAN only) */
295 #define v22_E_IS_VLAN 0x00200000
298 #define v22_E_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted (UNUSED) */
299 #define v22_E_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted (UNUSED) */
301 #define v22_E_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
304 #define v22_E_HEADER_IS_RX 0x21
305 #define v22_E_HEADER_IS_TX 0x31
307 #define v22_E_IS_ETHERNET 0x00700000 /* bits set in frame type if ethernet */
308 #define v22_E_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
310 /* definitions for v2.2 frames, WLAN format for VW510006 FPGA*/
311 #define v22_W_STATS_LEN 64 /* length of stats block trailer */
312 #define v22_W_VALID_OFF 0 /* bit 6 (0x40) is flow-is-valid flag */
313 #define v22_W_MTYPE_OFF 1 /* offset of modulation type */
314 #define v22_W_VCID_OFF 2 /* offset of VC ID */
315 #define v22_W_FLOWSEQ_OFF 4 /* offset of signature sequence number */
316 #define v22_W_FLOWID_OFF 5 /* offset of flow ID */
317 #define v22_W_OCTET_OFF 8 /* offset of octets */
318 #define v22_W_ERRORS_OFF 10 /* offset of error vector */
319 #define v22_W_PATN_OFF 12
320 #define v22_W_L4ID_OFF 12
321 #define v22_W_IPLEN_OFF 14
322 #define v22_W_FRAME_TYPE_OFF 16 /* offset of frame type, 32 bits */
323 #define v22_W_RSSI_OFF 21 /* RSSI (NOTE: RSSI must be negated!) */
324 #define v22_W_STARTT_OFF 24 /* offset of start time, 64 bits */
325 #define v22_W_ENDT_OFF 32 /* offset of end time, 64 bits */
326 #define v22_W_LATVAL_OFF 40 /* offset of latency, 32 bits */
327 #define v22_W_INFO_OFF 54 /* offset of INFO field, 16 LSBs */
328 #define v22_W_DIFFERENTIATOR_OFF 20 /* offset to determine whether */
329 /* eth/802.11, 32 bits */
331 #define v22_W_PLCP_LENGTH_OFF 4 /* LENGTH field in the plcp header */
334 #define v22_W_MT_CCKL 0 /* CCK modulation, long preamble */
335 #define v22_W_MT_CCKS 1 /* CCK modulation, short preamble */
336 #define v22_W_MT_OFDM 2 /* OFDM modulation */
338 #define v22_W_IS_TCP 0x00000040 /* TCP bit in FRAME_TYPE field */
339 #define v22_W_IS_UDP 0x00000010 /* UDP bit in FRAME_TYPE field */
340 #define v22_W_IS_ICMP 0x00000020 /* ICMP bit in FRAME_TYPE field */
341 #define v22_W_IS_IGMP 0x00000080 /* IGMP bit in FRAME_TYPE field */
342 #define v22_W_IS_QOS 0x80 /* QoS bit in MTYPE field (WLAN only) */
345 #define v22_W_FCS_ERROR 0x0002 /* FCS error flag in error vector */
346 #define v22_W_CRYPTO_ERR 0x1f00 /* RX decrypt error flags */
347 #define v22_W_SIG_ERR 0x0004 /* signature magic byte mismatch */
348 #define v22_W_PAYCHK_ERR 0x0008 /* payload checksum failure */
349 #define v22_W_RETRY_ERR 0x0400 /* excessive retries on TX failure */
350 #define v22_W_IS_RX 0x08 /* TX/RX bit in STATS block */
351 #define v22_W_MT_MASK 0x07 /* modulation type mask */
352 #define v22_W_VCID_MASK 0x01ff /* VC ID is only 9 bits */
353 #define v22_W_FLOW_VALID 0x40 /* flow-is-valid flag (else force to 0) */
354 #define v22_W_DIFFERENTIATOR_MASK 0Xf0ff /* mask to differentiate ethernet from */
357 #define v22_W_RX_DECRYPTS 0x0007 /* RX-frame-was-decrypted bits */
358 #define v22_W_TX_DECRYPTS 0x0007 /* TX-frame-was-decrypted bits */
360 #define v22_W_WEPTYPE 0x0001 /* WEP frame */
361 #define v22_W_TKIPTYPE 0x0002 /* TKIP frame */
362 #define v22_W_CCMPTYPE 0x0004 /* CCMP frame */
364 #define v22_W_HEADER_IS_RX 0x21
365 #define v22_W_HEADER_IS_TX 0x31
367 #define v22_W_FC_PROT_BIT 0x40 /* Protected Frame bit in FC1 of frame */
369 #define v22_W_IS_ETHERNET 0x00100000 /* bits set in frame type if ethernet */
370 #define v22_W_IS_80211 0x7F000000 /* bits set in frame type if 802.11 */
372 /* definitions for VW510021 FPGA, WLAN format */
375 8 bytes of stat block
376 plcp stuff (11 bytes plcp + 1 byte pad)
378 remaining 48 bytes of stat block
380 /* offsets in the stats block */
381 #define vVW510021_W_STATS_LEN 48 /* length of stats block trailer after the plcp portion*/
382 #define vVW510021_W_STARTT_OFF 0 /* offset of start time, 64 bits */
383 #define vVW510021_W_ENDT_OFF 8 /* offset of end time, 64 bits */
384 #define vVW510021_W_ERRORS_OFF 16 /* offset of error vector */
385 #define vVW510021_W_VALID_OFF 20 /* 2 Bytes with different validity bits */
386 #define vVW510021_W_INFO_OFF 22 /* offset of INFO field, 16 LSBs */
387 #define vVW510021_W_FRAME_TYPE_OFF 24
388 #define vVW510021_W_L4ID_OFF 28
389 #define vVW510021_W_IPLEN_OFF 30 /* offset of IP Total Length field */
390 #define vVW510021_W_FLOWSEQ_OFF 32 /* offset of signature sequence number */
391 #define vVW510021_W_FLOWID_OFF 33 /* offset of flow ID */
392 #define vVW510021_W_LATVAL_OFF 36 /* offset of delay/flowtimestamp, 32b */
393 #define vVW510021_W_DEBUG_OFF 40 /* offset of debug, 16 bits */
394 #define S2_W_FPGA_VERSION_OFF 44 /* offset of fpga version, 16 bits */
395 #define vVW510021_W_MATCH_OFF 47 /* offset of pattern match vector */
397 /* offsets in the header block */
398 #define vVW510021_W_HEADER_LEN 16 /* length of FRAME header */
399 #define vVW510021_W_RXTX_OFF 0 /* rxtx offset, cmd byte of header */
400 #define vVW510021_W_HEADER_VERSION_OFF 9 /* version, 2bytes */
401 #define vVW510021_MSG_LENGTH_OFF 10 /* MSG LENGTH, 2bytes */
402 #define vVW510021_W_DEVICE_TYPE_OFF 8 /* version, 2bytes */
404 /* offsets that occur right after the header */
405 #define vVW510021_W_AFTERHEADER_LEN 8 /* length of STATs info directly after header */
406 #define vVW510021_W_L1P_1_OFF 0 /* offset of 1st byte of layer one info */
407 #define vVW510021_W_L1P_2_OFF 1 /* offset of 2nd byte of layer one info */
408 #define vVW510021_W_MTYPE_OFF vVW510021_W_L1P_2_OFF
409 #define vVW510021_W_PREAMBLE_OFF vVW510021_W_L1P_1_OFF
410 #define vVW510021_W_RSSI_TXPOWER_OFF 2 /* RSSI (NOTE: RSSI must be negated!) */
411 #define vVW510021_W_MSDU_LENGTH_OFF 3 /* 7:0 of length, next byte 11:8 in top 4 bits */
412 #define vVW510021_W_BVCV_VALID_OFF 4 /* BV,CV Determine validaity of bssid and txpower */
413 #define vVW510021_W_VCID_OFF 6 /* offset of VC (client) ID */
414 #define vVW510021_W_PLCP_LENGTH_OFF 12 /* LENGTH field in the plcp header */
416 /* Masks and defines */
417 #define vVW510021_W_IS_BV 0x04 /* BV bit in STATS block */
418 #define vVW510021_W_IS_CV 0x02 /* BV bit in STATS block */
419 #define vVW510021_W_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else 0) */
420 #define vVW510021_W_QOS_VALID 0x4000
421 #define vVW510021_W_HT_VALID 0x2000
422 #define vVW510021_W_L4ID_VALID 0x1000
423 #define vVW510021_W_PREAMBLE_MASK 0x40 /* short/long preamble/guard(ofdm) mask */
424 #define vVW510021_W_MCS_MASK 0x3f /* mcs index (a/b) type mask */
425 #define vVW510021_W_MOD_SCHEME_MASK 0x3f /* modulation type mask */
426 #define vVW510021_W_PLCPC_MASK 0x03 /* PLPCP type mask */
427 #define vVW510021_W_SEL_MASK 0x80
428 #define vVW510021_W_WEP_MASK 0x0001
429 #define vVW510021_W_CBW_MASK 0xC0
431 #define vVW510021_W_MT_SEL_LEGACY 0x00
432 #define vVW510021_W_PLCP_LEGACY 0x00
433 #define vVW510021_W_PLCP_MIXED 0x01
434 #define vVW510021_W_PLCP_GREENFIELD 0x02
435 #define vVW510021_W_PLCP_VHT_MIXED 0x03
436 #define vVW510021_W_HEADER_IS_RX 0x21
437 #define vVW510021_W_HEADER_IS_TX 0x31
438 #define vVW510021_W_IS_WEP 0x0001
439 #define vVW510021_W_IS_LONGPREAMBLE 0x40
441 #define vVW510021_W_IS_TCP 0x01000000 /* TCP bit in FRAME_TYPE field */
442 #define vVW510021_W_IS_UDP 0x00100000 /* UDP bit in FRAME_TYPE field */
443 #define vVW510021_W_IS_ICMP 0x00001000 /* ICMP bit in FRAME_TYPE field */
444 #define vVW510021_W_IS_IGMP 0x00010000 /* IGMP bit in FRAME_TYPE field */
447 #define vVW510021_W_HEADER_VERSION 0x00
448 #define vVW510021_W_DEVICE_TYPE 0x15
449 #define vVW510021_W_11n_DEVICE_TYPE 0x20
450 #define S2_W_FPGA_VERSION 0x000C
451 #define vVW510021_W_11n_FPGA_VERSION 0x000D
454 #define vVW510021_W_FCS_ERROR 0x01
455 #define vVW510021_W_CRYPTO_ERROR 0x50000
457 #define vVW510021_W_WEPTYPE 0x0001 /* WEP frame */
458 #define vVW510021_W_TKIPTYPE 0x0002 /* TKIP frame */
459 #define vVW510021_W_CCMPTYPE 0x0004 /* CCMP frame */
461 /* definitions for VW510024 FPGA, wired ethernet format */
464 52 bytes of stats block trailer
466 /* offsets in the stats block */
467 #define vVW510024_E_STATS_LEN 48 /* length of stats block trailer */
468 #define vVW510024_E_MSDU_LENGTH_OFF 0 /* MSDU 16 BITS */
469 #define vVW510024_E_BMCV_VALID_OFF 2 /* BM,CV Determine validITY */
470 #define vVW510024_E_VCID_OFF 2 /* offset of VC (client) ID 13:8, */
472 #define vVW510024_E_STARTT_OFF 4 /* offset of start time, 64 bits */
473 #define vVW510024_E_ENDT_OFF 12 /* offset of end time, 64 bits */
474 #define vVW510024_E_ERRORS_OFF 22 /* offset of error vector */
475 #define vVW510024_E_VALID_OFF 24 /* 2 Bytes with different validity bits */
476 #define vVW510024_E_INFO_OFF 26 /* offset of INFO field, 16 LSBs */
477 #define vVW510024_E_FRAME_TYPE_OFF 28
478 #define vVW510024_E_L4ID_OFF 32
479 #define vVW510024_E_IPLEN_OFF 34
480 #define vVW510024_E_FLOWSEQ_OFF 36 /* offset of signature sequence number */
481 #define vVW510024_E_FLOWID_OFF 37 /* offset of flow ID */
482 #define vVW510024_E_LATVAL_OFF 40 /* offset of delay/flowtimestamp, 32 bits */
483 #define vVW510024_E_FPGA_VERSION_OFF 20 /* offset of fpga version, 16 bits */
484 #define vVW510024_E_MATCH_OFF 51 /* offset of pattern match vector */
486 /* offsets in the header block */
487 #define vVW510024_E_HEADER_LEN vVW510021_W_HEADER_LEN /* length of FRAME header */
488 #define vVW510024_E_RXTX_OFF vVW510021_W_RXTX_OFF /* rxtx offset, cmd byte */
489 #define vVW510024_E_HEADER_VERSION_OFF 16 /* version, 2bytes */
490 #define vVW510024_E_MSG_LENGTH_OFF vVW510021_MSG_LENGTH_OFF /* MSG LENGTH, 2bytes */
491 #define vVW510024_E_DEVICE_TYPE_OFF vVW510021_W_DEVICE_TYPE_OFF /* Device Type, 2bytes */
493 /* Masks and defines */
494 #define vVW510024_E_IS_BV 0x80 /* Bm bit in STATS block */
495 #define vVW510024_E_IS_CV 0x40 /* cV bit in STATS block */
496 #define vVW510024_E_FLOW_VALID 0x8000 /* valid_off flow-is-valid flag (else force to 0) */
497 #define vVW510024_E_QOS_VALID 0x0000 /** not valid for ethernet **/
498 #define vVW510024_E_L4ID_VALID 0x1000
499 #define vVW510024_E_CBW_MASK 0xC0
500 #define vVW510024_E_VCID_MASK 0x3FFF
502 #define vVW510024_E_HEADER_IS_RX 0x21
503 #define vVW510024_E_HEADER_IS_TX 0x31
505 #define vVW510024_E_IS_TCP 0x01000000 /* TCP bit in FRAME_TYPE field */
506 #define vVW510024_E_IS_UDP 0x00100000 /* UDP bit in FRAME_TYPE field */
507 #define vVW510024_E_IS_ICMP 0x00001000 /* ICMP bit in FRAME_TYPE field */
508 #define vVW510024_E_IS_IGMP 0x00010000
509 #define vVW510024_E_IS_VLAN 0x4000
511 #define vVW510024_E_HEADER_VERSION 0x00
512 #define vVW510024_E_DEVICE_TYPE 0x18
513 #define vVW510024_E_FPGA_VERSION 0x0001
515 #define FPGA_VER_NOT_APPLICABLE 0
517 #define UNKNOWN_FPGA 0
520 #define vVW510012_E_FPGA 3
521 #define vVW510024_E_FPGA 4
524 /* the flow signature is:
526 0 Magic Number (0xDD)
527 1 Chassis Number[7:0]
533 7 Flow Sequence Number[7:0]
544 #define SIG_SIZE 16 /* size of signature field, bytes */
545 #define SIG_FID_OFF 4 /* offset of flow ID in signature */
546 #define SIG_FSQ_OFF 7 /* offset of flow seqnum in signature */
547 #define SIG_TS_OFF 8 /* offset of flow seqnum in signature */
551 /*--------------------------------------------------------------------------------------*/
552 /* Per-capture file private data structure */
555 /* offsets in stats block; these are dependent on the frame type (Ethernet/WLAN) and */
556 /* version number of .vwr file, and are set up by setup_defaults() */
557 guint32 STATS_LEN
; /* length of stats block trailer */
558 guint32 STATS_START_OFF
; /* STATS OFF AFTER HEADER */
559 guint32 VALID_OFF
; /* bit 6 (0x40) is flow-is-valid flag */
560 guint32 MTYPE_OFF
; /* offset of modulation type */
561 guint32 VCID_OFF
; /* offset of VC ID */
562 guint32 FLOWSEQ_OFF
; /* offset of signature sequence number */
563 guint32 FLOWID_OFF
; /* offset of flow ID */
564 guint32 OCTET_OFF
; /* offset of octets */
565 guint32 ERRORS_OFF
; /* offset of error vector */
566 guint32 PATN_OFF
; /* offset of pattern match vector */
567 guint32 RSSI_OFF
; /* RSSI (NOTE: RSSI must be negated!) */
568 guint32 STARTT_OFF
; /* offset of start time, 64 bits */
569 guint32 ENDT_OFF
; /* offset of end time, 64 bits */
570 guint32 LATVAL_OFF
; /* offset of latency, 32 bits */
571 guint32 INFO_OFF
; /* offset of INFO field, 16 bits */
572 guint32 L1P_1_OFF
; /* offset 1ST Byte of l1params */
573 guint32 L1P_2_OFF
; /* offset 2nd Byte of l1params */
574 guint32 L4ID_OFF
; /* LAYER 4 id offset*/
575 guint32 IPLEN_OFF
; /* */
576 guint32 PLCP_LENGTH_OFF
; /* plcp length offset*/
577 guint32 FPGA_VERSION_OFF
; /* offset of fpga version field, 16 bits */
578 guint32 HEADER_VERSION_OFF
; /* offset of header version, 16 bits */
579 guint32 RXTX_OFF
; /* offset of CMD bit, rx or tx */
580 guint32 FRAME_TYPE_OFF
;
582 /* other information about the file in question */
583 guint32 MT_10_HALF
; /* 10 Mb/s half-duplex */
584 guint32 MT_10_FULL
; /* 10 Mb/s full-duplex */
585 guint32 MT_100_HALF
; /* 100 Mb/s half-duplex */
586 guint32 MT_100_FULL
; /* 100 Mb/s full-duplex */
587 guint32 MT_1G_HALF
; /* 1 Gb/s half-duplex */
588 guint32 MT_1G_FULL
; /* 1 Gb/s full-duplex */
589 guint32 FCS_ERROR
; /* FCS error in frame */
590 guint32 CRYPTO_ERR
; /* RX decrypt error flags */
591 guint32 PAYCHK_ERR
; /* payload checksum failure */
592 guint32 RETRY_ERR
; /* excessive retries on TX failure */
593 guint8 IS_RX
; /* TX/RX bit in STATS block */
594 guint8 MT_MASK
; /* modulation type mask */
595 guint16 VCID_MASK
; /* VC ID is only 9 bits */
596 guint32 FLOW_VALID
; /* flow-is-valid flag (else force to 0) */
598 guint32 RX_DECRYPTS
; /* RX-frame-was-decrypted bits */
599 guint32 TX_DECRYPTS
; /* TX-frame-was-decrypted bits */
600 guint32 FC_PROT_BIT
; /* Protected Frame bit in FC1 of frame */
601 guint32 MT_CCKL
; /* CCK modulation, long preamble */
602 guint32 MT_CCKS
; /* CCK modulation, short preamble */
603 guint32 MT_OFDM
; /* OFDM modulation */
604 guint32 MCS_INDEX_MASK
; /* mcs index type mask */
605 guint32 FPGA_VERSION
;
606 guint32 HEADER_IS_RX
;
607 guint32 HEADER_IS_TX
;
608 guint32 WEPTYPE
; /* frame is WEP */
609 guint32 TKIPTYPE
; /* frame is TKIP */
610 guint32 CCMPTYPE
; /* frame is CCMP */
620 /* internal utility functions */
621 static int decode_msg(vwr_t
*vwr
, register guint8
*, int *, int *);
622 static guint8
get_ofdm_rate(guint8
*);
623 static guint8
get_cck_rate(guint8
*plcp
);
624 static void setup_defaults(vwr_t
*, guint16
);
626 static gboolean
vwr_read(wtap
*, int *, gchar
**, gint64
*);
627 static gboolean
vwr_seek_read(wtap
*, gint64
, struct wtap_pkthdr
*phdr
,
628 Buffer
*, int, int *, gchar
**);
630 static gboolean
vwr_read_rec_header(vwr_t
*, FILE_T
, int *, int *, int *, gchar
**);
631 static gboolean
vwr_process_rec_data(wtap
*wth
, FILE_T fh
, int rec_size
,
633 vwr_t
*vwr
, int IS_TX
, int *err
,
635 static void vwr_read_rec_data_wlan(wtap
*, guint8
*, guint8
*, int, int);
637 static int vwr_get_fpga_version(wtap
*, int *, gchar
**);
639 static int parse_s1_W_stats(wtap
*, guint8
*, int , ext_rtap_fields
*, stats_common_fields
*);
640 static int parse_s2_W_stats(wtap
*, guint8
*, int , ext_rtap_fields
*, stats_common_fields
*, int);
641 static void vwr_read_rec_data_ethernet(wtap
*, guint8
*, guint8
*, int, int);
643 static int find_signature(register guint8
*, int, int, register guint32
, register guint8
);
644 static guint64
get_signature_ts(register guint8
*, int);
645 static float getRate( guint8 plcpType
, guint8 mcsIndex
, guint16 rflags
, guint8 nss
);
647 /* Open a .vwr file for reading */
648 /* This does very little, except setting the wiretap header for a VWR file type */
649 /* and setting the timestamp precision to microseconds. */
651 int vwr_open(wtap
*wth
, int *err
, gchar
**err_info
)
658 fpgaVer
= vwr_get_fpga_version(wth
, err
, err_info
);
660 return -1; /* I/O error */
662 if (fpgaVer
== UNKNOWN_FPGA
) {
663 return 0; /* not a VWR file */
666 /* This is a vwr file */
667 vwr
= (vwr_t
*)g_malloc0(sizeof(vwr_t
));
668 wth
->priv
= (void *)vwr
;
670 vwr
->FPGA_VERSION
= fpgaVer
;
671 /* set the local module options first */
672 setup_defaults(vwr
, fpgaVer
);
674 wth
->snapshot_length
= 0;
675 wth
->subtype_read
= vwr_read
;
676 wth
->subtype_seek_read
= vwr_seek_read
;
677 wth
->tsprecision
= WTAP_FILE_TSPREC_USEC
;
678 wth
->file_encap
= WTAP_ENCAP_IXVERIWAVE
;
680 if (fpgaVer
== S2_W_FPGA
|| fpgaVer
== S1_W_FPGA
|| fpgaVer
== S3_W_FPGA
)
681 wth
->file_type_subtype
= WTAP_FILE_TYPE_SUBTYPE_VWR_80211
;
682 else if (fpgaVer
== vVW510012_E_FPGA
|| fpgaVer
== vVW510024_E_FPGA
)
683 wth
->file_type_subtype
= WTAP_FILE_TYPE_SUBTYPE_VWR_ETH
;
689 /* Read the next packet */
690 /* Note that the VWR file format consists of a sequence of fixed 16-byte record headers of */
691 /* different types; some types, including frame record headers, are followed by */
692 /* variable-length data. */
693 /* A frame record consists of: the above 16-byte record header, a 1-16384 byte raw PLCP */
694 /* frame, and a 64-byte statistics block trailer. */
695 /* The PLCP frame consists of a 4-byte or 6-byte PLCP header, followed by the MAC frame */
697 static gboolean
vwr_read(wtap
*wth
, int *err
, gchar
**err_info
, gint64
*data_offset
)
699 vwr_t
*vwr
= (vwr_t
*)wth
->priv
;
700 int rec_size
= 0, IS_TX
;
702 /* read the next frame record header in the capture file; if no more frames, return */
703 if (!vwr_read_rec_header(vwr
, wth
->fh
, &rec_size
, &IS_TX
, err
, err_info
))
704 return FALSE
; /* Read error or EOF */
706 *data_offset
= (file_tell(wth
->fh
) - 16); /* set offset for random seek @PLCP */
708 /* got a frame record; read and process it */
709 if (!vwr_process_rec_data(wth
, wth
->fh
, rec_size
,
710 wth
->frame_buffer
, vwr
, IS_TX
, err
, err_info
))
713 /* If the per-file encapsulation isn't known, set it to this packet's encapsulation. */
714 /* If it *is* known, and it isn't this packet's encapsulation, set it to */
715 /* WTAP_ENCAP_PER_PACKET, as this file doesn't have a single encapsulation for all */
716 /* packets in the file. */
717 if (wth
->file_encap
== WTAP_ENCAP_UNKNOWN
)
718 wth
->file_encap
= wth
->phdr
.pkt_encap
;
720 if (wth
->file_encap
!= wth
->phdr
.pkt_encap
)
721 wth
->file_encap
= WTAP_ENCAP_PER_PACKET
;
727 /* read a random frame in the middle of a file; the start of the PLCP frame is @ seek_off */
729 static gboolean
vwr_seek_read(wtap
*wth
, gint64 seek_off
,
730 struct wtap_pkthdr
*phdr _U_
, Buffer
*buf
, int pkt_size _U_
,
731 int *err
, gchar
**err_info
)
733 vwr_t
*vwr
= (vwr_t
*)wth
->priv
;
736 /* first seek to the indicated record header */
737 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
740 /* read in the record header */
741 if (!vwr_read_rec_header(vwr
, wth
->random_fh
, &rec_size
, &IS_TX
, err
, err_info
))
742 return FALSE
; /* Read error or EOF */
744 return vwr_process_rec_data(wth
, wth
->random_fh
, rec_size
, buf
,
745 vwr
, IS_TX
, err
, err_info
);
748 /* Scan down in the input capture file to find the next frame header. */
749 /* Decode and skip over all non-frame messages that are in the way. */
750 /* Return TRUE on success, FALSE on EOF or error. */
751 /* Also return the frame size in bytes and the "is transmitted frame" flag. */
753 static gboolean
vwr_read_rec_header(vwr_t
*vwr
, FILE_T fh
, int *rec_size
, int *IS_TX
, int *err
, gchar
**err_info
)
758 errno
= WTAP_ERR_CANT_READ
;
761 /* Read out the file data in 16-byte messages, stopping either after we find a frame, */
762 /* or if we run out of data. */
763 /* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
764 /* variable-length item, we read the variable length item out and discard it. */
765 /* If we find a frame, we return (with the header in the passed buffer). */
767 if (file_read(header
, 16, fh
) != 16) {
768 *err
= file_error(fh
, err_info
);
772 /* Got a header; invoke decode-message function to parse and process it. */
773 /* If the function returns a length, then a frame or variable-length message */
774 /* follows the 16-byte message. */
775 /* If the variable length message is not a frame, simply skip over it. */
776 if ((f_len
= decode_msg(vwr
, header
, &v_type
, IS_TX
)) != 0) {
777 if (f_len
> B_SIZE
) {
778 *err
= WTAP_ERR_BAD_FILE
;
779 *err_info
= g_strdup_printf("vwr: Invalid message record length %d", f_len
);
782 else if (v_type
!= VT_FRAME
) {
783 if (file_seek(fh
, f_len
, SEEK_CUR
, err
) < 0)
794 /* Figure out the FPGA version (and also see whether this is a VWR file type. */
795 /* Return FPGA version if it's a known version, UNKNOWN_FPGA if it's not, */
796 /* and -1 on an I/O error. */
798 static int vwr_get_fpga_version(wtap
*wth
, int *err
, gchar
**err_info
)
800 guint8 rec
[B_SIZE
]; /* local buffer (holds input record) */
804 guint8
*s_510006_ptr
= NULL
;
805 guint8
*s_510024_ptr
= NULL
;
806 guint8
*s_510012_ptr
= NULL
; /* stats pointers */
808 guint32 frame_type
= 0;
810 guint16 data_length
= 0;
811 guint16 fpga_version
;
813 filePos
= file_tell(wth
->fh
);
815 *err
= file_error(wth
->fh
, err_info
);
820 /* Got a frame record; see if it is vwr */
821 /* If we don't get it all, then declare an error, we can't process the frame. */
822 /* Read out the file data in 16-byte messages, stopping either after we find a frame, */
823 /* or if we run out of data. */
824 /* Each 16-byte message is decoded; if we run across a non-frame message followed by a */
825 /* variable-length item, we read the variable length item out and discard it. */
826 /* If we find a frame, we return (with the header in the passed buffer). */
827 while ((file_read(header
, 16, wth
->fh
)) == 16) {
828 /* Got a header; invoke decode-message function to parse and process it. */
829 /* If the function returns a length, then a frame or variable-length message */
830 /* follows the 16-byte message. */
831 /* If the variable length message is not a frame, simply skip over it. */
832 if ((f_len
= decode_msg(NULL
, header
, &v_type
, NULL
)) != 0) {
833 if (f_len
> B_SIZE
) {
834 /* Treat this here as an indication that the file probably */
835 /* isn't a vwr file. */
838 else if (v_type
!= VT_FRAME
) {
839 if (file_seek(wth
->fh
, f_len
, SEEK_CUR
, err
) < 0)
844 /* Got a frame record; read over entire record (frame + trailer) into a local buffer */
845 /* If we don't get it all, assume this isn't a vwr file */
846 if (file_read(rec
, rec_size
, wth
->fh
) != rec_size
) {
847 *err
= file_error(wth
->fh
, err_info
);
848 if (*err
!= 0 && *err
!= WTAP_ERR_SHORT_READ
)
850 return UNKNOWN_FPGA
; /* short read - not a vwr file */
854 /* I'll grab the bytes where the Ethernet "octets" field should be and the bytes where */
855 /* the 802.11 "octets" field should be. Then if I do rec_size - octets - */
856 /* size_of_stats_block and it's 0, I can select the correct type. */
857 /* octets + stats_len = rec_size only when octets have been incremented to nearest */
858 /* number divisible by 4. */
860 /* First check for series I WLAN since the check is more rigorous. */
861 if (rec_size
> v22_W_STATS_LEN
) {
862 s_510006_ptr
= &(rec
[rec_size
- v22_W_STATS_LEN
]); /* point to 510006 WLAN */
865 data_length
= pntohs(&s_510006_ptr
[v22_W_OCTET_OFF
]);
867 while (((data_length
+ i
) % 4) != 0)
870 frame_type
= pntohl(&s_510006_ptr
[v22_W_FRAME_TYPE_OFF
]);
872 if (rec_size
== (data_length
+ v22_W_STATS_LEN
+ i
) && (frame_type
& v22_W_IS_80211
) == 0x1000000) {
873 fpga_version
= S1_W_FPGA
;
877 /* Next for the series I Ethernet */
878 if ((rec_size
> v22_E_STATS_LEN
) && (fpga_version
== 1000)) {
879 s_510012_ptr
= &(rec
[rec_size
- v22_E_STATS_LEN
]); /* point to 510012 enet */
881 data_length
= pntohs(&s_510012_ptr
[v22_E_OCTET_OFF
]);
883 while (((data_length
+ i
) % 4) != 0)
886 if (rec_size
== (data_length
+ v22_E_STATS_LEN
+ i
))
887 fpga_version
= vVW510012_E_FPGA
;
891 /* Next the series II WLAN */
892 if ((rec_size
> vVW510021_W_STATS_LEN
) && (fpga_version
== 1000)) {
895 data_length
= (256 * (rec
[vVW510021_W_MSDU_LENGTH_OFF
+ 1] & 0x1f)) + rec
[vVW510021_W_MSDU_LENGTH_OFF
];
898 while (((data_length
+ i
) % 4) != 0)
901 /*the 12 is from the 12 bytes of plcp header */
902 if (rec_size
== (data_length
+ vVW510021_W_STATS_LEN
+vVW510021_W_AFTERHEADER_LEN
+12+i
))
903 fpga_version
= S2_W_FPGA
;
906 /* Finally the Series II Ethernet */
907 if ((rec_size
> vVW510024_E_STATS_LEN
) && (fpga_version
== 1000)) {
908 s_510024_ptr
= &(rec
[rec_size
- vVW510024_E_STATS_LEN
]); /* point to 510024 ENET */
909 data_length
= pntohs(&s_510024_ptr
[vVW510024_E_MSDU_LENGTH_OFF
]);
912 while (((data_length
+ i
) % 4) != 0)
915 if (rec_size
== (data_length
+ vVW510024_E_STATS_LEN
+ i
))
916 fpga_version
= vVW510024_E_FPGA
;
918 if ((rec_size
> vVW510021_W_STATS_LEN
) && (fpga_version
== 1000)) {
919 /* Check the version of the FPGA */
921 fpga_version
= S3_W_FPGA
;
923 if ((rec_size
> vVW510021_W_STATS_LEN
) && (fpga_version
== 1000)) {
924 /* Check the version of the FPGA */
926 fpga_version
= S3_W_FPGA
;
928 if (fpga_version
!= 1000)
930 /* reset the file position offset */
931 if (file_seek (wth
->fh
, filePos
, SEEK_SET
, err
) == -1) {
934 /* We found an FPGA that works */
941 *err
= file_error(wth
->fh
, err_info
);
942 if (*err
!= 0 && *err
!= WTAP_ERR_SHORT_READ
)
944 return UNKNOWN_FPGA
; /* short read - not a vwr file */
947 /* Copy the actual packet data from the capture file into the target data block. */
948 /* The packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
951 static void vwr_read_rec_data_wlan(wtap
*wth
, guint8
*data_ptr
, guint8
*rec
, int rec_size
, int IS_TX
)
953 vwr_t
*vwr
= (vwr_t
*)wth
->priv
;
954 int bytes_written
= 0; /* bytes output to buf so far */
955 ext_rtap_fields er_fields
; /* extended radiotap fields */
956 stats_common_fields common_fields
; /* extended radiotap fields */
959 /* Parse the stats block and fill the common and er structs */
960 switch (vwr
->FPGA_VERSION
) {
962 mpdu_offset
= parse_s1_W_stats(wth
, rec
, rec_size
, &er_fields
, &common_fields
);
966 mpdu_offset
= parse_s2_W_stats(wth
, rec
, rec_size
, &er_fields
, &common_fields
, IS_TX
);
972 /* put common_fields into the packet buffer in little-endian byte order */
973 phtoles(&data_ptr
[bytes_written
], common_fields
.vw_port_type
);
975 phtoles(&data_ptr
[bytes_written
], common_fields
.it_len
);
977 phtoles(&data_ptr
[bytes_written
], common_fields
.vw_msdu_length
);
980 phtolel(&data_ptr
[bytes_written
], common_fields
.vw_flowid
);
982 phtoles(&data_ptr
[bytes_written
], common_fields
.vw_vcid
);
984 phtoles(&data_ptr
[bytes_written
], common_fields
.vw_seqnum
);
986 phtolel(&data_ptr
[bytes_written
], common_fields
.vw_latency
);
988 phtolel(&data_ptr
[bytes_written
], common_fields
.vw_sig_ts
);
990 phtolell(&data_ptr
[bytes_written
], common_fields
.vw_startt
);
992 phtolell(&data_ptr
[bytes_written
], common_fields
.vw_endt
);
994 phtolel(&data_ptr
[bytes_written
], common_fields
.vw_pktdur
);
997 /* put er_fields into the packet buffer in little-endian byte order */
998 phtoles(&data_ptr
[bytes_written
], er_fields
.it_len
);
1000 phtoles(&data_ptr
[bytes_written
], er_fields
.flags
);
1002 phtoles(&data_ptr
[bytes_written
], er_fields
.chanflags
);
1004 phtoles(&data_ptr
[bytes_written
], er_fields
.phyRate
);
1006 data_ptr
[bytes_written
] = er_fields
.plcpType
;
1008 data_ptr
[bytes_written
] = er_fields
.mcsIndex
;
1010 data_ptr
[bytes_written
] = er_fields
.nss
;
1012 data_ptr
[bytes_written
] = er_fields
.signal
;
1014 /* antennae b, c, d signal power */
1015 data_ptr
[bytes_written
] = er_fields
.signalb
;
1017 data_ptr
[bytes_written
] = er_fields
.signalc
;
1019 data_ptr
[bytes_written
] = er_fields
.signald
;
1022 data_ptr
[bytes_written
] = 0;
1024 phtoles(&data_ptr
[bytes_written
], er_fields
.vw_flags
);
1026 phtoles(&data_ptr
[bytes_written
], er_fields
.vw_ht_length
);
1028 phtoles(&data_ptr
[bytes_written
], er_fields
.vw_info
);
1030 phtolel(&data_ptr
[bytes_written
], er_fields
.vw_errors
);
1033 /* finally, copy the whole MAC frame to the packet buffer as-is; exclude 4-byte FCS */
1034 if ( rec_size
< ((int)common_fields
.vw_msdu_length
+ (int)vwr
->STATS_LEN
) )
1035 /*something's been truncated, DUMP AS-IS*/
1036 memcpy(&data_ptr
[bytes_written
], &rec
[mpdu_offset
], common_fields
.vw_msdu_length
);
1037 else if (common_fields
.vw_msdu_length
>= 4)
1038 memcpy(&data_ptr
[bytes_written
], &rec
[mpdu_offset
], common_fields
.vw_msdu_length
- 4);
1040 memcpy(&data_ptr
[bytes_written
], &rec
[mpdu_offset
], common_fields
.vw_msdu_length
);
1044 static int parse_s1_W_stats(wtap
*wth
, guint8
*rec
, int rec_size
, ext_rtap_fields
* er_fields
, stats_common_fields
* common_fields
)
1046 vwr_t
*vwr
= (vwr_t
*)wth
->priv
;
1047 register int i
; /* temps */
1048 register guint8
*s_ptr
, *m_ptr
; /* stats pointer */
1049 guint16 octets
, msdu_length
; /* octets in frame */
1052 guint8 m_type
, flow_seq
; /* mod type (CCK-L/CCK-S/OFDM), seqnum */
1053 guint64 s_time
= LL_ZERO
, e_time
= LL_ZERO
; /* start/end */
1056 guint64 start_time
, s_sec
, s_usec
= LL_ZERO
; /* start time, sec + usec */
1057 guint64 end_time
; /* end time */
1058 guint32 info
; /* INFO/ERRORS fields in stats blk */
1059 gint16 rssi
; /* RSSI, signed 16-bit number */
1060 int f_tx
; /* flag: if set, is a TX frame */
1061 guint8 plcp_type
, mcs_index
, nss
; /* PLCP type 0: Legacy, 1: Mixed, 2: Green field, 3: VHT Mixed */
1062 guint16 vc_id
, flow_id
, ht_len
=0; /* VC ID, flow ID, total ip length */
1063 guint32 d_time
, errors
; /* packet duration & errors */
1064 guint16 r_hdr_len
; /* length of radiotap headers */
1065 int sig_off
, pay_off
; /* MAC+SNAP header len, signature offset */
1066 guint64 sig_ts
; /* 32 LSBs of timestamp in signature */
1073 /* Calculate the start of the statistics block in the buffer */
1074 /* Also get a bunch of fields from the stats block */
1075 s_ptr
= &(rec
[rec_size
- 64]); /* point to it */
1076 m_type
= s_ptr
[1] & 0x7;
1077 f_tx
= !(s_ptr
[1] & 0x8);
1078 octets
= pntohs(&s_ptr
[8]);
1079 vc_id
= pntohs(&s_ptr
[2]) & 0x3ff;
1080 flow_seq
= s_ptr
[4];
1082 /* XXX - this is 48 bits, in a weird byte order */
1083 latency
= (s_ptr
[40 + 6] << 8) | (s_ptr
[40 + 7]); /* latency MSbytes */
1084 for (i
= 0; i
< 4; i
++)
1085 latency
= (latency
<< 8) | s_ptr
[40 + i
];
1087 flow_id
= pntohs(&s_ptr
[6]); /* only 16 LSBs kept */
1088 errors
= pntohs(&s_ptr
[10]);
1090 info
= pntohs(&s_ptr
[54]);
1091 rssi
= (s_ptr
[21] & 0x80) ? (-1 * (s_ptr
[21] & 0x7f)) : s_ptr
[21];
1093 /* Decode OFDM or CCK PLCP header and determine rate and short preamble flag. */
1094 /* The SIGNAL byte is always the first byte of the PLCP header in the frame. */
1097 if (m_type
== vwr
->MT_OFDM
)
1098 mcs_index
= get_ofdm_rate(rec
);
1099 else if ((m_type
== vwr
->MT_CCKL
) || (m_type
== vwr
->MT_CCKS
))
1100 mcs_index
= get_cck_rate(rec
);
1103 rflags
= (m_type
== vwr
->MT_CCKS
) ? RADIOTAP_F_SHORTPRE
: 0;
1104 phyRate
= getRate(plcp_type
, mcs_index
, rflags
, nss
);
1105 /* Calculate the MPDU size/ptr stuff; MPDU starts at 4 or 6 depending on OFDM/CCK. */
1106 /* Note that the number of octets in the frame also varies depending on OFDM/CCK, */
1107 /* because the PLCP header is prepended to the actual MPDU. */
1108 m_ptr
= &(rec
[((m_type
== vwr
->MT_OFDM
) ? 4 : 6)]);
1109 tmp_len
= (m_type
== vwr
->MT_OFDM
) ? 4 : 6;
1110 if (octets
>= tmp_len
)
1111 octets
-= (guint16
) tmp_len
;
1115 /* Sanity check the octets field to determine if it is OK (or segfaults result). */
1116 /* ff it's greater, then truncate to actual record size. */
1117 if (octets
> (rec_size
- 64))
1118 octets
= (rec_size
- 64);
1119 msdu_length
= octets
;
1122 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1123 /* 64-bit times are "Corey-endian" */
1124 s_time
= pcoreytohll(&s_ptr
[24]);
1125 e_time
= pcoreytohll(&s_ptr
[32]);
1127 /* find the packet duration (difference between start and end times) */
1128 d_time
= (guint32
)((e_time
- s_time
) / NS_IN_US
); /* find diff, converting to usec */
1130 /* also convert the packet start time to seconds and microseconds */
1131 start_time
= s_time
/ NS_IN_US
; /* convert to microseconds first */
1132 s_sec
= (start_time
/ US_IN_SEC
); /* get the number of seconds */
1133 s_usec
= start_time
- (s_sec
* US_IN_SEC
); /* get the number of microseconds */
1135 /* also convert the packet end time to seconds and microseconds */
1136 end_time
= e_time
/ NS_IN_US
; /* convert to microseconds first */
1138 /* extract the 32 LSBs of the signature timestamp field from the data block*/
1139 pay_off
= 42; /* 24 (MAC) + 8 (SNAP) + IP */
1140 sig_off
= find_signature(m_ptr
, rec_size
- 6, pay_off
, flow_id
, flow_seq
);
1141 if ((m_ptr
[sig_off
] == 0xdd) && (sig_off
+ 15 <= (rec_size
- 48)))
1142 sig_ts
= get_signature_ts(m_ptr
, sig_off
);
1146 /* Pack the common and er structs) */
1147 r_hdr_len
= STATS_COMMON_FIELDS_LEN
+ EXT_RTAP_FIELDS_LEN
;
1149 tmp_len
= (msdu_length
- 4) + r_hdr_len
;
1150 wth
->phdr
.len
= tmp_len
<=G_MAXUINT32
? (guint32
) tmp_len
: 0;
1151 tmp_len
= (octets
- 4) + r_hdr_len
;
1152 wth
->phdr
.caplen
= tmp_len
<=G_MAXUINT32
? (guint32
) tmp_len
: 0;
1154 wth
->phdr
.len
= (msdu_length
- 4) + r_hdr_len
;
1155 wth
->phdr
.caplen
= (octets
- 4) + r_hdr_len
;
1157 wth
->phdr
.presence_flags
= WTAP_HAS_TS
;
1159 wth
->phdr
.ts
.secs
= (time_t)s_sec
;
1160 wth
->phdr
.ts
.nsecs
= (int)(s_usec
* 1000);
1161 wth
->phdr
.pkt_encap
= WTAP_ENCAP_IXVERIWAVE
;
1163 /* generate and copy out the radiotap header, set the port type to 0 (WLAN) */
1164 common_fields
->vw_port_type
= 0;
1165 common_fields
->it_len
= STATS_COMMON_FIELDS_LEN
;
1166 common_fields
->vw_vcid
= (guint16
)vc_id
;
1167 common_fields
->vw_flowid
= (guint16
)flow_id
;
1168 common_fields
->vw_seqnum
= (guint16
)flow_seq
;
1169 if (!f_tx
&& sig_ts
!= 0)
1170 common_fields
->vw_latency
= (guint32
)latency
;
1172 common_fields
->vw_latency
= 0;
1173 common_fields
->vw_pktdur
= (guint32
)d_time
;
1174 common_fields
->vw_msdu_length
= (guint16
)msdu_length
;
1175 common_fields
->vw_sig_ts
= (guint32
)sig_ts
; /* 32 LSBs of signature timestamp (nsec) */
1176 common_fields
->vw_startt
= start_time
; /* record start & end times of frame */
1177 common_fields
->vw_endt
= end_time
;
1179 er_fields
->it_len
= EXT_RTAP_FIELDS_LEN
;
1180 er_fields
->flags
= rflags
;
1181 er_fields
->phyRate
= (guint16
)(phyRate
* 10);
1182 er_fields
->plcpType
= plcp_type
;
1183 er_fields
->mcsIndex
= mcs_index
;
1184 er_fields
->nss
= nss
;
1185 er_fields
->chanflags
= (m_type
== vwr
->MT_OFDM
) ? CHAN_OFDM
: CHAN_CCK
;
1186 er_fields
->signal
= (gint8
)rssi
;
1187 er_fields
->signalb
= 100;
1188 er_fields
->signalc
= 100;
1189 er_fields
->signald
= 100;
1191 /* fill in the VeriWave flags field */
1192 er_fields
->vw_flags
= 0;
1194 er_fields
->vw_flags
|= RADIOTAP_VWF_TXF
;
1195 if (errors
& vwr
->FCS_ERROR
)
1196 er_fields
->vw_flags
|= RADIOTAP_VWF_FCSERR
;
1197 if (!f_tx
&& (errors
& vwr
->CRYPTO_ERR
))
1198 er_fields
->vw_flags
|= RADIOTAP_VWF_DCRERR
;
1199 if (!f_tx
&& (errors
& vwr
->RETRY_ERR
))
1200 er_fields
->vw_flags
|= RADIOTAP_VWF_RETRERR
;
1201 if (info
& vwr
->WEPTYPE
)
1202 er_fields
->vw_flags
|= RADIOTAP_VWF_IS_WEP
;
1203 else if (info
& vwr
->TKIPTYPE
)
1204 er_fields
->vw_flags
|= RADIOTAP_VWF_IS_TKIP
;
1205 else if (info
& vwr
->CCMPTYPE
)
1206 er_fields
->vw_flags
|= RADIOTAP_VWF_IS_CCMP
;
1207 er_fields
->vw_errors
= (guint32
)errors
;
1208 er_fields
->vw_info
= (guint16
)info
;
1209 er_fields
->vw_ht_length
= (guint16
)ht_len
;
1211 /* return the offset to the actual frame data */
1212 return (m_type
== vwr
->MT_OFDM
) ? 4 : 6;
1216 static int parse_s2_W_stats(wtap
*wth
, guint8
*rec
, int rec_size
, ext_rtap_fields
* er_fields
, stats_common_fields
* common_fields
, int IS_TX
)
1218 vwr_t
*vwr
= (vwr_t
*)wth
->priv
;
1220 register int i
; /* temps */
1221 register guint8
*s_start_ptr
,*s_trail_ptr
, *plcp_ptr
, *m_ptr
; /* stats & MPDU ptr */
1223 guint32 msdu_length
, actual_octets
; /* octets in frame */
1225 guint8 l1p_1
,l1p_2
, flow_seq
, plcp_type
, mcs_index
, nss
; /* mod (CCK-L/CCK-S/OFDM) */
1226 guint64 s_time
= LL_ZERO
, e_time
= LL_ZERO
; /* start/end */
1228 guint64 latency
= LL_ZERO
;
1229 guint64 start_time
, s_sec
, s_usec
= LL_ZERO
; /* start time, sec + usec */
1230 guint64 end_time
; /* end time */
1231 guint16 info
; /* INFO/ERRORS fields in stats blk */
1233 gint16 rssi
[] = {0,0,0,0}; /* RSSI, signed 16-bit number */
1234 int f_tx
; /* flag: if set, is a TX frame */
1235 guint16 vc_id
, ht_len
=0; /* VC ID , total ip length*/
1236 guint32 flow_id
, d_time
; /* flow ID, packet duration*/
1237 guint16 r_hdr_len
; /* length of radiotap headers */
1238 int sig_off
, pay_off
; /* MAC+SNAP header len, signature offset */
1239 guint64 sig_ts
, tsid
; /* 32 LSBs of timestamp in signature */
1240 guint16 chanflags
= 0; /* extended radio tap channel flags */
1241 guint16 radioflags
= 0; /* extended radio tap flags */
1242 guint64 delta_b
; /* Used for calculating latency */
1248 /* Calculate the start of the statistics block in the buffer */
1249 /* Also get a bunch of fields from the stats block */
1250 s_start_ptr
= &(rec
[0]);
1251 s_trail_ptr
= &(rec
[rec_size
- 48]); /* point to it */
1253 /* L1p info is different for series III and for Series II - need to check */
1254 l1p_1
= s_start_ptr
[0];
1255 l1p_2
= s_start_ptr
[1];
1256 if (vwr
->FPGA_VERSION
== S2_W_FPGA
)
1258 mcs_index
= l1p_1
& 0x3f;
1259 plcp_type
= l1p_2
& 0x03;
1260 /* we do the range checks at the end before copying the values
1261 into the wtap header */
1262 msdu_length
= ((s_start_ptr
[4] & 0x1f) << 8) + s_start_ptr
[3];
1263 actual_octets
= msdu_length
;
1265 vc_id
= pntohs(&s_start_ptr
[6]);
1268 rssi
[0] = (s_start_ptr
[2] & 0x80) ? -1 * (s_start_ptr
[2] & 0x7f) : s_start_ptr
[2] & 0x7f;
1272 rssi
[0] = (s_start_ptr
[2] & 0x80) ? (s_start_ptr
[2]- 256) : s_start_ptr
[2];
1279 plcp_ptr
= &(rec
[8]);
1283 plcp_type
= l1p_2
& 0xf;
1284 if (plcp_type
== vVW510021_W_PLCP_VHT_MIXED
)
1286 mcs_index
= l1p_1
& 0x0f;
1287 nss
= (l1p_1
>> 4 & 0x3) + 1; /* The nss is zero based from the fpga - increment it here */
1291 mcs_index
= l1p_1
& 0x3f;
1294 msdu_length
= pntoh24(&s_start_ptr
[9]);
1295 actual_octets
= msdu_length
;
1296 vc_id
= pntohs(&s_start_ptr
[14]) & 0x3ff;
1297 for (i
= 0; i
< 4; i
++)
1301 rssi
[i
] = (s_start_ptr
[4+i
] & 0x80) ? -1 * (s_start_ptr
[4+i
] & 0x7f) : s_start_ptr
[4+i
] & 0x7f;
1305 rssi
[i
] = (s_start_ptr
[4+i
] >= 128) ? (s_start_ptr
[4+i
] - 256) : s_start_ptr
[4+i
];
1308 plcp_ptr
= &(rec
[16]);
1312 flow_seq
= s_trail_ptr
[32];
1314 latency
= 0x00000000; /* clear latency */
1315 flow_id
= pntoh24(&s_trail_ptr
[33]); /* all 24 bits valid */
1316 /* For tx latency is duration, for rx latency is timestamp */
1317 /* Get 48-bit latency value */
1318 tsid
= (s_trail_ptr
[36 + 6] << 8) | (s_trail_ptr
[36 + 7]);
1320 for (i
= 0; i
< 4; i
++)
1321 tsid
= (tsid
<< 8) | s_trail_ptr
[36 + i
];
1323 errors
= pntohl(&s_trail_ptr
[16]);
1324 info
= pntohs(&s_trail_ptr
[22]);
1325 if ((info
& 0xFC00) != 0)
1326 /* this length includes the Start_Spacing + Delimiter + MPDU + Padding for each piece of the aggregate*/
1327 ht_len
= pletohs(&s_start_ptr
[vwr
->PLCP_LENGTH_OFF
]);
1330 /* decode OFDM or CCK PLCP header and determine rate and short preamble flag */
1331 /* the SIGNAL byte is always the first byte of the PLCP header in the frame */
1332 if (plcp_type
== vVW510021_W_PLCP_LEGACY
){
1333 if (mcs_index
< 4) {
1334 chanflags
|= CHAN_CCK
;
1337 chanflags
|= CHAN_OFDM
;
1340 else if (plcp_type
== vVW510021_W_PLCP_MIXED
) {
1341 /* set the appropriate flags to indicate HT mode and CB */
1342 radioflags
|= RADIOTAP_F_CHAN_HT
| ((plcp_ptr
[3] & 0x80) ? RADIOTAP_F_CHAN_40MHZ
: 0) |
1343 ((l1p_1
& 0x40) ? 0 : RADIOTAP_F_CHAN_SHORTGI
);
1344 chanflags
|= CHAN_OFDM
;
1346 else if (plcp_type
== vVW510021_W_PLCP_GREENFIELD
) {
1347 /* set the appropriate flags to indicate HT mode and CB */
1348 radioflags
|= RADIOTAP_F_CHAN_HT
| ((plcp_ptr
[0] & 0x80) ? RADIOTAP_F_CHAN_40MHZ
: 0) |
1349 ((l1p_1
& 0x40) ? 0 : RADIOTAP_F_CHAN_SHORTGI
);
1350 chanflags
|= CHAN_OFDM
;
1352 else if (plcp_type
== vVW510021_W_PLCP_VHT_MIXED
) {
1353 guint8 SBW
= l1p_2
>> 4 & 0xf;
1354 radioflags
|= RADIOTAP_F_CHAN_VHT
| ((l1p_1
& 0x40) ? 0 : RADIOTAP_F_CHAN_SHORTGI
);
1355 chanflags
|= CHAN_OFDM
;
1357 radioflags
|= RADIOTAP_F_CHAN_40MHZ
;
1359 radioflags
|= RADIOTAP_F_CHAN_80MHZ
;
1362 if (msdu_length
> (guint32
)(rec_size
- 48)) {
1363 msdu_length
= (guint32
)(rec_size
- 48);
1366 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1367 /* 64-bit times are "Corey-endian" */
1368 s_time
= pcoreytohll(&s_trail_ptr
[0]);
1369 e_time
= pcoreytohll(&s_trail_ptr
[8]);
1371 /* find the packet duration (difference between start and end times) */
1372 d_time
= (guint32
)((e_time
- s_time
) / NS_IN_US
); /* find diff, converting to usec */
1374 /* also convert the packet start time to seconds and microseconds */
1375 start_time
= s_time
/ NS_IN_US
; /* convert to microseconds first */
1376 s_sec
= (start_time
/ US_IN_SEC
); /* get the number of seconds */
1377 s_usec
= start_time
- (s_sec
* US_IN_SEC
); /* get the number of microseconds */
1379 /* also convert the packet end time to seconds and microseconds */
1380 end_time
= e_time
/ NS_IN_US
; /* convert to microseconds first */
1382 /* extract the 32 LSBs of the signature timestamp field */
1383 m_ptr
= &(rec
[8+12]);
1384 pay_off
= 42; /* 24 (MAC) + 8 (SNAP) + IP */
1385 sig_off
= find_signature(m_ptr
, rec_size
- 20, pay_off
, flow_id
, flow_seq
);
1386 if ((m_ptr
[sig_off
] == 0xdd) && (sig_off
+ 15 <= (rec_size
- 48)))
1387 sig_ts
= get_signature_ts(m_ptr
, sig_off
);
1391 /* Set latency based on rx/tx and signature timestamp */
1393 if (tsid
< s_time
) {
1394 latency
= s_time
- tsid
;
1396 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
1397 /* we look for a large difference between l_time and s_time. */
1398 delta_b
= tsid
- s_time
;
1399 if (delta_b
> 0x10000000)
1406 /* Fill up the per-packet header (amazingly like a PCAP packet header! ;-) */
1407 /* Frames are always 802.11, with an extended radiotap header. */
1408 /* caplen is the length that is captured into the file (i.e., the written-out frame */
1409 /* block), and should always represent the actual number of bytes in the file. */
1410 /* len is the length of the original packet before truncation. */
1411 /* The FCS is NOT included. */
1412 r_hdr_len
= STATS_COMMON_FIELDS_LEN
+ EXT_RTAP_FIELDS_LEN
;
1413 tmp_len
= (actual_octets
- 4) + r_hdr_len
;
1414 wth
->phdr
.len
= tmp_len
<=G_MAXUINT32
? (guint32
) tmp_len
: 0;
1415 tmp_len
= (msdu_length
- 4) + r_hdr_len
;
1416 wth
->phdr
.caplen
= tmp_len
<=G_MAXUINT32
? (guint32
) tmp_len
: 0;
1418 wth
->phdr
.presence_flags
= WTAP_HAS_TS
;
1420 wth
->phdr
.ts
.secs
= (time_t)s_sec
;
1421 wth
->phdr
.ts
.nsecs
= (int)(s_usec
* 1000);
1422 wth
->phdr
.pkt_encap
= WTAP_ENCAP_IXVERIWAVE
;
1424 /* generate and copy out the radiotap header, set the port type to 0 (WLAN) */
1425 common_fields
->vw_port_type
= 0;
1426 common_fields
->it_len
= STATS_COMMON_FIELDS_LEN
;
1427 common_fields
->vw_vcid
= (guint16
)vc_id
;
1428 common_fields
->vw_msdu_length
= (guint16
)msdu_length
;
1429 common_fields
->vw_flowid
= (guint32
)flow_id
;
1430 common_fields
->vw_seqnum
= (guint16
)flow_seq
;
1431 if (!f_tx
&& (sig_ts
!= 0) )
1432 common_fields
->vw_latency
= (guint32
)latency
;
1434 common_fields
->vw_latency
= 0;
1435 common_fields
->vw_pktdur
= (guint32
)d_time
;
1436 common_fields
->vw_startt
= start_time
; /* record start & end times of frame */
1437 common_fields
->vw_endt
= end_time
;
1438 common_fields
->vw_sig_ts
= (guint32
)(sig_ts
); /* 32 LSBs of signature */
1440 er_fields
->it_len
= EXT_RTAP_FIELDS_LEN
;
1441 er_fields
->flags
= radioflags
;
1442 if (info
& vVW510021_W_IS_WEP
)
1443 er_fields
->flags
|= RADIOTAP_F_WEP
;
1444 if ((l1p_1
& vVW510021_W_PREAMBLE_MASK
) != vVW510021_W_IS_LONGPREAMBLE
&& (plcp_type
== vVW510021_W_PLCP_LEGACY
))
1445 er_fields
->flags
|= RADIOTAP_F_SHORTPRE
;
1446 er_fields
->phyRate
= (guint16
)(getRate(plcp_type
, mcs_index
, er_fields
->flags
, nss
) * 10);
1447 er_fields
->plcpType
= plcp_type
;
1448 er_fields
->mcsIndex
= mcs_index
;
1449 er_fields
->nss
= nss
;
1450 er_fields
->chanflags
= chanflags
;
1451 er_fields
->signal
= (gint8
)rssi
[0];
1452 er_fields
->signalb
= (gint8
)rssi
[1];
1453 er_fields
->signalc
= (gint8
)rssi
[2];
1454 er_fields
->signald
= (gint8
)rssi
[3];
1455 /* fill in the VeriWave flags field */
1456 er_fields
->vw_flags
= 0;
1458 er_fields
->vw_flags
|= RADIOTAP_VWF_TXF
;
1459 if (errors
& 0x1f) /* If any error is flagged, then set the FCS error bit */
1460 er_fields
->vw_flags
|= RADIOTAP_VWF_FCSERR
;
1461 if (!f_tx
&& (errors
& vwr
->CRYPTO_ERR
))
1462 er_fields
->vw_flags
|= RADIOTAP_VWF_DCRERR
;
1463 if (!f_tx
&& (errors
& vwr
->RETRY_ERR
))
1464 er_fields
->vw_flags
|= RADIOTAP_VWF_RETRERR
;
1465 if (info
& vwr
->WEPTYPE
)
1466 er_fields
->vw_flags
|= RADIOTAP_VWF_IS_WEP
;
1467 else if (info
& vwr
->TKIPTYPE
)
1468 er_fields
->vw_flags
|= RADIOTAP_VWF_IS_TKIP
;
1469 else if (info
& vwr
->CCMPTYPE
)
1470 er_fields
->vw_flags
|= RADIOTAP_VWF_IS_CCMP
;
1472 er_fields
->vw_errors
= (guint32
)errors
;
1473 er_fields
->vw_ht_length
= (guint16
)ht_len
;
1474 er_fields
->vw_info
= (guint16
)info
;
1476 /* return the offset to the actual frame data */
1477 /* Calculate the MPDU size/ptr stuff; MPDU starts at 4 or 6 depending on OFDM/CCK. */
1478 /* Note that the number of octets in the frame also varies depending on OFDM/CCK */
1479 /* because the PLCP header is prepended to the actual MPDU. */
1480 /* The 8 is from the 8 bytes of stats block that precede the plcps; */
1481 /* the 12 is for 11 bytes plcp and 1 byte of pad before the data. */
1483 return vwr
->MPDU_OFF
;
1486 /* read an Ethernet packet */
1487 /* Copy the actual packet data from the capture file into the target data block. */
1488 /* The packet is constructed as a 38-byte VeriWave-extended Radiotap header plus the raw */
1491 static void vwr_read_rec_data_ethernet(wtap
*wth
, guint8
*data_ptr
, guint8
*rec
, int rec_size
, int IS_TX
)
1493 vwr_t
*vwr
= (vwr_t
*)wth
->priv
;
1494 int bytes_written
= 0; /* bytes output to buf so far */
1495 register int i
; /* temps */
1496 register guint8
*s_ptr
, *m_ptr
; /* stats and MPDU pointers */
1497 guint16 msdu_length
,actual_octets
; /* octets in frame */
1498 guint8 flow_seq
; /* seqnum */
1499 guint64 s_time
= LL_ZERO
, e_time
= LL_ZERO
; /* start/end */
1501 guint32 latency
= 0;
1502 guint64 start_time
, s_sec
, s_usec
= LL_ZERO
; /* start time, sec + usec */
1503 guint64 end_time
; /* end time */
1504 guint16 l4id
, info
, validityBits
; /* INFO/ERRORS fields in stats */
1506 guint16 vc_id
; /* VC ID, total (incl of aggregates) */
1507 guint32 flow_id
, d_time
; /* packet duration */
1508 int f_flow
; /* flags: flow valid */
1509 guint32 frame_type
; /* frame type field */
1510 guint16 e_hdr_len
; /* length of ethernettap headers */
1511 int mac_len
, sig_off
, pay_off
; /* MAC header len, signature offset */
1512 guint64 sig_ts
, tsid
; /* 32 LSBs of timestamp in signature */
1513 guint64 delta_b
; /* Used for calculating latency */
1515 stats_ethernettap_fields etap_hdr
; /* VWR ethernettap header */
1516 stats_common_fields common_hdr
; /* VWR common header */
1518 /* Calculate the start of the statistics block in the buffer. */
1519 /* Also get a bunch of fields from the stats block. */
1520 m_ptr
= &(rec
[0]); /* point to the data block */
1521 s_ptr
= &(rec
[rec_size
- vwr
->STATS_LEN
]); /* point to the stats block */
1523 msdu_length
= pntohs(&s_ptr
[vwr
->OCTET_OFF
]);
1524 actual_octets
= msdu_length
;
1525 /* Sanity check the msdu_length field to determine if it is OK (or segfaults result). */
1526 /* If it's greater, then truncate to the indicated message length. */
1527 if (msdu_length
> (rec_size
- (int)vwr
->STATS_LEN
)) {
1528 msdu_length
= (rec_size
- (int)vwr
->STATS_LEN
);
1531 vc_id
= pntohs(&s_ptr
[vwr
->VCID_OFF
]) & vwr
->VCID_MASK
;
1532 flow_seq
= s_ptr
[vwr
->FLOWSEQ_OFF
];
1533 frame_type
= pntohl(&s_ptr
[vwr
->FRAME_TYPE_OFF
]);
1535 if (vwr
->FPGA_VERSION
== vVW510024_E_FPGA
) {
1536 validityBits
= pntohs(&s_ptr
[vwr
->VALID_OFF
]);
1537 f_flow
= validityBits
& vwr
->FLOW_VALID
;
1539 mac_len
= (validityBits
& vwr
->IS_VLAN
) ? 16 : 14; /* MAC hdr length based on VLAN tag */
1542 errors
= pntohs(&s_ptr
[vwr
->ERRORS_OFF
]);
1545 f_flow
= s_ptr
[vwr
->VALID_OFF
] & vwr
->FLOW_VALID
;
1546 mac_len
= (frame_type
& vwr
->IS_VLAN
) ? 16 : 14; /* MAC hdr length based on VLAN tag */
1549 /* for older fpga errors is only represented by 16 bits) */
1550 errors
= pntohs(&s_ptr
[vwr
->ERRORS_OFF
]);
1553 info
= pntohs(&s_ptr
[vwr
->INFO_OFF
]);
1555 flow_id
= pntoh24(&s_ptr
[vwr
->FLOWID_OFF
]);
1557 /* For tx latency is duration, for rx latency is timestamp. */
1558 /* Get 64-bit latency value. */
1559 tsid
= (s_ptr
[vwr
->LATVAL_OFF
+ 6] << 8) | (s_ptr
[vwr
->LATVAL_OFF
+ 7]);
1560 for (i
= 0; i
< 4; i
++)
1561 tsid
= (tsid
<< 8) | s_ptr
[vwr
->LATVAL_OFF
+ i
];
1564 l4id
= pntohs(&s_ptr
[vwr
->L4ID_OFF
]);
1566 /* Calculate start & end times (in sec/usec), converting 64-bit times to usec. */
1567 /* 64-bit times are "Corey-endian" */
1568 s_time
= pcoreytohll(&s_ptr
[vwr
->STARTT_OFF
]);
1569 e_time
= pcoreytohll(&s_ptr
[vwr
->ENDT_OFF
]);
1571 /* find the packet duration (difference between start and end times) */
1572 d_time
= (guint32
)((e_time
- s_time
)); /* find diff, leaving in nsec for Ethernet */
1574 /* also convert the packet start time to seconds and microseconds */
1575 start_time
= s_time
/ NS_IN_US
; /* convert to microseconds first */
1576 s_sec
= (start_time
/ US_IN_SEC
); /* get the number of seconds */
1577 s_usec
= start_time
- (s_sec
* US_IN_SEC
); /* get the number of microseconds */
1579 /* also convert the packet end time to seconds and microseconds */
1580 end_time
= e_time
/ NS_IN_US
; /* convert to microseconds first */
1582 if (frame_type
& vwr
->IS_TCP
) /* signature offset for TCP frame */
1584 pay_off
= mac_len
+ 40;
1586 else if (frame_type
& vwr
->IS_UDP
) /* signature offset for UDP frame */
1588 pay_off
= mac_len
+ 28;
1590 else if (frame_type
& vwr
->IS_ICMP
) /* signature offset for ICMP frame */
1592 pay_off
= mac_len
+ 24;
1594 else if (frame_type
& vwr
->IS_IGMP
) /* signature offset for IGMPv2 frame */
1596 pay_off
= mac_len
+ 28;
1598 else /* signature offset for raw IP frame */
1600 pay_off
= mac_len
+ 20;
1603 sig_off
= find_signature(m_ptr
, rec_size
, pay_off
, flow_id
, flow_seq
);
1604 if ((m_ptr
[sig_off
] == 0xdd) && (sig_off
+ 15 <= msdu_length
) && (f_flow
!= 0))
1605 sig_ts
= get_signature_ts(m_ptr
, sig_off
);
1609 /* Set latency based on rx/tx and signature timestamp */
1611 if (sig_ts
< s_time
) {
1612 latency
= (guint32
)(s_time
- sig_ts
);
1614 /* Account for the rollover case. Since we cannot use 0x100000000 - l_time + s_time */
1615 /* we look for a large difference between l_time and s_time. */
1616 delta_b
= sig_ts
- s_time
;
1617 if (delta_b
> 0x10000000) {
1620 latency
= (guint32
)delta_b
;
1623 /* Fill up the per-packet header (amazingly like a PCAP packet header! ;-) */
1624 /* Frames are always wired ethernet with a wired ethernettap header. */
1625 /* Caplen is the length that is captured into the file (i.e., the written-out frame */
1626 /* block), and should always represent the actual number of bytes in the file. */
1627 /* len is the length of the original packet before truncation. */
1628 /* The FCS is NEVER included. */
1629 e_hdr_len
= STATS_COMMON_FIELDS_LEN
+ STATS_ETHERNETTAP_FIELDS_LEN
;
1630 wth
->phdr
.len
= (actual_octets
- 4) + e_hdr_len
;
1631 wth
->phdr
.caplen
= (msdu_length
- 4) + e_hdr_len
;
1633 wth
->phdr
.presence_flags
= WTAP_HAS_TS
;
1635 wth
->phdr
.ts
.secs
= (time_t)s_sec
;
1636 wth
->phdr
.ts
.nsecs
= (int)(s_usec
* 1000);
1637 wth
->phdr
.pkt_encap
= WTAP_ENCAP_IXVERIWAVE
;
1639 /* generate and copy out the ETHERNETTAP header, set the port type to 1 (Ethernet) */
1640 common_hdr
.vw_port_type
= 1;
1641 common_hdr
.it_len
= STATS_COMMON_FIELDS_LEN
;
1642 etap_hdr
.it_len
= STATS_ETHERNETTAP_FIELDS_LEN
;
1644 etap_hdr
.vw_errors
= (guint32
)errors
;
1645 etap_hdr
.vw_info
= (guint16
)info
;
1646 common_hdr
.vw_msdu_length
= (guint16
)msdu_length
;
1647 /*etap_hdr.vw_ip_length = (guint16)ip_len;*/
1649 common_hdr
.vw_flowid
= (guint32
)flow_id
;
1650 common_hdr
.vw_vcid
= (guint16
)vc_id
;
1651 common_hdr
.vw_seqnum
= (guint16
)flow_seq
;
1653 if (!IS_TX
&& (sig_ts
!= 0))
1654 common_hdr
.vw_latency
= (guint32
)latency
;
1656 common_hdr
.vw_latency
= 0;
1657 common_hdr
.vw_pktdur
= (guint32
)d_time
;
1658 etap_hdr
.vw_l4id
= (guint32
)l4id
;
1659 etap_hdr
.vw_flags
= 0;
1661 etap_hdr
.vw_flags
|= RADIOTAP_VWF_TXF
;
1662 if (errors
& vwr
->FCS_ERROR
)
1663 etap_hdr
.vw_flags
|= RADIOTAP_VWF_FCSERR
;
1664 common_hdr
.vw_startt
= start_time
; /* record start & end times of frame */
1665 common_hdr
.vw_endt
= end_time
;
1666 common_hdr
.vw_sig_ts
= (guint32
)(sig_ts
);
1668 etap_hdr
.it_pad2
= 0;
1670 /* put common_hdr into the packet buffer in little-endian byte order */
1671 phtoles(&data_ptr
[bytes_written
], common_hdr
.vw_port_type
);
1673 phtoles(&data_ptr
[bytes_written
], common_hdr
.it_len
);
1675 phtoles(&data_ptr
[bytes_written
], common_hdr
.vw_msdu_length
);
1677 phtolel(&data_ptr
[bytes_written
], common_hdr
.vw_flowid
);
1679 phtoles(&data_ptr
[bytes_written
], common_hdr
.vw_vcid
);
1681 phtoles(&data_ptr
[bytes_written
], common_hdr
.vw_seqnum
);
1683 phtolel(&data_ptr
[bytes_written
], common_hdr
.vw_latency
);
1685 phtolel(&data_ptr
[bytes_written
], common_hdr
.vw_sig_ts
);
1687 phtolell(&data_ptr
[bytes_written
], common_hdr
.vw_startt
);
1689 phtolell(&data_ptr
[bytes_written
], common_hdr
.vw_endt
);
1691 phtolel(&data_ptr
[bytes_written
], common_hdr
.vw_pktdur
);
1694 /* put etap_hdr into the packet buffer in little-endian byte order */
1695 phtoles(&data_ptr
[bytes_written
], etap_hdr
.it_len
);
1697 phtoles(&data_ptr
[bytes_written
], etap_hdr
.vw_flags
);
1699 phtoles(&data_ptr
[bytes_written
], etap_hdr
.vw_info
);
1701 phtolel(&data_ptr
[bytes_written
], etap_hdr
.vw_errors
);
1703 phtolel(&data_ptr
[bytes_written
], etap_hdr
.vw_l4id
);
1709 /* finally, copy the whole MAC frame to the packet bufffer as-is; ALWAYS exclude 4-byte FCS */
1710 if ( rec_size
< ((int)actual_octets
+ (int)vwr
->STATS_LEN
) )
1711 /*something's been truncated, DUMP AS-IS*/
1712 memcpy(&data_ptr
[bytes_written
], m_ptr
, msdu_length
);
1713 else if (msdu_length
>= 4)
1714 memcpy(&data_ptr
[bytes_written
], m_ptr
, msdu_length
- 4);
1716 memcpy(&data_ptr
[bytes_written
], m_ptr
, msdu_length
);
1719 /*--------------------------------------------------------------------------------------*/
1720 /* utility to split up and decode a 16-byte message record */
1722 static int decode_msg(vwr_t
*vwr
, guint8
*rec
, int *v_type
, int *IS_TX
)
1724 guint8 cmd
; /* components of message */
1726 int v_size
= 0; /* size of var-len message */
1727 /* assume it's zero */
1729 /* break up the message record into its pieces */
1731 wd2
= pntohl(&rec
[8]);
1732 wd3
= pntohl(&rec
[12]);
1735 if ((cmd
& vwr
->HEADER_IS_TX
) == vwr
->HEADER_IS_TX
)
1737 else if ((cmd
& vwr
->HEADER_IS_RX
) == vwr
->HEADER_IS_RX
)
1739 else *IS_TX
= 2; /*NULL case*/
1741 /* now decode based on the command byte */
1745 v_size
= (int)(wd2
& 0xffff);
1751 v_size
= (int)(wd2
& 0xffff);
1756 v_size
= (int)(wd3
& 0xffff);
1768 /*---------------------------------------------------------------------------------------*/
1769 /* Utilities to extract and decode the PHY bit rate from 802.11 PLCP headers (OFDM/CCK). */
1770 /* They are passed a pointer to 4 or 6 consecutive bytes of PLCP header. */
1771 /* The integer returned by the get_xxx_rate() functions is in units of 0.5 Mb/s. */
1772 /* The string returned by the decode_xxx_rate() functions is 3 characters wide. */
1774 static guint8
get_ofdm_rate(guint8
*plcp
)
1776 /* extract the RATE field (LS nibble of first byte) then convert it to the MCS index used by the L1p fields */
1777 switch (plcp
[0] & 0x0f) {
1778 case 0x0b: return 4;
1779 case 0x0f: return 5;
1780 case 0x0a: return 6;
1781 case 0x0e: return 7;
1782 case 0x09: return 8;
1783 case 0x0d: return 9;
1784 case 0x08: return 10;
1785 case 0x0c: return 11;
1790 static guint8
get_cck_rate(guint8
*plcp
)
1792 /* extract rate from the SIGNAL field then convert it to the MCS index used by the L1p fields */
1794 case 0x0a: return 0;
1795 case 0x14: return 1;
1796 case 0x37: return 2;
1797 case 0x6e: return 3;
1802 /*--------------------------------------------------------------------------------------*/
1803 /* utility to set up offsets and bitmasks for decoding the stats blocks */
1805 static void setup_defaults(vwr_t
*vwr
, guint16 fpga
)
1810 vwr
->STATS_LEN
= vVW510021_W_STATS_LEN
;
1812 vwr
->VALID_OFF
= vVW510021_W_VALID_OFF
;
1813 vwr
->MTYPE_OFF
= vVW510021_W_MTYPE_OFF
;
1814 vwr
->VCID_OFF
= vVW510021_W_VCID_OFF
;
1815 vwr
->FLOWSEQ_OFF
= vVW510021_W_FLOWSEQ_OFF
;
1816 vwr
->FLOWID_OFF
= vVW510021_W_FLOWID_OFF
;
1818 /*vwr->OCTET_OFF = v22_W_OCTET_OFF;*/
1820 vwr
->ERRORS_OFF
= vVW510021_W_ERRORS_OFF
;
1821 vwr
->PATN_OFF
= vVW510021_W_MATCH_OFF
;
1822 vwr
->RSSI_OFF
= vVW510021_W_RSSI_TXPOWER_OFF
;
1823 vwr
->STARTT_OFF
= vVW510021_W_STARTT_OFF
;
1824 vwr
->ENDT_OFF
= vVW510021_W_ENDT_OFF
;
1825 vwr
->LATVAL_OFF
= vVW510021_W_LATVAL_OFF
;
1826 vwr
->INFO_OFF
= vVW510021_W_INFO_OFF
;
1827 vwr
->FPGA_VERSION_OFF
= S2_W_FPGA_VERSION_OFF
;
1828 vwr
->HEADER_VERSION_OFF
= vVW510021_W_HEADER_VERSION_OFF
;
1829 vwr
->OCTET_OFF
= vVW510021_W_MSDU_LENGTH_OFF
;
1830 vwr
->L1P_1_OFF
= vVW510021_W_L1P_1_OFF
;
1831 vwr
->L1P_2_OFF
= vVW510021_W_L1P_2_OFF
;
1832 vwr
->L4ID_OFF
= vVW510021_W_L4ID_OFF
;
1833 vwr
->IPLEN_OFF
= vVW510021_W_IPLEN_OFF
;
1834 vwr
->PLCP_LENGTH_OFF
= vVW510021_W_PLCP_LENGTH_OFF
;
1836 vwr
->HEADER_IS_RX
= vVW510021_W_HEADER_IS_RX
;
1837 vwr
->HEADER_IS_TX
= vVW510021_W_HEADER_IS_TX
;
1838 vwr
->MT_MASK
= vVW510021_W_SEL_MASK
;
1839 vwr
->MCS_INDEX_MASK
= vVW510021_W_MCS_MASK
;
1840 vwr
->VCID_MASK
= 0xffff;
1841 vwr
->FLOW_VALID
= vVW510021_W_FLOW_VALID
;
1842 vwr
->STATS_START_OFF
= vVW510021_W_HEADER_LEN
;
1843 vwr
->FCS_ERROR
= vVW510021_W_FCS_ERROR
;
1844 vwr
->CRYPTO_ERR
= v22_W_CRYPTO_ERR
;
1845 vwr
->RETRY_ERR
= v22_W_RETRY_ERR
;
1847 /*vwr->STATS_START_OFF = 0;*/
1849 vwr
->RXTX_OFF
= vVW510021_W_RXTX_OFF
;
1851 vwr
->MT_10_HALF
= 0;
1852 vwr
->MT_10_FULL
= 0;
1853 vwr
->MT_100_HALF
= 0;
1854 vwr
->MT_100_FULL
= 0;
1855 vwr
->MT_1G_HALF
= 0;
1856 vwr
->MT_1G_FULL
= 0;
1857 vwr
->MT_CCKL
= v22_W_MT_CCKL
;
1858 vwr
->MT_CCKS
= v22_W_MT_CCKS
;
1859 /*vwr->MT_OFDM = vVW510021_W_MT_OFDM;*/
1861 vwr
->WEPTYPE
= vVW510021_W_WEPTYPE
;
1862 vwr
->TKIPTYPE
= vVW510021_W_TKIPTYPE
;
1863 vwr
->CCMPTYPE
= vVW510021_W_CCMPTYPE
;
1865 vwr
->FRAME_TYPE_OFF
= vVW510021_W_FRAME_TYPE_OFF
;
1866 vwr
->IS_TCP
= vVW510021_W_IS_TCP
;
1867 vwr
->IS_UDP
= vVW510021_W_IS_UDP
;
1868 vwr
->IS_ICMP
= vVW510021_W_IS_ICMP
;
1869 vwr
->IS_IGMP
= vVW510021_W_IS_IGMP
;
1870 vwr
->IS_QOS
= vVW510021_W_QOS_VALID
;
1877 vwr
->STATS_LEN
= STATS_COMMON_FIELDS_LEN
+ EXT_RTAP_FIELDS_LEN
;
1878 vwr
->PLCP_LENGTH_OFF
= 16;
1879 vwr
->HEADER_IS_RX
= vVW510021_W_HEADER_IS_RX
;
1880 vwr
->HEADER_IS_TX
= vVW510021_W_HEADER_IS_TX
;
1885 case vVW510012_E_FPGA
:
1886 vwr
->STATS_LEN
= v22_E_STATS_LEN
;
1888 vwr
->VALID_OFF
= v22_E_VALID_OFF
;
1889 vwr
->MTYPE_OFF
= v22_E_MTYPE_OFF
;
1890 vwr
->VCID_OFF
= v22_E_VCID_OFF
;
1891 vwr
->FLOWSEQ_OFF
= v22_E_FLOWSEQ_OFF
;
1892 vwr
->FLOWID_OFF
= v22_E_FLOWID_OFF
;
1893 vwr
->OCTET_OFF
= v22_E_OCTET_OFF
;
1894 vwr
->ERRORS_OFF
= v22_E_ERRORS_OFF
;
1895 vwr
->PATN_OFF
= v22_E_PATN_OFF
;
1896 vwr
->RSSI_OFF
= v22_E_RSSI_OFF
;
1897 vwr
->STARTT_OFF
= v22_E_STARTT_OFF
;
1898 vwr
->ENDT_OFF
= v22_E_ENDT_OFF
;
1899 vwr
->LATVAL_OFF
= v22_E_LATVAL_OFF
;
1900 vwr
->INFO_OFF
= v22_E_INFO_OFF
;
1901 vwr
->L4ID_OFF
= v22_E_L4ID_OFF
;
1903 vwr
->HEADER_IS_RX
= v22_E_HEADER_IS_RX
;
1904 vwr
->HEADER_IS_TX
= v22_E_HEADER_IS_TX
;
1906 vwr
->IS_RX
= v22_E_IS_RX
;
1907 vwr
->MT_MASK
= v22_E_MT_MASK
;
1908 vwr
->VCID_MASK
= v22_E_VCID_MASK
;
1909 vwr
->FLOW_VALID
= v22_E_FLOW_VALID
;
1910 vwr
->FCS_ERROR
= v22_E_FCS_ERROR
;
1912 vwr
->RX_DECRYPTS
= v22_E_RX_DECRYPTS
;
1913 vwr
->TX_DECRYPTS
= v22_E_TX_DECRYPTS
;
1914 vwr
->FC_PROT_BIT
= v22_E_FC_PROT_BIT
;
1916 vwr
->MT_10_HALF
= v22_E_MT_10_HALF
;
1917 vwr
->MT_10_FULL
= v22_E_MT_10_FULL
;
1918 vwr
->MT_100_HALF
= v22_E_MT_100_HALF
;
1919 vwr
->MT_100_FULL
= v22_E_MT_100_FULL
;
1920 vwr
->MT_1G_HALF
= v22_E_MT_1G_HALF
;
1921 vwr
->MT_1G_FULL
= v22_E_MT_1G_FULL
;
1926 vwr
->FRAME_TYPE_OFF
= v22_E_FRAME_TYPE_OFF
;
1927 vwr
->IS_TCP
= v22_E_IS_TCP
;
1928 vwr
->IS_UDP
= v22_E_IS_UDP
;
1929 vwr
->IS_ICMP
= v22_E_IS_ICMP
;
1930 vwr
->IS_IGMP
= v22_E_IS_IGMP
;
1931 vwr
->IS_QOS
= v22_E_IS_QOS
;
1932 vwr
->IS_VLAN
= v22_E_IS_VLAN
;
1938 vwr
->STATS_LEN
= v22_W_STATS_LEN
;
1940 vwr
->MTYPE_OFF
= v22_W_MTYPE_OFF
;
1941 vwr
->VALID_OFF
= v22_W_VALID_OFF
;
1942 vwr
->VCID_OFF
= v22_W_VCID_OFF
;
1943 vwr
->FLOWSEQ_OFF
= v22_W_FLOWSEQ_OFF
;
1944 vwr
->FLOWID_OFF
= v22_W_FLOWID_OFF
;
1945 vwr
->OCTET_OFF
= v22_W_OCTET_OFF
;
1946 vwr
->ERRORS_OFF
= v22_W_ERRORS_OFF
;
1947 vwr
->PATN_OFF
= v22_W_PATN_OFF
;
1948 vwr
->RSSI_OFF
= v22_W_RSSI_OFF
;
1949 vwr
->STARTT_OFF
= v22_W_STARTT_OFF
;
1950 vwr
->ENDT_OFF
= v22_W_ENDT_OFF
;
1951 vwr
->LATVAL_OFF
= v22_W_LATVAL_OFF
;
1952 vwr
->INFO_OFF
= v22_W_INFO_OFF
;
1953 vwr
->L4ID_OFF
= v22_W_L4ID_OFF
;
1954 vwr
->IPLEN_OFF
= v22_W_IPLEN_OFF
;
1955 vwr
->PLCP_LENGTH_OFF
= v22_W_PLCP_LENGTH_OFF
;
1957 vwr
->FCS_ERROR
= v22_W_FCS_ERROR
;
1958 vwr
->CRYPTO_ERR
= v22_W_CRYPTO_ERR
;
1959 vwr
->PAYCHK_ERR
= v22_W_PAYCHK_ERR
;
1960 vwr
->RETRY_ERR
= v22_W_RETRY_ERR
;
1961 vwr
->IS_RX
= v22_W_IS_RX
;
1962 vwr
->MT_MASK
= v22_W_MT_MASK
;
1963 vwr
->VCID_MASK
= v22_W_VCID_MASK
;
1964 vwr
->FLOW_VALID
= v22_W_FLOW_VALID
;
1966 vwr
->HEADER_IS_RX
= v22_W_HEADER_IS_RX
;
1967 vwr
->HEADER_IS_TX
= v22_W_HEADER_IS_TX
;
1969 vwr
->RX_DECRYPTS
= v22_W_RX_DECRYPTS
;
1970 vwr
->TX_DECRYPTS
= v22_W_TX_DECRYPTS
;
1971 vwr
->FC_PROT_BIT
= v22_W_FC_PROT_BIT
;
1973 vwr
->MT_10_HALF
= 0;
1974 vwr
->MT_10_FULL
= 0;
1975 vwr
->MT_100_HALF
= 0;
1976 vwr
->MT_100_FULL
= 0;
1977 vwr
->MT_1G_HALF
= 0;
1978 vwr
->MT_1G_FULL
= 0;
1979 vwr
->MT_CCKL
= v22_W_MT_CCKL
;
1980 vwr
->MT_CCKS
= v22_W_MT_CCKS
;
1981 vwr
->MT_OFDM
= v22_W_MT_OFDM
;
1983 vwr
->WEPTYPE
= v22_W_WEPTYPE
;
1984 vwr
->TKIPTYPE
= v22_W_TKIPTYPE
;
1985 vwr
->CCMPTYPE
= v22_W_CCMPTYPE
;
1987 vwr
->FRAME_TYPE_OFF
= v22_W_FRAME_TYPE_OFF
;
1988 vwr
->IS_TCP
= v22_W_IS_TCP
;
1989 vwr
->IS_UDP
= v22_W_IS_UDP
;
1990 vwr
->IS_ICMP
= v22_W_IS_ICMP
;
1991 vwr
->IS_IGMP
= v22_W_IS_IGMP
;
1992 vwr
->IS_QOS
= v22_W_IS_QOS
;
1996 /* Ethernet frames */
1997 case vVW510024_E_FPGA
:
1998 vwr
->STATS_LEN
= vVW510024_E_STATS_LEN
;
2000 vwr
->VALID_OFF
= vVW510024_E_VALID_OFF
;
2001 vwr
->VCID_OFF
= vVW510024_E_VCID_OFF
;
2002 vwr
->FLOWSEQ_OFF
= vVW510024_E_FLOWSEQ_OFF
;
2003 vwr
->FLOWID_OFF
= vVW510024_E_FLOWID_OFF
;
2004 vwr
->OCTET_OFF
= vVW510024_E_MSDU_LENGTH_OFF
;
2005 vwr
->ERRORS_OFF
= vVW510024_E_ERRORS_OFF
;
2006 vwr
->PATN_OFF
= vVW510024_E_MATCH_OFF
;
2007 vwr
->STARTT_OFF
= vVW510024_E_STARTT_OFF
;
2008 vwr
->ENDT_OFF
= vVW510024_E_ENDT_OFF
;
2009 vwr
->LATVAL_OFF
= vVW510024_E_LATVAL_OFF
;
2010 vwr
->INFO_OFF
= vVW510024_E_INFO_OFF
;
2011 vwr
->L4ID_OFF
= vVW510024_E_L4ID_OFF
;
2012 vwr
->IPLEN_OFF
= vVW510024_E_IPLEN_OFF
;
2014 vwr
->FPGA_VERSION_OFF
= vVW510024_E_FPGA_VERSION_OFF
;
2015 vwr
->HEADER_VERSION_OFF
= vVW510024_E_HEADER_VERSION_OFF
;
2017 vwr
->HEADER_IS_RX
= vVW510024_E_HEADER_IS_RX
;
2018 vwr
->HEADER_IS_TX
= vVW510024_E_HEADER_IS_TX
;
2020 vwr
->VCID_MASK
= vVW510024_E_VCID_MASK
;
2021 vwr
->FLOW_VALID
= vVW510024_E_FLOW_VALID
;
2022 vwr
->FCS_ERROR
= v22_E_FCS_ERROR
;
2024 vwr
->FRAME_TYPE_OFF
= vVW510024_E_FRAME_TYPE_OFF
;
2025 vwr
->IS_TCP
= vVW510024_E_IS_TCP
;
2026 vwr
->IS_UDP
= vVW510024_E_IS_UDP
;
2027 vwr
->IS_ICMP
= vVW510024_E_IS_ICMP
;
2028 vwr
->IS_IGMP
= vVW510024_E_IS_IGMP
;
2029 vwr
->IS_QOS
= vVW510024_E_QOS_VALID
;
2030 vwr
->IS_VLAN
= vVW510024_E_IS_VLAN
;
2035 #define SIG_SCAN_RANGE 64 /* range of signature scanning region */
2037 /* Utility routine: check that signature is at specified location; scan for it if not. */
2038 /* If we can't find a signature at all, then simply return the originally supplied offset. */
2039 int find_signature(guint8
*m_ptr
, int rec_size
, int pay_off
, guint32 flow_id
, guint8 flow_seq
)
2041 int tgt
; /* temps */
2044 /* initial check is very simple: look for a '0xdd' at the target location */
2045 if (m_ptr
[pay_off
] == 0xdd) /* if magic byte is present */
2046 return pay_off
; /* got right offset, return it */
2048 /* Hmmm, signature magic byte is not where it is supposed to be; scan from start of */
2049 /* payload until maximum scan range exhausted to see if we can find it. */
2050 /* The scanning process consists of looking for a '0xdd', then checking for the correct */
2051 /* flow ID and sequence number at the appropriate offsets. */
2052 for (tgt
= pay_off
; tgt
< (rec_size
); tgt
++) {
2053 if (m_ptr
[tgt
] == 0xdd) { /* found magic byte? check fields */
2054 if (m_ptr
[tgt
+ 15] == 0xe2) {
2055 if (m_ptr
[tgt
+ 4] != flow_seq
)
2058 fid
= pletoh24(&m_ptr
[tgt
+ 1]);
2066 { /* out which one... */
2067 if (m_ptr
[tgt
+ SIG_FSQ_OFF
] != flow_seq
) /* check sequence number */
2068 continue; /* if failed, keep scanning */
2070 fid
= pletoh24(&m_ptr
[tgt
+ SIG_FID_OFF
]); /* assemble flow ID from signature */
2071 if (fid
!= flow_id
) /* check flow ID against expected */
2072 continue; /* if failed, keep scanning */
2074 /* matched magic byte, sequence number, flow ID; found the signature */
2075 return (tgt
); /* return offset of signature */
2080 /* failed to find the signature, return the original offset as default */
2084 /* utility routine: harvest the signature time stamp from the data frame */
2085 guint64
get_signature_ts(guint8
*m_ptr
,int sig_off
)
2090 if (m_ptr
[sig_off
+ 15] == 0xe2)
2095 sig_ts
= pletohl(&m_ptr
[sig_off
+ ts_offset
]);
2097 return (sig_ts
& 0xffffffff);
2100 static float getRate( guint8 plcpType
, guint8 mcsIndex
, guint16 rflags
, guint8 nss
)
2102 /* Rate conversion data */
2103 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
};
2105 int canonical_ndbps_20_ht
[] = {26, 52, 78, 104, 156, 208, 234, 260};
2106 int canonical_ndbps_40_ht
[] = {54, 108, 162, 216, 324, 432, 486, 540};
2108 int canonical_ndbps_20_vht
[] = {26,52, 78, 104, 156, 208, 234, 260, 312};
2109 int canonical_ndbps_40_vht
[] = {54, 108, 162, 216, 324, 432, 486, 540, 648, 720};
2110 int canonical_ndbps_80_vht
[] = {117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560};
2113 float symbol_tx_time
, bitrate
= 0.0f
;
2116 bitrate
= canonical_rate_legacy
[mcsIndex
];
2117 else if (plcpType
== 1 || plcpType
== 2)
2119 if ( rflags
& IEEE80211_RADIOTAP_F_SHORTGI
)
2120 symbol_tx_time
= 3.6f
;
2122 symbol_tx_time
= 4.0f
;
2124 if ( rflags
& IEEE80211_RADIOTAP_F_40MHZ
)
2125 ndbps
= canonical_ndbps_40_ht
[ mcsIndex
- 8*(int)(mcsIndex
/8) ];
2127 ndbps
= canonical_ndbps_20_ht
[ mcsIndex
- 8*(int)(mcsIndex
/8) ];
2129 bitrate
= ( ndbps
* (((int)(mcsIndex
/8) + 1) )) / symbol_tx_time
;
2133 if ( rflags
& IEEE80211_RADIOTAP_F_SHORTGI
)
2134 symbol_tx_time
= 3.6f
;
2136 symbol_tx_time
= 4.0f
;
2138 /* Check for the out of range mcsIndex. Should never happen, but if mcs index is greater than 9 assume 9 is the value */
2139 if (mcsIndex
> 9) mcsIndex
= 9;
2140 if ( rflags
& IEEE80211_RADIOTAP_F_40MHZ
)
2141 bitrate
= (canonical_ndbps_40_vht
[ mcsIndex
] * nss
) / symbol_tx_time
;
2142 else if (rflags
& IEEE80211_RADIOTAP_F_80MHZ
)
2143 bitrate
= (canonical_ndbps_80_vht
[ mcsIndex
] * nss
) / symbol_tx_time
;
2146 if (mcsIndex
== 9 && nss
== 3)
2147 bitrate
= 1040 / symbol_tx_time
;
2148 else if (mcsIndex
< 9)
2149 bitrate
= (canonical_ndbps_20_vht
[ mcsIndex
] * nss
) / symbol_tx_time
;
2157 vwr_process_rec_data(wtap
*wth
, FILE_T fh
, int rec_size
,
2158 Buffer
*buf
, vwr_t
*vwr
,
2159 int IS_TX
, int *err
, gchar
**err_info
)
2161 guint8 rec
[B_SIZE
]; /* local buffer (holds input record) */
2162 guint16 pkt_len
; /* length of radiotap headers */
2165 /* Read over the entire record (frame + trailer) into a local buffer. */
2166 /* If we don't get it all, then declare an error, we can't process the frame. */
2167 if (file_read(rec
, rec_size
, fh
) != rec_size
) {
2168 *err
= file_error(fh
, err_info
);
2170 *err
= WTAP_ERR_SHORT_READ
;
2174 if (rec_size
< (int)vwr
->STATS_LEN
) {
2175 *err_info
= g_strdup_printf("vwr: Invalid record length %d (must be at least %u)", rec_size
, vwr
->STATS_LEN
);
2176 *err
= WTAP_ERR_BAD_FILE
;
2180 /* before writing anything out, make sure the buffer has enough space for everything */
2181 if ((vwr
->FPGA_VERSION
== S2_W_FPGA
) || (vwr
->FPGA_VERSION
== S1_W_FPGA
) || (vwr
->FPGA_VERSION
== S3_W_FPGA
) )
2182 /* frames are always 802.11 with an extended radiotap header */
2183 pkt_len
= (guint16
)(rec_size
+ STATS_COMMON_FIELDS_LEN
+ EXT_RTAP_FIELDS_LEN
);
2185 /* frames are always ethernet with an extended ethernettap header */
2186 pkt_len
= (guint16
)(rec_size
+ STATS_COMMON_FIELDS_LEN
+ STATS_ETHERNETTAP_FIELDS_LEN
);
2187 buffer_assure_space(buf
, pkt_len
);
2188 data_ptr
= buffer_start_ptr(buf
);
2190 /* now format up the frame data */
2191 switch (vwr
->FPGA_VERSION
)
2196 vwr_read_rec_data_wlan(wth
, data_ptr
, rec
, rec_size
, IS_TX
);
2198 case vVW510012_E_FPGA
:
2199 vwr_read_rec_data_ethernet(wth
, data_ptr
, rec
, rec_size
, IS_TX
);
2201 case vVW510024_E_FPGA
:
2202 vwr_read_rec_data_ethernet(wth
, data_ptr
, rec
, rec_size
, IS_TX
);
2209 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2214 * indent-tabs-mode: nil
2217 * vi: set shiftwidth=4 tabstop=8 expandtab:
2218 * :indentSize=4:tabSize=8:noTabs=true: