1c28c5f11bfc046cff996faf386cb652f35206fa
[metze/wireshark/wip.git] / wiretap / netscaler.c
1 /* netscaler.c
2  *
3  * Wiretap Library
4  * Copyright (c) 2006 by Ravi Kondamuru <Ravi.Kondamuru@citrix.com>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "config.h"
22 #include <errno.h>
23 #include <string.h>
24 #include "wtap-int.h"
25 #include "file_wrappers.h"
26 #include <wsutil/buffer.h>
27 #include "netscaler.h"
28
29 /* Defines imported from netscaler code: nsperfrc.h */
30
31 #define NSPR_SIGSTR_V10 "NetScaler Performance Data"
32 #define NSPR_SIGSTR_V20 "NetScaler V20 Performance Data"
33 #define NSPR_SIGSTR     NSPR_SIGSTR_V20
34 #define NSPR_SIGSTR_V30 "Netscaler V30 Performance Data"
35 /* Defined but not used */
36 #define NSPR_SIGSTR_V21 "NetScaler V21 Performance Data"
37 #define NSPR_SIGSTR_V22 "NetScaler V22 Performance Data"
38
39 /*
40  * NetScaler trace files are divided into 8K pages, with each page
41  * containing one or more records.  The last page of the file
42  * might be less than 8K bytes.
43  *
44  * Records are not split across page boundaries; if a record doesn't
45  * fit in what remains in a page, the page is padded with null bytes
46  * and the next record is put at the beginning of the next page.
47  * A record type value of 0 means "unused space", so if there are
48  * enough null bytes to constitute a record type value, it will
49  * look as if there's an "unused space" record (which has no fields
50  * other than the type and zero or more additional padding bytes).
51  */
52 #define NSPR_PAGESIZE   8192
53 #define NSPR_PAGESIZE_TRACE (2*NSPR_PAGESIZE)
54
55 /* The different record types
56 ** NOTE: The Record Type is two byte fields and unused space is recognized by
57 ** either bytes being zero, therefore no record should any byte value as
58 ** zero.
59 **
60 ** New Performance Record Type is only one byte.
61 */
62 #define NSPR_UNUSEDSPACE_V10    0x0000  /* rest of the page is unused */
63 #define NSPR_UNUSEDSPACE_V20    0x00    /* rest of the page is unused */
64 #define NSPR_SIGNATURE_V10      0x0101  /* signature */
65 #define NSPR_SIGNATURE_V20      0x01    /* signature */
66 #define NSPR_SIGNATURE_V30      NSPR_SIGNATURE_V20
67 #define NSPR_ABSTIME_V10        0x0107  /* data capture time in secs from 1970*/
68 #define NSPR_ABSTIME_V20        0x07    /* data capture time in secs from 1970*/
69 #define NSPR_RELTIME_V10        0x0108  /* relative time in ms from last time */
70 #define NSPR_RELTIME_V20        0x08    /* relative time in ms from last time */
71 #define NSPR_RELTIMEHR_V10      0x0109  /* high resolution relative time */
72 #define NSPR_RELTIMEHR_V20      0x09    /* high resolution relative time */
73 #define NSPR_SYSTARTIME_V10     0x010A  /* system start time */
74 #define NSPR_SYSTARTIME_V20     0x0A    /* system start time */
75 #define NSPR_RELTIME2B_V10      0x010B  /* relative time in ms from last time */
76 #define NSPR_RELTIME2B_V20      0x0B    /* relative time in ms from last time */
77
78
79 /* The high resolution relative time format.
80 ** The MS 2 bits of the high resoltion time is defined as follows:
81 ** 00 : time value is in seconds
82 ** 01 : time value is in milliseconds
83 ** 10 : time value is in microseconds
84 ** 11 : time value is in nanoseconds
85 */
86 #define NSPR_HRTIME_MASKTM      0x3FFFFFFF /* mask to get time value */
87 #define NSPR_HRTIME_MASKFMT     0xC0000000 /* time value format mask */
88 #define NSPR_HRTIME_SEC         0x00000000 /* time value in second */
89 #define NSPR_HRTIME_MSEC        0x40000000 /* time value in mili second */
90 #define NSPR_HRTIME_USEC        0x80000000 /* time value in micro second */
91 #define NSPR_HRTIME_NSEC        0xC0000000 /* time value in nano second */
92
93
94 typedef struct nspr_header_v10
95 {
96     guint8 ph_RecordType[2]; /* Record Type */
97     guint8 ph_RecordSize[2]; /* Record Size including header */
98 } nspr_header_v10_t;
99 #define nspr_header_v10_s    ((guint32)sizeof(nspr_header_v10_t))
100
101 /* This is V20 short header (2 bytes long) to be included where needed */
102 #define NSPR_HEADER_V20(prefix) \
103     guint8 prefix##_RecordType; /* Record Type */ \
104     guint8 prefix##_RecordSize  /* Record Size including header */ \
105                                 /* end of declaration */
106
107 /* This is new long header (3 bytes long) to be included where needed */
108 #define NSPR_HEADER3B_V20(prefix) \
109     guint8 prefix##_RecordType;    /* Record Type */ \
110     guint8 prefix##_RecordSizeLow; /* Record Size including header */ \
111     guint8 prefix##_RecordSizeHigh /* Record Size including header */ \
112                                    /* end of declaration */
113 #define NSPR_HEADER3B_V21 NSPR_HEADER3B_V20
114 #define NSPR_HEADER3B_V22 NSPR_HEADER3B_V20
115 #define NSPR_HEADER3B_V30 NSPR_HEADER3B_V20
116
117 typedef struct nspr_hd_v20
118 {
119     NSPR_HEADER3B_V20(phd); /* long performance header */
120
121 } nspr_hd_v20_t;
122 #define nspr_hd_v20_s    ((guint32)sizeof(nspr_hd_v20_t))
123
124
125 /*
126 ** How to know if header size is short or long?
127 ** The short header size can be 0-127 bytes long. If MS Bit of ph_RecordSize
128 ** is set then record size has 2 bytes
129 */
130 #define NSPR_V20RECORDSIZE_2BYTES       0x80
131
132 /* Performance Data Header with device number */
133 typedef struct nspr_headerdev_v10
134 {
135     guint8 ph_RecordType[2]; /* Record Type */
136     guint8 ph_RecordSize[2]; /* Record Size including header */
137     guint8 ph_DevNo[4];      /* Network Device (NIC/CONN) number */
138 } nspr_headerdev_v10_t;
139 #define nspr_headerdev_v10_s    ((guint32)sizeof(nspr_headerdev_v10_t))
140
141 typedef struct nspr_hd_v10
142 {
143     nspr_header_v10_t phd; /* performance header */
144 } nspr_hd_v10_t;
145 #define nspr_hd_v10_s    ((guint32)sizeof(nspr_hd_v10_t))
146
147 typedef struct nspr_hdev_v10
148 {
149     nspr_headerdev_v10_t phd; /* performance header */
150 } nspr_hdev_v10_t;
151 #define nspr_hdev_v10_s    ((guint32)sizeof(nspr_hdev_v10_t))
152
153 /* if structure has defined phd as first field, it can use following names */
154 #define nsprRecordType    phd.ph_RecordType
155 #define nsprRecordSize    phd.ph_RecordSize
156 #define nsprReserved      phd.ph_Reserved
157 #define nsprRecordTypeOrg phd.ph_Reserved
158 #define nsprDevNo         phd.ph_DevNo
159
160 /* NSPR_SIGNATURE_V10 structure */
161 #define NSPR_SIGSIZE_V10        56 /* signature value size in bytes */
162 typedef struct nspr_signature_v10
163 {
164     nspr_header_v10_t phd; /* performance header */
165     guint8 sig_EndianType; /* Endian Type for the data */
166     guint8 sig_Reserved0;
167     guint8 sig_Reserved1[2];
168     gchar sig_Signature[NSPR_SIGSIZE_V10]; /* Signature value */
169 } nspr_signature_v10_t;
170 #define nspr_signature_v10_s    ((guint32)sizeof(nspr_signature_v10_t))
171
172 /* NSPR_SIGNATURE_V20 structure */
173 #define NSPR_SIGSIZE_V20        sizeof(NSPR_SIGSTR_V20) /* signature value size in bytes */
174 typedef struct nspr_signature_v20
175 {
176     NSPR_HEADER_V20(sig);  /* short performance header */
177     guint8 sig_EndianType; /* Endian Type for the data */
178     gchar sig_Signature[NSPR_SIGSIZE_V20]; /* Signature value */
179 } nspr_signature_v20_t;
180 #define nspr_signature_v20_s    ((guint32)sizeof(nspr_signature_v20_t))
181
182 /* NSPR_SIGNATURE_V30 structure */
183 #define NSPR_SIGSIZE_V30        sizeof(NSPR_SIGSTR_V30) /* signature value size in bytes */
184 typedef struct nspr_signature_v30
185 {
186     NSPR_HEADER_V20(sig);  /* short performance header */
187     guint8 sig_EndianType; /* Endian Type for the data */
188     gchar sig_Signature[NSPR_SIGSIZE_V30]; /* Signature value */
189 } nspr_signature_v30_t;
190 #define nspr_signature_v30_s    ((guint32)sizeof(nspr_signature_v30_t))
191
192 /* NSPR_ABSTIME_V10 and NSPR_SYSTARTIME_V10 structure */
193 typedef struct nspr_abstime_v10
194 {
195     nspr_header_v10_t phd; /* performance header */
196     guint8 abs_RelTime[4]; /* relative time is ms from last time */
197     guint8 abs_Time[4];    /* absolute time in seconds from 1970 */
198 } nspr_abstime_v10_t;
199 #define nspr_abstime_v10_s    ((guint32)sizeof(nspr_abstime_v10_t))
200
201
202 /* NSPR_ABSTIME_V20 and NSPR_SYSTARTIME_V20 structure */
203 typedef struct nspr_abstime_v20
204 {
205     NSPR_HEADER_V20(abs);  /* short performance header */
206     guint8 abs_RelTime[2]; /* relative time is ms from last time */
207     guint8 abs_Time[4];    /* absolute time in seconds from 1970 */
208 } nspr_abstime_v20_t;
209 #define nspr_abstime_v20_s    ((guint32)sizeof(nspr_abstime_v20_t))
210
211
212
213 /* full packet trace structure */
214 typedef struct nspr_pktracefull_v10
215 {
216     nspr_headerdev_v10_t phd; /* performance header */
217     guint8 fp_RelTimeHr[4];   /* High resolution relative time */
218     guint8 fp_Data[1];        /* packet data starts here */
219 } nspr_pktracefull_v10_t;
220 #define nspr_pktracefull_v10_s    (nspr_hdev_v10_s + 4)
221
222 /* new full packet trace structure v20 */
223 typedef struct nspr_pktracefull_v20
224 {
225     NSPR_HEADER3B_V20(fp);  /* long performance header */
226     guint8 fp_DevNo;        /* Network Device (NIC) number */
227     guint8 fp_RelTimeHr[4]; /* High resolution relative time */
228     guint8 fp_Data[4];      /* packet data starts here */
229 } nspr_pktracefull_v20_t;
230 #define nspr_pktracefull_v20_s    ((guint32)(sizeof(nspr_pktracefull_v20_t) - 4))
231
232 /* new full packet trace structure v21 */
233 typedef struct nspr_pktracefull_v21
234 {
235     NSPR_HEADER3B_V21(fp);  /* long performance header */
236     guint8 fp_DevNo;        /* Network Device (NIC) number */
237     guint8 fp_RelTimeHr[4]; /* High resolution relative time */
238     guint8 fp_PcbDevNo[4];  /* PCB devno */
239     guint8 fp_lPcbDevNo[4]; /* link PCB devno */
240     guint8 fp_Data[4];      /* packet data starts here */
241 } nspr_pktracefull_v21_t;
242 #define nspr_pktracefull_v21_s    ((guint32)(sizeof(nspr_pktracefull_v21_t) - 4))
243
244 /* new full packet trace structure v22 */
245 typedef struct nspr_pktracefull_v22
246 {
247     NSPR_HEADER3B_V22(fp);  /* long performance header */
248     guint8 fp_DevNo;        /* Network Device (NIC) number */
249     guint8 fp_RelTimeHr[4]; /* High resolution relative time */
250     guint8 fp_PcbDevNo[4];  /* PCB devno */
251     guint8 fp_lPcbDevNo[4]; /* link PCB devno */
252     guint8 fp_VlanTag[2];   /* vlan tag */
253     guint8 fp_Data[2];      /* packet data starts here */
254 } nspr_pktracefull_v22_t;
255 #define nspr_pktracefull_v22_s    ((guint32)(sizeof(nspr_pktracefull_v22_t) - 2))
256
257 typedef struct nspr_pktracefull_v23
258 {
259     NSPR_HEADER3B_V22(fp);  /* long performance header */
260     guint8 fp_DevNo;        /* Network Device (NIC) number */
261     guint8 fp_AbsTimeHr[8]; /* High resolution absolute time */
262     guint8 fp_PcbDevNo[4];  /* PCB devno */
263     guint8 fp_lPcbDevNo[4]; /* link PCB devno */
264     guint8 fp_VlanTag[2];   /* vlan tag */
265     guint8 fp_Coreid[2];    /* coreid of the packet */
266     guint8 fp_Data[2];      /* packet data starts here */
267 } nspr_pktracefull_v23_t;
268 #define nspr_pktracefull_v23_s    ((guint32)(sizeof(nspr_pktracefull_v23_t) - 2))
269
270 /* New full packet trace structure v24 for cluster tracing */
271 typedef struct nspr_pktracefull_v24
272 {
273     NSPR_HEADER3B_V22(fp);   /* long performance header */
274     guint8 fp_DevNo;         /* Network Device (NIC) number */
275     guint8 fp_AbsTimeHr[8];  /* High resolution absolute time in nanosec */
276     guint8 fp_PcbDevNo[4];   /* PCB devno */
277     guint8 fp_lPcbDevNo[4];  /* link PCB devno */
278     guint8 fp_VlanTag[2];    /* vlan tag */
279     guint8 fp_Coreid[2];     /* coreid of the packet */
280     guint8 fp_srcNodeId[2];  /* source node # */
281     guint8 fp_destNodeId[2]; /* destination node # */
282     guint8 fp_clFlags;       /* cluster flags */
283     guint8 fp_Data[2];       /* packet data starts here */
284 } nspr_pktracefull_v24_t;
285 #define nspr_pktracefull_v24_s    ((guint32)(sizeof(nspr_pktracefull_v24_t) - 4))
286
287 /* New full packet trace structure v25 for vm info tracing */
288 typedef struct nspr_pktracefull_v25
289 {
290     NSPR_HEADER3B_V22(fp);    /* long performance header */
291     guint8 fp_DevNo;          /* Network Device (NIC) number */
292     guint8 fp_AbsTimeHr[8];   /* High resolution absolute time in nanosec */
293     guint8 fp_PcbDevNo[4];    /* PCB devno */
294     guint8 fp_lPcbDevNo[4];   /* link PCB devno */
295     guint8 fp_VlanTag[2];     /* vlan tag */
296     guint8 fp_Coreid[2];      /* coreid of the packet */
297     guint8 fp_srcNodeId[2];   /* source node # */
298     guint8 fp_destNodeId[2];  /* destination node # */
299     guint8 fp_clFlags;        /* cluster flags */
300     guint8 fp_src_vmname_len; /* vm src info */
301     guint8 fp_dst_vmname_len; /* vm src info */
302     guint8 fp_Data[4];        /* packet data starts here */
303 } nspr_pktracefull_v25_t;
304 #define nspr_pktracefull_v25_s    ((guint32)(sizeof(nspr_pktracefull_v25_t) - 4))
305 #define fp_src_vmname    fp_Data
306 #define fp_src_vmname    fp_Data
307
308 /* New full packet trace structure v26 for vm info tracing */
309 typedef struct nspr_pktracefull_v26
310 {
311     NSPR_HEADER3B_V22(fp);     /* long performance header */
312     guint8 fp_DevNo;           /* Network Device (NIC) number */
313     guint8 fp_AbsTimeHr[8];    /* High resolution absolute time in nanosec */
314     guint8 fp_PcbDevNo[4];     /* PCB devno */
315     guint8 fp_lPcbDevNo[4];    /* link PCB devno */
316     guint8 fp_VlanTag[2];      /* vlan tag */
317     guint8 fp_Coreid[2];       /* coreid of the packet */
318     guint8 fp_srcNodeId[2];    /* source node # */
319     guint8 fp_destNodeId[2];   /* destination node # */
320     guint8 fp_clFlags;         /* cluster flags */
321     guint8 fp_src_vmname_len;  /* vm src info */
322     guint8 fp_dst_vmname_len;  /* vm src info */
323     guint8 fp_reserved;
324     guint8 fp_ns_activity[4];
325     guint8 fp_reserved_32[12]; /* Adding more field to reduce wireshark changes every time */
326     guint8 fp_Data[4];         /* packet data starts here */
327 } nspr_pktracefull_v26_t;
328 #define nspr_pktracefull_v26_s    ((guint32)(sizeof(nspr_pktracefull_v26_t) - 4))
329
330 /* partial packet trace structure */
331 typedef struct nspr_pktracepart_v10
332 {
333     nspr_headerdev_v10_t phd; /* performance header */
334     guint8 pp_RelTimeHr[4];   /* High resolution relative time */
335     guint8 pp_PktSizeOrg[2];  /* Original packet size */
336     guint8 pp_PktOffset[2];   /* starting offset in packet */
337     guint8 pp_Data[1];        /* packet data starts here */
338 } nspr_pktracepart_v10_t;
339 #define nspr_pktracepart_v10_s    (nspr_pktracefull_v10_s + 4)
340
341 /* new partial packet trace structure */
342 typedef struct nspr_pktracepart_v20
343 {
344     NSPR_HEADER3B_V20(pp);   /* long performance header */
345     guint8 pp_DevNo;         /* Network Device (NIC) number */
346     guint8 pp_RelTimeHr[4];  /* High resolution relative time */
347     guint8 pp_PktSizeOrg[2]; /* Original packet size */
348     guint8 pp_PktOffset[2];  /* starting offset in packet */
349     guint8 pp_Data[4];       /* packet data starts here */
350 } nspr_pktracepart_v20_t;
351 #define nspr_pktracepart_v20_s    ((guint32)(sizeof(nspr_pktracepart_v20_t) -4))
352
353 /* new partial packet trace structure */
354 typedef struct nspr_pktracepart_v21
355 {
356     NSPR_HEADER3B_V21(pp);   /* long performance header */
357     guint8 pp_DevNo;         /* Network Device (NIC) number */
358     guint8 pp_RelTimeHr[4];  /* High resolution relative time */
359     guint8 pp_PktSizeOrg[2]; /* Original packet size */
360     guint8 pp_PktOffset[2];  /* starting offset in packet */
361     guint8 pp_PcbDevNo[4];   /* PCB devno */
362     guint8 pp_lPcbDevNo[4];  /* link PCB devno */
363     guint8 pp_Data[4];       /* packet data starts here */
364 } nspr_pktracepart_v21_t;
365 #define nspr_pktracepart_v21_s    ((guint32)(sizeof(nspr_pktracepart_v21_t) -4))
366
367 /* new partial packet trace structure v22 */
368 typedef struct nspr_pktracepart_v22
369 {
370     NSPR_HEADER3B_V22(pp);   /* long performance header */
371     guint8 pp_DevNo;         /* Network Device (NIC) number */
372     guint8 pp_RelTimeHr[4];  /* High resolution relative time */
373     guint8 pp_PktSizeOrg[2]; /* Original packet size */
374     guint8 pp_PktOffset[2];  /* starting offset in packet */
375     guint8 pp_PcbDevNo[4];   /* PCB devno */
376     guint8 pp_lPcbDevNo[4];  /* link PCB devno */
377     guint8 pp_VlanTag[2];    /* Vlan Tag */
378     guint8 pp_Data[2];       /* packet data starts here */
379 } nspr_pktracepart_v22_t;
380 #define nspr_pktracepart_v22_s    ((guint32)(sizeof(nspr_pktracepart_v22_t) -2))
381
382 typedef struct nspr_pktracepart_v23
383 {
384     NSPR_HEADER3B_V22(pp);   /* long performance header */
385     guint8 pp_DevNo;         /* Network Device (NIC) number */
386     guint8 pp_AbsTimeHr[8];  /* High resolution absolute time */
387     guint8 pp_PktSizeOrg[2]; /* Original packet size */
388     guint8 pp_PktOffset[2];  /* starting offset in packet */
389     guint8 pp_PcbDevNo[4];   /* PCB devno */
390     guint8 pp_lPcbDevNo[4];  /* link PCB devno */
391     guint8 pp_VlanTag[2];    /* vlan tag */
392     guint8 pp_Coreid[2];     /* Coreid of the packet */
393     guint8 pp_Data[4];       /* packet data starts here */
394 } nspr_pktracepart_v23_t;
395 #define nspr_pktracepart_v23_s    ((guint32)(sizeof(nspr_pktracepart_v23_t) -4))
396
397 /* New partial packet trace structure v24 for cluster tracing */
398 typedef struct nspr_pktracepart_v24
399 {
400     NSPR_HEADER3B_V22(pp);   /* long performance header */
401     guint8 pp_DevNo;         /* Network Device (NIC) number */
402     guint8 pp_AbsTimeHr[8];  /*High resolution absolute time in nanosec*/
403     guint8 pp_PktSizeOrg[2]; /* Original packet size */
404     guint8 pp_PktOffset[2];  /* starting offset in packet */
405     guint8 pp_PcbDevNo[4];   /* PCB devno */
406     guint8 pp_lPcbDevNo[4];  /* link PCB devno */
407     guint8 pp_VlanTag[2];    /* vlan tag */
408     guint8 pp_Coreid[2];     /* Coreid of the packet */
409     guint8 pp_srcNodeId[2];  /* source node # */
410     guint8 pp_destNodeId[2]; /* destination node # */
411     guint8 pp_clFlags;       /* cluster flags */
412     guint8 pp_Data[4];       /* packet data starts here */
413 } nspr_pktracepart_v24_t;
414 #define nspr_pktracepart_v24_s    ((guint32)(sizeof(nspr_pktracepart_v24_t) -4))
415
416 /* New partial packet trace structure v25 for vm info tracing */
417 typedef struct nspr_pktracepart_v25
418 {
419     NSPR_HEADER3B_V22(pp);    /* long performance header */
420     guint8 pp_DevNo;          /* Network Device (NIC) number */
421     guint8 pp_AbsTimeHr[8];   /*High resolution absolute time in nanosec*/
422     guint8 pp_PktSizeOrg[2];  /* Original packet size */
423     guint8 pp_PktOffset[2];   /* starting offset in packet */
424     guint8 pp_PcbDevNo[4];    /* PCB devno */
425     guint8 pp_lPcbDevNo[4];   /* link PCB devno */
426     guint8 pp_VlanTag[2];     /* vlan tag */
427     guint8 pp_Coreid[2];      /* Coreid of the packet */
428     guint8 pp_srcNodeId[2];   /* source node # */
429     guint8 pp_destNodeId[2];  /* destination node # */
430     guint8 pp_clFlags;        /* cluster flags */
431     guint8 pp_src_vmname_len; /* vm info */
432     guint8 pp_dst_vmname_len; /* vm info */
433     guint8 pp_Data[4];        /* packet data starts here */
434 } nspr_pktracepart_v25_t;
435 #define nspr_pktracepart_v25_s    ((guint32)(sizeof(nspr_pktracepart_v25_t) -4))
436 #define pp_src_vmname    pp_Data
437 #define pp_dst_vmname    pp_Data
438
439
440 /* New full packet trace structure v30 for multipage spanning data */
441 typedef struct  nspr_pktracefull_v30
442 {
443     NSPR_HEADER3B_V30(fp);  /* long performance header */
444     guint8 fp_DevNo;   /* Network Device (NIC) number */
445     guint8 fp_AbsTimeHr[8];  /*High resolution absolute time in nanosec*/
446     guint8 fp_PcbDevNo[4];    /* PCB devno */
447     guint8 fp_lPcbDevNo[4];   /* link PCB devno */
448     guint8 fp_PktSizeOrg[2];  /* Original packet size */
449     guint8 fp_VlanTag[2]; /* vlan tag */
450     guint8 fp_Coreid[2]; /* coreid of the packet */
451     guint8 fp_srcNodeId[2]; /* cluster nodeid of the packet */
452     guint8 fp_destNodeId[2];
453     guint8 fp_clFlags;
454     guint8 fp_src_vmname_len;
455     guint8 fp_dst_vmname_len;
456     guint8 fp_reserved[3];
457     guint8 fp_ns_activity[4];
458     guint8 fp_reserved_32[12];
459     guint8 fp_Data[0]; /* packet data starts here */
460 } nspr_pktracefull_v30_t;
461 #define nspr_pktracefull_v30_s  ((guint32)(sizeof(nspr_pktracefull_v30_t)))
462 #define fp_src_vmname   fp_Data
463 #define fp_dst_vmname   fp_Data
464
465 /* New partial packet trace structure v26 for vm info tracing */
466 typedef struct nspr_pktracepart_v26
467 {
468     NSPR_HEADER3B_V22(pp);     /* long performance header */
469     guint8 pp_DevNo;           /* Network Device (NIC) number */
470     guint8 pp_AbsTimeHr[8];    /*High resolution absolute time in nanosec*/
471     guint8 pp_PktSizeOrg[2];   /* Original packet size */
472     guint8 pp_PktOffset[2];    /* starting offset in packet */
473     guint8 pp_PcbDevNo[4];     /* PCB devno */
474     guint8 pp_lPcbDevNo[4];    /* link PCB devno */
475     guint8 pp_VlanTag[2];      /* vlan tag */
476     guint8 pp_Coreid[2];       /* Coreid of the packet */
477     guint8 pp_srcNodeId[2];    /* source node # */
478     guint8 pp_destNodeId[2];   /* destination node # */
479     guint8 pp_clFlags;         /* cluster flags */
480     guint8 pp_src_vmname_len;  /* vm info */
481     guint8 pp_dst_vmname_len;  /* vm info */
482     guint8 pp_reserved;
483     guint8 pp_ns_activity[4];
484     guint8 pp_reserved_32[12]; /* Adding more field to reduce wireshark changes every time */
485     guint8 pp_Data[4];         /* packet data starts here */
486 } nspr_pktracepart_v26_t;
487 #define nspr_pktracepart_v26_s    ((guint32)(sizeof(nspr_pktracepart_v26_t) -4))
488
489 #define myoffsetof(type,fieldname) (&(((type*)0)->fieldname))
490
491 #define __TNO(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
492     guint8 enumprefix##_##hdrname##_offset = (guint8)GPOINTER_TO_INT(myoffsetof(nspr_##structname##_t,structprefix##_##structfieldname));
493
494 #define __TNL(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
495     guint8 enumprefix##_##hdrname##_len = (guint8)sizeof(((nspr_##structname##_t*)0)->structprefix##_##structfieldname);
496
497 #define __TNV1O(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
498     guint8 enumprefix##_##hdrname##_offset = (guint8)GPOINTER_TO_INT(myoffsetof(nspr_##structname##_t,structfieldname));
499
500 #define __TNV1L(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
501     guint8 enumprefix##_##hdrname##_len = (guint8)sizeof(((nspr_##structname##_t*)0)->structfieldname);
502
503 #define TRACE_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
504     __TNV1O(phdr,enumprefix,structprefix,structname,dir,phd.ph_RecordType)\
505     __TNV1L(phdr,enumprefix,structprefix,structname,dir,phd.ph_RecordType)\
506     __TNV1O(phdr,enumprefix,structprefix,structname,nicno,phd.ph_DevNo)\
507     __TNV1L(phdr,enumprefix,structprefix,structname,nicno,phd.ph_DevNo)\
508     __TNO(phdr,enumprefix,structprefix,structname,eth,Data)
509
510 #define TRACE_FULL_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
511     (phdr)->len = pletoh16(&(fp)->nsprRecordSize);\
512     (phdr)->caplen = (phdr)->len;\
513     TRACE_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)
514
515 #define TRACE_PART_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
516     (phdr)->rec_type = REC_TYPE_PACKET;\
517     (phdr)->presence_flags |= WTAP_HAS_CAP_LEN;\
518     (phdr)->len =  pletoh16(&pp->pp_PktSizeOrg) + nspr_pktracepart_v10_s;\
519     (phdr)->caplen =  pletoh16(&pp->nsprRecordSize);\
520     TRACE_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)
521
522 #define TRACE_V20_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
523     __TNO(phdr,enumprefix,structprefix,structname,dir,RecordType)\
524     __TNL(phdr,enumprefix,structprefix,structname,dir,RecordType)\
525     __TNO(phdr,enumprefix,structprefix,structname,nicno,DevNo)\
526     __TNL(phdr,enumprefix,structprefix,structname,nicno,DevNo)\
527     __TNO(phdr,enumprefix,structprefix,structname,eth,Data)
528
529 #define TRACE_V21_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
530     TRACE_V20_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
531     __TNO(phdr,enumprefix,structprefix,structname,pcb,PcbDevNo)\
532     __TNO(phdr,enumprefix,structprefix,structname,l_pcb,lPcbDevNo)
533
534 #define TRACE_V22_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
535     TRACE_V21_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
536     __TNO(phdr,enumprefix,structprefix,structname,vlantag,VlanTag)
537
538 #define TRACE_V23_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
539     TRACE_V22_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
540     __TNO(phdr,enumprefix,structprefix,structname,coreid,Coreid)
541
542 #define TRACE_V24_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
543     TRACE_V23_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
544     __TNO(phdr,enumprefix,structprefix,structname,srcnodeid,srcNodeId)\
545     __TNO(phdr,enumprefix,structprefix,structname,destnodeid,destNodeId)\
546     __TNO(phdr,enumprefix,structprefix,structname,clflags,clFlags)
547
548 #define TRACE_V25_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
549     TRACE_V24_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
550     __TNO(phdr,enumprefix,structprefix,structname,src_vmname_len,src_vmname_len)\
551     __TNO(phdr,enumprefix,structprefix,structname,dst_vmname_len,dst_vmname_len)\
552     __TNO(phdr,enumprefix,structprefix,structname,data,Data)
553
554 #define TRACE_V26_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
555     TRACE_V25_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
556     __TNO(phdr,enumprefix,structprefix,structname,ns_activity,ns_activity)\
557
558 #define TRACE_V30_REC_LEN_OFF(phdr, enumprefix, structprefix, structname) \
559     TRACE_V26_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
560
561     TRACE_V10_REC_LEN_OFF(NULL,v10_part,pp,pktracepart_v10)
562     TRACE_V10_REC_LEN_OFF(NULL,v10_full,fp,pktracefull_v10)
563     TRACE_V20_REC_LEN_OFF(NULL,v20_part,pp,pktracepart_v20)
564     TRACE_V20_REC_LEN_OFF(NULL,v20_full,fp,pktracefull_v20)
565     TRACE_V21_REC_LEN_OFF(NULL,v21_part,pp,pktracepart_v21)
566     TRACE_V21_REC_LEN_OFF(NULL,v21_full,fp,pktracefull_v21)
567     TRACE_V22_REC_LEN_OFF(NULL,v22_part,pp,pktracepart_v22)
568     TRACE_V22_REC_LEN_OFF(NULL,v22_full,fp,pktracefull_v22)
569     TRACE_V23_REC_LEN_OFF(NULL,v23_part,pp,pktracepart_v23)
570     TRACE_V23_REC_LEN_OFF(NULL,v23_full,fp,pktracefull_v23)
571     TRACE_V24_REC_LEN_OFF(NULL,v24_part,pp,pktracepart_v24)
572     TRACE_V24_REC_LEN_OFF(NULL,v24_full,fp,pktracefull_v24)
573     TRACE_V25_REC_LEN_OFF(NULL,v25_part,pp,pktracepart_v25)
574     TRACE_V25_REC_LEN_OFF(NULL,v25_full,fp,pktracefull_v25)
575     TRACE_V26_REC_LEN_OFF(NULL,v26_part,pp,pktracepart_v26)
576     TRACE_V26_REC_LEN_OFF(NULL,v26_full,fp,pktracefull_v26)
577     TRACE_V30_REC_LEN_OFF(NULL,v30_full,fp,pktracefull_v30)
578
579 #undef __TNV1O
580 #undef __TNV1L
581 #undef __TNO
582 #undef __TNL
583
584
585 #define ns_setabstime(nstrace, AbsoluteTime, RelativeTimems) \
586     do { \
587         (nstrace)->nspm_curtime = AbsoluteTime; \
588         (nstrace)->nspm_curtimemsec += RelativeTimems; \
589         (nstrace)->nspm_curtimelastmsec = nstrace->nspm_curtimemsec; \
590     } while(0)
591
592
593 #define ns_setrelativetime(nstrace, RelativeTimems) \
594     do { \
595         guint32    rsec; \
596         (nstrace)->nspm_curtimemsec += RelativeTimems; \
597         rsec = (guint32)((nstrace)->nspm_curtimemsec - (nstrace)->nspm_curtimelastmsec)/1000; \
598         (nstrace)->nspm_curtime += rsec; \
599         (nstrace)->nspm_curtimelastmsec += rsec * 1000; \
600     } while (0)
601
602
603 typedef struct {
604     gchar  *pnstrace_buf;
605     gint64  xxx_offset;
606     gint32  nstrace_buf_offset;
607     gint32  nstrace_buflen;
608     /* Performance Monitor Time variables */
609     guint32 nspm_curtime;         /* current time since 1970 */
610     guint64 nspm_curtimemsec;     /* current time in milliseconds */
611     guint64 nspm_curtimelastmsec; /* nspm_curtime last update time in milliseconds */
612     guint64 nsg_creltime;
613     guint64 file_size;
614 } nstrace_t;
615
616 static guint32 nspm_signature_version(wtap*, gchar*, gint32);
617 static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info,
618                                  gint64 *data_offset);
619 static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info,
620                                  gint64 *data_offset);
621 static gboolean nstrace_read_v30(wtap *wth, int *err, gchar **err_info,
622                                  gint64 *data_offset);
623 static gboolean nstrace_seek_read_v10(wtap *wth, gint64 seek_off,
624                                       struct wtap_pkthdr *phdr,
625                                       Buffer *buf,
626                                       int *err, gchar **err_info);
627 static gboolean nstrace_seek_read_v20(wtap *wth, gint64 seek_off,
628                                       struct wtap_pkthdr *phdr,
629                                       Buffer *buf,
630                                       int *err, gchar **err_info);
631 static gboolean nstrace_seek_read_v30(wtap *wth, gint64 seek_off,
632                                       struct wtap_pkthdr *phdr,
633                                       Buffer *buf,
634                                       int *err, gchar **err_info);
635 static void nstrace_close(wtap *wth);
636
637 static gboolean nstrace_set_start_time_v10(wtap *wth);
638 static gboolean nstrace_set_start_time_v20(wtap *wth);
639 static gboolean nstrace_set_start_time(wtap *wth);
640 static guint64 ns_hrtime2nsec(guint32 tm);
641
642 static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
643                              const guint8 *pd, int *err);
644
645
646 /*
647  * Minimum of the page size and the amount of data left in the file;
648  * the last page of a file can be short.
649  */
650 #define GET_READ_PAGE_SIZE(remaining_file_size) ((gint32)((remaining_file_size>NSPR_PAGESIZE)?NSPR_PAGESIZE:remaining_file_size))
651 #define GET_READ_PAGE_SIZEV3(remaining_file_size) ((gint32)((remaining_file_size>NSPR_PAGESIZE_TRACE)?NSPR_PAGESIZE_TRACE:remaining_file_size))
652
653 static guint64 ns_hrtime2nsec(guint32 tm)
654 {
655     guint32    val = tm & NSPR_HRTIME_MASKTM;
656     switch(tm & NSPR_HRTIME_MASKFMT)
657     {
658     case NSPR_HRTIME_SEC:     return (guint64)val*1000000000;
659     case NSPR_HRTIME_MSEC:    return (guint64)val*1000000;
660     case NSPR_HRTIME_USEC:    return (guint64)val*1000;
661     case NSPR_HRTIME_NSEC:    return val;
662     }
663     return tm;
664 }
665
666
667 /*
668 ** Netscaler trace format open routines
669 */
670 int nstrace_open(wtap *wth, int *err, gchar **err_info)
671 {
672     gchar *nstrace_buf;
673     gint64 file_size;
674     gint32 page_size;
675     nstrace_t *nstrace;
676
677
678     if ((file_size = wtap_file_size(wth, err)) == -1)
679         return 0;
680
681     nstrace_buf = (gchar *)g_malloc(NSPR_PAGESIZE);
682     page_size = GET_READ_PAGE_SIZE(file_size);
683
684     switch ((wth->file_type_subtype = nspm_signature_version(wth, nstrace_buf, page_size)))
685     {
686     case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0:
687         wth->file_encap = WTAP_ENCAP_NSTRACE_1_0;
688         break;
689
690     case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0:
691         wth->file_encap = WTAP_ENCAP_NSTRACE_2_0;
692         break;
693
694     case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0:
695         wth->file_encap = WTAP_ENCAP_NSTRACE_3_0;
696         g_free(nstrace_buf);
697         nstrace_buf = (gchar *)g_malloc(NSPR_PAGESIZE_TRACE);
698         page_size = GET_READ_PAGE_SIZEV3(file_size);
699         break;
700
701     default:
702         /* No known signature found, assume it's not NetScaler */
703         g_free(nstrace_buf);
704         return 0;
705     }
706
707     if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
708     {
709         *err = file_error(wth->fh, err_info);
710         g_free(nstrace_buf);
711         return 0;
712     }
713
714     if (!wtap_read_bytes(wth->fh, nstrace_buf, page_size, err, err_info))
715     {
716         g_free(nstrace_buf);
717         if (*err != WTAP_ERR_SHORT_READ)
718             return -1;
719         return 0;
720     }
721
722     switch (wth->file_type_subtype)
723     {
724     case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0:
725         wth->subtype_read = nstrace_read_v10;
726         wth->subtype_seek_read = nstrace_seek_read_v10;
727         break;
728
729     case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0:
730         wth->subtype_read = nstrace_read_v20;
731         wth->subtype_seek_read = nstrace_seek_read_v20;
732         break;
733
734     case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0:
735         wth->subtype_read = nstrace_read_v30;
736         wth->subtype_seek_read = nstrace_seek_read_v30;
737         break;
738     }
739     wth->subtype_close = nstrace_close;
740
741     nstrace = (nstrace_t *)g_malloc(sizeof(nstrace_t));
742     wth->priv = (void *)nstrace;
743     nstrace->pnstrace_buf = nstrace_buf;
744     nstrace->xxx_offset = 0;
745     nstrace->nstrace_buflen = page_size;
746     nstrace->nstrace_buf_offset = 0;
747     nstrace->nspm_curtime = 0;
748     nstrace->nspm_curtimemsec = 0;
749     nstrace->nspm_curtimelastmsec = 0;
750     nstrace->nsg_creltime = 0;
751     nstrace->file_size = file_size;
752
753
754     /* Set the start time by looking for the abstime record */
755     if ((nstrace_set_start_time(wth)) == FALSE)
756     {
757         /* Reset the read pointer to start of the file. */
758         if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
759         {
760             g_free(nstrace->pnstrace_buf);
761             g_free(nstrace);
762             return -1;
763         }
764
765         /* Read the first page of data */
766         if (!wtap_read_bytes(wth->fh, nstrace_buf, page_size, err, err_info))
767         {
768             g_free(nstrace->pnstrace_buf);
769             g_free(nstrace);
770             return -1;
771         }
772
773         /* reset the buffer offset */
774         nstrace->nstrace_buf_offset = 0;
775     }
776
777     wth->file_tsprec = WTAP_TSPREC_NSEC;
778     wth->phdr.ts.secs = nstrace->nspm_curtime;
779     wth->phdr.ts.nsecs = 0;
780
781     *err = 0;
782     return 1;
783 }
784
785
786 #define nspm_signature_func(ver) \
787     static guint32 nspm_signature_isv##ver(gchar *sigp) {\
788         return strncmp(sigp,NSPR_SIGSTR_V##ver,(sizeof(NSPR_SIGSTR_V##ver)-1));\
789     }
790
791 nspm_signature_func(10)
792 nspm_signature_func(20)
793 nspm_signature_func(30)
794
795 /*
796 ** Check signature and return the file type and subtype for files with
797 ** that signature.  If it finds no signature that it recognizes, it
798 ** returns WTAP_FILE_TYPE_SUBTYPE_UNKNOWN. At the time of return from
799 ** this function we might not be at the first page. So after a call to
800 ** this function, there has to be a file seek to return to the start
801 ** of the first page.
802 */
803 static guint32
804 nspm_signature_version(wtap *wth, gchar *nstrace_buf, gint32 len)
805 {
806     gchar *dp = nstrace_buf;
807     int bytes_read;
808
809     bytes_read = file_read(dp, len, wth->fh);
810     if (bytes_read == len) {
811
812         for ( ; len > (gint32)(MIN(sizeof(NSPR_SIGSTR_V10), sizeof(NSPR_SIGSTR_V20))); dp++, len--)
813         {
814 #define sigv10p    ((nspr_signature_v10_t*)dp)
815             if ((pletoh16(&sigv10p->nsprRecordType) == NSPR_SIGNATURE_V10) &&
816                 (pletoh16(&sigv10p->nsprRecordSize) <= len) &&
817                 ((gint32)sizeof(NSPR_SIGSTR_V10) <= len) &&
818                 (!nspm_signature_isv10(sigv10p->sig_Signature)))
819                 return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0;
820 #undef    sigv10p
821
822 #define sigv20p    ((nspr_signature_v20_t*)dp)
823             if ((sigv20p->sig_RecordType == NSPR_SIGNATURE_V20) &&
824                 (sigv20p->sig_RecordSize <= len) &&
825                 ((gint32)sizeof(NSPR_SIGSTR_V20) <= len))
826             {
827                 if (!nspm_signature_isv20(sigv20p->sig_Signature))
828                     return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0;
829                 else if (!nspm_signature_isv30(sigv20p->sig_Signature))
830                     return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0;
831             }
832 #undef    sigv20p
833         }
834     }
835
836     return WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;    /* no version found */
837 }
838
839 #define nspr_getv10recordtype(hdp) (pletoh16(&(hdp)->nsprRecordType))
840 #define nspr_getv10recordsize(hdp) (pletoh16(&(hdp)->nsprRecordSize))
841 #define nspr_getv20recordtype(hdp) ((hdp)->phd_RecordType)
842 #define nspr_getv20recordsize(hdp) \
843     (((hdp)->phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES)? \
844         (((hdp)->phd_RecordSizeHigh * NSPR_V20RECORDSIZE_2BYTES)+ \
845          ((hdp)->phd_RecordSizeLow & ~NSPR_V20RECORDSIZE_2BYTES)) : \
846           (hdp)->phd_RecordSizeLow)
847
848
849 #define nstrace_set_start_time_ver(ver) \
850     gboolean nstrace_set_start_time_v##ver(wtap *wth) \
851     {\
852         nstrace_t *nstrace = (nstrace_t *)wth->priv;\
853         gchar* nstrace_buf = nstrace->pnstrace_buf;\
854         gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;\
855         gint32 nstrace_buflen = nstrace->nstrace_buflen;\
856         int bytes_read;\
857         do\
858         {\
859             while (nstrace_buf_offset < nstrace_buflen)\
860             {\
861                 nspr_hd_v##ver##_t *fp = (nspr_hd_v##ver##_t *) &nstrace_buf[nstrace_buf_offset];\
862                 switch (nspr_getv##ver##recordtype(fp))\
863                 {\
864                     case NSPR_ABSTIME_V##ver:\
865                         ns_setabstime(nstrace, pletoh32(&((nspr_abstime_v##ver##_t *) fp)->abs_Time), pletoh16(&((nspr_abstime_v##ver##_t *) fp)->abs_RelTime));\
866                         nstrace->nstrace_buf_offset = nstrace_buf_offset + nspr_getv##ver##recordsize(fp);\
867                         nstrace->nstrace_buflen = nstrace_buflen;\
868                         return TRUE;\
869                      case NSPR_UNUSEDSPACE_V10:\
870                         nstrace_buf_offset = nstrace_buflen;\
871                         break;\
872                     default:\
873                         nstrace_buf_offset += nspr_getv##ver##recordsize(fp);\
874                 }\
875             }\
876             nstrace_buf_offset = 0;\
877             nstrace->xxx_offset += nstrace_buflen;\
878             nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));\
879         }while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && bytes_read == nstrace_buflen); \
880         return FALSE;\
881     }
882
883 nstrace_set_start_time_ver(10)
884 nstrace_set_start_time_ver(20)
885
886 #undef nspr_getv10recordtype
887 #undef nspr_getv20recordtype
888
889 /*
890 ** Set the start time of the trace file. We look for the first ABSTIME record. We use that
891 ** to set the start time. Apart from that we also make sure that we remember the position of
892 ** the next record after the ABSTIME record. Inorder to report correct time values, all trace
893 ** records before the ABSTIME record are ignored.
894 */
895 static gboolean nstrace_set_start_time(wtap *wth)
896 {
897     if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
898         return nstrace_set_start_time_v10(wth);
899     else if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
900         return nstrace_set_start_time_v20(wth);
901     else if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0)
902         return nstrace_set_start_time_v20(wth);
903     return FALSE;
904 }
905
906 #define __TNO(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
907     (phdr)->pseudo_header.nstr.hdrname##_offset = enumprefix##_##hdrname##_offset;
908
909 #define __TNL(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
910     (phdr)->pseudo_header.nstr.hdrname##_len = enumprefix##_##hdrname##_len;
911
912 #define __TNV1O(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
913     __TNO(phdr,enumprefix,structprefix,structname,hdrname,structfieldname)
914
915 #define __TNV1L(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
916     __TNL(phdr,enumprefix,structprefix,structname,hdrname,structfieldname)
917
918
919
920 /*
921 ** Netscaler trace format read routines.
922 */
923 static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
924 {
925     nstrace_t *nstrace = (nstrace_t *)wth->priv;
926     guint64 nsg_creltime = nstrace->nsg_creltime;
927     gchar *nstrace_buf = nstrace->pnstrace_buf;
928     gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;
929     gint32 nstrace_buflen = nstrace->nstrace_buflen;
930     nspr_pktracefull_v10_t *fp;
931     nspr_pktracepart_v10_t *pp;
932     int bytes_read;
933
934     *err = 0;
935     *err_info = NULL;
936     do
937     {
938         while ((nstrace_buf_offset < nstrace_buflen) &&
939             ((nstrace_buflen - nstrace_buf_offset) >= ((gint32)sizeof(fp->nsprRecordType))))
940         {
941
942 #define GENERATE_CASE_FULL(phdr,type,acttype) \
943         case NSPR_PDPKTRACEFULLTX_V##type:\
944         case NSPR_PDPKTRACEFULLTXB_V##type:\
945         case NSPR_PDPKTRACEFULLRX_V##type:\
946             fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];\
947             /*\
948              * XXX - we can't do this in the seek-read routine,\
949              * as the time stamps in the records are relative to\
950              * the previous packet.\
951              */\
952             (phdr)->rec_type = REC_TYPE_PACKET;\
953             (phdr)->presence_flags = WTAP_HAS_TS;\
954             nsg_creltime += ns_hrtime2nsec(pletoh32(&fp->fp_RelTimeHr));\
955             (phdr)->ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);\
956             (phdr)->ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
957             TRACE_FULL_V##type##_REC_LEN_OFF(phdr,v##type##_full,fp,pktracefull_v##type);\
958             ws_buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
959             memcpy(ws_buffer_start_ptr(wth->frame_buffer), fp, (phdr)->caplen);\
960             *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
961             nstrace->nstrace_buf_offset = nstrace_buf_offset + (phdr)->len;\
962             nstrace->nstrace_buflen = nstrace_buflen;\
963             nstrace->nsg_creltime = nsg_creltime;\
964             return TRUE;
965
966 #define GENERATE_CASE_PART(phdr,type,acttype) \
967         case NSPR_PDPKTRACEPARTTX_V##type:\
968         case NSPR_PDPKTRACEPARTTXB_V##type:\
969         case NSPR_PDPKTRACEPARTRX_V##type:\
970             pp = (nspr_pktracepart_v10_t *) &nstrace_buf[nstrace_buf_offset];\
971             /*\
972              * XXX - we can't do this in the seek-read routine,\
973              * as the time stamps in the records are relative to\
974              * the previous packet.\
975              */\
976             (phdr)->rec_type = REC_TYPE_PACKET;\
977             (phdr)->presence_flags = WTAP_HAS_TS;\
978             nsg_creltime += ns_hrtime2nsec(pletoh32(&pp->pp_RelTimeHr));\
979             (phdr)->ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);\
980             (phdr)->ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
981             TRACE_PART_V##type##_REC_LEN_OFF(phdr,v##type##_part,pp,pktracepart_v##type);\
982             ws_buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
983             memcpy(ws_buffer_start_ptr(wth->frame_buffer), pp, (phdr)->caplen);\
984             *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
985             nstrace->nstrace_buf_offset = nstrace_buf_offset + (phdr)->caplen;\
986             nstrace->nsg_creltime = nsg_creltime;\
987             nstrace->nstrace_buflen = nstrace_buflen;\
988             return TRUE;\
989
990             switch (pletoh16(&(( nspr_header_v10_t*)&nstrace_buf[nstrace_buf_offset])->ph_RecordType))
991             {
992                 GENERATE_CASE_FULL(&wth->phdr,10,100)
993                 GENERATE_CASE_PART(&wth->phdr,10,100)
994
995 #undef GENERATE_CASE_FULL
996 #undef GENERATE_CASE_PART
997
998             case NSPR_ABSTIME_V10:
999
1000                 fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];
1001                 ns_setabstime(nstrace, pletoh32(((nspr_abstime_v10_t *) fp)->abs_Time), pletoh32(&((nspr_abstime_v10_t *) fp)->abs_RelTime));
1002                 nstrace_buf_offset += pletoh16(&fp->nsprRecordSize);
1003                 break;
1004
1005             case NSPR_RELTIME_V10:
1006
1007                 fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];
1008                 ns_setrelativetime(nstrace, pletoh32(((nspr_abstime_v10_t *) fp)->abs_RelTime));
1009                 nstrace_buf_offset += pletoh16(&fp->nsprRecordSize);
1010                 break;
1011
1012             case NSPR_UNUSEDSPACE_V10:
1013
1014                 nstrace_buf_offset = nstrace_buflen;
1015                 break;
1016
1017             default:
1018
1019                 fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];
1020                 nstrace_buf_offset += pletoh16(&fp->nsprRecordSize);
1021                 break;
1022             }
1023         }
1024
1025         nstrace_buf_offset = 0;
1026         nstrace->xxx_offset += nstrace_buflen;
1027         nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));
1028     }while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && (bytes_read == nstrace_buflen));
1029
1030     return FALSE;
1031 }
1032
1033 #define TIMEDEFV20(fp,type) \
1034     do {\
1035         wth->phdr.rec_type = REC_TYPE_PACKET;\
1036         wth->phdr.presence_flags |= WTAP_HAS_TS;\
1037         nsg_creltime += ns_hrtime2nsec(pletoh32(fp->type##_RelTimeHr));\
1038         wth->phdr.ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);\
1039         wth->phdr.ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
1040     }while(0)
1041
1042 #define TIMEDEFV23(fp,type) \
1043     do {\
1044         wth->phdr.rec_type = REC_TYPE_PACKET;\
1045         wth->phdr.presence_flags |= WTAP_HAS_TS;\
1046         /* access _AbsTimeHr as a 64bit value */\
1047         nsg_creltime = pletoh64(fp->type##_AbsTimeHr);\
1048         wth->phdr.ts.secs = (guint32) (nsg_creltime / 1000000000);\
1049         wth->phdr.ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
1050     }while(0)
1051
1052 #define TIMEDEFV30(fp,type) \
1053     do {\
1054         wth->phdr.rec_type = REC_TYPE_PACKET;\
1055         wth->phdr.presence_flags |= WTAP_HAS_TS;\
1056         /* access _AbsTimeHr as a 64bit value */\
1057         nsg_creltime = pletoh64(fp->type##_AbsTimeHr);\
1058         wth->phdr.ts.secs = (guint32) (nsg_creltime / 1000000000);\
1059         wth->phdr.ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
1060     }while(0)
1061
1062 #define TIMEDEFV21(fp,type) TIMEDEFV20(fp,type)
1063 #define TIMEDEFV22(fp,type) TIMEDEFV20(fp,type)
1064 #define TIMEDEFV24(fp,type) TIMEDEFV23(fp,type)
1065 #define TIMEDEFV25(fp,type) TIMEDEFV24(fp,type)
1066 #define TIMEDEFV26(fp,type) TIMEDEFV24(fp,type)
1067
1068 #define PPSIZEDEFV20(phdr,pp,ver) \
1069     do {\
1070         (phdr)->rec_type = REC_TYPE_PACKET;\
1071         (phdr)->presence_flags |= WTAP_HAS_CAP_LEN;\
1072         (phdr)->len = pletoh16(&pp->pp_PktSizeOrg) + nspr_pktracepart_v##ver##_s;\
1073         (phdr)->caplen = nspr_getv20recordsize((nspr_hd_v20_t *)pp);\
1074     }while(0)
1075
1076 #define PPSIZEDEFV21(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1077 #define PPSIZEDEFV22(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1078 #define PPSIZEDEFV23(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1079 #define PPSIZEDEFV24(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1080 #define PPSIZEDEFV25(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1081 #define PPSIZEDEFV26(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1082
1083 #define FPSIZEDEFV20(phdr,fp,ver)\
1084     do {\
1085         (phdr)->len = nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
1086         (phdr)->caplen = (phdr)->len;\
1087     }while(0)
1088
1089 #define FPSIZEDEFV21(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1090 #define FPSIZEDEFV22(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1091 #define FPSIZEDEFV23(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1092 #define FPSIZEDEFV24(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1093 #define FPSIZEDEFV25(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1094 #define FPSIZEDEFV26(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1095
1096 #define FPSIZEDEFV30(phdr,fp,ver)\
1097     do {\
1098         (phdr)->rec_type = REC_TYPE_PACKET;\
1099         (phdr)->presence_flags |= WTAP_HAS_CAP_LEN;\
1100         (phdr)->len = pletoh16(&fp->fp_PktSizeOrg) + nspr_pktracefull_v##ver##_s;\
1101         (phdr)->caplen = nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
1102     }while(0)
1103
1104 #define PACKET_DESCRIBE(phdr,FPTIMEDEF,SIZEDEF,ver,enumprefix,type,structname,TYPE)\
1105     do {\
1106         nspr_##structname##_t *fp= (nspr_##structname##_t*)&nstrace_buf[nstrace_buf_offset];\
1107         TIMEDEFV##ver(fp,type);\
1108         SIZEDEF##ver((phdr),fp,ver);\
1109         TRACE_V##ver##_REC_LEN_OFF((phdr),enumprefix,type,structname);\
1110         (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##TYPE;\
1111         ws_buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
1112         memcpy(ws_buffer_start_ptr(wth->frame_buffer), fp, (phdr)->caplen);\
1113         *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
1114         nstrace->nstrace_buf_offset = nstrace_buf_offset + nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
1115         nstrace->nstrace_buflen = nstrace_buflen;\
1116         nstrace->nsg_creltime = nsg_creltime;\
1117         return TRUE;\
1118     }while(0)
1119
1120 static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
1121 {
1122     nstrace_t *nstrace = (nstrace_t *)wth->priv;
1123     guint64 nsg_creltime = nstrace->nsg_creltime;
1124     gchar *nstrace_buf = nstrace->pnstrace_buf;
1125     gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;
1126     gint32 nstrace_buflen = nstrace->nstrace_buflen;
1127     int bytes_read;
1128
1129     *err = 0;
1130     *err_info = NULL;
1131     do
1132     {
1133         while ((nstrace_buf_offset < nstrace_buflen) &&
1134             ((nstrace_buflen - nstrace_buf_offset) >= ((gint32)sizeof((( nspr_hd_v20_t*)&nstrace_buf[nstrace_buf_offset])->phd_RecordType))))
1135         {
1136             switch ((( nspr_hd_v20_t*)&nstrace_buf[nstrace_buf_offset])->phd_RecordType)
1137             {
1138
1139 #define GENERATE_CASE_FULL(phdr,type,acttype) \
1140         case NSPR_PDPKTRACEFULLTX_V##type:\
1141         case NSPR_PDPKTRACEFULLTXB_V##type:\
1142         case NSPR_PDPKTRACEFULLRX_V##type:\
1143             PACKET_DESCRIBE(phdr,TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
1144
1145 #define GENERATE_CASE_FULL_V25(phdr,type,acttype) \
1146         case NSPR_PDPKTRACEFULLTX_V##type:\
1147         case NSPR_PDPKTRACEFULLTXB_V##type:\
1148         case NSPR_PDPKTRACEFULLRX_V##type:\
1149         case NSPR_PDPKTRACEFULLNEWRX_V##type:\
1150             PACKET_DESCRIBE(phdr,TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
1151
1152 #define GENERATE_CASE_PART(phdr,type,acttype) \
1153         case NSPR_PDPKTRACEPARTTX_V##type:\
1154         case NSPR_PDPKTRACEPARTTXB_V##type:\
1155         case NSPR_PDPKTRACEPARTRX_V##type:\
1156             PACKET_DESCRIBE(phdr,TIMEDEF,PPSIZEDEFV,type,v##type##_part,pp,pktracepart_v##type,acttype);
1157
1158 #define GENERATE_CASE_PART_V25(phdr,type,acttype) \
1159         case NSPR_PDPKTRACEPARTTX_V##type:\
1160         case NSPR_PDPKTRACEPARTTXB_V##type:\
1161         case NSPR_PDPKTRACEPARTRX_V##type:\
1162         case NSPR_PDPKTRACEPARTNEWRX_V##type:\
1163             PACKET_DESCRIBE(phdr,TIMEDEF,PPSIZEDEFV,type,v##type##_part,pp,pktracepart_v##type,acttype);
1164
1165                 GENERATE_CASE_FULL(&wth->phdr,20,200);
1166                 GENERATE_CASE_PART(&wth->phdr,20,200);
1167                 GENERATE_CASE_FULL(&wth->phdr,21,201);
1168                 GENERATE_CASE_PART(&wth->phdr,21,201);
1169                 GENERATE_CASE_FULL(&wth->phdr,22,202);
1170                 GENERATE_CASE_PART(&wth->phdr,22,202);
1171                 GENERATE_CASE_FULL(&wth->phdr,23,203);
1172                 GENERATE_CASE_PART(&wth->phdr,23,203);
1173                 GENERATE_CASE_FULL_V25(&wth->phdr,24,204);
1174                 GENERATE_CASE_PART_V25(&wth->phdr,24,204);
1175                 GENERATE_CASE_FULL_V25(&wth->phdr,25,205);
1176                 GENERATE_CASE_PART_V25(&wth->phdr,25,205);
1177                 GENERATE_CASE_FULL_V25(&wth->phdr,26,206);
1178                 GENERATE_CASE_PART_V25(&wth->phdr,26,206);
1179
1180 #undef GENERATE_CASE_FULL
1181 #undef GENERATE_CASE_FULL_V25
1182 #undef GENERATE_CASE_PART
1183 #undef GENERATE_CASE_PART_V25
1184
1185                 case NSPR_ABSTIME_V20:
1186                 {
1187                     nspr_pktracefull_v20_t *fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1188                     nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1189                     ns_setabstime(nstrace, pletoh32(&((nspr_abstime_v20_t *) fp20)->abs_Time), pletoh16(&((nspr_abstime_v20_t *) fp20)->abs_RelTime));
1190                     break;
1191                 }
1192
1193                 case NSPR_RELTIME_V20:
1194                 {
1195                     nspr_pktracefull_v20_t *fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1196                     ns_setrelativetime(nstrace, pletoh16(&((nspr_abstime_v20_t *) fp20)->abs_RelTime));
1197                     nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1198                     break;
1199                   }
1200
1201                 case NSPR_UNUSEDSPACE_V20:
1202                 {
1203                     if (nstrace_buf_offset >= NSPR_PAGESIZE/2)
1204                         nstrace_buf_offset = nstrace_buflen;
1205                     else
1206                         nstrace_buf_offset = NSPR_PAGESIZE/2;
1207                     break;
1208                   }
1209
1210                 default:
1211                 {
1212                     nspr_pktracefull_v20_t *fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1213                     nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1214                     break;
1215                 }
1216             }
1217         }
1218
1219         nstrace_buf_offset = 0;
1220         nstrace->xxx_offset += nstrace_buflen;
1221         nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));
1222     }while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && (bytes_read == nstrace_buflen));
1223
1224     return FALSE;
1225 }
1226
1227 #undef PACKET_DESCRIBE
1228
1229 #define PACKET_DESCRIBE(phdr,FPTIMEDEF,SIZEDEF,ver,enumprefix,type,structname,TYPE)\
1230     do {\
1231     nspr_##structname##_t *fp = (nspr_##structname##_t *) &nstrace_buf[nstrace_buf_offset];\
1232     TIMEDEFV##ver(fp,type);\
1233     SIZEDEF##ver((phdr),fp,ver);\
1234     TRACE_V##ver##_REC_LEN_OFF((phdr),enumprefix,type,structname);\
1235     (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##TYPE;\
1236     ws_buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
1237     *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
1238     while (nstrace_tmpbuff_off < nspr_##structname##_s) {\
1239         nstrace_tmpbuff[nstrace_tmpbuff_off++] = nstrace_buf[nstrace_buf_offset++];\
1240     }\
1241     nst_dataSize = nspr_getv20recordsize(hdp);\
1242     rec_size = nst_dataSize - nstrace_tmpbuff_off;\
1243     nsg_nextPageOffset = ((nstrace_buf_offset + rec_size) >= NSPR_PAGESIZE_TRACE) ?\
1244     ((nstrace_buf_offset + rec_size) - (NSPR_PAGESIZE_TRACE - 1)) : 0;\
1245     while (nsg_nextPageOffset) {\
1246         while (nstrace_buf_offset < NSPR_PAGESIZE_TRACE) {\
1247             nstrace_tmpbuff[nstrace_tmpbuff_off++] = nstrace_buf[nstrace_buf_offset++];\
1248         }\
1249         nstrace_buflen = NSPR_PAGESIZE_TRACE;\
1250         nstrace->xxx_offset += nstrace_buflen;\
1251         bytes_read = file_read(nstrace_buf, NSPR_PAGESIZE_TRACE, wth->fh);\
1252         if (bytes_read != NSPR_PAGESIZE_TRACE) {\
1253             return FALSE;\
1254         } else {\
1255             nstrace_buf_offset = 0;\
1256         }\
1257         rec_size = nst_dataSize - nstrace_tmpbuff_off;\
1258         nsg_nextPageOffset = ((nstrace_buf_offset + rec_size) >= NSPR_PAGESIZE_TRACE) ?\
1259         ((nstrace_buf_offset + rec_size) - (NSPR_PAGESIZE_TRACE- 1)): 0;\
1260     } \
1261     while (nstrace_tmpbuff_off < nst_dataSize) {\
1262         nstrace_tmpbuff[nstrace_tmpbuff_off++] = nstrace_buf[nstrace_buf_offset++];\
1263     }\
1264     memcpy(ws_buffer_start_ptr(wth->frame_buffer), nstrace_tmpbuff, (phdr)->caplen);\
1265     nstrace->nstrace_buf_offset = nstrace_buf_offset;\
1266     nstrace->nstrace_buflen = nstrace_buflen = ((gint32)NSPR_PAGESIZE_TRACE);\
1267     nstrace->nsg_creltime = nsg_creltime;\
1268     return TRUE;\
1269 } while(0)
1270
1271 static gboolean nstrace_read_v30(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
1272 {
1273     nstrace_t *nstrace = (nstrace_t *)wth->priv;
1274     guint64 nsg_creltime = nstrace->nsg_creltime;
1275     gchar *nstrace_buf = nstrace->pnstrace_buf;
1276     gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;
1277     gint32 nstrace_buflen = nstrace->nstrace_buflen;
1278     guint8 nstrace_tmpbuff[65536];
1279     guint32 nstrace_tmpbuff_off=0,nst_dataSize=0,rec_size=0,nsg_nextPageOffset=0;
1280     nspr_hd_v20_t *hdp;
1281     int bytes_read;
1282     *err = 0;
1283     *err_info = NULL;
1284
1285     do
1286     {
1287         while ((nstrace_buf_offset < NSPR_PAGESIZE_TRACE) &&
1288             nstrace_buf[nstrace_buf_offset])
1289         {
1290             hdp = (nspr_hd_v20_t *) &nstrace_buf[nstrace_buf_offset];
1291             switch (hdp->phd_RecordType)
1292             {
1293
1294 #define GENERATE_CASE_V30(phdr,type,acttype) \
1295         case NSPR_PDPKTRACEFULLTX_V##type:\
1296         case NSPR_PDPKTRACEFULLTXB_V##type:\
1297         case NSPR_PDPKTRACEFULLRX_V##type:\
1298         case NSPR_PDPKTRACEFULLNEWRX_V##type:\
1299         PACKET_DESCRIBE(phdr, TIMEDEF, FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
1300         GENERATE_CASE_V30(&wth->phdr,30, 300);
1301 #undef GENERATE_CASE_V30
1302
1303                 case NSPR_ABSTIME_V20:
1304                 {
1305                     nstrace_buf_offset += nspr_getv20recordsize(hdp);
1306                     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));
1307                     break;
1308                 }
1309
1310                 case NSPR_RELTIME_V20:
1311                 {
1312                     ns_setrelativetime(nstrace, pletoh16(&((nspr_abstime_v20_t *) &nstrace_buf[nstrace_buf_offset])->abs_RelTime));
1313                     nstrace_buf_offset += nspr_getv20recordsize(hdp);
1314                     break;
1315                 }
1316
1317                 default:
1318                 {
1319                     nstrace_buf_offset += nspr_getv20recordsize(hdp);
1320                     break;
1321                 }
1322             }
1323         }
1324         nstrace_buf_offset = 0;
1325         nstrace->xxx_offset += nstrace_buflen;
1326         nstrace_buflen = NSPR_PAGESIZE_TRACE;
1327     } while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && (bytes_read == nstrace_buflen));
1328
1329     return FALSE;
1330 }
1331
1332 #undef PACKET_DESCRIBE
1333
1334 static gboolean nstrace_seek_read_v10(wtap *wth, gint64 seek_off,
1335     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
1336 {
1337     nspr_hd_v10_t hdr;
1338     guint record_length;
1339     guint8 *pd;
1340     unsigned int bytes_to_read;
1341     nspr_pktracefull_v10_t *fp;
1342     nspr_pktracepart_v10_t *pp;
1343
1344     *err = 0;
1345
1346     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
1347         return FALSE;
1348
1349     /*
1350     ** Read the record header.
1351     */
1352     if (!wtap_read_bytes(wth->random_fh, (void *)&hdr, sizeof hdr,
1353                          err, err_info))
1354         return FALSE;
1355
1356     /*
1357     ** Get the record length.
1358     */
1359     record_length = nspr_getv10recordsize(&hdr);
1360
1361     /*
1362     ** Copy the header to the buffer and read the rest of the record..
1363     */
1364     ws_buffer_assure_space(buf, record_length);
1365     pd = ws_buffer_start_ptr(buf);
1366     memcpy(pd, (void *)&hdr, sizeof hdr);
1367     if (record_length > sizeof hdr) {
1368         bytes_to_read = (unsigned int)(record_length - sizeof hdr);
1369         if (!wtap_read_bytes(wth->random_fh, pd + sizeof hdr, bytes_to_read,
1370                              err, err_info))
1371             return FALSE;
1372     }
1373
1374     /*
1375     ** Fill in what part of the struct wtap_pkthdr we can.
1376     */
1377 #define GENERATE_CASE_FULL(phdr,type,acttype) \
1378         case NSPR_PDPKTRACEFULLTX_V##type:\
1379         case NSPR_PDPKTRACEFULLTXB_V##type:\
1380         case NSPR_PDPKTRACEFULLRX_V##type:\
1381             fp = (nspr_pktracefull_v10_t *) pd;\
1382             TRACE_FULL_V##type##_REC_LEN_OFF(phdr,v##type##_full,fp,pktracefull_v##type);\
1383             (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##acttype;\
1384             break;
1385
1386 #define GENERATE_CASE_PART(phdr,type,acttype) \
1387         case NSPR_PDPKTRACEPARTTX_V##type:\
1388         case NSPR_PDPKTRACEPARTTXB_V##type:\
1389         case NSPR_PDPKTRACEPARTRX_V##type:\
1390             pp = (nspr_pktracepart_v10_t *) pd;\
1391             TRACE_PART_V##type##_REC_LEN_OFF(phdr,v##type##_part,pp,pktracepart_v##type);\
1392             (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##acttype;\
1393             break;
1394
1395     switch (pletoh16(&(( nspr_header_v10_t*)pd)->ph_RecordType))
1396     {
1397         GENERATE_CASE_FULL(phdr,10,100)
1398         GENERATE_CASE_PART(phdr,10,100)
1399     }
1400
1401 #undef GENERATE_CASE_FULL
1402 #undef GENERATE_CASE_PART
1403
1404     return TRUE;
1405 }
1406
1407 #define PACKET_DESCRIBE(phdr,FPTIMEDEF,SIZEDEF,ver,enumprefix,type,structname,TYPE)\
1408     do {\
1409         nspr_##structname##_t *fp= (nspr_##structname##_t*)pd;\
1410         SIZEDEF##ver((phdr),fp,ver);\
1411         TRACE_V##ver##_REC_LEN_OFF((phdr),enumprefix,type,structname);\
1412         (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##TYPE;\
1413         return TRUE;\
1414     }while(0)
1415
1416 static gboolean nstrace_seek_read_v20(wtap *wth, gint64 seek_off,
1417     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
1418 {
1419     nspr_hd_v20_t hdr;
1420     guint record_length;
1421     guint hdrlen;
1422     guint8 *pd;
1423     unsigned int bytes_to_read;
1424
1425     *err = 0;
1426
1427     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
1428         return FALSE;
1429
1430     /*
1431     ** Read the first 2 bytes of the record header.
1432     */
1433     if (!wtap_read_bytes(wth->random_fh, (void *)&hdr, 2, err, err_info))
1434         return FALSE;
1435     hdrlen = 2;
1436
1437     /*
1438     ** Is there a third byte?  If so, read it.
1439     */
1440     if (hdr.phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES) {
1441         if (!wtap_read_bytes(wth->random_fh, (void *)&hdr.phd_RecordSizeHigh, 1,
1442                              err, err_info))
1443             return FALSE;
1444         hdrlen = 3;
1445     }
1446
1447     /*
1448     ** Get the record length.
1449     */
1450     record_length = nspr_getv20recordsize(&hdr);
1451
1452     /*
1453     ** Copy the header to the buffer and read the rest of the record..
1454     */
1455     ws_buffer_assure_space(buf, record_length);
1456     pd = ws_buffer_start_ptr(buf);
1457     memcpy(pd, (void *)&hdr, hdrlen);
1458     if (record_length > hdrlen) {
1459         bytes_to_read = (unsigned int)(record_length - hdrlen);
1460         if (!wtap_read_bytes(wth->random_fh, pd + hdrlen, bytes_to_read,
1461                              err, err_info))
1462             return FALSE;
1463     }
1464
1465 #define GENERATE_CASE_FULL(phdr,type,acttype) \
1466         case NSPR_PDPKTRACEFULLTX_V##type:\
1467         case NSPR_PDPKTRACEFULLTXB_V##type:\
1468         case NSPR_PDPKTRACEFULLRX_V##type:\
1469             PACKET_DESCRIBE(phdr,TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
1470
1471 #define GENERATE_CASE_FULL_V25(phdr,type,acttype) \
1472         case NSPR_PDPKTRACEFULLTX_V##type:\
1473         case NSPR_PDPKTRACEFULLTXB_V##type:\
1474         case NSPR_PDPKTRACEFULLRX_V##type:\
1475         case NSPR_PDPKTRACEFULLNEWRX_V##type:\
1476             PACKET_DESCRIBE(phdr,TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
1477
1478 #define GENERATE_CASE_PART(phdr,type,acttype) \
1479         case NSPR_PDPKTRACEPARTTX_V##type:\
1480         case NSPR_PDPKTRACEPARTTXB_V##type:\
1481         case NSPR_PDPKTRACEPARTRX_V##type:\
1482             PACKET_DESCRIBE(phdr,TIMEDEF,PPSIZEDEFV,type,v##type##_part,pp,pktracepart_v##type,acttype);
1483
1484 #define GENERATE_CASE_PART_V25(phdr,type,acttype) \
1485         case NSPR_PDPKTRACEPARTTX_V##type:\
1486         case NSPR_PDPKTRACEPARTTXB_V##type:\
1487         case NSPR_PDPKTRACEPARTRX_V##type:\
1488         case NSPR_PDPKTRACEPARTNEWRX_V##type:\
1489             PACKET_DESCRIBE(phdr,TIMEDEF,PPSIZEDEFV,type,v##type##_part,pp,pktracepart_v##type,acttype);
1490
1491     switch ((( nspr_hd_v20_t*)pd)->phd_RecordType)
1492     {
1493         GENERATE_CASE_FULL(phdr,20,200)
1494         GENERATE_CASE_PART(phdr,20,200)
1495         GENERATE_CASE_FULL(phdr,21,201)
1496         GENERATE_CASE_PART(phdr,21,201)
1497         GENERATE_CASE_FULL(phdr,22,202)
1498         GENERATE_CASE_PART(phdr,22,202)
1499         GENERATE_CASE_FULL(phdr,23,203)
1500         GENERATE_CASE_PART(phdr,23,203)
1501         GENERATE_CASE_FULL_V25(phdr,24,204)
1502         GENERATE_CASE_PART_V25(phdr,24,204)
1503         GENERATE_CASE_FULL_V25(phdr,25,205)
1504         GENERATE_CASE_PART_V25(phdr,25,205)
1505         GENERATE_CASE_FULL_V25(phdr,26,206)
1506         GENERATE_CASE_PART_V25(phdr,26,206)
1507     }
1508
1509 #undef GENERATE_CASE_FULL
1510 #undef GENERATE_CASE_FULL_V25
1511 #undef GENERATE_CASE_PART
1512 #undef GENERATE_CASE_PART_V25
1513
1514     return TRUE;
1515 }
1516
1517
1518 static gboolean nstrace_seek_read_v30(wtap *wth, gint64 seek_off,
1519     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
1520 {
1521     nspr_hd_v20_t hdr;
1522     guint record_length;
1523     guint hdrlen;
1524     guint8 *pd;
1525     unsigned int bytes_to_read;
1526
1527     *err = 0;
1528
1529     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
1530         return FALSE;
1531     /*
1532     ** Read the first 2 bytes of the record header.
1533     */
1534     if (!wtap_read_bytes(wth->random_fh, (void *)&hdr, 2, err, err_info))
1535         return FALSE;
1536     hdrlen = 2;
1537
1538     /*
1539     ** Is there a third byte?  If so, read it.
1540     */
1541     if (hdr.phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES) {
1542         if (!wtap_read_bytes(wth->random_fh, (void *)&hdr.phd_RecordSizeHigh, 1,
1543                              err, err_info))
1544             return FALSE;
1545         hdrlen = 3;
1546     }
1547
1548     /*
1549     ** Get the record length.
1550     */
1551     record_length = nspr_getv20recordsize(&hdr);
1552
1553     /*
1554     ** Copy the header to the buffer and read the rest of the record..
1555     */
1556     ws_buffer_assure_space(buf, record_length);
1557     pd = ws_buffer_start_ptr(buf);
1558     memcpy(pd, (void *)&hdr, hdrlen);
1559     if (record_length > hdrlen) {
1560         bytes_to_read = (unsigned int)(record_length - hdrlen);
1561         if (!wtap_read_bytes(wth->random_fh, pd + hdrlen, bytes_to_read,
1562                              err, err_info))
1563             return FALSE;
1564     }
1565
1566 #define GENERATE_CASE_V30(phdr,type,acttype) \
1567     case NSPR_PDPKTRACEFULLTX_V##type:\
1568     case NSPR_PDPKTRACEFULLTXB_V##type:\
1569     case NSPR_PDPKTRACEFULLRX_V##type:\
1570     case NSPR_PDPKTRACEFULLNEWRX_V##type:\
1571     TRACE_V##type##_REC_LEN_OFF((phdr),v##type##_full,fp,pktracefull_v##type);\
1572         (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##acttype;\
1573         break;
1574
1575         switch ((( nspr_hd_v20_t*)pd)->phd_RecordType)
1576         {
1577             GENERATE_CASE_V30(phdr,30, 300);
1578         }
1579
1580     return TRUE;
1581 }
1582
1583
1584 /*
1585 ** Netscaler trace format close routines.
1586 */
1587 static void nstrace_close(wtap *wth)
1588 {
1589     nstrace_t *nstrace = (nstrace_t *)wth->priv;
1590
1591     g_free(nstrace->pnstrace_buf);
1592 }
1593
1594
1595 typedef struct {
1596     guint16 page_offset;
1597     guint16 page_len;
1598     guint32 absrec_time;
1599 } nstrace_dump_t;
1600
1601 /* Returns 0 if we could write the specified encapsulation type,
1602 ** an error indication otherwise. */
1603 int nstrace_10_dump_can_write_encap(int encap)
1604 {
1605     if (encap == WTAP_ENCAP_NSTRACE_1_0)
1606         return 0;
1607
1608     return WTAP_ERR_UNSUPPORTED_ENCAP;
1609 }
1610
1611
1612 /* Returns 0 if we could write the specified encapsulation type,
1613 ** an error indication otherwise. */
1614 int nstrace_20_dump_can_write_encap(int encap)
1615 {
1616     if (encap == WTAP_ENCAP_NSTRACE_2_0)
1617         return 0;
1618
1619     return WTAP_ERR_UNSUPPORTED_ENCAP;
1620 }
1621
1622 /* Returns 0 if we could write the specified encapsulation type,
1623 ** an error indication otherwise. */
1624 int nstrace_30_dump_can_write_encap(int encap)
1625 {
1626     if (encap == WTAP_ENCAP_NSTRACE_3_0)
1627         return 0;
1628
1629     return WTAP_ERR_UNSUPPORTED_ENCAP;
1630 }
1631
1632 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
1633 ** failure */
1634 gboolean nstrace_dump_open(wtap_dumper *wdh, int *err _U_)
1635 {
1636     nstrace_dump_t *nstrace;
1637
1638     wdh->subtype_write = nstrace_dump;
1639
1640     nstrace = (nstrace_dump_t *)g_malloc(sizeof(nstrace_dump_t));
1641     wdh->priv = (void *)nstrace;
1642     nstrace->page_offset = 0;
1643     nstrace->page_len = NSPR_PAGESIZE;
1644     nstrace->absrec_time = 0;
1645
1646     return TRUE;
1647 }
1648
1649
1650 static gboolean nstrace_add_signature(wtap_dumper *wdh, int *err)
1651 {
1652     nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
1653
1654     if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1655     {
1656         guint16 val16b;
1657         nspr_signature_v10_t sig10;
1658
1659         /* populate the record */
1660         val16b = GUINT16_TO_LE(NSPR_SIGNATURE_V10);
1661         memcpy(sig10.phd.ph_RecordType, &val16b, sizeof sig10.phd.ph_RecordType);
1662         val16b = GUINT16_TO_LE(nspr_signature_v10_s);
1663         memcpy(sig10.phd.ph_RecordSize, &val16b, sizeof sig10.phd.ph_RecordSize);
1664         memset(sig10.sig_Signature, 0, NSPR_SIGSIZE_V10);
1665         g_strlcpy(sig10.sig_Signature, NSPR_SIGSTR_V10, NSPR_SIGSIZE_V10);
1666
1667         /* Write the record into the file */
1668         if (!wtap_dump_file_write(wdh, &sig10, nspr_signature_v10_s,
1669             err))
1670             return FALSE;
1671
1672         /* Move forward the page offset */
1673         nstrace->page_offset += (guint16) nspr_signature_v10_s;
1674
1675     } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
1676     {
1677         nspr_signature_v20_t sig20;
1678
1679         sig20.sig_RecordType = NSPR_SIGNATURE_V20;
1680         sig20.sig_RecordSize = nspr_signature_v20_s;
1681         memcpy(sig20.sig_Signature, NSPR_SIGSTR_V20, sizeof(NSPR_SIGSTR_V20));
1682
1683         /* Write the record into the file */
1684         if (!wtap_dump_file_write(wdh, &sig20, sig20.sig_RecordSize,
1685             err))
1686             return FALSE;
1687
1688         /* Move forward the page offset */
1689         nstrace->page_offset += (guint16) sig20.sig_RecordSize;
1690
1691     } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0)
1692     {
1693         nspr_signature_v30_t sig30;
1694
1695         sig30.sig_RecordType = NSPR_SIGNATURE_V30;
1696         sig30.sig_RecordSize = nspr_signature_v30_s;
1697         memcpy(sig30.sig_Signature, NSPR_SIGSTR_V30, sizeof(NSPR_SIGSTR_V30));
1698
1699         /* Write the record into the file */
1700         if (!wtap_dump_file_write(wdh, &sig30, sig30.sig_RecordSize,
1701             err))
1702             return FALSE;
1703
1704         /* Move forward the page offset */
1705         nstrace->page_offset += (guint16) sig30.sig_RecordSize;
1706     } else
1707     {
1708         g_assert_not_reached();
1709         return FALSE;
1710     }
1711
1712     return TRUE;
1713 }
1714
1715
1716 static gboolean
1717 nstrace_add_abstime(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1718      const guint8 *pd, int *err)
1719 {
1720     nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
1721     guint64 nsg_creltime;
1722
1723     if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1724     {
1725         guint16 val16;
1726         guint32 reltime;
1727         guint64 abstime;
1728         nspr_abstime_v10_t abs10;
1729
1730         /* populate the record */
1731         val16 = GUINT16_TO_LE(NSPR_ABSTIME_V10);
1732         memcpy(abs10.phd.ph_RecordType, &val16, sizeof abs10.phd.ph_RecordType);
1733         val16 = GUINT16_TO_LE(nspr_abstime_v10_s);
1734         memcpy(abs10.phd.ph_RecordSize, &val16, sizeof abs10.phd.ph_RecordSize);
1735
1736         memcpy(&reltime, ((const nspr_pktracefull_v10_t *)pd)->fp_RelTimeHr, sizeof reltime);
1737         nsg_creltime = ns_hrtime2nsec(reltime);
1738
1739         memset(abs10.abs_RelTime, 0, sizeof abs10.abs_RelTime);
1740         abstime = GUINT32_TO_LE((guint32)phdr->ts.secs - (guint32)(nsg_creltime/1000000000));
1741         memcpy(abs10.abs_Time, &abstime, sizeof abs10.abs_Time);
1742
1743         /* Write the record into the file */
1744         if (!wtap_dump_file_write(wdh, &abs10, nspr_abstime_v10_s, err))
1745             return FALSE;
1746
1747         /* Move forward the page offset */
1748         nstrace->page_offset += nspr_abstime_v10_s;
1749
1750     } else if ((wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0) ||
1751         (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0))    {
1752         guint32 reltime;
1753         guint64 abstime;
1754         nspr_abstime_v20_t abs20;
1755
1756         abs20.abs_RecordType = NSPR_ABSTIME_V20;
1757         abs20.abs_RecordSize = nspr_abstime_v20_s;
1758
1759         memcpy(&reltime, ((const nspr_pktracefull_v20_t *)pd)->fp_RelTimeHr, sizeof reltime);
1760         nsg_creltime = ns_hrtime2nsec(reltime);
1761
1762         memset(abs20.abs_RelTime, 0, sizeof abs20.abs_RelTime);
1763         abstime = GUINT32_TO_LE((guint32)phdr->ts.secs - (guint32)(nsg_creltime/1000000000));
1764         memcpy(abs20.abs_RelTime, &abstime, sizeof abs20.abs_RelTime);
1765
1766         /* Write the record into the file */
1767         if (!wtap_dump_file_write(wdh, &abs20, nspr_abstime_v20_s, err))
1768             return FALSE;
1769
1770         /* Move forward the page offset */
1771         nstrace->page_offset += nspr_abstime_v20_s;
1772
1773     } else
1774     {
1775         g_assert_not_reached();
1776         return FALSE;
1777     }
1778
1779     return TRUE;
1780 }
1781
1782
1783 /* Write a record for a packet to a dump file.
1784    Returns TRUE on success, FALSE on failure. */
1785 static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1786     const guint8 *pd, int *err)
1787 {
1788     nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
1789
1790     /* We can only write packet records. */
1791     if (phdr->rec_type != REC_TYPE_PACKET) {
1792         *err = WTAP_ERR_REC_TYPE_UNSUPPORTED;
1793         return FALSE;
1794     }
1795
1796     if (nstrace->page_offset == 0)
1797     {
1798         /* Add the signature record and abs time record */
1799         if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1800         {
1801             if (!nstrace_add_signature(wdh, err) ||
1802                 !nstrace_add_abstime(wdh, phdr, pd, err))
1803                 return FALSE;
1804         } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
1805         {
1806             if (!nstrace_add_signature(wdh, err) ||
1807                 !nstrace_add_abstime(wdh, phdr, pd, err))
1808                 return FALSE;
1809         } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0)
1810         {
1811             if (!nstrace_add_signature(wdh, err) ||
1812                 !nstrace_add_abstime(wdh, phdr, pd, err))
1813                 return FALSE;
1814         } else
1815         {
1816             g_assert_not_reached();
1817             return FALSE;
1818         }
1819     }
1820
1821     switch (phdr->pseudo_header.nstr.rec_type)
1822     {
1823     case NSPR_HEADER_VERSION100:
1824
1825         if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1826         {
1827             if (nstrace->page_offset + phdr->caplen >= nstrace->page_len)
1828             {
1829                 /* Start on the next page */
1830                 if (wtap_dump_file_seek(wdh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR, err) == -1)
1831                     return FALSE;
1832
1833                 nstrace->page_offset = 0;
1834
1835                 /* Possibly add signature and abstime records and increment offset */
1836                 if (!nstrace_add_signature(wdh, err))
1837                     return FALSE;
1838             }
1839
1840             /* Write the actual record as is */
1841             if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
1842                 return FALSE;
1843
1844             nstrace->page_offset += (guint16) phdr->caplen;
1845         } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
1846         {
1847             *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1848             return FALSE;
1849         }
1850
1851         break;
1852
1853     case NSPR_HEADER_VERSION200:
1854     case NSPR_HEADER_VERSION201:
1855     case NSPR_HEADER_VERSION202:
1856     case NSPR_HEADER_VERSION203:
1857     case NSPR_HEADER_VERSION204:
1858     case NSPR_HEADER_VERSION205:
1859     case NSPR_HEADER_VERSION206:
1860         if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1861         {
1862             *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1863             return FALSE;
1864         } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
1865         {
1866             if (nstrace->page_offset + phdr->caplen >= nstrace->page_len)
1867             {
1868                 /* Start on the next page */
1869                 if (wtap_dump_file_seek(wdh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR, err) == -1)
1870                     return FALSE;
1871
1872                 nstrace->page_offset = 0;
1873
1874                 /* Possibly add signature and abstime records and increment offset */
1875                 if (!nstrace_add_signature(wdh, err))
1876                     return FALSE;
1877             }
1878
1879             /* Write the actual record as is */
1880             if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
1881                 return FALSE;
1882
1883             nstrace->page_offset += (guint16) phdr->caplen;
1884         }
1885
1886         break;
1887
1888     case NSPR_HEADER_VERSION300:
1889         if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1890         {
1891             *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1892             return FALSE;
1893         } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
1894         {
1895             *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1896             return FALSE;
1897         } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0)
1898         {
1899             if (nstrace->page_offset + phdr->caplen >= nstrace->page_len)
1900             {
1901                 /* Start on the next page */
1902                 if (wtap_dump_file_seek(wdh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR, err) == -1)
1903                     return FALSE;
1904
1905                 nstrace->page_offset = 0;
1906
1907                 /* Possibly add signature and abstime records and increment offset */
1908                 if (!nstrace_add_signature(wdh, err))
1909                     return FALSE;
1910             }
1911
1912             /* Write the actual record as is */
1913             if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
1914                 return FALSE;
1915
1916             nstrace->page_offset += (guint16) phdr->caplen;
1917         } else
1918         {
1919             g_assert_not_reached();
1920             return FALSE;
1921         }
1922         break;
1923
1924     default:
1925         g_assert_not_reached();
1926         return FALSE;
1927     }
1928
1929     return TRUE;
1930 }