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.
31 #include "file_wrappers.h"
39 guint32 sec; /* seconds since midnight */
43 struct unaligned_frame_date {
47 char sec[4]; /* seconds since midnight */
51 /* Found at the beginning of the file. Bytes 2 and 3 (D2:00) seem to be
52 * different in some captures */
53 static const guint8 radcom_magic[8] = {
54 0x42, 0xD2, 0x00, 0x34, 0x12, 0x66, 0x22, 0x88
57 static const guint8 encap_magic[4] = {
58 0x00, 0x42, 0x43, 0x09
61 static const guint8 active_time_magic[11] = {
62 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x54, 0x69, 0x6d, 0x65
65 /* RADCOM record header - followed by frame data (perhaps including FCS).
67 "data_length" appears to be the length of packet data following
68 the record header. It's 0 in the last record.
70 "length" appears to be the amount of captured packet data, and
71 "real_length" might be the actual length of the frame on the wire -
72 in some captures, it's the same as "length", and, in others,
73 it's greater than "length". In the last record, however, those
74 may have bogus values (or is that some kind of trailer record?).
76 "xxx" appears to be all-zero in all but the last record in one
77 capture; if so, perhaps this indicates that the last record is,
78 in fact, a trailer of some sort, and some field in the header
80 struct radcomrec_hdr {
81 char xxx[4]; /* unknown */
82 char data_length[2]; /* packet length? */
83 char xxy[5]; /* unknown */
84 struct unaligned_frame_date date; /* date/time stamp of packet */
85 char real_length[2]; /* actual length of packet */
86 char length[2]; /* captured length of packet */
87 char xxz[2]; /* unknown */
88 char dce; /* DCE/DTE flag (and other flags?) */
89 char xxw[9]; /* unknown */
92 static gboolean radcom_read(wtap *wth, int *err, gchar **err_info,
94 static gboolean radcom_seek_read(wtap *wth, gint64 seek_off,
95 union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
96 int *err, gchar **err_info);
97 static int radcom_read_rec_header(FILE_T fh, struct radcomrec_hdr *hdr,
99 static gboolean radcom_read_rec_data(FILE_T fh, guchar *pd, int length,
102 int radcom_open(wtap *wth, int *err, gchar **err_info)
105 guint8 r_magic[8], t_magic[11], search_encap[7];
106 struct frame_date start_date;
110 /* Read in the string that should be at the start of a RADCOM file */
111 errno = WTAP_ERR_CANT_READ;
112 bytes_read = file_read(r_magic, 1, 8, wth->fh);
113 if (bytes_read != 8) {
114 *err = file_error(wth->fh);
120 /* XXX: bytes 2 and 3 of the "magic" header seem to be different in some
121 * captures. We force them to our standard value so that the test
122 * succeeds (until we find if they have a special meaning, perhaps a
123 * version number ?) */
126 if (memcmp(r_magic, radcom_magic, 8) != 0) {
130 /* Look for the "Active Time" string. The "frame_date" structure should
131 * be located 32 bytes before the beginning of this string */
132 wth->data_offset = 8;
133 errno = WTAP_ERR_CANT_READ;
134 bytes_read = file_read(t_magic, 1, 11, wth->fh);
135 if (bytes_read != 11) {
136 *err = file_error(wth->fh);
141 while (memcmp(t_magic, active_time_magic, 11) != 0)
143 if (file_seek(wth->fh, -10, SEEK_CUR, err) == -1)
145 wth->data_offset += 1;
146 errno = WTAP_ERR_CANT_READ;
147 bytes_read = file_read(t_magic, 1, 11, wth->fh);
148 if (bytes_read != 11) {
149 *err = file_error(wth->fh);
155 if (file_seek(wth->fh, -43, SEEK_CUR, err) == -1) return -1;
156 wth->data_offset -= 32;
158 /* Get capture start time */
159 errno = WTAP_ERR_CANT_READ;
160 bytes_read = file_read(&start_date, 1, sizeof(struct frame_date),
162 if (bytes_read != sizeof(struct frame_date)) {
163 *err = file_error(wth->fh);
168 wth->data_offset += sizeof(struct frame_date);
170 /* This is a radcom file */
171 wth->file_type = WTAP_FILE_RADCOM;
172 wth->subtype_read = radcom_read;
173 wth->subtype_seek_read = radcom_seek_read;
174 wth->snapshot_length = 0; /* not available in header, only in frame */
175 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
177 tm.tm_year = pletohs(&start_date.year)-1900;
178 tm.tm_mon = start_date.month-1;
179 tm.tm_mday = start_date.day;
180 sec = pletohl(&start_date.sec);
181 tm.tm_hour = sec/3600;
182 tm.tm_min = (sec%3600)/60;
186 if (file_seek(wth->fh, sizeof(struct frame_date), SEEK_CUR, err) == -1)
188 wth->data_offset += sizeof(struct frame_date);
190 errno = WTAP_ERR_CANT_READ;
191 bytes_read = file_read(search_encap, 1, 4, wth->fh);
192 if (bytes_read != 4) {
195 wth->data_offset += 4;
196 while (memcmp(encap_magic, search_encap, 4)) {
197 if (file_seek(wth->fh, -3, SEEK_CUR, err) == -1)
199 wth->data_offset -= 3;
200 errno = WTAP_ERR_CANT_READ;
201 bytes_read = file_read(search_encap, 1, 4, wth->fh);
202 if (bytes_read != 4) {
205 wth->data_offset += 4;
207 if (file_seek(wth->fh, 12, SEEK_CUR, err) == -1)
209 wth->data_offset += 12;
210 errno = WTAP_ERR_CANT_READ;
211 bytes_read = file_read(search_encap, 1, 4, wth->fh);
212 if (bytes_read != 4) {
215 wth->data_offset += 4;
216 if (memcmp(search_encap, "LAPB", 4) == 0)
217 wth->file_encap = WTAP_ENCAP_LAPB;
218 else if (memcmp(search_encap, "Ethe", 4) == 0)
219 wth->file_encap = WTAP_ENCAP_ETHERNET;
220 else if (memcmp(search_encap, "ATM/", 4) == 0)
221 wth->file_encap = WTAP_ENCAP_ATM_RFC1483;
223 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
224 *err_info = g_strdup_printf("radcom: network type \"%.4s\" unknown", search_encap);
228 /*bytes_read = file_read(&next_date, 1, sizeof(struct frame_date), wth->fh);
229 errno = WTAP_ERR_CANT_READ;
230 if (bytes_read != sizeof(struct frame_date)) {
234 while (memcmp(&start_date, &next_date, 4)) {
235 if (file_seek(wth->fh, 1-sizeof(struct frame_date), SEEK_CUR, err) == -1)
237 errno = WTAP_ERR_CANT_READ;
238 bytes_read = file_read(&next_date, 1, sizeof(struct frame_date),
240 if (bytes_read != sizeof(struct frame_date)) {
245 if (wth->file_encap == WTAP_ENCAP_ETHERNET) {
246 if (file_seek(wth->fh, 294, SEEK_CUR, err) == -1)
248 wth->data_offset += 294;
249 } else if (wth->file_encap == WTAP_ENCAP_LAPB) {
250 if (file_seek(wth->fh, 297, SEEK_CUR, err) == -1)
252 wth->data_offset += 297;
253 } else if (wth->file_encap == WTAP_ENCAP_ATM_RFC1483) {
254 if (file_seek(wth->fh, 504, SEEK_CUR, err) == -1)
256 wth->data_offset += 504;
262 *err = file_error(wth->fh);
268 /* Read the next packet */
269 static gboolean radcom_read(wtap *wth, int *err, gchar **err_info _U_,
273 struct radcomrec_hdr hdr;
274 guint16 data_length, real_length, length;
281 /* Read record header. */
282 *data_offset = wth->data_offset;
283 ret = radcom_read_rec_header(wth->fh, &hdr, err);
285 /* Read error or EOF */
288 wth->data_offset += sizeof hdr;
289 data_length = pletohs(&hdr.data_length);
290 if (data_length == 0) {
292 * The last record appears to have 0 in its "data_length"
293 * field, but non-zero values in other fields, so we
294 * check for that and treat it as an EOF indication.
299 length = pletohs(&hdr.length);
300 real_length = pletohs(&hdr.real_length);
302 if (wth->file_encap == WTAP_ENCAP_LAPB) {
303 length -= 2; /* FCS */
307 wth->phdr.len = real_length;
308 wth->phdr.caplen = length;
310 tm.tm_year = pletohs(&hdr.date.year)-1900;
311 tm.tm_mon = (hdr.date.month&0x0f)-1;
312 tm.tm_mday = hdr.date.day;
313 sec = pletohl(&hdr.date.sec);
314 tm.tm_hour = sec/3600;
315 tm.tm_min = (sec%3600)/60;
318 wth->phdr.ts.secs = mktime(&tm);
319 wth->phdr.ts.nsecs = pletohl(&hdr.date.usec) * 1000;
321 switch (wth->file_encap) {
323 case WTAP_ENCAP_ETHERNET:
324 /* XXX - is there an FCS? */
325 wth->pseudo_header.eth.fcs_len = -1;
328 case WTAP_ENCAP_LAPB:
329 wth->pseudo_header.x25.flags = (hdr.dce & 0x1) ?
333 case WTAP_ENCAP_ATM_RFC1483:
335 * XXX - is this stuff a pseudo-header?
336 * The direction appears to be in the "hdr.dce" field.
338 if (!radcom_read_rec_data(wth->fh, phdr, sizeof phdr, err))
339 return FALSE; /* Read error */
340 wth->data_offset += 8;
343 wth->phdr.caplen -= 8;
348 * Read the packet data.
350 buffer_assure_space(wth->frame_buffer, length);
351 if (!radcom_read_rec_data(wth->fh,
352 buffer_start_ptr(wth->frame_buffer), length, err))
353 return FALSE; /* Read error */
354 wth->data_offset += length;
356 if (wth->file_encap == WTAP_ENCAP_LAPB) {
358 XXX - should we have some way of indicating the
359 presence and size of an FCS to our caller?
360 That'd let us handle other file types as well. */
361 errno = WTAP_ERR_CANT_READ;
362 bytes_read = file_read(&fcs, 1, sizeof fcs, wth->fh);
363 if (bytes_read != sizeof fcs) {
364 *err = file_error(wth->fh);
366 *err = WTAP_ERR_SHORT_READ;
369 wth->data_offset += sizeof fcs;
376 radcom_seek_read(wtap *wth, gint64 seek_off,
377 union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
378 int *err, gchar **err_info _U_)
381 struct radcomrec_hdr hdr;
384 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
387 /* Read record header. */
388 ret = radcom_read_rec_header(wth->random_fh, &hdr, err);
390 /* Read error or EOF */
392 /* EOF means "short read" in random-access mode */
393 *err = WTAP_ERR_SHORT_READ;
398 switch (wth->file_encap) {
400 case WTAP_ENCAP_ETHERNET:
401 /* XXX - is there an FCS? */
402 pseudo_header->eth.fcs_len = -1;
405 case WTAP_ENCAP_LAPB:
406 pseudo_header->x25.flags = (hdr.dce & 0x1) ? 0x00 : FROM_DCE;
409 case WTAP_ENCAP_ATM_RFC1483:
411 * XXX - is this stuff a pseudo-header?
412 * The direction appears to be in the "hdr.dce" field.
414 if (!radcom_read_rec_data(wth->random_fh, phdr, sizeof phdr,
416 return FALSE; /* Read error */
421 * Read the packet data.
423 return radcom_read_rec_data(wth->random_fh, pd, length, err);
427 radcom_read_rec_header(FILE_T fh, struct radcomrec_hdr *hdr, int *err)
431 errno = WTAP_ERR_CANT_READ;
432 bytes_read = file_read(hdr, 1, sizeof *hdr, fh);
433 if (bytes_read != sizeof *hdr) {
434 *err = file_error(fh);
437 if (bytes_read != 0) {
438 *err = WTAP_ERR_SHORT_READ;
447 radcom_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
451 errno = WTAP_ERR_CANT_READ;
452 bytes_read = file_read(pd, 1, length, fh);
454 if (bytes_read != length) {
455 *err = file_error(fh);
457 *err = WTAP_ERR_SHORT_READ;