Clean up white space.
[obnox/wireshark/wip.git] / wiretap / netmon.c
1 /* netmon.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 #include <errno.h>
27 #include <string.h>
28 #include "wtap-int.h"
29 #include "file_wrappers.h"
30 #include "buffer.h"
31 #include "atm.h"
32 #include "pcap-encap.h"
33 #include "netmon.h"
34
35 /* The file at
36  *
37  *      ftp://ftp.microsoft.com/developr/drg/cifs/cifs/Bhfile.zip
38  *
39  * contains "STRUCT.H", which declares the typedef CAPTUREFILE_HEADER
40  * for the header of a Microsoft Network Monitor capture file.
41  */
42
43 /* Capture file header, *including* magic number, is padded to 128 bytes. */
44 #define CAPTUREFILE_HEADER_SIZE 128
45
46 /* Magic number in Network Monitor 1.x files. */
47 static const char netmon_1_x_magic[] = {
48         'R', 'T', 'S', 'S'
49 };
50
51 /* Magic number in Network Monitor 2.x files. */
52 static const char netmon_2_x_magic[] = {
53         'G', 'M', 'B', 'U'
54 };
55
56 /* Network Monitor file header (minus magic number). */
57 struct netmon_hdr {
58         guint8  ver_minor;      /* minor version number */
59         guint8  ver_major;      /* major version number */
60         guint16 network;        /* network type */
61         guint16 ts_year;        /* year of capture start */
62         guint16 ts_month;       /* month of capture start (January = 1) */
63         guint16 ts_dow;         /* day of week of capture start (Sun = 0) */
64         guint16 ts_day;         /* day of month of capture start */
65         guint16 ts_hour;        /* hour of capture start */
66         guint16 ts_min;         /* minute of capture start */
67         guint16 ts_sec;         /* second of capture start */
68         guint16 ts_msec;        /* millisecond of capture start */
69         guint32 frametableoffset;       /* frame index table offset */
70         guint32 frametablelength;       /* frame index table size */
71         guint32 userdataoffset;         /* user data offset */
72         guint32 userdatalength;         /* user data size */
73         guint32 commentdataoffset;      /* comment data offset */
74         guint32 commentdatalength;      /* comment data size */
75         guint32 statisticsoffset;       /* offset to statistics structure */
76         guint32 statisticslength;       /* length of statistics structure */
77         guint32 networkinfooffset;      /* offset to network info structure */
78         guint32 networkinfolength;      /* length of network info structure */
79 };
80
81 /* Network Monitor 1.x record header; not defined in STRUCT.H, but deduced by
82  * looking at capture files. */
83 struct netmonrec_1_x_hdr {
84         guint32 ts_delta;       /* time stamp - msecs since start of capture */
85         guint16 orig_len;       /* actual length of packet */
86         guint16 incl_len;       /* number of octets captured in file */
87 };
88
89 /* Network Monitor 2.x record header; not defined in STRUCT.H, but deduced by
90  * looking at capture files. */
91 struct netmonrec_2_x_hdr {
92         guint32 ts_delta_lo;    /* time stamp - usecs since start of capture */
93         guint32 ts_delta_hi;    /* time stamp - usecs since start of capture */
94         guint32 orig_len;       /* actual length of packet */
95         guint32 incl_len;       /* number of octets captured in file */
96 };
97
98 /*
99  * Network Monitor 2.1 and later record trailers; documented in the Network
100  * Monitor 3.x help files, for 3.3 and later, although they don't clearly
101  * state how the trailer format changes from version to version.
102  *
103  * Some fields are multi-byte integers, but they're not aligned on their
104  * natural boundaries.
105  */
106 struct netmonrec_2_1_trlr {
107         guint8 network[2];              /* network type for this packet */
108 };
109
110 struct netmonrec_2_2_trlr {
111         guint8 network[2];              /* network type for this packet */
112         guint8 process_info_index[4];   /* index into the process info table */
113 };
114
115 struct netmonrec_2_3_trlr {
116         guint8 network[2];              /* network type for this packet */
117         guint8 process_info_index[4];   /* index into the process info table */
118         guint8 utc_timestamp[8];        /* packet time stamp, as .1 us units since January 1, 1601, 00:00:00 UTC */
119         guint8 timezone_index;          /* index of time zone information */
120 };
121
122 /*
123  * The link-layer header on ATM packets.
124  */
125 struct netmon_atm_hdr {
126         guint8  dest[6];        /* "Destination address" - what is it? */
127         guint8  src[6];         /* "Source address" - what is it? */
128         guint16 vpi;            /* VPI */
129         guint16 vci;            /* VCI */
130 };
131
132 typedef struct {
133         time_t  start_secs;
134         guint32 start_usecs;
135         guint8  version_major;
136         guint8  version_minor;
137         guint32 *frame_table;
138         guint32 frame_table_size;
139         guint   current_frame;
140 } netmon_t;
141
142 /*
143  * XXX - at least in some NetMon 3.4 VPN captures, the per-packet
144  * link-layer type is 0, but the packets have Ethernet headers.
145  * We handle this by mapping 0 to WTAP_ENCAP_ETHERNET; should we,
146  * instead, use the per-file link-layer type?
147  */
148 static const int netmon_encap[] = {
149         WTAP_ENCAP_ETHERNET,
150         WTAP_ENCAP_ETHERNET,
151         WTAP_ENCAP_TOKEN_RING,
152         WTAP_ENCAP_FDDI_BITSWAPPED,
153         WTAP_ENCAP_ATM_PDUS,    /* NDIS WAN - this is what's used for ATM */
154         WTAP_ENCAP_UNKNOWN,     /* NDIS LocalTalk, but format 2.x uses it for IP-over-IEEE 1394 */
155         WTAP_ENCAP_IEEE802_11_NETMON_RADIO,
156                                 /* NDIS "DIX", but format 2.x uses it for 802.11 */
157         WTAP_ENCAP_RAW_IP,      /* NDIS ARCNET raw, but format 2.x uses it for "Tunneling interfaces" */
158         WTAP_ENCAP_RAW_IP,      /* NDIS ARCNET 878.2, but format 2.x uses it for "Wireless WAN" */
159         WTAP_ENCAP_RAW_IP,      /* NDIS ATM (no, this is NOT used for ATM); format 2.x uses it for "Raw IP Frames" */
160         WTAP_ENCAP_UNKNOWN,     /* NDIS Wireless WAN */
161         WTAP_ENCAP_UNKNOWN      /* NDIS IrDA */
162 };
163 #define NUM_NETMON_ENCAPS (sizeof netmon_encap / sizeof netmon_encap[0])
164
165 /*
166  * Special link-layer types.
167  */
168 #define NETMON_NET_PCAP_BASE            0xE000
169 #define NETMON_NET_NETEVENT             0xFFE0
170 #define NETMON_NET_NETWORK_INFO_EX      0xFFFB
171 #define NETMON_NET_PAYLOAD_HEADER       0xFFFC
172 #define NETMON_NET_NETWORK_INFO         0xFFFD
173 #define NETMON_NET_DNS_CACHE            0xFFFE
174 #define NETMON_NET_NETMON_FILTER        0xFFFF
175
176 static gboolean netmon_read(wtap *wth, int *err, gchar **err_info,
177     gint64 *data_offset);
178 static gboolean netmon_seek_read(wtap *wth, gint64 seek_off,
179     union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
180     int *err, gchar **err_info);
181 static gboolean netmon_read_atm_pseudoheader(FILE_T fh,
182     union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
183 static gboolean netmon_read_rec_data(FILE_T fh, guint8 *pd, int length,
184     int *err, gchar **err_info);
185 static int netmon_read_rec_trailer(FILE_T fh, int trlr_size, int *err,
186     gchar **err_info);
187 static void netmon_sequential_close(wtap *wth);
188 static gboolean netmon_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
189     const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err);
190 static gboolean netmon_dump_close(wtap_dumper *wdh, int *err);
191
192 int netmon_open(wtap *wth, int *err, gchar **err_info)
193 {
194         int bytes_read;
195         char magic[sizeof netmon_1_x_magic];
196         struct netmon_hdr hdr;
197         int file_type;
198         struct tm tm;
199         int frame_table_offset;
200         guint32 frame_table_length;
201         guint32 frame_table_size;
202         guint32 *frame_table;
203 #ifdef WORDS_BIGENDIAN
204         unsigned int i;
205 #endif
206         netmon_t *netmon;
207
208         /* Read in the string that should be at the start of a Network
209          * Monitor file */
210         errno = WTAP_ERR_CANT_READ;
211         bytes_read = file_read(magic, sizeof magic, wth->fh);
212         if (bytes_read != sizeof magic) {
213                 *err = file_error(wth->fh, err_info);
214                 if (*err != 0)
215                         return -1;
216                 return 0;
217         }
218
219         if (memcmp(magic, netmon_1_x_magic, sizeof netmon_1_x_magic) != 0
220          && memcmp(magic, netmon_2_x_magic, sizeof netmon_1_x_magic) != 0) {
221                 return 0;
222         }
223
224         /* Read the rest of the header. */
225         errno = WTAP_ERR_CANT_READ;
226         bytes_read = file_read(&hdr, sizeof hdr, wth->fh);
227         if (bytes_read != sizeof hdr) {
228                 *err = file_error(wth->fh, err_info);
229                 if (*err != 0)
230                         return -1;
231                 return 0;
232         }
233
234         switch (hdr.ver_major) {
235
236         case 1:
237                 file_type = WTAP_FILE_NETMON_1_x;
238                 break;
239
240         case 2:
241                 file_type = WTAP_FILE_NETMON_2_x;
242                 break;
243
244         default:
245                 *err = WTAP_ERR_UNSUPPORTED;
246                 *err_info = g_strdup_printf("netmon: major version %u unsupported", hdr.ver_major);
247                 return -1;
248         }
249
250         hdr.network = pletohs(&hdr.network);
251         if (hdr.network >= NUM_NETMON_ENCAPS
252             || netmon_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
253                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
254                 *err_info = g_strdup_printf("netmon: network type %u unknown or unsupported",
255                     hdr.network);
256                 return -1;
257         }
258
259         /* This is a netmon file */
260         wth->file_type = file_type;
261         netmon = (netmon_t *)g_malloc(sizeof(netmon_t));
262         wth->priv = (void *)netmon;
263         wth->subtype_read = netmon_read;
264         wth->subtype_seek_read = netmon_seek_read;
265         wth->subtype_sequential_close = netmon_sequential_close;
266
267         /* NetMon capture file formats v2.1+ use per-packet encapsulation types.  NetMon 3 sets the value in
268          * the header to 1 (Ethernet) for backwards compability. */
269         if((hdr.ver_major == 2 && hdr.ver_minor >= 1) || hdr.ver_major > 2)
270                 wth->file_encap = WTAP_ENCAP_PER_PACKET;
271         else
272                 wth->file_encap = netmon_encap[hdr.network];
273
274         wth->snapshot_length = 0;       /* not available in header */
275         /*
276          * Convert the time stamp to a "time_t" and a number of
277          * milliseconds.
278          */
279         tm.tm_year = pletohs(&hdr.ts_year) - 1900;
280         tm.tm_mon = pletohs(&hdr.ts_month) - 1;
281         tm.tm_mday = pletohs(&hdr.ts_day);
282         tm.tm_hour = pletohs(&hdr.ts_hour);
283         tm.tm_min = pletohs(&hdr.ts_min);
284         tm.tm_sec = pletohs(&hdr.ts_sec);
285         tm.tm_isdst = -1;
286         netmon->start_secs = mktime(&tm);
287         /*
288          * XXX - what if "secs" is -1?  Unlikely, but if the capture was
289          * done in a time zone that switches between standard and summer
290          * time sometime other than when we do, and thus the time was one
291          * that doesn't exist here because a switch from standard to summer
292          * time zips over it, it could happen.
293          *
294          * On the other hand, if the capture was done in a different time
295          * zone, this won't work right anyway; unfortunately, the time
296          * zone isn't stored in the capture file (why the hell didn't
297          * they stuff a FILETIME, which is the number of 100-nanosecond
298          * intervals since 1601-01-01 00:00:00 "UTC", there, instead
299          * of stuffing a SYSTEMTIME, which is time-zone-dependent, there?).
300          */
301         netmon->start_usecs = pletohs(&hdr.ts_msec)*1000;
302
303         netmon->version_major = hdr.ver_major;
304         netmon->version_minor = hdr.ver_minor;
305
306         /*
307          * Get the offset of the frame index table.
308          */
309         frame_table_offset = pletohl(&hdr.frametableoffset);
310
311         /*
312          * It appears that some NetMon 2.x files don't have the
313          * first packet starting exactly 128 bytes into the file.
314          *
315          * Furthermore, it also appears that there are "holes" in
316          * the file, i.e. frame N+1 doesn't always follow immediately
317          * after frame N.
318          *
319          * Therefore, we must read the frame table, and use the offsets
320          * in it as the offsets of the frames.
321          */
322         frame_table_length = pletohl(&hdr.frametablelength);
323         frame_table_size = frame_table_length / (guint32)sizeof (guint32);
324         if ((frame_table_size * sizeof (guint32)) != frame_table_length) {
325                 *err = WTAP_ERR_UNSUPPORTED;
326                 *err_info = g_strdup_printf("netmon: frame table length is %u, which is not a multiple of the size of an entry",
327                     frame_table_length);
328                 g_free(netmon);
329                 return -1;
330         }
331         if (frame_table_size == 0) {
332                 *err = WTAP_ERR_UNSUPPORTED;
333                 *err_info = g_strdup_printf("netmon: frame table length is %u, which means it's less than one entry in size",
334                     frame_table_length);
335                 g_free(netmon);
336                 return -1;
337         }
338         if (file_seek(wth->fh, frame_table_offset, SEEK_SET, err) == -1) {
339                 g_free(netmon);
340                 return -1;
341         }
342         frame_table = g_malloc(frame_table_length);
343         errno = WTAP_ERR_CANT_READ;
344         bytes_read = file_read(frame_table, frame_table_length, wth->fh);
345         if ((guint32)bytes_read != frame_table_length) {
346                 *err = file_error(wth->fh, err_info);
347                 if (*err == 0)
348                         *err = WTAP_ERR_SHORT_READ;
349                 g_free(frame_table);
350                 g_free(netmon);
351                 return -1;
352         }
353         netmon->frame_table_size = frame_table_size;
354         netmon->frame_table = frame_table;
355
356 #ifdef WORDS_BIGENDIAN
357         /*
358          * OK, now byte-swap the frame table.
359          */
360         for (i = 0; i < frame_table_size; i++)
361                 frame_table[i] = pletohl(&frame_table[i]);
362 #endif
363
364         /* Set up to start reading at the first frame. */
365         netmon->current_frame = 0;
366         wth->tsprecision = WTAP_FILE_TSPREC_USEC;
367
368         return 1;
369 }
370
371 static size_t
372 netmon_trailer_size(netmon_t *netmon)
373 {
374         if ((netmon->version_major == 2 && netmon->version_minor >= 1) ||
375             netmon->version_major > 2) {
376                 if (netmon->version_major > 2) {
377                         /*
378                          * Asssume 2.3 format, for now.
379                          */
380                         return sizeof (struct netmonrec_2_3_trlr);
381                 } else {
382                         switch (netmon->version_minor) {
383
384                         case 1:
385                                 return sizeof (struct netmonrec_2_1_trlr);
386
387                         case 2:
388                                 return sizeof (struct netmonrec_2_2_trlr);
389
390                         default:
391                                 return sizeof (struct netmonrec_2_3_trlr);
392                         }
393                 }
394         }
395         return 0;       /* no trailer */
396 }
397
398 static void
399 netmon_set_pseudo_header_info(int pkt_encap,
400     union wtap_pseudo_header *pseudo_header, guint8 *pd, int length)
401 {
402         switch (pkt_encap) {
403
404         case WTAP_ENCAP_ATM_PDUS:
405                 /*
406                  * Attempt to guess from the packet data, the VPI, and
407                  * the VCIinformation about the type of traffic.
408                  */
409                 atm_guess_traffic_type(pd, length, pseudo_header);
410                 break;
411
412         case WTAP_ENCAP_ETHERNET:
413                 /*
414                  * We assume there's no FCS in this frame.
415                  */
416                 pseudo_header->eth.fcs_len = 0;
417                 break;
418
419         case WTAP_ENCAP_IEEE802_11_NETMON_RADIO:
420                 /*
421                  * It appears to be the case that management
422                  * frames have an FCS and data frames don't;
423                  * I'm not sure about control frames.  An
424                  * "FCS length" of -2 means "NetMon weirdness".
425                  */
426                 pseudo_header->ieee_802_11.fcs_len = -2;
427                 break;
428         }
429 }
430
431 /* Read the next packet */
432 static gboolean netmon_read(wtap *wth, int *err, gchar **err_info,
433     gint64 *data_offset)
434 {
435         netmon_t *netmon = (netmon_t *)wth->priv;
436         guint32 packet_size = 0;
437         guint32 orig_size = 0;
438         int     bytes_read;
439         union {
440                 struct netmonrec_1_x_hdr hdr_1_x;
441                 struct netmonrec_2_x_hdr hdr_2_x;
442         }       hdr;
443         int     hdr_size = 0;
444         int     trlr_size;
445         int     rec_offset;
446         guint8  *data_ptr;
447         gint64  delta = 0;      /* signed - frame times can be before the nominal start */
448         time_t  secs;
449         guint32 usecs;
450         double  t;
451
452 again:
453         /* Have we reached the end of the packet data? */
454         if (netmon->current_frame >= netmon->frame_table_size) {
455                 /* Yes.  We won't need the frame table any more;
456                    free it. */
457                 g_free(netmon->frame_table);
458                 netmon->frame_table = NULL;
459                 *err = 0;       /* it's just an EOF, not an error */
460                 return FALSE;
461         }
462
463         /* Seek to the beginning of the current record, if we're
464            not there already (seeking to the current position
465            may still cause a seek and a read of the underlying file,
466            so we don't want to do it unconditionally).
467
468            Yes, the current record could be before the previous
469            record.  At least some captures put the trailer record
470            with statistics as the first physical record in the
471            file, but set the frame table up so it's the last
472            record in sequence. */
473         rec_offset = netmon->frame_table[netmon->current_frame];
474         if (wth->data_offset != rec_offset) {
475                 wth->data_offset = rec_offset;
476                 if (file_seek(wth->fh, wth->data_offset, SEEK_SET, err) == -1)
477                         return FALSE;
478         }
479         netmon->current_frame++;
480
481         /* Read record header. */
482         switch (netmon->version_major) {
483
484         case 1:
485                 hdr_size = sizeof (struct netmonrec_1_x_hdr);
486                 break;
487
488         case 2:
489                 hdr_size = sizeof (struct netmonrec_2_x_hdr);
490                 break;
491         }
492         errno = WTAP_ERR_CANT_READ;
493
494         bytes_read = file_read(&hdr, hdr_size, wth->fh);
495         if (bytes_read != hdr_size) {
496                 *err = file_error(wth->fh, err_info);
497                 if (*err == 0 && bytes_read != 0) {
498                         *err = WTAP_ERR_SHORT_READ;
499                 }
500                 return FALSE;
501         }
502         wth->data_offset += hdr_size;
503
504         switch (netmon->version_major) {
505
506         case 1:
507                 orig_size = pletohs(&hdr.hdr_1_x.orig_len);
508                 packet_size = pletohs(&hdr.hdr_1_x.incl_len);
509                 break;
510
511         case 2:
512                 orig_size = pletohl(&hdr.hdr_2_x.orig_len);
513                 packet_size = pletohl(&hdr.hdr_2_x.incl_len);
514                 break;
515         }
516         if (packet_size > WTAP_MAX_PACKET_SIZE) {
517                 /*
518                  * Probably a corrupt capture file; don't blow up trying
519                  * to allocate space for an immensely-large packet.
520                  */
521                 *err = WTAP_ERR_BAD_RECORD;
522                 *err_info = g_strdup_printf("netmon: File has %u-byte packet, bigger than maximum of %u",
523                     packet_size, WTAP_MAX_PACKET_SIZE);
524                 return FALSE;
525         }
526
527         *data_offset = wth->data_offset;
528
529         /*
530          * If this is an ATM packet, the first
531          * "sizeof (struct netmon_atm_hdr)" bytes have destination and
532          * source addresses (6 bytes - MAC addresses of some sort?)
533          * and the VPI and VCI; read them and generate the pseudo-header
534          * from them.
535          */
536         switch (wth->file_encap) {
537
538         case WTAP_ENCAP_ATM_PDUS:
539                 if (packet_size < sizeof (struct netmon_atm_hdr)) {
540                         /*
541                          * Uh-oh, the packet isn't big enough to even
542                          * have a pseudo-header.
543                          */
544                         *err = WTAP_ERR_BAD_RECORD;
545                         *err_info = g_strdup_printf("netmon: ATM file has a %u-byte packet, too small to have even an ATM pseudo-header",
546                             packet_size);
547                         return FALSE;
548                 }
549                 if (!netmon_read_atm_pseudoheader(wth->fh, &wth->pseudo_header,
550                     err, err_info))
551                         return FALSE;   /* Read error */
552
553                 /*
554                  * Don't count the pseudo-header as part of the packet.
555                  */
556                 orig_size -= (guint)sizeof (struct netmon_atm_hdr);
557                 packet_size -= (guint)sizeof (struct netmon_atm_hdr);
558                 wth->data_offset += sizeof (struct netmon_atm_hdr);
559                 break;
560
561         default:
562                 break;
563         }
564
565         buffer_assure_space(wth->frame_buffer, packet_size);
566         data_ptr = buffer_start_ptr(wth->frame_buffer);
567         if (!netmon_read_rec_data(wth->fh, data_ptr, packet_size, err,
568             err_info))
569                 return FALSE;   /* Read error */
570         wth->data_offset += packet_size;
571
572         t = (double)netmon->start_usecs;
573         switch (netmon->version_major) {
574
575         case 1:
576                 /*
577                  * According to Paul Long, this offset is unsigned.
578                  * It's 32 bits, so the maximum value will fit in
579                  * a gint64 such as delta, even after multiplying
580                  * it by 1000.
581                  *
582                  * pletohl() returns a guint32; we cast it to gint64
583                  * before multiplying, so that the product doesn't
584                  * overflow a guint32.
585                  */
586                 delta = ((gint64)pletohl(&hdr.hdr_1_x.ts_delta))*1000;
587                 break;
588
589         case 2:
590                 delta = pletohl(&hdr.hdr_2_x.ts_delta_lo)
591                     | (((guint64)pletohl(&hdr.hdr_2_x.ts_delta_hi)) << 32);
592                 break;
593         }
594         t += (double)delta;
595         secs = (time_t)(t/1000000);
596         usecs = (guint32)(t - (double)secs*1000000);
597         wth->phdr.ts.secs = netmon->start_secs + secs;
598         wth->phdr.ts.nsecs = usecs * 1000;
599         wth->phdr.caplen = packet_size;
600         wth->phdr.len = orig_size;
601
602         /*
603          * For version 2.1 and later, there's additional information
604          * after the frame data.
605          */
606         trlr_size = (int)netmon_trailer_size(netmon);
607         if (trlr_size != 0) {
608                 /*
609                  * I haz a trailer.
610                  */
611                 wth->phdr.pkt_encap = netmon_read_rec_trailer(wth->fh,
612                     trlr_size, err, err_info);
613                 if (wth->phdr.pkt_encap == -1)
614                         return FALSE;   /* error */
615                 wth->data_offset += trlr_size;
616                 if (wth->phdr.pkt_encap == 0)
617                         goto again;
618                 netmon_set_pseudo_header_info(wth->phdr.pkt_encap,
619                     &wth->pseudo_header, data_ptr, packet_size);
620         } else {
621                 netmon_set_pseudo_header_info(wth->file_encap,
622                     &wth->pseudo_header, data_ptr, packet_size);
623         }
624
625         return TRUE;
626 }
627
628 static gboolean
629 netmon_seek_read(wtap *wth, gint64 seek_off,
630     union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
631     int *err, gchar **err_info)
632 {
633         netmon_t *netmon = (netmon_t *)wth->priv;
634         int     trlr_size;
635         int     pkt_encap;
636
637         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
638                 return FALSE;
639
640         switch (wth->file_encap) {
641
642         case WTAP_ENCAP_ATM_PDUS:
643                 if (!netmon_read_atm_pseudoheader(wth->random_fh, pseudo_header,
644                     err, err_info)) {
645                         /* Read error */
646                         return FALSE;
647                 }
648                 break;
649         }
650
651         /*
652          * Read the packet data.
653          */
654         if (!netmon_read_rec_data(wth->random_fh, pd, length, err, err_info))
655                 return FALSE;
656
657         /*
658          * For version 2.1 and later, there's additional information
659          * after the frame data.
660          */
661         trlr_size = (int)netmon_trailer_size(netmon);
662         if (trlr_size != 0) {
663                 /*
664                  * I haz a trailer.
665                  */
666                 pkt_encap = netmon_read_rec_trailer(wth->random_fh,
667                     trlr_size, err, err_info);
668                 if (pkt_encap == -1)
669                         return FALSE;   /* error */
670                 if (pkt_encap == 0) {
671                         /*
672                          * This should not happen.
673                          */
674                         *err = WTAP_ERR_BAD_RECORD;
675                         *err_info = g_strdup("netmon: saw metadata in netmon_seek_read");
676                         return FALSE;
677                 }
678                 netmon_set_pseudo_header_info(pkt_encap, pseudo_header,
679                     pd, length);
680         } else {
681                 netmon_set_pseudo_header_info(wth->file_encap, pseudo_header,
682                     pd, length);
683         }
684
685         return TRUE;
686 }
687
688 static gboolean
689 netmon_read_atm_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
690     int *err, gchar **err_info)
691 {
692         struct netmon_atm_hdr atm_phdr;
693         int     bytes_read;
694         guint16 vpi, vci;
695
696         errno = WTAP_ERR_CANT_READ;
697         bytes_read = file_read(&atm_phdr, sizeof (struct netmon_atm_hdr), fh);
698         if (bytes_read != sizeof (struct netmon_atm_hdr)) {
699                 *err = file_error(fh, err_info);
700                 if (*err == 0)
701                         *err = WTAP_ERR_SHORT_READ;
702                 return FALSE;
703         }
704
705         vpi = g_ntohs(atm_phdr.vpi);
706         vci = g_ntohs(atm_phdr.vci);
707
708         pseudo_header->atm.vpi = vpi;
709         pseudo_header->atm.vci = vci;
710
711         /* We don't have this information */
712         pseudo_header->atm.flags = 0;
713         pseudo_header->atm.channel = 0;
714         pseudo_header->atm.cells = 0;
715         pseudo_header->atm.aal5t_u2u = 0;
716         pseudo_header->atm.aal5t_len = 0;
717         pseudo_header->atm.aal5t_chksum = 0;
718
719         return TRUE;
720 }
721
722 static gboolean
723 netmon_read_rec_data(FILE_T fh, guint8 *pd, int length, int *err,
724     gchar **err_info)
725 {
726         int     bytes_read;
727
728         errno = WTAP_ERR_CANT_READ;
729         bytes_read = file_read(pd, length, fh);
730
731         if (bytes_read != length) {
732                 *err = file_error(fh, err_info);
733                 if (*err == 0)
734                         *err = WTAP_ERR_SHORT_READ;
735                 return FALSE;
736         }
737         return TRUE;
738 }
739
740 /*
741  * Read a record trailer.
742  * On success, returns the packet encapsulation type.
743  * On error, returns -1 (which is WTAP_ENCAP_PER_PACKET, but we'd
744  * never return that on success).
745  * For metadata packets, returns 0 (which is WTAP_ENCAP_UNKNOWN, but
746  * we'd never return that on success).
747  */
748 static int
749 netmon_read_rec_trailer(FILE_T fh, int trlr_size, int *err, gchar **err_info)
750 {
751         int     bytes_read;
752         union {
753                 struct netmonrec_2_1_trlr trlr_2_1;
754                 struct netmonrec_2_2_trlr trlr_2_2;
755                 struct netmonrec_2_3_trlr trlr_2_3;
756         }       trlr;
757         guint16 network;
758         int     pkt_encap;
759
760         errno = WTAP_ERR_CANT_READ;
761         bytes_read = file_read(&trlr, trlr_size, fh);
762         if (bytes_read != trlr_size) {
763                 *err = file_error(fh, err_info);
764                 if (*err == 0 && bytes_read != 0) {
765                         *err = WTAP_ERR_SHORT_READ;
766                 }
767                 return -1;      /* error */
768         }
769
770         network = pletohs(trlr.trlr_2_1.network);
771         if ((network & 0xF000) == NETMON_NET_PCAP_BASE) {
772                 /*
773                  * Converted pcap file - the LINKTYPE_ value
774                  * is the network value with 0xF000 masked off.
775                  */
776                 network &= 0x0FFF;
777                 pkt_encap = wtap_pcap_encap_to_wtap_encap(network);
778                 if (pkt_encap == WTAP_ENCAP_UNKNOWN) {
779                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
780                         *err_info = g_strdup_printf("netmon: converted pcap network type %u unknown or unsupported",
781                             network);
782                         return -1;      /* error */
783                 }
784         } else if (network < NUM_NETMON_ENCAPS) {
785                 /*
786                  * Regular NetMon encapsulation.
787                  */
788                 pkt_encap = netmon_encap[network];
789                 if (pkt_encap == WTAP_ENCAP_UNKNOWN) {
790                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
791                         *err_info = g_strdup_printf("netmon: network type %u unknown or unsupported",
792                             network);
793                         return -1;      /* error */
794                 }
795         } else {
796                 /*
797                  * Special packet type for metadata.
798                  */
799                 switch (network) {
800
801                 case NETMON_NET_NETEVENT:
802                 case NETMON_NET_NETWORK_INFO_EX:
803                 case NETMON_NET_PAYLOAD_HEADER:
804                 case NETMON_NET_NETWORK_INFO:
805                 case NETMON_NET_DNS_CACHE:
806                 case NETMON_NET_NETMON_FILTER:
807                         /*
808                          * Just ignore those record types, for
809                          * now.  Tell our caller to read the next
810                          * record.
811                          */
812                         return 0;
813
814                 default:
815                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
816                         *err_info = g_strdup_printf("netmon: network type %u unknown or unsupported",
817                             network);
818                         return -1;      /* error */
819                 }
820         }
821
822         return pkt_encap;       /* success */
823 }
824
825 /* Throw away the frame table used by the sequential I/O stream. */
826 static void
827 netmon_sequential_close(wtap *wth)
828 {
829         netmon_t *netmon = (netmon_t *)wth->priv;
830
831         if (netmon->frame_table != NULL) {
832                 g_free(netmon->frame_table);
833                 netmon->frame_table = NULL;
834         }
835 }
836
837 typedef struct {
838         gboolean got_first_record_time;
839         struct wtap_nstime first_record_time;
840         guint32 frame_table_offset;
841         guint32 *frame_table;
842         guint   frame_table_index;
843         guint   frame_table_size;
844 } netmon_dump_t;
845
846 static const int wtap_encap[] = {
847         -1,             /* WTAP_ENCAP_UNKNOWN -> unsupported */
848         1,              /* WTAP_ENCAP_ETHERNET -> NDIS Ethernet */
849         2,              /* WTAP_ENCAP_TOKEN_RING -> NDIS Token Ring */
850         -1,             /* WTAP_ENCAP_SLIP -> unsupported */
851         -1,             /* WTAP_ENCAP_PPP -> unsupported */
852         3,              /* WTAP_ENCAP_FDDI -> NDIS FDDI */
853         3,              /* WTAP_ENCAP_FDDI_BITSWAPPED -> NDIS FDDI */
854         -1,             /* WTAP_ENCAP_RAW_IP -> unsupported */
855         -1,             /* WTAP_ENCAP_ARCNET -> unsupported */
856         -1,             /* WTAP_ENCAP_ATM_RFC1483 -> unsupported */
857         -1,             /* WTAP_ENCAP_LINUX_ATM_CLIP -> unsupported */
858         -1,             /* WTAP_ENCAP_LAPB -> unsupported*/
859         4,              /* WTAP_ENCAP_ATM_PDUS -> NDIS WAN (*NOT* ATM!) */
860         -1              /* WTAP_ENCAP_NULL -> unsupported */
861 };
862 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
863
864 /* Returns 0 if we could write the specified encapsulation type,
865    an error indication otherwise. */
866 int netmon_dump_can_write_encap(int encap)
867 {
868         /* Per-packet encapsulations aren't supported. */
869         if (encap == WTAP_ENCAP_PER_PACKET)
870                 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
871
872         if (encap < 0 || (unsigned) encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
873                 return WTAP_ERR_UNSUPPORTED_ENCAP;
874
875         return 0;
876 }
877
878 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
879    failure */
880 gboolean netmon_dump_open(wtap_dumper *wdh, int *err)
881 {
882         netmon_dump_t *netmon;
883
884         /* We can't fill in all the fields in the file header, as we
885            haven't yet written any packets.  As we'll have to rewrite
886            the header when we've written out all the packets, we just
887            skip over the header for now. */
888         if (fseek(wdh->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET) == -1) {
889                 *err = errno;
890                 return FALSE;
891         }
892
893         wdh->subtype_write = netmon_dump;
894         wdh->subtype_close = netmon_dump_close;
895
896         netmon = (netmon_dump_t *)g_malloc(sizeof(netmon_dump_t));
897         wdh->priv = (void *)netmon;
898         netmon->frame_table_offset = CAPTUREFILE_HEADER_SIZE;
899         netmon->got_first_record_time = FALSE;
900         netmon->frame_table = NULL;
901         netmon->frame_table_index = 0;
902         netmon->frame_table_size = 0;
903
904         return TRUE;
905 }
906
907 /* Write a record for a packet to a dump file.
908    Returns TRUE on success, FALSE on failure. */
909 static gboolean netmon_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
910     const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
911 {
912         netmon_dump_t *netmon = (netmon_dump_t *)wdh->priv;
913         struct netmonrec_1_x_hdr rec_1_x_hdr;
914         struct netmonrec_2_x_hdr rec_2_x_hdr;
915         char *hdrp;
916         size_t hdr_size;
917         double t;
918         guint32 time_low, time_high;
919         struct netmon_atm_hdr atm_hdr;
920         int atm_hdrsize;
921
922         /* NetMon files have a capture start time in the file header,
923            and have times relative to that in the packet headers;
924            pick the time of the first packet as the capture start
925            time. */
926         if (!netmon->got_first_record_time) {
927                 netmon->first_record_time = phdr->ts;
928                 netmon->got_first_record_time = TRUE;
929         }
930
931         if (wdh->encap == WTAP_ENCAP_ATM_PDUS)
932                 atm_hdrsize = sizeof (struct netmon_atm_hdr);
933         else
934                 atm_hdrsize = 0;
935         switch (wdh->file_type) {
936
937         case WTAP_FILE_NETMON_1_x:
938                 rec_1_x_hdr.ts_delta = htolel(
939                     (phdr->ts.secs - netmon->first_record_time.secs)*1000
940                   + (phdr->ts.nsecs - netmon->first_record_time.nsecs + 500000)/1000000);
941                 rec_1_x_hdr.orig_len = htoles(phdr->len + atm_hdrsize);
942                 rec_1_x_hdr.incl_len = htoles(phdr->caplen + atm_hdrsize);
943                 hdrp = (char *)&rec_1_x_hdr;
944                 hdr_size = sizeof rec_1_x_hdr;
945                 break;
946
947         case WTAP_FILE_NETMON_2_x:
948                 /*
949                  * Unfortunately, not all the platforms on which we run
950                  * support 64-bit integral types, even though most do
951                  * (even on 32-bit processors), so we do it in floating
952                  * point.
953                  */
954                 t = (phdr->ts.secs - netmon->first_record_time.secs)*1000000.0
955                   + (phdr->ts.nsecs - netmon->first_record_time.nsecs) / 1000;
956                 time_high = (guint32) (t/4294967296.0);
957                 time_low  = (guint32) (t - (time_high*4294967296.0));
958                 rec_2_x_hdr.ts_delta_lo = htolel(time_low);
959                 rec_2_x_hdr.ts_delta_hi = htolel(time_high);
960                 rec_2_x_hdr.orig_len = htolel(phdr->len + atm_hdrsize);
961                 rec_2_x_hdr.incl_len = htolel(phdr->caplen + atm_hdrsize);
962                 hdrp = (char *)&rec_2_x_hdr;
963                 hdr_size = sizeof rec_2_x_hdr;
964                 break;
965
966         default:
967                 /* We should never get here - our open routine
968                    should only get called for the types above. */
969                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
970                 return FALSE;
971         }
972
973         if (!wtap_dump_file_write(wdh, hdrp, hdr_size, err))
974                 return FALSE;
975
976         if (wdh->encap == WTAP_ENCAP_ATM_PDUS) {
977                 /*
978                  * Write the ATM header.
979                  * We supply all-zero destination and source addresses.
980                  */
981                 memset(&atm_hdr.dest, 0, sizeof atm_hdr.dest);
982                 memset(&atm_hdr.src, 0, sizeof atm_hdr.src);
983                 atm_hdr.vpi = g_htons(pseudo_header->atm.vpi);
984                 atm_hdr.vci = g_htons(pseudo_header->atm.vci);
985                 if (!wtap_dump_file_write(wdh, &atm_hdr, sizeof atm_hdr, err))
986                         return FALSE;
987         }
988
989         if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
990                 return FALSE;
991
992         /*
993          * Stash the file offset of this frame.
994          */
995         if (netmon->frame_table_size == 0) {
996                 /*
997                  * Haven't yet allocated the buffer for the frame table.
998                  */
999                 netmon->frame_table = g_malloc(1024 * sizeof *netmon->frame_table);
1000                 netmon->frame_table_size = 1024;
1001         } else {
1002                 /*
1003                  * We've allocated it; are we at the end?
1004                  */
1005                 if (netmon->frame_table_index >= netmon->frame_table_size) {
1006                         /*
1007                          * Yes - double the size of the frame table.
1008                          */
1009                         netmon->frame_table_size *= 2;
1010                         netmon->frame_table = g_realloc(netmon->frame_table,
1011                             netmon->frame_table_size * sizeof *netmon->frame_table);
1012                 }
1013         }
1014         netmon->frame_table[netmon->frame_table_index] =
1015             htolel(netmon->frame_table_offset);
1016         netmon->frame_table_index++;
1017         netmon->frame_table_offset += (int) hdr_size + phdr->caplen + atm_hdrsize;
1018
1019         return TRUE;
1020 }
1021
1022 /* Finish writing to a dump file.
1023    Returns TRUE on success, FALSE on failure. */
1024 static gboolean netmon_dump_close(wtap_dumper *wdh, int *err)
1025 {
1026         netmon_dump_t *netmon = (netmon_dump_t *)wdh->priv;
1027         size_t n_to_write;
1028         struct netmon_hdr file_hdr;
1029         const char *magicp;
1030         size_t magic_size;
1031         struct tm *tm;
1032
1033         /* Write out the frame table.  "netmon->frame_table_index" is
1034            the number of entries we've put into it. */
1035         n_to_write = netmon->frame_table_index * sizeof *netmon->frame_table;
1036         if (!wtap_dump_file_write(wdh, netmon->frame_table, n_to_write, err))
1037                 return FALSE;
1038
1039         /* Now go fix up the file header. */
1040         fseek(wdh->fh, 0, SEEK_SET);
1041         memset(&file_hdr, '\0', sizeof file_hdr);
1042         switch (wdh->file_type) {
1043
1044         case WTAP_FILE_NETMON_1_x:
1045                 magicp = netmon_1_x_magic;
1046                 magic_size = sizeof netmon_1_x_magic;
1047                 /* NetMon file version, for 1.x, is 1.1 */
1048                 file_hdr.ver_major = 1;
1049                 file_hdr.ver_minor = 1;
1050                 break;
1051
1052         case WTAP_FILE_NETMON_2_x:
1053                 magicp = netmon_2_x_magic;
1054                 magic_size = sizeof netmon_2_x_magic;
1055                 /*
1056                  * NetMon file version, for 2.x, is 2.0;
1057                  * for 3.0, it's 2.1.
1058                  */
1059                 file_hdr.ver_major = 2;
1060                 file_hdr.ver_minor = 0;
1061                 break;
1062
1063         default:
1064                 /* We should never get here - our open routine
1065                    should only get called for the types above. */
1066                 if (err != NULL)
1067                         *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1068                 return FALSE;
1069         }
1070         if (!wtap_dump_file_write(wdh, magicp, magic_size, err))
1071                 return FALSE;
1072
1073         file_hdr.network = htoles(wtap_encap[wdh->encap]);
1074         tm = localtime(&netmon->first_record_time.secs);
1075         if (tm != NULL) {
1076                 file_hdr.ts_year  = htoles(1900 + tm->tm_year);
1077                 file_hdr.ts_month = htoles(tm->tm_mon + 1);
1078                 file_hdr.ts_dow   = htoles(tm->tm_wday);
1079                 file_hdr.ts_day   = htoles(tm->tm_mday);
1080                 file_hdr.ts_hour  = htoles(tm->tm_hour);
1081                 file_hdr.ts_min   = htoles(tm->tm_min);
1082                 file_hdr.ts_sec   = htoles(tm->tm_sec);
1083         } else {
1084                 file_hdr.ts_year  = htoles(1900 + 0);
1085                 file_hdr.ts_month = htoles(0 + 1);
1086                 file_hdr.ts_dow   = htoles(0);
1087                 file_hdr.ts_day   = htoles(0);
1088                 file_hdr.ts_hour  = htoles(0);
1089                 file_hdr.ts_min   = htoles(0);
1090                 file_hdr.ts_sec   = htoles(0);
1091         }
1092         file_hdr.ts_msec  = htoles(netmon->first_record_time.nsecs/1000000);
1093                 /* XXX - what about rounding? */
1094         file_hdr.frametableoffset = htolel(netmon->frame_table_offset);
1095         file_hdr.frametablelength =
1096             htolel(netmon->frame_table_index * sizeof *netmon->frame_table);
1097         if (!wtap_dump_file_write(wdh, &file_hdr, sizeof file_hdr, err))
1098                 return FALSE;
1099
1100         return TRUE;
1101 }