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