From Hans-Christoph Schemmel:
[obnox/wireshark/wip.git] / wiretap / snoop.c
1 /* snoop.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <errno.h>
27 #include <string.h>
28 #include "wtap-int.h"
29 #include "file_wrappers.h"
30 #include "buffer.h"
31 #include "atm.h"
32 #include "snoop.h"
33 /* See RFC 1761 for a description of the "snoop" file format. */
34
35 /* Magic number in "snoop" files. */
36 static const char snoop_magic[] = {
37         's', 'n', 'o', 'o', 'p', '\0', '\0', '\0'
38 };
39
40 /* "snoop" file header (minus magic number). */
41 struct snoop_hdr {
42         guint32 version;        /* version number (should be 2) */
43         guint32 network;        /* network type */
44 };
45
46 /* "snoop" record header. */
47 struct snooprec_hdr {
48         guint32 orig_len;       /* actual length of packet */
49         guint32 incl_len;       /* number of octets captured in file */
50         guint32 rec_len;        /* length of record */
51         guint32 cum_drops;      /* cumulative number of dropped packets */
52         guint32 ts_sec;         /* timestamp seconds */
53         guint32 ts_usec;        /* timestamp microseconds */
54 };
55
56 /*
57  * The link-layer header on ATM packets.
58  */
59 struct snoop_atm_hdr {
60         guint8  flags;          /* destination and traffic type */
61         guint8  vpi;            /* VPI */
62         guint16 vci;            /* VCI */
63 };
64
65 /*
66  * Extra information stuffed into the padding in Shomiti/Finisar Surveyor
67  * captures.
68  */
69 struct shomiti_trailer {
70         guint16 phy_rx_length;  /* length on the wire, including FCS? */
71         guint16 phy_rx_status;  /* status flags */
72         guint32 ts_40_ns_lsb;   /* 40 ns time stamp, low-order bytes? */
73         guint32 ts_40_ns_msb;   /* 40 ns time stamp, low-order bytes? */
74         gint32  frame_id;       /* "FrameID"? */
75 };
76
77 /*
78  * phy_rx_status flags.
79  */
80 #define RX_STATUS_OVERFLOW              0x8000  /* overflow error */
81 #define RX_STATUS_BAD_CRC               0x4000  /* CRC error */
82 #define RX_STATUS_DRIBBLE_NIBBLE        0x2000  /* dribble/nibble bits? */
83 #define RX_STATUS_SHORT_FRAME           0x1000  /* frame < 64 bytes */
84 #define RX_STATUS_OVERSIZE_FRAME        0x0800  /* frame > 1518 bytes */
85 #define RX_STATUS_GOOD_FRAME            0x0400  /* frame OK */
86 #define RX_STATUS_N12_BYTES_RECEIVED    0x0200  /* first 12 bytes of frame received? */
87 #define RX_STATUS_RXABORT               0x0100  /* RXABORT during reception */
88 #define RX_STATUS_FIFO_ERROR            0x0080  /* receive FIFO error */
89 #define RX_STATUS_TRIGGERED             0x0001  /* frame did trigger */
90
91 static gboolean snoop_read(wtap *wth, int *err, gchar **err_info,
92     gint64 *data_offset);
93 static gboolean snoop_seek_read(wtap *wth, gint64 seek_off,
94     union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
95     int *err, gchar **err_info);
96 static gboolean snoop_read_atm_pseudoheader(FILE_T fh,
97     union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
98 static gboolean snoop_read_shomiti_wireless_pseudoheader(FILE_T fh,
99     union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info,
100     int *header_size);
101 static gboolean snoop_read_rec_data(FILE_T fh, guchar *pd, int length,
102     int *err, gchar **err_info);
103 static gboolean snoop_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
104     const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
105
106 /*
107  * See
108  *
109  *      http://www.opengroup.org/onlinepubs/9638599/apdxf.htm
110  *
111  * for the "dlpi.h" header file specified by The Open Group, which lists
112  * the DL_ values for various protocols; Solaris 7 uses the same values.
113  *
114  * The page at
115  *
116  *      http://mrpink.lerc.nasa.gov/118x/support.html
117  *
118  * had links to modified versions of "tcpdump" and "libpcap" for SUNatm
119  * DLPI support; they suggested that the 3.0 verson of SUNatm uses those
120  * values.  The Wayback Machine archived that page, but not the stuff
121  * to which it linked, unfortunately.
122  *
123  * It also has a link to "convert.c", which is a program to convert files
124  * from the format written by the "atmsnoop" program that comes with the
125  * SunATM package to regular "snoop" format, claims that "SunATM 2.1 claimed
126  * to be DL_FDDI (don't ask why).  SunATM 3.0 claims to be DL_IPATM, which
127  * is 0x12".
128  *
129  * It also says that "ATM Mac header is 12 bytes long.", and seems to imply
130  * that in an "atmsnoop" file, the header contains 2 bytes (direction and
131  * VPI?), 2 bytes of VCI, 6 bytes of something, and 2 bytes of Ethernet
132  * type; if those 6 bytes are 2 bytes of DSAP, 2 bytes of LSAP, 1 byte
133  * of LLC control, and 3 bytes of SNAP OUI, that'd mean that an ATM
134  * pseudo-header in an "atmsnoop" file is probably 1 byte of direction,
135  * 1 byte of VPI, and 2 bytes of VCI.
136  *
137  * The aforementioned page also has a link to some capture files from
138  * "atmsnoop"; this version of "snoop.c" appears to be able to read them.
139  *
140  * Source to an "atmdump" package, which includes a modified version of
141  * "libpcap" to handle SunATM DLPI and an ATM driver for FreeBSD, and
142  * also includes "atmdump", which is a modified "tcpdump", is available
143  * at
144  *
145  *      ftp://ftp.cs.ndsu.nodak.edu/pub/freebsd/atm/atm-bpf.tgz
146  *
147  * and that code also indicates that DL_IPATM is used, and that an
148  * ATM packet handed up from the Sun driver for the Sun SBus ATM card on
149  * Solaris 2.5.1 has 1 byte of direction, 1 byte of VPI, 2 bytes of VCI,
150  * and then the ATM PDU, and suggests that the direction flag is 0x80 for
151  * "transmitted" (presumably meaning DTE->DCE) and presumably not 0x80 for
152  * "received" (presumably meaning DCE->DTE).  That code was used as the
153  * basis for the SunATM support in current CVS versions of libpcap and
154  * tcpdump, and it works.
155  *
156  * In fact, the "direction" byte appears to have some other stuff, perhaps
157  * a traffic type, in the lower 7 bits, with the 8th bit indicating the
158  * direction.  That appears to be the case.
159  *
160  * I don't know what the encapsulation of any of the other types is, so I
161  * leave them all as WTAP_ENCAP_UNKNOWN, except for those for which Brian
162  * Ginsbach has supplied information about the way UNICOS/mp uses them.
163  * I also don't know whether "snoop" can handle any of them (it presumably
164  * can't handle ATM, otherwise Sun wouldn't have supplied "atmsnoop"; even
165  * if it can't, this may be useful reference information for anybody doing
166  * code to use DLPI to do raw packet captures on those network types.
167  *
168  * See
169  *
170  *      http://web.archive.org/web/20010906213807/http://www.shomiti.com/support/TNCapFileFormat.htm
171  *
172  * for information on Shomiti's mutant flavor of snoop.  For some unknown
173  * unknown reason, they decided not to just Go With The DLPI Flow, and
174  * instead used the types unspecified in RFC 1461 for their own nefarious
175  * purposes, such as distinguishing 10MB from 100MB from 1000MB Ethernet
176  * and distinguishing 4MB from 16MB Token Ring, and distinguishing both
177  * of them from the "Shomiti" versions of same.
178  */
179 int snoop_open(wtap *wth, int *err, gchar **err_info)
180 {
181         int bytes_read;
182         char magic[sizeof snoop_magic];
183         struct snoop_hdr hdr;
184         struct snooprec_hdr rec_hdr;
185         guint padbytes;
186         gboolean is_shomiti;
187         static const int snoop_encap[] = {
188                 WTAP_ENCAP_ETHERNET,    /* IEEE 802.3 */
189                 WTAP_ENCAP_UNKNOWN,     /* IEEE 802.4 Token Bus */
190                 WTAP_ENCAP_TOKEN_RING,
191                 WTAP_ENCAP_UNKNOWN,     /* IEEE 802.6 Metro Net */
192                 WTAP_ENCAP_ETHERNET,
193                 WTAP_ENCAP_UNKNOWN,     /* HDLC */
194                 WTAP_ENCAP_UNKNOWN,     /* Character Synchronous, e.g. bisync */
195                 WTAP_ENCAP_UNKNOWN,     /* IBM Channel-to-Channel */
196                 WTAP_ENCAP_FDDI_BITSWAPPED,
197                 WTAP_ENCAP_NULL,        /* Other */
198                 WTAP_ENCAP_UNKNOWN,     /* Frame Relay LAPF */
199                 WTAP_ENCAP_UNKNOWN,     /* Multi-protocol over Frame Relay */
200                 WTAP_ENCAP_UNKNOWN,     /* Character Async (e.g., SLIP and PPP?) */
201                 WTAP_ENCAP_UNKNOWN,     /* X.25 Classical IP */
202                 WTAP_ENCAP_NULL,        /* software loopback */
203                 WTAP_ENCAP_UNKNOWN,     /* not defined in "dlpi.h" */
204                 WTAP_ENCAP_IP_OVER_FC,  /* Fibre Channel */
205                 WTAP_ENCAP_UNKNOWN,     /* ATM */
206                 WTAP_ENCAP_ATM_PDUS,    /* ATM Classical IP */
207                 WTAP_ENCAP_UNKNOWN,     /* X.25 LAPB */
208                 WTAP_ENCAP_UNKNOWN,     /* ISDN */
209                 WTAP_ENCAP_UNKNOWN,     /* HIPPI */
210                 WTAP_ENCAP_UNKNOWN,     /* 100VG-AnyLAN Ethernet */
211                 WTAP_ENCAP_UNKNOWN,     /* 100VG-AnyLAN Token Ring */
212                 WTAP_ENCAP_UNKNOWN,     /* "ISO 8802/3 and Ethernet" */
213                 WTAP_ENCAP_UNKNOWN,     /* 100BaseT (but that's just Ethernet) */
214         };
215         #define NUM_SNOOP_ENCAPS (sizeof snoop_encap / sizeof snoop_encap[0])
216         #define SNOOP_PRIVATE_BIT 0x80000000
217         static const int snoop_private_encap[] = {
218                 WTAP_ENCAP_UNKNOWN,     /* Not Used */
219                 WTAP_ENCAP_UNKNOWN,     /* IPv4 Tunnel Link */
220                 WTAP_ENCAP_UNKNOWN,     /* IPv6 Tunnel Link */
221                 WTAP_ENCAP_UNKNOWN,     /* Virtual network interface */
222                 WTAP_ENCAP_UNKNOWN,     /* IEEE 802.11 */
223                 WTAP_ENCAP_IPNET,       /* ipnet(7D) link */
224                 WTAP_ENCAP_UNKNOWN,     /* IPMP stub interface */
225                 WTAP_ENCAP_UNKNOWN,     /* 6to4 Tunnel Link */
226         };
227         #define NUM_SNOOP_PRIVATE_ENCAPS (sizeof snoop_private_encap / sizeof snoop_private_encap[0])
228         static const int shomiti_encap[] = {
229                 WTAP_ENCAP_ETHERNET,    /* IEEE 802.3 */
230                 WTAP_ENCAP_UNKNOWN,     /* IEEE 802.4 Token Bus */
231                 WTAP_ENCAP_TOKEN_RING,
232                 WTAP_ENCAP_UNKNOWN,     /* IEEE 802.6 Metro Net */
233                 WTAP_ENCAP_ETHERNET,
234                 WTAP_ENCAP_UNKNOWN,     /* HDLC */
235                 WTAP_ENCAP_UNKNOWN,     /* Character Synchronous, e.g. bisync */
236                 WTAP_ENCAP_UNKNOWN,     /* IBM Channel-to-Channel */
237                 WTAP_ENCAP_FDDI_BITSWAPPED,
238                 WTAP_ENCAP_UNKNOWN,     /* Other */
239                 WTAP_ENCAP_ETHERNET,    /* Fast Ethernet */
240                 WTAP_ENCAP_TOKEN_RING,  /* 4MB 802.5 token ring */
241                 WTAP_ENCAP_ETHERNET,    /* Gigabit Ethernet */
242                 WTAP_ENCAP_TOKEN_RING,  /* "IEEE 802.5 Shomiti" */
243                 WTAP_ENCAP_TOKEN_RING,  /* "4MB IEEE 802.5 Shomiti" */
244                 WTAP_ENCAP_UNKNOWN,     /* Other */
245                 WTAP_ENCAP_UNKNOWN,     /* Other */
246                 WTAP_ENCAP_UNKNOWN,     /* Other */
247                 WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
248         };
249         #define NUM_SHOMITI_ENCAPS (sizeof shomiti_encap / sizeof shomiti_encap[0])
250         int file_encap;
251
252         /* Read in the string that should be at the start of a "snoop" file */
253         errno = WTAP_ERR_CANT_READ;
254         bytes_read = file_read(magic, sizeof magic, wth->fh);
255         if (bytes_read != sizeof magic) {
256                 *err = file_error(wth->fh, err_info);
257                 if (*err != 0)
258                         return -1;
259                 return 0;
260         }
261         wth->data_offset += sizeof magic;
262
263         if (memcmp(magic, snoop_magic, sizeof snoop_magic) != 0) {
264                 return 0;
265         }
266
267         /* Read the rest of the header. */
268         errno = WTAP_ERR_CANT_READ;
269         bytes_read = file_read(&hdr, sizeof hdr, wth->fh);
270         if (bytes_read != sizeof hdr) {
271                 *err = file_error(wth->fh, err_info);
272                 if (*err != 0)
273                         return -1;
274                 return 0;
275         }
276         wth->data_offset += sizeof hdr;
277
278         /*
279          * Make sure it's a version we support.
280          */
281         hdr.version = g_ntohl(hdr.version);
282         switch (hdr.version) {
283
284         case 2:         /* Solaris 2.x and later snoop, and Shomiti
285                            Surveyor prior to 3.0, or 3.0 and later
286                            with NDIS card */
287         case 3:         /* Surveyor 3.0 and later, with Shomiti CMM2 hardware */
288         case 4:         /* Surveyor 3.0 and later, with Shomiti GAM hardware */
289         case 5:         /* Surveyor 3.0 and later, with Shomiti THG hardware */
290                 break;
291
292         default:
293                 *err = WTAP_ERR_UNSUPPORTED;
294                 *err_info = g_strdup_printf("snoop: version %u unsupported", hdr.version);
295                 return -1;
296         }
297
298         /*
299          * Oh, this is lovely.
300          *
301          * I suppose Shomiti could give a bunch of lawyerly noise about
302          * how "well, RFC 1761 said they were unassigned, and that's
303          * the standard, not the DLPI header file, so it's perfectly OK
304          * for us to use them, blah blah blah", but it's still irritating
305          * as hell that they used the unassigned-in-RFC-1761 values for
306          * their own purposes - especially given that Sun also used
307          * one of them in atmsnoop.
308          *
309          * We can't determine whether it's a Shomiti capture based on
310          * the version number, as, according to their documentation on
311          * their capture file format, Shomiti uses a version number of 2
312          * if the data "was captured using an NDIS card", which presumably
313          * means "captured with an ordinary boring network card via NDIS"
314          * as opposed to "captured with our whizzo special capture
315          * hardware".
316          *
317          * The only way I can see to determine that is to check how much
318          * padding there is in the first packet - if there's enough
319          * padding for a Shomiti trailer, it's probably a Shomiti
320          * capture, and otherwise, it's probably from Snoop.
321          */
322
323         /*
324          * Start out assuming it's not a Shomiti capture.
325          */
326         is_shomiti = FALSE;
327
328         /* Read first record header. */
329         errno = WTAP_ERR_CANT_READ;
330         bytes_read = file_read(&rec_hdr, sizeof rec_hdr, wth->fh);
331         if (bytes_read != sizeof rec_hdr) {
332                 *err = file_error(wth->fh, err_info);
333                 if (*err == 0 && bytes_read != 0)
334                         *err = WTAP_ERR_SHORT_READ;
335                 if (*err != 0) {
336                         /*
337                          * A real-live error.
338                          */
339                         return -1;
340                 }
341
342                 /*
343                  * The file ends after the record header, which means this
344                  * is a capture with no packets.
345                  *
346                  * We assume it's a snoop file; the actual type of file is
347                  * irrelevant, as there are no records in it, and thus no
348                  * extra information if it's a Shomiti capture, and no
349                  * link-layer headers whose type we have to know, and no
350                  * Ethernet frames that might have an FCS.
351                  */
352         } else {
353                 /*
354                  * Compute the number of bytes of padding in the
355                  * record.  If it's at least the size of a Shomiti
356                  * trailer record, we assume this is a Shomiti
357                  * capture.  (Some atmsnoop captures appear
358                  * to have 4 bytes of padding, and at least one
359                  * snoop capture appears to have 6 bytes of padding;
360                  * the Shomiti header is larger than either of those.)
361                  */
362                 if (g_ntohl(rec_hdr.rec_len) >
363                     (sizeof rec_hdr + g_ntohl(rec_hdr.incl_len))) {
364                         /*
365                          * Well, we have padding; how much?
366                          */
367                         padbytes = g_ntohl(rec_hdr.rec_len) -
368                             ((guint)sizeof rec_hdr + g_ntohl(rec_hdr.incl_len));
369
370                         /*
371                          * Is it at least the size of a Shomiti trailer?
372                          */
373                         is_shomiti =
374                             (padbytes >= sizeof (struct shomiti_trailer));
375                 }
376         }
377
378         /*
379          * Seek back to the beginning of the first record.
380          */
381         if (file_seek(wth->fh, wth->data_offset, SEEK_SET, err) == -1)
382                 return -1;
383
384         hdr.network = g_ntohl(hdr.network);
385         if (is_shomiti) {
386                 if (hdr.network >= NUM_SHOMITI_ENCAPS
387                     || shomiti_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
388                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
389                         *err_info = g_strdup_printf("snoop: Shomiti network type %u unknown or unsupported",
390                             hdr.network);
391                         return -1;
392                 }
393                 file_encap = shomiti_encap[hdr.network];
394
395                 /* This is a Shomiti file */
396                 wth->file_type = WTAP_FILE_SHOMITI;
397         } else if (hdr.network & SNOOP_PRIVATE_BIT) {
398                 if ((hdr.network^SNOOP_PRIVATE_BIT) >= NUM_SNOOP_PRIVATE_ENCAPS
399                     || snoop_private_encap[hdr.network^SNOOP_PRIVATE_BIT] == WTAP_ENCAP_UNKNOWN) {
400                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
401                         *err_info = g_strdup_printf("snoop: private network type %u unknown or unsupported",
402                             hdr.network);
403                         return -1;
404                 }
405                 file_encap = snoop_private_encap[hdr.network^SNOOP_PRIVATE_BIT];
406
407                 /* This is a snoop file */
408                 wth->file_type = WTAP_FILE_SNOOP;
409         } else {
410                 if (hdr.network >= NUM_SNOOP_ENCAPS
411                     || snoop_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
412                         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
413                         *err_info = g_strdup_printf("snoop: network type %u unknown or unsupported",
414                             hdr.network);
415                         return -1;
416                 }
417                 file_encap = snoop_encap[hdr.network];
418
419                 /* This is a snoop file */
420                 wth->file_type = WTAP_FILE_SNOOP;
421         }
422
423         /*
424          * We don't currently use the extra information in Shomiti
425          * records, so we use the same routines to read snoop and
426          * Shomiti files.
427          */
428         wth->subtype_read = snoop_read;
429         wth->subtype_seek_read = snoop_seek_read;
430         wth->file_encap = file_encap;
431         wth->snapshot_length = 0;       /* not available in header */
432         wth->tsprecision = WTAP_FILE_TSPREC_USEC;
433         return 1;
434 }
435
436 typedef struct {
437         guint8 pad[4];
438         guint8 undecrypt[2];
439         guint8 rate;
440         guint8 preamble;
441         guint8 code;
442         guint8 signal;
443         guint8 qual;
444         guint8 channel;
445 } shomiti_wireless_header;
446
447
448 /* Read the next packet */
449 static gboolean snoop_read(wtap *wth, int *err, gchar **err_info,
450     gint64 *data_offset)
451 {
452         guint32 rec_size;
453         guint32 packet_size;
454         guint32 orig_size;
455         int     bytes_read;
456         struct snooprec_hdr hdr;
457         char    padbuf[4];
458         guint   padbytes;
459         int     bytes_to_read;
460         int header_size;
461
462         /* Read record header. */
463         errno = WTAP_ERR_CANT_READ;
464         bytes_read = file_read(&hdr, sizeof hdr, wth->fh);
465         if (bytes_read != sizeof hdr) {
466                 *err = file_error(wth->fh, err_info);
467                 if (*err == 0 && bytes_read != 0)
468                         *err = WTAP_ERR_SHORT_READ;
469                 return FALSE;
470         }
471         wth->data_offset += sizeof hdr;
472
473         rec_size = g_ntohl(hdr.rec_len);
474         orig_size = g_ntohl(hdr.orig_len);
475         packet_size = g_ntohl(hdr.incl_len);
476         if (packet_size > WTAP_MAX_PACKET_SIZE) {
477                 /*
478                  * Probably a corrupt capture file; don't blow up trying
479                  * to allocate space for an immensely-large packet.
480                  */
481                 *err = WTAP_ERR_BAD_RECORD;
482                 *err_info = g_strdup_printf("snoop: File has %u-byte packet, bigger than maximum of %u",
483                     packet_size, WTAP_MAX_PACKET_SIZE);
484                 return FALSE;
485         }
486         if (packet_size > rec_size) {
487                 /*
488                  * Probably a corrupt capture file.
489                  */
490                 *err = WTAP_ERR_BAD_RECORD;
491                 *err_info = g_strdup_printf("snoop: File has %u-byte packet, bigger than record size %u",
492                     packet_size, rec_size);
493                 return FALSE;
494         }
495
496         *data_offset = wth->data_offset;
497
498         /*
499          * If this is an ATM packet, the first four bytes are the
500          * direction of the packet (transmit/receive), the VPI, and
501          * the VCI; read them and generate the pseudo-header from
502          * them.
503          */
504         switch (wth->file_encap) {
505
506         case WTAP_ENCAP_ATM_PDUS:
507                 if (packet_size < sizeof (struct snoop_atm_hdr)) {
508                         /*
509                          * Uh-oh, the packet isn't big enough to even
510                          * have a pseudo-header.
511                          */
512                         *err = WTAP_ERR_BAD_RECORD;
513                         *err_info = g_strdup_printf("snoop: atmsnoop file has a %u-byte packet, too small to have even an ATM pseudo-header",
514                             packet_size);
515                         return FALSE;
516                 }
517                 if (!snoop_read_atm_pseudoheader(wth->fh, &wth->pseudo_header,
518                     err, err_info))
519                         return FALSE;   /* Read error */
520
521                 /*
522                  * Don't count the pseudo-header as part of the packet.
523                  */
524                 rec_size -= (guint32)sizeof (struct snoop_atm_hdr);
525                 orig_size -= (guint32)sizeof (struct snoop_atm_hdr);
526                 packet_size -= (guint32)sizeof (struct snoop_atm_hdr);
527                 wth->data_offset += sizeof (struct snoop_atm_hdr);
528                 break;
529
530         case WTAP_ENCAP_ETHERNET:
531                 /*
532                  * If this is a snoop file, we assume there's no FCS in
533                  * this frame; if this is a Shomit file, we assume there
534                  * is.  (XXX - or should we treat it a "maybe"?)
535                  */
536                 if (wth->file_type == WTAP_FILE_SHOMITI)
537                         wth->pseudo_header.eth.fcs_len = 4;
538                 else
539                         wth->pseudo_header.eth.fcs_len = 0;
540                 break;
541
542         case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
543                 if (packet_size < sizeof (shomiti_wireless_header)) {
544                         /*
545                          * Uh-oh, the packet isn't big enough to even
546                          * have a pseudo-header.
547                          */
548                         *err = WTAP_ERR_BAD_RECORD;
549                         *err_info = g_strdup_printf("snoop: Shomiti wireless file has a %u-byte packet, too small to have even a wireless pseudo-header",
550                             packet_size);
551                         return FALSE;
552                 }
553                 if (!snoop_read_shomiti_wireless_pseudoheader(wth->fh,
554                     &wth->pseudo_header, err, err_info, &header_size))
555                         return FALSE;   /* Read error */
556
557                 /*
558                  * Don't count the pseudo-header as part of the packet.
559                  */
560                 rec_size -= header_size;
561                 orig_size -= header_size;
562                 packet_size -= header_size;
563                 wth->data_offset += header_size;
564                 break;
565         }
566
567         buffer_assure_space(wth->frame_buffer, packet_size);
568         if (!snoop_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
569             packet_size, err, err_info))
570                 return FALSE;   /* Read error */
571         wth->data_offset += packet_size;
572
573         wth->phdr.ts.secs = g_ntohl(hdr.ts_sec);
574         wth->phdr.ts.nsecs = g_ntohl(hdr.ts_usec) * 1000;
575         wth->phdr.caplen = packet_size;
576         wth->phdr.len = orig_size;
577
578         /*
579          * If this is ATM LANE traffic, try to guess what type of LANE
580          * traffic it is based on the packet contents.
581          */
582         if (wth->file_encap == WTAP_ENCAP_ATM_PDUS &&
583             wth->pseudo_header.atm.type == TRAF_LANE) {
584                 atm_guess_lane_type(buffer_start_ptr(wth->frame_buffer),
585                     wth->phdr.caplen, &wth->pseudo_header);
586         }
587
588         /*
589          * Skip over the padding (don't "fseek()", as the standard
590          * I/O library on some platforms discards buffered data if
591          * you do that, which means it does a lot more reads).
592          * There's probably not much padding (it's probably padded only
593          * to a 4-byte boundary), so we probably need only do one read.
594          */
595         if (rec_size < (sizeof hdr + packet_size)) {
596                 /*
597                  * What, *negative* padding?  Bogus.
598                  */
599                 *err = WTAP_ERR_BAD_RECORD;
600                 *err_info = g_strdup_printf("snoop: File has %u-byte record with packet size of %u",
601                     rec_size, packet_size);
602                 return FALSE;
603         }
604         padbytes = rec_size - ((guint)sizeof hdr + packet_size);
605         while (padbytes != 0) {
606                 bytes_to_read = padbytes;
607                 if ((unsigned)bytes_to_read > sizeof padbuf)
608                         bytes_to_read = sizeof padbuf;
609                 errno = WTAP_ERR_CANT_READ;
610                 bytes_read = file_read(padbuf, bytes_to_read, wth->fh);
611                 if (bytes_read != bytes_to_read) {
612                         *err = file_error(wth->fh, err_info);
613                         if (*err == 0)
614                                 *err = WTAP_ERR_SHORT_READ;
615                         return FALSE;
616                 }
617                 wth->data_offset += bytes_read;
618                 padbytes -= bytes_read;
619         }
620
621         return TRUE;
622 }
623
624 static gboolean
625 snoop_seek_read(wtap *wth, gint64 seek_off,
626     union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
627     int *err, gchar **err_info)
628 {
629         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
630                 return FALSE;
631
632         switch (wth->file_encap) {
633
634         case WTAP_ENCAP_ATM_PDUS:
635                 if (!snoop_read_atm_pseudoheader(wth->random_fh, pseudo_header,
636                     err, err_info)) {
637                         /* Read error */
638                         return FALSE;
639                 }
640                 break;
641
642         case WTAP_ENCAP_ETHERNET:
643                 /*
644                  * If this is a snoop file, we assume there's no FCS in
645                  * this frame; if this is a Shomit file, we assume there
646                  * is.  (XXX - or should we treat it a "maybe"?)
647                  */
648                 if (wth->file_type == WTAP_FILE_SHOMITI)
649                         pseudo_header->eth.fcs_len = 4;
650                 else
651                         pseudo_header->eth.fcs_len = 0;
652                 break;
653
654         case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
655                 if (!snoop_read_shomiti_wireless_pseudoheader(wth->random_fh,
656                     pseudo_header, err, err_info, NULL)) {
657                         /* Read error */
658                         return FALSE;
659                 }
660                 break;
661         }
662
663         /*
664          * Read the packet data.
665          */
666         if (!snoop_read_rec_data(wth->random_fh, pd, length, err, err_info))
667                 return FALSE;   /* failed */
668
669         /*
670          * If this is ATM LANE traffic, try to guess what type of LANE
671          * traffic it is based on the packet contents.
672          */
673         if (wth->file_encap == WTAP_ENCAP_ATM_PDUS &&
674             pseudo_header->atm.type == TRAF_LANE)
675                 atm_guess_lane_type(pd, length, pseudo_header);
676         return TRUE;
677 }
678
679 static gboolean
680 snoop_read_atm_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
681     int *err, gchar **err_info)
682 {
683         struct snoop_atm_hdr atm_phdr;
684         int     bytes_read;
685         guint8  vpi;
686         guint16 vci;
687
688         errno = WTAP_ERR_CANT_READ;
689         bytes_read = file_read(&atm_phdr, sizeof (struct snoop_atm_hdr), fh);
690         if (bytes_read != sizeof (struct snoop_atm_hdr)) {
691                 *err = file_error(fh, err_info);
692                 if (*err == 0)
693                         *err = WTAP_ERR_SHORT_READ;
694                 return FALSE;
695         }
696
697         vpi = atm_phdr.vpi;
698         vci = pntohs(&atm_phdr.vci);
699
700         /*
701          * The lower 4 bits of the first byte of the header indicate
702          * the type of traffic, as per the "atmioctl.h" header in
703          * SunATM.
704          */
705         switch (atm_phdr.flags & 0x0F) {
706
707         case 0x01:      /* LANE */
708                 pseudo_header->atm.aal = AAL_5;
709                 pseudo_header->atm.type = TRAF_LANE;
710                 break;
711
712         case 0x02:      /* RFC 1483 LLC multiplexed traffic */
713                 pseudo_header->atm.aal = AAL_5;
714                 pseudo_header->atm.type = TRAF_LLCMX;
715                 break;
716
717         case 0x05:      /* ILMI */
718                 pseudo_header->atm.aal = AAL_5;
719                 pseudo_header->atm.type = TRAF_ILMI;
720                 break;
721
722         case 0x06:      /* Signalling AAL */
723                 pseudo_header->atm.aal = AAL_SIGNALLING;
724                 pseudo_header->atm.type = TRAF_UNKNOWN;
725                 break;
726
727         case 0x03:      /* MARS (RFC 2022) */
728                 pseudo_header->atm.aal = AAL_5;
729                 pseudo_header->atm.type = TRAF_UNKNOWN;
730                 break;
731
732         case 0x04:      /* IFMP (Ipsilon Flow Management Protocol; see RFC 1954) */
733                 pseudo_header->atm.aal = AAL_5;
734                 pseudo_header->atm.type = TRAF_UNKNOWN; /* XXX - TRAF_IPSILON? */
735                 break;
736
737         default:
738                 /*
739                  * Assume it's AAL5, unless it's VPI 0 and VCI 5, in which
740                  * case assume it's AAL_SIGNALLING; we know nothing more
741                  * about it.
742                  *
743                  * XXX - is this necessary?  Or are we guaranteed that
744                  * all signalling traffic has a type of 0x06?
745                  *
746                  * XXX - is this guaranteed to be AAL5?  Or, if the type is
747                  * 0x00 ("raw"), might it be non-AAL5 traffic?
748                  */
749                 if (vpi == 0 && vci == 5)
750                         pseudo_header->atm.aal = AAL_SIGNALLING;
751                 else
752                         pseudo_header->atm.aal = AAL_5;
753                 pseudo_header->atm.type = TRAF_UNKNOWN;
754                 break;
755         }
756         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
757
758         pseudo_header->atm.vpi = vpi;
759         pseudo_header->atm.vci = vci;
760         pseudo_header->atm.channel = (atm_phdr.flags & 0x80) ? 0 : 1;
761
762         /* We don't have this information */
763         pseudo_header->atm.flags = 0;
764         pseudo_header->atm.cells = 0;
765         pseudo_header->atm.aal5t_u2u = 0;
766         pseudo_header->atm.aal5t_len = 0;
767         pseudo_header->atm.aal5t_chksum = 0;
768
769         return TRUE;
770 }
771
772 static gboolean
773 snoop_read_shomiti_wireless_pseudoheader(FILE_T fh,
774     union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info,
775     int *header_size)
776 {
777         shomiti_wireless_header whdr;
778         int     bytes_read;
779         int     rsize;
780
781         errno = WTAP_ERR_CANT_READ;
782         bytes_read = file_read(&whdr, sizeof (shomiti_wireless_header), fh);
783         if (bytes_read != sizeof (shomiti_wireless_header)) {
784                 *err = file_error(fh, err_info);
785                 if (*err == 0)
786                         *err = WTAP_ERR_SHORT_READ;
787                 return FALSE;
788         }
789
790         /* the 4th byte of the pad is actually a header length,
791          * we've already read 8 bytes of it, and it must never
792          * be less than 8.
793          *
794          * XXX - presumably that means that the header length
795          * doesn't include the length field, as we've read
796          * 12 bytes total.
797          *
798          * XXX - what's in the other 3 bytes of the padding?  Is it a
799          * 4-byte length field?
800          * XXX - is there anything in the rest of the header of interest?
801          * XXX - are there any files where the header is shorter than
802          * 4 bytes of length plus 8 bytes of information?
803          */
804         if (whdr.pad[3] < 8) {
805                 *err = WTAP_ERR_BAD_RECORD;
806                 *err_info = g_strdup_printf("snoop: Header length in Surveyor record is %u, less than minimum of 8",
807                     whdr.pad[3]);
808                 return FALSE;
809         }
810         /* Skip the header. */
811         rsize = ((int) whdr.pad[3]) - 8;
812         if (file_seek(fh, rsize, SEEK_CUR, err) == -1)
813                 return FALSE;
814
815         pseudo_header->ieee_802_11.fcs_len = 4;
816         pseudo_header->ieee_802_11.channel = whdr.channel;
817         pseudo_header->ieee_802_11.data_rate = whdr.rate;
818         pseudo_header->ieee_802_11.signal_level = whdr.signal;
819
820         /* add back the header and don't forget the pad as well */
821         if(header_size != NULL)
822             *header_size = rsize + 8 + 4;
823
824     return TRUE;
825 }
826
827 static gboolean
828 snoop_read_rec_data(FILE_T fh, guchar *pd, int length, int *err,
829     gchar **err_info)
830 {
831         int     bytes_read;
832
833         errno = WTAP_ERR_CANT_READ;
834         bytes_read = file_read(pd, length, fh);
835
836         if (bytes_read != length) {
837                 *err = file_error(fh, err_info);
838                 if (*err == 0)
839                         *err = WTAP_ERR_SHORT_READ;
840                 return FALSE;
841         }
842         return TRUE;
843 }
844
845 static const int wtap_encap[] = {
846         -1,             /* WTAP_ENCAP_UNKNOWN -> unsupported */
847         0x04,           /* WTAP_ENCAP_ETHERNET -> DL_ETHER */
848         0x02,           /* WTAP_ENCAP_TOKEN_RING -> DL_TPR */
849         -1,             /* WTAP_ENCAP_SLIP -> unsupported */
850         -1,             /* WTAP_ENCAP_PPP -> unsupported */
851         0x08,           /* WTAP_ENCAP_FDDI -> DL_FDDI */
852         0x08,           /* WTAP_ENCAP_FDDI_BITSWAPPED -> DL_FDDI */
853         -1,             /* WTAP_ENCAP_RAW_IP -> unsupported */
854         -1,             /* WTAP_ENCAP_ARCNET -> unsupported */
855         -1,             /* WTAP_ENCAP_ATM_RFC1483 -> unsupported */
856         -1,             /* WTAP_ENCAP_LINUX_ATM_CLIP -> unsupported */
857         -1,             /* WTAP_ENCAP_LAPB -> unsupported*/
858         0x12,           /* WTAP_ENCAP_ATM_PDUS -> DL_IPATM */
859         -1              /* WTAP_ENCAP_NULL -> unsupported */
860 };
861 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
862
863 /* Returns 0 if we could write the specified encapsulation type,
864    an error indication otherwise. */
865 int snoop_dump_can_write_encap(int encap)
866 {
867         /* Per-packet encapsulations aren't supported. */
868         if (encap == WTAP_ENCAP_PER_PACKET)
869                 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
870
871         if (encap < 0 || (unsigned)encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
872                 return WTAP_ERR_UNSUPPORTED_ENCAP;
873
874         return 0;
875 }
876
877 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
878    failure */
879 gboolean snoop_dump_open(wtap_dumper *wdh, int *err)
880 {
881         struct snoop_hdr file_hdr;
882
883         /* This is a snoop file */
884         wdh->subtype_write = snoop_dump;
885         wdh->subtype_close = NULL;
886
887         /* Write the file header. */
888         if (!wtap_dump_file_write(wdh, &snoop_magic, sizeof snoop_magic, err))
889                 return FALSE;
890
891         /* current "snoop" format is 2 */
892         file_hdr.version = g_htonl(2);
893         file_hdr.network = g_htonl(wtap_encap[wdh->encap]);
894         if (!wtap_dump_file_write(wdh, &file_hdr, sizeof file_hdr, err))
895                 return FALSE;
896
897         return TRUE;
898 }
899
900 /* Write a record for a packet to a dump file.
901    Returns TRUE on success, FALSE on failure. */
902 static gboolean snoop_dump(wtap_dumper *wdh,
903         const struct wtap_pkthdr *phdr,
904         const union wtap_pseudo_header *pseudo_header _U_,
905         const guchar *pd, int *err)
906 {
907         struct snooprec_hdr rec_hdr;
908         int reclen;
909         guint padlen;
910         static char zeroes[4];
911         struct snoop_atm_hdr atm_hdr;
912         int atm_hdrsize;
913
914         if (wdh->encap == WTAP_ENCAP_ATM_PDUS)
915                 atm_hdrsize = sizeof (struct snoop_atm_hdr);
916         else
917                 atm_hdrsize = 0;
918
919         /* Record length = header length plus data length... */
920         reclen = (int)sizeof rec_hdr + phdr->caplen + atm_hdrsize;
921
922         /* ... plus enough bytes to pad it to a 4-byte boundary. */
923         padlen = ((reclen + 3) & ~3) - reclen;
924         reclen += padlen;
925
926         rec_hdr.orig_len = g_htonl(phdr->len + atm_hdrsize);
927         rec_hdr.incl_len = g_htonl(phdr->caplen + atm_hdrsize);
928         rec_hdr.rec_len = g_htonl(reclen);
929         rec_hdr.cum_drops = 0;
930         rec_hdr.ts_sec = g_htonl(phdr->ts.secs);
931         rec_hdr.ts_usec = g_htonl(phdr->ts.nsecs / 1000);
932         if (!wtap_dump_file_write(wdh, &rec_hdr, sizeof rec_hdr, err))
933                 return FALSE;
934
935         if (wdh->encap == WTAP_ENCAP_ATM_PDUS) {
936                 /*
937                  * Write the ATM header.
938                  */
939                 atm_hdr.flags =
940                     (pseudo_header->atm.channel == 0) ? 0x80 : 0x00;
941                 switch (pseudo_header->atm.aal) {
942
943                 case AAL_SIGNALLING:
944                         /* Signalling AAL */
945                         atm_hdr.flags |= 0x06;
946                         break;
947
948                 case AAL_5:
949                         switch (pseudo_header->atm.type) {
950
951                         case TRAF_LANE:
952                                 /* LANE */
953                                 atm_hdr.flags |= 0x01;
954                                 break;
955
956                         case TRAF_LLCMX:
957                                 /* RFC 1483 LLC multiplexed traffic */
958                                 atm_hdr.flags |= 0x02;
959                                 break;
960
961                         case TRAF_ILMI:
962                                 /* ILMI */
963                                 atm_hdr.flags |= 0x05;
964                                 break;
965                         }
966                         break;
967                 }
968                 atm_hdr.vpi = (guint8) pseudo_header->atm.vpi;
969                 atm_hdr.vci = g_htons(pseudo_header->atm.vci);
970                 if (!wtap_dump_file_write(wdh, &atm_hdr, sizeof atm_hdr, err))
971                         return FALSE;
972         }
973
974         if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
975                 return FALSE;
976
977         /* Now write the padding. */
978         if (!wtap_dump_file_write(wdh, zeroes, padlen, err))
979                 return FALSE;
980         return TRUE;
981 }