3 * $Id: snoop.c,v 1.13 1999/09/28 01:19:01 guy Exp $
6 * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_NETINET_IN_H
32 #include <netinet/in.h>
35 /* See RFC 1761 for a description of the "snoop" file format. */
37 /* Magic number in "snoop" files. */
38 static const char snoop_magic[] = {
39 's', 'n', 'o', 'o', 'p', '\0', '\0', '\0'
42 /* "snoop" file header (minus magic number). */
44 guint32 version; /* version number (should be 2) */
45 guint32 network; /* network type */
48 /* "snoop" record header. */
50 guint32 orig_len; /* actual length of packet */
51 guint32 incl_len; /* number of octets captured in file */
52 guint32 rec_len; /* length of record */
53 guint32 cum_drops; /* cumulative number of dropped packets */
54 guint32 ts_sec; /* timestamp seconds */
55 guint32 ts_usec; /* timestamp microseconds */
58 static int snoop_read(wtap *wth, int *err);
60 int snoop_open(wtap *wth, int *err)
63 char magic[sizeof snoop_magic];
65 static const int snoop_encap[] = {
66 WTAP_ENCAP_ETHERNET, /* IEEE 802.3 */
67 WTAP_ENCAP_UNKNOWN, /* IEEE 802.4 Token Bus */
69 WTAP_ENCAP_UNKNOWN, /* IEEE 802.6 Metro Net */
71 WTAP_ENCAP_UNKNOWN, /* HDLC */
72 WTAP_ENCAP_UNKNOWN, /* Character Synchronous */
73 WTAP_ENCAP_UNKNOWN, /* IBM Channel-to-Channel */
74 WTAP_ENCAP_FDDI_BITSWAPPED,
75 WTAP_ENCAP_UNKNOWN /* Other */
77 #define NUM_SNOOP_ENCAPS (sizeof snoop_encap / sizeof snoop_encap[0])
79 /* Read in the string that should be at the start of a "snoop" file */
80 file_seek(wth->fh, 0, SEEK_SET);
82 errno = WTAP_ERR_CANT_READ;
83 bytes_read = file_read(magic, 1, sizeof magic, wth->fh);
84 if (bytes_read != sizeof magic) {
85 if (file_error(wth->fh)) {
91 wth->data_offset += sizeof magic;
93 if (memcmp(magic, snoop_magic, sizeof snoop_magic) != 0) {
97 /* Read the rest of the header. */
98 errno = WTAP_ERR_CANT_READ;
99 bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
100 if (bytes_read != sizeof hdr) {
101 if (file_error(wth->fh)) {
107 wth->data_offset += sizeof hdr;
109 hdr.version = ntohl(hdr.version);
110 if (hdr.version != 2) {
111 /* We only support version 2. */
112 g_message("snoop: version %u unsupported", hdr.version);
113 *err = WTAP_ERR_UNSUPPORTED;
116 hdr.network = ntohl(hdr.network);
117 if (hdr.network >= NUM_SNOOP_ENCAPS
118 || snoop_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
119 g_message("snoop: network type %u unknown or unsupported",
121 *err = WTAP_ERR_UNSUPPORTED;
125 /* This is a snoop file */
126 wth->file_type = WTAP_FILE_SNOOP;
127 wth->subtype_read = snoop_read;
128 wth->file_encap = snoop_encap[hdr.network];
129 wth->snapshot_length = 16384; /* XXX - not available in header */
133 /* Read the next packet */
134 static int snoop_read(wtap *wth, int *err)
138 struct snooprec_hdr hdr;
144 /* Read record header. */
145 errno = WTAP_ERR_CANT_READ;
146 bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
147 if (bytes_read != sizeof hdr) {
148 if (file_error(wth->fh)) {
152 if (bytes_read != 0) {
153 *err = WTAP_ERR_SHORT_READ;
158 wth->data_offset += sizeof hdr;
160 packet_size = ntohl(hdr.incl_len);
161 if (packet_size > WTAP_MAX_PACKET_SIZE) {
163 * Probably a corrupt capture file; don't blow up trying
164 * to allocate space for an immensely-large packet.
166 g_message("snoop: File has %u-byte packet, bigger than maximum of %u",
167 packet_size, WTAP_MAX_PACKET_SIZE);
168 *err = WTAP_ERR_BAD_RECORD;
171 buffer_assure_space(wth->frame_buffer, packet_size);
172 data_offset = wth->data_offset;
173 errno = WTAP_ERR_CANT_READ;
174 bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1,
175 packet_size, wth->fh);
177 if (bytes_read != packet_size) {
178 if (file_error(wth->fh))
181 *err = WTAP_ERR_SHORT_READ;
184 wth->data_offset += packet_size;
186 wth->phdr.ts.tv_sec = ntohl(hdr.ts_sec);
187 wth->phdr.ts.tv_usec = ntohl(hdr.ts_usec);
188 wth->phdr.caplen = packet_size;
189 wth->phdr.len = ntohl(hdr.orig_len);
190 wth->phdr.pkt_encap = wth->file_encap;
193 * Skip over the padding (don't "fseek()", as the standard
194 * I/O library on some platforms discards buffered data if
195 * you do that, which means it does a lot more reads).
196 * There's probably not much padding (it's probably padded only
197 * to a 4-byte boundary), so we probably need only do one read.
199 padbytes = ntohl(hdr.rec_len) - (sizeof hdr + packet_size);
200 while (padbytes != 0) {
201 bytes_to_read = padbytes;
202 if (bytes_to_read > sizeof padbuf)
203 bytes_to_read = sizeof padbuf;
204 errno = WTAP_ERR_CANT_READ;
205 bytes_read = file_read(padbuf, 1, bytes_to_read, wth->fh);
206 if (bytes_read != bytes_to_read) {
207 if (file_error(wth->fh))
210 *err = WTAP_ERR_SHORT_READ;
213 wth->data_offset += bytes_read;
214 padbytes -= bytes_read;