6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "file_wrappers.h"
30 #include "pcap-encap.h"
35 * ftp://ftp.microsoft.com/developr/drg/cifs/cifs/Bhfile.zip
37 * contains "STRUCT.H", which declares the typedef CAPTUREFILE_HEADER
38 * for the header of a Microsoft Network Monitor 1.x capture file.
40 * The help files for Network Monitor 3.x document the 2.x file format.
43 /* Capture file header, *including* magic number, is padded to 128 bytes. */
44 #define CAPTUREFILE_HEADER_SIZE 128
46 /* Magic number size, for both 1.x and 2.x. */
49 /* Magic number in Network Monitor 1.x files. */
50 static const char netmon_1_x_magic[MAGIC_SIZE] = {
54 /* Magic number in Network Monitor 2.x files. */
55 static const char netmon_2_x_magic[MAGIC_SIZE] = {
59 /* Network Monitor file header (minus magic number). */
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 */
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 */
93 * Network Monitor 2.x record header, as documented in NetMon 3.x's
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 */
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.
107 * Some fields are multi-byte integers, but they're not aligned on their
108 * natural boundaries.
110 struct netmonrec_2_1_trlr {
111 guint8 network[2]; /* network type for this packet */
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 */
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 */
127 * The link-layer header on ATM packets.
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 */
139 guint8 version_major;
140 guint8 version_minor;
141 guint32 *frame_table;
142 guint32 frame_table_size;
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?
152 static const int netmon_encap[] = {
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 */
167 #define NUM_NETMON_ENCAPS (sizeof netmon_encap / sizeof netmon_encap[0])
170 * Special link-layer types.
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
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, guint8 *pd, 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 gboolean netmon_read_rec_data(FILE_T fh, guint8 *pd, int length,
188 int *err, gchar **err_info);
189 static int netmon_read_rec_trailer(FILE_T fh, int trlr_size, int *err,
191 static void netmon_sequential_close(wtap *wth);
192 static gboolean netmon_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
193 const guint8 *pd, int *err);
194 static gboolean netmon_dump_close(wtap_dumper *wdh, int *err);
196 int netmon_open(wtap *wth, int *err, gchar **err_info)
199 char magic[MAGIC_SIZE];
200 struct netmon_hdr hdr;
203 guint32 frame_table_offset;
204 guint32 frame_table_length;
205 guint32 frame_table_size;
206 guint32 *frame_table;
207 #ifdef WORDS_BIGENDIAN
212 /* Read in the string that should be at the start of a Network
214 errno = WTAP_ERR_CANT_READ;
215 bytes_read = file_read(magic, MAGIC_SIZE, wth->fh);
216 if (bytes_read != MAGIC_SIZE) {
217 *err = file_error(wth->fh, err_info);
218 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
223 if (memcmp(magic, netmon_1_x_magic, MAGIC_SIZE) != 0 &&
224 memcmp(magic, netmon_2_x_magic, MAGIC_SIZE) != 0) {
228 /* Read the rest of the header. */
229 errno = WTAP_ERR_CANT_READ;
230 bytes_read = file_read(&hdr, sizeof hdr, wth->fh);
231 if (bytes_read != sizeof hdr) {
232 *err = file_error(wth->fh, err_info);
234 *err = WTAP_ERR_SHORT_READ;
238 switch (hdr.ver_major) {
241 file_type = WTAP_FILE_NETMON_1_x;
245 file_type = WTAP_FILE_NETMON_2_x;
249 *err = WTAP_ERR_UNSUPPORTED;
250 *err_info = g_strdup_printf("netmon: major version %u unsupported", hdr.ver_major);
254 hdr.network = pletohs(&hdr.network);
255 if (hdr.network >= NUM_NETMON_ENCAPS
256 || netmon_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
257 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
258 *err_info = g_strdup_printf("netmon: network type %u unknown or unsupported",
263 /* This is a netmon file */
264 wth->file_type = file_type;
265 netmon = (netmon_t *)g_malloc(sizeof(netmon_t));
266 wth->priv = (void *)netmon;
267 wth->subtype_read = netmon_read;
268 wth->subtype_seek_read = netmon_seek_read;
269 wth->subtype_sequential_close = netmon_sequential_close;
271 /* NetMon capture file formats v2.1+ use per-packet encapsulation types. NetMon 3 sets the value in
272 * the header to 1 (Ethernet) for backwards compability. */
273 if((hdr.ver_major == 2 && hdr.ver_minor >= 1) || hdr.ver_major > 2)
274 wth->file_encap = WTAP_ENCAP_PER_PACKET;
276 wth->file_encap = netmon_encap[hdr.network];
278 wth->snapshot_length = 0; /* not available in header */
280 * Convert the time stamp to a "time_t" and a number of
283 tm.tm_year = pletohs(&hdr.ts_year) - 1900;
284 tm.tm_mon = pletohs(&hdr.ts_month) - 1;
285 tm.tm_mday = pletohs(&hdr.ts_day);
286 tm.tm_hour = pletohs(&hdr.ts_hour);
287 tm.tm_min = pletohs(&hdr.ts_min);
288 tm.tm_sec = pletohs(&hdr.ts_sec);
290 netmon->start_secs = mktime(&tm);
292 * XXX - what if "secs" is -1? Unlikely, but if the capture was
293 * done in a time zone that switches between standard and summer
294 * time sometime other than when we do, and thus the time was one
295 * that doesn't exist here because a switch from standard to summer
296 * time zips over it, it could happen.
298 * On the other hand, if the capture was done in a different time
299 * zone, this won't work right anyway; unfortunately, the time
300 * zone isn't stored in the capture file (why the hell didn't
301 * they stuff a FILETIME, which is the number of 100-nanosecond
302 * intervals since 1601-01-01 00:00:00 "UTC", there, instead
303 * of stuffing a SYSTEMTIME, which is time-zone-dependent, there?).
305 netmon->start_nsecs = pletohs(&hdr.ts_msec)*1000000;
307 netmon->version_major = hdr.ver_major;
308 netmon->version_minor = hdr.ver_minor;
311 * Get the offset of the frame index table.
313 frame_table_offset = pletohl(&hdr.frametableoffset);
316 * It appears that some NetMon 2.x files don't have the
317 * first packet starting exactly 128 bytes into the file.
319 * Furthermore, it also appears that there are "holes" in
320 * the file, i.e. frame N+1 doesn't always follow immediately
323 * Therefore, we must read the frame table, and use the offsets
324 * in it as the offsets of the frames.
326 frame_table_length = pletohl(&hdr.frametablelength);
327 frame_table_size = frame_table_length / (guint32)sizeof (guint32);
328 if ((frame_table_size * sizeof (guint32)) != frame_table_length) {
329 *err = WTAP_ERR_BAD_FILE;
330 *err_info = g_strdup_printf("netmon: frame table length is %u, which is not a multiple of the size of an entry",
334 if (frame_table_size == 0) {
335 *err = WTAP_ERR_BAD_FILE;
336 *err_info = g_strdup_printf("netmon: frame table length is %u, which means it's less than one entry in size",
341 * XXX - clamp the size of the frame table, so that we don't
342 * attempt to allocate a huge frame table and fail.
344 * Given that file offsets in the frame table are 32-bit,
345 * a NetMon file cannot be bigger than 2^32 bytes.
346 * Given that a NetMon 1.x-format packet header is 8 bytes,
347 * that means a NetMon file cannot have more than
348 * 512*2^20 packets. We'll pick that as the limit for
349 * now; it's 1/8th of a 32-bit address space, which is
350 * probably not going to exhaust the address space all by
351 * itself, and probably won't exhaust the backing store.
353 if (frame_table_size > 512*1024*1024) {
354 *err = WTAP_ERR_BAD_FILE;
355 *err_info = g_strdup_printf("netmon: frame table length is %u, which is larger than we support",
359 if (file_seek(wth->fh, frame_table_offset, SEEK_SET, err) == -1) {
362 frame_table = (guint32 *)g_try_malloc(frame_table_length);
363 if (frame_table_length != 0 && frame_table == NULL) {
364 *err = ENOMEM; /* we assume we're out of memory */
367 errno = WTAP_ERR_CANT_READ;
368 bytes_read = file_read(frame_table, frame_table_length, wth->fh);
369 if ((guint32)bytes_read != frame_table_length) {
370 *err = file_error(wth->fh, err_info);
372 *err = WTAP_ERR_SHORT_READ;
376 netmon->frame_table_size = frame_table_size;
377 netmon->frame_table = frame_table;
379 #ifdef WORDS_BIGENDIAN
381 * OK, now byte-swap the frame table.
383 for (i = 0; i < frame_table_size; i++)
384 frame_table[i] = pletohl(&frame_table[i]);
387 /* Set up to start reading at the first frame. */
388 netmon->current_frame = 0;
389 switch (netmon->version_major) {
393 * Version 1.x of the file format supports
394 * millisecond precision.
396 wth->tsprecision = WTAP_FILE_TSPREC_MSEC;
401 * Version 1.x of the file format supports
402 * 100-nanosecond precision; we don't
403 * currently support that, so say
404 * "nanosecond precision" for now.
406 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
413 netmon_trailer_size(netmon_t *netmon)
415 if ((netmon->version_major == 2 && netmon->version_minor >= 1) ||
416 netmon->version_major > 2) {
417 if (netmon->version_major > 2) {
419 * Asssume 2.3 format, for now.
421 return sizeof (struct netmonrec_2_3_trlr);
423 switch (netmon->version_minor) {
426 return sizeof (struct netmonrec_2_1_trlr);
429 return sizeof (struct netmonrec_2_2_trlr);
432 return sizeof (struct netmonrec_2_3_trlr);
436 return 0; /* no trailer */
440 netmon_set_pseudo_header_info(int pkt_encap,
441 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length)
445 case WTAP_ENCAP_ATM_PDUS:
447 * Attempt to guess from the packet data, the VPI, and
448 * the VCIinformation about the type of traffic.
450 atm_guess_traffic_type(pd, length, pseudo_header);
453 case WTAP_ENCAP_ETHERNET:
455 * We assume there's no FCS in this frame.
457 pseudo_header->eth.fcs_len = 0;
460 case WTAP_ENCAP_IEEE_802_11_NETMON:
462 * It appears to be the case that management
463 * frames have an FCS and data frames don't;
464 * I'm not sure about control frames. An
465 * "FCS length" of -2 means "NetMon weirdness".
467 pseudo_header->ieee_802_11.fcs_len = -2;
468 pseudo_header->ieee_802_11.decrypted = FALSE;
473 static gboolean netmon_process_rec_header(wtap *wth, FILE_T fh,
474 struct wtap_pkthdr *phdr, int *err, gchar **err_info)
476 netmon_t *netmon = (netmon_t *)wth->priv;
479 struct netmonrec_1_x_hdr hdr_1_x;
480 struct netmonrec_2_x_hdr hdr_2_x;
483 gint64 delta = 0; /* signed - frame times can be before the nominal start */
487 guint32 packet_size = 0;
488 guint32 orig_size = 0;
490 /* Read record header. */
491 switch (netmon->version_major) {
494 hdr_size = sizeof (struct netmonrec_1_x_hdr);
498 hdr_size = sizeof (struct netmonrec_2_x_hdr);
501 errno = WTAP_ERR_CANT_READ;
503 bytes_read = file_read(&hdr, hdr_size, fh);
504 if (bytes_read != hdr_size) {
505 *err = file_error(fh, err_info);
506 if (*err == 0 && bytes_read != 0) {
507 *err = WTAP_ERR_SHORT_READ;
512 switch (netmon->version_major) {
515 orig_size = pletohs(&hdr.hdr_1_x.orig_len);
516 packet_size = pletohs(&hdr.hdr_1_x.incl_len);
520 orig_size = pletohl(&hdr.hdr_2_x.orig_len);
521 packet_size = pletohl(&hdr.hdr_2_x.incl_len);
524 if (packet_size > WTAP_MAX_PACKET_SIZE) {
526 * Probably a corrupt capture file; don't blow up trying
527 * to allocate space for an immensely-large packet.
529 *err = WTAP_ERR_BAD_FILE;
530 *err_info = g_strdup_printf("netmon: File has %u-byte packet, bigger than maximum of %u",
531 packet_size, WTAP_MAX_PACKET_SIZE);
536 * If this is an ATM packet, the first
537 * "sizeof (struct netmon_atm_hdr)" bytes have destination and
538 * source addresses (6 bytes - MAC addresses of some sort?)
539 * and the VPI and VCI; read them and generate the pseudo-header
542 switch (wth->file_encap) {
544 case WTAP_ENCAP_ATM_PDUS:
545 if (packet_size < sizeof (struct netmon_atm_hdr)) {
547 * Uh-oh, the packet isn't big enough to even
548 * have a pseudo-header.
550 *err = WTAP_ERR_BAD_FILE;
551 *err_info = g_strdup_printf("netmon: ATM file has a %u-byte packet, too small to have even an ATM pseudo-header",
555 if (!netmon_read_atm_pseudoheader(fh, &phdr->pseudo_header,
557 return FALSE; /* Read error */
560 * Don't count the pseudo-header as part of the packet.
562 orig_size -= (guint)sizeof (struct netmon_atm_hdr);
563 packet_size -= (guint)sizeof (struct netmon_atm_hdr);
570 switch (netmon->version_major) {
574 * According to Paul Long, this offset is unsigned.
575 * It's 32 bits, so the maximum value will fit in
576 * a gint64 such as delta, even after multiplying
579 * pletohl() returns a guint32; we cast it to gint64
580 * before multiplying, so that the product doesn't
581 * overflow a guint32.
583 delta = ((gint64)pletohl(&hdr.hdr_1_x.ts_delta))*1000000;
588 * OK, this is weird. Microsoft's documentation
589 * says this is in microseconds and is a 64-bit
590 * unsigned number, but it can be negative; they
591 * say what appears to amount to "treat it as an
592 * unsigned number, multiply it by 10, and then
593 * interpret the resulting 64-bit quantity as a
594 * signed number". That operation can turn a
595 * value with the uppermost bit 0 to a value with
596 * the uppermost bit 1, hence turning a large
597 * positive number-of-microseconds into a small
598 * negative number-of-100-nanosecond-increments.
600 delta = pletohll(&hdr.hdr_2_x.ts_delta)*10;
603 * OK, it's now a signed value in 100-nanosecond
604 * units. Now convert it to nanosecond units.
610 t = netmon->start_nsecs + delta;
613 * Propagate a borrow into the seconds.
614 * The seconds is a time_t, and can be < 0
615 * (unlikely, as Windows didn't exist before
616 * January 1, 1970, 00:00:00 UTC), while the
617 * nanoseconds should be positive, as in
618 * "nanoseconds since the instant of time
619 * represented by the seconds".
621 * We do not want t to be negative, as, according
622 * to the C90 standard, "if either operand [of /
623 * or %] is negative, whether the result of the
624 * / operator is the largest integer less than or
625 * equal to the algebraic quotient or the smallest
626 * greater than or equal to the algebraic quotient
627 * is implementation-defined, as is the sign of
628 * the result of the % operator", and we want
629 * the result of the division and remainder
630 * operations to be the same on all platforms.
635 secs += (time_t)(t/1000000000);
636 nsecs = (guint32)(t%1000000000);
637 phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
638 phdr->ts.secs = netmon->start_secs + secs;
639 phdr->ts.nsecs = nsecs;
640 phdr->caplen = packet_size;
641 phdr->len = orig_size;
650 } process_trailer_retval;
652 static process_trailer_retval netmon_process_rec_trailer(netmon_t *netmon,
653 FILE_T fh, struct wtap_pkthdr *phdr, int *err, gchar **err_info)
657 trlr_size = (int)netmon_trailer_size(netmon);
658 if (trlr_size != 0) {
662 phdr->pkt_encap = netmon_read_rec_trailer(fh,
663 trlr_size, err, err_info);
664 if (phdr->pkt_encap == -1)
665 return FAILURE; /* error */
666 if (phdr->pkt_encap == 0)
673 /* Read the next packet */
674 static gboolean netmon_read(wtap *wth, int *err, gchar **err_info,
677 netmon_t *netmon = (netmon_t *)wth->priv;
682 /* Have we reached the end of the packet data? */
683 if (netmon->current_frame >= netmon->frame_table_size) {
684 /* Yes. We won't need the frame table any more;
686 g_free(netmon->frame_table);
687 netmon->frame_table = NULL;
688 *err = 0; /* it's just an EOF, not an error */
692 /* Seek to the beginning of the current record, if we're
693 not there already (seeking to the current position
694 may still cause a seek and a read of the underlying file,
695 so we don't want to do it unconditionally).
697 Yes, the current record could be before the previous
698 record. At least some captures put the trailer record
699 with statistics as the first physical record in the
700 file, but set the frame table up so it's the last
701 record in sequence. */
702 rec_offset = netmon->frame_table[netmon->current_frame];
703 if (file_tell(wth->fh) != rec_offset) {
704 if (file_seek(wth->fh, rec_offset, SEEK_SET, err) == -1)
707 netmon->current_frame++;
709 *data_offset = file_tell(wth->fh);
711 if (!netmon_process_rec_header(wth, wth->fh, &wth->phdr,
715 buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
716 data_ptr = buffer_start_ptr(wth->frame_buffer);
717 if (!netmon_read_rec_data(wth->fh, data_ptr, wth->phdr.caplen, err,
719 return FALSE; /* Read error */
722 * For version 2.1 and later, there's additional information
723 * after the frame data.
725 switch (netmon_process_rec_trailer(netmon, wth->fh, &wth->phdr,
738 netmon_set_pseudo_header_info(wth->phdr.pkt_encap,
739 &wth->phdr.pseudo_header, data_ptr, wth->phdr.caplen);
744 netmon_seek_read(wtap *wth, gint64 seek_off,
745 struct wtap_pkthdr *phdr, guint8 *pd, int length,
746 int *err, gchar **err_info)
748 netmon_t *netmon = (netmon_t *)wth->priv;
750 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
753 if (!netmon_process_rec_header(wth, wth->random_fh, phdr,
758 * Read the packet data.
760 if (!netmon_read_rec_data(wth->random_fh, pd, length, err, err_info))
764 * For version 2.1 and later, there's additional information
765 * after the frame data.
767 switch (netmon_process_rec_trailer(netmon, wth->random_fh, phdr,
772 * This should not happen.
774 *err = WTAP_ERR_BAD_FILE;
775 *err_info = g_strdup("netmon: saw metadata in netmon_seek_read");
785 netmon_set_pseudo_header_info(phdr->pkt_encap,
786 &phdr->pseudo_header, pd, phdr->caplen);
792 netmon_read_atm_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
793 int *err, gchar **err_info)
795 struct netmon_atm_hdr atm_phdr;
799 errno = WTAP_ERR_CANT_READ;
800 bytes_read = file_read(&atm_phdr, sizeof (struct netmon_atm_hdr), fh);
801 if (bytes_read != sizeof (struct netmon_atm_hdr)) {
802 *err = file_error(fh, err_info);
804 *err = WTAP_ERR_SHORT_READ;
808 vpi = g_ntohs(atm_phdr.vpi);
809 vci = g_ntohs(atm_phdr.vci);
811 pseudo_header->atm.vpi = vpi;
812 pseudo_header->atm.vci = vci;
814 /* We don't have this information */
815 pseudo_header->atm.flags = 0;
816 pseudo_header->atm.channel = 0;
817 pseudo_header->atm.cells = 0;
818 pseudo_header->atm.aal5t_u2u = 0;
819 pseudo_header->atm.aal5t_len = 0;
820 pseudo_header->atm.aal5t_chksum = 0;
826 netmon_read_rec_data(FILE_T fh, guint8 *pd, int length, int *err,
831 errno = WTAP_ERR_CANT_READ;
832 bytes_read = file_read(pd, length, fh);
834 if (bytes_read != length) {
835 *err = file_error(fh, err_info);
837 *err = WTAP_ERR_SHORT_READ;
844 * Read a record trailer.
845 * On success, returns the packet encapsulation type.
846 * On error, returns -1 (which is WTAP_ENCAP_PER_PACKET, but we'd
847 * never return that on success).
848 * For metadata packets, returns 0 (which is WTAP_ENCAP_UNKNOWN, but
849 * we'd never return that on success).
852 netmon_read_rec_trailer(FILE_T fh, int trlr_size, int *err, gchar **err_info)
856 struct netmonrec_2_1_trlr trlr_2_1;
857 struct netmonrec_2_2_trlr trlr_2_2;
858 struct netmonrec_2_3_trlr trlr_2_3;
863 errno = WTAP_ERR_CANT_READ;
864 bytes_read = file_read(&trlr, trlr_size, fh);
865 if (bytes_read != trlr_size) {
866 *err = file_error(fh, err_info);
867 if (*err == 0 && bytes_read != 0) {
868 *err = WTAP_ERR_SHORT_READ;
870 return -1; /* error */
873 network = pletohs(trlr.trlr_2_1.network);
874 if ((network & 0xF000) == NETMON_NET_PCAP_BASE) {
876 * Converted pcap file - the LINKTYPE_ value
877 * is the network value with 0xF000 masked off.
880 pkt_encap = wtap_pcap_encap_to_wtap_encap(network);
881 if (pkt_encap == WTAP_ENCAP_UNKNOWN) {
882 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
883 *err_info = g_strdup_printf("netmon: converted pcap network type %u unknown or unsupported",
885 return -1; /* error */
887 } else if (network < NUM_NETMON_ENCAPS) {
889 * Regular NetMon encapsulation.
891 pkt_encap = netmon_encap[network];
892 if (pkt_encap == WTAP_ENCAP_UNKNOWN) {
893 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
894 *err_info = g_strdup_printf("netmon: network type %u unknown or unsupported",
896 return -1; /* error */
900 * Special packet type for metadata.
904 case NETMON_NET_NETEVENT:
905 case NETMON_NET_NETWORK_INFO_EX:
906 case NETMON_NET_PAYLOAD_HEADER:
907 case NETMON_NET_NETWORK_INFO:
908 case NETMON_NET_DNS_CACHE:
909 case NETMON_NET_NETMON_FILTER:
911 * Just ignore those record types, for
912 * now. Tell our caller to read the next
918 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
919 *err_info = g_strdup_printf("netmon: network type %u unknown or unsupported",
921 return -1; /* error */
925 return pkt_encap; /* success */
928 /* Throw away the frame table used by the sequential I/O stream. */
930 netmon_sequential_close(wtap *wth)
932 netmon_t *netmon = (netmon_t *)wth->priv;
934 if (netmon->frame_table != NULL) {
935 g_free(netmon->frame_table);
936 netmon->frame_table = NULL;
941 gboolean got_first_record_time;
942 struct wtap_nstime first_record_time;
943 guint32 frame_table_offset;
944 guint32 *frame_table;
945 guint frame_table_index;
946 guint frame_table_size;
947 gboolean no_more_room; /* TRUE if no more records can be written */
950 static const int wtap_encap[] = {
951 -1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
952 1, /* WTAP_ENCAP_ETHERNET -> NDIS Ethernet */
953 2, /* WTAP_ENCAP_TOKEN_RING -> NDIS Token Ring */
954 -1, /* WTAP_ENCAP_SLIP -> unsupported */
955 -1, /* WTAP_ENCAP_PPP -> unsupported */
956 3, /* WTAP_ENCAP_FDDI -> NDIS FDDI */
957 3, /* WTAP_ENCAP_FDDI_BITSWAPPED -> NDIS FDDI */
958 -1, /* WTAP_ENCAP_RAW_IP -> unsupported */
959 -1, /* WTAP_ENCAP_ARCNET -> unsupported */
960 -1, /* WTAP_ENCAP_ARCNET_LINUX -> unsupported */
961 -1, /* WTAP_ENCAP_ATM_RFC1483 -> unsupported */
962 -1, /* WTAP_ENCAP_LINUX_ATM_CLIP -> unsupported */
963 -1, /* WTAP_ENCAP_LAPB -> unsupported*/
964 4, /* WTAP_ENCAP_ATM_PDUS -> NDIS WAN (*NOT* ATM!) */
966 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
968 /* Returns 0 if we could write the specified encapsulation type,
969 an error indication otherwise. */
970 int netmon_dump_can_write_encap_1_x(int encap)
973 * Per-packet encapsulations are *not* supported in NetMon 1.x
976 if (encap < 0 || (unsigned) encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
977 return WTAP_ERR_UNSUPPORTED_ENCAP;
982 int netmon_dump_can_write_encap_2_x(int encap)
985 * Per-packet encapsulations are supported in NetMon 2.1
988 if (encap == WTAP_ENCAP_PER_PACKET)
991 if (encap < 0 || (unsigned) encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
992 return WTAP_ERR_UNSUPPORTED_ENCAP;
997 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
999 gboolean netmon_dump_open(wtap_dumper *wdh, int *err)
1001 netmon_dump_t *netmon;
1003 /* We can't fill in all the fields in the file header, as we
1004 haven't yet written any packets. As we'll have to rewrite
1005 the header when we've written out all the packets, we just
1006 skip over the header for now. */
1007 if (wtap_dump_file_seek(wdh, CAPTUREFILE_HEADER_SIZE, SEEK_SET, err) == -1)
1010 wdh->subtype_write = netmon_dump;
1011 wdh->subtype_close = netmon_dump_close;
1013 netmon = (netmon_dump_t *)g_malloc(sizeof(netmon_dump_t));
1014 wdh->priv = (void *)netmon;
1015 netmon->frame_table_offset = CAPTUREFILE_HEADER_SIZE;
1016 netmon->got_first_record_time = FALSE;
1017 netmon->frame_table = NULL;
1018 netmon->frame_table_index = 0;
1019 netmon->frame_table_size = 0;
1020 netmon->no_more_room = FALSE;
1025 /* Write a record for a packet to a dump file.
1026 Returns TRUE on success, FALSE on failure. */
1027 static gboolean netmon_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1028 const guint8 *pd, int *err)
1030 const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
1031 netmon_dump_t *netmon = (netmon_dump_t *)wdh->priv;
1032 struct netmonrec_1_x_hdr rec_1_x_hdr;
1033 struct netmonrec_2_x_hdr rec_2_x_hdr;
1036 struct netmonrec_2_1_trlr rec_2_x_trlr;
1038 struct netmon_atm_hdr atm_hdr;
1043 if (wdh->encap == WTAP_ENCAP_PER_PACKET) {
1045 * Is this network type supported?
1047 if (phdr->pkt_encap < 0 ||
1048 (unsigned) phdr->pkt_encap >= NUM_WTAP_ENCAPS ||
1049 wtap_encap[phdr->pkt_encap] == -1) {
1053 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
1058 * Fill in the trailer with the network type.
1060 phtoles(rec_2_x_trlr.network, wtap_encap[phdr->pkt_encap]);
1064 * Will the file offset of this frame fit in a 32-bit unsigned
1067 if (netmon->no_more_room) {
1069 * No, so the file is too big for NetMon format to
1077 * NetMon files have a capture start time in the file header,
1078 * and have times relative to that in the packet headers;
1079 * pick the time of the first packet as the capture start
1082 * That time has millisecond resolution, so chop any
1083 * sub-millisecond part of the time stamp off.
1085 if (!netmon->got_first_record_time) {
1086 netmon->first_record_time.secs = phdr->ts.secs;
1087 netmon->first_record_time.nsecs =
1088 (phdr->ts.nsecs/1000000)*1000000;
1089 netmon->got_first_record_time = TRUE;
1092 if (wdh->encap == WTAP_ENCAP_ATM_PDUS)
1093 atm_hdrsize = sizeof (struct netmon_atm_hdr);
1096 secs = (gint64)(phdr->ts.secs - netmon->first_record_time.secs);
1097 nsecs = phdr->ts.nsecs - netmon->first_record_time.nsecs;
1100 * Propagate a borrow into the seconds.
1101 * The seconds is a time_t, and can be < 0
1102 * (unlikely, as neither UN*X nor DOS
1103 * nor the original Mac System existed
1104 * before January 1, 1970, 00:00:00 UTC),
1105 * while the nanoseconds should be positive,
1106 * as in "nanoseconds since the instant of time
1107 * represented by the seconds".
1109 * We do not want t to be negative, as, according
1110 * to the C90 standard, "if either operand [of /
1111 * or %] is negative, whether the result of the
1112 * / operator is the largest integer less than or
1113 * equal to the algebraic quotient or the smallest
1114 * greater than or equal to the algebraic quotient
1115 * is implementation-defined, as is the sign of
1116 * the result of the % operator", and we want
1117 * the result of the division and remainder
1118 * operations to be the same on all platforms.
1120 nsecs += 1000000000;
1123 switch (wdh->file_type) {
1125 case WTAP_FILE_NETMON_1_x:
1126 rec_1_x_hdr.ts_delta = htolel(secs*1000 + (nsecs + 500000)/1000000);
1127 rec_1_x_hdr.orig_len = htoles(phdr->len + atm_hdrsize);
1128 rec_1_x_hdr.incl_len = htoles(phdr->caplen + atm_hdrsize);
1129 hdrp = &rec_1_x_hdr;
1130 hdr_size = sizeof rec_1_x_hdr;
1133 case WTAP_FILE_NETMON_2_x:
1134 rec_2_x_hdr.ts_delta = htolell(secs*1000000 + (nsecs + 500)/1000);
1135 rec_2_x_hdr.orig_len = htolel(phdr->len + atm_hdrsize);
1136 rec_2_x_hdr.incl_len = htolel(phdr->caplen + atm_hdrsize);
1137 hdrp = &rec_2_x_hdr;
1138 hdr_size = sizeof rec_2_x_hdr;
1142 /* We should never get here - our open routine
1143 should only get called for the types above. */
1144 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1149 * Keep track of the record size, as we need to update
1150 * the current file offset.
1154 if (!wtap_dump_file_write(wdh, hdrp, hdr_size, err))
1156 rec_size += hdr_size;
1158 if (wdh->encap == WTAP_ENCAP_ATM_PDUS) {
1160 * Write the ATM header.
1161 * We supply all-zero destination and source addresses.
1163 memset(&atm_hdr.dest, 0, sizeof atm_hdr.dest);
1164 memset(&atm_hdr.src, 0, sizeof atm_hdr.src);
1165 atm_hdr.vpi = g_htons(pseudo_header->atm.vpi);
1166 atm_hdr.vci = g_htons(pseudo_header->atm.vci);
1167 if (!wtap_dump_file_write(wdh, &atm_hdr, sizeof atm_hdr, err))
1169 rec_size += sizeof atm_hdr;
1172 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
1174 rec_size += phdr->caplen;
1176 if (wdh->encap == WTAP_ENCAP_PER_PACKET) {
1178 * Write out the trailer.
1180 if (!wtap_dump_file_write(wdh, &rec_2_x_trlr,
1181 sizeof rec_2_x_trlr, err))
1183 rec_size += sizeof rec_2_x_trlr;
1187 * Stash the file offset of this frame.
1189 if (netmon->frame_table_size == 0) {
1191 * Haven't yet allocated the buffer for the frame table.
1193 netmon->frame_table = (guint32 *)g_malloc(1024 * sizeof *netmon->frame_table);
1194 netmon->frame_table_size = 1024;
1197 * We've allocated it; are we at the end?
1199 if (netmon->frame_table_index >= netmon->frame_table_size) {
1201 * Yes - double the size of the frame table.
1203 netmon->frame_table_size *= 2;
1204 netmon->frame_table = (guint32 *)g_realloc(netmon->frame_table,
1205 netmon->frame_table_size * sizeof *netmon->frame_table);
1209 netmon->frame_table[netmon->frame_table_index] =
1210 htolel(netmon->frame_table_offset);
1213 * Is this the last record we can write?
1214 * I.e., will the frame table offset of the next record not fit
1215 * in a 32-bit frame table offset entry?
1217 * (We don't bother checking whether the number of frames
1218 * will fit in a 32-bit value, as, even if each record were
1219 * 1 byte, if there were more than 2^32-1 packets, the frame
1220 * table offset of at least one of those packets will be >
1223 * Note: this also catches the unlikely possibility that
1224 * the record itself is > 2^32 - 1 bytes long.
1226 if ((guint64)netmon->frame_table_offset + rec_size > G_MAXUINT32) {
1230 netmon->no_more_room = TRUE;
1232 netmon->frame_table_index++;
1233 netmon->frame_table_offset += (guint32) rec_size;
1238 /* Finish writing to a dump file.
1239 Returns TRUE on success, FALSE on failure. */
1240 static gboolean netmon_dump_close(wtap_dumper *wdh, int *err)
1242 netmon_dump_t *netmon = (netmon_dump_t *)wdh->priv;
1244 struct netmon_hdr file_hdr;
1249 /* Write out the frame table. "netmon->frame_table_index" is
1250 the number of entries we've put into it. */
1251 n_to_write = netmon->frame_table_index * sizeof *netmon->frame_table;
1252 if (!wtap_dump_file_write(wdh, netmon->frame_table, n_to_write, err))
1255 /* Now go fix up the file header. */
1256 if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1)
1258 memset(&file_hdr, '\0', sizeof file_hdr);
1259 switch (wdh->file_type) {
1261 case WTAP_FILE_NETMON_1_x:
1262 magicp = netmon_1_x_magic;
1263 magic_size = sizeof netmon_1_x_magic;
1264 /* NetMon file version, for 1.x, is 1.1 */
1265 file_hdr.ver_major = 1;
1266 file_hdr.ver_minor = 1;
1269 case WTAP_FILE_NETMON_2_x:
1270 magicp = netmon_2_x_magic;
1271 magic_size = sizeof netmon_2_x_magic;
1273 * NetMon file version, for 2.x, is 2.0;
1274 * for 3.0, it's 2.1.
1276 * If the file encapsulation is WTAP_ENCAP_PER_PACKET,
1277 * we need version 2.1.
1279 * XXX - version 2.3 supports UTC time stamps; when
1280 * should we use it? According to the file format
1281 * documentation, NetMon 3.3 "cannot properly
1282 * interpret" the UTC timestamp information; does
1283 * that mean it ignores it and uses the local-time
1284 * start time and time deltas, or mishandles them?
1285 * Also, NetMon 3.1 and earlier can't read version
1286 * 2.2, much less version 2.3.
1288 file_hdr.ver_major = 2;
1289 file_hdr.ver_minor =
1290 (wdh->encap == WTAP_ENCAP_PER_PACKET) ? 1 : 0;
1294 /* We should never get here - our open routine
1295 should only get called for the types above. */
1297 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
1300 if (!wtap_dump_file_write(wdh, magicp, magic_size, err))
1303 if (wdh->encap == WTAP_ENCAP_PER_PACKET) {
1305 * We're writing NetMon 2.1 format, so the media
1306 * type in the file header is irrelevant. Set it
1307 * to 1, just as Network Monitor does.
1309 file_hdr.network = htoles(1);
1311 file_hdr.network = htoles(wtap_encap[wdh->encap]);
1312 tm = localtime(&netmon->first_record_time.secs);
1314 file_hdr.ts_year = htoles(1900 + tm->tm_year);
1315 file_hdr.ts_month = htoles(tm->tm_mon + 1);
1316 file_hdr.ts_dow = htoles(tm->tm_wday);
1317 file_hdr.ts_day = htoles(tm->tm_mday);
1318 file_hdr.ts_hour = htoles(tm->tm_hour);
1319 file_hdr.ts_min = htoles(tm->tm_min);
1320 file_hdr.ts_sec = htoles(tm->tm_sec);
1322 file_hdr.ts_year = htoles(1900 + 0);
1323 file_hdr.ts_month = htoles(0 + 1);
1324 file_hdr.ts_dow = htoles(0);
1325 file_hdr.ts_day = htoles(0);
1326 file_hdr.ts_hour = htoles(0);
1327 file_hdr.ts_min = htoles(0);
1328 file_hdr.ts_sec = htoles(0);
1330 file_hdr.ts_msec = htoles(netmon->first_record_time.nsecs/1000000);
1331 file_hdr.frametableoffset = htolel(netmon->frame_table_offset);
1332 file_hdr.frametablelength =
1333 htolel(netmon->frame_table_index * sizeof *netmon->frame_table);
1334 if (!wtap_dump_file_write(wdh, &file_hdr, sizeof file_hdr, err))