From Mark C. Brown: fix support for nettl NETTL_SUBSYS_NS_LS_ICMP and
[obnox/wireshark/wip.git] / wiretap / netxray.c
1 /* netxray.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <string.h>
30 #include "wtap-int.h"
31 #include "file_wrappers.h"
32 #include "netxray.h"
33 #include "buffer.h"
34 #include "atm.h"
35
36 /* Capture file header, *including* magic number, is padded to 128 bytes. */
37 #define CAPTUREFILE_HEADER_SIZE 128
38
39 /* Magic number in NetXRay 1.x files. */
40 static const char old_netxray_magic[] = {
41         'V', 'L', '\0', '\0'
42 };
43
44 /* Magic number in NetXRay 2.0 and later, and Windows Sniffer, files. */
45 static const char netxray_magic[] = {   /* magic header */
46         'X', 'C', 'P', '\0'
47 };
48
49 /* NetXRay file header (minus magic number). */
50 struct netxray_hdr {
51         char    version[8];     /* version number */
52         guint32 start_time;     /* UNIX time when capture started */
53         guint32 nframes;        /* number of packets */
54         guint32 xxx;            /* unknown */
55         guint32 start_offset;   /* offset of first packet in capture */
56         guint32 end_offset;     /* offset after last packet in capture */
57         guint32 xxy[3];         /* unknown */
58         guint8  network;        /* datalink type */
59         guint8  xxz[3];         /* XXX - is this the upper 3 bytes of the datalink type? */
60         guint8  timeunit;       /* encodes length of a tick */
61         guint8  xxa[3];         /* XXX - is this the upper 3 bytes of the time units? */
62         guint32 timelo;         /* lower 32 bits of time stamp of capture start */
63         guint32 timehi;         /* upper 32 bits of time stamp of capture start */
64         guint32 linespeed;      /* speed of network, in bits/second */
65         guint8  xxb[64];        /* other stuff */
66 };
67
68 /*
69  * Capture type, in xxb[20].
70  */
71 #define CAPTYPE_NDIS    0       /* Capture on network interface using NDIS */
72 #define CAPTYPE_BROUTER 1       /* Bridge/router captured with pod */
73 #define CAPTYPE_GIGPOD  2       /* gigabit Ethernet captured with pod */
74 #define CAPTYPE_PPP     3       /* PPP captured with pod */
75 #define CAPTYPE_FRELAY  4       /* Frame Relay captured with pod */
76 #define CAPTYPE_BROUTER2 5      /* Bridge/router captured with pod */
77 #define CAPTYPE_HDLC    6       /* HDLC (X.25, ISDN) captured with pod */
78 #define CAPTYPE_SDLC    7       /* SDLC captured with pod */
79 #define CAPTYPE_HDLC2   8       /* HDLC captured with pod */
80 #define CAPTYPE_BROUTER3 9      /* Bridge/router captured with pod */
81 #define CAPTYPE_SMDS    10      /* SMDS DXI */
82 #define CAPTYPE_BROUTER4 11     /* Bridge/router captured with pod */
83 #define CAPTYPE_BROUTER5 12     /* Bridge/router captured with pod */
84
85 /*
86  * # of ticks that equal 1 second
87  *
88  * XXX - the third item was 1193180.0, presumably because somebody found
89  * it gave the right answer for some captures, but 3 times that, i.e.
90  * 3579540.0, appears to give the right answer for some other captures.
91  *
92  * Is there something else in the file header to indicate which of those
93  * is correct?
94  */
95 static double TpS[] = { 1e6, 1193000.0, 3579540.0 };
96 #define NUM_NETXRAY_TIMEUNITS (sizeof TpS / sizeof TpS[0])
97
98 /* Version number strings. */
99 static const char vers_1_0[] = {
100         '0', '0', '1', '.', '0', '0', '0', '\0'
101 };
102
103 static const char vers_1_1[] = {
104         '0', '0', '1', '.', '1', '0', '0', '\0'
105 };
106
107 static const char vers_2_000[] = {
108         '0', '0', '2', '.', '0', '0', '0', '\0'
109 };
110
111 static const char vers_2_001[] = {
112         '0', '0', '2', '.', '0', '0', '1', '\0'
113 };
114
115 static const char vers_2_002[] = {
116         '0', '0', '2', '.', '0', '0', '2', '\0'
117 };
118
119 /* Old NetXRay data record format - followed by frame data. */
120 struct old_netxrayrec_hdr {
121         guint32 timelo;         /* lower 32 bits of time stamp */
122         guint32 timehi;         /* upper 32 bits of time stamp */
123         guint16 len;            /* packet length */
124         guint8  xxx[6];         /* unknown */
125 };
126
127 /* NetXRay format version 1.x data record format - followed by frame data. */
128 struct netxrayrec_1_x_hdr {
129         guint32 timelo;         /* lower 32 bits of time stamp */
130         guint32 timehi;         /* upper 32 bits of time stamp */
131         guint16 orig_len;       /* packet length */
132         guint16 incl_len;       /* capture length */
133         guint8  xxx[16];        /* unknown */
134 };
135
136 /* NetXRay format version 2.x data record format - followed by frame data. */
137 struct netxrayrec_2_x_hdr {
138         guint32 timelo;         /* lower 32 bits of time stamp */
139         guint32 timehi;         /* upper 32 bits of time stamp */
140         guint16 orig_len;       /* packet length */
141         guint16 incl_len;       /* capture length */
142         guint8  xxx[28];        /* various data */
143 };
144
145 /*
146  * Union of the data record headers.
147  */
148 union netxrayrec_hdr {
149         struct old_netxrayrec_hdr old_hdr;
150         struct netxrayrec_1_x_hdr hdr_1_x;
151         struct netxrayrec_2_x_hdr hdr_2_x;
152 };
153
154 static gboolean netxray_read(wtap *wth, int *err, gchar **err_info,
155     long *data_offset);
156 static gboolean netxray_seek_read(wtap *wth, long seek_off,
157     union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
158     int *err, gchar **err_info);
159 static int netxray_read_rec_header(wtap *wth, FILE_T fh,
160     union netxrayrec_hdr *hdr, int *err);
161 static guint netxray_set_pseudo_header(wtap *wth, const guint8 *pd, int len,
162     union wtap_pseudo_header *pseudo_header, union netxrayrec_hdr *hdr);
163 static gboolean netxray_read_rec_data(FILE_T fh, guint8 *data_ptr,
164     guint32 packet_size, int *err);
165 static void netxray_close(wtap *wth);
166 static gboolean netxray_dump_1_1(wtap_dumper *wdh,
167     const struct wtap_pkthdr *phdr,
168     const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
169 static gboolean netxray_dump_close_1_1(wtap_dumper *wdh, int *err);
170 static gboolean netxray_dump_2_0(wtap_dumper *wdh,
171     const struct wtap_pkthdr *phdr,
172     const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
173 static gboolean netxray_dump_close_2_0(wtap_dumper *wdh, int *err);
174
175 int netxray_open(wtap *wth, int *err, gchar **err_info)
176 {
177         int bytes_read;
178         char magic[sizeof netxray_magic];
179         gboolean is_old;
180         struct netxray_hdr hdr;
181         guint network_type;
182         double timeunit;
183         int version_major, version_minor;
184         int file_type;
185         double start_timestamp;
186         static const int netxray_encap[] = {
187                 WTAP_ENCAP_UNKNOWN,
188                 WTAP_ENCAP_ETHERNET,
189                 WTAP_ENCAP_TOKEN_RING,
190                 WTAP_ENCAP_FDDI_BITSWAPPED,
191                 /*
192                  * XXX - PPP captures may look like Ethernet, perhaps
193                  * because they're using NDIS to capture on the
194                  * same machine and it provides simulated-Ethernet
195                  * packets, but at least one ISDN capture uses the
196                  * same network type value but isn't shaped like
197                  * Ethernet.
198                  */
199                 WTAP_ENCAP_ETHERNET,    /* WAN(PPP), but shaped like Ethernet */
200                 WTAP_ENCAP_UNKNOWN,     /* LocalTalk */
201                 WTAP_ENCAP_UNKNOWN,     /* "DIX" - should not occur */
202                 WTAP_ENCAP_UNKNOWN,     /* ARCNET raw */
203                 WTAP_ENCAP_UNKNOWN,     /* ARCNET 878.2 */
204                 WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,        /* ATM */
205                 WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
206                                         /* Wireless WAN with radio information */
207                 WTAP_ENCAP_UNKNOWN      /* IrDA */
208         };
209         #define NUM_NETXRAY_ENCAPS (sizeof netxray_encap / sizeof netxray_encap[0])
210         int file_encap;
211         guint isdn_type = 0;
212
213         /* Read in the string that should be at the start of a NetXRay
214          * file */
215         errno = WTAP_ERR_CANT_READ;
216         bytes_read = file_read(magic, 1, sizeof magic, wth->fh);
217         if (bytes_read != sizeof magic) {
218                 *err = file_error(wth->fh);
219                 if (*err != 0)
220                         return -1;
221                 return 0;
222         }
223         wth->data_offset += sizeof magic;
224
225         if (memcmp(magic, netxray_magic, sizeof magic) == 0) {
226                 is_old = FALSE;
227         } else if (memcmp(magic, old_netxray_magic, sizeof magic) == 0) {
228                 is_old = TRUE;
229         } else {
230                 return 0;
231         }
232
233         /* Read the rest of the header. */
234         errno = WTAP_ERR_CANT_READ;
235         bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
236         if (bytes_read != sizeof hdr) {
237                 *err = file_error(wth->fh);
238                 if (*err != 0)
239                         return -1;
240                 return 0;
241         }
242         wth->data_offset += sizeof hdr;
243
244         if (is_old) {
245                 version_major = 0;
246                 version_minor = 0;
247                 file_type = WTAP_FILE_NETXRAY_OLD;
248         } else {
249                 /* It appears that version 1.1 files (as produced by Windows
250                  * Sniffer Pro 2.0.01) have the time stamp in microseconds,
251                  * rather than the milliseconds version 1.0 files appear to
252                  * have.
253                  *
254                  * It also appears that version 2.00x files have per-packet
255                  * headers with some extra fields. */
256                 if (memcmp(hdr.version, vers_1_0, sizeof vers_1_0) == 0) {
257                         timeunit = 1000.0;
258                         version_major = 1;
259                         version_minor = 0;
260                         file_type = WTAP_FILE_NETXRAY_1_0;
261                 } else if (memcmp(hdr.version, vers_1_1, sizeof vers_1_1) == 0) {
262                         timeunit = 1000000.0;
263                         version_major = 1;
264                         version_minor = 1;
265                         file_type = WTAP_FILE_NETXRAY_1_1;
266                 } else if (memcmp(hdr.version, vers_2_000, sizeof vers_2_000) == 0) {
267                         version_major = 2;
268                         version_minor = 0;
269                         file_type = WTAP_FILE_NETXRAY_2_00x;
270                 } else if (memcmp(hdr.version, vers_2_001, sizeof vers_2_001) == 0) {
271                         version_major = 2;
272                         version_minor = 1;
273                         file_type = WTAP_FILE_NETXRAY_2_00x;
274                 } else if (memcmp(hdr.version, vers_2_002, sizeof vers_2_002) == 0) {
275                         version_major = 2;
276                         version_minor = 2;
277                         file_type = WTAP_FILE_NETXRAY_2_00x;
278                 } else {
279                         *err = WTAP_ERR_UNSUPPORTED;
280                         *err_info = g_strdup_printf("netxray: version \"%.8s\" unsupported", hdr.version);
281                         return -1;
282                 }
283         }
284
285         switch (hdr.xxz[0]) {
286
287         case 0:
288                 /*
289                  * The byte after hdr.network is usually 0, in which case
290                  * the hdr.network byte is an NDIS network type value - 1.
291                  */
292                 network_type = hdr.network + 1;
293                 break;
294
295         case 2:
296                 /*
297                  * However, in some Ethernet captures, it's 2, and the
298                  * hdr.network byte is 1 rather than 0.  We assume
299                  * that if there's a byte after hdr.network with the value
300                  * 2, the hdr.network byte is an NDIS network type, rather
301                  * than an NDIS network type - 1.
302                  */
303                 network_type = hdr.network;
304                 break;
305
306         default:
307                 *err = WTAP_ERR_UNSUPPORTED;
308                 *err_info = g_strdup_printf("netxray: the byte after the network type has the value %u, which I don't understand",
309                     hdr.xxz[0]);
310                 return -1;
311         }
312
313         if (network_type >= NUM_NETXRAY_ENCAPS
314             || netxray_encap[network_type] == WTAP_ENCAP_UNKNOWN) {
315                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
316                 *err_info = g_strdup_printf("netxray: network type %u (%u) unknown or unsupported",
317                     network_type, hdr.xxz[0]);
318                 return -1;
319         }
320
321         /*
322          * Figure out the time stamp units and start time stamp.
323          */
324         start_timestamp = (double)pletohl(&hdr.timelo)
325             + (double)pletohl(&hdr.timehi)*4294967296.0;
326         switch (file_type) {
327
328         case WTAP_FILE_NETXRAY_OLD:
329                 timeunit = 1000.0;
330                 break;
331
332         case WTAP_FILE_NETXRAY_1_0:
333                 timeunit = 1000.0;
334                 break;
335
336         case WTAP_FILE_NETXRAY_1_1:
337                 timeunit = 1000000.0;
338                 break;
339
340         case WTAP_FILE_NETXRAY_2_00x:
341                 /*
342                  * It appears that, at least for Ethernet
343                  * captures, if hdr.xxb[20] is 2, that indicates
344                  * that it's a gigabit Ethernet capture, possibly
345                  * from a special whizzo gigabit pod, and also
346                  * indicates that the time stamps have some
347                  * higher resolution than in other captures,
348                  * possibly thanks to a high-resolution
349                  * timer on the pod.
350                  *
351                  * It also appears that the time units might differ
352                  * for gigabit pod captures between version 002.001
353                  * and 002.002.
354                  */
355                 if (network_type == 1 && hdr.xxb[20] == CAPTYPE_GIGPOD) {
356                         if (version_minor == 1) {
357                                 /*
358                                  * It appears that the time units for
359                                  * these captures are nanoseconds, unless
360                                  * hdr.timeunit is 2, in which case it's
361                                  * 1/31250000.0 of a second.
362                                  */
363                                 if (hdr.timeunit == 2)
364                                         timeunit = 31250000.0;
365                                 else
366                                         timeunit = 1e9;
367                         } else {
368                                 /*
369                                  * These just seem to be 1000 times
370                                  * the regular time stamp units, unless
371                                  * hdr.timeunit is 2, in which case it's
372                                  * 1/1125000 of a second.
373                                  *
374                                  * In addition, the start timestamp
375                                  * appears to be 0.
376                                  */
377                                 if (hdr.timeunit == 2)
378                                         timeunit = 1250000.0;
379                                 else
380                                         timeunit = TpS[hdr.timeunit]*1000.0;
381                                 start_timestamp = 0.0;
382                         }
383                 } else {
384                         if (hdr.timeunit > NUM_NETXRAY_TIMEUNITS) {
385                                 *err = WTAP_ERR_UNSUPPORTED;
386                                 *err_info = g_strdup_printf("netxray: Unknown timeunit %u",
387                                     hdr.timeunit);
388                                 return -1;
389                         }
390                         timeunit = TpS[hdr.timeunit];
391                 }
392                 break;
393
394         default:
395                 g_assert_not_reached();
396                 timeunit = 0.0;
397         }
398         start_timestamp = start_timestamp/timeunit;
399
400         if (network_type == 4) {
401                 /*
402                  * In version 0 and 1, we assume, for now, that all
403                  * WAN captures have frames that look like Ethernet
404                  * frames (as a result, presumably, of having passed
405                  * through NDISWAN).
406                  *
407                  * In version 2, it looks as if there's stuff in the "xxb"
408                  * words of the file header to specify what particular
409                  * type of WAN capture we have.
410                  */
411                 if (version_major == 2) {
412                         switch (hdr.xxb[20]) {
413
414                         case CAPTYPE_PPP:
415                                 /*
416                                  * PPP.
417                                  */
418                                 file_encap = WTAP_ENCAP_PPP_WITH_PHDR;
419                                 break;
420
421                         case CAPTYPE_FRELAY:
422                                 /*
423                                  * Frame Relay.
424                                  */
425                                 file_encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
426                                 break;
427
428                         case CAPTYPE_HDLC:
429                         case CAPTYPE_HDLC2:
430                                 /*
431                                  * Various HDLC flavors?
432                                  */
433                                 switch (hdr.xxb[28]) {
434
435                                 case 0: /* LAPB/X.25 */
436                                         file_encap = WTAP_ENCAP_LAPB;
437                                         break;
438
439                                 case 1: /* E1 PRI */
440                                 case 2: /* T1 PRI */
441                                 case 3: /* BRI */
442                                         file_encap = WTAP_ENCAP_ISDN;
443                                         isdn_type = hdr.xxb[28];
444                                         break;
445
446                                 default:
447                                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
448                                         *err_info = g_strdup_printf("netxray: WAN HDLC capture subsubtype 0x%02x unknown or unsupported",
449                                            hdr.xxb[28]);
450                                         return -1;
451                                 }
452                                 break;
453
454                         case CAPTYPE_SDLC:
455                                 /*
456                                  * SDLC.
457                                  */
458                                 file_encap = WTAP_ENCAP_SDLC;
459                                 break;
460
461                         default:
462                                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
463                                 *err_info = g_strdup_printf("netxray: WAN capture subtype 0x%02x unknown or unsupported",
464                                    hdr.xxb[20]);
465                                 return -1;
466                         }
467                 } else
468                         file_encap = WTAP_ENCAP_ETHERNET;
469         } else
470                 file_encap = netxray_encap[network_type];
471
472         /* This is a netxray file */
473         wth->file_type = file_type;
474         wth->capture.netxray = g_malloc(sizeof(netxray_t));
475         wth->subtype_read = netxray_read;
476         wth->subtype_seek_read = netxray_seek_read;
477         wth->subtype_close = netxray_close;
478         wth->file_encap = file_encap;
479         wth->snapshot_length = 0;       /* not available in header */
480         wth->capture.netxray->start_time = pletohl(&hdr.start_time);
481         wth->capture.netxray->timeunit = timeunit;
482         wth->capture.netxray->start_timestamp = start_timestamp;
483         wth->capture.netxray->version_major = version_major;
484
485         /*
486          * If frames have an extra 4 bytes of stuff at the end, is
487          * it an FCS, or just junk?
488          */
489         wth->capture.netxray->fcs_valid = FALSE;
490         switch (file_encap) {
491
492         case WTAP_ENCAP_ETHERNET:
493         case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
494         case WTAP_ENCAP_ISDN:
495                 /*
496                  * It appears that, in at least some version 2 Ethernet
497                  * captures, for frames that have 0xff in hdr_2_x.xxx[2]
498                  * and hdr_2_x.xxx[3] in the per-packet header:
499                  *
500                  *      if, in the file header, hdr.xxb[13] is 0x34 and
501                  *      hdr.xxb[14] is 0x12, the frames have an FCS at
502                  *      the end;
503                  *
504                  *      otherwise, they have 4 bytes of junk at the end.
505                  *
506                  * For now, we assume that to be true for 802.11 captures
507                  * as well; it appears to be the case for at least one
508                  * such capture.
509                  *
510                  * For ISDN captures, it appears, at least in some
511                  * captures, to be similar, although I haven't yet
512                  * checked whether it's a valid FCS.
513                  *
514                  * XXX - should we do this for all encapsulation types?
515                  *
516                  * XXX - is that actually a 2-byte little-endian 0x1234?
517                  * What does that field signify?
518                  */
519                 if (version_major == 2) {
520                         if (hdr.xxb[13] == 0x34 && hdr.xxb[14] == 0x12)
521                                 wth->capture.netxray->fcs_valid = TRUE;
522                 }
523                 break;
524         }
525
526         /*
527          * Remember the ISDN type, as we need it to interpret the
528          * channel number in ISDN captures.
529          */
530         wth->capture.netxray->isdn_type = isdn_type;
531
532         /* Remember the offset after the last packet in the capture (which
533          * isn't necessarily the last packet in the file), as it appears
534          * there's sometimes crud after it. */
535         wth->capture.netxray->wrapped = FALSE;
536         wth->capture.netxray->end_offset = pletohl(&hdr.end_offset);
537
538         /* Seek to the beginning of the data records. */
539         if (file_seek(wth->fh, pletohl(&hdr.start_offset), SEEK_SET, err) == -1) {
540                 g_free(wth->capture.netxray);
541                 return -1;
542         }
543         wth->data_offset = pletohl(&hdr.start_offset);
544
545         return 1;
546 }
547
548 /* Read the next packet */
549 static gboolean netxray_read(wtap *wth, int *err, gchar **err_info _U_,
550     long *data_offset)
551 {
552         guint32 packet_size;
553         union netxrayrec_hdr hdr;
554         int     hdr_size;
555         double  t;
556         guint8  *pd;
557         guint   padding;
558
559 reread:
560         /* Have we reached the end of the packet data? */
561         if (wth->data_offset == wth->capture.netxray->end_offset) {
562                 /* Yes. */
563                 *err = 0;       /* it's just an EOF, not an error */
564                 return FALSE;
565         }
566         /* Read record header. */
567         hdr_size = netxray_read_rec_header(wth, wth->fh, &hdr, err);
568         if (hdr_size == 0) {
569                 /*
570                  * Error or EOF.
571                  */
572                 if (*err != 0) {
573                         /*
574                          * Error of some sort; give up.
575                          */
576                         return FALSE;
577                 }
578
579                 /* We're at EOF.  Wrap? */
580                 if (!wth->capture.netxray->wrapped) {
581                         /* Yes.  Remember that we did. */
582                         wth->capture.netxray->wrapped = TRUE;
583                         if (file_seek(wth->fh, CAPTUREFILE_HEADER_SIZE,
584                             SEEK_SET, err) == -1)
585                                 return FALSE;
586                         wth->data_offset = CAPTUREFILE_HEADER_SIZE;
587                         goto reread;
588                 }
589
590                 /* We've already wrapped - don't wrap again. */
591                 return FALSE;
592         }
593
594         /*
595          * Return the offset of the record header, so we can reread it
596          * if we go back to this frame.
597          */
598         *data_offset = wth->data_offset;
599         wth->data_offset += hdr_size;
600
601         /*
602          * Read the packet data.
603          */
604         if (wth->capture.netxray->version_major == 0)
605                 packet_size = pletohs(&hdr.old_hdr.len);
606         else
607                 packet_size = pletohs(&hdr.hdr_1_x.incl_len);
608         buffer_assure_space(wth->frame_buffer, packet_size);
609         pd = buffer_start_ptr(wth->frame_buffer);
610         if (!netxray_read_rec_data(wth->fh, pd, packet_size, err))
611                 return FALSE;
612         wth->data_offset += packet_size;
613
614         /*
615          * Set the pseudo-header.
616          */
617         padding = netxray_set_pseudo_header(wth, pd, packet_size,
618             &wth->pseudo_header, &hdr);
619
620         if (wth->capture.netxray->version_major == 0) {
621                 t = (double)pletohl(&hdr.old_hdr.timelo)
622                     + (double)pletohl(&hdr.old_hdr.timehi)*4294967296.0;
623                 t /= wth->capture.netxray->timeunit;
624                 t -= wth->capture.netxray->start_timestamp;
625                 wth->phdr.ts.tv_sec = wth->capture.netxray->start_time + (long)t;
626                 wth->phdr.ts.tv_usec = (unsigned long)((t-(double)(unsigned long)(t))
627                         *1.0e6);
628                 /*
629                  * We subtract the padding from the packet size, so our caller
630                  * doesn't see it.
631                  */
632                 wth->phdr.caplen = packet_size - padding;
633                 wth->phdr.len = wth->phdr.caplen;
634         } else {
635                 t = (double)pletohl(&hdr.hdr_1_x.timelo)
636                     + (double)pletohl(&hdr.hdr_1_x.timehi)*4294967296.0;
637                 t /= wth->capture.netxray->timeunit;
638                 t -= wth->capture.netxray->start_timestamp;
639                 wth->phdr.ts.tv_sec = wth->capture.netxray->start_time + (long)t;
640                 wth->phdr.ts.tv_usec = (unsigned long)((t-(double)(unsigned long)(t))
641                         *1.0e6);
642                 /*
643                  * We subtract the padding from the packet size, so our caller
644                  * doesn't see it.
645                  */
646                 wth->phdr.caplen = packet_size - padding;
647                 wth->phdr.len = pletohs(&hdr.hdr_1_x.orig_len) - padding;
648         }
649
650         return TRUE;
651 }
652
653 static gboolean
654 netxray_seek_read(wtap *wth, long seek_off,
655     union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
656     int *err, gchar **err_info _U_)
657 {
658         union netxrayrec_hdr hdr;
659         gboolean ret;
660
661         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
662                 return FALSE;
663
664         if (!netxray_read_rec_header(wth, wth->random_fh, &hdr, err)) {
665                 if (*err == 0) {
666                         /*
667                          * EOF - we report that as a short read, as
668                          * we've read this once and know that it
669                          * should be there.
670                          */
671                         *err = WTAP_ERR_SHORT_READ;
672                 }
673                 return FALSE;
674         }
675
676         /*
677          * Read the packet data.
678          */
679         ret = netxray_read_rec_data(wth->random_fh, pd, length, err);
680         if (!ret)
681                 return FALSE;
682
683         /*
684          * Set the pseudo-header.
685          */
686         netxray_set_pseudo_header(wth, pd, length, pseudo_header, &hdr);
687         return TRUE;
688 }
689
690 static int
691 netxray_read_rec_header(wtap *wth, FILE_T fh, union netxrayrec_hdr *hdr,
692     int *err)
693 {
694         int     bytes_read;
695         int     hdr_size = 0;
696
697         /* Read record header. */
698         switch (wth->capture.netxray->version_major) {
699
700         case 0:
701                 hdr_size = sizeof (struct old_netxrayrec_hdr);
702                 break;
703
704         case 1:
705                 hdr_size = sizeof (struct netxrayrec_1_x_hdr);
706                 break;
707
708         case 2:
709                 hdr_size = sizeof (struct netxrayrec_2_x_hdr);
710                 break;
711         }
712         errno = WTAP_ERR_CANT_READ;
713         bytes_read = file_read(hdr, 1, hdr_size, fh);
714         if (bytes_read != hdr_size) {
715                 *err = file_error(wth->fh);
716                 if (*err != 0)
717                         return 0;
718                 if (bytes_read != 0) {
719                         *err = WTAP_ERR_SHORT_READ;
720                         return 0;
721                 }
722
723                 /*
724                  * We're at EOF.  "*err" is 0; we return FALSE - that
725                  * combination tells our caller we're at EOF.
726                  */
727                 return 0;
728         }
729         return hdr_size;
730 }
731
732 static guint
733 netxray_set_pseudo_header(wtap *wth, const guint8 *pd, int len,
734     union wtap_pseudo_header *pseudo_header, union netxrayrec_hdr *hdr)
735 {
736         guint padding = 0;
737
738         /*
739          * If this is Ethernet, 802.11, ISDN, X.25, or ATM, set the
740          * pseudo-header.
741          */
742         switch (wth->capture.netxray->version_major) {
743
744         case 1:
745                 switch (wth->file_encap) {
746
747                 case WTAP_ENCAP_ETHERNET:
748                         /*
749                          * XXX - if hdr->hdr_1_x.xxx[15] is 1
750                          * the frame appears not to have any extra
751                          * stuff at the end, but if it's 0,
752                          * there appears to be 4 bytes of stuff
753                          * at the end, but it's not an FCS.
754                          *
755                          * Or is that just the low-order bit?
756                          *
757                          * For now, we just say "no FCS".
758                          */
759                         pseudo_header->eth.fcs_len = 0;
760                         break;
761                 }
762                 break;
763
764         case 2:
765                 switch (wth->file_encap) {
766
767                 case WTAP_ENCAP_ETHERNET:
768                         /*
769                          * It appears, at least with version 2 captures,
770                          * that we have 4 bytes of stuff (which might be
771                          * a valid FCS or might be junk) at the end of
772                          * the packet if hdr->hdr_2_x.xxx[2] and
773                          * hdr->hdr_2_x.xxx[3] are 0xff, and we don't if
774                          * they don't.
775                          *
776                          * It also appears that if the low-order bit of
777                          * hdr->hdr_2_x.xxx[8] is set, the packet has a
778                          * bad FCS.
779                          */
780                         if (hdr->hdr_2_x.xxx[2] == 0xff &&
781                             hdr->hdr_2_x.xxx[3] == 0xff) {
782                                 /*
783                                  * We have 4 bytes of stuff at the
784                                  * end of the frame - FCS, or junk?
785                                  */
786                                 if (wth->capture.netxray->fcs_valid) {
787                                         /*
788                                          * FCS.
789                                          */
790                                         pseudo_header->eth.fcs_len = 4;
791                                 } else {
792                                         /*
793                                          * Junk.
794                                          */
795                                         padding = 4;
796                                 }
797                         } else
798                                 pseudo_header->eth.fcs_len = 0;
799                         break;
800
801                 case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
802                         /*
803                          * It appears, in one 802.11 capture, that
804                          * we have 4 bytes of junk at the ends of
805                          * frames in which hdr->hdr_2_x.xxx[2] and
806                          * hdr->hdr_2_x.xxx[3] are 0xff; we assume
807                          * for now that it works like Ethernet.
808                          */
809                         if (hdr->hdr_2_x.xxx[2] == 0xff &&
810                             hdr->hdr_2_x.xxx[3] == 0xff) {
811                                 /*
812                                  * We have 4 bytes of stuff at the
813                                  * end of the frame - FCS, or junk?
814                                  */
815                                 if (wth->capture.netxray->fcs_valid) {
816                                         /*
817                                          * FCS.
818                                          */
819                                         pseudo_header->ieee_802_11.fcs_len = 4;
820                                 } else {
821                                         /*
822                                          * Junk.
823                                          */
824                                         padding = 4;
825                                 }
826                         } else
827                                 pseudo_header->ieee_802_11.fcs_len = 0;
828
829                         pseudo_header->ieee_802_11.channel =
830                             hdr->hdr_2_x.xxx[12];
831                         pseudo_header->ieee_802_11.data_rate =
832                             hdr->hdr_2_x.xxx[13];
833                         pseudo_header->ieee_802_11.signal_level =
834                             hdr->hdr_2_x.xxx[14];
835                         break;
836
837                 case WTAP_ENCAP_ISDN:
838                         /*
839                          * ISDN.
840                          *
841                          * The bottommost bit of byte 12 of "hdr.hdr_2_x.xxx"
842                          * is the direction flag.
843                          *
844                          * The bottom 5 bits of byte 13 of "hdr.hdr_2_x.xxx"
845                          * are the channel number, but some mapping is
846                          * required for PRI.  (Is it really just the time
847                          * slot?)
848                          */
849                         pseudo_header->isdn.uton =
850                             (hdr->hdr_2_x.xxx[12] & 0x01);
851                         pseudo_header->isdn.channel =
852                             hdr->hdr_2_x.xxx[13] & 0x1F;
853                         switch (wth->capture.netxray->isdn_type) {
854
855                         case 1:
856                                 /*
857                                  * E1 PRI.  Channel numbers 0 and 16
858                                  * are the D channel; channel numbers 1
859                                  * through 15 are B1 through B15; channel
860                                  * numbers 17 through 31 are B16 through
861                                  * B31.
862                                  */
863                                 if (pseudo_header->isdn.channel == 16)
864                                         pseudo_header->isdn.channel = 0;
865                                 else if (pseudo_header->isdn.channel > 16)
866                                         pseudo_header->isdn.channel -= 1;
867                                 break;
868
869                         case 2:
870                                 /*
871                                  * T1 PRI.  Channel numbers 0 and 24
872                                  * are the D channel; channel numbers 1
873                                  * through 23 are B1 through B23.
874                                  */
875                                 if (pseudo_header->isdn.channel == 24)
876                                         pseudo_header->isdn.channel = 0;
877                                 else if (pseudo_header->isdn.channel > 24)
878                                         pseudo_header->isdn.channel -= 1;
879                                 break;
880                         }
881
882                         /*
883                          * It appears, at least with version 2 captures,
884                          * that we have 4 bytes of stuff (which might be
885                          * a valid FCS or might be junk) at the end of
886                          * the packet if hdr->hdr_2_x.xxx[2] and
887                          * hdr->hdr_2_x.xxx[3] are 0xff, and we don't if
888                          * they don't.
889                          *
890                          * XXX - does the low-order bit of hdr->hdr_2_x.xxx[8]
891                          * indicate a bad FCS, as is the case with
892                          * Ethernet?
893                          */
894                         if (hdr->hdr_2_x.xxx[2] == 0xff &&
895                             hdr->hdr_2_x.xxx[3] == 0xff) {
896                                 /*
897                                  * FCS, or junk, at the end.
898                                  * XXX - is it an FCS if "fcs_valid" is
899                                  * true?
900                                  */
901                                 padding = 4;
902                         }
903                         break;
904
905                 case WTAP_ENCAP_LAPB:
906                 case WTAP_ENCAP_FRELAY_WITH_PHDR:
907                         /*
908                          * LAPB/X.25 and Frame Relay.
909                          *
910                          * The bottommost bit of byte 12 of "hdr.hdr_2_x.xxx"
911                          * is the direction flag.  (Probably true for other
912                          * HDLC encapsulations as well.)
913                          */
914                         pseudo_header->x25.flags =
915                             (hdr->hdr_2_x.xxx[12] & 0x01) ? 0x00 : FROM_DCE;
916                         break;
917
918                 case WTAP_ENCAP_PPP_WITH_PHDR:
919                 case WTAP_ENCAP_SDLC:
920                         pseudo_header->p2p.sent =
921                             (hdr->hdr_2_x.xxx[12] & 0x01) ? TRUE : FALSE;
922                         break;
923
924                 case WTAP_ENCAP_ATM_PDUS_UNTRUNCATED:
925                         pseudo_header->atm.flags = 0;
926                         /*
927                          * XXX - is 0x08 an "OAM cell" flag?
928                          */
929                         if (hdr->hdr_2_x.xxx[9] & 0x04)
930                                 pseudo_header->atm.flags |= ATM_RAW_CELL;
931                         pseudo_header->atm.vpi = hdr->hdr_2_x.xxx[11];
932                         pseudo_header->atm.vci = pletohs(&hdr->hdr_2_x.xxx[12]);
933                         pseudo_header->atm.channel =
934                             (hdr->hdr_2_x.xxx[15] & 0x10)? 1 : 0;
935                         pseudo_header->atm.cells = 0;
936
937                         switch (hdr->hdr_2_x.xxx[0] & 0xF0) {
938
939                         case 0x00:      /* Unknown */
940                                 /*
941                                  * Infer the AAL, traffic type, and subtype.
942                                  */
943                                 atm_guess_traffic_type(pd, len,
944                                     pseudo_header);
945                                 break;
946
947                         case 0x50:      /* AAL5 (including signalling) */
948                                 pseudo_header->atm.aal = AAL_5;
949                                 switch (hdr->hdr_2_x.xxx[0] & 0x0F) {
950
951                                 case 0x09:
952                                 case 0x0a:      /* Signalling traffic */
953                                         pseudo_header->atm.aal = AAL_SIGNALLING;
954                                         pseudo_header->atm.type = TRAF_UNKNOWN;
955                                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
956                                         break;
957
958                                 case 0x0b:      /* ILMI */
959                                         pseudo_header->atm.type = TRAF_ILMI;
960                                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
961                                         break;
962
963                                 case 0x0c:      /* LANE LE Control */
964                                         pseudo_header->atm.type = TRAF_LANE;
965                                         pseudo_header->atm.subtype = TRAF_ST_LANE_LE_CTRL;
966                                         break;
967
968                                 case 0x0d:
969                                         /*
970                                          * 0x0d is *mostly* LANE 802.3,
971                                          * but I've seen an LE Control frame
972                                          * with 0x0d.
973                                          */
974                                         pseudo_header->atm.type = TRAF_LANE;
975                                         atm_guess_lane_type(pd, len,
976                                             pseudo_header);
977                                         break;
978
979                                 case 0x0f:      /* LLC multiplexed */
980                                         pseudo_header->atm.type = TRAF_LLCMX;   /* XXX */
981                                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;   /* XXX */
982                                         break;
983
984                                 default:
985                                         /*
986                                          * XXX - discover the other types.
987                                          */
988                                         pseudo_header->atm.type = TRAF_UNKNOWN;
989                                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
990                                         break;
991                                 }
992                                 break;
993
994                         default:
995                                 /*
996                                  * 0x60 seen, and dissected by Sniffer
997                                  * Pro as a raw cell.
998                                  *
999                                  * XXX - discover what those types are.
1000                                  */
1001                                 pseudo_header->atm.aal = AAL_UNKNOWN;
1002                                 pseudo_header->atm.type = TRAF_UNKNOWN;
1003                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1004                                 break;
1005                         }
1006                         break;
1007                 }
1008                 break;
1009         }
1010         return padding;
1011 }
1012
1013 static gboolean
1014 netxray_read_rec_data(FILE_T fh, guint8 *data_ptr, guint32 packet_size,
1015     int *err)
1016 {
1017         int     bytes_read;
1018
1019         errno = WTAP_ERR_CANT_READ;
1020         bytes_read = file_read(data_ptr, 1, packet_size, fh);
1021
1022         if (bytes_read <= 0 || (guint32)bytes_read != packet_size) {
1023                 *err = file_error(fh);
1024                 if (*err == 0)
1025                         *err = WTAP_ERR_SHORT_READ;
1026                 return FALSE;
1027         }
1028         return TRUE;
1029 }
1030
1031 static void
1032 netxray_close(wtap *wth)
1033 {
1034         g_free(wth->capture.netxray);
1035 }
1036
1037 static const struct {
1038         int     wtap_encap_value;
1039         int     ndis_value;
1040 } wtap_encap_1_1[] = {
1041     { WTAP_ENCAP_ETHERNET, 0 },         /* -> NDIS Ethernet */
1042     { WTAP_ENCAP_TOKEN_RING, 1 },       /* -> NDIS Token Ring */
1043     { WTAP_ENCAP_FDDI, 2 },             /* -> NDIS FDDI */
1044     { WTAP_ENCAP_FDDI_BITSWAPPED, 2 },  /* -> NDIS FDDI */
1045 };
1046 #define NUM_WTAP_ENCAPS_1_1 (sizeof wtap_encap_1_1 / sizeof wtap_encap_1_1[0])
1047
1048 static int
1049 wtap_encap_to_netxray_1_1_encap(int encap)
1050 {
1051     unsigned int i;
1052
1053     for (i = 0; i < NUM_WTAP_ENCAPS_1_1; i++) {
1054         if (encap == wtap_encap_1_1[i].wtap_encap_value)
1055             return wtap_encap_1_1[i].ndis_value;
1056     }
1057
1058     return -1;
1059 }
1060
1061 /* Returns 0 if we could write the specified encapsulation type,
1062    an error indication otherwise. */
1063 int netxray_dump_can_write_encap_1_1(int encap)
1064 {
1065     /* Per-packet encapsulations aren't supported. */
1066     if (encap == WTAP_ENCAP_PER_PACKET)
1067         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
1068
1069     if (wtap_encap_to_netxray_1_1_encap(encap) == -1)
1070         return WTAP_ERR_UNSUPPORTED_ENCAP;
1071
1072     return 0;
1073 }
1074
1075 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
1076    failure */
1077 gboolean netxray_dump_open_1_1(wtap_dumper *wdh, gboolean cant_seek, int *err)
1078 {
1079     /* This is a NetXRay file.  We can't fill in some fields in the header
1080        until all the packets have been written, so we can't write to a
1081        pipe. */
1082     if (cant_seek) {
1083         *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
1084         return FALSE;
1085     }
1086
1087     wdh->subtype_write = netxray_dump_1_1;
1088     wdh->subtype_close = netxray_dump_close_1_1;
1089
1090     /* We can't fill in all the fields in the file header, as we
1091        haven't yet written any packets.  As we'll have to rewrite
1092        the header when we've written out all the packets, we just
1093        skip over the header for now. */
1094     if (fseek(wdh->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET) == -1) {
1095         *err = errno;
1096         return FALSE;
1097     }
1098
1099     wdh->dump.netxray = g_malloc(sizeof(netxray_dump_t));
1100     wdh->dump.netxray->first_frame = TRUE;
1101     wdh->dump.netxray->start.tv_sec = 0;
1102     wdh->dump.netxray->start.tv_usec = 0;
1103     wdh->dump.netxray->nframes = 0;
1104
1105     return TRUE;
1106 }
1107
1108 /* Write a record for a packet to a dump file.
1109    Returns TRUE on success, FALSE on failure. */
1110 static gboolean netxray_dump_1_1(wtap_dumper *wdh,
1111         const struct wtap_pkthdr *phdr,
1112         const union wtap_pseudo_header *pseudo_header _U_,
1113         const guchar *pd, int *err)
1114 {
1115     netxray_dump_t *netxray = wdh->dump.netxray;
1116     guint32 timestamp;
1117     struct netxrayrec_1_x_hdr rec_hdr;
1118     size_t nwritten;
1119
1120     /* NetXRay/Windows Sniffer files have a capture start date/time
1121        in the header, in a UNIX-style format, with one-second resolution,
1122        and a start time stamp with microsecond resolution that's just
1123        an arbitrary time stamp relative to some unknown time (boot
1124        time?), and have times relative to the start time stamp in
1125        the packet headers; pick the seconds value of the time stamp
1126        of the first packet as the UNIX-style start date/time, and make
1127        the high-resolution start time stamp 0, with the time stamp of
1128        packets being the delta between the stamp of the packet and
1129        the stamp of the first packet with the microseconds part 0. */
1130     if (netxray->first_frame) {
1131         netxray->first_frame = FALSE;
1132         netxray->start = phdr->ts;
1133     }
1134
1135     /* build the header for each packet */
1136     memset(&rec_hdr, '\0', sizeof(rec_hdr));
1137     timestamp = (phdr->ts.tv_sec - netxray->start.tv_sec)*1000000 +
1138         phdr->ts.tv_usec;
1139     rec_hdr.timelo = htolel(timestamp);
1140     rec_hdr.timehi = htolel(0);
1141     rec_hdr.orig_len = htoles(phdr->len);
1142     rec_hdr.incl_len = htoles(phdr->caplen);
1143
1144     nwritten = fwrite(&rec_hdr, 1, sizeof(rec_hdr), wdh->fh);
1145     if (nwritten != sizeof(rec_hdr)) {
1146         if (nwritten == 0 && ferror(wdh->fh))
1147             *err = errno;
1148         else
1149             *err = WTAP_ERR_SHORT_WRITE;
1150         return FALSE;
1151     }
1152
1153     /* write the packet data */
1154     nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
1155     if (nwritten != phdr->caplen) {
1156         if (nwritten == 0 && ferror(wdh->fh))
1157             *err = errno;
1158         else
1159             *err = WTAP_ERR_SHORT_WRITE;
1160         return FALSE;
1161     }
1162
1163     netxray->nframes++;
1164
1165     return TRUE;
1166 }
1167
1168 /* Finish writing to a dump file.
1169    Returns TRUE on success, FALSE on failure. */
1170 static gboolean netxray_dump_close_1_1(wtap_dumper *wdh, int *err)
1171 {
1172     char hdr_buf[CAPTUREFILE_HEADER_SIZE - sizeof(netxray_magic)];
1173     netxray_dump_t *netxray = wdh->dump.netxray;
1174     guint32 filelen;
1175     struct netxray_hdr file_hdr;
1176     size_t nwritten;
1177
1178     filelen = ftell(wdh->fh);
1179
1180     /* Go back to beginning */
1181     fseek(wdh->fh, 0, SEEK_SET);
1182
1183     /* Rewrite the file header. */
1184     nwritten = fwrite(netxray_magic, 1, sizeof netxray_magic, wdh->fh);
1185     if (nwritten != sizeof netxray_magic) {
1186         if (err != NULL) {
1187             if (nwritten == 0 && ferror(wdh->fh))
1188                 *err = errno;
1189             else
1190                 *err = WTAP_ERR_SHORT_WRITE;
1191         }
1192         return FALSE;
1193     }
1194
1195     /* "sniffer" version ? */
1196     memset(&file_hdr, '\0', sizeof file_hdr);
1197     memcpy(file_hdr.version, vers_1_1, sizeof vers_1_1);
1198     file_hdr.start_time = htolel(netxray->start.tv_sec);
1199     file_hdr.nframes = htolel(netxray->nframes);
1200     file_hdr.start_offset = htolel(CAPTUREFILE_HEADER_SIZE);
1201     file_hdr.end_offset = htolel(filelen);
1202     file_hdr.network = (guint8) htoles(wtap_encap_to_netxray_1_1_encap(wdh->encap));
1203     file_hdr.timelo = htolel(0);
1204     file_hdr.timehi = htolel(0);
1205
1206     memset(hdr_buf, '\0', sizeof hdr_buf);
1207     memcpy(hdr_buf, &file_hdr, sizeof(file_hdr));
1208     nwritten = fwrite(hdr_buf, 1, sizeof hdr_buf, wdh->fh);
1209     if (nwritten != sizeof hdr_buf) {
1210         if (err != NULL) {
1211             if (nwritten == 0 && ferror(wdh->fh))
1212                 *err = errno;
1213             else
1214                 *err = WTAP_ERR_SHORT_WRITE;
1215         }
1216         return FALSE;
1217     }
1218
1219     return TRUE;
1220 }
1221
1222 static const struct {
1223         int     wtap_encap_value;
1224         int     ndis_value;
1225 } wtap_encap_2_0[] = {
1226     { WTAP_ENCAP_ETHERNET, 0 },                 /* -> NDIS Ethernet */
1227     { WTAP_ENCAP_TOKEN_RING, 1 },               /* -> NDIS Token Ring */
1228     { WTAP_ENCAP_FDDI, 2 },                     /* -> NDIS FDDI */
1229     { WTAP_ENCAP_FDDI_BITSWAPPED, 2 },          /* -> NDIS FDDI */
1230     { WTAP_ENCAP_PPP_WITH_PHDR, 3 },            /* -> NDIS WAN */
1231     { WTAP_ENCAP_FRELAY_WITH_PHDR, 3 },         /* -> NDIS WAN */
1232     { WTAP_ENCAP_LAPB, 3 },                     /* -> NDIS WAN */
1233     { WTAP_ENCAP_SDLC, 3 },                     /* -> NDIS WAN */
1234 };
1235 #define NUM_WTAP_ENCAPS_2_0 (sizeof wtap_encap_2_0 / sizeof wtap_encap_2_0[0])
1236
1237 static int
1238 wtap_encap_to_netxray_2_0_encap(int encap)
1239 {
1240     unsigned int i;
1241
1242     for (i = 0; i < NUM_WTAP_ENCAPS_2_0; i++) {
1243         if (encap == wtap_encap_2_0[i].wtap_encap_value)
1244             return wtap_encap_2_0[i].ndis_value;
1245     }
1246
1247     return -1;
1248 }
1249
1250 /* Returns 0 if we could write the specified encapsulation type,
1251    an error indication otherwise. */
1252 int netxray_dump_can_write_encap_2_0(int encap)
1253 {
1254     /* Per-packet encapsulations aren't supported. */
1255     if (encap == WTAP_ENCAP_PER_PACKET)
1256         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
1257
1258     if (wtap_encap_to_netxray_2_0_encap(encap) == -1)
1259         return WTAP_ERR_UNSUPPORTED_ENCAP;
1260
1261     return 0;
1262 }
1263
1264 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
1265    failure */
1266 gboolean netxray_dump_open_2_0(wtap_dumper *wdh, gboolean cant_seek, int *err)
1267 {
1268     /* This is a NetXRay file.  We can't fill in some fields in the header
1269        until all the packets have been written, so we can't write to a
1270        pipe. */
1271     if (cant_seek) {
1272         *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
1273         return FALSE;
1274     }
1275
1276     wdh->subtype_write = netxray_dump_2_0;
1277     wdh->subtype_close = netxray_dump_close_2_0;
1278
1279     /* We can't fill in all the fields in the file header, as we
1280        haven't yet written any packets.  As we'll have to rewrite
1281        the header when we've written out all the packets, we just
1282        skip over the header for now. */
1283     if (fseek(wdh->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET) == -1) {
1284         *err = errno;
1285         return FALSE;
1286     }
1287
1288     wdh->dump.netxray = g_malloc(sizeof(netxray_dump_t));
1289     wdh->dump.netxray->first_frame = TRUE;
1290     wdh->dump.netxray->start.tv_sec = 0;
1291     wdh->dump.netxray->start.tv_usec = 0;
1292     wdh->dump.netxray->nframes = 0;
1293
1294     return TRUE;
1295 }
1296
1297 /* Write a record for a packet to a dump file.
1298    Returns TRUE on success, FALSE on failure. */
1299 static gboolean netxray_dump_2_0(wtap_dumper *wdh,
1300         const struct wtap_pkthdr *phdr,
1301         const union wtap_pseudo_header *pseudo_header _U_,
1302         const guchar *pd, int *err)
1303 {
1304     netxray_dump_t *netxray = wdh->dump.netxray;
1305     guint32 timestamp;
1306     struct netxrayrec_2_x_hdr rec_hdr;
1307     size_t nwritten;
1308
1309     /* NetXRay/Windows Sniffer files have a capture start date/time
1310        in the header, in a UNIX-style format, with one-second resolution,
1311        and a start time stamp with microsecond resolution that's just
1312        an arbitrary time stamp relative to some unknown time (boot
1313        time?), and have times relative to the start time stamp in
1314        the packet headers; pick the seconds value of the time stamp
1315        of the first packet as the UNIX-style start date/time, and make
1316        the high-resolution start time stamp 0, with the time stamp of
1317        packets being the delta between the stamp of the packet and
1318        the stamp of the first packet with the microseconds part 0. */
1319     if (netxray->first_frame) {
1320         netxray->first_frame = FALSE;
1321         netxray->start = phdr->ts;
1322     }
1323
1324     /* build the header for each packet */
1325     memset(&rec_hdr, '\0', sizeof(rec_hdr));
1326     timestamp = (phdr->ts.tv_sec - netxray->start.tv_sec)*1000000 +
1327         phdr->ts.tv_usec;
1328     rec_hdr.timelo = htolel(timestamp);
1329     rec_hdr.timehi = htolel(0);
1330     rec_hdr.orig_len = htoles(phdr->len);
1331     rec_hdr.incl_len = htoles(phdr->caplen);
1332
1333     switch (phdr->pkt_encap) {
1334
1335     case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
1336         rec_hdr.xxx[12] = pseudo_header->ieee_802_11.channel;
1337         rec_hdr.xxx[13] = pseudo_header->ieee_802_11.data_rate;
1338         rec_hdr.xxx[14] = pseudo_header->ieee_802_11.signal_level;
1339         break;
1340
1341     case WTAP_ENCAP_PPP_WITH_PHDR:
1342     case WTAP_ENCAP_SDLC:
1343         rec_hdr.xxx[12] |= pseudo_header->p2p.sent ? 0x01 : 0x00;
1344         break;
1345
1346     case WTAP_ENCAP_FRELAY_WITH_PHDR:
1347         rec_hdr.xxx[12] |= (pseudo_header->x25.flags & FROM_DCE) ? 0x00 : 0x01;
1348         break;
1349     }
1350
1351     nwritten = fwrite(&rec_hdr, 1, sizeof(rec_hdr), wdh->fh);
1352     if (nwritten != sizeof(rec_hdr)) {
1353         if (nwritten == 0 && ferror(wdh->fh))
1354             *err = errno;
1355         else
1356             *err = WTAP_ERR_SHORT_WRITE;
1357         return FALSE;
1358     }
1359
1360     /* write the packet data */
1361     nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
1362     if (nwritten != phdr->caplen) {
1363         if (nwritten == 0 && ferror(wdh->fh))
1364             *err = errno;
1365         else
1366             *err = WTAP_ERR_SHORT_WRITE;
1367         return FALSE;
1368     }
1369
1370     netxray->nframes++;
1371
1372     return TRUE;
1373 }
1374
1375 /* Finish writing to a dump file.
1376    Returns TRUE on success, FALSE on failure. */
1377 static gboolean netxray_dump_close_2_0(wtap_dumper *wdh, int *err)
1378 {
1379     char hdr_buf[CAPTUREFILE_HEADER_SIZE - sizeof(netxray_magic)];
1380     netxray_dump_t *netxray = wdh->dump.netxray;
1381     guint32 filelen;
1382     struct netxray_hdr file_hdr;
1383     size_t nwritten;
1384
1385     filelen = ftell(wdh->fh);
1386
1387     /* Go back to beginning */
1388     fseek(wdh->fh, 0, SEEK_SET);
1389
1390     /* Rewrite the file header. */
1391     nwritten = fwrite(netxray_magic, 1, sizeof netxray_magic, wdh->fh);
1392     if (nwritten != sizeof netxray_magic) {
1393         if (err != NULL) {
1394             if (nwritten == 0 && ferror(wdh->fh))
1395                 *err = errno;
1396             else
1397                 *err = WTAP_ERR_SHORT_WRITE;
1398         }
1399         return FALSE;
1400     }
1401
1402     /* "sniffer" version ? */
1403     memset(&file_hdr, '\0', sizeof file_hdr);
1404     memcpy(file_hdr.version, vers_2_001, sizeof vers_2_001);
1405     file_hdr.start_time = htolel(netxray->start.tv_sec);
1406     file_hdr.nframes = htolel(netxray->nframes);
1407     file_hdr.start_offset = htolel(CAPTUREFILE_HEADER_SIZE);
1408     file_hdr.end_offset = htolel(filelen);
1409     file_hdr.network = (guint8) htoles(wtap_encap_to_netxray_2_0_encap(wdh->encap));
1410     file_hdr.timelo = htolel(0);
1411     file_hdr.timehi = htolel(0);
1412     switch (wdh->encap) {
1413
1414     case WTAP_ENCAP_PPP_WITH_PHDR:
1415         file_hdr.xxb[20] = CAPTYPE_PPP;
1416         break;
1417
1418     case WTAP_ENCAP_FRELAY_WITH_PHDR:
1419         file_hdr.xxb[20] = CAPTYPE_FRELAY;
1420         break;
1421
1422     case WTAP_ENCAP_LAPB:
1423         file_hdr.xxb[20] = CAPTYPE_HDLC;
1424         file_hdr.xxb[28] = 0;
1425         break;
1426
1427     case WTAP_ENCAP_SDLC:
1428         file_hdr.xxb[20] = CAPTYPE_SDLC;
1429         break;
1430
1431     default:
1432         file_hdr.xxb[20] = CAPTYPE_NDIS;
1433         break;
1434     }
1435
1436     memset(hdr_buf, '\0', sizeof hdr_buf);
1437     memcpy(hdr_buf, &file_hdr, sizeof(file_hdr));
1438     nwritten = fwrite(hdr_buf, 1, sizeof hdr_buf, wdh->fh);
1439     if (nwritten != sizeof hdr_buf) {
1440         if (err != NULL) {
1441             if (nwritten == 0 && ferror(wdh->fh))
1442                 *err = errno;
1443             else
1444                 *err = WTAP_ERR_SHORT_WRITE;
1445         }
1446         return FALSE;
1447     }
1448
1449     return TRUE;
1450 }