Olivier Abad's patch to add dissectors for LAP-B and X.25, and wiretap
[metze/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 <time.h>
27 #include "wtap.h"
28 #include "buffer.h"
29 #include "radcom.h"
30 #ifdef HAVE_NETINET_IN_H
31 #include <netinet/in.h>
32 #endif
33
34 struct frame_date {
35         guint16 year;
36         guint8  month;
37         guint8  day;
38         guint32 sec;            /* seconds since midnight */
39         guint32 usec;
40 };
41
42 static char radcom_magic[8] = {
43         0x42, 0xD2, 0x00, 0x34, 0x12, 0x66, 0x22, 0x88
44 };
45
46 /* Returns WTAP_FILE_RADCOM on success, WTAP_FILE_UNKNOWN on failure */
47 int radcom_open(wtap *wth)
48 {
49         int bytes_read;
50         char magic[8];
51         struct frame_date start_date;
52         struct tm tm;
53         char byte;
54         char encap_magic[7] = {0x54, 0x43, 0x50, 0x00, 0x42, 0x43, 0x09};
55         char search_encap[7];
56
57         /* Read in the string that should be at the start of a Sniffer file */
58         fseek(wth->fh, 0, SEEK_SET);
59         bytes_read = fread(magic, 1, 8, wth->fh);
60
61         if (bytes_read != 8) {
62                 return WTAP_FILE_UNKNOWN;
63         }
64
65         if (memcmp(magic, radcom_magic, 8)) {
66                 return WTAP_FILE_UNKNOWN;
67         }
68
69         /* This is a radcom file */
70         wth->capture.radcom = g_malloc(sizeof(radcom_t));
71         wth->subtype_read = radcom_read;
72         wth->snapshot_length = 16384;   /* not available in header, only in frame */
73         fseek(wth->fh, 0x8B, SEEK_SET);
74         bytes_read = fread(&byte, 1, 1, wth->fh);
75         if (bytes_read != 1) {
76                 return WTAP_FILE_UNKNOWN;
77         }
78         while (byte) {
79                 bytes_read = fread(&byte, 1, 1, wth->fh);
80                 if (bytes_read != 1) {
81                         return WTAP_FILE_UNKNOWN;
82                 }
83         }
84         fseek(wth->fh, 1, SEEK_CUR);
85
86         /* Get capture start time */
87         bytes_read = fread(&start_date, 1, sizeof(struct frame_date), wth->fh);
88
89         if (bytes_read != sizeof(struct frame_date)) {
90                 return WTAP_FILE_UNKNOWN;
91         }
92
93         tm.tm_year = start_date.year-1900;
94         tm.tm_mon = start_date.month-1;
95         tm.tm_mday = start_date.day;
96         tm.tm_hour = start_date.sec/3600;
97         tm.tm_min = (start_date.sec%3600)/60;
98         tm.tm_sec = start_date.sec%60;
99         tm.tm_isdst = -1;
100         wth->capture.radcom->start = mktime(&tm);
101
102         fseek(wth->fh, sizeof(struct frame_date), SEEK_CUR);
103
104         bytes_read = fread(search_encap, 1, 7, wth->fh);
105         if (bytes_read != 7) {
106                 return WTAP_FILE_UNKNOWN;
107         }
108         while (memcmp(encap_magic, search_encap, 7)) {
109                 fseek(wth->fh, -6, SEEK_CUR);
110                 bytes_read = fread(search_encap, 1, 7, wth->fh);
111                 if (bytes_read != 7) {
112                         return WTAP_FILE_UNKNOWN;
113                 }
114         }
115         fseek(wth->fh, 12, SEEK_CUR);
116         bytes_read = fread(search_encap, 1, 4, wth->fh);
117         if (bytes_read != 4) {
118                 return WTAP_FILE_UNKNOWN;
119         }
120         if (!memcmp(search_encap, "LAPB", 4))
121                 wth->file_encap = WTAP_ENCAP_LAPB;
122         else if (!memcmp(search_encap, "Ethe", 4))
123                 wth->file_encap = WTAP_ENCAP_ETHERNET;
124         else
125                 return WTAP_FILE_UNKNOWN;
126
127         /*bytes_read = fread(&next_date, 1, sizeof(struct frame_date), wth->fh);
128         if (bytes_read != sizeof(struct frame_date)) {
129                 return WTAP_FILE_UNKNOWN;
130         }
131
132         while (memcmp(&start_date, &next_date, 4)) {
133                 fseek(wth->fh, 1-sizeof(struct frame_date), SEEK_CUR);
134                 bytes_read = fread(&next_date, 1, sizeof(struct frame_date),
135                                    wth->fh);
136                 if (bytes_read != sizeof(struct frame_date)) {
137                         return WTAP_FILE_UNKNOWN;
138                 }
139         }*/
140
141         if (wth->file_encap == WTAP_ENCAP_ETHERNET)
142                 fseek(wth->fh, 294, SEEK_CUR);
143         else if (wth->file_encap == WTAP_ENCAP_LAPB)
144                 fseek(wth->fh, 297, SEEK_CUR);
145
146         return WTAP_FILE_RADCOM;
147 }
148
149 /* Read the next packet */
150 int radcom_read(wtap *wth)
151 {
152         int     bytes_read;
153         guint16 length;
154         struct frame_date date;
155         int     data_offset;
156         struct tm tm;
157         char dce;
158
159         fseek(wth->fh, 4, SEEK_CUR);
160
161         /*
162          * Read the frame size
163          */
164         bytes_read = fread(&length, 1, 2, wth->fh);
165         if (bytes_read != 2) {
166                 /*
167                  * End of file or error.
168                  */
169                 g_message("radcom_read: not enough frame data (%d bytes)",
170                         bytes_read);
171                 return 0;
172         }
173
174         if (wth->file_encap == WTAP_ENCAP_LAPB) length -= 2; /* FCS */
175
176         wth->phdr.len = length;
177         wth->phdr.caplen = length;
178
179         fseek(wth->fh, 5, SEEK_CUR);
180         bytes_read = fread(&date, 1, sizeof(struct frame_date), wth->fh);
181         if (bytes_read != sizeof(struct frame_date)) {
182                 /*
183                  * End of file or error.
184                  */
185                 g_message("radcom_read: not enough frame data (%d bytes)",
186                         bytes_read);
187                 return 0;
188         }
189
190         tm.tm_year = date.year-1900;
191         tm.tm_mon = date.month-1;
192         tm.tm_mday = date.day;
193         tm.tm_hour = date.sec/3600;
194         tm.tm_min = (date.sec%3600)/60;
195         tm.tm_sec = date.sec%60;
196         tm.tm_isdst = -1;
197         wth->phdr.ts.tv_sec = mktime(&tm);
198         wth->phdr.ts.tv_usec = date.usec;
199
200         fseek(wth->fh, 6, SEEK_CUR);
201         bytes_read = fread(&dce, 1, 1, wth->fh);
202         if (bytes_read != 1) {
203                 /*
204                  * End of file or error.
205                  */
206                 g_message("radcom_read: not enough frame data (%d bytes)",
207                         bytes_read);
208                 return 0;
209         }
210         wth->phdr.flags = (dce & 0x1) ? 0x00 : 0x80;
211
212         fseek(wth->fh, 9, SEEK_CUR);
213
214         /*
215          * Read the packet data.
216          */
217         buffer_assure_space(wth->frame_buffer, length);
218         data_offset = ftell(wth->fh);
219         bytes_read = fread(buffer_start_ptr(wth->frame_buffer), 1,
220                         length, wth->fh);
221
222         if (bytes_read != length) {
223                 if (ferror(wth->fh)) {
224                         g_message("radcom_read: fread for data: read error\n");
225                 } else {
226                         g_message("radcom_read: fread for data: %d bytes out of %d",
227                                 bytes_read, length);
228                 }
229                 return -1;
230         }
231
232         wth->phdr.pkt_encap = wth->file_encap;
233
234         if (wth->file_encap == WTAP_ENCAP_LAPB)
235                 fseek(wth->fh, 2, SEEK_CUR); /* FCS */
236
237         return data_offset;
238 }