More white-space cleanups.
[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
40 #define NSPR_PAGESIZE   8192
41
42 /* The different record types
43 ** NOTE: The Record Type is two byte fields and unused space is recognized by
44 ** either bytes being zero, therefore no record should any byte value as
45 ** zero.
46 **
47 ** New Performance Record Type is only one byte.
48 */
49 #define NSPR_UNUSEDSPACE_V10    0x0000  /* rest of the page is unused */
50 #define NSPR_UNUSEDSPACE_V20    0x00    /* rest of the page is unused */
51 #define NSPR_SIGNATURE_V10      0x0101  /* signature */
52 #define NSPR_SIGNATURE_V20      0x01    /* signature */
53 #define NSPR_ABSTIME_V10        0x0107  /* data capture time in secs from 1970*/
54 #define NSPR_ABSTIME_V20        0x07    /* data capture time in secs from 1970*/
55 #define NSPR_RELTIME_V10        0x0108  /* relative time in ms from last time */
56 #define NSPR_RELTIME_V20        0x08    /* relative time in ms from last time */
57 #define NSPR_RELTIMEHR_V10      0x0109  /* high resolution relative time */
58 #define NSPR_RELTIMEHR_V20      0x09    /* high resolution relative time */
59 #define NSPR_SYSTARTIME_V10     0x010A  /* system start time */
60 #define NSPR_SYSTARTIME_V20     0x0A    /* system start time */
61 #define NSPR_RELTIME2B_V10      0x010B  /* relative time in ms from last time */
62 #define NSPR_RELTIME2B_V20      0x0B    /* relative time in ms from last time */
63
64
65 /* The high resolution relative time format.
66 ** The MS 2 bits of the high resoltion time is defined as follows:
67 ** 00 : time value is in second
68 ** 01 : time value is in mili second
69 ** 10 : time value is in micro second
70 ** 11 : time value is in nano second
71 */
72 #define NSPR_HRTIME_MASKTM      0x3FFFFFFF /* mask to get time value */
73 #define NSPR_HRTIME_MASKFMT     0xC0000000 /* time value format mask */
74 #define NSPR_HRTIME_SEC         0x00000000 /* time value in second */
75 #define NSPR_HRTIME_MSEC        0x40000000 /* time value in mili second */
76 #define NSPR_HRTIME_USEC        0x80000000 /* time value in micro second */
77 #define NSPR_HRTIME_NSEC        0xC0000000 /* time value in nano second */
78
79
80 typedef struct nspr_header_v10
81 {
82     guint8 ph_RecordType[2]; /* Record Type */
83     guint8 ph_RecordSize[2]; /* Record Size including header */
84 } nspr_header_v10_t;
85 #define nspr_header_v10_s    sizeof(nspr_header_v10_t)
86
87 /* This is V20 short header (2 bytes long) to be included where needed */
88 #define NSPR_HEADER_V20(prefix) \
89     guint8 prefix##_RecordType; /* Record Type */ \
90     guint8 prefix##_RecordSize /* Record Size including header */ \
91                                /* end of declaration */
92
93 /* This is new long header (3 bytes long) to be included where needed */
94 #define NSPR_HEADER3B_V20(prefix) \
95     guint8 prefix##_RecordType;    /* Record Type */ \
96     guint8 prefix##_RecordSizeLow; /* Record Size including header */ \
97     guint8 prefix##_RecordSizeHigh /* Record Size including header */ \
98                                    /* end of declaration */
99 #define NSPR_HEADER3B_V21 NSPR_HEADER3B_V20
100 #define NSPR_HEADER3B_V22 NSPR_HEADER3B_V20
101
102 typedef struct nspr_hd_v20
103 {
104     NSPR_HEADER3B_V20(phd); /* long performance header */
105
106 } nspr_hd_v20_t;
107 #define nspr_hd_v20_s    sizeof(nspr_hd_v20_t)
108
109
110 /*
111 ** How to know if header size is short or long?
112 ** The short header size can be 0-127 bytes long. If MS Bit of ph_RecordSize
113 ** is set then record size has 2 bytes
114 */
115 #define NSPR_V20RECORDSIZE_2BYTES       0x80
116
117 /* Performance Data Header with device number */
118 typedef struct nspr_headerdev_v10
119 {
120     guint8 ph_RecordType[2]; /* Record Type */
121     guint8 ph_RecordSize[2]; /* Record Size including header */
122     guint8 ph_DevNo[4];      /* Network Device (NIC/CONN) number */
123 } nspr_headerdev_v10_t;
124 #define nspr_headerdev_v10_s    sizeof(nspr_headerdev_v10_t)
125
126 typedef struct nspr_hd_v10
127 {
128     nspr_header_v10_t phd; /* performance header */
129 } nspr_hd_v10_t;
130 #define nspr_hd_v10_s    sizeof(nspr_hd_v10_t)
131
132 typedef struct nspr_hdev_v10
133 {
134     nspr_headerdev_v10_t phd; /* performance header */
135 } nspr_hdev_v10_t;
136 #define nspr_hdev_v10_s    sizeof(nspr_hdev_v10_t)
137
138 /* if structure has defined phd as first field, it can use following names */
139 #define nsprRecordType    phd.ph_RecordType
140 #define nsprRecordSize    phd.ph_RecordSize
141 #define nsprReserved      phd.ph_Reserved
142 #define nsprRecordTypeOrg phd.ph_Reserved
143 #define nsprDevNo         phd.ph_DevNo
144
145 /* NSPR_SIGNATURE_V10 structure */
146 #define NSPR_SIGSIZE_V10        56 /* signature value size in bytes */
147 typedef struct nspr_signature_v10
148 {
149     nspr_header_v10_t phd; /* performance header */
150     guint8 sig_EndianType; /* Endian Type for the data */
151     guint8 sig_Reserved0;
152     guint8 sig_Reserved1[2];
153     gchar sig_Signature[NSPR_SIGSIZE_V10]; /* Signature value */
154 } nspr_signature_v10_t;
155 #define nspr_signature_v10_s    sizeof(nspr_signature_v10_t)
156
157 /* NSPR_SIGNATURE_V20 structure */
158 #define NSPR_SIGSIZE_V20        sizeof(NSPR_SIGSTR_V20) /* signature value size in bytes */
159 typedef struct nspr_signature_v20
160 {
161     NSPR_HEADER_V20(sig);  /* short performance header */
162     guint8 sig_EndianType; /* Endian Type for the data */
163     gchar sig_Signature[NSPR_SIGSIZE_V20]; /* Signature value */
164 } nspr_signature_v20_t;
165 #define nspr_signature_v20_s    sizeof(nspr_signature_v20_t)
166
167 /* NSPR_ABSTIME_V10 and NSPR_SYSTARTIME_V10 structure */
168 typedef struct nspr_abstime_v10
169 {
170     nspr_header_v10_t phd; /* performance header */
171     guint8 abs_RelTime[4]; /* relative time is ms from last time */
172     guint8 abs_Time[4];    /* absolute time in seconds from 1970 */
173 } nspr_abstime_v10_t;
174 #define nspr_abstime_v10_s    sizeof(nspr_abstime_v10_t)
175
176
177 /* NSPR_ABSTIME_V20 and NSPR_SYSTARTIME_V20 structure */
178 typedef struct nspr_abstime_v20
179 {
180     NSPR_HEADER_V20(abs);  /* short performance header */
181     guint8 abs_RelTime[2]; /* relative time is ms from last time */
182     guint8 abs_Time[4];    /* absolute time in seconds from 1970 */
183 } nspr_abstime_v20_t;
184 #define nspr_abstime_v20_s    sizeof(nspr_abstime_v20_t)
185
186
187
188 /* full packet trace structure */
189 typedef struct nspr_pktracefull_v10
190 {
191     nspr_headerdev_v10_t phd; /* performance header */
192     guint8 fp_RelTimeHr[4];   /* High resolution relative time */
193     guint8 fp_Data[1];        /* packet data starts here */
194 } nspr_pktracefull_v10_t;
195 #define nspr_pktracefull_v10_s    (nspr_hdev_v10_s + 4)
196
197 /* new full packet trace structure v20 */
198 typedef struct nspr_pktracefull_v20
199 {
200     NSPR_HEADER3B_V20(fp);  /* long performance header */
201     guint8 fp_DevNo;        /* Network Device (NIC) number */
202     guint8 fp_RelTimeHr[4]; /* High resolution relative time */
203     guint8 fp_Data[4];      /* packet data starts here */
204 } nspr_pktracefull_v20_t;
205 #define nspr_pktracefull_v20_s    (sizeof(nspr_pktracefull_v20_t) - 4)
206
207 /* new full packet trace structure v21 */
208 typedef struct nspr_pktracefull_v21
209 {
210     NSPR_HEADER3B_V21(fp);  /* long performance header */
211     guint8 fp_DevNo;        /* Network Device (NIC) number */
212     guint8 fp_RelTimeHr[4]; /* High resolution relative time */
213     guint8 fp_PcbDevNo[4];  /* PCB devno */
214     guint8 fp_lPcbDevNo[4]; /* link PCB devno */
215     guint8 fp_Data[4];      /* packet data starts here */
216 } nspr_pktracefull_v21_t;
217 #define nspr_pktracefull_v21_s    (sizeof(nspr_pktracefull_v21_t) - 4)
218
219 /* new full packet trace structure v22 */
220 typedef struct nspr_pktracefull_v22
221 {
222     NSPR_HEADER3B_V22(fp);  /* long performance header */
223     guint8 fp_DevNo;        /* Network Device (NIC) number */
224     guint8 fp_RelTimeHr[4]; /* High resolution relative time */
225     guint8 fp_PcbDevNo[4];  /* PCB devno */
226     guint8 fp_lPcbDevNo[4]; /* link PCB devno */
227     guint8 fp_VlanTag[2];   /* vlan tag */
228     guint8 fp_Data[2];      /* packet data starts here */
229 } nspr_pktracefull_v22_t;
230 #define nspr_pktracefull_v22_s    (sizeof(nspr_pktracefull_v22_t) - 2)
231
232 typedef struct nspr_pktracefull_v23
233 {
234     NSPR_HEADER3B_V22(fp);  /* long performance header */
235     guint8 fp_DevNo;        /* Network Device (NIC) number */
236     guint8 fp_AbsTimeHr[8]; /* High resolution absolute time */
237     guint8 fp_PcbDevNo[4];  /* PCB devno */
238     guint8 fp_lPcbDevNo[4]; /* link PCB devno */
239     guint8 fp_VlanTag[2];   /* vlan tag */
240     guint8 fp_Coreid[2];    /* coreid of the packet */
241     guint8 fp_Data[2];      /* packet data starts here */
242 } nspr_pktracefull_v23_t;
243 #define nspr_pktracefull_v23_s    (sizeof(nspr_pktracefull_v23_t) - 2)
244
245 /* New full packet trace structure v24 for cluster tracing */
246 typedef struct nspr_pktracefull_v24
247 {
248     NSPR_HEADER3B_V22(fp);   /* long performance header */
249     guint8 fp_DevNo;         /* Network Device (NIC) number */
250     guint8 fp_AbsTimeHr[8];  /* High resolution absolute time in nanosec */
251     guint8 fp_PcbDevNo[4];   /* PCB devno */
252     guint8 fp_lPcbDevNo[4];  /* link PCB devno */
253     guint8 fp_VlanTag[2];    /* vlan tag */
254     guint8 fp_Coreid[2];     /* coreid of the packet */
255     guint8 fp_srcNodeId[2];  /* source node # */
256     guint8 fp_destNodeId[2]; /* destination node # */
257     guint8 fp_clFlags;       /* cluster flags */
258     guint8 fp_Data[2];       /* packet data starts here */
259 } nspr_pktracefull_v24_t;
260 #define nspr_pktracefull_v24_s    (sizeof(nspr_pktracefull_v24_t) - 4)
261
262 /* New full packet trace structure v25 for vm info tracing */
263 typedef struct nspr_pktracefull_v25
264 {
265     NSPR_HEADER3B_V22(fp);    /* long performance header */
266     guint8 fp_DevNo;          /* Network Device (NIC) number */
267     guint8 fp_AbsTimeHr[8];   /* High resolution absolute time in nanosec */
268     guint8 fp_PcbDevNo[4];    /* PCB devno */
269     guint8 fp_lPcbDevNo[4];   /* link PCB devno */
270     guint8 fp_VlanTag[2];     /* vlan tag */
271     guint8 fp_Coreid[2];      /* coreid of the packet */
272     guint8 fp_srcNodeId[2];   /* source node # */
273     guint8 fp_destNodeId[2];  /* destination node # */
274     guint8 fp_clFlags;        /* cluster flags */
275     guint8 fp_src_vmname_len; /* vm src info */
276     guint8 fp_dst_vmname_len; /* vm src info */
277     guint8 fp_Data[4];        /* packet data starts here */
278 } nspr_pktracefull_v25_t;
279 #define nspr_pktracefull_v25_s    (sizeof(nspr_pktracefull_v25_t) - 4)
280 #define fp_src_vmname    fp_Data
281 #define fp_src_vmname    fp_Data
282
283
284 /* partial packet trace structure */
285 typedef struct nspr_pktracepart_v10
286 {
287     nspr_headerdev_v10_t phd; /* performance header */
288     guint8 pp_RelTimeHr[4];   /* High resolution relative time */
289     guint8 pp_PktSizeOrg[2];  /* Original packet size */
290     guint8 pp_PktOffset[2];   /* starting offset in packet */
291     guint8 pp_Data[1];        /* packet data starts here */
292 } nspr_pktracepart_v10_t;
293 #define nspr_pktracepart_v10_s    (nspr_pktracefull_v10_s + 4)
294
295 /* new partial packet trace structure */
296 typedef struct nspr_pktracepart_v20
297 {
298     NSPR_HEADER3B_V20(pp);   /* long performance header */
299     guint8 pp_DevNo;         /* Network Device (NIC) number */
300     guint8 pp_RelTimeHr[4];  /* High resolution relative time */
301     guint8 pp_PktSizeOrg[2]; /* Original packet size */
302     guint8 pp_PktOffset[2];  /* starting offset in packet */
303     guint8 pp_Data[4];       /* packet data starts here */
304 } nspr_pktracepart_v20_t;
305 #define nspr_pktracepart_v20_s    (sizeof(nspr_pktracepart_v20_t) -4)
306
307 /* new partial packet trace structure */
308 typedef struct nspr_pktracepart_v21
309 {
310     NSPR_HEADER3B_V21(pp);   /* long performance header */
311     guint8 pp_DevNo;         /* Network Device (NIC) number */
312     guint8 pp_RelTimeHr[4];  /* High resolution relative time */
313     guint8 pp_PktSizeOrg[2]; /* Original packet size */
314     guint8 pp_PktOffset[2];  /* starting offset in packet */
315     guint8 pp_PcbDevNo[4];   /* PCB devno */
316     guint8 pp_lPcbDevNo[4];  /* link PCB devno */
317     guint8 pp_Data[4];       /* packet data starts here */
318 } nspr_pktracepart_v21_t;
319 #define nspr_pktracepart_v21_s    (sizeof(nspr_pktracepart_v21_t) -4)
320
321 /* new partial packet trace structure v22 */
322 typedef struct nspr_pktracepart_v22
323 {
324     NSPR_HEADER3B_V22(pp);   /* long performance header */
325     guint8 pp_DevNo;         /* Network Device (NIC) number */
326     guint8 pp_RelTimeHr[4];  /* High resolution relative time */
327     guint8 pp_PktSizeOrg[2]; /* Original packet size */
328     guint8 pp_PktOffset[2];  /* starting offset in packet */
329     guint8 pp_PcbDevNo[4];   /* PCB devno */
330     guint8 pp_lPcbDevNo[4];  /* link PCB devno */
331     guint8 pp_VlanTag[2];    /* Vlan Tag */
332     guint8 pp_Data[2];       /* packet data starts here */
333 } nspr_pktracepart_v22_t;
334 #define nspr_pktracepart_v22_s    (sizeof(nspr_pktracepart_v22_t) -2)
335
336 typedef struct nspr_pktracepart_v23
337 {
338     NSPR_HEADER3B_V22(pp);   /* long performance header */
339     guint8 pp_DevNo;         /* Network Device (NIC) number */
340     guint8 pp_AbsTimeHr[8];  /* High resolution absolute time */
341     guint8 pp_PktSizeOrg[2]; /* Original packet size */
342     guint8 pp_PktOffset[2];  /* starting offset in packet */
343     guint8 pp_PcbDevNo[4];   /* PCB devno */
344     guint8 pp_lPcbDevNo[4];  /* link PCB devno */
345     guint8 pp_VlanTag[2];    /* vlan tag */
346     guint8 pp_Coreid[2];     /* Coreid of the packet */
347     guint8 pp_Data[4];       /* packet data starts here */
348 } nspr_pktracepart_v23_t;
349 #define nspr_pktracepart_v23_s    (sizeof(nspr_pktracepart_v23_t) -4)
350
351 /* New partial packet trace structure v24 for cluster tracing */
352 typedef struct nspr_pktracepart_v24
353 {
354     NSPR_HEADER3B_V22(pp);   /* long performance header */
355     guint8 pp_DevNo;         /* Network Device (NIC) number */
356     guint8 pp_AbsTimeHr[8];  /*High resolution absolute time in nanosec*/
357     guint8 pp_PktSizeOrg[2]; /* Original packet size */
358     guint8 pp_PktOffset[2];  /* starting offset in packet */
359     guint8 pp_PcbDevNo[4];   /* PCB devno */
360     guint8 pp_lPcbDevNo[4];  /* link PCB devno */
361     guint8 pp_VlanTag[2];    /* vlan tag */
362     guint8 pp_Coreid[2];     /* Coreid of the packet */
363     guint8 pp_srcNodeId[2];  /* source node # */
364     guint8 pp_destNodeId[2]; /* destination node # */
365     guint8 pp_clFlags;       /* cluster flags */
366     guint8 pp_Data[4];       /* packet data starts here */
367 } nspr_pktracepart_v24_t;
368 #define nspr_pktracepart_v24_s    (sizeof(nspr_pktracepart_v24_t) -4)
369
370 /* New partial packet trace structure v25 for vm info tracing */
371 typedef struct nspr_pktracepart_v25
372 {
373     NSPR_HEADER3B_V22(pp);    /* long performance header */
374     guint8 pp_DevNo;          /* Network Device (NIC) number */
375     guint8 pp_AbsTimeHr[8];   /*High resolution absolute time in nanosec*/
376     guint8 pp_PktSizeOrg[2];  /* Original packet size */
377     guint8 pp_PktOffset[2];   /* starting offset in packet */
378     guint8 pp_PcbDevNo[4];    /* PCB devno */
379     guint8 pp_lPcbDevNo[4];   /* link PCB devno */
380     guint8 pp_VlanTag[2];     /* vlan tag */
381     guint8 pp_Coreid[2];      /* Coreid of the packet */
382     guint8 pp_srcNodeId[2];   /* source node # */
383     guint8 pp_destNodeId[2];  /* destination node # */
384     guint8 pp_clFlags;        /* cluster flags */
385     guint8 pp_src_vmname_len; /* vm info */
386     guint8 pp_dst_vmname_len; /* vm info */
387     guint8 pp_Data[4];        /* packet data starts here */
388 } nspr_pktracepart_v25_t;
389 #define nspr_pktracepart_v25_s    (sizeof(nspr_pktracepart_v25_t) -4)
390 #define pp_src_vmname    pp_Data
391 #define pp_dst_vmname    pp_Data
392
393 #define myoffsetof(type,fieldname) (&(((type*)0)->fieldname))
394
395 #define __TNO(enumprefix,structprefix,structname,hdrname,structfieldname) \
396     guint8 enumprefix##_##hdrname##_offset = (guint8)GPOINTER_TO_INT(myoffsetof(nspr_##structname##_t,structprefix##_##structfieldname));
397
398 #define __TNL(enumprefix,structprefix,structname,hdrname,structfieldname) \
399     guint8 enumprefix##_##hdrname##_len = (guint8)sizeof(((nspr_##structname##_t*)0)->structprefix##_##structfieldname);
400
401 #define __TNV1O(enumprefix,structprefix,structname,hdrname,structfieldname) \
402     guint8 enumprefix##_##hdrname##_offset = (guint8)GPOINTER_TO_INT(myoffsetof(nspr_##structname##_t,structfieldname));
403
404 #define __TNV1L(enumprefix,structprefix,structname,hdrname,structfieldname) \
405     guint8 enumprefix##_##hdrname##_len = (guint8)sizeof(((nspr_##structname##_t*)0)->structfieldname);
406
407 #define TRACE_V10_REC_LEN_OFF(enumprefix,structprefix,structname) \
408         __TNV1O(enumprefix,structprefix,structname,dir,phd.ph_RecordType)\
409         __TNV1L(enumprefix,structprefix,structname,dir,phd.ph_RecordType)\
410         __TNV1O(enumprefix,structprefix,structname,nicno,phd.ph_DevNo)\
411         __TNV1L(enumprefix,structprefix,structname,nicno,phd.ph_DevNo)\
412         __TNO(enumprefix,structprefix,structname,eth,Data)
413
414 #define TRACE_V20_REC_LEN_OFF(enumprefix,structprefix,structname) \
415         __TNO(enumprefix,structprefix,structname,dir,RecordType)\
416         __TNL(enumprefix,structprefix,structname,dir,RecordType)\
417         __TNO(enumprefix,structprefix,structname,nicno,DevNo)\
418         __TNL(enumprefix,structprefix,structname,nicno,DevNo)\
419         __TNO(enumprefix,structprefix,structname,eth,Data)
420
421 #define TRACE_V21_REC_LEN_OFF(enumprefix,structprefix,structname) \
422         TRACE_V20_REC_LEN_OFF(enumprefix,structprefix,structname)\
423         __TNO(enumprefix,structprefix,structname,pcb,PcbDevNo)\
424         __TNO(enumprefix,structprefix,structname,l_pcb,lPcbDevNo)
425
426 #define TRACE_V22_REC_LEN_OFF(enumprefix,structprefix,structname) \
427         TRACE_V21_REC_LEN_OFF(enumprefix,structprefix,structname)\
428         __TNO(enumprefix,structprefix,structname,vlantag,VlanTag)
429
430 #define TRACE_V23_REC_LEN_OFF(enumprefix,structprefix,structname) \
431         TRACE_V22_REC_LEN_OFF(enumprefix,structprefix,structname)\
432         __TNO(enumprefix,structprefix,structname,coreid,Coreid)
433
434 #define TRACE_V24_REC_LEN_OFF(enumprefix,structprefix,structname) \
435         TRACE_V23_REC_LEN_OFF(enumprefix,structprefix,structname)\
436         __TNO(enumprefix,structprefix,structname,srcnodeid,srcNodeId)\
437         __TNO(enumprefix,structprefix,structname,destnodeid,destNodeId)\
438         __TNO(enumprefix,structprefix,structname,clflags,clFlags)
439
440 #define TRACE_V25_REC_LEN_OFF(enumprefix,structprefix,structname) \
441             TRACE_V24_REC_LEN_OFF(enumprefix,structprefix,structname)\
442             __TNO(enumprefix,structprefix,structname,src_vmname_len,src_vmname_len)\
443             __TNO(enumprefix,structprefix,structname,dst_vmname_len,dst_vmname_len)\
444             __TNO(enumprefix,structprefix,structname,data,Data)
445     
446     TRACE_V10_REC_LEN_OFF(v10_part,pp,pktracepart_v10)
447     TRACE_V10_REC_LEN_OFF(v10_full,fp,pktracefull_v10)
448     TRACE_V20_REC_LEN_OFF(v20_part,pp,pktracepart_v20)
449     TRACE_V20_REC_LEN_OFF(v20_full,fp,pktracefull_v20)
450     TRACE_V21_REC_LEN_OFF(v21_part,pp,pktracepart_v21)
451     TRACE_V21_REC_LEN_OFF(v21_full,fp,pktracefull_v21)
452     TRACE_V22_REC_LEN_OFF(v22_part,pp,pktracepart_v22)
453     TRACE_V22_REC_LEN_OFF(v22_full,fp,pktracefull_v22)
454     TRACE_V23_REC_LEN_OFF(v23_part,pp,pktracepart_v23)
455     TRACE_V23_REC_LEN_OFF(v23_full,fp,pktracefull_v23)
456     TRACE_V24_REC_LEN_OFF(v24_part,pp,pktracepart_v24)
457     TRACE_V24_REC_LEN_OFF(v24_full,fp,pktracefull_v24)
458     TRACE_V25_REC_LEN_OFF(v25_part,pp,pktracepart_v25)
459     TRACE_V25_REC_LEN_OFF(v25_full,fp,pktracefull_v25)
460
461 #undef __TNV1O
462 #undef __TNV1L
463 #undef __TNO
464 #undef __TNL
465
466
467 #define ns_setabstime(nstrace, AbsoluteTime, RelativeTimems) \
468     do { \
469         (nstrace)->nspm_curtime = AbsoluteTime; \
470         (nstrace)->nspm_curtimemsec += RelativeTimems; \
471         (nstrace)->nspm_curtimelastmsec = nstrace->nspm_curtimemsec; \
472     } while(0)
473
474
475 #define ns_setrelativetime(nstrace, RelativeTimems) \
476     do { \
477         guint32    rsec; \
478         (nstrace)->nspm_curtimemsec += RelativeTimems; \
479         rsec = (guint32)((nstrace)->nspm_curtimemsec - (nstrace)->nspm_curtimelastmsec)/1000; \
480         (nstrace)->nspm_curtime += rsec; \
481         (nstrace)->nspm_curtimelastmsec += rsec * 1000; \
482     } while (0)
483
484
485 typedef struct {
486     gchar  *pnstrace_buf;
487     gint64  xxx_offset;
488     gint32  nstrace_buf_offset;
489     gint32  nstrace_buflen;
490     /* Performance Monitor Time variables */
491     guint32 nspm_curtime;         /* current time since 1970 */
492     guint64 nspm_curtimemsec;     /* current time in milliseconds */
493     guint64 nspm_curtimelastmsec; /* nspm_curtime last update time in milliseconds */
494     guint64 nsg_creltime;
495     guint64 file_size;
496 } nstrace_t;
497
498 static guint32 nspm_signature_version(wtap*, gchar*, gint32);
499 static gboolean nstrace_read(wtap *wth, int *err, gchar **err_info,
500                              gint64 *data_offset);
501 static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info,
502                                  gint64 *data_offset);
503 static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info,
504                                  gint64 *data_offset);
505 static gboolean nstrace_seek_read(wtap *wth, gint64 seek_off,
506                                   struct wtap_pkthdr *phdr,
507                                   guint8 *pd, int length,
508                                   int *err, gchar **err_info);
509 static void nstrace_close(wtap *wth);
510
511 static gboolean nstrace_set_start_time_v10(wtap *wth);
512 static gboolean nstrace_set_start_time_v20(wtap *wth);
513 static gboolean nstrace_set_start_time(wtap *wth);
514 static guint64 ns_hrtime2nsec(guint32 tm);
515
516 static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
517                              const guint8 *pd, int *err);
518
519
520 #define GET_READ_PAGE_SIZE(remaining_file_size) ((gint32)((remaining_file_size>NSPR_PAGESIZE)?NSPR_PAGESIZE:remaining_file_size))
521
522
523 static guint64 ns_hrtime2nsec(guint32 tm)
524 {
525     guint32    val = tm & NSPR_HRTIME_MASKTM;
526     switch(tm & NSPR_HRTIME_MASKFMT)
527     {
528     case NSPR_HRTIME_SEC:    return (guint64)val*1000000000;
529     case NSPR_HRTIME_MSEC:    return (guint64)val*1000000;
530     case NSPR_HRTIME_USEC:    return (guint64)val*1000;
531     case NSPR_HRTIME_NSEC:    return val;
532     }
533     return tm;
534 }
535
536
537 /*
538 ** Netscaler trace format open routines
539 */
540 int nstrace_open(wtap *wth, int *err, gchar **err_info)
541 {
542     gchar *nstrace_buf;
543     gint64 file_size;
544     gint32 page_size;
545     nstrace_t *nstrace;
546     int bytes_read;
547
548     errno = WTAP_ERR_CANT_READ;
549
550     if ((file_size = wtap_file_size(wth, err)) == -1)
551         return 0;
552
553     nstrace_buf = (gchar *)g_malloc(NSPR_PAGESIZE);
554     page_size = GET_READ_PAGE_SIZE(file_size);
555
556     switch ((wth->file_type = nspm_signature_version(wth, nstrace_buf, page_size)))
557     {
558     case WTAP_FILE_NETSCALER_1_0:
559         wth->file_encap = WTAP_ENCAP_NSTRACE_1_0;
560         break;
561
562     case WTAP_FILE_NETSCALER_2_0:
563         wth->file_encap = WTAP_ENCAP_NSTRACE_2_0;
564         break;
565
566     default:
567         *err = WTAP_ERR_UNSUPPORTED;
568         *err_info = g_strdup_printf("nstrace: file type %d unsupported", wth->file_type);
569         g_free(nstrace_buf);
570         return 0;
571     }
572
573     if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
574     {
575         *err = file_error(wth->fh, err_info);
576         g_free(nstrace_buf);
577         return 0;
578     }
579
580     bytes_read = file_read(nstrace_buf, page_size, wth->fh);
581     if (bytes_read != page_size)
582     {
583         *err = file_error(wth->fh, err_info);
584         g_free(nstrace_buf);
585         return 0;
586     }
587
588     wth->subtype_read = nstrace_read;
589     wth->subtype_seek_read = nstrace_seek_read;
590     wth->subtype_close = nstrace_close;
591
592     nstrace = (nstrace_t *)g_malloc(sizeof(nstrace_t));
593     wth->priv = (void *)nstrace;
594     nstrace->pnstrace_buf = nstrace_buf;
595     nstrace->xxx_offset = 0;
596     nstrace->nstrace_buflen = page_size;
597     nstrace->nstrace_buf_offset = 0;
598     nstrace->nspm_curtime = 0;
599     nstrace->nspm_curtimemsec = 0;
600     nstrace->nspm_curtimelastmsec = 0;
601     nstrace->nsg_creltime = 0;
602     nstrace->file_size = file_size;
603
604
605     /* Set the start time by looking for the abstime record */
606     if ((nstrace_set_start_time(wth)) == FALSE)
607     {
608         /* Reset the read pointer to start of the file. */
609         if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
610         {
611             *err = file_error(wth->fh, err_info);
612             g_free(nstrace->pnstrace_buf);
613             g_free(nstrace);
614             return 0;
615         }
616
617         /* Read the first page of data */
618         bytes_read = file_read(nstrace_buf, page_size, wth->fh);
619         if (bytes_read != page_size)
620         {
621             *err = file_error(wth->fh, err_info);
622             g_free(nstrace->pnstrace_buf);
623             g_free(nstrace);
624             return 0;
625         }
626
627         /* reset the buffer offset */
628         nstrace->nstrace_buf_offset = 0;
629     }
630
631     wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
632     wth->phdr.ts.secs = nstrace->nspm_curtime;
633     wth->phdr.ts.nsecs = 0;
634
635     *err = 0;
636     return 1;
637 }
638
639
640 #define nspm_signature_func(ver) \
641     static guint32 nspm_signature_isv##ver(gchar *sigp) {\
642         return strncmp(sigp,NSPR_SIGSTR_V##ver,(sizeof(NSPR_SIGSTR_V##ver)-1));\
643     }
644
645 nspm_signature_func(10)
646 nspm_signature_func(20)
647
648 /*
649 ** Check signature and return the version number of the signature.
650 ** If not found, it returns 0. At the time of return from this function
651 ** we might not be at the first page. So after a call to this function, there
652 ** has to be a file seek to return to the start of the first page.
653 */
654 static guint32
655 nspm_signature_version(wtap *wth, gchar *nstrace_buf, gint32 len)
656 {
657     gchar *dp = nstrace_buf;
658     int bytes_read;
659
660     bytes_read = file_read(dp, len, wth->fh);
661     if (bytes_read == len) {
662
663         for ( ; len > (gint32)(MIN(sizeof(NSPR_SIGSTR_V10), sizeof(NSPR_SIGSTR_V20))); dp++, len--)
664         {
665 #define sigv10p    ((nspr_signature_v10_t*)dp)
666             if ((pletohs(&sigv10p->nsprRecordType) == NSPR_SIGNATURE_V10) &&
667                 (pletohs(&sigv10p->nsprRecordSize) <= len) &&
668                 ((gint32)sizeof(NSPR_SIGSTR_V10) <= len) &&
669                 (!nspm_signature_isv10(sigv10p->sig_Signature)))
670                 return WTAP_FILE_NETSCALER_1_0;
671 #undef    sigv10p
672
673 #define sigv20p    ((nspr_signature_v20_t*)dp)
674             if ((sigv20p->sig_RecordType == NSPR_SIGNATURE_V20) &&
675                 (sigv20p->sig_RecordSize <= len) &&
676                 ((gint32)sizeof(NSPR_SIGSTR_V20) <= len) &&
677                 (!nspm_signature_isv20(sigv20p->sig_Signature)))
678                 return WTAP_FILE_NETSCALER_2_0;
679 #undef    sigv20p
680         }
681     }
682
683     return 0;    /* no version found */
684 }
685
686 #define nspr_getv10recordtype(hdp) (pletohs(&hdp->nsprRecordType))
687 #define nspr_getv10recordsize(hdp) (pletohs(&hdp->nsprRecordSize))
688 #define nspr_getv20recordtype(hdp) (hdp->phd_RecordType)
689 #define nspr_getv20recordsize(hdp) \
690     (((hdp)->phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES)? \
691         (((hdp)->phd_RecordSizeHigh * NSPR_V20RECORDSIZE_2BYTES)+ \
692          ((hdp)->phd_RecordSizeLow & ~NSPR_V20RECORDSIZE_2BYTES)) : \
693           (hdp)->phd_RecordSizeLow)
694
695
696 #define nstrace_set_start_time_ver(ver) \
697     gboolean nstrace_set_start_time_v##ver(wtap *wth) \
698     {\
699         nstrace_t *nstrace = (nstrace_t *)wth->priv;\
700         gchar* nstrace_buf = nstrace->pnstrace_buf;\
701         gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;\
702         gint32 nstrace_buflen = nstrace->nstrace_buflen;\
703         int bytes_read;\
704         do\
705         {\
706             while (nstrace_buf_offset < nstrace_buflen)\
707             {\
708                 nspr_hd_v##ver##_t *fp = (nspr_hd_v##ver##_t *) &nstrace_buf[nstrace_buf_offset];\
709                 switch (nspr_getv##ver##recordtype(fp))\
710                 {\
711                     case NSPR_ABSTIME_V##ver:\
712                         ns_setabstime(nstrace, pletohl(&((nspr_abstime_v##ver##_t *) fp)->abs_Time), pletohs(&((nspr_abstime_v##ver##_t *) fp)->abs_RelTime));\
713                         nstrace->nstrace_buf_offset = nstrace_buf_offset + nspr_getv##ver##recordsize(fp);\
714                         nstrace->nstrace_buflen = nstrace_buflen;\
715                         return TRUE;\
716                      case NSPR_UNUSEDSPACE_V10:\
717                         nstrace_buf_offset = nstrace_buflen;\
718                         break;\
719                     default:\
720                         nstrace_buf_offset += nspr_getv##ver##recordsize(fp);\
721                 }\
722             }\
723             nstrace_buf_offset = 0;\
724             nstrace->xxx_offset += nstrace_buflen;\
725             nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));\
726         }while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && bytes_read == nstrace_buflen); \
727         return FALSE;\
728     }
729
730 nstrace_set_start_time_ver(10)
731 nstrace_set_start_time_ver(20)
732
733 #undef nspr_getv10recordtype
734 #undef nspr_getv20recordtype
735 #undef nspr_getv10recordsize
736
737 /*
738 ** Set the start time of the trace file. We look for the first ABSTIME record. We use that
739 ** to set the start time. Apart from that we also make sure that we remember the position of
740 ** the next record after the ABSTIME record. Inorder to report correct time values, all trace
741 ** records before the ABSTIME record are ignored.
742 */
743 static gboolean nstrace_set_start_time(wtap *wth)
744 {
745     if (wth->file_type == WTAP_FILE_NETSCALER_1_0)
746         return nstrace_set_start_time_v10(wth);
747     else if (wth->file_type == WTAP_FILE_NETSCALER_2_0)
748         return nstrace_set_start_time_v20(wth);
749
750     return FALSE;
751 }
752
753 #define __TNO(enumprefix,structprefix,structname,hdrname,structfieldname) \
754     wth->phdr.pseudo_header.nstr.hdrname##_offset =  enumprefix##_##hdrname##_offset;
755
756 #define __TNL(enumprefix,structprefix,structname,hdrname,structfieldname) \
757     wth->phdr.pseudo_header.nstr.hdrname##_len = enumprefix##_##hdrname##_len;
758
759 #define __TNV1O(enumprefix,structprefix,structname,hdrname,structfieldname) \
760     __TNO(enumprefix,structprefix,structname,hdrname,structfieldname)
761
762 #define __TNV1L(enumprefix,structprefix,structname,hdrname,structfieldname) \
763     __TNL(enumprefix,structprefix,structname,hdrname,structfieldname)
764
765
766
767 /*
768 ** Netscaler trace format read routines.
769 */
770 static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
771 {
772     nstrace_t *nstrace = (nstrace_t *)wth->priv;
773     guint64 nsg_creltime = nstrace->nsg_creltime;
774     gchar *nstrace_buf = nstrace->pnstrace_buf;
775     gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;
776     gint32 nstrace_buflen = nstrace->nstrace_buflen;
777     nspr_pktracefull_v10_t *fp;
778     nspr_pktracepart_v10_t *pp;
779     int bytes_read;
780
781     *err = 0;
782     *err_info = NULL;
783     do
784     {
785         while ((nstrace_buf_offset < nstrace_buflen) &&
786             ((nstrace_buflen - nstrace_buf_offset) >= ((gint32)sizeof(fp->nsprRecordType))))
787         {
788
789             fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];
790             pp = (nspr_pktracepart_v10_t *) fp;
791
792             switch (pletohs(&fp->nsprRecordType))
793             {
794             case NSPR_PDPKTRACEFULLTX_V10:
795             case NSPR_PDPKTRACEFULLTXB_V10:
796             case NSPR_PDPKTRACEFULLRX_V10:
797
798                 wth->phdr.presence_flags = WTAP_HAS_TS;
799
800                 nsg_creltime += ns_hrtime2nsec(pletohl(&fp->fp_RelTimeHr));
801                 wth->phdr.ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);
802                 wth->phdr.ts.nsecs = (guint32) (nsg_creltime % 1000000000);
803
804                 wth->phdr.len = pletohs(&fp->nsprRecordSize);
805                 wth->phdr.caplen = wth->phdr.len;
806
807
808                 TRACE_V10_REC_LEN_OFF(v10_full,fp,pktracefull_v10);
809
810                 buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
811                 memcpy(buffer_start_ptr(wth->frame_buffer), fp, wth->phdr.caplen);
812                 *data_offset = nstrace->xxx_offset + nstrace_buf_offset;
813
814                 nstrace->nstrace_buf_offset = nstrace_buf_offset + wth->phdr.len;
815                 nstrace->nstrace_buflen = nstrace_buflen;
816                 nstrace->nsg_creltime = nsg_creltime;
817
818                 return TRUE;
819
820             case NSPR_PDPKTRACEPARTTX_V10:
821             case NSPR_PDPKTRACEPARTTXB_V10:
822             case NSPR_PDPKTRACEPARTRX_V10:
823
824                 wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
825
826                 nsg_creltime += ns_hrtime2nsec(pletohl(&pp->pp_RelTimeHr));
827                 wth->phdr.ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);
828                 wth->phdr.ts.nsecs = (guint32) (nsg_creltime % 1000000000);
829
830                 wth->phdr.len =  pletohs(&pp->pp_PktSizeOrg) + nspr_pktracepart_v10_s;
831                 wth->phdr.caplen =  pletohs(&pp->nsprRecordSize);
832
833                 TRACE_V10_REC_LEN_OFF(v10_part,pp,pktracepart_v10);
834
835                 buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
836                 memcpy(buffer_start_ptr(wth->frame_buffer), pp, wth->phdr.caplen);
837                 *data_offset = nstrace->xxx_offset + nstrace_buf_offset;
838
839                 nstrace->nstrace_buf_offset = nstrace_buf_offset + wth->phdr.caplen;
840                 nstrace->nsg_creltime = nsg_creltime;
841                 nstrace->nstrace_buflen = nstrace_buflen;
842
843                 return TRUE;
844
845             case NSPR_ABSTIME_V10:
846
847                 ns_setabstime(nstrace, pletohl(((nspr_abstime_v10_t *) fp)->abs_Time), pletohl(&((nspr_abstime_v10_t *) fp)->abs_RelTime));
848                 nstrace_buf_offset += pletohs(&fp->nsprRecordSize);
849                 break;
850
851             case NSPR_RELTIME_V10:
852
853                 ns_setrelativetime(nstrace, pletohl(((nspr_abstime_v10_t *) fp)->abs_RelTime));
854                 nstrace_buf_offset += pletohs(&fp->nsprRecordSize);
855                 break;
856
857             case NSPR_UNUSEDSPACE_V10:
858
859                 nstrace_buf_offset = nstrace_buflen;
860                 break;
861
862             default:
863
864                 nstrace_buf_offset += pletohs(&fp->nsprRecordSize);
865                 break;
866             }
867         }
868
869         nstrace_buf_offset = 0;
870         nstrace->xxx_offset += nstrace_buflen;
871         nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));
872     }while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && (bytes_read == nstrace_buflen));
873
874     return FALSE;
875 }
876
877 #define TIMEDEFV20(fp,type) \
878     do {\
879         wth->phdr.presence_flags |= WTAP_HAS_TS;\
880         nsg_creltime += ns_hrtime2nsec(pletohl(fp->type##_RelTimeHr));\
881         wth->phdr.ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);\
882         wth->phdr.ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
883     }while(0)
884
885 #define TIMEDEFV23(fp,type) \
886     do {\
887         wth->phdr.presence_flags |= WTAP_HAS_TS;\
888         /* access _AbsTimeHr as a 64bit value */\
889         nsg_creltime = pletohll(fp->type##_AbsTimeHr);\
890         wth->phdr.ts.secs = (guint32) (nsg_creltime / 1000000000);\
891         wth->phdr.ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
892     }while(0)
893
894 #define TIMEDEFV21(fp,type) TIMEDEFV20(fp,type)
895 #define TIMEDEFV22(fp,type) TIMEDEFV20(fp,type)
896 #define TIMEDEFV24(fp,type) TIMEDEFV23(fp,type)
897 #define TIMEDEFV25(fp,type) TIMEDEFV24(fp,type)
898 #define PPSIZEDEFV20(pp,ver) \
899     do {\
900         wth->phdr.presence_flags |= WTAP_HAS_CAP_LEN;\
901         wth->phdr.len = pletohs(&pp->pp_PktSizeOrg) + nspr_pktracepart_v##ver##_s;\
902         wth->phdr.caplen = nspr_getv20recordsize((nspr_hd_v20_t *)pp);\
903     }while(0)
904
905 #define PPSIZEDEFV21(pp,ver) PPSIZEDEFV20(pp,ver)
906 #define PPSIZEDEFV22(pp,ver) PPSIZEDEFV20(pp,ver)
907 #define PPSIZEDEFV23(pp,ver) PPSIZEDEFV20(pp,ver)
908 #define PPSIZEDEFV24(pp,ver) PPSIZEDEFV20(pp,ver)
909 #define PPSIZEDEFV25(pp,ver) PPSIZEDEFV20(pp,ver)
910
911 #define FPSIZEDEFV20(fp,ver)\
912     do {\
913         wth->phdr.len = nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
914         wth->phdr.caplen = wth->phdr.len;\
915     }while(0)
916
917 #define FPSIZEDEFV21(pp,ver) FPSIZEDEFV20(fp,ver)
918 #define FPSIZEDEFV22(pp,ver) FPSIZEDEFV20(fp,ver)
919 #define FPSIZEDEFV23(pp,ver) FPSIZEDEFV20(fp,ver)
920 #define FPSIZEDEFV24(pp,ver) FPSIZEDEFV20(fp,ver)
921 #define FPSIZEDEFV25(pp,ver) FPSIZEDEFV20(fp,ver)
922
923 #define PACKET_DESCRIBE(FPTIMEDEF,SIZEDEF,ver,enumprefix,type,structname,TYPE)\
924     do {\
925         nspr_##structname##_t *fp= (nspr_##structname##_t*)&nstrace_buf[nstrace_buf_offset];\
926         TIMEDEFV##ver(fp,type);\
927         SIZEDEF##ver(fp,ver);\
928         TRACE_V##ver##_REC_LEN_OFF(enumprefix,type,structname);\
929         buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);\
930         memcpy(buffer_start_ptr(wth->frame_buffer), fp, wth->phdr.caplen);\
931         *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
932         nstrace->nstrace_buf_offset = nstrace_buf_offset + nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
933         nstrace->nstrace_buflen = nstrace_buflen;\
934         nstrace->nsg_creltime = nsg_creltime;\
935         wth->phdr.pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##TYPE;\
936         return TRUE;\
937     }while(0)
938
939 static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
940 {
941     nstrace_t *nstrace = (nstrace_t *)wth->priv;
942     guint64 nsg_creltime = nstrace->nsg_creltime;
943     gchar *nstrace_buf = nstrace->pnstrace_buf;
944     gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;
945     gint32 nstrace_buflen = nstrace->nstrace_buflen;
946     nspr_pktracefull_v20_t *fp20;
947     nspr_pktracefull_v21_t *fp21;
948     int bytes_read;
949
950     *err = 0;
951     *err_info = NULL;
952     do
953     {
954         while ((nstrace_buf_offset < nstrace_buflen) &&
955             ((nstrace_buflen - nstrace_buf_offset) >= ((gint32)sizeof(fp21->fp_RecordType))))
956         {
957             fp21 = (nspr_pktracefull_v21_t *) &nstrace_buf[nstrace_buf_offset];
958
959             switch (fp21->fp_RecordType)
960             {
961
962 #define GENERATE_CASE(type,acttype) \
963         case NSPR_PDPKTRACEFULLTX_V##type:\
964         case NSPR_PDPKTRACEFULLTXB_V##type:\
965         case NSPR_PDPKTRACEFULLRX_V##type:\
966             PACKET_DESCRIBE(TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
967 #define GENERATE_CASE_V25(type,acttype) \
968         case NSPR_PDPKTRACEFULLTX_V##type:\
969         case NSPR_PDPKTRACEFULLTXB_V##type:\
970         case NSPR_PDPKTRACEFULLRX_V##type:\
971         case NSPR_PDPKTRACEFULLNEWRX_V##type:\
972             PACKET_DESCRIBE(TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
973                 GENERATE_CASE_V25(25,205);
974                 GENERATE_CASE_V25(24,204);
975                 GENERATE_CASE(23,203);
976                 GENERATE_CASE(22,202);
977                 GENERATE_CASE(21,201);
978                 GENERATE_CASE(20,200);
979 #undef GENERATE_CASE
980 #undef GENERATE_CASE_V25
981
982 #define GENERATE_CASE(type,acttype) \
983         case NSPR_PDPKTRACEPARTTX_V##type:\
984         case NSPR_PDPKTRACEPARTTXB_V##type:\
985         case NSPR_PDPKTRACEPARTRX_V##type:\
986             PACKET_DESCRIBE(TIMEDEF,PPSIZEDEFV,type,v##type##_part,pp,pktracepart_v##type,acttype);
987 #define GENERATE_CASE_V25(type,acttype) \
988         case NSPR_PDPKTRACEPARTTX_V##type:\
989         case NSPR_PDPKTRACEPARTTXB_V##type:\
990         case NSPR_PDPKTRACEPARTRX_V##type:\
991         case NSPR_PDPKTRACEPARTNEWRX_V##type:\
992             PACKET_DESCRIBE(TIMEDEF,PPSIZEDEFV,type,v##type##_part,pp,pktracepart_v##type,acttype);
993                 GENERATE_CASE_V25(25,205);
994                 GENERATE_CASE_V25(24,204);
995                 GENERATE_CASE(23,203);
996                 GENERATE_CASE(22,202);
997                 GENERATE_CASE(21,201);
998                 GENERATE_CASE(20,200);
999 #undef GENERATE_CASE
1000 #undef GENERATE_CASE_V25
1001
1002                 case NSPR_ABSTIME_V20:
1003                 {
1004                     fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1005                     nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1006                     ns_setabstime(nstrace, pletohl(&((nspr_abstime_v20_t *) fp20)->abs_Time), pletohs(&((nspr_abstime_v20_t *) fp20)->abs_RelTime));
1007                     break;
1008                 }
1009
1010                 case NSPR_RELTIME_V20:
1011                 {
1012                     fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1013                     ns_setrelativetime(nstrace, pletohs(&((nspr_abstime_v20_t *) fp20)->abs_RelTime));
1014                     nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1015                     break;
1016                   }
1017
1018                 case NSPR_UNUSEDSPACE_V20:
1019                 {
1020                     if (nstrace_buf_offset >= NSPR_PAGESIZE/2)
1021                         nstrace_buf_offset = nstrace_buflen;
1022                     else
1023                         nstrace_buf_offset = NSPR_PAGESIZE/2;
1024                     break;
1025                   }
1026
1027                 default:
1028                 {
1029                     fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1030                     nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1031                     break;
1032                 }
1033             }
1034         }
1035
1036         nstrace_buf_offset = 0;
1037         nstrace->xxx_offset += nstrace_buflen;
1038         nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));
1039     }while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && (bytes_read == nstrace_buflen));
1040
1041     return FALSE;
1042 }
1043
1044 #undef __TNO
1045 #undef __TNL
1046 #undef __TNV1O
1047 #undef __TNV1L
1048
1049
1050
1051 static gboolean nstrace_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
1052 {
1053
1054     if (wth->file_type == WTAP_FILE_NETSCALER_1_0)
1055         return nstrace_read_v10(wth, err, err_info, data_offset);
1056     else if (wth->file_type == WTAP_FILE_NETSCALER_2_0)
1057         return nstrace_read_v20(wth, err, err_info, data_offset);
1058
1059     return FALSE;
1060 }
1061
1062
1063 #define __TNO(enumprefix,structprefix,structname,hdrname,structfieldname) \
1064     phdr->pseudo_header.nstr.hdrname##_offset = (guint8) enumprefix##_##hdrname##_offset;
1065 #define __TNL(enumprefix,structprefix,structname,hdrname,structfieldname) \
1066     phdr->pseudo_header.nstr.hdrname##_len = (guint8) enumprefix##_##hdrname##_len;
1067
1068 #define __TNV1O(enumprefix,structprefix,structname,hdrname,structfieldname) \
1069     __TNO(enumprefix,structprefix,structname,hdrname,structfieldname)
1070 #define __TNV1L(enumprefix,structprefix,structname,hdrname,structfieldname) \
1071     __TNL(enumprefix,structprefix,structname,hdrname,structfieldname)
1072
1073
1074 static gboolean nstrace_seek_read(wtap *wth, gint64 seek_off,
1075     struct wtap_pkthdr *phdr, guint8 *pd, int length,
1076     int *err, gchar **err_info)
1077 {
1078     union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
1079     int bytes_read;
1080
1081     *err = 0;
1082
1083     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
1084         return FALSE;
1085
1086     /*
1087     ** Read the packet data.
1088     */
1089     bytes_read = file_read(pd, length, wth->random_fh);
1090     if (bytes_read != length) {
1091         *err = file_error(wth->random_fh, err_info);
1092         if (*err == 0)
1093             *err = WTAP_ERR_SHORT_READ;
1094         return FALSE;
1095     }
1096
1097     if (wth->file_type == WTAP_FILE_NETSCALER_1_0)
1098     {
1099
1100 #define GENERATE_CASE_FULL(type,acttype) \
1101         case NSPR_PDPKTRACEFULLTX_V##type:\
1102         case NSPR_PDPKTRACEFULLTXB_V##type:\
1103         case NSPR_PDPKTRACEFULLRX_V##type:\
1104             TRACE_V##type##_REC_LEN_OFF(v##type##_full,fp,pktracefull_v##type);\
1105             pseudo_header->nstr.rec_type = NSPR_HEADER_VERSION##acttype;\
1106             break;\
1107
1108 #define GENERATE_CASE_PART(type,acttype) \
1109         case NSPR_PDPKTRACEPARTTX_V##type:\
1110         case NSPR_PDPKTRACEPARTTXB_V##type:\
1111         case NSPR_PDPKTRACEPARTRX_V##type:\
1112             TRACE_V##type##_REC_LEN_OFF(v##type##_part,pp,pktracepart_v##type);\
1113             pseudo_header->nstr.rec_type = NSPR_HEADER_VERSION##acttype;\
1114             break;\
1115
1116         switch (pletohs(&(( nspr_header_v10_t*)pd)->ph_RecordType))
1117         {
1118             GENERATE_CASE_FULL(10,100)
1119             GENERATE_CASE_PART(10,100)
1120         }
1121     } else if (wth->file_type == WTAP_FILE_NETSCALER_2_0)
1122     {
1123 #define GENERATE_CASE_FULL_V25(type,acttype) \
1124         case NSPR_PDPKTRACEFULLTX_V##type:\
1125         case NSPR_PDPKTRACEFULLTXB_V##type:\
1126         case NSPR_PDPKTRACEFULLRX_V##type:\
1127         case NSPR_PDPKTRACEFULLNEWRX_V##type:\
1128             TRACE_V##type##_REC_LEN_OFF(v##type##_full,fp,pktracefull_v##type);\
1129             pseudo_header->nstr.rec_type = NSPR_HEADER_VERSION##acttype;\
1130             break;\
1131
1132 #define GENERATE_CASE_PART_V25(type,acttype) \
1133         case NSPR_PDPKTRACEPARTTX_V##type:\
1134         case NSPR_PDPKTRACEPARTTXB_V##type:\
1135         case NSPR_PDPKTRACEPARTRX_V##type:\
1136         case NSPR_PDPKTRACEPARTNEWRX_V##type:\
1137             TRACE_V##type##_REC_LEN_OFF(v##type##_part,pp,pktracepart_v##type);\
1138             pseudo_header->nstr.rec_type = NSPR_HEADER_VERSION##acttype;\
1139             break;\
1140
1141         switch ((( nspr_hd_v20_t*)pd)->phd_RecordType)
1142         {
1143             GENERATE_CASE_FULL(20,200)
1144             GENERATE_CASE_PART(20,200)
1145             GENERATE_CASE_FULL(21,201)
1146             GENERATE_CASE_PART(21,201)
1147             GENERATE_CASE_FULL(22,202)
1148             GENERATE_CASE_PART(22,202)
1149             GENERATE_CASE_FULL(23,203)
1150             GENERATE_CASE_PART(23,203)
1151             GENERATE_CASE_FULL_V25(24,204)
1152             GENERATE_CASE_PART_V25(24,204)
1153             GENERATE_CASE_FULL_V25(25,205)
1154             GENERATE_CASE_PART_V25(25,205)
1155         }
1156     }
1157
1158     return TRUE;
1159 }
1160
1161 #undef __TNL
1162 #undef __TNO
1163 #undef __TNV1L
1164 #undef __TNV1O
1165
1166
1167 /*
1168 ** Netscaler trace format close routines.
1169 */
1170 static void nstrace_close(wtap *wth)
1171 {
1172     nstrace_t *nstrace = (nstrace_t *)wth->priv;
1173
1174     g_free(nstrace->pnstrace_buf);
1175 }
1176
1177
1178 typedef struct {
1179     guint16 page_offset;
1180     guint16 page_len;
1181     guint32 absrec_time;
1182 } nstrace_dump_t;
1183
1184 /* Returns 0 if we could write the specified encapsulation type,
1185 ** an error indication otherwise. */
1186 int nstrace_10_dump_can_write_encap(int encap)
1187 {
1188     if (encap == WTAP_ENCAP_NSTRACE_1_0)
1189         return 0;
1190
1191     return WTAP_ERR_UNSUPPORTED_ENCAP;
1192 }
1193
1194
1195 /* Returns 0 if we could write the specified encapsulation type,
1196 ** an error indication otherwise. */
1197 int nstrace_20_dump_can_write_encap(int encap)
1198 {
1199     if (encap == WTAP_ENCAP_NSTRACE_2_0)
1200         return 0;
1201
1202     return WTAP_ERR_UNSUPPORTED_ENCAP;
1203 }
1204
1205
1206 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
1207 ** failure */
1208 gboolean nstrace_dump_open(wtap_dumper *wdh, int *err _U_)
1209 {
1210     nstrace_dump_t *nstrace;
1211
1212     wdh->subtype_write = nstrace_dump;
1213
1214     nstrace = (nstrace_dump_t *)g_malloc(sizeof(nstrace_dump_t));
1215     wdh->priv = (void *)nstrace;
1216     nstrace->page_offset = 0;
1217     nstrace->page_len = NSPR_PAGESIZE;
1218     nstrace->absrec_time = 0;
1219
1220     return TRUE;
1221 }
1222
1223
1224 static gboolean nstrace_add_signature(wtap_dumper *wdh, int *err)
1225 {
1226     nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
1227
1228     if (wdh->file_type == WTAP_FILE_NETSCALER_1_0)
1229     {
1230         guint16 val16b;
1231         nspr_signature_v10_t sig10;
1232
1233         /* populate the record */
1234         val16b = htoles(NSPR_SIGNATURE_V10);
1235         memcpy(sig10.phd.ph_RecordType, &val16b, sizeof sig10.phd.ph_RecordType);
1236         val16b = htoles(nspr_signature_v10_s);
1237         memcpy(sig10.phd.ph_RecordSize, &val16b, sizeof sig10.phd.ph_RecordSize);
1238         memset(sig10.sig_Signature, 0, NSPR_SIGSIZE_V10);
1239         g_strlcpy(sig10.sig_Signature, NSPR_SIGSTR_V10, NSPR_SIGSIZE_V10);
1240
1241         /* Write the record into the file */
1242         if (!wtap_dump_file_write(wdh, &sig10, nspr_signature_v10_s,
1243             err))
1244             return FALSE;
1245
1246         /* Move forward the page offset */
1247         nstrace->page_offset += (guint16) nspr_signature_v10_s;
1248
1249     } else if (wdh->file_type == WTAP_FILE_NETSCALER_2_0)
1250     {
1251         nspr_signature_v20_t sig20;
1252
1253         sig20.sig_RecordType = NSPR_SIGNATURE_V20;
1254         sig20.sig_RecordSize = nspr_signature_v20_s;
1255         memcpy(sig20.sig_Signature, NSPR_SIGSTR_V20, sizeof(NSPR_SIGSTR_V20));
1256
1257         /* Write the record into the file */
1258         if (!wtap_dump_file_write(wdh, &sig20, sig20.sig_RecordSize,
1259             err))
1260             return FALSE;
1261
1262         /* Move forward the page offset */
1263         nstrace->page_offset += (guint16) sig20.sig_RecordSize;
1264
1265     } else
1266     {
1267         g_assert_not_reached();
1268         return FALSE;
1269     }
1270
1271     return TRUE;
1272 }
1273
1274
1275 static gboolean
1276 nstrace_add_abstime(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1277      const guint8 *pd, int *err)
1278 {
1279     nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
1280     guint64 nsg_creltime;
1281
1282     if (wdh->file_type == WTAP_FILE_NETSCALER_1_0)
1283     {
1284         guint16 val16;
1285         guint32 reltime;
1286         guint64 abstime;
1287         nspr_abstime_v10_t abs10;
1288
1289         /* populate the record */
1290         val16 = htoles(NSPR_ABSTIME_V10);
1291         memcpy(abs10.phd.ph_RecordType, &val16, sizeof abs10.phd.ph_RecordType);
1292         val16 = htoles(nspr_abstime_v10_s);
1293         memcpy(abs10.phd.ph_RecordSize, &val16, sizeof abs10.phd.ph_RecordSize);
1294
1295         memcpy(&reltime, ((const nspr_pktracefull_v10_t *)pd)->fp_RelTimeHr, sizeof reltime);
1296         nsg_creltime = ns_hrtime2nsec(reltime);
1297
1298         memset(abs10.abs_RelTime, 0, sizeof abs10.abs_RelTime);
1299         abstime = htolel((guint32)phdr->ts.secs - (guint32)(nsg_creltime/1000000000));
1300         memcpy(abs10.abs_Time, &abstime, sizeof abs10.abs_Time);
1301
1302         /* Write the record into the file */
1303         if (!wtap_dump_file_write(wdh, &abs10, nspr_abstime_v10_s, err))
1304             return FALSE;
1305
1306         /* Move forward the page offset */
1307         nstrace->page_offset += nspr_abstime_v10_s;
1308
1309     } else if (wdh->file_type == WTAP_FILE_NETSCALER_2_0)
1310     {
1311         guint32 reltime;
1312         guint64 abstime;
1313         nspr_abstime_v20_t abs20;
1314
1315         abs20.abs_RecordType = NSPR_ABSTIME_V20;
1316         abs20.abs_RecordSize = nspr_abstime_v20_s;
1317
1318         memcpy(&reltime, ((const nspr_pktracefull_v20_t *)pd)->fp_RelTimeHr, sizeof reltime);
1319         nsg_creltime = ns_hrtime2nsec(reltime);
1320
1321         memset(abs20.abs_RelTime, 0, sizeof abs20.abs_RelTime);
1322         abstime = htolel((guint32)phdr->ts.secs - (guint32)(nsg_creltime/1000000000));
1323         memcpy(abs20.abs_RelTime, &abstime, sizeof abs20.abs_RelTime);
1324
1325         /* Write the record into the file */
1326         if (!wtap_dump_file_write(wdh, &abs20, nspr_abstime_v20_s, err))
1327             return FALSE;
1328
1329         /* Move forward the page offset */
1330         nstrace->page_offset += nspr_abstime_v20_s;
1331
1332     } else
1333     {
1334         g_assert_not_reached();
1335         return FALSE;
1336     }
1337
1338     return TRUE;
1339 }
1340
1341
1342 /* Write a record for a packet to a dump file.
1343    Returns TRUE on success, FALSE on failure. */
1344 static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1345     const guint8 *pd, int *err)
1346 {
1347     nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
1348
1349     if (nstrace->page_offset == 0)
1350     {
1351         /* Add the signature record and abs time record */
1352         if (wdh->file_type == WTAP_FILE_NETSCALER_1_0)
1353         {
1354             if (!nstrace_add_signature(wdh, err) ||
1355                 !nstrace_add_abstime(wdh, phdr, pd, err))
1356                 return FALSE;
1357         } else if (wdh->file_type == WTAP_FILE_NETSCALER_2_0)
1358         {
1359             if (!nstrace_add_signature(wdh, err) ||
1360                 !nstrace_add_abstime(wdh, phdr, pd, err))
1361                 return FALSE;
1362         } else
1363         {
1364             g_assert_not_reached();
1365             return FALSE;
1366         }
1367     }
1368
1369     switch (phdr->pseudo_header.nstr.rec_type)
1370     {
1371     case NSPR_HEADER_VERSION100:
1372
1373         if (wdh->file_type == WTAP_FILE_NETSCALER_1_0)
1374         {
1375             if (nstrace->page_offset + phdr->caplen >= nstrace->page_len)
1376             {
1377                 /* Start on the next page */
1378                 if (fseek(wdh->fh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR) == -1)
1379                 {
1380                     *err = errno;
1381                     return FALSE;
1382                 }
1383
1384                 nstrace->page_offset = 0;
1385
1386                 /* Possibly add signature and abstime records and increment offset */
1387                 if (!nstrace_add_signature(wdh, err))
1388                     return FALSE;
1389             }
1390
1391             /* Write the actual record as is */
1392             if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
1393                 return FALSE;
1394
1395             nstrace->page_offset += (guint16) phdr->caplen;
1396         } else if (wdh->file_type == WTAP_FILE_NETSCALER_2_0)
1397         {
1398             *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1399             return FALSE;
1400         }
1401
1402         break;
1403
1404     case NSPR_HEADER_VERSION200:
1405     case NSPR_HEADER_VERSION201:
1406     case NSPR_HEADER_VERSION202:
1407     case NSPR_HEADER_VERSION203:
1408     case NSPR_HEADER_VERSION204:
1409     case NSPR_HEADER_VERSION205:
1410         if (wdh->file_type == WTAP_FILE_NETSCALER_1_0)
1411         {
1412             *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1413             return FALSE;
1414         } else if (wdh->file_type == WTAP_FILE_NETSCALER_2_0)
1415         {
1416             if (nstrace->page_offset + phdr->caplen >= nstrace->page_len)
1417             {
1418                 /* Start on the next page */
1419                 if (fseek(wdh->fh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR) == -1)
1420                 {
1421                     *err = errno;
1422                     return FALSE;
1423                 }
1424
1425                 nstrace->page_offset = 0;
1426
1427                 /* Possibly add signature and abstime records and increment offset */
1428                 if (!nstrace_add_signature(wdh, err))
1429                     return FALSE;
1430             }
1431
1432             /* Write the actual record as is */
1433             if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
1434                 return FALSE;
1435
1436             nstrace->page_offset += (guint16) phdr->caplen;
1437         }
1438
1439         break;
1440
1441     default:
1442         g_assert_not_reached();
1443         return FALSE;
1444     }
1445
1446     return TRUE;
1447 }
1448