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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #include "file_wrappers.h"
38 guint32 sec; /* seconds since midnight */
42 struct unaligned_frame_date {
46 char sec[4]; /* seconds since midnight */
50 /* Found at the beginning of the file. Bytes 2 and 3 (D2:00) seem to be
51 * different in some captures */
52 static const guint8 radcom_magic[8] = {
53 0x42, 0xD2, 0x00, 0x34, 0x12, 0x66, 0x22, 0x88
56 static const guint8 encap_magic[4] = {
57 0x00, 0x42, 0x43, 0x09
60 static const guint8 active_time_magic[11] = {
61 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65
64 /* RADCOM record header - followed by frame data (perhaps including FCS).
66 "data_length" appears to be the length of packet data following
67 the record header. It's 0 in the last record.
69 "length" appears to be the amount of captured packet data, and
70 "real_length" might be the actual length of the frame on the wire -
71 in some captures, it's the same as "length", and, in others,
72 it's greater than "length". In the last record, however, those
73 may have bogus values (or is that some kind of trailer record?).
75 "xxx" appears to be all-zero in all but the last record in one
76 capture; if so, perhaps this indicates that the last record is,
77 in fact, a trailer of some sort, and some field in the header
79 struct radcomrec_hdr {
80 char xxx[4]; /* unknown */
81 char data_length[2]; /* packet length? */
82 char xxy[5]; /* unknown */
83 struct unaligned_frame_date date; /* date/time stamp of packet */
84 char real_length[2]; /* actual length of packet */
85 char length[2]; /* captured length of packet */
86 char xxz[2]; /* unknown */
87 char dce; /* DCE/DTE flag (and other flags?) */
88 char xxw[9]; /* unknown */
91 static gboolean radcom_read(wtap *wth, int *err, gchar **err_info,
93 static gboolean radcom_seek_read(wtap *wth, gint64 seek_off,
94 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
95 int *err, gchar **err_info);
96 static int radcom_read_rec_header(FILE_T fh, struct radcomrec_hdr *hdr,
97 int *err, gchar **err_info);
98 static gboolean radcom_read_rec_data(FILE_T fh, guint8 *pd, int length,
99 int *err, gchar **err_info);
101 int radcom_open(wtap *wth, int *err, gchar **err_info)
104 guint8 r_magic[8], t_magic[11], search_encap[7];
105 struct frame_date start_date;
111 /* Read in the string that should be at the start of a RADCOM file */
112 errno = WTAP_ERR_CANT_READ;
113 bytes_read = file_read(r_magic, 8, wth->fh);
114 if (bytes_read != 8) {
115 *err = file_error(wth->fh, err_info);
121 /* XXX: bytes 2 and 3 of the "magic" header seem to be different in some
122 * captures. We force them to our standard value so that the test
123 * succeeds (until we find if they have a special meaning, perhaps a
124 * version number ?) */
127 if (memcmp(r_magic, radcom_magic, 8) != 0) {
131 /* Look for the "Active Time" string. The "frame_date" structure should
132 * be located 32 bytes before the beginning of this string */
133 wth->data_offset = 8;
134 errno = WTAP_ERR_CANT_READ;
135 bytes_read = file_read(t_magic, 11, wth->fh);
136 if (bytes_read != 11) {
137 *err = file_error(wth->fh, err_info);
142 while (memcmp(t_magic, active_time_magic, 11) != 0)
144 if (file_seek(wth->fh, -10, SEEK_CUR, err) == -1)
146 wth->data_offset += 1;
147 errno = WTAP_ERR_CANT_READ;
148 bytes_read = file_read(t_magic, 11, wth->fh);
149 if (bytes_read != 11) {
150 *err = file_error(wth->fh, err_info);
156 if (file_seek(wth->fh, -43, SEEK_CUR, err) == -1) return -1;
157 wth->data_offset -= 32;
159 /* Get capture start time */
160 errno = WTAP_ERR_CANT_READ;
161 bytes_read = file_read(&start_date, sizeof(struct frame_date),
163 if (bytes_read != sizeof(struct frame_date)) {
164 *err = file_error(wth->fh, err_info);
169 wth->data_offset += sizeof(struct frame_date);
171 /* This is a radcom file */
172 wth->file_type = WTAP_FILE_RADCOM;
173 wth->subtype_read = radcom_read;
174 wth->subtype_seek_read = radcom_seek_read;
175 wth->snapshot_length = 0; /* not available in header, only in frame */
176 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
179 tm.tm_year = pletohs(&start_date.year)-1900;
180 tm.tm_mon = start_date.month-1;
181 tm.tm_mday = start_date.day;
182 sec = pletohl(&start_date.sec);
183 tm.tm_hour = sec/3600;
184 tm.tm_min = (sec%3600)/60;
188 if (file_seek(wth->fh, sizeof(struct frame_date), SEEK_CUR, err) == -1)
190 wth->data_offset += sizeof(struct frame_date);
192 errno = WTAP_ERR_CANT_READ;
193 bytes_read = file_read(search_encap, 4, wth->fh);
194 if (bytes_read != 4) {
197 wth->data_offset += 4;
198 while (memcmp(encap_magic, search_encap, 4)) {
199 if (file_seek(wth->fh, -3, SEEK_CUR, err) == -1)
201 wth->data_offset -= 3;
202 errno = WTAP_ERR_CANT_READ;
203 bytes_read = file_read(search_encap, 4, wth->fh);
204 if (bytes_read != 4) {
207 wth->data_offset += 4;
209 if (file_seek(wth->fh, 12, SEEK_CUR, err) == -1)
211 wth->data_offset += 12;
212 errno = WTAP_ERR_CANT_READ;
213 bytes_read = file_read(search_encap, 4, wth->fh);
214 if (bytes_read != 4) {
217 wth->data_offset += 4;
218 if (memcmp(search_encap, "LAPB", 4) == 0)
219 wth->file_encap = WTAP_ENCAP_LAPB;
220 else if (memcmp(search_encap, "Ethe", 4) == 0)
221 wth->file_encap = WTAP_ENCAP_ETHERNET;
222 else if (memcmp(search_encap, "ATM/", 4) == 0)
223 wth->file_encap = WTAP_ENCAP_ATM_RFC1483;
225 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
226 *err_info = g_strdup_printf("radcom: network type \"%.4s\" unknown", search_encap);
231 bytes_read = file_read(&next_date, sizeof(struct frame_date), wth->fh);
232 errno = WTAP_ERR_CANT_READ;
233 if (bytes_read != sizeof(struct frame_date)) {
237 while (memcmp(&start_date, &next_date, 4)) {
238 if (file_seek(wth->fh, 1-sizeof(struct frame_date), SEEK_CUR, err) == -1)
240 errno = WTAP_ERR_CANT_READ;
241 bytes_read = file_read(&next_date, sizeof(struct frame_date),
243 if (bytes_read != sizeof(struct frame_date)) {
249 if (wth->file_encap == WTAP_ENCAP_ETHERNET) {
250 if (file_seek(wth->fh, 294, SEEK_CUR, err) == -1)
252 wth->data_offset += 294;
253 } else if (wth->file_encap == WTAP_ENCAP_LAPB) {
254 if (file_seek(wth->fh, 297, SEEK_CUR, err) == -1)
256 wth->data_offset += 297;
257 } else if (wth->file_encap == WTAP_ENCAP_ATM_RFC1483) {
258 if (file_seek(wth->fh, 504, SEEK_CUR, err) == -1)
260 wth->data_offset += 504;
266 *err = file_error(wth->fh, err_info);
272 /* Read the next packet */
273 static gboolean radcom_read(wtap *wth, int *err, gchar **err_info,
277 struct radcomrec_hdr hdr;
278 guint16 data_length, real_length, length;
285 /* Read record header. */
286 *data_offset = wth->data_offset;
287 ret = radcom_read_rec_header(wth->fh, &hdr, err, err_info);
289 /* Read error or EOF */
292 wth->data_offset += sizeof hdr;
293 data_length = pletohs(&hdr.data_length);
294 if (data_length == 0) {
296 * The last record appears to have 0 in its "data_length"
297 * field, but non-zero values in other fields, so we
298 * check for that and treat it as an EOF indication.
303 length = pletohs(&hdr.length);
304 real_length = pletohs(&hdr.real_length);
306 if (wth->file_encap == WTAP_ENCAP_LAPB) {
307 length -= 2; /* FCS */
311 wth->phdr.len = real_length;
312 wth->phdr.caplen = length;
314 tm.tm_year = pletohs(&hdr.date.year)-1900;
315 tm.tm_mon = (hdr.date.month&0x0f)-1;
316 tm.tm_mday = hdr.date.day;
317 sec = pletohl(&hdr.date.sec);
318 tm.tm_hour = sec/3600;
319 tm.tm_min = (sec%3600)/60;
322 wth->phdr.ts.secs = mktime(&tm);
323 wth->phdr.ts.nsecs = pletohl(&hdr.date.usec) * 1000;
325 switch (wth->file_encap) {
327 case WTAP_ENCAP_ETHERNET:
328 /* XXX - is there an FCS? */
329 wth->pseudo_header.eth.fcs_len = -1;
332 case WTAP_ENCAP_LAPB:
333 wth->pseudo_header.x25.flags = (hdr.dce & 0x1) ?
337 case WTAP_ENCAP_ATM_RFC1483:
339 * XXX - is this stuff a pseudo-header?
340 * The direction appears to be in the "hdr.dce" field.
342 if (!radcom_read_rec_data(wth->fh, phdr, sizeof phdr, err,
344 return FALSE; /* Read error */
345 wth->data_offset += 8;
348 wth->phdr.caplen -= 8;
353 * Read the packet data.
355 buffer_assure_space(wth->frame_buffer, length);
356 if (!radcom_read_rec_data(wth->fh,
357 buffer_start_ptr(wth->frame_buffer), length, err, err_info))
358 return FALSE; /* Read error */
359 wth->data_offset += length;
361 if (wth->file_encap == WTAP_ENCAP_LAPB) {
363 XXX - should we have some way of indicating the
364 presence and size of an FCS to our caller?
365 That'd let us handle other file types as well. */
366 errno = WTAP_ERR_CANT_READ;
367 bytes_read = file_read(&fcs, sizeof fcs, wth->fh);
368 if (bytes_read != sizeof fcs) {
369 *err = file_error(wth->fh, err_info);
371 *err = WTAP_ERR_SHORT_READ;
374 wth->data_offset += sizeof fcs;
381 radcom_seek_read(wtap *wth, gint64 seek_off,
382 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
383 int *err, gchar **err_info)
386 struct radcomrec_hdr hdr;
389 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
392 /* Read record header. */
393 ret = radcom_read_rec_header(wth->random_fh, &hdr, err, err_info);
395 /* Read error or EOF */
397 /* EOF means "short read" in random-access mode */
398 *err = WTAP_ERR_SHORT_READ;
403 switch (wth->file_encap) {
405 case WTAP_ENCAP_ETHERNET:
406 /* XXX - is there an FCS? */
407 pseudo_header->eth.fcs_len = -1;
410 case WTAP_ENCAP_LAPB:
411 pseudo_header->x25.flags = (hdr.dce & 0x1) ? 0x00 : FROM_DCE;
414 case WTAP_ENCAP_ATM_RFC1483:
416 * XXX - is this stuff a pseudo-header?
417 * The direction appears to be in the "hdr.dce" field.
419 if (!radcom_read_rec_data(wth->random_fh, phdr, sizeof phdr,
421 return FALSE; /* Read error */
426 * Read the packet data.
428 return radcom_read_rec_data(wth->random_fh, pd, length, err, err_info);
432 radcom_read_rec_header(FILE_T fh, struct radcomrec_hdr *hdr, int *err,
437 errno = WTAP_ERR_CANT_READ;
438 bytes_read = file_read(hdr, sizeof *hdr, fh);
439 if (bytes_read != sizeof *hdr) {
440 *err = file_error(fh, err_info);
443 if (bytes_read != 0) {
444 *err = WTAP_ERR_SHORT_READ;
453 radcom_read_rec_data(FILE_T fh, guint8 *pd, int length, int *err,
458 errno = WTAP_ERR_CANT_READ;
459 bytes_read = file_read(pd, length, fh);
461 if (bytes_read != length) {
462 *err = file_error(fh, err_info);
464 *err = WTAP_ERR_SHORT_READ;