Revert "UNUSED enc_key_id_{equal,hash}"
[wireshark-sm.git] / wiretap / netscaler.c
blobe1f0dfe9746c006a0bcbc5e45986aebeea630203
1 /* netscaler.c
3 * Wiretap Library
4 * Copyright (c) 2006 by Ravi Kondamuru <Ravi.Kondamuru@citrix.com>
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
9 #include "config.h"
10 #include "netscaler.h"
12 #include <string.h>
13 #include "wtap-int.h"
14 #include "file_wrappers.h"
15 #include <wsutil/ws_assert.h>
17 /* Defines imported from netscaler code: nsperfrc.h */
19 #define NSPR_SIGSTR_V10 "NetScaler Performance Data"
20 #define NSPR_SIGSTR_V20 "NetScaler V20 Performance Data"
21 #define NSPR_SIGSTR NSPR_SIGSTR_V20
22 #define NSPR_SIGSTR_V30 "Netscaler V30 Performance Data"
23 #define NSPR_SIGSTR_V35 "Netscaler V35 Performance Data"
24 /* Defined but not used */
25 #define NSPR_SIGSTR_V21 "NetScaler V21 Performance Data"
26 #define NSPR_SIGSTR_V22 "NetScaler V22 Performance Data"
29 * NetScaler trace files are divided into 8K pages, with each page
30 * containing one or more records. The last page of the file
31 * might be less than 8K bytes.
33 * Records are not split across page boundaries; if a record doesn't
34 * fit in what remains in a page, the page is padded with null bytes
35 * and the next record is put at the beginning of the next page.
36 * A record type value of 0 means "unused space", so if there are
37 * enough null bytes to constitute a record type value, it will
38 * look as if there's an "unused space" record (which has no fields
39 * other than the type and zero or more additional padding bytes).
41 #define NSPR_PAGESIZE 8192
42 #define NSPR_PAGESIZE_TRACE (2*NSPR_PAGESIZE)
44 /* The different record types
45 ** NOTE: The Record Type is two byte fields and unused space is recognized by
46 ** either bytes being zero, therefore no record should any byte value as
47 ** zero.
49 ** New Performance Record Type is only one byte.
51 #define NSPR_UNUSEDSPACE_V10 0x0000 /* rest of the page is unused */
52 #define NSPR_UNUSEDSPACE_V20 0x00 /* rest of the page is unused */
53 #define NSPR_SIGNATURE_V10 0x0101 /* signature */
54 #define NSPR_SIGNATURE_V20 0x01 /* signature */
55 #define NSPR_SIGNATURE_V30 NSPR_SIGNATURE_V20
56 #define NSPR_SIGNATURE_V35 NSPR_SIGNATURE_V20
57 #define NSPR_ABSTIME_V10 0x0107 /* data capture time in secs from 1970*/
58 #define NSPR_ABSTIME_V20 0x07 /* data capture time in secs from 1970*/
59 #define NSPR_RELTIME_V10 0x0108 /* relative time in ms from last time */
60 #define NSPR_RELTIME_V20 0x08 /* relative time in ms from last time */
61 #define NSPR_RELTIMEHR_V10 0x0109 /* high resolution relative time */
62 #define NSPR_RELTIMEHR_V20 0x09 /* high resolution relative time */
63 #define NSPR_SYSTARTIME_V10 0x010A /* system start time */
64 #define NSPR_SYSTARTIME_V20 0x0A /* system start time */
65 #define NSPR_RELTIME2B_V10 0x010B /* relative time in ms from last time */
66 #define NSPR_RELTIME2B_V20 0x0B /* relative time in ms from last time */
69 /* The high resolution relative time format.
70 ** The MS 2 bits of the high resolution time is defined as follows:
71 ** 00 : time value is in seconds
72 ** 01 : time value is in milliseconds
73 ** 10 : time value is in microseconds
74 ** 11 : time value is in nanoseconds
76 #define NSPR_HRTIME_MASKTM 0x3FFFFFFF /* mask to get time value */
77 #define NSPR_HRTIME_MASKFMT 0xC0000000 /* time value format mask */
78 #define NSPR_HRTIME_SEC 0x00000000 /* time value in second */
79 #define NSPR_HRTIME_MSEC 0x40000000 /* time value in mili second */
80 #define NSPR_HRTIME_USEC 0x80000000 /* time value in micro second */
81 #define NSPR_HRTIME_NSEC 0xC0000000 /* time value in nano second */
84 typedef struct nspr_header_v10
86 uint8_t ph_RecordType[2]; /* Record Type */
87 uint8_t ph_RecordSize[2]; /* Record Size including header */
88 } nspr_header_v10_t;
89 #define nspr_header_v10_s ((uint32_t)sizeof(nspr_header_v10_t))
91 /* This is V20 short header (2 bytes long) to be included where needed */
92 #define NSPR_HEADER_V20(prefix) \
93 uint8_t prefix##_RecordType; /* Record Type */ \
94 uint8_t prefix##_RecordSize /* Record Size including header */ \
95 /* end of declaration */
97 /* This is new long header (3 bytes long) to be included where needed */
98 #define NSPR_HEADER3B_V20(prefix) \
99 uint8_t prefix##_RecordType; /* Record Type */ \
100 uint8_t prefix##_RecordSizeLow; /* Record Size including header */ \
101 uint8_t prefix##_RecordSizeHigh /* Record Size including header */ \
102 /* end of declaration */
103 #define NSPR_HEADER3B_V21 NSPR_HEADER3B_V20
104 #define NSPR_HEADER3B_V22 NSPR_HEADER3B_V20
105 #define NSPR_HEADER3B_V30 NSPR_HEADER3B_V20
107 typedef struct nspr_hd_v20
109 NSPR_HEADER3B_V20(phd); /* long performance header */
111 } nspr_hd_v20_t;
112 #define nspr_hd_v20_s ((uint32_t)sizeof(nspr_hd_v20_t))
116 ** How to know if header size is short or long?
117 ** The short header size can be 0-127 bytes long. If MS Bit of ph_RecordSize
118 ** is set then record size has 2 bytes
120 #define NSPR_V20RECORDSIZE_2BYTES 0x80U
122 /* Performance Data Header with device number */
123 typedef struct nspr_headerdev_v10
125 uint8_t ph_RecordType[2]; /* Record Type */
126 uint8_t ph_RecordSize[2]; /* Record Size including header */
127 uint8_t ph_DevNo[4]; /* Network Device (NIC/CONN) number */
128 } nspr_headerdev_v10_t;
129 #define nspr_headerdev_v10_s ((uint32_t)sizeof(nspr_headerdev_v10_t))
131 typedef struct nspr_hd_v10
133 nspr_header_v10_t phd; /* performance header */
134 } nspr_hd_v10_t;
135 #define nspr_hd_v10_s ((uint32_t)sizeof(nspr_hd_v10_t))
137 typedef struct nspr_hdev_v10
139 nspr_headerdev_v10_t phd; /* performance header */
140 } nspr_hdev_v10_t;
141 #define nspr_hdev_v10_s ((uint32_t)sizeof(nspr_hdev_v10_t))
143 /* if structure has defined phd as first field, it can use following names */
144 #define nsprRecordType phd.ph_RecordType
145 #define nsprRecordSize phd.ph_RecordSize
146 #define nsprReserved phd.ph_Reserved
147 #define nsprRecordTypeOrg phd.ph_Reserved
148 #define nsprDevNo phd.ph_DevNo
150 /* NSPR_SIGNATURE_V10 structure */
151 #define NSPR_SIGSIZE_V10 56 /* signature value size in bytes */
152 typedef struct nspr_signature_v10
154 nspr_header_v10_t phd; /* performance header */
155 uint8_t sig_EndianType; /* Endian Type for the data */
156 uint8_t sig_Reserved0;
157 uint8_t sig_Reserved1[2];
158 char sig_Signature[NSPR_SIGSIZE_V10]; /* Signature value */
159 } nspr_signature_v10_t;
160 #define nspr_signature_v10_s ((uint32_t)sizeof(nspr_signature_v10_t))
162 /* NSPR_SIGNATURE_V20 structure */
163 #define NSPR_SIGSIZE_V20 sizeof(NSPR_SIGSTR_V20) /* signature value size in bytes */
164 typedef struct nspr_signature_v20
166 NSPR_HEADER_V20(sig); /* short performance header */
167 uint8_t sig_EndianType; /* Endian Type for the data */
168 char sig_Signature[NSPR_SIGSIZE_V20]; /* Signature value */
169 } nspr_signature_v20_t;
170 #define nspr_signature_v20_s ((uint32_t)sizeof(nspr_signature_v20_t))
172 /* NSPR_SIGNATURE_V30 structure */
173 #define NSPR_SIGSIZE_V30 sizeof(NSPR_SIGSTR_V30) /* signature value size in bytes */
174 typedef struct nspr_signature_v30
176 NSPR_HEADER_V20(sig); /* short performance header */
177 uint8_t sig_EndianType; /* Endian Type for the data */
178 char sig_Signature[NSPR_SIGSIZE_V30]; /* Signature value */
179 } nspr_signature_v30_t;
180 #define nspr_signature_v30_s ((uint32_t)sizeof(nspr_signature_v30_t))
182 #define NSPR_SIGSIZE_V35 sizeof(NSPR_SIGSTR_V35) /* signature value size in bytes */
183 typedef struct nspr_signature_v35
185 NSPR_HEADER_V20(sig); /* short performance header */
186 uint8_t sig_EndianType; /* Endian Type for the data */
187 char sig_Signature[NSPR_SIGSIZE_V35]; /* Signature value */
188 } nspr_signature_v35_t;
189 #define nspr_signature_v35_s ((uint32_t)sizeof(nspr_signature_v35_t))
191 /* NSPR_ABSTIME_V10 and NSPR_SYSTARTIME_V10 structure */
192 typedef struct nspr_abstime_v10
194 nspr_header_v10_t phd; /* performance header */
195 uint8_t abs_RelTime[4]; /* relative time is ms from last time */
196 uint8_t abs_Time[4]; /* absolute time in seconds from 1970 */
197 } nspr_abstime_v10_t;
198 #define nspr_abstime_v10_s ((uint32_t)sizeof(nspr_abstime_v10_t))
201 /* NSPR_ABSTIME_V20 and NSPR_SYSTARTIME_V20 structure */
202 typedef struct nspr_abstime_v20
204 NSPR_HEADER_V20(abs); /* short performance header */
205 uint8_t abs_RelTime[2]; /* relative time is ms from last time */
206 uint8_t abs_Time[4]; /* absolute time in seconds from 1970 */
207 } nspr_abstime_v20_t;
208 #define nspr_abstime_v20_s ((uint32_t)sizeof(nspr_abstime_v20_t))
212 /* full packet trace structure */
213 typedef struct nspr_pktracefull_v10
215 nspr_headerdev_v10_t phd; /* performance header */
216 uint8_t fp_RelTimeHr[4]; /* High resolution relative time */
217 } nspr_pktracefull_v10_t;
218 #define nspr_pktracefull_v10_s ((uint32_t)(sizeof(nspr_pktracefull_v10_t)))
220 /* new full packet trace structure v20 */
221 typedef struct nspr_pktracefull_v20
223 NSPR_HEADER3B_V20(fp); /* long performance header */
224 uint8_t fp_DevNo; /* Network Device (NIC) number */
225 uint8_t fp_RelTimeHr[4]; /* High resolution relative time */
226 } nspr_pktracefull_v20_t;
227 #define nspr_pktracefull_v20_s ((uint32_t)(sizeof(nspr_pktracefull_v20_t)))
229 /* new full packet trace structure v21 */
230 typedef struct nspr_pktracefull_v21
232 NSPR_HEADER3B_V21(fp); /* long performance header */
233 uint8_t fp_DevNo; /* Network Device (NIC) number */
234 uint8_t fp_RelTimeHr[4]; /* High resolution relative time */
235 uint8_t fp_PcbDevNo[4]; /* PCB devno */
236 uint8_t fp_lPcbDevNo[4]; /* link PCB devno */
237 } nspr_pktracefull_v21_t;
238 #define nspr_pktracefull_v21_s ((uint32_t)(sizeof(nspr_pktracefull_v21_t)))
240 /* new full packet trace structure v22 */
241 typedef struct nspr_pktracefull_v22
243 NSPR_HEADER3B_V22(fp); /* long performance header */
244 uint8_t fp_DevNo; /* Network Device (NIC) number */
245 uint8_t fp_RelTimeHr[4]; /* High resolution relative time */
246 uint8_t fp_PcbDevNo[4]; /* PCB devno */
247 uint8_t fp_lPcbDevNo[4]; /* link PCB devno */
248 uint8_t fp_VlanTag[2]; /* vlan tag */
249 } nspr_pktracefull_v22_t;
250 #define nspr_pktracefull_v22_s ((uint32_t)(sizeof(nspr_pktracefull_v22_t)))
252 typedef struct nspr_pktracefull_v23
254 NSPR_HEADER3B_V22(fp); /* long performance header */
255 uint8_t fp_DevNo; /* Network Device (NIC) number */
256 uint8_t fp_AbsTimeHr[8]; /* High resolution absolute time */
257 uint8_t fp_PcbDevNo[4]; /* PCB devno */
258 uint8_t fp_lPcbDevNo[4]; /* link PCB devno */
259 uint8_t fp_VlanTag[2]; /* vlan tag */
260 uint8_t fp_Coreid[2]; /* coreid of the packet */
261 } nspr_pktracefull_v23_t;
262 #define nspr_pktracefull_v23_s ((uint32_t)(sizeof(nspr_pktracefull_v23_t)))
264 /* New full packet trace structure v24 for cluster tracing */
265 typedef struct nspr_pktracefull_v24
267 NSPR_HEADER3B_V22(fp); /* long performance header */
268 uint8_t fp_DevNo; /* Network Device (NIC) number */
269 uint8_t fp_AbsTimeHr[8]; /* High resolution absolute time in nanosec */
270 uint8_t fp_PcbDevNo[4]; /* PCB devno */
271 uint8_t fp_lPcbDevNo[4]; /* link PCB devno */
272 uint8_t fp_VlanTag[2]; /* vlan tag */
273 uint8_t fp_Coreid[2]; /* coreid of the packet */
274 uint8_t fp_srcNodeId[2]; /* source node # */
275 uint8_t fp_destNodeId[2]; /* destination node # */
276 uint8_t fp_clFlags; /* cluster flags */
277 } nspr_pktracefull_v24_t;
278 #define nspr_pktracefull_v24_s ((uint32_t)(sizeof(nspr_pktracefull_v24_t)))
280 /* New full packet trace structure v25 for vm info tracing */
281 typedef struct nspr_pktracefull_v25
283 NSPR_HEADER3B_V22(fp); /* long performance header */
284 uint8_t fp_DevNo; /* Network Device (NIC) number */
285 uint8_t fp_AbsTimeHr[8]; /* High resolution absolute time in nanosec */
286 uint8_t fp_PcbDevNo[4]; /* PCB devno */
287 uint8_t fp_lPcbDevNo[4]; /* link PCB devno */
288 uint8_t fp_VlanTag[2]; /* vlan tag */
289 uint8_t fp_Coreid[2]; /* coreid of the packet */
290 uint8_t fp_srcNodeId[2]; /* source node # */
291 uint8_t fp_destNodeId[2]; /* destination node # */
292 uint8_t fp_clFlags; /* cluster flags */
293 uint8_t fp_src_vmname_len; /* vm src info */
294 uint8_t fp_dst_vmname_len; /* vm src info */
295 } nspr_pktracefull_v25_t;
296 #define nspr_pktracefull_v25_s ((uint32_t)(sizeof(nspr_pktracefull_v25_t)))
298 /* New full packet trace structure v26 for vm info tracing */
299 typedef struct nspr_pktracefull_v26
301 NSPR_HEADER3B_V22(fp); /* long performance header */
302 uint8_t fp_DevNo; /* Network Device (NIC) number */
303 uint8_t fp_AbsTimeHr[8]; /* High resolution absolute time in nanosec */
304 uint8_t fp_PcbDevNo[4]; /* PCB devno */
305 uint8_t fp_lPcbDevNo[4]; /* link PCB devno */
306 uint8_t fp_VlanTag[2]; /* vlan tag */
307 uint8_t fp_Coreid[2]; /* coreid of the packet */
308 uint8_t fp_srcNodeId[2]; /* source node # */
309 uint8_t fp_destNodeId[2]; /* destination node # */
310 uint8_t fp_clFlags; /* cluster flags */
311 uint8_t fp_src_vmname_len; /* vm src info */
312 uint8_t fp_dst_vmname_len; /* vm src info */
313 uint8_t fp_reserved;
314 uint8_t fp_ns_activity[4];
315 uint8_t fp_reserved_32[12]; /* Adding more field to reduce wireshark changes every time */
316 } nspr_pktracefull_v26_t;
317 #define nspr_pktracefull_v26_s ((uint32_t)(sizeof(nspr_pktracefull_v26_t)))
319 /* partial packet trace structure */
320 typedef struct nspr_pktracepart_v10
322 nspr_headerdev_v10_t phd; /* performance header */
323 uint8_t pp_RelTimeHr[4]; /* High resolution relative time */
324 uint8_t pp_PktSizeOrg[2]; /* Original packet size */
325 uint8_t pp_PktOffset[2]; /* starting offset in packet */
326 } nspr_pktracepart_v10_t;
327 #define nspr_pktracepart_v10_s ((uint32_t)(sizeof(nspr_pktracepart_v10_t)))
329 /* new partial packet trace structure */
330 typedef struct nspr_pktracepart_v20
332 NSPR_HEADER3B_V20(pp); /* long performance header */
333 uint8_t pp_DevNo; /* Network Device (NIC) number */
334 uint8_t pp_RelTimeHr[4]; /* High resolution relative time */
335 uint8_t pp_PktSizeOrg[2]; /* Original packet size */
336 uint8_t pp_PktOffset[2]; /* starting offset in packet */
337 } nspr_pktracepart_v20_t;
338 #define nspr_pktracepart_v20_s ((uint32_t)(sizeof(nspr_pktracepart_v20_t)))
340 /* new partial packet trace structure */
341 typedef struct nspr_pktracepart_v21
343 NSPR_HEADER3B_V21(pp); /* long performance header */
344 uint8_t pp_DevNo; /* Network Device (NIC) number */
345 uint8_t pp_RelTimeHr[4]; /* High resolution relative time */
346 uint8_t pp_PktSizeOrg[2]; /* Original packet size */
347 uint8_t pp_PktOffset[2]; /* starting offset in packet */
348 uint8_t pp_PcbDevNo[4]; /* PCB devno */
349 uint8_t pp_lPcbDevNo[4]; /* link PCB devno */
350 } nspr_pktracepart_v21_t;
351 #define nspr_pktracepart_v21_s ((uint32_t)(sizeof(nspr_pktracepart_v21_t)))
353 /* new partial packet trace structure v22 */
354 typedef struct nspr_pktracepart_v22
356 NSPR_HEADER3B_V22(pp); /* long performance header */
357 uint8_t pp_DevNo; /* Network Device (NIC) number */
358 uint8_t pp_RelTimeHr[4]; /* High resolution relative time */
359 uint8_t pp_PktSizeOrg[2]; /* Original packet size */
360 uint8_t pp_PktOffset[2]; /* starting offset in packet */
361 uint8_t pp_PcbDevNo[4]; /* PCB devno */
362 uint8_t pp_lPcbDevNo[4]; /* link PCB devno */
363 uint8_t pp_VlanTag[2]; /* Vlan Tag */
364 } nspr_pktracepart_v22_t;
365 #define nspr_pktracepart_v22_s ((uint32_t)(sizeof(nspr_pktracepart_v22_t)))
367 typedef struct nspr_pktracepart_v23
369 NSPR_HEADER3B_V22(pp); /* long performance header */
370 uint8_t pp_DevNo; /* Network Device (NIC) number */
371 uint8_t pp_AbsTimeHr[8]; /* High resolution absolute time */
372 uint8_t pp_PktSizeOrg[2]; /* Original packet size */
373 uint8_t pp_PktOffset[2]; /* starting offset in packet */
374 uint8_t pp_PcbDevNo[4]; /* PCB devno */
375 uint8_t pp_lPcbDevNo[4]; /* link PCB devno */
376 uint8_t pp_VlanTag[2]; /* vlan tag */
377 uint8_t pp_Coreid[2]; /* Coreid of the packet */
378 } nspr_pktracepart_v23_t;
379 #define nspr_pktracepart_v23_s ((uint32_t)(sizeof(nspr_pktracepart_v23_t)))
381 /* New partial packet trace structure v24 for cluster tracing */
382 typedef struct nspr_pktracepart_v24
384 NSPR_HEADER3B_V22(pp); /* long performance header */
385 uint8_t pp_DevNo; /* Network Device (NIC) number */
386 uint8_t pp_AbsTimeHr[8]; /*High resolution absolute time in nanosec*/
387 uint8_t pp_PktSizeOrg[2]; /* Original packet size */
388 uint8_t pp_PktOffset[2]; /* starting offset in packet */
389 uint8_t pp_PcbDevNo[4]; /* PCB devno */
390 uint8_t pp_lPcbDevNo[4]; /* link PCB devno */
391 uint8_t pp_VlanTag[2]; /* vlan tag */
392 uint8_t pp_Coreid[2]; /* Coreid of the packet */
393 uint8_t pp_srcNodeId[2]; /* source node # */
394 uint8_t pp_destNodeId[2]; /* destination node # */
395 uint8_t pp_clFlags; /* cluster flags */
396 } nspr_pktracepart_v24_t;
397 #define nspr_pktracepart_v24_s ((uint32_t)(sizeof(nspr_pktracepart_v24_t)))
399 /* New partial packet trace structure v25 for vm info tracing */
400 typedef struct nspr_pktracepart_v25
402 NSPR_HEADER3B_V22(pp); /* long performance header */
403 uint8_t pp_DevNo; /* Network Device (NIC) number */
404 uint8_t pp_AbsTimeHr[8]; /*High resolution absolute time in nanosec*/
405 uint8_t pp_PktSizeOrg[2]; /* Original packet size */
406 uint8_t pp_PktOffset[2]; /* starting offset in packet */
407 uint8_t pp_PcbDevNo[4]; /* PCB devno */
408 uint8_t pp_lPcbDevNo[4]; /* link PCB devno */
409 uint8_t pp_VlanTag[2]; /* vlan tag */
410 uint8_t pp_Coreid[2]; /* Coreid of the packet */
411 uint8_t pp_srcNodeId[2]; /* source node # */
412 uint8_t pp_destNodeId[2]; /* destination node # */
413 uint8_t pp_clFlags; /* cluster flags */
414 uint8_t pp_src_vmname_len; /* vm info */
415 uint8_t pp_dst_vmname_len; /* vm info */
416 } nspr_pktracepart_v25_t;
417 #define nspr_pktracepart_v25_s ((uint32_t)(sizeof(nspr_pktracepart_v25_t)))
419 /* New full packet trace structure v30 for multipage spanning data */
420 typedef struct nspr_pktracefull_v30
422 NSPR_HEADER3B_V30(fp); /* long performance header */
423 uint8_t fp_DevNo; /* Network Device (NIC) number */
424 uint8_t fp_AbsTimeHr[8]; /*High resolution absolute time in nanosec*/
425 uint8_t fp_PcbDevNo[4]; /* PCB devno */
426 uint8_t fp_lPcbDevNo[4]; /* link PCB devno */
427 uint8_t fp_PktSizeOrg[2]; /* Original packet size */
428 uint8_t fp_VlanTag[2]; /* vlan tag */
429 uint8_t fp_Coreid[2]; /* coreid of the packet */
430 uint8_t fp_srcNodeId[2]; /* cluster nodeid of the packet */
431 uint8_t fp_destNodeId[2];
432 uint8_t fp_clFlags;
433 uint8_t fp_src_vmname_len;
434 uint8_t fp_dst_vmname_len;
435 uint8_t fp_reserved[3];
436 uint8_t fp_ns_activity[4];
437 uint8_t fp_reserved_32[12];
438 } nspr_pktracefull_v30_t;
439 #define nspr_pktracefull_v30_s ((uint32_t)(sizeof(nspr_pktracefull_v30_t)))
441 /* New full packet trace structure v35 for multipage spanning data */
442 typedef struct nspr_pktracefull_v35
444 NSPR_HEADER3B_V30(fp); /* long performance header */
445 uint8_t fp_DevNo; /* Network Device (NIC) number */
446 uint8_t fp_AbsTimeHr[8]; /*High resolution absolute time in nanosec*/
447 uint8_t fp_PcbDevNo[4]; /* PCB devno */
448 uint8_t fp_lPcbDevNo[4]; /* link PCB devno */
449 uint8_t fp_PktSizeOrg[2]; /* Original packet size */
450 uint8_t fp_VlanTag[2]; /* vlan tag */
451 uint8_t fp_Coreid[2]; /* coreid of the packet */
452 uint8_t fp_headerlen[2];
453 uint8_t fp_errorcode;
454 uint8_t fp_app;
455 uint8_t fp_ns_activity[4];
456 uint8_t fp_nextrectype;
457 } nspr_pktracefull_v35_t;
458 #define nspr_pktracefull_v35_s ((uint32_t)(sizeof(nspr_pktracefull_v35_t)))
460 /* New partial packet trace structure v26 for vm info tracing */
461 typedef struct nspr_pktracepart_v26
463 NSPR_HEADER3B_V22(pp); /* long performance header */
464 uint8_t pp_DevNo; /* Network Device (NIC) number */
465 uint8_t pp_AbsTimeHr[8]; /*High resolution absolute time in nanosec*/
466 uint8_t pp_PktSizeOrg[2]; /* Original packet size */
467 uint8_t pp_PktOffset[2]; /* starting offset in packet */
468 uint8_t pp_PcbDevNo[4]; /* PCB devno */
469 uint8_t pp_lPcbDevNo[4]; /* link PCB devno */
470 uint8_t pp_VlanTag[2]; /* vlan tag */
471 uint8_t pp_Coreid[2]; /* Coreid of the packet */
472 uint8_t pp_srcNodeId[2]; /* source node # */
473 uint8_t pp_destNodeId[2]; /* destination node # */
474 uint8_t pp_clFlags; /* cluster flags */
475 uint8_t pp_src_vmname_len; /* vm info */
476 uint8_t pp_dst_vmname_len; /* vm info */
477 uint8_t pp_reserved;
478 uint8_t pp_ns_activity[4];
479 uint8_t pp_reserved_32[12]; /* Adding more field to reduce wireshark changes every time */
480 } nspr_pktracepart_v26_t;
481 #define nspr_pktracepart_v26_s ((uint32_t)(sizeof(nspr_pktracepart_v26_t)))
483 #define __TNDO(rec,enumprefix,structname,hdrname)\
484 static const uint8_t enumprefix##_##hdrname##_offset = (uint8_t)sizeof(nspr_##structname##_t);
486 #define __TNO(rec,enumprefix,structprefix,structname,hdrname,structfieldname) \
487 static const uint8_t enumprefix##_##hdrname##_offset = (uint8_t)GPOINTER_TO_INT(offsetof(nspr_##structname##_t,structprefix##_##structfieldname));
489 #define __TNL(rec,enumprefix,structprefix,structname,hdrname,structfieldname) \
490 static const uint8_t enumprefix##_##hdrname##_len = (uint8_t)sizeof(((nspr_##structname##_t*)0)->structprefix##_##structfieldname);
492 #define __TNV1O(rec,enumprefix,structprefix,structname,hdrname,structfieldname) \
493 static const uint8_t enumprefix##_##hdrname##_offset = (uint8_t)GPOINTER_TO_INT(offsetof(nspr_##structname##_t,structfieldname));
495 #define __TNV1L(rec,enumprefix,structprefix,structname,hdrname,structfieldname) \
496 static const uint8_t enumprefix##_##hdrname##_len = (uint8_t)sizeof(((nspr_##structname##_t*)0)->structfieldname);
498 #define TRACE_V10_REC_LEN_OFF(rec,enumprefix,structprefix,structname) \
499 __TNV1O(rec,enumprefix,structprefix,structname,dir,phd.ph_RecordType)\
500 __TNV1L(rec,enumprefix,structprefix,structname,dir,phd.ph_RecordType)\
501 __TNV1O(rec,enumprefix,structprefix,structname,nicno,phd.ph_DevNo)\
502 __TNV1L(rec,enumprefix,structprefix,structname,nicno,phd.ph_DevNo)\
503 __TNDO(rec,enumprefix,structname,eth)
505 #define TRACE_V20_REC_LEN_OFF(rec,enumprefix,structprefix,structname) \
506 __TNO(rec,enumprefix,structprefix,structname,dir,RecordType)\
507 __TNL(rec,enumprefix,structprefix,structname,dir,RecordType)\
508 __TNO(rec,enumprefix,structprefix,structname,nicno,DevNo)\
509 __TNL(rec,enumprefix,structprefix,structname,nicno,DevNo)\
510 __TNDO(rec,enumprefix,structname,eth)
512 #define TRACE_V21_REC_LEN_OFF(rec,enumprefix,structprefix,structname) \
513 TRACE_V20_REC_LEN_OFF(rec,enumprefix,structprefix,structname)\
514 __TNO(rec,enumprefix,structprefix,structname,pcb,PcbDevNo)\
515 __TNO(rec,enumprefix,structprefix,structname,l_pcb,lPcbDevNo)
517 #define TRACE_V22_REC_LEN_OFF(rec,enumprefix,structprefix,structname) \
518 TRACE_V21_REC_LEN_OFF(rec,enumprefix,structprefix,structname)\
519 __TNO(rec,enumprefix,structprefix,structname,vlantag,VlanTag)
521 #define TRACE_V23_REC_LEN_OFF(rec,enumprefix,structprefix,structname) \
522 TRACE_V22_REC_LEN_OFF(rec,enumprefix,structprefix,structname)\
523 __TNO(rec,enumprefix,structprefix,structname,coreid,Coreid)
525 #define TRACE_V24_REC_LEN_OFF(rec,enumprefix,structprefix,structname) \
526 TRACE_V23_REC_LEN_OFF(rec,enumprefix,structprefix,structname)\
527 __TNO(rec,enumprefix,structprefix,structname,srcnodeid,srcNodeId)\
528 __TNO(rec,enumprefix,structprefix,structname,destnodeid,destNodeId)\
529 __TNO(rec,enumprefix,structprefix,structname,clflags,clFlags)
531 #define TRACE_V25_REC_LEN_OFF(rec,enumprefix,structprefix,structname) \
532 TRACE_V24_REC_LEN_OFF(rec,enumprefix,structprefix,structname)\
533 __TNO(rec,enumprefix,structprefix,structname,src_vmname_len,src_vmname_len)\
534 __TNO(rec,enumprefix,structprefix,structname,dst_vmname_len,dst_vmname_len)\
535 __TNDO(rec,enumprefix,structname,data)
537 #define TRACE_V26_REC_LEN_OFF(rec,enumprefix,structprefix,structname) \
538 TRACE_V25_REC_LEN_OFF(rec,enumprefix,structprefix,structname)\
539 __TNO(rec,enumprefix,structprefix,structname,ns_activity,ns_activity)\
541 #define TRACE_V30_REC_LEN_OFF(rec, enumprefix, structprefix, structname) \
542 TRACE_V26_REC_LEN_OFF(rec,enumprefix,structprefix,structname)\
544 #define TRACE_V35_REC_LEN_OFF(rec, enumprefix, structprefix, structname) \
545 TRACE_V23_REC_LEN_OFF(rec,enumprefix,structprefix,structname)\
546 __TNDO(rec,enumprefix,structname,data)\
547 __TNO(rec,enumprefix,structprefix,structname,ns_activity,ns_activity)
549 TRACE_V10_REC_LEN_OFF(NULL,v10_part,pp,pktracepart_v10)
550 TRACE_V10_REC_LEN_OFF(NULL,v10_full,fp,pktracefull_v10)
551 TRACE_V20_REC_LEN_OFF(NULL,v20_part,pp,pktracepart_v20)
552 TRACE_V20_REC_LEN_OFF(NULL,v20_full,fp,pktracefull_v20)
553 TRACE_V21_REC_LEN_OFF(NULL,v21_part,pp,pktracepart_v21)
554 TRACE_V21_REC_LEN_OFF(NULL,v21_full,fp,pktracefull_v21)
555 TRACE_V22_REC_LEN_OFF(NULL,v22_part,pp,pktracepart_v22)
556 TRACE_V22_REC_LEN_OFF(NULL,v22_full,fp,pktracefull_v22)
557 TRACE_V23_REC_LEN_OFF(NULL,v23_part,pp,pktracepart_v23)
558 TRACE_V23_REC_LEN_OFF(NULL,v23_full,fp,pktracefull_v23)
559 TRACE_V24_REC_LEN_OFF(NULL,v24_part,pp,pktracepart_v24)
560 TRACE_V24_REC_LEN_OFF(NULL,v24_full,fp,pktracefull_v24)
561 TRACE_V25_REC_LEN_OFF(NULL,v25_part,pp,pktracepart_v25)
562 TRACE_V25_REC_LEN_OFF(NULL,v25_full,fp,pktracefull_v25)
563 TRACE_V26_REC_LEN_OFF(NULL,v26_part,pp,pktracepart_v26)
564 TRACE_V26_REC_LEN_OFF(NULL,v26_full,fp,pktracefull_v26)
565 TRACE_V30_REC_LEN_OFF(NULL,v30_full,fp,pktracefull_v30)
566 TRACE_V35_REC_LEN_OFF(NULL,v35_full,fp,pktracefull_v35)
568 #undef __TNV1O
569 #undef __TNV1L
570 #undef __TNO
571 #undef __TNDO
572 #undef __TNL
575 #define ns_setabstime(nstrace, AbsoluteTime, RelativeTimems) \
576 do { \
577 (nstrace)->nspm_curtime = AbsoluteTime; \
578 (nstrace)->nspm_curtimemsec += RelativeTimems; \
579 (nstrace)->nspm_curtimelastmsec = nstrace->nspm_curtimemsec; \
580 } while(0)
583 #define ns_setrelativetime(nstrace, RelativeTimems) \
584 do { \
585 uint32_t rsec; \
586 (nstrace)->nspm_curtimemsec += RelativeTimems; \
587 rsec = (uint32_t)((nstrace)->nspm_curtimemsec - (nstrace)->nspm_curtimelastmsec)/1000; \
588 (nstrace)->nspm_curtime += rsec; \
589 (nstrace)->nspm_curtimelastmsec += rsec * 1000; \
590 } while (0)
593 typedef struct {
594 char *pnstrace_buf;
595 uint32_t page_size;
596 int64_t xxx_offset;
597 uint32_t nstrace_buf_offset;
598 uint32_t nstrace_buflen;
599 /* Performance Monitor Time variables */
600 uint32_t nspm_curtime; /* current time since 1970 */
601 uint64_t nspm_curtimemsec; /* current time in milliseconds */
602 uint64_t nspm_curtimelastmsec; /* nspm_curtime last update time in milliseconds */
603 uint64_t nsg_creltime;
604 uint64_t file_size;
605 } nstrace_t;
608 * File versions.
610 #define NSPM_SIGNATURE_1_0 0
611 #define NSPM_SIGNATURE_2_0 1
612 #define NSPM_SIGNATURE_3_0 2
613 #define NSPM_SIGNATURE_3_5 3
614 #define NSPM_SIGNATURE_NOMATCH -1
616 static int nspm_signature_version(char*, unsigned);
617 static bool nstrace_read_v10(wtap *wth, wtap_rec *rec, Buffer *buf,
618 int *err, char **err_info,
619 int64_t *data_offset);
620 static bool nstrace_read_v20(wtap *wth, wtap_rec *rec, Buffer *buf,
621 int *err, char **err_info,
622 int64_t *data_offset);
623 static bool nstrace_read_v30(wtap *wth, wtap_rec *rec, Buffer *buf,
624 int *err, char **err_info,
625 int64_t *data_offset);
626 static bool nstrace_seek_read_v10(wtap *wth, int64_t seek_off,
627 wtap_rec *rec,
628 Buffer *buf,
629 int *err, char **err_info);
630 static bool nstrace_seek_read_v20(wtap *wth, int64_t seek_off,
631 wtap_rec *rec,
632 Buffer *buf,
633 int *err, char **err_info);
634 static bool nstrace_seek_read_v30(wtap *wth, int64_t seek_off,
635 wtap_rec *rec,
636 Buffer *buf,
637 int *err, char **err_info);
638 static void nstrace_close(wtap *wth);
640 static bool nstrace_set_start_time_v10(wtap *wth, int *err,
641 char **err_info);
642 static bool nstrace_set_start_time_v20(wtap *wth, int *err,
643 char **err_info);
644 static bool nstrace_set_start_time(wtap *wth, int version, int *err,
645 char **err_info);
646 static uint64_t ns_hrtime2nsec(uint32_t tm);
648 static bool nstrace_dump(wtap_dumper *wdh, const wtap_rec *rec,
649 const uint8_t *pd, int *err, char **err_info);
652 static int nstrace_1_0_file_type_subtype = -1;
653 static int nstrace_2_0_file_type_subtype = -1;
654 static int nstrace_3_0_file_type_subtype = -1;
655 static int nstrace_3_5_file_type_subtype = -1;
657 void register_nstrace(void);
660 * Minimum of the page size and the amount of data left in the file;
661 * the last page of a file can be short.
663 #define GET_READ_PAGE_SIZE(remaining_file_size) ((int32_t)((remaining_file_size>NSPR_PAGESIZE)?NSPR_PAGESIZE:remaining_file_size))
664 #define GET_READ_PAGE_SIZEV3(remaining_file_size) ((int32_t)((remaining_file_size>NSPR_PAGESIZE_TRACE)?NSPR_PAGESIZE_TRACE:remaining_file_size))
667 * Check whether we have enough room to retrieve the data in the caller.
668 * If not, we have a malformed file.
670 static bool nstrace_ensure_buflen(nstrace_t* nstrace, unsigned offset, unsigned len, int *err, char** err_info)
672 if (offset > nstrace->nstrace_buflen || nstrace->nstrace_buflen - offset < len) {
673 *err = WTAP_ERR_BAD_FILE;
674 *err_info = g_strdup("nstrace: malformed file");
675 return false;
677 return true;
680 static uint64_t ns_hrtime2nsec(uint32_t tm)
682 uint32_t val = tm & NSPR_HRTIME_MASKTM;
683 switch(tm & NSPR_HRTIME_MASKFMT)
685 case NSPR_HRTIME_SEC: return (uint64_t)val*1000000000;
686 case NSPR_HRTIME_MSEC: return (uint64_t)val*1000000;
687 case NSPR_HRTIME_USEC: return (uint64_t)val*1000;
688 case NSPR_HRTIME_NSEC: return val;
690 return tm;
693 static bool
694 nstrace_read_page(wtap *wth, int *err, char **err_info)
696 nstrace_t *nstrace = (nstrace_t *)wth->priv;
697 int bytes_read;
699 bytes_read = file_read(nstrace->pnstrace_buf, nstrace->page_size, wth->fh);
700 if (bytes_read < 0) {
701 *err = file_error(wth->fh, err_info);
702 return false;
704 if (bytes_read == 0) {
706 * EOF.
708 *err = 0;
709 return false;
711 nstrace->nstrace_buflen = (uint32_t)bytes_read;
712 return true;
716 ** Netscaler trace format open routines
718 wtap_open_return_val nstrace_open(wtap *wth, int *err, char **err_info)
720 int file_version;
721 char *nstrace_buf;
722 int64_t file_size;
723 int32_t page_size;
724 int bytes_read;
725 nstrace_t *nstrace;
727 if ((file_size = wtap_file_size(wth, err)) == -1)
728 return WTAP_OPEN_ERROR;
729 if (file_size == 0)
730 return WTAP_OPEN_NOT_MINE;
731 /* The size is 64 bits; we assume it fits in 63 bits, so it's positive */
733 nstrace_buf = (char *)g_malloc(NSPR_PAGESIZE);
734 page_size = NSPR_PAGESIZE;
737 * Read the first page, so we can look for a signature.
738 * A short read is OK, as a file may have fewer records
739 * than required to fill up a page.
741 bytes_read = file_read(nstrace_buf, NSPR_PAGESIZE, wth->fh);
742 if (bytes_read < 0) {
743 *err = file_error(wth->fh, err_info);
744 g_free(nstrace_buf);
745 return WTAP_OPEN_ERROR;
747 if (bytes_read == 0) {
748 /* An empty file. */
749 g_free(nstrace_buf);
750 return WTAP_OPEN_NOT_MINE;
754 * Scan it for a signature block.
756 file_version = nspm_signature_version(nstrace_buf, (unsigned)bytes_read);
757 switch (file_version) {
759 case NSPM_SIGNATURE_1_0:
760 wth->file_type_subtype = nstrace_1_0_file_type_subtype;
761 wth->file_encap = WTAP_ENCAP_NSTRACE_1_0;
762 break;
764 case NSPM_SIGNATURE_2_0:
765 wth->file_type_subtype = nstrace_2_0_file_type_subtype;
766 wth->file_encap = WTAP_ENCAP_NSTRACE_2_0;
767 break;
769 case NSPM_SIGNATURE_3_0:
770 wth->file_type_subtype = nstrace_3_0_file_type_subtype;
771 wth->file_encap = WTAP_ENCAP_NSTRACE_3_0;
773 * File pages are larger in version 3.0; grow the buffer.
774 * (XXX - use g_realloc()?)
776 g_free(nstrace_buf);
777 nstrace_buf = (char *)g_malloc(NSPR_PAGESIZE_TRACE);
778 page_size = NSPR_PAGESIZE_TRACE;
779 break;
781 case NSPM_SIGNATURE_3_5:
782 wth->file_type_subtype = nstrace_3_5_file_type_subtype;
783 wth->file_encap = WTAP_ENCAP_NSTRACE_3_5;
785 * File pages are larger in version 3.5; grow the buffer.
786 * (XXX - use g_realloc()?)
788 g_free(nstrace_buf);
789 nstrace_buf = (char *)g_malloc(NSPR_PAGESIZE_TRACE);
790 page_size = NSPR_PAGESIZE_TRACE;
791 break;
793 default:
794 /* No known signature found, assume it's not NetScaler */
795 g_free(nstrace_buf);
796 return WTAP_OPEN_NOT_MINE;
799 switch (file_version)
801 case NSPM_SIGNATURE_1_0:
802 wth->subtype_read = nstrace_read_v10;
803 wth->subtype_seek_read = nstrace_seek_read_v10;
804 break;
806 case NSPM_SIGNATURE_2_0:
807 wth->subtype_read = nstrace_read_v20;
808 wth->subtype_seek_read = nstrace_seek_read_v20;
809 break;
811 case NSPM_SIGNATURE_3_0:
812 wth->subtype_read = nstrace_read_v30;
813 wth->subtype_seek_read = nstrace_seek_read_v30;
814 break;
816 case NSPM_SIGNATURE_3_5:
817 wth->subtype_read = nstrace_read_v30;
818 wth->subtype_seek_read = nstrace_seek_read_v30;
819 break;
821 wth->subtype_close = nstrace_close;
823 nstrace = g_new(nstrace_t, 1);
824 wth->priv = (void *)nstrace;
825 nstrace->pnstrace_buf = nstrace_buf;
826 nstrace->page_size = page_size;
827 nstrace->xxx_offset = 0;
828 nstrace->nstrace_buf_offset = 0;
829 nstrace->nspm_curtime = 0;
830 nstrace->nspm_curtimemsec = 0;
831 nstrace->nspm_curtimelastmsec = 0;
832 nstrace->nsg_creltime = 0;
833 nstrace->file_size = file_size;
836 * Seek back to the beginning of the file and read the first page,
837 * now that we know the page size.
839 if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
841 g_free(nstrace_buf);
842 return WTAP_OPEN_ERROR;
844 if (!nstrace_read_page(wth, err, err_info)) {
845 if (*err == 0) {
846 /* EOF, so an empty file. */
847 g_free(nstrace_buf);
848 return WTAP_OPEN_NOT_MINE;
850 /* Read error. */
851 return WTAP_OPEN_ERROR;
854 /* Set the start time by looking for the abstime record */
855 if ((nstrace_set_start_time(wth, file_version, err, err_info)) == false)
858 * No absolute time record seen, so we just reset the read
859 * pointer to the start of the file, so we start reading
860 * at the first record, rather than skipping records up
861 * to and including an absolute time record.
863 if (*err != 0)
865 /* We got an error reading the records. */
866 return WTAP_OPEN_ERROR;
868 if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
870 return WTAP_OPEN_ERROR;
873 /* Read the first page of data */
874 if (!nstrace_read_page(wth, err, err_info)) {
875 if (*err == 0) {
876 /* EOF, so an empty file. */
877 g_free(nstrace_buf);
878 return WTAP_OPEN_NOT_MINE;
880 /* Read error. */
881 return WTAP_OPEN_ERROR;
884 /* reset the buffer offset */
885 nstrace->nstrace_buf_offset = 0;
888 wth->file_tsprec = WTAP_TSPREC_NSEC;
890 *err = 0;
893 * Add an IDB; we don't know how many interfaces were
894 * involved, so we just say one interface, about which
895 * we only know the link-layer type, snapshot length,
896 * and time stamp resolution.
898 wtap_add_generated_idb(wth);
900 return WTAP_OPEN_MINE;
904 ** Generates a function that checks whether the specified signature
905 ** field, with the specified size, matches the signature string for
906 ** the version specified as an argument to the macro.
908 ** The function does so by checking whether the signature string for
909 ** the version in question is a prefix of the signature field. The
910 ** signature field appears to be a blob of text, with one or more
911 ** lines, with lines separated by '\n', and the last line terminated
912 ** with '\0'. The first lign is the signature field; it may end with
913 ** '\n', meaning there's another line following it, or it may end
914 ** with '\0', meaning it's the last line.
916 ** For that to be true, the field must have a size >= to the size (not
917 ** counting the terminating'\0') of the version's signature string,
918 ** and the first N bytes of the field, where N is the length of the
919 ** version string of the version (again, not counting the terminating
920 ** '\0'), are equal to the version's signature string.
922 ** XXX - should this do an exact match rather than a prefix match,
923 ** checking whether either a '\n' or '\0' follows the first line?
925 #define nspm_signature_func(ver) \
926 static uint32_t nspm_signature_isv##ver(char *sigp, size_t sigsize) {\
927 size_t versiglen = sizeof(NSPR_SIGSTR_V##ver)-1;\
928 return sigsize >= versiglen && strncmp(sigp,NSPR_SIGSTR_V##ver,versiglen) == 0;\
931 nspm_signature_func(10)
932 nspm_signature_func(20)
933 nspm_signature_func(30)
934 nspm_signature_func(35)
937 ** Scan a page for something that looks like a signature record and,
938 ** if we find one, check the signature against the ones we support.
939 ** If we find one we support, return the file type/subtype for that
940 ** file version. If we don't find a signature record with a signature
941 ** we support, return NSPM_SIGNATURE_NOMATCH.
943 ** We don't know what version the file is, so we can't make
944 ** assumptions about the format of the records.
946 ** XXX - can we assume the signature block is the first block?
948 static int
949 nspm_signature_version(char *nstrace_buf, unsigned len)
951 char *dp = nstrace_buf;
953 for ( ; len > MIN(nspr_signature_v10_s, nspr_signature_v20_s); dp++, len--)
955 #define sigv10p ((nspr_signature_v10_t*)dp)
957 * If this is a V10 signature record, then:
959 * 1) we have a full signature record's worth of data in what
960 * remains of the first page;
962 * 2) it appears to have a record type of NSPR_SIGNATURE_V10;
964 * 3) the length field specifies a length that fits in what
965 * remains of the first page;
967 * 4) it also specifies something as large as, or larger than,
968 * the declared size of a V10 signature record.
970 * (XXX - are all V10 signature records that size, or might they
971 * be smaller, with a shorter signature field?)
973 if (len >= nspr_signature_v10_s &&
974 (pletoh16(&sigv10p->nsprRecordType) == NSPR_SIGNATURE_V10) &&
975 (pletoh16(&sigv10p->nsprRecordSize) <= len) &&
976 (pletoh16(&sigv10p->nsprRecordSize) >= nspr_signature_v10_s))
978 if ((nspm_signature_isv10(sigv10p->sig_Signature, sizeof sigv10p->sig_Signature)))
979 return NSPM_SIGNATURE_1_0;
981 #undef sigv10p
983 #define sigv20p ((nspr_signature_v20_t*)dp)
985 * If this is a V20-or-later signature record, then:
987 * 1) we have a full signature record's worth of data in what
988 * remains of the first page;
990 * 2) it appears to have a record type of NSPR_SIGNATURE_V20;
992 * 3) the length field specifies a length that fits in what
993 * remains of the first page;
995 * 4) it also specifies something as large as, or larger than,
996 * the declared size of a V20 signature record.
998 if (len >= nspr_signature_v20_s &&
999 (sigv20p->sig_RecordType == NSPR_SIGNATURE_V20) &&
1000 (sigv20p->sig_RecordSize <= len) &&
1001 (sigv20p->sig_RecordSize >= nspr_signature_v20_s))
1003 if (nspm_signature_isv20(sigv20p->sig_Signature, sizeof sigv20p->sig_Signature)){
1004 return NSPM_SIGNATURE_2_0;
1005 } else if (nspm_signature_isv30(sigv20p->sig_Signature, sizeof sigv20p->sig_Signature)){
1006 return NSPM_SIGNATURE_3_0;
1007 } else if (nspm_signature_isv35(sigv20p->sig_Signature, sizeof sigv20p->sig_Signature)){
1008 return NSPM_SIGNATURE_3_5;
1011 #undef sigv20p
1014 return NSPM_SIGNATURE_NOMATCH; /* no version found */
1017 #define nspr_getv10recordtype(hdp) (pletoh16(&(hdp)->nsprRecordType))
1018 #define nspr_getv10recordsize(hdp) (pletoh16(&(hdp)->nsprRecordSize))
1019 #define nspr_getv20recordtype(hdp) ((hdp)->phd_RecordType)
1020 #define nspr_getv20recordsize(hdp) \
1021 (uint32_t)(((hdp)->phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES)? \
1022 (((hdp)->phd_RecordSizeHigh * NSPR_V20RECORDSIZE_2BYTES)+ \
1023 ((hdp)->phd_RecordSizeLow & ~NSPR_V20RECORDSIZE_2BYTES)) : \
1024 (hdp)->phd_RecordSizeLow)
1028 * For a given file version, this defines a routine to find an absolute
1029 * time record in a file of that version and set the start time based on
1030 * that.
1032 * The routine called from the open routine after a file has been recognized
1033 * as a NetScaler trace.
1035 #define nstrace_set_start_time_ver(ver) \
1036 bool nstrace_set_start_time_v##ver(wtap *wth, int *err, char **err_info) \
1038 nstrace_t *nstrace = (nstrace_t *)wth->priv;\
1039 char* nstrace_buf = nstrace->pnstrace_buf;\
1040 uint32_t nstrace_buf_offset = nstrace->nstrace_buf_offset;\
1041 uint32_t nstrace_buflen = nstrace->nstrace_buflen;\
1042 uint32_t record_size;\
1045 while (nstrace_buf_offset < nstrace_buflen)\
1047 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_hd_v##ver##_t), err, err_info))\
1048 return false;\
1049 nspr_hd_v##ver##_t *fp = (nspr_hd_v##ver##_t *) &nstrace_buf[nstrace_buf_offset];\
1050 switch (nspr_getv##ver##recordtype(fp))\
1052 case NSPR_ABSTIME_V##ver:\
1053 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_abstime_v##ver##_t), err, err_info))\
1054 return false;\
1055 ns_setabstime(nstrace, pletoh32(&((nspr_abstime_v##ver##_t *) fp)->abs_Time), pletoh16(&((nspr_abstime_v##ver##_t *) fp)->abs_RelTime));\
1056 nstrace->nstrace_buf_offset = nstrace_buf_offset + nspr_getv##ver##recordsize(fp);\
1057 nstrace->nstrace_buflen = nstrace_buflen;\
1058 return true;\
1059 case NSPR_UNUSEDSPACE_V10:\
1060 nstrace_buf_offset = nstrace_buflen;\
1061 break;\
1062 default:\
1063 record_size = nspr_getv##ver##recordsize(fp);\
1064 if (record_size == 0) {\
1065 *err = WTAP_ERR_BAD_FILE;\
1066 *err_info = g_strdup("nstrace: zero size record found");\
1067 return false;\
1069 nstrace_buf_offset += record_size;\
1072 nstrace_buf_offset = 0;\
1073 nstrace->xxx_offset += nstrace_buflen;\
1074 nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));\
1075 }while((nstrace_buflen > 0) && (nstrace_read_page(wth, err, err_info)));\
1076 return false;\
1079 nstrace_set_start_time_ver(10)
1080 nstrace_set_start_time_ver(20)
1082 #undef nspr_getv10recordtype
1083 #undef nspr_getv20recordtype
1086 ** Set the start time of the trace file. We look for the first ABSTIME record. We use that
1087 ** to set the start time. Apart from that we also make sure that we remember the position of
1088 ** the next record after the ABSTIME record. Inorder to report correct time values, all trace
1089 ** records before the ABSTIME record are ignored.
1091 static bool nstrace_set_start_time(wtap *wth, int file_version, int *err,
1092 char **err_info)
1094 if (file_version == NSPM_SIGNATURE_1_0)
1095 return nstrace_set_start_time_v10(wth, err, err_info);
1096 else if (file_version == NSPM_SIGNATURE_2_0)
1097 return nstrace_set_start_time_v20(wth, err, err_info);
1098 else if (file_version == NSPM_SIGNATURE_3_0)
1099 return nstrace_set_start_time_v20(wth, err, err_info);
1100 return false;
1103 #define __TNDO(rec,enumprefix,structname,hdrname)\
1104 (rec)->rec_header.packet_header.pseudo_header.nstr.hdrname##_offset = enumprefix##_##hdrname##_offset;
1106 #define __TNO(rec,enumprefix,structprefix,structname,hdrname,structfieldname) \
1107 (rec)->rec_header.packet_header.pseudo_header.nstr.hdrname##_offset = enumprefix##_##hdrname##_offset;
1109 #define __TNL(rec,enumprefix,structprefix,structname,hdrname,structfieldname) \
1110 (rec)->rec_header.packet_header.pseudo_header.nstr.hdrname##_len = enumprefix##_##hdrname##_len;
1112 #define __TNV1O(rec,enumprefix,structprefix,structname,hdrname,structfieldname) \
1113 __TNO(rec,enumprefix,structprefix,structname,hdrname,structfieldname)
1115 #define __TNV1L(rec,enumprefix,structprefix,structname,hdrname,structfieldname) \
1116 __TNL(rec,enumprefix,structprefix,structname,hdrname,structfieldname)
1121 ** Netscaler trace format read routines.
1123 ** The maximum value of the record data size is 65535, which is less than
1124 ** WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
1126 #define TIMEDEFV10(rec,fp,type) \
1127 do {\
1128 (rec)->presence_flags = WTAP_HAS_TS;\
1129 nsg_creltime += ns_hrtime2nsec(pletoh32(&type->type##_RelTimeHr));\
1130 (rec)->ts.secs = nstrace->nspm_curtime + (uint32_t) (nsg_creltime / 1000000000);\
1131 (rec)->ts.nsecs = (uint32_t) (nsg_creltime % 1000000000);\
1132 }while(0)
1134 #define PARTSIZEDEFV10(rec,pp,ver) \
1135 do {\
1136 (rec)->presence_flags |= WTAP_HAS_CAP_LEN;\
1137 (rec)->rec_header.packet_header.len = pletoh16(&pp->pp_PktSizeOrg) + nspr_pktracepart_v##ver##_s;\
1138 (rec)->rec_header.packet_header.caplen = pletoh16(&pp->nsprRecordSize);\
1139 }while(0)
1141 #define FULLSIZEDEFV10(rec,fp,ver) \
1142 do {\
1143 (rec)->rec_header.packet_header.len = pletoh16(&(fp)->nsprRecordSize);\
1144 (rec)->rec_header.packet_header.caplen = (rec)->rec_header.packet_header.len;\
1145 }while(0)
1147 #define PACKET_DESCRIBE(rec,buf,FULLPART,fullpart,ver,type,HEADERVER) \
1148 do {\
1149 /* Make sure the record header is entirely contained in the page */\
1150 if ((nstrace_buflen - nstrace_buf_offset) < sizeof(nspr_pktrace##fullpart##_v##ver##_t)) {\
1151 *err = WTAP_ERR_BAD_FILE;\
1152 *err_info = g_strdup("nstrace: record header crosses page boundary");\
1153 return false;\
1155 nspr_pktrace##fullpart##_v##ver##_t *type = (nspr_pktrace##fullpart##_v##ver##_t *) &nstrace_buf[nstrace_buf_offset];\
1156 /* Check sanity of record size */\
1157 if (pletoh16(&type->nsprRecordSize) < sizeof *type) {\
1158 *err = WTAP_ERR_BAD_FILE;\
1159 *err_info = g_strdup("nstrace: record size is less than record header size");\
1160 return false;\
1162 (rec)->rec_type = REC_TYPE_PACKET;\
1163 (rec)->block = wtap_block_create(WTAP_BLOCK_PACKET);\
1164 TIMEDEFV##ver((rec),fp,type);\
1165 FULLPART##SIZEDEFV##ver((rec),type,ver);\
1166 TRACE_V##ver##_REC_LEN_OFF((rec),v##ver##_##fullpart,type,pktrace##fullpart##_v##ver);\
1167 /* Make sure the record is entirely contained in the page */\
1168 if ((nstrace_buflen - nstrace_buf_offset) < (rec)->rec_header.packet_header.caplen) {\
1169 *err = WTAP_ERR_BAD_FILE;\
1170 *err_info = g_strdup("nstrace: record crosses page boundary");\
1171 return false;\
1173 ws_buffer_assure_space((buf), (rec)->rec_header.packet_header.caplen);\
1174 memcpy(ws_buffer_start_ptr((buf)), type, (rec)->rec_header.packet_header.caplen);\
1175 *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
1176 nstrace->nstrace_buf_offset = nstrace_buf_offset + (rec)->rec_header.packet_header.caplen;\
1177 nstrace->nstrace_buflen = nstrace_buflen;\
1178 nstrace->nsg_creltime = nsg_creltime;\
1179 return true;\
1180 }while(0)
1182 static bool nstrace_read_v10(wtap *wth, wtap_rec *rec, Buffer *buf,
1183 int *err, char **err_info, int64_t *data_offset)
1185 nstrace_t *nstrace = (nstrace_t *)wth->priv;
1186 uint64_t nsg_creltime = nstrace->nsg_creltime;
1187 char *nstrace_buf = nstrace->pnstrace_buf;
1188 uint32_t nstrace_buf_offset = nstrace->nstrace_buf_offset;
1189 uint32_t nstrace_buflen = nstrace->nstrace_buflen;
1191 *err = 0;
1192 *err_info = NULL;
1195 while ((nstrace_buf_offset < nstrace_buflen) &&
1196 ((nstrace_buflen - nstrace_buf_offset) >= ((int32_t)sizeof((( nspr_header_v10_t*)&nstrace_buf[nstrace_buf_offset])->ph_RecordType))))
1199 #define GENERATE_CASE_FULL(rec,buf,ver,HEADERVER) \
1200 case NSPR_PDPKTRACEFULLTX_V##ver:\
1201 case NSPR_PDPKTRACEFULLTXB_V##ver:\
1202 case NSPR_PDPKTRACEFULLRX_V##ver:\
1203 PACKET_DESCRIBE(rec,buf,FULL,full,ver,fp,HEADERVER);
1205 #define GENERATE_CASE_PART(rec,buf,ver,HEADERVER) \
1206 case NSPR_PDPKTRACEPARTTX_V##ver:\
1207 case NSPR_PDPKTRACEPARTTXB_V##ver:\
1208 case NSPR_PDPKTRACEPARTRX_V##ver:\
1209 PACKET_DESCRIBE(rec,buf,PART,part,ver,pp,HEADERVER);
1211 switch (pletoh16(&(( nspr_header_v10_t*)&nstrace_buf[nstrace_buf_offset])->ph_RecordType))
1213 GENERATE_CASE_FULL(rec,buf,10,100)
1214 GENERATE_CASE_PART(rec,buf,10,100)
1216 #undef GENERATE_CASE_FULL
1217 #undef GENERATE_CASE_PART
1219 case NSPR_ABSTIME_V10:
1221 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_pktracefull_v10_t), err, err_info))
1222 return false;
1223 nspr_pktracefull_v10_t *fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];
1224 if (pletoh16(&fp->nsprRecordSize) == 0) {
1225 *err = WTAP_ERR_BAD_FILE;
1226 *err_info = g_strdup("nstrace: zero size record found");
1227 return false;
1229 ns_setabstime(nstrace, pletoh32(((nspr_abstime_v10_t *) fp)->abs_Time), pletoh32(&((nspr_abstime_v10_t *) fp)->abs_RelTime));
1230 nstrace_buf_offset += pletoh16(&fp->nsprRecordSize);
1231 break;
1234 case NSPR_RELTIME_V10:
1236 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_pktracefull_v10_t), err, err_info))
1237 return false;
1238 nspr_pktracefull_v10_t *fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];
1239 if (pletoh16(&fp->nsprRecordSize) == 0) {
1240 *err = WTAP_ERR_BAD_FILE;
1241 *err_info = g_strdup("nstrace: zero size record found");
1242 return false;
1244 ns_setrelativetime(nstrace, pletoh32(((nspr_abstime_v10_t *) fp)->abs_RelTime));
1245 nstrace_buf_offset += pletoh16(&fp->nsprRecordSize);
1246 break;
1249 case NSPR_UNUSEDSPACE_V10:
1250 nstrace_buf_offset = nstrace_buflen;
1251 break;
1253 default:
1255 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_pktracefull_v10_t), err, err_info))
1256 return false;
1257 nspr_pktracefull_v10_t *fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];
1258 if (pletoh16(&fp->nsprRecordSize) == 0) {
1259 *err = WTAP_ERR_BAD_FILE;
1260 *err_info = g_strdup("nstrace: zero size record found");
1261 return false;
1263 nstrace_buf_offset += pletoh16(&fp->nsprRecordSize);
1264 break;
1269 nstrace_buf_offset = 0;
1270 nstrace->xxx_offset += nstrace_buflen;
1271 nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));
1272 }while((nstrace_buflen > 0) && (nstrace_read_page(wth, err, err_info)));
1274 return false;
1277 #undef PACKET_DESCRIBE
1279 #define TIMEDEFV20(rec,fp,type) \
1280 do {\
1281 (rec)->presence_flags = WTAP_HAS_TS;\
1282 nsg_creltime += ns_hrtime2nsec(pletoh32(fp->type##_RelTimeHr));\
1283 (rec)->ts.secs = nstrace->nspm_curtime + (uint32_t) (nsg_creltime / 1000000000);\
1284 (rec)->ts.nsecs = (uint32_t) (nsg_creltime % 1000000000);\
1285 }while(0)
1287 #define TIMEDEFV23(rec,fp,type) \
1288 do {\
1289 (rec)->presence_flags = WTAP_HAS_TS;\
1290 /* access _AbsTimeHr as a 64bit value */\
1291 nsg_creltime = pletoh64(fp->type##_AbsTimeHr);\
1292 (rec)->ts.secs = (uint32_t) (nsg_creltime / 1000000000);\
1293 (rec)->ts.nsecs = (uint32_t) (nsg_creltime % 1000000000);\
1294 }while(0)
1296 #define TIMEDEFV21(rec,fp,type) TIMEDEFV20(rec,fp,type)
1297 #define TIMEDEFV22(rec,fp,type) TIMEDEFV20(rec,fp,type)
1298 #define TIMEDEFV24(rec,fp,type) TIMEDEFV23(rec,fp,type)
1299 #define TIMEDEFV25(rec,fp,type) TIMEDEFV24(rec,fp,type)
1300 #define TIMEDEFV26(rec,fp,type) TIMEDEFV24(rec,fp,type)
1303 ** The maximum value of the record data size is 65535, which is less than
1304 ** WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
1306 #define PARTSIZEDEFV20(rec,pp,ver) \
1307 do {\
1308 (rec)->presence_flags |= WTAP_HAS_CAP_LEN;\
1309 (rec)->rec_header.packet_header.len = pletoh16(&pp->pp_PktSizeOrg) + nspr_pktracepart_v##ver##_s;\
1310 (rec)->rec_header.packet_header.caplen = nspr_getv20recordsize((nspr_hd_v20_t *)pp);\
1311 }while(0)
1313 #define PARTSIZEDEFV21(rec,pp,ver) PARTSIZEDEFV20(rec,pp,ver)
1314 #define PARTSIZEDEFV22(rec,pp,ver) PARTSIZEDEFV20(rec,pp,ver)
1315 #define PARTSIZEDEFV23(rec,pp,ver) PARTSIZEDEFV20(rec,pp,ver)
1316 #define PARTSIZEDEFV24(rec,pp,ver) PARTSIZEDEFV20(rec,pp,ver)
1317 #define PARTSIZEDEFV25(rec,pp,ver) PARTSIZEDEFV20(rec,pp,ver)
1318 #define PARTSIZEDEFV26(rec,pp,ver) PARTSIZEDEFV20(rec,pp,ver)
1320 #define FULLSIZEDEFV20(rec,fp,ver)\
1321 do {\
1322 (rec)->rec_header.packet_header.len = nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
1323 (rec)->rec_header.packet_header.caplen = (rec)->rec_header.packet_header.len;\
1324 }while(0)
1326 #define FULLSIZEDEFV21(rec,fp,ver) FULLSIZEDEFV20(rec,fp,ver)
1327 #define FULLSIZEDEFV22(rec,fp,ver) FULLSIZEDEFV20(rec,fp,ver)
1328 #define FULLSIZEDEFV23(rec,fp,ver) FULLSIZEDEFV20(rec,fp,ver)
1329 #define FULLSIZEDEFV24(rec,fp,ver) FULLSIZEDEFV20(rec,fp,ver)
1330 #define FULLSIZEDEFV25(rec,fp,ver) FULLSIZEDEFV20(rec,fp,ver)
1331 #define FULLSIZEDEFV26(rec,fp,ver) FULLSIZEDEFV20(rec,fp,ver)
1333 #define PACKET_DESCRIBE(rec,buf,FULLPART,ver,enumprefix,type,structname,HEADERVER)\
1334 do {\
1335 nspr_##structname##_t *fp= (nspr_##structname##_t*)&nstrace_buf[nstrace_buf_offset];\
1336 /* Make sure the record header is entirely contained in the page */\
1337 if ((nstrace_buflen - nstrace_buf_offset) < sizeof *fp) {\
1338 *err = WTAP_ERR_BAD_FILE;\
1339 *err_info = g_strdup("nstrace: record header crosses page boundary");\
1340 return false;\
1342 /* Check sanity of record size */\
1343 if (nspr_getv20recordsize((nspr_hd_v20_t *)fp) < sizeof *fp) {\
1344 *err = WTAP_ERR_BAD_FILE;\
1345 *err_info = g_strdup("nstrace: record size is less than record header size");\
1346 return false;\
1348 (rec)->rec_type = REC_TYPE_PACKET;\
1349 (rec)->block = wtap_block_create(WTAP_BLOCK_PACKET);\
1350 TIMEDEFV##ver((rec),fp,type);\
1351 FULLPART##SIZEDEFV##ver((rec),fp,ver);\
1352 TRACE_V##ver##_REC_LEN_OFF((rec),enumprefix,type,structname);\
1353 (rec)->rec_header.packet_header.pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##HEADERVER;\
1354 /* Make sure the record is entirely contained in the page */\
1355 if ((nstrace_buflen - nstrace_buf_offset) < (rec)->rec_header.packet_header.caplen) {\
1356 *err = WTAP_ERR_BAD_FILE;\
1357 *err_info = g_strdup("nstrace: record crosses page boundary");\
1358 return false;\
1360 ws_buffer_assure_space((buf), (rec)->rec_header.packet_header.caplen);\
1361 memcpy(ws_buffer_start_ptr((buf)), fp, (rec)->rec_header.packet_header.caplen);\
1362 *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
1363 nstrace->nstrace_buf_offset = nstrace_buf_offset + nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
1364 nstrace->nstrace_buflen = nstrace_buflen;\
1365 nstrace->nsg_creltime = nsg_creltime;\
1366 return true;\
1367 }while(0)
1369 static bool nstrace_read_v20(wtap *wth, wtap_rec *rec, Buffer *buf,
1370 int *err, char **err_info, int64_t *data_offset)
1372 nstrace_t *nstrace = (nstrace_t *)wth->priv;
1373 uint64_t nsg_creltime = nstrace->nsg_creltime;
1374 char *nstrace_buf = nstrace->pnstrace_buf;
1375 uint32_t nstrace_buf_offset = nstrace->nstrace_buf_offset;
1376 uint32_t nstrace_buflen = nstrace->nstrace_buflen;
1378 *err = 0;
1379 *err_info = NULL;
1382 while ((nstrace_buf_offset < nstrace_buflen) &&
1383 ((nstrace_buflen - nstrace_buf_offset) >= ((int32_t)sizeof((( nspr_hd_v20_t*)&nstrace_buf[nstrace_buf_offset])->phd_RecordType))))
1385 switch ((( nspr_hd_v20_t*)&nstrace_buf[nstrace_buf_offset])->phd_RecordType)
1388 #define GENERATE_CASE_FULL(rec,buf,ver,HEADERVER) \
1389 case NSPR_PDPKTRACEFULLTX_V##ver:\
1390 case NSPR_PDPKTRACEFULLTXB_V##ver:\
1391 case NSPR_PDPKTRACEFULLRX_V##ver:\
1392 PACKET_DESCRIBE(rec,buf,FULL,ver,v##ver##_full,fp,pktracefull_v##ver,HEADERVER);
1394 #define GENERATE_CASE_FULL_V25(rec,buf,ver,HEADERVER) \
1395 case NSPR_PDPKTRACEFULLTX_V##ver:\
1396 case NSPR_PDPKTRACEFULLTXB_V##ver:\
1397 case NSPR_PDPKTRACEFULLRX_V##ver:\
1398 case NSPR_PDPKTRACEFULLNEWRX_V##ver:\
1399 PACKET_DESCRIBE(rec,buf,FULL,ver,v##ver##_full,fp,pktracefull_v##ver,HEADERVER);
1401 #define GENERATE_CASE_PART(rec,buf,ver,HEADERVER) \
1402 case NSPR_PDPKTRACEPARTTX_V##ver:\
1403 case NSPR_PDPKTRACEPARTTXB_V##ver:\
1404 case NSPR_PDPKTRACEPARTRX_V##ver:\
1405 PACKET_DESCRIBE(rec,buf,PART,ver,v##ver##_part,pp,pktracepart_v##ver,HEADERVER);
1407 #define GENERATE_CASE_PART_V25(rec,buf,ver,HEADERVER) \
1408 case NSPR_PDPKTRACEPARTTX_V##ver:\
1409 case NSPR_PDPKTRACEPARTTXB_V##ver:\
1410 case NSPR_PDPKTRACEPARTRX_V##ver:\
1411 case NSPR_PDPKTRACEPARTNEWRX_V##ver:\
1412 PACKET_DESCRIBE(rec,buf,PART,ver,v##ver##_part,pp,pktracepart_v##ver,HEADERVER);
1414 GENERATE_CASE_FULL(rec,buf,20,200);
1415 GENERATE_CASE_PART(rec,buf,20,200);
1416 GENERATE_CASE_FULL(rec,buf,21,201);
1417 GENERATE_CASE_PART(rec,buf,21,201);
1418 GENERATE_CASE_FULL(rec,buf,22,202);
1419 GENERATE_CASE_PART(rec,buf,22,202);
1420 GENERATE_CASE_FULL(rec,buf,23,203);
1421 GENERATE_CASE_PART(rec,buf,23,203);
1422 GENERATE_CASE_FULL_V25(rec,buf,24,204);
1423 GENERATE_CASE_PART_V25(rec,buf,24,204);
1424 GENERATE_CASE_FULL_V25(rec,buf,25,205);
1425 GENERATE_CASE_PART_V25(rec,buf,25,205);
1426 GENERATE_CASE_FULL_V25(rec,buf,26,206);
1427 GENERATE_CASE_PART_V25(rec,buf,26,206);
1429 #undef GENERATE_CASE_FULL
1430 #undef GENERATE_CASE_FULL_V25
1431 #undef GENERATE_CASE_PART
1432 #undef GENERATE_CASE_PART_V25
1434 case NSPR_ABSTIME_V20:
1436 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_pktracefull_v20_t), err, err_info))
1437 return false;
1438 nspr_pktracefull_v20_t *fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1439 if (nspr_getv20recordsize((nspr_hd_v20_t *)fp20) == 0) {
1440 *err = WTAP_ERR_BAD_FILE;
1441 *err_info = g_strdup("nstrace: zero size record found");
1442 return false;
1444 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_hd_v20_t), err, err_info))
1445 return false;
1446 nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1447 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_abstime_v20_t), err, err_info))
1448 return false;
1449 ns_setabstime(nstrace, pletoh32(&((nspr_abstime_v20_t *) fp20)->abs_Time), pletoh16(&((nspr_abstime_v20_t *) fp20)->abs_RelTime));
1450 break;
1453 case NSPR_RELTIME_V20:
1455 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_pktracefull_v20_t), err, err_info))
1456 return false;
1457 nspr_pktracefull_v20_t *fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1458 if (nspr_getv20recordsize((nspr_hd_v20_t *)fp20) == 0) {
1459 *err = WTAP_ERR_BAD_FILE;
1460 *err_info = g_strdup("nstrace: zero size record found");
1461 return false;
1463 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_abstime_v20_t), err, err_info))
1464 return false;
1465 ns_setrelativetime(nstrace, pletoh16(&((nspr_abstime_v20_t *) fp20)->abs_RelTime));
1466 nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1467 break;
1470 case NSPR_UNUSEDSPACE_V20:
1472 if (nstrace_buf_offset >= NSPR_PAGESIZE/2)
1473 nstrace_buf_offset = nstrace_buflen;
1474 else
1475 nstrace_buf_offset = NSPR_PAGESIZE/2;
1476 break;
1479 default:
1481 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_pktracefull_v20_t), err, err_info))
1482 return false;
1483 nspr_pktracefull_v20_t *fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1484 if (nspr_getv20recordsize((nspr_hd_v20_t *)fp20) == 0) {
1485 *err = WTAP_ERR_BAD_FILE;
1486 *err_info = g_strdup("nstrace: zero size record found");
1487 return false;
1489 nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1490 break;
1495 nstrace_buf_offset = 0;
1496 nstrace->xxx_offset += nstrace_buflen;
1497 nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));
1498 }while((nstrace_buflen > 0) && (nstrace_read_page(wth, err, err_info)));
1500 return false;
1503 #undef PACKET_DESCRIBE
1505 #define SETETHOFFSET_35(rec)\
1506 (rec)->rec_header.packet_header.pseudo_header.nstr.eth_offset = pletoh16(&fp->fp_headerlen);\
1508 #define SETETHOFFSET_30(rec) ;\
1510 #define TIMEDEFV30(rec,fp,type) \
1511 do {\
1512 (rec)->presence_flags = WTAP_HAS_TS;\
1513 /* access _AbsTimeHr as a 64bit value */\
1514 nsg_creltime = pletoh64(fp->type##_AbsTimeHr);\
1515 (rec)->ts.secs = (uint32_t) (nsg_creltime / 1000000000);\
1516 (rec)->ts.nsecs = (uint32_t) (nsg_creltime % 1000000000);\
1517 }while(0)
1519 #define TIMEDEFV35 TIMEDEFV30
1522 ** The maximum value of the record data size is 65535, which is less than
1523 ** WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
1525 #define FULLSIZEDEFV30(rec,fp,ver)\
1526 do {\
1527 (rec)->presence_flags |= WTAP_HAS_CAP_LEN;\
1528 (rec)->rec_header.packet_header.len = pletoh16(&fp->fp_PktSizeOrg) + nspr_pktracefull_v##ver##_s + fp->fp_src_vmname_len + fp->fp_dst_vmname_len;\
1529 (rec)->rec_header.packet_header.caplen = nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
1530 }while(0)
1532 #define FULLSIZEDEFV35(rec,fp,ver)\
1533 do {\
1534 (rec)->presence_flags |= WTAP_HAS_CAP_LEN;\
1535 (rec)->rec_header.packet_header.len = pletoh16(&fp->fp_PktSizeOrg) + pletoh16(&fp->fp_headerlen);\
1536 (rec)->rec_header.packet_header.caplen = nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
1537 }while(0)
1539 #define PACKET_DESCRIBE(rec,buf,FULLPART,ver,enumprefix,type,structname,HEADERVER)\
1540 do {\
1541 /* Make sure the record header is entirely contained in the page */\
1542 if ((nstrace->nstrace_buflen - nstrace_buf_offset) < sizeof(nspr_##structname##_t)) {\
1543 *err = WTAP_ERR_BAD_FILE;\
1544 *err_info = g_strdup("nstrace: record header crosses page boundary");\
1545 g_free(nstrace_tmpbuff);\
1546 return false;\
1548 nspr_##structname##_t *fp = (nspr_##structname##_t *) &nstrace_buf[nstrace_buf_offset];\
1549 (rec)->rec_type = REC_TYPE_PACKET;\
1550 (rec)->block = wtap_block_create(WTAP_BLOCK_PACKET);\
1551 TIMEDEFV##ver((rec),fp,type);\
1552 FULLPART##SIZEDEFV##ver((rec),fp,ver);\
1553 TRACE_V##ver##_REC_LEN_OFF((rec),enumprefix,type,structname);\
1554 SETETHOFFSET_##ver(rec)\
1555 (rec)->rec_header.packet_header.pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##HEADERVER;\
1556 /* Check sanity of record size */\
1557 if ((rec)->rec_header.packet_header.caplen < sizeof *fp) {\
1558 *err = WTAP_ERR_BAD_FILE;\
1559 *err_info = g_strdup("nstrace: record size is less than record header size");\
1560 g_free(nstrace_tmpbuff);\
1561 return false;\
1563 ws_buffer_assure_space((buf), (rec)->rec_header.packet_header.caplen);\
1564 *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
1565 /* Copy record header */\
1566 while (nstrace_tmpbuff_off < nspr_##structname##_s) {\
1567 if (nstrace_buf_offset >= nstrace_buflen) {\
1568 *err = WTAP_ERR_BAD_FILE;\
1569 *err_info = g_strdup("nstrace: malformed file");\
1570 g_free(nstrace_tmpbuff);\
1571 return false;\
1573 nstrace_tmpbuff[nstrace_tmpbuff_off++] = nstrace_buf[nstrace_buf_offset++];\
1575 nst_dataSize = nspr_getv20recordsize(hdp);\
1576 rec_size = nst_dataSize - nstrace_tmpbuff_off;\
1577 nsg_nextPageOffset = ((nstrace_buf_offset + rec_size) >= (unsigned)nstrace->nstrace_buflen) ?\
1578 ((nstrace_buf_offset + rec_size) - (NSPR_PAGESIZE_TRACE - 1)) : 0;\
1579 /* Copy record data */\
1580 while (nsg_nextPageOffset) {\
1581 /* Copy everything from this page */\
1582 while (nstrace_buf_offset < nstrace->nstrace_buflen) {\
1583 nstrace_tmpbuff[nstrace_tmpbuff_off++] = nstrace_buf[nstrace_buf_offset++];\
1585 nstrace->xxx_offset += nstrace_buflen;\
1586 nstrace_buflen = NSPR_PAGESIZE_TRACE;\
1587 /* Read the next page */\
1588 bytes_read = file_read(nstrace_buf, NSPR_PAGESIZE_TRACE, wth->fh);\
1589 if ( !file_eof(wth->fh) && bytes_read != NSPR_PAGESIZE_TRACE) {\
1590 g_free(nstrace_tmpbuff);\
1591 return false;\
1592 } else {\
1593 nstrace_buf_offset = 0;\
1595 nstrace_buflen = bytes_read;\
1596 rec_size = nst_dataSize - nstrace_tmpbuff_off;\
1597 nsg_nextPageOffset = ((nstrace_buf_offset + rec_size) >= (unsigned)nstrace->nstrace_buflen) ?\
1598 ((nstrace_buf_offset + rec_size) - (NSPR_PAGESIZE_TRACE- 1)): 0;\
1600 /* Copy the rest of the record */\
1601 while (nstrace_tmpbuff_off < nst_dataSize) {\
1602 nstrace_tmpbuff[nstrace_tmpbuff_off++] = nstrace_buf[nstrace_buf_offset++];\
1604 memcpy(ws_buffer_start_ptr((buf)), nstrace_tmpbuff, (rec)->rec_header.packet_header.caplen);\
1605 nstrace->nstrace_buf_offset = nstrace_buf_offset;\
1606 nstrace->nstrace_buflen = nstrace_buflen;\
1607 nstrace->nsg_creltime = nsg_creltime;\
1608 g_free(nstrace_tmpbuff);\
1609 return true;\
1610 } while(0)
1612 static bool nstrace_read_v30(wtap *wth, wtap_rec *rec, Buffer *buf,
1613 int *err, char **err_info, int64_t *data_offset)
1615 nstrace_t *nstrace = (nstrace_t *)wth->priv;
1616 uint64_t nsg_creltime;
1617 char *nstrace_buf = nstrace->pnstrace_buf;
1618 uint32_t nstrace_buf_offset = nstrace->nstrace_buf_offset;
1619 uint32_t nstrace_buflen = nstrace->nstrace_buflen;
1620 uint8_t* nstrace_tmpbuff;
1621 uint32_t nstrace_tmpbuff_off=0,nst_dataSize=0,rec_size=0,nsg_nextPageOffset=0;
1622 nspr_hd_v20_t *hdp;
1623 int bytes_read = 0;
1625 *err = 0;
1626 *err_info = NULL;
1627 if(nstrace_buflen == 0){
1628 return false; /* Reached End Of File */
1631 nstrace_tmpbuff = (uint8_t*)g_malloc(65536);
1636 if (nstrace_buf_offset >= nstrace_buflen) {
1637 *err = WTAP_ERR_BAD_FILE;
1638 *err_info = g_strdup("nstrace: malformed file");
1639 g_free(nstrace_tmpbuff);
1640 return false;
1643 if (!nstrace_buf[nstrace_buf_offset] && nstrace_buf_offset <= NSPR_PAGESIZE_TRACE){
1644 nstrace_buf_offset = NSPR_PAGESIZE_TRACE;
1646 if (file_eof(wth->fh) && bytes_read > 0 && bytes_read < NSPR_PAGESIZE_TRACE){
1647 memset(&nstrace_buf[bytes_read], 0, NSPR_PAGESIZE_TRACE-bytes_read);
1649 while ((nstrace_buf_offset < NSPR_PAGESIZE_TRACE) &&
1650 nstrace_buf[nstrace_buf_offset])
1652 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_hd_v20_t), err, err_info)) {
1653 g_free(nstrace_tmpbuff);
1654 return false;
1656 hdp = (nspr_hd_v20_t *) &nstrace_buf[nstrace_buf_offset];
1657 if (nspr_getv20recordsize(hdp) == 0) {
1658 *err = WTAP_ERR_BAD_FILE;
1659 *err_info = g_strdup("nstrace: zero size record found");
1660 g_free(nstrace_tmpbuff);
1661 return false;
1663 switch (hdp->phd_RecordType)
1666 #define GENERATE_CASE_FULL_V30(rec,buf,ver,HEADERVER) \
1667 case NSPR_PDPKTRACEFULLTX_V##ver:\
1668 case NSPR_PDPKTRACEFULLTXB_V##ver:\
1669 case NSPR_PDPKTRACEFULLRX_V##ver:\
1670 case NSPR_PDPKTRACEFULLNEWRX_V##ver:\
1671 PACKET_DESCRIBE(rec,buf,FULL,ver,v##ver##_full,fp,pktracefull_v##ver,HEADERVER);
1673 GENERATE_CASE_FULL_V30(rec,buf,30,300);
1675 #undef GENERATE_CASE_FULL_V30
1677 #define GENERATE_CASE_FULL_V35(rec,buf,ver,HEADERVER) \
1678 case NSPR_PDPKTRACEFULLTX_V##ver:\
1679 case NSPR_PDPKTRACEFULLTXB_V##ver:\
1680 case NSPR_PDPKTRACEFULLRX_V##ver:\
1681 case NSPR_PDPKTRACEFULLNEWRX_V##ver:\
1682 PACKET_DESCRIBE(rec,buf,FULL,ver,v##ver##_full,fp,pktracefull_v##ver,HEADERVER);
1683 GENERATE_CASE_FULL_V35(rec,buf,35,350);
1685 #undef GENERATE_CASE_FULL_V35
1687 case NSPR_ABSTIME_V20:
1689 nstrace_buf_offset += nspr_getv20recordsize(hdp);
1690 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_abstime_v20_t), err, err_info)) {
1691 g_free(nstrace_tmpbuff);
1692 return false;
1694 ns_setabstime(nstrace, pletoh32(&((nspr_abstime_v20_t *) &nstrace_buf[nstrace_buf_offset])->abs_Time), pletoh16(&((nspr_abstime_v20_t *) &nstrace_buf[nstrace_buf_offset])->abs_RelTime));
1695 break;
1698 case NSPR_RELTIME_V20:
1700 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_abstime_v20_t), err, err_info)) {
1701 g_free(nstrace_tmpbuff);
1702 return false;
1704 ns_setrelativetime(nstrace, pletoh16(&((nspr_abstime_v20_t *) &nstrace_buf[nstrace_buf_offset])->abs_RelTime));
1705 nstrace_buf_offset += nspr_getv20recordsize(hdp);
1706 break;
1709 default:
1711 if (!nstrace_ensure_buflen(nstrace, nstrace_buf_offset, sizeof(nspr_hd_v20_t), err, err_info)) {
1712 g_free(nstrace_tmpbuff);
1713 return false;
1715 nstrace_buf_offset += nspr_getv20recordsize(hdp);
1716 break;
1720 nstrace_buf_offset = 0;
1721 nstrace->xxx_offset += nstrace_buflen;
1722 nstrace_buflen = NSPR_PAGESIZE_TRACE;
1723 } while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) > 0 && (file_eof(wth->fh) || (uint32_t)bytes_read == nstrace_buflen));
1725 if (bytes_read < 0)
1726 *err = file_error(wth->fh, err_info);
1727 else
1728 *err = 0;
1729 g_free(nstrace_tmpbuff);
1730 return false;
1733 #undef PACKET_DESCRIBE
1736 * XXX - for these, we can't set the time stamp in the seek-read
1737 * routine, because the time stamps are relative.
1739 #undef TIMEDEFV10
1740 #define TIMEDEFV10(rec,fp,type) \
1741 do {\
1742 (rec)->presence_flags = 0;\
1743 }while(0)
1745 #define PACKET_DESCRIBE(rec,FULLPART,fullpart,ver,type,HEADERVER) \
1746 do {\
1747 nspr_pktrace##fullpart##_v##ver##_t *type = (nspr_pktrace##fullpart##_v##ver##_t *) pd;\
1748 (rec)->rec_type = REC_TYPE_PACKET;\
1749 (rec)->block = wtap_block_create(WTAP_BLOCK_PACKET);\
1750 TIMEDEFV##ver((rec),fp,type);\
1751 FULLPART##SIZEDEFV##ver((rec),type,ver);\
1752 TRACE_V##ver##_REC_LEN_OFF(rec,v##ver##_##fullpart,type,pktrace##fullpart##_v##ver);\
1753 (rec)->rec_header.packet_header.pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##HEADERVER;\
1754 }while(0)
1756 static bool nstrace_seek_read_v10(wtap *wth, int64_t seek_off,
1757 wtap_rec *rec, Buffer *buf, int *err, char **err_info)
1759 nspr_hd_v10_t hdr;
1760 unsigned record_length;
1761 uint8_t *pd;
1762 unsigned int bytes_to_read;
1764 *err = 0;
1766 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
1767 return false;
1770 ** Read the record header.
1772 if (!wtap_read_bytes(wth->random_fh, (void *)&hdr, sizeof hdr,
1773 err, err_info))
1774 return false;
1777 ** Get the record length.
1779 record_length = nspr_getv10recordsize(&hdr);
1782 ** Copy the header to the buffer and read the rest of the record..
1784 ws_buffer_assure_space(buf, record_length);
1785 pd = ws_buffer_start_ptr(buf);
1786 memcpy(pd, (void *)&hdr, sizeof hdr);
1787 if (record_length > sizeof hdr) {
1788 bytes_to_read = (unsigned int)(record_length - sizeof hdr);
1789 if (!wtap_read_bytes(wth->random_fh, pd + sizeof hdr, bytes_to_read,
1790 err, err_info))
1791 return false;
1795 ** Fill in what part of the struct wtap_rec we can.
1797 #define GENERATE_CASE_FULL(rec,type,HEADERVER) \
1798 case NSPR_PDPKTRACEFULLTX_V##type:\
1799 case NSPR_PDPKTRACEFULLTXB_V##type:\
1800 case NSPR_PDPKTRACEFULLRX_V##type:\
1801 PACKET_DESCRIBE(rec,FULL,full,type,fp,HEADERVER);\
1802 break;
1804 #define GENERATE_CASE_PART(rec,type,HEADERVER) \
1805 case NSPR_PDPKTRACEPARTTX_V##type:\
1806 case NSPR_PDPKTRACEPARTTXB_V##type:\
1807 case NSPR_PDPKTRACEPARTRX_V##type:\
1808 PACKET_DESCRIBE(rec,PART,part,type,pp,HEADERVER);\
1809 break;
1811 switch (pletoh16(&(( nspr_header_v10_t*)pd)->ph_RecordType))
1813 GENERATE_CASE_FULL(rec,10,100)
1814 GENERATE_CASE_PART(rec,10,100)
1817 #undef GENERATE_CASE_FULL
1818 #undef GENERATE_CASE_PART
1820 return true;
1823 #undef PACKET_DESCRIBE
1826 * XXX - for these, we can't set the time stamp in the seek-read
1827 * routine, because the time stamps are relative.
1829 #undef TIMEDEFV20
1830 #define TIMEDEFV20(rec,fp,type) \
1831 do {\
1832 (rec)->presence_flags = 0;\
1833 }while(0)
1835 #undef TIMEDEFV21
1836 #undef TIMEDEFV22
1837 #define TIMEDEFV21(rec,fp,type) TIMEDEFV20(rec,fp,type)
1838 #define TIMEDEFV22(rec,fp,type) TIMEDEFV20(rec,fp,type)
1840 #define PACKET_DESCRIBE(rec,FULLPART,ver,enumprefix,type,structname,HEADERVER)\
1841 do {\
1842 nspr_##structname##_t *fp= (nspr_##structname##_t*)pd;\
1843 (rec)->rec_type = REC_TYPE_PACKET;\
1844 (rec)->block = wtap_block_create(WTAP_BLOCK_PACKET);\
1845 TIMEDEFV##ver((rec),fp,type);\
1846 FULLPART##SIZEDEFV##ver((rec),fp,ver);\
1847 TRACE_V##ver##_REC_LEN_OFF((rec),enumprefix,type,structname);\
1848 (rec)->rec_header.packet_header.pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##HEADERVER;\
1849 return true;\
1850 }while(0)
1852 static bool nstrace_seek_read_v20(wtap *wth, int64_t seek_off,
1853 wtap_rec *rec, Buffer *buf, int *err, char **err_info)
1855 nspr_hd_v20_t hdr;
1856 unsigned record_length;
1857 unsigned hdrlen;
1858 uint8_t *pd;
1859 unsigned int bytes_to_read;
1860 uint64_t nsg_creltime;
1862 *err = 0;
1864 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
1865 return false;
1868 ** Read the first 2 bytes of the record header.
1870 if (!wtap_read_bytes(wth->random_fh, (void *)&hdr, 2, err, err_info))
1871 return false;
1872 hdrlen = 2;
1875 ** Is there a third byte? If so, read it.
1877 if (hdr.phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES) {
1878 if (!wtap_read_bytes(wth->random_fh, (void *)&hdr.phd_RecordSizeHigh, 1,
1879 err, err_info))
1880 return false;
1881 hdrlen = 3;
1885 ** Get the record length.
1887 record_length = nspr_getv20recordsize(&hdr);
1890 ** Copy the header to the buffer and read the rest of the record..
1892 ws_buffer_assure_space(buf, record_length);
1893 pd = ws_buffer_start_ptr(buf);
1894 memcpy(pd, (void *)&hdr, hdrlen);
1895 if (record_length > hdrlen) {
1896 bytes_to_read = (unsigned int)(record_length - hdrlen);
1897 if (!wtap_read_bytes(wth->random_fh, pd + hdrlen, bytes_to_read,
1898 err, err_info))
1899 return false;
1902 #define GENERATE_CASE_FULL(rec,ver,HEADERVER) \
1903 case NSPR_PDPKTRACEFULLTX_V##ver:\
1904 case NSPR_PDPKTRACEFULLTXB_V##ver:\
1905 case NSPR_PDPKTRACEFULLRX_V##ver:\
1906 PACKET_DESCRIBE(rec,FULL,ver,v##ver##_full,fp,pktracefull_v##ver,HEADERVER);
1908 #define GENERATE_CASE_FULL_V25(rec,ver,HEADERVER) \
1909 case NSPR_PDPKTRACEFULLTX_V##ver:\
1910 case NSPR_PDPKTRACEFULLTXB_V##ver:\
1911 case NSPR_PDPKTRACEFULLRX_V##ver:\
1912 case NSPR_PDPKTRACEFULLNEWRX_V##ver:\
1913 PACKET_DESCRIBE(rec,FULL,ver,v##ver##_full,fp,pktracefull_v##ver,HEADERVER);
1915 #define GENERATE_CASE_PART(rec,ver,HEADERVER) \
1916 case NSPR_PDPKTRACEPARTTX_V##ver:\
1917 case NSPR_PDPKTRACEPARTTXB_V##ver:\
1918 case NSPR_PDPKTRACEPARTRX_V##ver:\
1919 PACKET_DESCRIBE(rec,PART,ver,v##ver##_part,pp,pktracepart_v##ver,HEADERVER);
1921 #define GENERATE_CASE_PART_V25(rec,ver,HEADERVER) \
1922 case NSPR_PDPKTRACEPARTTX_V##ver:\
1923 case NSPR_PDPKTRACEPARTTXB_V##ver:\
1924 case NSPR_PDPKTRACEPARTRX_V##ver:\
1925 case NSPR_PDPKTRACEPARTNEWRX_V##ver:\
1926 PACKET_DESCRIBE(rec,PART,ver,v##ver##_part,pp,pktracepart_v##ver,HEADERVER);
1928 switch ((( nspr_hd_v20_t*)pd)->phd_RecordType)
1930 GENERATE_CASE_FULL(rec,20,200)
1931 GENERATE_CASE_PART(rec,20,200)
1932 GENERATE_CASE_FULL(rec,21,201)
1933 GENERATE_CASE_PART(rec,21,201)
1934 GENERATE_CASE_FULL(rec,22,202)
1935 GENERATE_CASE_PART(rec,22,202)
1936 GENERATE_CASE_FULL(rec,23,203)
1937 GENERATE_CASE_PART(rec,23,203)
1938 GENERATE_CASE_FULL_V25(rec,24,204)
1939 GENERATE_CASE_PART_V25(rec,24,204)
1940 GENERATE_CASE_FULL_V25(rec,25,205)
1941 GENERATE_CASE_PART_V25(rec,25,205)
1942 GENERATE_CASE_FULL_V25(rec,26,206)
1943 GENERATE_CASE_PART_V25(rec,26,206)
1946 #undef GENERATE_CASE_FULL
1947 #undef GENERATE_CASE_FULL_V25
1948 #undef GENERATE_CASE_PART
1949 #undef GENERATE_CASE_PART_V25
1951 return true;
1954 #undef PACKET_DESCRIBE
1955 #undef SETETHOFFSET_35
1956 #undef SETETHOFFSET_30
1958 #define SETETHOFFSET_35(rec)\
1960 (rec)->rec_header.packet_header.pseudo_header.nstr.eth_offset = pletoh16(&fp->fp_headerlen);\
1963 #define SETETHOFFSET_30(rec) ;\
1965 #define PACKET_DESCRIBE(rec,FULLPART,ver,enumprefix,type,structname,HEADERVER)\
1966 do {\
1967 nspr_##structname##_t *fp= (nspr_##structname##_t*)pd;\
1968 (rec)->rec_type = REC_TYPE_PACKET;\
1969 (rec)->block = wtap_block_create(WTAP_BLOCK_PACKET);\
1970 TIMEDEFV##ver((rec),fp,type);\
1971 SETETHOFFSET_##ver(rec);\
1972 FULLPART##SIZEDEFV##ver((rec),fp,ver);\
1973 TRACE_V##ver##_REC_LEN_OFF((rec),enumprefix,type,structname);\
1974 (rec)->rec_header.packet_header.pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##HEADERVER;\
1975 return true;\
1976 }while(0)
1978 static bool nstrace_seek_read_v30(wtap *wth, int64_t seek_off,
1979 wtap_rec *rec, Buffer *buf, int *err, char **err_info)
1981 nspr_hd_v20_t hdr;
1982 unsigned record_length;
1983 unsigned hdrlen;
1984 uint8_t *pd;
1985 unsigned int bytes_to_read;
1986 uint64_t nsg_creltime;
1988 *err = 0;
1990 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
1991 return false;
1993 ** Read the first 2 bytes of the record header.
1995 if (!wtap_read_bytes(wth->random_fh, (void *)&hdr, 2, err, err_info))
1996 return false;
1997 hdrlen = 2;
2000 ** Is there a third byte? If so, read it.
2002 if (hdr.phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES) {
2003 if (!wtap_read_bytes(wth->random_fh, (void *)&hdr.phd_RecordSizeHigh, 1,
2004 err, err_info))
2005 return false;
2006 hdrlen = 3;
2010 ** Get the record length.
2011 ** The maximum value of the record data size is 65535, which is less
2012 ** than WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check it.
2014 record_length = nspr_getv20recordsize(&hdr);
2017 ** Copy the header to the buffer and read the rest of the record..
2019 ws_buffer_assure_space(buf, record_length);
2020 pd = ws_buffer_start_ptr(buf);
2021 memcpy(pd, (void *)&hdr, hdrlen);
2022 if (record_length > hdrlen) {
2023 bytes_to_read = (unsigned int)(record_length - hdrlen);
2024 if (!wtap_read_bytes(wth->random_fh, pd + hdrlen, bytes_to_read,
2025 err, err_info))
2026 return false;
2029 (rec)->rec_header.packet_header.caplen = (rec)->rec_header.packet_header.len = record_length;
2031 #define GENERATE_CASE_V30(rec,ver,HEADERVER) \
2032 case NSPR_PDPKTRACEFULLTX_V##ver:\
2033 case NSPR_PDPKTRACEFULLTXB_V##ver:\
2034 case NSPR_PDPKTRACEFULLRX_V##ver:\
2035 case NSPR_PDPKTRACEFULLNEWRX_V##ver:\
2036 PACKET_DESCRIBE(rec,FULL,ver,v##ver##_full,fp,pktracefull_v##ver,HEADERVER);
2038 switch ((( nspr_hd_v20_t*)pd)->phd_RecordType)
2040 GENERATE_CASE_V30(rec,30, 300);
2041 GENERATE_CASE_V30(rec,35, 350);
2044 return true;
2049 ** Netscaler trace format close routines.
2051 static void nstrace_close(wtap *wth)
2053 nstrace_t *nstrace = (nstrace_t *)wth->priv;
2055 g_free(nstrace->pnstrace_buf);
2059 #define NSTRACE_1_0 0
2060 #define NSTRACE_2_0 1
2061 #define NSTRACE_3_0 2
2062 #define NSTRACE_3_5 3
2064 typedef struct {
2065 unsigned version;
2066 uint16_t page_offset;
2067 uint16_t page_len;
2068 uint32_t absrec_time;
2069 bool newfile;
2070 } nstrace_dump_t;
2072 /* Returns 0 if we could write the specified encapsulation type,
2073 ** an error indication otherwise. */
2074 static int nstrace_10_dump_can_write_encap(int encap)
2076 if (encap == WTAP_ENCAP_NSTRACE_1_0)
2077 return 0;
2079 return WTAP_ERR_UNWRITABLE_ENCAP;
2083 /* Returns 0 if we could write the specified encapsulation type,
2084 ** an error indication otherwise. */
2085 static int nstrace_20_dump_can_write_encap(int encap)
2087 if (encap == WTAP_ENCAP_NSTRACE_2_0)
2088 return 0;
2090 return WTAP_ERR_UNWRITABLE_ENCAP;
2093 /* Returns 0 if we could write the specified encapsulation type,
2094 ** an error indication otherwise. */
2095 static int nstrace_30_dump_can_write_encap(int encap)
2097 if (encap == WTAP_ENCAP_NSTRACE_3_0)
2098 return 0;
2100 return WTAP_ERR_UNWRITABLE_ENCAP;
2103 /* Returns 0 if we could write the specified encapsulation type,
2104 ** an error indication otherwise. */
2105 static int nstrace_35_dump_can_write_encap(int encap)
2107 if (encap == WTAP_ENCAP_NSTRACE_3_5)
2108 return 0;
2110 return WTAP_ERR_UNWRITABLE_ENCAP;
2113 /* Returns true on success, false on failure; sets "*err" to an error code on
2114 ** failure */
2115 static bool nstrace_dump_open(wtap_dumper *wdh, unsigned version, int *err _U_,
2116 char **err_info _U_)
2118 nstrace_dump_t *nstrace;
2120 wdh->subtype_write = nstrace_dump;
2122 nstrace = g_new(nstrace_dump_t, 1);
2123 wdh->priv = (void *)nstrace;
2124 nstrace->version = version;
2125 nstrace->page_offset = 0;
2126 if ((nstrace->version == NSTRACE_3_0) ||
2127 (nstrace->version == NSTRACE_3_5))
2128 nstrace->page_len = NSPR_PAGESIZE_TRACE;
2129 else
2130 nstrace->page_len = NSPR_PAGESIZE;
2132 nstrace->absrec_time = 0;
2133 nstrace->newfile = true;
2135 return true;
2138 static bool nstrace_10_dump_open(wtap_dumper *wdh, int *err,
2139 char **err_info)
2141 return nstrace_dump_open(wdh, NSTRACE_1_0, err, err_info);
2144 static bool nstrace_20_dump_open(wtap_dumper *wdh, int *err,
2145 char **err_info)
2147 return nstrace_dump_open(wdh, NSTRACE_2_0, err, err_info);
2150 static bool nstrace_30_dump_open(wtap_dumper *wdh, int *err,
2151 char **err_info)
2153 return nstrace_dump_open(wdh, NSTRACE_3_0, err, err_info);
2156 static bool nstrace_35_dump_open(wtap_dumper *wdh, int *err,
2157 char **err_info)
2159 return nstrace_dump_open(wdh, NSTRACE_3_5, err, err_info);
2162 static bool nstrace_add_signature(wtap_dumper *wdh, int *err)
2164 nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
2166 if (nstrace->version == NSTRACE_1_0)
2168 uint16_t val16b;
2169 nspr_signature_v10_t sig10;
2171 /* populate the record */
2172 val16b = GUINT16_TO_LE(NSPR_SIGNATURE_V10);
2173 memcpy(sig10.phd.ph_RecordType, &val16b, sizeof sig10.phd.ph_RecordType);
2174 val16b = GUINT16_TO_LE(nspr_signature_v10_s);
2175 memcpy(sig10.phd.ph_RecordSize, &val16b, sizeof sig10.phd.ph_RecordSize);
2176 memset(sig10.sig_Signature, 0, NSPR_SIGSIZE_V10);
2177 (void) g_strlcpy(sig10.sig_Signature, NSPR_SIGSTR_V10, NSPR_SIGSIZE_V10);
2179 /* Write the record into the file */
2180 if (!wtap_dump_file_write(wdh, &sig10, nspr_signature_v10_s,
2181 err))
2182 return false;
2184 /* Move forward the page offset */
2185 nstrace->page_offset += (uint16_t) nspr_signature_v10_s;
2187 } else if (nstrace->version == NSTRACE_2_0)
2189 nspr_signature_v20_t sig20;
2191 sig20.sig_RecordType = NSPR_SIGNATURE_V20;
2192 sig20.sig_RecordSize = nspr_signature_v20_s;
2193 memcpy(sig20.sig_Signature, NSPR_SIGSTR_V20, sizeof(NSPR_SIGSTR_V20));
2195 /* Write the record into the file */
2196 if (!wtap_dump_file_write(wdh, &sig20, sig20.sig_RecordSize,
2197 err))
2198 return false;
2200 /* Move forward the page offset */
2201 nstrace->page_offset += (uint16_t) sig20.sig_RecordSize;
2203 } else if (nstrace->version == NSTRACE_3_0)
2205 nspr_signature_v30_t sig30;
2207 sig30.sig_RecordType = NSPR_SIGNATURE_V30;
2208 sig30.sig_RecordSize = nspr_signature_v30_s;
2209 memcpy(sig30.sig_Signature, NSPR_SIGSTR_V30, sizeof(NSPR_SIGSTR_V30));
2211 /* Write the record into the file */
2212 if (!wtap_dump_file_write(wdh, &sig30, sig30.sig_RecordSize,
2213 err))
2214 return false;
2216 /* Move forward the page offset */
2217 nstrace->page_offset += (uint16_t) sig30.sig_RecordSize;
2218 } else if (nstrace->version == NSTRACE_3_5)
2220 nspr_signature_v35_t sig35;
2222 sig35.sig_RecordType = NSPR_SIGNATURE_V35;
2223 sig35.sig_RecordSize = nspr_signature_v35_s;
2224 memcpy(sig35.sig_Signature, NSPR_SIGSTR_V35, sizeof(NSPR_SIGSTR_V35));
2226 /* Write the record into the file */
2227 if (!wtap_dump_file_write(wdh, &sig35, sig35.sig_RecordSize,
2228 err))
2229 return false;
2231 /* Move forward the page offset */
2232 nstrace->page_offset += (uint16_t) sig35.sig_RecordSize;
2233 } else
2235 ws_assert_not_reached();
2236 return false;
2239 return true;
2243 static bool
2244 nstrace_add_abstime(wtap_dumper *wdh, const wtap_rec *rec,
2245 const uint8_t *pd, int *err)
2247 nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
2248 uint64_t nsg_creltime;
2250 if (nstrace->version == NSTRACE_1_0)
2252 uint16_t val16;
2253 uint32_t reltime;
2254 uint64_t abstime;
2255 nspr_abstime_v10_t abs10;
2257 /* populate the record */
2258 val16 = GUINT16_TO_LE(NSPR_ABSTIME_V10);
2259 memcpy(abs10.phd.ph_RecordType, &val16, sizeof abs10.phd.ph_RecordType);
2260 val16 = GUINT16_TO_LE(nspr_abstime_v10_s);
2261 memcpy(abs10.phd.ph_RecordSize, &val16, sizeof abs10.phd.ph_RecordSize);
2263 memcpy(&reltime, ((const nspr_pktracefull_v10_t *)pd)->fp_RelTimeHr, sizeof reltime);
2264 nsg_creltime = ns_hrtime2nsec(reltime);
2266 memset(abs10.abs_RelTime, 0, sizeof abs10.abs_RelTime);
2267 abstime = GUINT32_TO_LE((uint32_t)rec->ts.secs - (uint32_t)(nsg_creltime/1000000000));
2268 memcpy(abs10.abs_Time, &abstime, sizeof abs10.abs_Time);
2270 /* Write the record into the file */
2271 if (!wtap_dump_file_write(wdh, &abs10, nspr_abstime_v10_s, err))
2272 return false;
2274 /* Move forward the page offset */
2275 nstrace->page_offset += nspr_abstime_v10_s;
2277 } else if ((nstrace->version == NSTRACE_2_0) ||
2278 (nstrace->version == NSTRACE_3_0) ||
2279 (nstrace->version == NSTRACE_3_5)) {
2280 uint32_t reltime;
2281 uint64_t abstime;
2282 nspr_abstime_v20_t abs20;
2284 abs20.abs_RecordType = NSPR_ABSTIME_V20;
2285 abs20.abs_RecordSize = nspr_abstime_v20_s;
2287 memcpy(&reltime, ((const nspr_pktracefull_v20_t *)pd)->fp_RelTimeHr, sizeof reltime);
2288 nsg_creltime = ns_hrtime2nsec(reltime);
2290 memset(abs20.abs_RelTime, 0, sizeof abs20.abs_RelTime);
2291 abstime = GUINT32_TO_LE((uint32_t)rec->ts.secs - (uint32_t)(nsg_creltime/1000000000));
2292 memcpy(abs20.abs_RelTime, &abstime, sizeof abs20.abs_RelTime);
2294 /* Write the record into the file */
2295 if (!wtap_dump_file_write(wdh, &abs20, nspr_abstime_v20_s, err))
2296 return false;
2298 /* Move forward the page offset */
2299 nstrace->page_offset += nspr_abstime_v20_s;
2301 } else
2303 ws_assert_not_reached();
2304 return false;
2307 return true;
2311 /* Write a record for a packet to a dump file.
2312 Returns true on success, false on failure. */
2313 static bool nstrace_dump(wtap_dumper *wdh, const wtap_rec *rec,
2314 const uint8_t *pd, int *err, char **err_info _U_)
2316 nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
2318 /* We can only write packet records. */
2319 if (rec->rec_type != REC_TYPE_PACKET) {
2320 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
2321 return false;
2325 * Make sure this packet doesn't have a link-layer type that
2326 * differs from the one for the file.
2328 if (wdh->file_encap != rec->rec_header.packet_header.pkt_encap) {
2329 *err = WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
2330 return false;
2333 if (nstrace->newfile == true)
2335 nstrace->newfile = false;
2336 /* Add the signature record and abs time record */
2337 if (nstrace->version == NSTRACE_1_0)
2339 if (!nstrace_add_signature(wdh, err) ||
2340 !nstrace_add_abstime(wdh, rec, pd, err))
2341 return false;
2342 } else if (nstrace->version == NSTRACE_2_0)
2344 if (!nstrace_add_signature(wdh, err) ||
2345 !nstrace_add_abstime(wdh, rec, pd, err))
2346 return false;
2347 } else if (nstrace->version == NSTRACE_3_0 ||
2348 nstrace->version == NSTRACE_3_5 )
2350 if (!nstrace_add_signature(wdh, err) ||
2351 !nstrace_add_abstime(wdh, rec, pd, err))
2352 return false;
2353 } else
2355 ws_assert_not_reached();
2356 return false;
2360 switch (rec->rec_header.packet_header.pseudo_header.nstr.rec_type)
2362 case NSPR_HEADER_VERSION100:
2364 if (nstrace->version == NSTRACE_1_0)
2366 if (nstrace->page_offset + rec->rec_header.packet_header.caplen >= nstrace->page_len)
2368 /* Start on the next page */
2369 if (wtap_dump_file_seek(wdh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR, err) == -1)
2370 return false;
2372 nstrace->page_offset = 0;
2374 /* Possibly add signature and abstime records and increment offset */
2375 if (!nstrace_add_signature(wdh, err))
2376 return false;
2379 /* Write the actual record as is */
2380 if (!wtap_dump_file_write(wdh, pd, rec->rec_header.packet_header.caplen, err))
2381 return false;
2383 nstrace->page_offset += (uint16_t) rec->rec_header.packet_header.caplen;
2384 } else if (nstrace->version == NSTRACE_2_0)
2386 *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
2387 return false;
2390 break;
2392 case NSPR_HEADER_VERSION200:
2393 case NSPR_HEADER_VERSION201:
2394 case NSPR_HEADER_VERSION202:
2395 case NSPR_HEADER_VERSION203:
2396 case NSPR_HEADER_VERSION204:
2397 case NSPR_HEADER_VERSION205:
2398 case NSPR_HEADER_VERSION206:
2399 if (nstrace->version == NSTRACE_1_0)
2401 *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
2402 return false;
2403 } else if (nstrace->version == NSTRACE_2_0)
2405 if (nstrace->page_offset + rec->rec_header.packet_header.caplen >= nstrace->page_len)
2407 /* Start on the next page */
2408 if (wtap_dump_file_seek(wdh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR, err) == -1)
2409 return false;
2411 nstrace->page_offset = 0;
2413 /* Possibly add signature and abstime records and increment offset */
2414 if (!nstrace_add_signature(wdh, err))
2415 return false;
2418 /* Write the actual record as is */
2419 if (!wtap_dump_file_write(wdh, pd, rec->rec_header.packet_header.caplen, err))
2420 return false;
2422 nstrace->page_offset += (uint16_t) rec->rec_header.packet_header.caplen;
2425 break;
2427 case NSPR_HEADER_VERSION300:
2428 case NSPR_HEADER_VERSION350:
2429 if (nstrace->version == NSTRACE_1_0)
2431 *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
2432 return false;
2433 } else if (nstrace->version == NSTRACE_2_0)
2435 *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
2436 return false;
2437 } else if (nstrace->version == NSTRACE_3_0 || nstrace->version == NSTRACE_3_5)
2439 if (nstrace->page_offset + rec->rec_header.packet_header.caplen >= nstrace->page_len)
2441 /* Start on the next page */
2442 if (wtap_dump_file_seek(wdh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR, err) == -1)
2443 return false;
2445 nstrace->page_offset = 0;
2447 /* Possibly add signature and abstime records and increment offset */
2448 if (!nstrace_add_signature(wdh, err))
2449 return false;
2452 /* Write the actual record as is */
2453 if (!wtap_dump_file_write(wdh, pd, rec->rec_header.packet_header.caplen, err))
2454 return false;
2456 nstrace->page_offset += (uint16_t) rec->rec_header.packet_header.caplen;
2457 } else
2459 ws_assert_not_reached();
2460 return false;
2462 break;
2464 default:
2465 ws_assert_not_reached();
2466 return false;
2469 return true;
2472 static const struct supported_block_type nstrace_1_0_blocks_supported[] = {
2474 * We support packet blocks, with no comments or other options.
2476 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
2479 static const struct file_type_subtype_info nstrace_1_0_info = {
2480 "NetScaler Trace (Version 1.0)", "nstrace10", NULL, NULL,
2481 true, BLOCKS_SUPPORTED(nstrace_1_0_blocks_supported),
2482 nstrace_10_dump_can_write_encap, nstrace_10_dump_open, NULL
2485 static const struct supported_block_type nstrace_2_0_blocks_supported[] = {
2487 * We support packet blocks, with no comments or other options.
2489 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
2492 static const struct file_type_subtype_info nstrace_2_0_info = {
2493 "NetScaler Trace (Version 2.0)", "nstrace20", "cap", NULL,
2494 true, BLOCKS_SUPPORTED(nstrace_2_0_blocks_supported),
2495 nstrace_20_dump_can_write_encap, nstrace_20_dump_open, NULL
2498 static const struct supported_block_type nstrace_3_0_blocks_supported[] = {
2500 * We support packet blocks, with no comments or other options.
2502 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
2505 static const struct file_type_subtype_info nstrace_3_0_info = {
2506 "NetScaler Trace (Version 3.0)", "nstrace30", "cap", NULL,
2507 true, BLOCKS_SUPPORTED(nstrace_3_0_blocks_supported),
2508 nstrace_30_dump_can_write_encap, nstrace_30_dump_open, NULL
2511 static const struct supported_block_type nstrace_3_5_blocks_supported[] = {
2513 * We support packet blocks, with no comments or other options.
2515 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
2518 static const struct file_type_subtype_info nstrace_3_5_info = {
2519 "NetScaler Trace (Version 3.5)", "nstrace35", "cap", NULL,
2520 true, BLOCKS_SUPPORTED(nstrace_3_5_blocks_supported),
2521 nstrace_35_dump_can_write_encap, nstrace_35_dump_open, NULL
2524 void register_nstrace(void)
2526 nstrace_1_0_file_type_subtype = wtap_register_file_type_subtype(&nstrace_1_0_info);
2527 nstrace_2_0_file_type_subtype = wtap_register_file_type_subtype(&nstrace_2_0_info);
2528 nstrace_3_0_file_type_subtype = wtap_register_file_type_subtype(&nstrace_3_0_info);
2529 nstrace_3_5_file_type_subtype = wtap_register_file_type_subtype(&nstrace_3_5_info);
2532 * Register names for backwards compatibility with the
2533 * wtap_filetypes table in Lua.
2535 wtap_register_backwards_compatibility_lua_name("NETSCALER_1_0",
2536 nstrace_1_0_file_type_subtype);
2537 wtap_register_backwards_compatibility_lua_name("NETSCALER_2_0",
2538 nstrace_2_0_file_type_subtype);
2539 wtap_register_backwards_compatibility_lua_name("NETSCALER_3_0",
2540 nstrace_3_0_file_type_subtype);
2541 wtap_register_backwards_compatibility_lua_name("NETSCALER_3_5",
2542 nstrace_3_5_file_type_subtype);
2546 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2548 * Local variables:
2549 * c-basic-offset: 4
2550 * tab-width: 8
2551 * indent-tabs-mode: nil
2552 * End:
2554 * vi: set shiftwidth=4 tabstop=8 expandtab:
2555 * :indentSize=4:tabSize=8:noTabs=true: