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