Fixes from Olivier Abad to the code to maintain "wth->data_offset".
[obnox/wireshark/wip.git] / wiretap / radcom.c
1 /* radcom.c
2  *
3  * Wiretap Library
4  * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
5  * 
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <time.h>
28 #include "wtap.h"
29 #include "buffer.h"
30 #include "radcom.h"
31
32 struct frame_date {
33         guint16 year;
34         guint8  month;
35         guint8  day;
36         guint32 sec;            /* seconds since midnight */
37         guint32 usec;
38 };
39
40 static char radcom_magic[8] = {
41         0x42, 0xD2, 0x00, 0x34, 0x12, 0x66, 0x22, 0x88
42 };
43
44 static int radcom_read(wtap *wth, int *err);
45
46 int radcom_open(wtap *wth, int *err)
47 {
48         int bytes_read;
49         char magic[8];
50         struct frame_date start_date;
51         struct tm tm;
52         char byte;
53         char encap_magic[7] = {0x54, 0x43, 0x50, 0x00, 0x42, 0x43, 0x09};
54         char search_encap[7];
55
56         /* Read in the string that should be at the start of a RADCOM file */
57         fseek(wth->fh, 0, SEEK_SET);
58         errno = WTAP_ERR_CANT_READ;
59         bytes_read = fread(magic, 1, 8, wth->fh);
60         if (bytes_read != 8) {
61                 if (ferror(wth->fh)) {
62                         *err = errno;
63                         return -1;
64                 }
65                 return 0;
66         }
67
68         if (memcmp(magic, radcom_magic, 8)) {
69                 return 0;
70         }
71
72         fseek(wth->fh, 0x8B, SEEK_SET);
73         wth->data_offset = 0x8B;
74         errno = WTAP_ERR_CANT_READ;
75         bytes_read = fread(&byte, 1, 1, wth->fh);
76         if (bytes_read != 1) {
77                 if (ferror(wth->fh)) {
78                         *err = errno;
79                         return -1;
80                 }
81                 return 0;
82         }
83         wth->data_offset += 1;
84         while (byte) {
85                 errno = WTAP_ERR_CANT_READ;
86                 bytes_read = fread(&byte, 1, 1, wth->fh);
87                 if (bytes_read != 1) {
88                         if (ferror(wth->fh)) {
89                                 *err = errno;
90                                 return -1;
91                         }
92                         return 0;
93                 }
94                 wth->data_offset += 1;
95         }
96         fseek(wth->fh, 1, SEEK_CUR);
97         wth->data_offset += 1;
98
99         /* Get capture start time */
100         errno = WTAP_ERR_CANT_READ;
101         bytes_read = fread(&start_date, 1, sizeof(struct frame_date), wth->fh);
102         if (bytes_read != sizeof(struct frame_date)) {
103                 if (ferror(wth->fh)) {
104                         *err = errno;
105                         return -1;
106                 }
107                 return 0;
108         }
109         wth->data_offset += sizeof(struct frame_date);
110
111         /* This is a radcom file */
112         wth->file_type = WTAP_FILE_RADCOM;
113         wth->capture.radcom = g_malloc(sizeof(radcom_t));
114         wth->subtype_read = radcom_read;
115         wth->snapshot_length = 16384;   /* not available in header, only in frame */
116
117         tm.tm_year = pletohs(&start_date.year)-1900;
118         tm.tm_mon = start_date.month-1;
119         tm.tm_mday = start_date.day;
120         tm.tm_hour = start_date.sec/3600;
121         tm.tm_min = (start_date.sec%3600)/60;
122         tm.tm_sec = pletohl(&start_date.sec)%60;
123         tm.tm_isdst = -1;
124         wth->capture.radcom->start = mktime(&tm);
125
126         fseek(wth->fh, sizeof(struct frame_date), SEEK_CUR);
127         wth->data_offset += sizeof(struct frame_date);
128
129         errno = WTAP_ERR_CANT_READ;
130         bytes_read = fread(search_encap, 1, 7, wth->fh);
131         if (bytes_read != 7) {
132                 goto read_error;
133         }
134         wth->data_offset += 7;
135         while (memcmp(encap_magic, search_encap, 7)) {
136                 fseek(wth->fh, -6, SEEK_CUR);
137                 wth->data_offset -= 6;
138                 errno = WTAP_ERR_CANT_READ;
139                 bytes_read = fread(search_encap, 1, 7, wth->fh);
140                 if (bytes_read != 7) {
141                         goto read_error;
142                 }
143                 wth->data_offset += 7;
144         }
145         fseek(wth->fh, 12, SEEK_CUR);
146         wth->data_offset += 12;
147         errno = WTAP_ERR_CANT_READ;
148         bytes_read = fread(search_encap, 1, 4, wth->fh);
149         if (bytes_read != 4) {
150                 goto read_error;
151         }
152         wth->data_offset += 4;
153         if (!memcmp(search_encap, "LAPB", 4))
154                 wth->file_encap = WTAP_ENCAP_LAPB;
155         else if (!memcmp(search_encap, "Ethe", 4))
156                 wth->file_encap = WTAP_ENCAP_ETHERNET;
157         else {
158                 g_message("pcap: network type \"%.4s\" unknown", search_encap);
159                 *err = WTAP_ERR_UNSUPPORTED;
160                 return -1;
161         }
162
163         /*bytes_read = fread(&next_date, 1, sizeof(struct frame_date), wth->fh);
164         errno = WTAP_ERR_CANT_READ;
165         if (bytes_read != sizeof(struct frame_date)) {
166                 goto read_error;
167         }
168
169         while (memcmp(&start_date, &next_date, 4)) {
170                 fseek(wth->fh, 1-sizeof(struct frame_date), SEEK_CUR);
171                 errno = WTAP_ERR_CANT_READ;
172                 bytes_read = fread(&next_date, 1, sizeof(struct frame_date),
173                                    wth->fh);
174                 if (bytes_read != sizeof(struct frame_date)) {
175                         goto read_error;
176                 }
177         }*/
178
179         if (wth->file_encap == WTAP_ENCAP_ETHERNET) {
180                 fseek(wth->fh, 294, SEEK_CUR);
181                 wth->data_offset += 294;
182         } else if (wth->file_encap == WTAP_ENCAP_LAPB) {
183                 fseek(wth->fh, 297, SEEK_CUR);
184                 wth->data_offset += 297;
185         }
186
187         return 1;
188
189 read_error:
190         if (ferror(wth->fh)) {
191                 *err = errno;
192                 free(wth->capture.radcom);
193                 return -1;
194         }
195         free(wth->capture.radcom);
196         return 0;
197 }
198
199 /* Read the next packet */
200 static int radcom_read(wtap *wth, int *err)
201 {
202         int     bytes_read;
203         guint16 length;
204         struct frame_date date;
205         int     data_offset;
206         struct tm tm;
207         char dce;
208
209         fseek(wth->fh, 4, SEEK_CUR);
210         wth->data_offset += 4;
211
212         /*
213          * Read the frame size
214          */
215         errno = WTAP_ERR_CANT_READ;
216         bytes_read = fread(&length, 1, 2, wth->fh);
217         if (bytes_read != 2) {
218                 if (ferror(wth->fh)) {
219                         *err = errno;
220                         return -1;
221                 }
222                 if (bytes_read != 0) {
223                         *err = WTAP_ERR_SHORT_READ;
224                         return -1;
225                 }
226                 return 0;
227         }
228         wth->data_offset += 2;
229         length = pletohs(&length);
230
231         if (wth->file_encap == WTAP_ENCAP_LAPB)
232                 length -= 2; /* FCS */
233
234         wth->phdr.len = length;
235         wth->phdr.caplen = length;
236
237         fseek(wth->fh, 5, SEEK_CUR);
238         wth->data_offset += 5;
239         errno = WTAP_ERR_CANT_READ;
240         bytes_read = fread(&date, 1, sizeof(struct frame_date), wth->fh);
241         if (bytes_read != sizeof(struct frame_date)) {
242                 if (ferror(wth->fh))
243                         *err = errno;
244                 else
245                         *err = WTAP_ERR_SHORT_READ;
246                 return -1;
247         }
248         wth->data_offset += sizeof(struct frame_date);
249
250         tm.tm_year = pletohs(&date.year)-1900;
251         tm.tm_mon = date.month-1;
252         tm.tm_mday = date.day;
253         tm.tm_hour = date.sec/3600;
254         tm.tm_min = (date.sec%3600)/60;
255         tm.tm_sec = pletohl(&date.sec)%60;
256         tm.tm_isdst = -1;
257         wth->phdr.ts.tv_sec = mktime(&tm);
258         wth->phdr.ts.tv_usec = pletohl(&date.usec);
259
260         fseek(wth->fh, 6, SEEK_CUR);
261         wth->data_offset += 6;
262         errno = WTAP_ERR_CANT_READ;
263         bytes_read = fread(&dce, 1, 1, wth->fh);
264         if (bytes_read != 1) {
265                 if (ferror(wth->fh))
266                         *err = errno;
267                 else
268                         *err = WTAP_ERR_SHORT_READ;
269                 return -1;
270         }
271         wth->data_offset += 1;
272         wth->phdr.pseudo_header.x25.flags = (dce & 0x1) ? 0x00 : 0x80;
273
274         fseek(wth->fh, 9, SEEK_CUR);
275         wth->data_offset += 9;
276
277         /*
278          * Read the packet data.
279          */
280         buffer_assure_space(wth->frame_buffer, length);
281         data_offset = wth->data_offset;
282         errno = WTAP_ERR_CANT_READ;
283         bytes_read = fread(buffer_start_ptr(wth->frame_buffer), 1,
284                         length, wth->fh);
285
286         if (bytes_read != length) {
287                 if (ferror(wth->fh))
288                         *err = errno;
289                 else
290                         *err = WTAP_ERR_SHORT_READ;
291                 return -1;
292         }
293         wth->data_offset += length;
294
295         wth->phdr.pkt_encap = wth->file_encap;
296
297         if (wth->file_encap == WTAP_ENCAP_LAPB) {
298                 fseek(wth->fh, 2, SEEK_CUR); /* FCS */
299                 wth->data_offset += 2;
300         }
301
302         return data_offset;
303 }