Witness: working witness.cnf
[wireshark-wip.git] / wiretap / netscaler.c
blob4e53ab6e93443a88e12faa0c667f69202cc52a29
1 /* netscaler.c
3 * $Id$
5 * Wiretap Library
6 * Copyright (c) 2006 by Ravi Kondamuru <Ravi.Kondamuru@citrix.com>
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.
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.
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.
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"
31 /* Defines imported from netscaler code: nsperfrc.h */
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"
41 * NetScaler trace files are divided into 8K pages, with each page
42 * containing one or more records. The last page of the file
43 * might be less than 8K bytes.
45 * Records are not split across page boundaries; if a record doesn't
46 * fit in what remains in a page, the page is padded with null bytes
47 * and the next record is put at the beginning of the next page.
48 * A record type value of 0 means "unused space", so if there are
49 * enough null bytes to constitute a record type value, it will
50 * look as if there's an "unused space" record (which has no fields
51 * other than the type and zero or more additional padding bytes).
53 #define NSPR_PAGESIZE 8192
55 /* The different record types
56 ** NOTE: The Record Type is two byte fields and unused space is recognized by
57 ** either bytes being zero, therefore no record should any byte value as
58 ** zero.
60 ** New Performance Record Type is only one byte.
62 #define NSPR_UNUSEDSPACE_V10 0x0000 /* rest of the page is unused */
63 #define NSPR_UNUSEDSPACE_V20 0x00 /* rest of the page is unused */
64 #define NSPR_SIGNATURE_V10 0x0101 /* signature */
65 #define NSPR_SIGNATURE_V20 0x01 /* signature */
66 #define NSPR_ABSTIME_V10 0x0107 /* data capture time in secs from 1970*/
67 #define NSPR_ABSTIME_V20 0x07 /* data capture time in secs from 1970*/
68 #define NSPR_RELTIME_V10 0x0108 /* relative time in ms from last time */
69 #define NSPR_RELTIME_V20 0x08 /* relative time in ms from last time */
70 #define NSPR_RELTIMEHR_V10 0x0109 /* high resolution relative time */
71 #define NSPR_RELTIMEHR_V20 0x09 /* high resolution relative time */
72 #define NSPR_SYSTARTIME_V10 0x010A /* system start time */
73 #define NSPR_SYSTARTIME_V20 0x0A /* system start time */
74 #define NSPR_RELTIME2B_V10 0x010B /* relative time in ms from last time */
75 #define NSPR_RELTIME2B_V20 0x0B /* relative time in ms from last time */
78 /* The high resolution relative time format.
79 ** The MS 2 bits of the high resoltion time is defined as follows:
80 ** 00 : time value is in seconds
81 ** 01 : time value is in milliseconds
82 ** 10 : time value is in microseconds
83 ** 11 : time value is in nanoseconds
85 #define NSPR_HRTIME_MASKTM 0x3FFFFFFF /* mask to get time value */
86 #define NSPR_HRTIME_MASKFMT 0xC0000000 /* time value format mask */
87 #define NSPR_HRTIME_SEC 0x00000000 /* time value in second */
88 #define NSPR_HRTIME_MSEC 0x40000000 /* time value in mili second */
89 #define NSPR_HRTIME_USEC 0x80000000 /* time value in micro second */
90 #define NSPR_HRTIME_NSEC 0xC0000000 /* time value in nano second */
93 typedef struct nspr_header_v10
95 guint8 ph_RecordType[2]; /* Record Type */
96 guint8 ph_RecordSize[2]; /* Record Size including header */
97 } nspr_header_v10_t;
98 #define nspr_header_v10_s ((guint32)sizeof(nspr_header_v10_t))
100 /* This is V20 short header (2 bytes long) to be included where needed */
101 #define NSPR_HEADER_V20(prefix) \
102 guint8 prefix##_RecordType; /* Record Type */ \
103 guint8 prefix##_RecordSize /* Record Size including header */ \
104 /* end of declaration */
106 /* This is new long header (3 bytes long) to be included where needed */
107 #define NSPR_HEADER3B_V20(prefix) \
108 guint8 prefix##_RecordType; /* Record Type */ \
109 guint8 prefix##_RecordSizeLow; /* Record Size including header */ \
110 guint8 prefix##_RecordSizeHigh /* Record Size including header */ \
111 /* end of declaration */
112 #define NSPR_HEADER3B_V21 NSPR_HEADER3B_V20
113 #define NSPR_HEADER3B_V22 NSPR_HEADER3B_V20
115 typedef struct nspr_hd_v20
117 NSPR_HEADER3B_V20(phd); /* long performance header */
119 } nspr_hd_v20_t;
120 #define nspr_hd_v20_s ((guint32)sizeof(nspr_hd_v20_t))
124 ** How to know if header size is short or long?
125 ** The short header size can be 0-127 bytes long. If MS Bit of ph_RecordSize
126 ** is set then record size has 2 bytes
128 #define NSPR_V20RECORDSIZE_2BYTES 0x80
130 /* Performance Data Header with device number */
131 typedef struct nspr_headerdev_v10
133 guint8 ph_RecordType[2]; /* Record Type */
134 guint8 ph_RecordSize[2]; /* Record Size including header */
135 guint8 ph_DevNo[4]; /* Network Device (NIC/CONN) number */
136 } nspr_headerdev_v10_t;
137 #define nspr_headerdev_v10_s ((guint32)sizeof(nspr_headerdev_v10_t))
139 typedef struct nspr_hd_v10
141 nspr_header_v10_t phd; /* performance header */
142 } nspr_hd_v10_t;
143 #define nspr_hd_v10_s ((guint32)sizeof(nspr_hd_v10_t))
145 typedef struct nspr_hdev_v10
147 nspr_headerdev_v10_t phd; /* performance header */
148 } nspr_hdev_v10_t;
149 #define nspr_hdev_v10_s ((guint32)sizeof(nspr_hdev_v10_t))
151 /* if structure has defined phd as first field, it can use following names */
152 #define nsprRecordType phd.ph_RecordType
153 #define nsprRecordSize phd.ph_RecordSize
154 #define nsprReserved phd.ph_Reserved
155 #define nsprRecordTypeOrg phd.ph_Reserved
156 #define nsprDevNo phd.ph_DevNo
158 /* NSPR_SIGNATURE_V10 structure */
159 #define NSPR_SIGSIZE_V10 56 /* signature value size in bytes */
160 typedef struct nspr_signature_v10
162 nspr_header_v10_t phd; /* performance header */
163 guint8 sig_EndianType; /* Endian Type for the data */
164 guint8 sig_Reserved0;
165 guint8 sig_Reserved1[2];
166 gchar sig_Signature[NSPR_SIGSIZE_V10]; /* Signature value */
167 } nspr_signature_v10_t;
168 #define nspr_signature_v10_s ((guint32)sizeof(nspr_signature_v10_t))
170 /* NSPR_SIGNATURE_V20 structure */
171 #define NSPR_SIGSIZE_V20 sizeof(NSPR_SIGSTR_V20) /* signature value size in bytes */
172 typedef struct nspr_signature_v20
174 NSPR_HEADER_V20(sig); /* short performance header */
175 guint8 sig_EndianType; /* Endian Type for the data */
176 gchar sig_Signature[NSPR_SIGSIZE_V20]; /* Signature value */
177 } nspr_signature_v20_t;
178 #define nspr_signature_v20_s ((guint32)sizeof(nspr_signature_v20_t))
180 /* NSPR_ABSTIME_V10 and NSPR_SYSTARTIME_V10 structure */
181 typedef struct nspr_abstime_v10
183 nspr_header_v10_t phd; /* performance header */
184 guint8 abs_RelTime[4]; /* relative time is ms from last time */
185 guint8 abs_Time[4]; /* absolute time in seconds from 1970 */
186 } nspr_abstime_v10_t;
187 #define nspr_abstime_v10_s ((guint32)sizeof(nspr_abstime_v10_t))
190 /* NSPR_ABSTIME_V20 and NSPR_SYSTARTIME_V20 structure */
191 typedef struct nspr_abstime_v20
193 NSPR_HEADER_V20(abs); /* short performance header */
194 guint8 abs_RelTime[2]; /* relative time is ms from last time */
195 guint8 abs_Time[4]; /* absolute time in seconds from 1970 */
196 } nspr_abstime_v20_t;
197 #define nspr_abstime_v20_s ((guint32)sizeof(nspr_abstime_v20_t))
201 /* full packet trace structure */
202 typedef struct nspr_pktracefull_v10
204 nspr_headerdev_v10_t phd; /* performance header */
205 guint8 fp_RelTimeHr[4]; /* High resolution relative time */
206 guint8 fp_Data[1]; /* packet data starts here */
207 } nspr_pktracefull_v10_t;
208 #define nspr_pktracefull_v10_s (nspr_hdev_v10_s + 4)
210 /* new full packet trace structure v20 */
211 typedef struct nspr_pktracefull_v20
213 NSPR_HEADER3B_V20(fp); /* long performance header */
214 guint8 fp_DevNo; /* Network Device (NIC) number */
215 guint8 fp_RelTimeHr[4]; /* High resolution relative time */
216 guint8 fp_Data[4]; /* packet data starts here */
217 } nspr_pktracefull_v20_t;
218 #define nspr_pktracefull_v20_s ((guint32)(sizeof(nspr_pktracefull_v20_t) - 4))
220 /* new full packet trace structure v21 */
221 typedef struct nspr_pktracefull_v21
223 NSPR_HEADER3B_V21(fp); /* long performance header */
224 guint8 fp_DevNo; /* Network Device (NIC) number */
225 guint8 fp_RelTimeHr[4]; /* High resolution relative time */
226 guint8 fp_PcbDevNo[4]; /* PCB devno */
227 guint8 fp_lPcbDevNo[4]; /* link PCB devno */
228 guint8 fp_Data[4]; /* packet data starts here */
229 } nspr_pktracefull_v21_t;
230 #define nspr_pktracefull_v21_s ((guint32)(sizeof(nspr_pktracefull_v21_t) - 4))
232 /* new full packet trace structure v22 */
233 typedef struct nspr_pktracefull_v22
235 NSPR_HEADER3B_V22(fp); /* long performance header */
236 guint8 fp_DevNo; /* Network Device (NIC) number */
237 guint8 fp_RelTimeHr[4]; /* High resolution relative time */
238 guint8 fp_PcbDevNo[4]; /* PCB devno */
239 guint8 fp_lPcbDevNo[4]; /* link PCB devno */
240 guint8 fp_VlanTag[2]; /* vlan tag */
241 guint8 fp_Data[2]; /* packet data starts here */
242 } nspr_pktracefull_v22_t;
243 #define nspr_pktracefull_v22_s ((guint32)(sizeof(nspr_pktracefull_v22_t) - 2))
245 typedef struct nspr_pktracefull_v23
247 NSPR_HEADER3B_V22(fp); /* long performance header */
248 guint8 fp_DevNo; /* Network Device (NIC) number */
249 guint8 fp_AbsTimeHr[8]; /* High resolution absolute time */
250 guint8 fp_PcbDevNo[4]; /* PCB devno */
251 guint8 fp_lPcbDevNo[4]; /* link PCB devno */
252 guint8 fp_VlanTag[2]; /* vlan tag */
253 guint8 fp_Coreid[2]; /* coreid of the packet */
254 guint8 fp_Data[2]; /* packet data starts here */
255 } nspr_pktracefull_v23_t;
256 #define nspr_pktracefull_v23_s ((guint32)(sizeof(nspr_pktracefull_v23_t) - 2))
258 /* New full packet trace structure v24 for cluster tracing */
259 typedef struct nspr_pktracefull_v24
261 NSPR_HEADER3B_V22(fp); /* long performance header */
262 guint8 fp_DevNo; /* Network Device (NIC) number */
263 guint8 fp_AbsTimeHr[8]; /* High resolution absolute time in nanosec */
264 guint8 fp_PcbDevNo[4]; /* PCB devno */
265 guint8 fp_lPcbDevNo[4]; /* link PCB devno */
266 guint8 fp_VlanTag[2]; /* vlan tag */
267 guint8 fp_Coreid[2]; /* coreid of the packet */
268 guint8 fp_srcNodeId[2]; /* source node # */
269 guint8 fp_destNodeId[2]; /* destination node # */
270 guint8 fp_clFlags; /* cluster flags */
271 guint8 fp_Data[2]; /* packet data starts here */
272 } nspr_pktracefull_v24_t;
273 #define nspr_pktracefull_v24_s ((guint32)(sizeof(nspr_pktracefull_v24_t) - 4))
275 /* New full packet trace structure v25 for vm info tracing */
276 typedef struct nspr_pktracefull_v25
278 NSPR_HEADER3B_V22(fp); /* long performance header */
279 guint8 fp_DevNo; /* Network Device (NIC) number */
280 guint8 fp_AbsTimeHr[8]; /* High resolution absolute time in nanosec */
281 guint8 fp_PcbDevNo[4]; /* PCB devno */
282 guint8 fp_lPcbDevNo[4]; /* link PCB devno */
283 guint8 fp_VlanTag[2]; /* vlan tag */
284 guint8 fp_Coreid[2]; /* coreid of the packet */
285 guint8 fp_srcNodeId[2]; /* source node # */
286 guint8 fp_destNodeId[2]; /* destination node # */
287 guint8 fp_clFlags; /* cluster flags */
288 guint8 fp_src_vmname_len; /* vm src info */
289 guint8 fp_dst_vmname_len; /* vm src info */
290 guint8 fp_Data[4]; /* packet data starts here */
291 } nspr_pktracefull_v25_t;
292 #define nspr_pktracefull_v25_s ((guint32)(sizeof(nspr_pktracefull_v25_t) - 4))
293 #define fp_src_vmname fp_Data
294 #define fp_src_vmname fp_Data
296 /* New full packet trace structure v26 for vm info tracing */
297 typedef struct nspr_pktracefull_v26
299 NSPR_HEADER3B_V22(fp); /* long performance header */
300 guint8 fp_DevNo; /* Network Device (NIC) number */
301 guint8 fp_AbsTimeHr[8]; /* High resolution absolute time in nanosec */
302 guint8 fp_PcbDevNo[4]; /* PCB devno */
303 guint8 fp_lPcbDevNo[4]; /* link PCB devno */
304 guint8 fp_VlanTag[2]; /* vlan tag */
305 guint8 fp_Coreid[2]; /* coreid of the packet */
306 guint8 fp_srcNodeId[2]; /* source node # */
307 guint8 fp_destNodeId[2]; /* destination node # */
308 guint8 fp_clFlags; /* cluster flags */
309 guint8 fp_src_vmname_len; /* vm src info */
310 guint8 fp_dst_vmname_len; /* vm src info */
311 guint8 fp_reserved;
312 guint8 fp_ns_activity[4];
313 guint8 fp_reserved_32[12]; /* Adding more field to reduce wireshark changes every time */
314 guint8 fp_Data[4]; /* packet data starts here */
315 } nspr_pktracefull_v26_t;
316 #define nspr_pktracefull_v26_s ((guint32)(sizeof(nspr_pktracefull_v26_t) - 4))
318 /* partial packet trace structure */
319 typedef struct nspr_pktracepart_v10
321 nspr_headerdev_v10_t phd; /* performance header */
322 guint8 pp_RelTimeHr[4]; /* High resolution relative time */
323 guint8 pp_PktSizeOrg[2]; /* Original packet size */
324 guint8 pp_PktOffset[2]; /* starting offset in packet */
325 guint8 pp_Data[1]; /* packet data starts here */
326 } nspr_pktracepart_v10_t;
327 #define nspr_pktracepart_v10_s (nspr_pktracefull_v10_s + 4)
329 /* new partial packet trace structure */
330 typedef struct nspr_pktracepart_v20
332 NSPR_HEADER3B_V20(pp); /* long performance header */
333 guint8 pp_DevNo; /* Network Device (NIC) number */
334 guint8 pp_RelTimeHr[4]; /* High resolution relative time */
335 guint8 pp_PktSizeOrg[2]; /* Original packet size */
336 guint8 pp_PktOffset[2]; /* starting offset in packet */
337 guint8 pp_Data[4]; /* packet data starts here */
338 } nspr_pktracepart_v20_t;
339 #define nspr_pktracepart_v20_s ((guint32)(sizeof(nspr_pktracepart_v20_t) -4))
341 /* new partial packet trace structure */
342 typedef struct nspr_pktracepart_v21
344 NSPR_HEADER3B_V21(pp); /* long performance header */
345 guint8 pp_DevNo; /* Network Device (NIC) number */
346 guint8 pp_RelTimeHr[4]; /* High resolution relative time */
347 guint8 pp_PktSizeOrg[2]; /* Original packet size */
348 guint8 pp_PktOffset[2]; /* starting offset in packet */
349 guint8 pp_PcbDevNo[4]; /* PCB devno */
350 guint8 pp_lPcbDevNo[4]; /* link PCB devno */
351 guint8 pp_Data[4]; /* packet data starts here */
352 } nspr_pktracepart_v21_t;
353 #define nspr_pktracepart_v21_s ((guint32)(sizeof(nspr_pktracepart_v21_t) -4))
355 /* new partial packet trace structure v22 */
356 typedef struct nspr_pktracepart_v22
358 NSPR_HEADER3B_V22(pp); /* long performance header */
359 guint8 pp_DevNo; /* Network Device (NIC) number */
360 guint8 pp_RelTimeHr[4]; /* High resolution relative time */
361 guint8 pp_PktSizeOrg[2]; /* Original packet size */
362 guint8 pp_PktOffset[2]; /* starting offset in packet */
363 guint8 pp_PcbDevNo[4]; /* PCB devno */
364 guint8 pp_lPcbDevNo[4]; /* link PCB devno */
365 guint8 pp_VlanTag[2]; /* Vlan Tag */
366 guint8 pp_Data[2]; /* packet data starts here */
367 } nspr_pktracepart_v22_t;
368 #define nspr_pktracepart_v22_s ((guint32)(sizeof(nspr_pktracepart_v22_t) -2))
370 typedef struct nspr_pktracepart_v23
372 NSPR_HEADER3B_V22(pp); /* long performance header */
373 guint8 pp_DevNo; /* Network Device (NIC) number */
374 guint8 pp_AbsTimeHr[8]; /* High resolution absolute time */
375 guint8 pp_PktSizeOrg[2]; /* Original packet size */
376 guint8 pp_PktOffset[2]; /* starting offset in packet */
377 guint8 pp_PcbDevNo[4]; /* PCB devno */
378 guint8 pp_lPcbDevNo[4]; /* link PCB devno */
379 guint8 pp_VlanTag[2]; /* vlan tag */
380 guint8 pp_Coreid[2]; /* Coreid of the packet */
381 guint8 pp_Data[4]; /* packet data starts here */
382 } nspr_pktracepart_v23_t;
383 #define nspr_pktracepart_v23_s ((guint32)(sizeof(nspr_pktracepart_v23_t) -4))
385 /* New partial packet trace structure v24 for cluster tracing */
386 typedef struct nspr_pktracepart_v24
388 NSPR_HEADER3B_V22(pp); /* long performance header */
389 guint8 pp_DevNo; /* Network Device (NIC) number */
390 guint8 pp_AbsTimeHr[8]; /*High resolution absolute time in nanosec*/
391 guint8 pp_PktSizeOrg[2]; /* Original packet size */
392 guint8 pp_PktOffset[2]; /* starting offset in packet */
393 guint8 pp_PcbDevNo[4]; /* PCB devno */
394 guint8 pp_lPcbDevNo[4]; /* link PCB devno */
395 guint8 pp_VlanTag[2]; /* vlan tag */
396 guint8 pp_Coreid[2]; /* Coreid of the packet */
397 guint8 pp_srcNodeId[2]; /* source node # */
398 guint8 pp_destNodeId[2]; /* destination node # */
399 guint8 pp_clFlags; /* cluster flags */
400 guint8 pp_Data[4]; /* packet data starts here */
401 } nspr_pktracepart_v24_t;
402 #define nspr_pktracepart_v24_s ((guint32)(sizeof(nspr_pktracepart_v24_t) -4))
404 /* New partial packet trace structure v25 for vm info tracing */
405 typedef struct nspr_pktracepart_v25
407 NSPR_HEADER3B_V22(pp); /* long performance header */
408 guint8 pp_DevNo; /* Network Device (NIC) number */
409 guint8 pp_AbsTimeHr[8]; /*High resolution absolute time in nanosec*/
410 guint8 pp_PktSizeOrg[2]; /* Original packet size */
411 guint8 pp_PktOffset[2]; /* starting offset in packet */
412 guint8 pp_PcbDevNo[4]; /* PCB devno */
413 guint8 pp_lPcbDevNo[4]; /* link PCB devno */
414 guint8 pp_VlanTag[2]; /* vlan tag */
415 guint8 pp_Coreid[2]; /* Coreid of the packet */
416 guint8 pp_srcNodeId[2]; /* source node # */
417 guint8 pp_destNodeId[2]; /* destination node # */
418 guint8 pp_clFlags; /* cluster flags */
419 guint8 pp_src_vmname_len; /* vm info */
420 guint8 pp_dst_vmname_len; /* vm info */
421 guint8 pp_Data[4]; /* packet data starts here */
422 } nspr_pktracepart_v25_t;
423 #define nspr_pktracepart_v25_s ((guint32)(sizeof(nspr_pktracepart_v25_t) -4))
424 #define pp_src_vmname pp_Data
425 #define pp_dst_vmname pp_Data
427 /* New partial packet trace structure v26 for vm info tracing */
428 typedef struct nspr_pktracepart_v26
430 NSPR_HEADER3B_V22(pp); /* long performance header */
431 guint8 pp_DevNo; /* Network Device (NIC) number */
432 guint8 pp_AbsTimeHr[8]; /*High resolution absolute time in nanosec*/
433 guint8 pp_PktSizeOrg[2]; /* Original packet size */
434 guint8 pp_PktOffset[2]; /* starting offset in packet */
435 guint8 pp_PcbDevNo[4]; /* PCB devno */
436 guint8 pp_lPcbDevNo[4]; /* link PCB devno */
437 guint8 pp_VlanTag[2]; /* vlan tag */
438 guint8 pp_Coreid[2]; /* Coreid of the packet */
439 guint8 pp_srcNodeId[2]; /* source node # */
440 guint8 pp_destNodeId[2]; /* destination node # */
441 guint8 pp_clFlags; /* cluster flags */
442 guint8 pp_src_vmname_len; /* vm info */
443 guint8 pp_dst_vmname_len; /* vm info */
444 guint8 pp_reserved;
445 guint8 pp_ns_activity[4];
446 guint8 pp_reserved_32[12]; /* Adding more field to reduce wireshark changes every time */
447 guint8 pp_Data[4]; /* packet data starts here */
448 } nspr_pktracepart_v26_t;
449 #define nspr_pktracepart_v26_s ((guint32)(sizeof(nspr_pktracepart_v26_t) -4))
451 #define myoffsetof(type,fieldname) (&(((type*)0)->fieldname))
453 #define __TNO(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
454 guint8 enumprefix##_##hdrname##_offset = (guint8)GPOINTER_TO_INT(myoffsetof(nspr_##structname##_t,structprefix##_##structfieldname));
456 #define __TNL(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
457 guint8 enumprefix##_##hdrname##_len = (guint8)sizeof(((nspr_##structname##_t*)0)->structprefix##_##structfieldname);
459 #define __TNV1O(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
460 guint8 enumprefix##_##hdrname##_offset = (guint8)GPOINTER_TO_INT(myoffsetof(nspr_##structname##_t,structfieldname));
462 #define __TNV1L(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
463 guint8 enumprefix##_##hdrname##_len = (guint8)sizeof(((nspr_##structname##_t*)0)->structfieldname);
465 #define TRACE_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
466 __TNV1O(phdr,enumprefix,structprefix,structname,dir,phd.ph_RecordType)\
467 __TNV1L(phdr,enumprefix,structprefix,structname,dir,phd.ph_RecordType)\
468 __TNV1O(phdr,enumprefix,structprefix,structname,nicno,phd.ph_DevNo)\
469 __TNV1L(phdr,enumprefix,structprefix,structname,nicno,phd.ph_DevNo)\
470 __TNO(phdr,enumprefix,structprefix,structname,eth,Data)
472 #define TRACE_FULL_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
473 (phdr)->len = pletohs(&(fp)->nsprRecordSize);\
474 (phdr)->caplen = (phdr)->len;\
475 TRACE_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)
477 #define TRACE_PART_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
478 (phdr)->presence_flags |= WTAP_HAS_CAP_LEN;\
479 (phdr)->len = pletohs(&pp->pp_PktSizeOrg) + nspr_pktracepart_v10_s;\
480 (phdr)->caplen = pletohs(&pp->nsprRecordSize);\
481 TRACE_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)
483 #define TRACE_V20_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
484 __TNO(phdr,enumprefix,structprefix,structname,dir,RecordType)\
485 __TNL(phdr,enumprefix,structprefix,structname,dir,RecordType)\
486 __TNO(phdr,enumprefix,structprefix,structname,nicno,DevNo)\
487 __TNL(phdr,enumprefix,structprefix,structname,nicno,DevNo)\
488 __TNO(phdr,enumprefix,structprefix,structname,eth,Data)
490 #define TRACE_V21_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
491 TRACE_V20_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
492 __TNO(phdr,enumprefix,structprefix,structname,pcb,PcbDevNo)\
493 __TNO(phdr,enumprefix,structprefix,structname,l_pcb,lPcbDevNo)
495 #define TRACE_V22_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
496 TRACE_V21_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
497 __TNO(phdr,enumprefix,structprefix,structname,vlantag,VlanTag)
499 #define TRACE_V23_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
500 TRACE_V22_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
501 __TNO(phdr,enumprefix,structprefix,structname,coreid,Coreid)
503 #define TRACE_V24_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
504 TRACE_V23_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
505 __TNO(phdr,enumprefix,structprefix,structname,srcnodeid,srcNodeId)\
506 __TNO(phdr,enumprefix,structprefix,structname,destnodeid,destNodeId)\
507 __TNO(phdr,enumprefix,structprefix,structname,clflags,clFlags)
509 #define TRACE_V25_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
510 TRACE_V24_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
511 __TNO(phdr,enumprefix,structprefix,structname,src_vmname_len,src_vmname_len)\
512 __TNO(phdr,enumprefix,structprefix,structname,dst_vmname_len,dst_vmname_len)\
513 __TNO(phdr,enumprefix,structprefix,structname,data,Data)
515 #define TRACE_V26_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
516 TRACE_V25_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
517 __TNO(phdr,enumprefix,structprefix,structname,ns_activity,ns_activity)\
519 TRACE_V10_REC_LEN_OFF(NULL,v10_part,pp,pktracepart_v10)
520 TRACE_V10_REC_LEN_OFF(NULL,v10_full,fp,pktracefull_v10)
521 TRACE_V20_REC_LEN_OFF(NULL,v20_part,pp,pktracepart_v20)
522 TRACE_V20_REC_LEN_OFF(NULL,v20_full,fp,pktracefull_v20)
523 TRACE_V21_REC_LEN_OFF(NULL,v21_part,pp,pktracepart_v21)
524 TRACE_V21_REC_LEN_OFF(NULL,v21_full,fp,pktracefull_v21)
525 TRACE_V22_REC_LEN_OFF(NULL,v22_part,pp,pktracepart_v22)
526 TRACE_V22_REC_LEN_OFF(NULL,v22_full,fp,pktracefull_v22)
527 TRACE_V23_REC_LEN_OFF(NULL,v23_part,pp,pktracepart_v23)
528 TRACE_V23_REC_LEN_OFF(NULL,v23_full,fp,pktracefull_v23)
529 TRACE_V24_REC_LEN_OFF(NULL,v24_part,pp,pktracepart_v24)
530 TRACE_V24_REC_LEN_OFF(NULL,v24_full,fp,pktracefull_v24)
531 TRACE_V25_REC_LEN_OFF(NULL,v25_part,pp,pktracepart_v25)
532 TRACE_V25_REC_LEN_OFF(NULL,v25_full,fp,pktracefull_v25)
533 TRACE_V26_REC_LEN_OFF(NULL,v26_part,pp,pktracepart_v26)
534 TRACE_V26_REC_LEN_OFF(NULL,v26_full,fp,pktracefull_v26)
536 #undef __TNV1O
537 #undef __TNV1L
538 #undef __TNO
539 #undef __TNL
542 #define ns_setabstime(nstrace, AbsoluteTime, RelativeTimems) \
543 do { \
544 (nstrace)->nspm_curtime = AbsoluteTime; \
545 (nstrace)->nspm_curtimemsec += RelativeTimems; \
546 (nstrace)->nspm_curtimelastmsec = nstrace->nspm_curtimemsec; \
547 } while(0)
550 #define ns_setrelativetime(nstrace, RelativeTimems) \
551 do { \
552 guint32 rsec; \
553 (nstrace)->nspm_curtimemsec += RelativeTimems; \
554 rsec = (guint32)((nstrace)->nspm_curtimemsec - (nstrace)->nspm_curtimelastmsec)/1000; \
555 (nstrace)->nspm_curtime += rsec; \
556 (nstrace)->nspm_curtimelastmsec += rsec * 1000; \
557 } while (0)
560 typedef struct {
561 gchar *pnstrace_buf;
562 gint64 xxx_offset;
563 gint32 nstrace_buf_offset;
564 gint32 nstrace_buflen;
565 /* Performance Monitor Time variables */
566 guint32 nspm_curtime; /* current time since 1970 */
567 guint64 nspm_curtimemsec; /* current time in milliseconds */
568 guint64 nspm_curtimelastmsec; /* nspm_curtime last update time in milliseconds */
569 guint64 nsg_creltime;
570 guint64 file_size;
571 } nstrace_t;
573 static guint32 nspm_signature_version(wtap*, gchar*, gint32);
574 static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info,
575 gint64 *data_offset);
576 static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info,
577 gint64 *data_offset);
578 static gboolean nstrace_seek_read_v10(wtap *wth, gint64 seek_off,
579 struct wtap_pkthdr *phdr,
580 Buffer *buf, int length,
581 int *err, gchar **err_info);
582 static gboolean nstrace_seek_read_v20(wtap *wth, gint64 seek_off,
583 struct wtap_pkthdr *phdr,
584 Buffer *buf, int length,
585 int *err, gchar **err_info);
586 static void nstrace_close(wtap *wth);
588 static gboolean nstrace_set_start_time_v10(wtap *wth);
589 static gboolean nstrace_set_start_time_v20(wtap *wth);
590 static gboolean nstrace_set_start_time(wtap *wth);
591 static guint64 ns_hrtime2nsec(guint32 tm);
593 static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
594 const guint8 *pd, int *err);
598 * Minimum of the page size and the amount of data left in the file;
599 * the last page of a file can be short.
601 #define GET_READ_PAGE_SIZE(remaining_file_size) ((gint32)((remaining_file_size>NSPR_PAGESIZE)?NSPR_PAGESIZE:remaining_file_size))
604 static guint64 ns_hrtime2nsec(guint32 tm)
606 guint32 val = tm & NSPR_HRTIME_MASKTM;
607 switch(tm & NSPR_HRTIME_MASKFMT)
609 case NSPR_HRTIME_SEC: return (guint64)val*1000000000;
610 case NSPR_HRTIME_MSEC: return (guint64)val*1000000;
611 case NSPR_HRTIME_USEC: return (guint64)val*1000;
612 case NSPR_HRTIME_NSEC: return val;
614 return tm;
619 ** Netscaler trace format open routines
621 int nstrace_open(wtap *wth, int *err, gchar **err_info)
623 gchar *nstrace_buf;
624 gint64 file_size;
625 gint32 page_size;
626 nstrace_t *nstrace;
627 int bytes_read;
629 errno = WTAP_ERR_CANT_READ;
631 if ((file_size = wtap_file_size(wth, err)) == -1)
632 return 0;
634 nstrace_buf = (gchar *)g_malloc(NSPR_PAGESIZE);
635 page_size = GET_READ_PAGE_SIZE(file_size);
637 switch ((wth->file_type_subtype = nspm_signature_version(wth, nstrace_buf, page_size)))
639 case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0:
640 wth->file_encap = WTAP_ENCAP_NSTRACE_1_0;
641 break;
643 case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0:
644 wth->file_encap = WTAP_ENCAP_NSTRACE_2_0;
645 break;
647 default:
648 *err = WTAP_ERR_UNSUPPORTED;
649 *err_info = g_strdup_printf("nstrace: file type %d unsupported", wth->file_type_subtype);
650 g_free(nstrace_buf);
651 return 0;
654 if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
656 *err = file_error(wth->fh, err_info);
657 g_free(nstrace_buf);
658 return 0;
661 bytes_read = file_read(nstrace_buf, page_size, wth->fh);
662 if (bytes_read != page_size)
664 *err = file_error(wth->fh, err_info);
665 g_free(nstrace_buf);
666 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
667 return -1;
668 return 0;
671 switch (wth->file_type_subtype)
673 case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0:
674 wth->subtype_read = nstrace_read_v10;
675 wth->subtype_seek_read = nstrace_seek_read_v10;
676 break;
678 case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0:
679 wth->subtype_read = nstrace_read_v20;
680 wth->subtype_seek_read = nstrace_seek_read_v20;
681 break;
683 wth->subtype_close = nstrace_close;
685 nstrace = (nstrace_t *)g_malloc(sizeof(nstrace_t));
686 wth->priv = (void *)nstrace;
687 nstrace->pnstrace_buf = nstrace_buf;
688 nstrace->xxx_offset = 0;
689 nstrace->nstrace_buflen = page_size;
690 nstrace->nstrace_buf_offset = 0;
691 nstrace->nspm_curtime = 0;
692 nstrace->nspm_curtimemsec = 0;
693 nstrace->nspm_curtimelastmsec = 0;
694 nstrace->nsg_creltime = 0;
695 nstrace->file_size = file_size;
698 /* Set the start time by looking for the abstime record */
699 if ((nstrace_set_start_time(wth)) == FALSE)
701 /* Reset the read pointer to start of the file. */
702 if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
704 *err = file_error(wth->fh, err_info);
705 g_free(nstrace->pnstrace_buf);
706 g_free(nstrace);
707 return 0;
710 /* Read the first page of data */
711 bytes_read = file_read(nstrace_buf, page_size, wth->fh);
712 if (bytes_read != page_size)
714 *err = file_error(wth->fh, err_info);
715 g_free(nstrace->pnstrace_buf);
716 g_free(nstrace);
717 return 0;
720 /* reset the buffer offset */
721 nstrace->nstrace_buf_offset = 0;
724 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
725 wth->phdr.ts.secs = nstrace->nspm_curtime;
726 wth->phdr.ts.nsecs = 0;
728 *err = 0;
729 return 1;
733 #define nspm_signature_func(ver) \
734 static guint32 nspm_signature_isv##ver(gchar *sigp) {\
735 return strncmp(sigp,NSPR_SIGSTR_V##ver,(sizeof(NSPR_SIGSTR_V##ver)-1));\
738 nspm_signature_func(10)
739 nspm_signature_func(20)
742 ** Check signature and return the version number of the signature.
743 ** If not found, it returns 0. At the time of return from this function
744 ** we might not be at the first page. So after a call to this function, there
745 ** has to be a file seek to return to the start of the first page.
747 static guint32
748 nspm_signature_version(wtap *wth, gchar *nstrace_buf, gint32 len)
750 gchar *dp = nstrace_buf;
751 int bytes_read;
753 bytes_read = file_read(dp, len, wth->fh);
754 if (bytes_read == len) {
756 for ( ; len > (gint32)(MIN(sizeof(NSPR_SIGSTR_V10), sizeof(NSPR_SIGSTR_V20))); dp++, len--)
758 #define sigv10p ((nspr_signature_v10_t*)dp)
759 if ((pletohs(&sigv10p->nsprRecordType) == NSPR_SIGNATURE_V10) &&
760 (pletohs(&sigv10p->nsprRecordSize) <= len) &&
761 ((gint32)sizeof(NSPR_SIGSTR_V10) <= len) &&
762 (!nspm_signature_isv10(sigv10p->sig_Signature)))
763 return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0;
764 #undef sigv10p
766 #define sigv20p ((nspr_signature_v20_t*)dp)
767 if ((sigv20p->sig_RecordType == NSPR_SIGNATURE_V20) &&
768 (sigv20p->sig_RecordSize <= len) &&
769 ((gint32)sizeof(NSPR_SIGSTR_V20) <= len) &&
770 (!nspm_signature_isv20(sigv20p->sig_Signature)))
771 return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0;
772 #undef sigv20p
776 return 0; /* no version found */
779 #define nspr_getv10recordtype(hdp) (pletohs(&hdp->nsprRecordType))
780 #define nspr_getv10recordsize(hdp) (pletohs(&hdp->nsprRecordSize))
781 #define nspr_getv20recordtype(hdp) (hdp->phd_RecordType)
782 #define nspr_getv20recordsize(hdp) \
783 (((hdp)->phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES)? \
784 (((hdp)->phd_RecordSizeHigh * NSPR_V20RECORDSIZE_2BYTES)+ \
785 ((hdp)->phd_RecordSizeLow & ~NSPR_V20RECORDSIZE_2BYTES)) : \
786 (hdp)->phd_RecordSizeLow)
789 #define nstrace_set_start_time_ver(ver) \
790 gboolean nstrace_set_start_time_v##ver(wtap *wth) \
792 nstrace_t *nstrace = (nstrace_t *)wth->priv;\
793 gchar* nstrace_buf = nstrace->pnstrace_buf;\
794 gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;\
795 gint32 nstrace_buflen = nstrace->nstrace_buflen;\
796 int bytes_read;\
799 while (nstrace_buf_offset < nstrace_buflen)\
801 nspr_hd_v##ver##_t *fp = (nspr_hd_v##ver##_t *) &nstrace_buf[nstrace_buf_offset];\
802 switch (nspr_getv##ver##recordtype(fp))\
804 case NSPR_ABSTIME_V##ver:\
805 ns_setabstime(nstrace, pletohl(&((nspr_abstime_v##ver##_t *) fp)->abs_Time), pletohs(&((nspr_abstime_v##ver##_t *) fp)->abs_RelTime));\
806 nstrace->nstrace_buf_offset = nstrace_buf_offset + nspr_getv##ver##recordsize(fp);\
807 nstrace->nstrace_buflen = nstrace_buflen;\
808 return TRUE;\
809 case NSPR_UNUSEDSPACE_V10:\
810 nstrace_buf_offset = nstrace_buflen;\
811 break;\
812 default:\
813 nstrace_buf_offset += nspr_getv##ver##recordsize(fp);\
816 nstrace_buf_offset = 0;\
817 nstrace->xxx_offset += nstrace_buflen;\
818 nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));\
819 }while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && bytes_read == nstrace_buflen); \
820 return FALSE;\
823 nstrace_set_start_time_ver(10)
824 nstrace_set_start_time_ver(20)
826 #undef nspr_getv10recordtype
827 #undef nspr_getv20recordtype
828 #undef nspr_getv10recordsize
831 ** Set the start time of the trace file. We look for the first ABSTIME record. We use that
832 ** to set the start time. Apart from that we also make sure that we remember the position of
833 ** the next record after the ABSTIME record. Inorder to report correct time values, all trace
834 ** records before the ABSTIME record are ignored.
836 static gboolean nstrace_set_start_time(wtap *wth)
838 if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
839 return nstrace_set_start_time_v10(wth);
840 else if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
841 return nstrace_set_start_time_v20(wth);
843 return FALSE;
846 #define __TNO(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
847 (phdr)->pseudo_header.nstr.hdrname##_offset = enumprefix##_##hdrname##_offset;
849 #define __TNL(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
850 (phdr)->pseudo_header.nstr.hdrname##_len = enumprefix##_##hdrname##_len;
852 #define __TNV1O(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
853 __TNO(phdr,enumprefix,structprefix,structname,hdrname,structfieldname)
855 #define __TNV1L(phdr,enumprefix,structprefix,structname,hdrname,structfieldname) \
856 __TNL(phdr,enumprefix,structprefix,structname,hdrname,structfieldname)
861 ** Netscaler trace format read routines.
863 static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
865 nstrace_t *nstrace = (nstrace_t *)wth->priv;
866 guint64 nsg_creltime = nstrace->nsg_creltime;
867 gchar *nstrace_buf = nstrace->pnstrace_buf;
868 gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;
869 gint32 nstrace_buflen = nstrace->nstrace_buflen;
870 nspr_pktracefull_v10_t *fp;
871 nspr_pktracepart_v10_t *pp;
872 int bytes_read;
874 *err = 0;
875 *err_info = NULL;
878 while ((nstrace_buf_offset < nstrace_buflen) &&
879 ((nstrace_buflen - nstrace_buf_offset) >= ((gint32)sizeof(fp->nsprRecordType))))
882 #define GENERATE_CASE_FULL(phdr,type,acttype) \
883 case NSPR_PDPKTRACEFULLTX_V##type:\
884 case NSPR_PDPKTRACEFULLTXB_V##type:\
885 case NSPR_PDPKTRACEFULLRX_V##type:\
886 fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];\
888 * XXX - we can't do this in the seek-read routine,\
889 * as the time stamps in the records are relative to\
890 * the previous packet.\
892 (phdr)->presence_flags = WTAP_HAS_TS;\
893 nsg_creltime += ns_hrtime2nsec(pletohl(&fp->fp_RelTimeHr));\
894 (phdr)->ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);\
895 (phdr)->ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
896 TRACE_FULL_V##type##_REC_LEN_OFF(phdr,v##type##_full,fp,pktracefull_v##type);\
897 buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
898 memcpy(buffer_start_ptr(wth->frame_buffer), fp, (phdr)->caplen);\
899 *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
900 nstrace->nstrace_buf_offset = nstrace_buf_offset + (phdr)->len;\
901 nstrace->nstrace_buflen = nstrace_buflen;\
902 nstrace->nsg_creltime = nsg_creltime;\
903 return TRUE;
905 #define GENERATE_CASE_PART(phdr,type,acttype) \
906 case NSPR_PDPKTRACEPARTTX_V##type:\
907 case NSPR_PDPKTRACEPARTTXB_V##type:\
908 case NSPR_PDPKTRACEPARTRX_V##type:\
909 pp = (nspr_pktracepart_v10_t *) &nstrace_buf[nstrace_buf_offset];\
911 * XXX - we can't do this in the seek-read routine,\
912 * as the time stamps in the records are relative to\
913 * the previous packet.\
915 (phdr)->presence_flags = WTAP_HAS_TS;\
916 nsg_creltime += ns_hrtime2nsec(pletohl(&pp->pp_RelTimeHr));\
917 (phdr)->ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);\
918 (phdr)->ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
919 TRACE_PART_V##type##_REC_LEN_OFF(phdr,v##type##_part,pp,pktracepart_v##type);\
920 buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
921 memcpy(buffer_start_ptr(wth->frame_buffer), pp, (phdr)->caplen);\
922 *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
923 nstrace->nstrace_buf_offset = nstrace_buf_offset + (phdr)->caplen;\
924 nstrace->nsg_creltime = nsg_creltime;\
925 nstrace->nstrace_buflen = nstrace_buflen;\
926 return TRUE;\
928 switch (pletohs(&(( nspr_header_v10_t*)&nstrace_buf[nstrace_buf_offset])->ph_RecordType))
930 GENERATE_CASE_FULL(&wth->phdr,10,100)
931 GENERATE_CASE_PART(&wth->phdr,10,100)
933 #undef GENERATE_CASE_FULL
934 #undef GENERATE_CASE_PART
936 case NSPR_ABSTIME_V10:
938 fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];
939 ns_setabstime(nstrace, pletohl(((nspr_abstime_v10_t *) fp)->abs_Time), pletohl(&((nspr_abstime_v10_t *) fp)->abs_RelTime));
940 nstrace_buf_offset += pletohs(&fp->nsprRecordSize);
941 break;
943 case NSPR_RELTIME_V10:
945 fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];
946 ns_setrelativetime(nstrace, pletohl(((nspr_abstime_v10_t *) fp)->abs_RelTime));
947 nstrace_buf_offset += pletohs(&fp->nsprRecordSize);
948 break;
950 case NSPR_UNUSEDSPACE_V10:
952 nstrace_buf_offset = nstrace_buflen;
953 break;
955 default:
957 fp = (nspr_pktracefull_v10_t *) &nstrace_buf[nstrace_buf_offset];
958 nstrace_buf_offset += pletohs(&fp->nsprRecordSize);
959 break;
963 nstrace_buf_offset = 0;
964 nstrace->xxx_offset += nstrace_buflen;
965 nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));
966 }while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && (bytes_read == nstrace_buflen));
968 return FALSE;
971 #define TIMEDEFV20(fp,type) \
972 do {\
973 wth->phdr.presence_flags |= WTAP_HAS_TS;\
974 nsg_creltime += ns_hrtime2nsec(pletohl(fp->type##_RelTimeHr));\
975 wth->phdr.ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);\
976 wth->phdr.ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
977 }while(0)
979 #define TIMEDEFV23(fp,type) \
980 do {\
981 wth->phdr.presence_flags |= WTAP_HAS_TS;\
982 /* access _AbsTimeHr as a 64bit value */\
983 nsg_creltime = pletohll(fp->type##_AbsTimeHr);\
984 wth->phdr.ts.secs = (guint32) (nsg_creltime / 1000000000);\
985 wth->phdr.ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
986 }while(0)
988 #define TIMEDEFV21(fp,type) TIMEDEFV20(fp,type)
989 #define TIMEDEFV22(fp,type) TIMEDEFV20(fp,type)
990 #define TIMEDEFV24(fp,type) TIMEDEFV23(fp,type)
991 #define TIMEDEFV25(fp,type) TIMEDEFV24(fp,type)
992 #define TIMEDEFV26(fp,type) TIMEDEFV24(fp,type)
993 #define PPSIZEDEFV20(phdr,pp,ver) \
994 do {\
995 (phdr)->presence_flags |= WTAP_HAS_CAP_LEN;\
996 (phdr)->len = pletohs(&pp->pp_PktSizeOrg) + nspr_pktracepart_v##ver##_s;\
997 (phdr)->caplen = nspr_getv20recordsize((nspr_hd_v20_t *)pp);\
998 }while(0)
1000 #define PPSIZEDEFV21(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1001 #define PPSIZEDEFV22(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1002 #define PPSIZEDEFV23(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1003 #define PPSIZEDEFV24(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1004 #define PPSIZEDEFV25(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1005 #define PPSIZEDEFV26(phdr,pp,ver) PPSIZEDEFV20(phdr,pp,ver)
1007 #define FPSIZEDEFV20(phdr,fp,ver)\
1008 do {\
1009 (phdr)->len = nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
1010 (phdr)->caplen = (phdr)->len;\
1011 }while(0)
1013 #define FPSIZEDEFV21(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1014 #define FPSIZEDEFV22(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1015 #define FPSIZEDEFV23(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1016 #define FPSIZEDEFV24(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1017 #define FPSIZEDEFV25(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1018 #define FPSIZEDEFV26(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
1020 #define PACKET_DESCRIBE(phdr,FPTIMEDEF,SIZEDEF,ver,enumprefix,type,structname,TYPE)\
1021 do {\
1022 nspr_##structname##_t *fp= (nspr_##structname##_t*)&nstrace_buf[nstrace_buf_offset];\
1023 TIMEDEFV##ver(fp,type);\
1024 SIZEDEF##ver((phdr),fp,ver);\
1025 TRACE_V##ver##_REC_LEN_OFF((phdr),enumprefix,type,structname);\
1026 (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##TYPE;\
1027 buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
1028 memcpy(buffer_start_ptr(wth->frame_buffer), fp, (phdr)->caplen);\
1029 *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
1030 nstrace->nstrace_buf_offset = nstrace_buf_offset + nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
1031 nstrace->nstrace_buflen = nstrace_buflen;\
1032 nstrace->nsg_creltime = nsg_creltime;\
1033 return TRUE;\
1034 }while(0)
1036 static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
1038 nstrace_t *nstrace = (nstrace_t *)wth->priv;
1039 guint64 nsg_creltime = nstrace->nsg_creltime;
1040 gchar *nstrace_buf = nstrace->pnstrace_buf;
1041 gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;
1042 gint32 nstrace_buflen = nstrace->nstrace_buflen;
1043 int bytes_read;
1045 *err = 0;
1046 *err_info = NULL;
1049 while ((nstrace_buf_offset < nstrace_buflen) &&
1050 ((nstrace_buflen - nstrace_buf_offset) >= ((gint32)sizeof((( nspr_hd_v20_t*)&nstrace_buf[nstrace_buf_offset])->phd_RecordType))))
1052 switch ((( nspr_hd_v20_t*)&nstrace_buf[nstrace_buf_offset])->phd_RecordType)
1055 #define GENERATE_CASE_FULL(phdr,type,acttype) \
1056 case NSPR_PDPKTRACEFULLTX_V##type:\
1057 case NSPR_PDPKTRACEFULLTXB_V##type:\
1058 case NSPR_PDPKTRACEFULLRX_V##type:\
1059 PACKET_DESCRIBE(phdr,TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
1061 #define GENERATE_CASE_FULL_V25(phdr,type,acttype) \
1062 case NSPR_PDPKTRACEFULLTX_V##type:\
1063 case NSPR_PDPKTRACEFULLTXB_V##type:\
1064 case NSPR_PDPKTRACEFULLRX_V##type:\
1065 case NSPR_PDPKTRACEFULLNEWRX_V##type:\
1066 PACKET_DESCRIBE(phdr,TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
1068 #define GENERATE_CASE_PART(phdr,type,acttype) \
1069 case NSPR_PDPKTRACEPARTTX_V##type:\
1070 case NSPR_PDPKTRACEPARTTXB_V##type:\
1071 case NSPR_PDPKTRACEPARTRX_V##type:\
1072 PACKET_DESCRIBE(phdr,TIMEDEF,PPSIZEDEFV,type,v##type##_part,pp,pktracepart_v##type,acttype);
1074 #define GENERATE_CASE_PART_V25(phdr,type,acttype) \
1075 case NSPR_PDPKTRACEPARTTX_V##type:\
1076 case NSPR_PDPKTRACEPARTTXB_V##type:\
1077 case NSPR_PDPKTRACEPARTRX_V##type:\
1078 case NSPR_PDPKTRACEPARTNEWRX_V##type:\
1079 PACKET_DESCRIBE(phdr,TIMEDEF,PPSIZEDEFV,type,v##type##_part,pp,pktracepart_v##type,acttype);
1081 GENERATE_CASE_FULL(&wth->phdr,20,200);
1082 GENERATE_CASE_PART(&wth->phdr,20,200);
1083 GENERATE_CASE_FULL(&wth->phdr,21,201);
1084 GENERATE_CASE_PART(&wth->phdr,21,201);
1085 GENERATE_CASE_FULL(&wth->phdr,22,202);
1086 GENERATE_CASE_PART(&wth->phdr,22,202);
1087 GENERATE_CASE_FULL(&wth->phdr,23,203);
1088 GENERATE_CASE_PART(&wth->phdr,23,203);
1089 GENERATE_CASE_FULL_V25(&wth->phdr,24,204);
1090 GENERATE_CASE_PART_V25(&wth->phdr,24,204);
1091 GENERATE_CASE_FULL_V25(&wth->phdr,25,205);
1092 GENERATE_CASE_PART_V25(&wth->phdr,25,205);
1093 GENERATE_CASE_FULL_V25(&wth->phdr,26,206);
1094 GENERATE_CASE_PART_V25(&wth->phdr,26,206);
1096 #undef GENERATE_CASE_FULL
1097 #undef GENERATE_CASE_FULL_V25
1098 #undef GENERATE_CASE_PART
1099 #undef GENERATE_CASE_PART_V25
1101 case NSPR_ABSTIME_V20:
1103 nspr_pktracefull_v20_t *fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1104 nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1105 ns_setabstime(nstrace, pletohl(&((nspr_abstime_v20_t *) fp20)->abs_Time), pletohs(&((nspr_abstime_v20_t *) fp20)->abs_RelTime));
1106 break;
1109 case NSPR_RELTIME_V20:
1111 nspr_pktracefull_v20_t *fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1112 ns_setrelativetime(nstrace, pletohs(&((nspr_abstime_v20_t *) fp20)->abs_RelTime));
1113 nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1114 break;
1117 case NSPR_UNUSEDSPACE_V20:
1119 if (nstrace_buf_offset >= NSPR_PAGESIZE/2)
1120 nstrace_buf_offset = nstrace_buflen;
1121 else
1122 nstrace_buf_offset = NSPR_PAGESIZE/2;
1123 break;
1126 default:
1128 nspr_pktracefull_v20_t *fp20 = (nspr_pktracefull_v20_t *) &nstrace_buf[nstrace_buf_offset];
1129 nstrace_buf_offset += nspr_getv20recordsize((nspr_hd_v20_t *)fp20);
1130 break;
1135 nstrace_buf_offset = 0;
1136 nstrace->xxx_offset += nstrace_buflen;
1137 nstrace_buflen = GET_READ_PAGE_SIZE((nstrace->file_size - nstrace->xxx_offset));
1138 }while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && (bytes_read == nstrace_buflen));
1140 return FALSE;
1143 #undef PACKET_DESCRIBE
1145 static gboolean nstrace_seek_read_v10(wtap *wth, gint64 seek_off,
1146 struct wtap_pkthdr *phdr, Buffer *buf, int length,
1147 int *err, gchar **err_info)
1149 guint8 *pd;
1150 int bytes_read;
1151 nspr_pktracefull_v10_t *fp;
1152 nspr_pktracepart_v10_t *pp;
1154 *err = 0;
1156 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
1157 return FALSE;
1160 ** Read the packet data.
1162 buffer_assure_space(buf, length);
1163 pd = buffer_start_ptr(buf);
1164 bytes_read = file_read(pd, length, wth->random_fh);
1165 if (bytes_read != length) {
1166 *err = file_error(wth->random_fh, err_info);
1167 if (*err == 0)
1168 *err = WTAP_ERR_SHORT_READ;
1169 return FALSE;
1172 #define GENERATE_CASE_FULL(phdr,type,acttype) \
1173 case NSPR_PDPKTRACEFULLTX_V##type:\
1174 case NSPR_PDPKTRACEFULLTXB_V##type:\
1175 case NSPR_PDPKTRACEFULLRX_V##type:\
1176 fp = (nspr_pktracefull_v10_t *) pd;\
1177 TRACE_FULL_V##type##_REC_LEN_OFF(phdr,v##type##_full,fp,pktracefull_v##type);\
1178 (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##acttype;\
1179 break;
1181 #define GENERATE_CASE_PART(phdr,type,acttype) \
1182 case NSPR_PDPKTRACEPARTTX_V##type:\
1183 case NSPR_PDPKTRACEPARTTXB_V##type:\
1184 case NSPR_PDPKTRACEPARTRX_V##type:\
1185 pp = (nspr_pktracepart_v10_t *) pd;\
1186 TRACE_PART_V##type##_REC_LEN_OFF(phdr,v##type##_part,pp,pktracepart_v##type);\
1187 (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##acttype;\
1188 break;
1190 switch (pletohs(&(( nspr_header_v10_t*)pd)->ph_RecordType))
1192 GENERATE_CASE_FULL(phdr,10,100)
1193 GENERATE_CASE_PART(phdr,10,100)
1196 #undef GENERATE_CASE_FULL
1197 #undef GENERATE_CASE_PART
1199 return TRUE;
1202 #define PACKET_DESCRIBE(phdr,FPTIMEDEF,SIZEDEF,ver,enumprefix,type,structname,TYPE)\
1203 do {\
1204 nspr_##structname##_t *fp= (nspr_##structname##_t*)pd;\
1205 SIZEDEF##ver((phdr),fp,ver);\
1206 TRACE_V##ver##_REC_LEN_OFF((phdr),enumprefix,type,structname);\
1207 (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##TYPE;\
1208 return TRUE;\
1209 }while(0)
1211 static gboolean nstrace_seek_read_v20(wtap *wth, gint64 seek_off,
1212 struct wtap_pkthdr *phdr, Buffer *buf, int length,
1213 int *err, gchar **err_info)
1215 guint8 *pd;
1216 int bytes_read;
1218 *err = 0;
1220 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
1221 return FALSE;
1224 ** Read the packet data.
1226 buffer_assure_space(buf, length);
1227 pd = buffer_start_ptr(buf);
1228 bytes_read = file_read(pd, length, wth->random_fh);
1229 if (bytes_read != length) {
1230 *err = file_error(wth->random_fh, err_info);
1231 if (*err == 0)
1232 *err = WTAP_ERR_SHORT_READ;
1233 return FALSE;
1236 #define GENERATE_CASE_FULL(phdr,type,acttype) \
1237 case NSPR_PDPKTRACEFULLTX_V##type:\
1238 case NSPR_PDPKTRACEFULLTXB_V##type:\
1239 case NSPR_PDPKTRACEFULLRX_V##type:\
1240 PACKET_DESCRIBE(phdr,TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
1242 #define GENERATE_CASE_FULL_V25(phdr,type,acttype) \
1243 case NSPR_PDPKTRACEFULLTX_V##type:\
1244 case NSPR_PDPKTRACEFULLTXB_V##type:\
1245 case NSPR_PDPKTRACEFULLRX_V##type:\
1246 case NSPR_PDPKTRACEFULLNEWRX_V##type:\
1247 PACKET_DESCRIBE(phdr,TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
1249 #define GENERATE_CASE_PART(phdr,type,acttype) \
1250 case NSPR_PDPKTRACEPARTTX_V##type:\
1251 case NSPR_PDPKTRACEPARTTXB_V##type:\
1252 case NSPR_PDPKTRACEPARTRX_V##type:\
1253 PACKET_DESCRIBE(phdr,TIMEDEF,PPSIZEDEFV,type,v##type##_part,pp,pktracepart_v##type,acttype);
1255 #define GENERATE_CASE_PART_V25(phdr,type,acttype) \
1256 case NSPR_PDPKTRACEPARTTX_V##type:\
1257 case NSPR_PDPKTRACEPARTTXB_V##type:\
1258 case NSPR_PDPKTRACEPARTRX_V##type:\
1259 case NSPR_PDPKTRACEPARTNEWRX_V##type:\
1260 PACKET_DESCRIBE(phdr,TIMEDEF,PPSIZEDEFV,type,v##type##_part,pp,pktracepart_v##type,acttype);
1262 switch ((( nspr_hd_v20_t*)pd)->phd_RecordType)
1264 GENERATE_CASE_FULL(phdr,20,200)
1265 GENERATE_CASE_PART(phdr,20,200)
1266 GENERATE_CASE_FULL(phdr,21,201)
1267 GENERATE_CASE_PART(phdr,21,201)
1268 GENERATE_CASE_FULL(phdr,22,202)
1269 GENERATE_CASE_PART(phdr,22,202)
1270 GENERATE_CASE_FULL(phdr,23,203)
1271 GENERATE_CASE_PART(phdr,23,203)
1272 GENERATE_CASE_FULL_V25(phdr,24,204)
1273 GENERATE_CASE_PART_V25(phdr,24,204)
1274 GENERATE_CASE_FULL_V25(phdr,25,205)
1275 GENERATE_CASE_PART_V25(phdr,25,205)
1276 GENERATE_CASE_FULL_V25(phdr,26,206)
1277 GENERATE_CASE_PART_V25(phdr,26,206)
1280 #undef GENERATE_CASE_FULL
1281 #undef GENERATE_CASE_FULL_V25
1282 #undef GENERATE_CASE_PART
1283 #undef GENERATE_CASE_PART_V25
1285 return TRUE;
1289 ** Netscaler trace format close routines.
1291 static void nstrace_close(wtap *wth)
1293 nstrace_t *nstrace = (nstrace_t *)wth->priv;
1295 g_free(nstrace->pnstrace_buf);
1299 typedef struct {
1300 guint16 page_offset;
1301 guint16 page_len;
1302 guint32 absrec_time;
1303 } nstrace_dump_t;
1305 /* Returns 0 if we could write the specified encapsulation type,
1306 ** an error indication otherwise. */
1307 int nstrace_10_dump_can_write_encap(int encap)
1309 if (encap == WTAP_ENCAP_NSTRACE_1_0)
1310 return 0;
1312 return WTAP_ERR_UNSUPPORTED_ENCAP;
1316 /* Returns 0 if we could write the specified encapsulation type,
1317 ** an error indication otherwise. */
1318 int nstrace_20_dump_can_write_encap(int encap)
1320 if (encap == WTAP_ENCAP_NSTRACE_2_0)
1321 return 0;
1323 return WTAP_ERR_UNSUPPORTED_ENCAP;
1327 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
1328 ** failure */
1329 gboolean nstrace_dump_open(wtap_dumper *wdh, int *err _U_)
1331 nstrace_dump_t *nstrace;
1333 wdh->subtype_write = nstrace_dump;
1335 nstrace = (nstrace_dump_t *)g_malloc(sizeof(nstrace_dump_t));
1336 wdh->priv = (void *)nstrace;
1337 nstrace->page_offset = 0;
1338 nstrace->page_len = NSPR_PAGESIZE;
1339 nstrace->absrec_time = 0;
1341 return TRUE;
1345 static gboolean nstrace_add_signature(wtap_dumper *wdh, int *err)
1347 nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
1349 if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1351 guint16 val16b;
1352 nspr_signature_v10_t sig10;
1354 /* populate the record */
1355 val16b = htoles(NSPR_SIGNATURE_V10);
1356 memcpy(sig10.phd.ph_RecordType, &val16b, sizeof sig10.phd.ph_RecordType);
1357 val16b = htoles(nspr_signature_v10_s);
1358 memcpy(sig10.phd.ph_RecordSize, &val16b, sizeof sig10.phd.ph_RecordSize);
1359 memset(sig10.sig_Signature, 0, NSPR_SIGSIZE_V10);
1360 g_strlcpy(sig10.sig_Signature, NSPR_SIGSTR_V10, NSPR_SIGSIZE_V10);
1362 /* Write the record into the file */
1363 if (!wtap_dump_file_write(wdh, &sig10, nspr_signature_v10_s,
1364 err))
1365 return FALSE;
1367 /* Move forward the page offset */
1368 nstrace->page_offset += (guint16) nspr_signature_v10_s;
1370 } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
1372 nspr_signature_v20_t sig20;
1374 sig20.sig_RecordType = NSPR_SIGNATURE_V20;
1375 sig20.sig_RecordSize = nspr_signature_v20_s;
1376 memcpy(sig20.sig_Signature, NSPR_SIGSTR_V20, sizeof(NSPR_SIGSTR_V20));
1378 /* Write the record into the file */
1379 if (!wtap_dump_file_write(wdh, &sig20, sig20.sig_RecordSize,
1380 err))
1381 return FALSE;
1383 /* Move forward the page offset */
1384 nstrace->page_offset += (guint16) sig20.sig_RecordSize;
1386 } else
1388 g_assert_not_reached();
1389 return FALSE;
1392 return TRUE;
1396 static gboolean
1397 nstrace_add_abstime(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1398 const guint8 *pd, int *err)
1400 nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
1401 guint64 nsg_creltime;
1403 if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1405 guint16 val16;
1406 guint32 reltime;
1407 guint64 abstime;
1408 nspr_abstime_v10_t abs10;
1410 /* populate the record */
1411 val16 = htoles(NSPR_ABSTIME_V10);
1412 memcpy(abs10.phd.ph_RecordType, &val16, sizeof abs10.phd.ph_RecordType);
1413 val16 = htoles(nspr_abstime_v10_s);
1414 memcpy(abs10.phd.ph_RecordSize, &val16, sizeof abs10.phd.ph_RecordSize);
1416 memcpy(&reltime, ((const nspr_pktracefull_v10_t *)pd)->fp_RelTimeHr, sizeof reltime);
1417 nsg_creltime = ns_hrtime2nsec(reltime);
1419 memset(abs10.abs_RelTime, 0, sizeof abs10.abs_RelTime);
1420 abstime = htolel((guint32)phdr->ts.secs - (guint32)(nsg_creltime/1000000000));
1421 memcpy(abs10.abs_Time, &abstime, sizeof abs10.abs_Time);
1423 /* Write the record into the file */
1424 if (!wtap_dump_file_write(wdh, &abs10, nspr_abstime_v10_s, err))
1425 return FALSE;
1427 /* Move forward the page offset */
1428 nstrace->page_offset += nspr_abstime_v10_s;
1430 } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
1432 guint32 reltime;
1433 guint64 abstime;
1434 nspr_abstime_v20_t abs20;
1436 abs20.abs_RecordType = NSPR_ABSTIME_V20;
1437 abs20.abs_RecordSize = nspr_abstime_v20_s;
1439 memcpy(&reltime, ((const nspr_pktracefull_v20_t *)pd)->fp_RelTimeHr, sizeof reltime);
1440 nsg_creltime = ns_hrtime2nsec(reltime);
1442 memset(abs20.abs_RelTime, 0, sizeof abs20.abs_RelTime);
1443 abstime = htolel((guint32)phdr->ts.secs - (guint32)(nsg_creltime/1000000000));
1444 memcpy(abs20.abs_RelTime, &abstime, sizeof abs20.abs_RelTime);
1446 /* Write the record into the file */
1447 if (!wtap_dump_file_write(wdh, &abs20, nspr_abstime_v20_s, err))
1448 return FALSE;
1450 /* Move forward the page offset */
1451 nstrace->page_offset += nspr_abstime_v20_s;
1453 } else
1455 g_assert_not_reached();
1456 return FALSE;
1459 return TRUE;
1463 /* Write a record for a packet to a dump file.
1464 Returns TRUE on success, FALSE on failure. */
1465 static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1466 const guint8 *pd, int *err)
1468 nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
1470 if (nstrace->page_offset == 0)
1472 /* Add the signature record and abs time record */
1473 if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1475 if (!nstrace_add_signature(wdh, err) ||
1476 !nstrace_add_abstime(wdh, phdr, pd, err))
1477 return FALSE;
1478 } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
1480 if (!nstrace_add_signature(wdh, err) ||
1481 !nstrace_add_abstime(wdh, phdr, pd, err))
1482 return FALSE;
1483 } else
1485 g_assert_not_reached();
1486 return FALSE;
1490 switch (phdr->pseudo_header.nstr.rec_type)
1492 case NSPR_HEADER_VERSION100:
1494 if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1496 if (nstrace->page_offset + phdr->caplen >= nstrace->page_len)
1498 /* Start on the next page */
1499 if (wtap_dump_file_seek(wdh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR, err) == -1)
1500 return FALSE;
1502 nstrace->page_offset = 0;
1504 /* Possibly add signature and abstime records and increment offset */
1505 if (!nstrace_add_signature(wdh, err))
1506 return FALSE;
1509 /* Write the actual record as is */
1510 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
1511 return FALSE;
1513 nstrace->page_offset += (guint16) phdr->caplen;
1514 } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
1516 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1517 return FALSE;
1520 break;
1522 case NSPR_HEADER_VERSION200:
1523 case NSPR_HEADER_VERSION201:
1524 case NSPR_HEADER_VERSION202:
1525 case NSPR_HEADER_VERSION203:
1526 case NSPR_HEADER_VERSION204:
1527 case NSPR_HEADER_VERSION205:
1528 case NSPR_HEADER_VERSION206:
1529 if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
1531 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1532 return FALSE;
1533 } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
1535 if (nstrace->page_offset + phdr->caplen >= nstrace->page_len)
1537 /* Start on the next page */
1538 if (wtap_dump_file_seek(wdh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR, err) == -1)
1539 return FALSE;
1541 nstrace->page_offset = 0;
1543 /* Possibly add signature and abstime records and increment offset */
1544 if (!nstrace_add_signature(wdh, err))
1545 return FALSE;
1548 /* Write the actual record as is */
1549 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
1550 return FALSE;
1552 nstrace->page_offset += (guint16) phdr->caplen;
1555 break;
1557 default:
1558 g_assert_not_reached();
1559 return FALSE;
1562 return TRUE;