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