4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
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.
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.
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.
26 #include "file_wrappers.h"
33 guint32 sec; /* seconds since midnight */
37 struct unaligned_frame_date {
41 char sec[4]; /* seconds since midnight */
45 /* Found at the beginning of the file. Bytes 2 and 3 (D2:00) seem to be
46 * different in some captures */
47 static const guint8 radcom_magic[8] = {
48 0x42, 0xD2, 0x00, 0x34, 0x12, 0x66, 0x22, 0x88
51 static const guint8 encap_magic[4] = {
52 0x00, 0x42, 0x43, 0x09
55 static const guint8 active_time_magic[11] = {
56 'A', 'c', 't', 'i', 'v', 'e', ' ', 'T', 'i', 'm', 'e'
59 /* RADCOM record header - followed by frame data (perhaps including FCS).
61 "data_length" appears to be the length of packet data following
62 the record header. It's 0 in the last record.
64 "length" appears to be the amount of captured packet data, and
65 "real_length" might be the actual length of the frame on the wire -
66 in some captures, it's the same as "length", and, in others,
67 it's greater than "length". In the last record, however, those
68 may have bogus values (or is that some kind of trailer record?).
70 "xxx" appears to be all-zero in all but the last record in one
71 capture; if so, perhaps this indicates that the last record is,
72 in fact, a trailer of some sort, and some field in the header
74 struct radcomrec_hdr {
75 char xxx[4]; /* unknown */
76 char data_length[2]; /* packet length? */
77 char xxy[5]; /* unknown */
78 struct unaligned_frame_date date; /* date/time stamp of packet */
79 char real_length[2]; /* actual length of packet */
80 char length[2]; /* captured length of packet */
81 char xxz[2]; /* unknown */
82 char dce; /* DCE/DTE flag (and other flags?) */
83 char xxw[9]; /* unknown */
86 static gboolean radcom_read(wtap *wth, int *err, gchar **err_info,
88 static gboolean radcom_seek_read(wtap *wth, gint64 seek_off,
89 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
90 static gboolean radcom_read_rec(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
91 Buffer *buf, int *err, gchar **err_info);
93 wtap_open_return_val radcom_open(wtap *wth, int *err, gchar **err_info)
95 guint8 r_magic[8], t_magic[11], search_encap[7];
96 struct frame_date start_date;
102 /* Read in the string that should be at the start of a RADCOM file */
103 if (!wtap_read_bytes(wth->fh, r_magic, 8, err, err_info)) {
104 if (*err != WTAP_ERR_SHORT_READ)
105 return WTAP_OPEN_ERROR;
106 return WTAP_OPEN_NOT_MINE;
109 /* XXX: bytes 2 and 3 of the "magic" header seem to be different in some
110 * captures. We force them to our standard value so that the test
111 * succeeds (until we find if they have a special meaning, perhaps a
112 * version number ?) */
115 if (memcmp(r_magic, radcom_magic, 8) != 0) {
116 return WTAP_OPEN_NOT_MINE;
119 /* Look for the "Active Time" string. The "frame_date" structure should
120 * be located 32 bytes before the beginning of this string */
121 if (!wtap_read_bytes(wth->fh, t_magic, 11, err, err_info)) {
122 if (*err != WTAP_ERR_SHORT_READ)
123 return WTAP_OPEN_ERROR;
124 return WTAP_OPEN_NOT_MINE;
126 while (memcmp(t_magic, active_time_magic, 11) != 0)
128 if (file_seek(wth->fh, -10, SEEK_CUR, err) == -1)
129 return WTAP_OPEN_ERROR;
130 if (!wtap_read_bytes(wth->fh, t_magic, 11, err, err_info)) {
131 if (*err != WTAP_ERR_SHORT_READ)
132 return WTAP_OPEN_ERROR;
133 return WTAP_OPEN_NOT_MINE;
136 if (file_seek(wth->fh, -43, SEEK_CUR, err) == -1)
137 return WTAP_OPEN_ERROR;
139 /* Get capture start time */
140 if (!wtap_read_bytes(wth->fh, &start_date, sizeof(struct frame_date),
142 if (*err != WTAP_ERR_SHORT_READ)
143 return WTAP_OPEN_ERROR;
144 return WTAP_OPEN_NOT_MINE;
147 if (file_seek(wth->fh, sizeof(struct frame_date), SEEK_CUR, err) == -1)
148 return WTAP_OPEN_ERROR;
151 if (!wtap_read_bytes(wth->fh, search_encap, 4,
153 if (*err != WTAP_ERR_SHORT_READ)
154 return WTAP_OPEN_ERROR;
155 return WTAP_OPEN_NOT_MINE;
158 if (memcmp(encap_magic, search_encap, 4) == 0)
162 * OK, that's not it, go forward 1 byte - reading
163 * the magic moved us forward 4 bytes, so seeking
164 * backward 3 bytes moves forward 1 byte - and
165 * try the 4 bytes at that offset.
167 if (file_seek(wth->fh, -3, SEEK_CUR, err) == -1)
168 return WTAP_OPEN_ERROR;
170 if (file_seek(wth->fh, 12, SEEK_CUR, err) == -1)
171 return WTAP_OPEN_ERROR;
172 if (!wtap_read_bytes(wth->fh, search_encap, 4, err, err_info)) {
173 if (*err != WTAP_ERR_SHORT_READ)
174 return WTAP_OPEN_ERROR;
175 return WTAP_OPEN_NOT_MINE;
178 /* This is a radcom file */
179 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_RADCOM;
180 wth->subtype_read = radcom_read;
181 wth->subtype_seek_read = radcom_seek_read;
182 wth->snapshot_length = 0; /* not available in header, only in frame */
183 wth->file_tsprec = WTAP_TSPREC_USEC;
186 tm.tm_year = pletoh16(&start_date.year)-1900;
187 tm.tm_mon = start_date.month-1;
188 tm.tm_mday = start_date.day;
189 sec = pletoh32(&start_date.sec);
190 tm.tm_hour = sec/3600;
191 tm.tm_min = (sec%3600)/60;
196 if (memcmp(search_encap, "LAPB", 4) == 0)
197 wth->file_encap = WTAP_ENCAP_LAPB;
198 else if (memcmp(search_encap, "Ethe", 4) == 0)
199 wth->file_encap = WTAP_ENCAP_ETHERNET;
200 else if (memcmp(search_encap, "ATM/", 4) == 0)
201 wth->file_encap = WTAP_ENCAP_ATM_RFC1483;
203 *err = WTAP_ERR_UNSUPPORTED;
204 *err_info = g_strdup_printf("radcom: network type \"%.4s\" unknown", search_encap);
205 return WTAP_OPEN_ERROR;
209 if (!wtap_read_bytes(wth->fh, &next_date, sizeof(struct frame_date),
211 return WTAP_OPEN_ERROR;
213 while (memcmp(&start_date, &next_date, 4)) {
214 if (file_seek(wth->fh, 1-sizeof(struct frame_date), SEEK_CUR, err) == -1)
215 return WTAP_OPEN_ERROR;
216 if (!wtap_read_bytes(wth->fh, &next_date, sizeof(struct frame_date),
218 return WTAP_OPEN_ERROR;
222 if (wth->file_encap == WTAP_ENCAP_ETHERNET) {
223 if (file_seek(wth->fh, 294, SEEK_CUR, err) == -1)
224 return WTAP_OPEN_ERROR;
225 } else if (wth->file_encap == WTAP_ENCAP_LAPB) {
226 if (file_seek(wth->fh, 297, SEEK_CUR, err) == -1)
227 return WTAP_OPEN_ERROR;
228 } else if (wth->file_encap == WTAP_ENCAP_ATM_RFC1483) {
229 if (file_seek(wth->fh, 504, SEEK_CUR, err) == -1)
230 return WTAP_OPEN_ERROR;
233 return WTAP_OPEN_MINE;
236 /* Read the next packet */
237 static gboolean radcom_read(wtap *wth, int *err, gchar **err_info,
242 *data_offset = file_tell(wth->fh);
245 if (!radcom_read_rec(wth, wth->fh, &wth->phdr, wth->frame_buffer,
247 /* Read error or EOF */
251 if (wth->file_encap == WTAP_ENCAP_LAPB) {
253 XXX - should we have some way of indicating the
254 presence and size of an FCS to our caller?
255 That'd let us handle other file types as well. */
256 if (!wtap_read_bytes(wth->fh, &fcs, sizeof fcs, err, err_info))
264 radcom_seek_read(wtap *wth, gint64 seek_off,
265 struct wtap_pkthdr *phdr, Buffer *buf,
266 int *err, gchar **err_info)
268 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
272 if (!radcom_read_rec(wth, wth->random_fh, phdr, buf, err,
274 /* Read error or EOF */
276 /* EOF means "short read" in random-access mode */
277 *err = WTAP_ERR_SHORT_READ;
285 radcom_read_rec(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
286 int *err, gchar **err_info)
288 struct radcomrec_hdr hdr;
289 guint16 data_length, real_length, length;
294 if (!wtap_read_bytes_or_eof(fh, &hdr, sizeof hdr, err, err_info))
297 data_length = pletoh16(&hdr.data_length);
298 if (data_length == 0) {
300 * The last record appears to have 0 in its "data_length"
301 * field, but non-zero values in other fields, so we
302 * check for that and treat it as an EOF indication.
307 length = pletoh16(&hdr.length);
308 real_length = pletoh16(&hdr.real_length);
310 * The maximum value of length is 65535, which is less than
311 * WTAP_MAX_PACKET_SIZE will ever be, so we don't need to check
315 phdr->rec_type = REC_TYPE_PACKET;
316 phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
318 tm.tm_year = pletoh16(&hdr.date.year)-1900;
319 tm.tm_mon = (hdr.date.month&0x0f)-1;
320 tm.tm_mday = hdr.date.day;
321 sec = pletoh32(&hdr.date.sec);
322 tm.tm_hour = sec/3600;
323 tm.tm_min = (sec%3600)/60;
326 phdr->ts.secs = mktime(&tm);
327 phdr->ts.nsecs = pletoh32(&hdr.date.usec) * 1000;
329 switch (wth->file_encap) {
331 case WTAP_ENCAP_ETHERNET:
332 /* XXX - is there an FCS? */
333 phdr->pseudo_header.eth.fcs_len = -1;
336 case WTAP_ENCAP_LAPB:
337 phdr->pseudo_header.x25.flags = (hdr.dce & 0x1) ?
339 length -= 2; /* FCS */
343 case WTAP_ENCAP_ATM_RFC1483:
345 * XXX - is this stuff a pseudo-header?
346 * The direction appears to be in the "hdr.dce" field.
348 if (!wtap_read_bytes(fh, atmhdr, sizeof atmhdr, err,
350 return FALSE; /* Read error */
356 phdr->len = real_length;
357 phdr->caplen = length;
360 * Read the packet data.
362 if (!wtap_read_packet_bytes(fh, buf, length, err, err_info))
363 return FALSE; /* Read error */
369 * Editor modelines - http://www.wireshark.org/tools/modelines.html
374 * indent-tabs-mode: t
377 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
378 * :indentSize=8:tabSize=8:noTabs=false: