3 * $Id: radcom.c,v 1.42 2003/10/01 07:11:48 guy Exp $
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 guint8 radcom_magic[8] = {
54 0x42, 0xD2, 0x00, 0x34, 0x12, 0x66, 0x22, 0x88
57 static guint8 encap_magic[4] = {
58 0x00, 0x42, 0x43, 0x09
61 static 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, long *data_offset);
93 static gboolean radcom_seek_read(wtap *wth, long seek_off,
94 union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
96 static int radcom_read_rec_header(FILE_T fh, struct radcomrec_hdr *hdr,
98 static gboolean radcom_read_rec_data(FILE_T fh, guchar *pd, int length,
101 int radcom_open(wtap *wth, int *err)
104 guint8 r_magic[8], t_magic[11], search_encap[7];
105 struct frame_date start_date;
109 /* Read in the string that should be at the start of a RADCOM file */
110 errno = WTAP_ERR_CANT_READ;
111 bytes_read = file_read(r_magic, 1, 8, wth->fh);
112 if (bytes_read != 8) {
113 *err = file_error(wth->fh);
119 /* XXX: bytes 2 and 3 of the "magic" header seem to be different in some
120 * captures. We force them to our standard value so that the test
121 * succeeds (until we find if they have a special meaning, perhaps a
122 * version number ?) */
125 if (memcmp(r_magic, radcom_magic, 8) != 0) {
129 /* Look for the "Active Time" string. The "frame_date" structure should
130 * be located 32 bytes before the beginning of this string */
131 wth->data_offset = 8;
132 errno = WTAP_ERR_CANT_READ;
133 bytes_read = file_read(t_magic, 1, 11, wth->fh);
134 if (bytes_read != 11) {
135 *err = file_error(wth->fh);
140 while (memcmp(t_magic, active_time_magic, 11) != 0)
142 if (file_seek(wth->fh, -10, SEEK_CUR, err) == -1)
144 wth->data_offset += 1;
145 errno = WTAP_ERR_CANT_READ;
146 bytes_read = file_read(t_magic, 1, 11, wth->fh);
147 if (bytes_read != 11) {
148 *err = file_error(wth->fh);
154 if (file_seek(wth->fh, -43, SEEK_CUR, err) == -1) return -1;
155 wth->data_offset -= 32;
157 /* Get capture start time */
158 errno = WTAP_ERR_CANT_READ;
159 bytes_read = file_read(&start_date, 1, sizeof(struct frame_date),
161 if (bytes_read != sizeof(struct frame_date)) {
162 *err = file_error(wth->fh);
167 wth->data_offset += sizeof(struct frame_date);
169 /* This is a radcom file */
170 wth->file_type = WTAP_FILE_RADCOM;
171 wth->subtype_read = radcom_read;
172 wth->subtype_seek_read = radcom_seek_read;
173 wth->snapshot_length = 0; /* not available in header, only in frame */
175 tm.tm_year = pletohs(&start_date.year)-1900;
176 tm.tm_mon = start_date.month-1;
177 tm.tm_mday = start_date.day;
178 sec = pletohl(&start_date.sec);
179 tm.tm_hour = sec/3600;
180 tm.tm_min = (sec%3600)/60;
184 if (file_seek(wth->fh, sizeof(struct frame_date), SEEK_CUR, err) == -1)
186 wth->data_offset += sizeof(struct frame_date);
188 errno = WTAP_ERR_CANT_READ;
189 bytes_read = file_read(search_encap, 1, 4, wth->fh);
190 if (bytes_read != 4) {
193 wth->data_offset += 4;
194 while (memcmp(encap_magic, search_encap, 4)) {
195 if (file_seek(wth->fh, -3, SEEK_CUR, err) == -1)
197 wth->data_offset -= 3;
198 errno = WTAP_ERR_CANT_READ;
199 bytes_read = file_read(search_encap, 1, 4, wth->fh);
200 if (bytes_read != 4) {
203 wth->data_offset += 4;
205 if (file_seek(wth->fh, 12, SEEK_CUR, err) == -1)
207 wth->data_offset += 12;
208 errno = WTAP_ERR_CANT_READ;
209 bytes_read = file_read(search_encap, 1, 4, wth->fh);
210 if (bytes_read != 4) {
213 wth->data_offset += 4;
214 if (memcmp(search_encap, "LAPB", 4) == 0)
215 wth->file_encap = WTAP_ENCAP_LAPB;
216 else if (memcmp(search_encap, "Ethe", 4) == 0)
217 wth->file_encap = WTAP_ENCAP_ETHERNET;
218 else if (memcmp(search_encap, "ATM/", 4) == 0)
219 wth->file_encap = WTAP_ENCAP_ATM_RFC1483;
221 g_message("pcap: network type \"%.4s\" unknown", search_encap);
222 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
226 /*bytes_read = file_read(&next_date, 1, sizeof(struct frame_date), wth->fh);
227 errno = WTAP_ERR_CANT_READ;
228 if (bytes_read != sizeof(struct frame_date)) {
232 while (memcmp(&start_date, &next_date, 4)) {
233 if (file_seek(wth->fh, 1-sizeof(struct frame_date), SEEK_CUR, err) == -1)
235 errno = WTAP_ERR_CANT_READ;
236 bytes_read = file_read(&next_date, 1, sizeof(struct frame_date),
238 if (bytes_read != sizeof(struct frame_date)) {
243 if (wth->file_encap == WTAP_ENCAP_ETHERNET) {
244 if (file_seek(wth->fh, 294, SEEK_CUR, err) == -1)
246 wth->data_offset += 294;
247 } else if (wth->file_encap == WTAP_ENCAP_LAPB) {
248 if (file_seek(wth->fh, 297, SEEK_CUR, err) == -1)
250 wth->data_offset += 297;
251 } else if (wth->file_encap == WTAP_ENCAP_ATM_RFC1483) {
252 if (file_seek(wth->fh, 504, SEEK_CUR, err) == -1)
254 wth->data_offset += 504;
260 *err = file_error(wth->fh);
266 /* Read the next packet */
267 static gboolean radcom_read(wtap *wth, int *err, long *data_offset)
270 struct radcomrec_hdr hdr;
271 guint16 data_length, real_length, length;
278 /* Read record header. */
279 *data_offset = wth->data_offset;
280 ret = radcom_read_rec_header(wth->fh, &hdr, err);
282 /* Read error or EOF */
285 wth->data_offset += sizeof hdr;
286 data_length = pletohs(&hdr.data_length);
287 if (data_length == 0) {
289 * The last record appears to have 0 in its "data_length"
290 * field, but non-zero values in other fields, so we
291 * check for that and treat it as an EOF indication.
295 length = pletohs(&hdr.length);
296 real_length = pletohs(&hdr.real_length);
298 if (wth->file_encap == WTAP_ENCAP_LAPB) {
299 length -= 2; /* FCS */
303 wth->phdr.len = real_length;
304 wth->phdr.caplen = length;
306 tm.tm_year = pletohs(&hdr.date.year)-1900;
307 tm.tm_mon = (hdr.date.month&0x0f)-1;
308 tm.tm_mday = hdr.date.day;
309 sec = pletohl(&hdr.date.sec);
310 tm.tm_hour = sec/3600;
311 tm.tm_min = (sec%3600)/60;
314 wth->phdr.ts.tv_sec = mktime(&tm);
315 wth->phdr.ts.tv_usec = pletohl(&hdr.date.usec);
317 switch (wth->file_encap) {
319 case WTAP_ENCAP_ETHERNET:
320 /* XXX - is there an FCS? */
321 wth->pseudo_header.eth.fcs_len = -1;
324 case WTAP_ENCAP_LAPB:
325 wth->pseudo_header.x25.flags = (hdr.dce & 0x1) ?
329 case WTAP_ENCAP_ATM_RFC1483:
331 * XXX - is this stuff a pseudo-header?
332 * The direction appears to be in the "hdr.dce" field.
334 if (!radcom_read_rec_data(wth->fh, phdr, sizeof phdr, err))
335 return FALSE; /* Read error */
336 wth->data_offset += 8;
339 wth->phdr.caplen -= 8;
344 * Read the packet data.
346 buffer_assure_space(wth->frame_buffer, length);
347 if (!radcom_read_rec_data(wth->fh,
348 buffer_start_ptr(wth->frame_buffer), length, err))
349 return FALSE; /* Read error */
350 wth->data_offset += length;
352 wth->phdr.pkt_encap = wth->file_encap;
354 if (wth->file_encap == WTAP_ENCAP_LAPB) {
356 XXX - should we have some way of indicating the
357 presence and size of an FCS to our caller?
358 That'd let us handle other file types as well. */
359 errno = WTAP_ERR_CANT_READ;
360 bytes_read = file_read(&fcs, 1, sizeof fcs, wth->fh);
361 if (bytes_read != sizeof fcs) {
362 *err = file_error(wth->fh);
364 *err = WTAP_ERR_SHORT_READ;
367 wth->data_offset += sizeof fcs;
374 radcom_seek_read(wtap *wth, long seek_off,
375 union wtap_pseudo_header *pseudo_header, guchar *pd, int length, int *err)
378 struct radcomrec_hdr hdr;
381 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
384 /* Read record header. */
385 ret = radcom_read_rec_header(wth->random_fh, &hdr, err);
387 /* Read error or EOF */
389 /* EOF means "short read" in random-access mode */
390 *err = WTAP_ERR_SHORT_READ;
395 switch (wth->file_encap) {
397 case WTAP_ENCAP_ETHERNET:
398 /* XXX - is there an FCS? */
399 pseudo_header->eth.fcs_len = -1;
402 case WTAP_ENCAP_LAPB:
403 pseudo_header->x25.flags = (hdr.dce & 0x1) ? 0x00 : FROM_DCE;
406 case WTAP_ENCAP_ATM_RFC1483:
408 * XXX - is this stuff a pseudo-header?
409 * The direction appears to be in the "hdr.dce" field.
411 if (!radcom_read_rec_data(wth->random_fh, phdr, sizeof phdr,
413 return FALSE; /* Read error */
418 * Read the packet data.
420 return radcom_read_rec_data(wth->random_fh, pd, length, err);
424 radcom_read_rec_header(FILE_T fh, struct radcomrec_hdr *hdr, int *err)
428 errno = WTAP_ERR_CANT_READ;
429 bytes_read = file_read(hdr, 1, sizeof *hdr, fh);
430 if (bytes_read != sizeof *hdr) {
431 *err = file_error(fh);
434 if (bytes_read != 0) {
435 *err = WTAP_ERR_SHORT_READ;
444 radcom_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
448 errno = WTAP_ERR_CANT_READ;
449 bytes_read = file_read(pd, 1, length, fh);
451 if (bytes_read != length) {
452 *err = file_error(fh);
454 *err = WTAP_ERR_SHORT_READ;