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.
29 #include "file_wrappers.h"
33 /* Magic number in Aethra PC108 files. */
36 static const guchar aethra_magic[MAGIC_SIZE] = {
37 'V', '0', '2', '0', '8'
40 /* Aethra file header. */
42 guchar magic[MAGIC_SIZE];
44 guchar sw_vers[60]; /* software version string, not null-terminated */
46 guint8 start_sec; /* seconds of capture start time */
47 guint8 start_min; /* minutes of capture start time */
48 guint8 start_hour; /* hour of capture start time */
49 guint8 unknown3[5007];
50 guint8 start_year[2]; /* year of capture start date */
51 guint8 start_month[2]; /* month of capture start date */
53 guint8 start_day[2]; /* day of capture start date */
55 guchar com_info[16]; /* COM port and speed, null-padded(?) */
57 guchar xxx_vers[29]; /* unknown version string (longer, null-padded?) */
61 /* Aethra record header. Yes, the alignment is weird.
62 All multi-byte fields are little-endian. */
63 struct aethrarec_hdr {
64 guint8 rec_size[2]; /* record length, not counting the length itself */
65 guint8 rec_type; /* record type */
66 guint8 timestamp[4]; /* milliseconds since start of capture */
67 guint8 flags; /* low-order bit: 0 = N->U, 1 = U->N */
73 #define AETHRA_STOP_MONITOR 0 /* end of capture */
74 #define AETHRA_PACKET 1 /* packet */
79 #define AETHRA_U_TO_N 0x01
85 static gboolean aethra_read(wtap *wth, int *err, gchar **err_info,
87 static gboolean aethra_seek_read(wtap *wth, gint64 seek_off,
88 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
89 int *err, gchar **err_info);
90 static gboolean aethra_read_rec_header(FILE_T fh, struct aethrarec_hdr *hdr,
91 union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
92 static gboolean aethra_read_rec_data(FILE_T fh, guint8 *pd, int length,
93 int *err, gchar **err_info);
95 int aethra_open(wtap *wth, int *err, gchar **err_info)
98 struct aethra_hdr hdr;
102 /* Read in the string that should be at the start of a "aethra" file */
103 errno = WTAP_ERR_CANT_READ;
104 bytes_read = file_read(hdr.magic, sizeof hdr.magic, wth->fh);
105 if (bytes_read != sizeof hdr.magic) {
106 *err = file_error(wth->fh, err_info);
111 wth->data_offset += sizeof hdr.magic;
113 if (memcmp(hdr.magic, aethra_magic, sizeof aethra_magic) != 0)
116 /* Read the rest of the header. */
117 errno = WTAP_ERR_CANT_READ;
118 bytes_read = file_read((char *)&hdr + sizeof hdr.magic,
119 sizeof hdr - sizeof hdr.magic, wth->fh);
120 if (bytes_read != sizeof hdr - sizeof hdr.magic) {
121 *err = file_error(wth->fh, err_info);
126 wth->data_offset += sizeof hdr - sizeof hdr.magic;
127 wth->file_type = WTAP_FILE_AETHRA;
128 aethra = (aethra_t *)g_malloc(sizeof(aethra_t));
129 wth->priv = (void *)aethra;
130 wth->subtype_read = aethra_read;
131 wth->subtype_seek_read = aethra_seek_read;
133 fprintf(stderr, "sizeof hdr.magic %" G_GINT64_MODIFIER "u, sizeof hdr %" G_GINT64_MODIFIER "u, data_offset %" G_GINT64_MODIFIER "u\n",
134 (guint64)sizeof hdr.magic, (guint64)sizeof hdr, wth->data_offset);
137 * Convert the time stamp to a "time_t".
139 tm.tm_year = pletohs(&hdr.start_year) - 1900;
140 tm.tm_mon = pletohs(&hdr.start_month) - 1;
141 tm.tm_mday = pletohs(&hdr.start_day);
142 tm.tm_hour = hdr.start_hour;
143 tm.tm_min = hdr.start_min;
144 tm.tm_sec = hdr.start_sec;
146 aethra->start = mktime(&tm);
149 * We've only seen ISDN files, so, for now, we treat all
152 wth->file_encap = WTAP_ENCAP_ISDN;
153 wth->snapshot_length = 0; /* not available in header */
154 wth->tsprecision = WTAP_FILE_TSPREC_MSEC;
158 /* Read the next packet */
159 static gboolean aethra_read(wtap *wth, int *err, gchar **err_info,
162 aethra_t *aethra = (aethra_t *)wth->priv;
163 struct aethrarec_hdr hdr;
169 * Keep reading until we see an AETHRA_PACKET record or get
173 *data_offset = wth->data_offset;
175 /* Read record header. */
176 if (!aethra_read_rec_header(wth->fh, &hdr, &wth->pseudo_header,
180 fprintf(stderr, "aethra_read_rec_header() got an EOF\n");
182 fprintf(stderr, "aethra_read_rec_header() fails: err %d\n", *err);
186 rec_size = pletohs(hdr.rec_size);
187 if (rec_size < (sizeof hdr - sizeof hdr.rec_size)) {
188 /* The record is shorter than a record header. */
189 *err = WTAP_ERR_BAD_RECORD;
190 *err_info = g_strdup_printf("aethra: File has %u-byte record, less than minimum of %u",
191 rec_size, (unsigned int)(sizeof hdr - sizeof hdr.rec_size));
194 wth->data_offset += sizeof hdr;
196 fprintf(stderr, "sizeof hdr %" G_GINT64_MODIFIER "u, data_offset %" G_GINT64_MODIFIER "u\n",
197 (guint64)sizeof hdr, wth->data_offset);
200 * XXX - if this is big, we might waste memory by
201 * growing the buffer to handle it.
203 packet_size = rec_size - (sizeof hdr - sizeof hdr.rec_size);
204 fprintf(stderr, "rec_size %u, packet_size %u, sizeof hdr.rec_size %" G_GINT64_MODIFIER "u, delta %" G_GINT64_MODIFIER "u\n",
205 rec_size, packet_size, (guint64)sizeof hdr.rec_size,
206 (guint64)(sizeof hdr - sizeof hdr.rec_size));
207 if (packet_size != 0) {
208 buffer_assure_space(wth->frame_buffer, packet_size);
209 if (!aethra_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
210 packet_size, err, err_info))
212 fprintf(stderr, "aethra_read_rec_data() fails\n");
213 return FALSE; /* Read error */
215 wth->data_offset += packet_size;
216 fprintf(stderr, "data_offset %" G_GINT64_MODIFIER "u\n",
219 fprintf(stderr, "hdr.rec_type %u\n", hdr.rec_type);
220 } while (hdr.rec_type != AETHRA_PACKET);
222 msecs = pletohl(hdr.timestamp);
223 wth->phdr.ts.secs = aethra->start + (msecs / 1000);
224 wth->phdr.ts.nsecs = (msecs % 1000) * 1000000;
225 wth->phdr.caplen = packet_size;
226 wth->phdr.len = packet_size;
232 aethra_seek_read(wtap *wth, gint64 seek_off,
233 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
234 int *err, gchar **err_info)
236 struct aethrarec_hdr hdr;
238 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
241 if (!aethra_read_rec_header(wth->random_fh, &hdr, pseudo_header, err, err_info))
245 * Read the packet data.
247 if (!aethra_read_rec_data(wth->random_fh, pd, length, err, err_info))
248 return FALSE; /* failed */
254 aethra_read_rec_header(FILE_T fh, struct aethrarec_hdr *hdr,
255 union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
259 /* Read record header. */
260 errno = WTAP_ERR_CANT_READ;
261 bytes_read = file_read(hdr, sizeof hdr, fh);
262 if (bytes_read != sizeof *hdr) {
263 *err = file_error(fh, err_info);
264 if (*err == 0 && bytes_read != 0)
265 *err = WTAP_ERR_SHORT_READ;
269 pseudo_header->isdn.uton = hdr->flags & AETHRA_U_TO_N;
270 pseudo_header->isdn.channel = 0; /* XXX - D channel */
276 aethra_read_rec_data(FILE_T fh, guint8 *pd, int length, int *err,
281 errno = WTAP_ERR_CANT_READ;
282 bytes_read = file_read(pd, length, fh);
284 if (bytes_read != length) {
285 *err = file_error(fh, err_info);
287 *err = WTAP_ERR_SHORT_READ;