Add some debugging code; the current code doesn't work when compiled
[obnox/wireshark/wip.git] / wiretap / aethra.c
1 /* aethra.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
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.
12  *
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.
17  *
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.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <errno.h>
27 #include <string.h>
28 #include "wtap-int.h"
29 #include "file_wrappers.h"
30 #include "buffer.h"
31 #include "aethra.h"
32
33 /* Magic number in Aethra PC108 files. */
34 #define MAGIC_SIZE      5
35
36 static const guchar aethra_magic[MAGIC_SIZE] = {
37         'V', '0', '2', '0', '8'
38 };
39
40 /* Aethra file header. */
41 struct aethra_hdr {
42         guchar  magic[MAGIC_SIZE];
43         guint8  unknown1[39];
44         guchar  sw_vers[60];    /* software version string, not null-terminated */
45         guint8  unknown2[118];
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 */
52         guint8  unknown4[2];
53         guint8  start_day[2];   /* day of capture start date */
54         guint8  unknown5[8];
55         guchar  com_info[16];   /* COM port and speed, null-padded(?) */
56         guint8  unknown6[107];
57         guchar  xxx_vers[29];   /* unknown version string (longer, null-padded?) */
58         guint8  unknown7[20];
59 };
60
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 */
68 };
69
70 /*
71  * Record types.
72  */
73 #define AETHRA_STOP_MONITOR     0       /* end of capture */
74 #define AETHRA_PACKET           1       /* packet */
75
76 /*
77  * Flags.
78  */
79 #define AETHRA_U_TO_N           0x01
80
81 typedef struct {
82         time_t  start;
83 } aethra_t;
84
85 static gboolean aethra_read(wtap *wth, int *err, gchar **err_info,
86     gint64 *data_offset);
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);
94
95 int aethra_open(wtap *wth, int *err, gchar **err_info)
96 {
97         int bytes_read;
98         struct aethra_hdr hdr;
99         struct tm tm;
100         aethra_t *aethra;
101
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);
107                 if (*err != 0)
108                         return -1;
109                 return 0;
110         }
111         wth->data_offset += sizeof hdr.magic;
112
113         if (memcmp(hdr.magic, aethra_magic, sizeof aethra_magic) != 0)
114                 return 0;
115
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);
122                 if (*err != 0)
123                         return -1;
124                 return 0;
125         }
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;
132
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);
135
136         /*
137          * Convert the time stamp to a "time_t".
138          */
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;
145         tm.tm_isdst = -1;
146         aethra->start = mktime(&tm);
147
148         /*
149          * We've only seen ISDN files, so, for now, we treat all
150          * files as ISDN.
151          */
152         wth->file_encap = WTAP_ENCAP_ISDN;
153         wth->snapshot_length = 0;       /* not available in header */
154         wth->tsprecision = WTAP_FILE_TSPREC_MSEC;
155         return 1;
156 }
157
158 /* Read the next packet */
159 static gboolean aethra_read(wtap *wth, int *err, gchar **err_info,
160     gint64 *data_offset)
161 {
162         aethra_t *aethra = (aethra_t *)wth->priv;
163         struct aethrarec_hdr hdr;
164         guint32 rec_size;
165         guint32 packet_size;
166         guint32 msecs;
167
168         /*
169          * Keep reading until we see an AETHRA_PACKET record or get
170          * an end-of-file.
171          */
172         do {
173                 *data_offset = wth->data_offset;
174
175                 /* Read record header. */
176                 if (!aethra_read_rec_header(wth->fh, &hdr, &wth->pseudo_header,
177                     err, err_info))
178 {
179 if (*err == 0)
180 fprintf(stderr, "aethra_read_rec_header() got an EOF\n");
181 else
182 fprintf(stderr, "aethra_read_rec_header() fails: err %d\n", *err);
183                         return FALSE;
184 }
185
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));
192                         return FALSE;
193                 }
194                 wth->data_offset += sizeof hdr;
195
196 fprintf(stderr, "sizeof hdr %" G_GINT64_MODIFIER "u, data_offset %" G_GINT64_MODIFIER "u\n",
197 (guint64)sizeof hdr, wth->data_offset);
198
199                 /*
200                  * XXX - if this is big, we might waste memory by
201                  * growing the buffer to handle it.
202                  */
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))
211 {
212 fprintf(stderr, "aethra_read_rec_data() fails\n");
213                                 return FALSE;   /* Read error */
214 }
215                         wth->data_offset += packet_size;
216 fprintf(stderr, "data_offset %" G_GINT64_MODIFIER "u\n",
217 wth->data_offset);
218                 }
219 fprintf(stderr, "hdr.rec_type %u\n", hdr.rec_type);
220         } while (hdr.rec_type != AETHRA_PACKET);
221
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;
227
228         return TRUE;
229 }
230
231 static gboolean
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)
235 {
236         struct aethrarec_hdr hdr;
237
238         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
239                 return FALSE;
240
241         if (!aethra_read_rec_header(wth->random_fh, &hdr, pseudo_header, err, err_info))
242                 return FALSE;
243
244         /*
245          * Read the packet data.
246          */
247         if (!aethra_read_rec_data(wth->random_fh, pd, length, err, err_info))
248                 return FALSE;   /* failed */
249
250         return TRUE;
251 }
252
253 static gboolean
254 aethra_read_rec_header(FILE_T fh, struct aethrarec_hdr *hdr,
255     union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
256 {
257         int     bytes_read;
258
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;
266                 return FALSE;
267         }
268
269         pseudo_header->isdn.uton = hdr->flags & AETHRA_U_TO_N;
270         pseudo_header->isdn.channel = 0;        /* XXX - D channel */
271
272         return TRUE;
273 }
274
275 static gboolean
276 aethra_read_rec_data(FILE_T fh, guint8 *pd, int length, int *err,
277     gchar **err_info)
278 {
279         int     bytes_read;
280
281         errno = WTAP_ERR_CANT_READ;
282         bytes_read = file_read(pd, length, fh);
283
284         if (bytes_read != length) {
285                 *err = file_error(fh, err_info);
286                 if (*err == 0)
287                         *err = WTAP_ERR_SHORT_READ;
288                 return FALSE;
289         }
290         return TRUE;
291 }