Replace macros: BSWAP16, BSWAP32, BSWAP64 with glib-version.
[metze/wireshark/wip.git] / wiretap / i4btrace.c
1 /* i4btrace.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1999 by Bert Driehuis <driehuis@playbeing.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <errno.h>
27 #include <string.h>
28 #include "wtap-int.h"
29 #include "file_wrappers.h"
30 #include "buffer.h"
31 #include "i4b_trace.h"
32 #include "i4btrace.h"
33
34 typedef struct {
35         gboolean byte_swapped;
36 } i4btrace_t;
37
38 static gboolean i4btrace_read(wtap *wth, int *err, gchar **err_info,
39     gint64 *data_offset);
40 static gboolean i4btrace_seek_read(wtap *wth, gint64 seek_off,
41     struct wtap_pkthdr *phdr, Buffer *buf, int length,
42     int *err, gchar **err_info);
43 static int i4b_read_rec(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
44     Buffer *buf, int *err, gchar **err_info);
45
46 /*
47  * Test some fields in the header to see if they make sense.
48  */
49 #define I4B_HDR_IS_OK(hdr) \
50         (!((unsigned)hdr.length < 3 || (unsigned)hdr.length > 16384 || \
51             (unsigned)hdr.unit > 4 || (unsigned)hdr.type > 4 || \
52             (unsigned)hdr.dir > 2 || (unsigned)hdr.trunc > 2048))
53
54 int i4btrace_open(wtap *wth, int *err, gchar **err_info)
55 {
56         int bytes_read;
57         i4b_trace_hdr_t hdr;
58         gboolean byte_swapped = FALSE;
59         i4btrace_t *i4btrace;
60
61         /* I4B trace files have no magic in the header... Sigh */
62         errno = WTAP_ERR_CANT_READ;
63         bytes_read = file_read(&hdr, sizeof(hdr), wth->fh);
64         if (bytes_read != sizeof(hdr)) {
65                 *err = file_error(wth->fh, err_info);
66                 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
67                         return -1;
68                 return 0;
69         }
70
71         /* Silly heuristic... */
72         if (!I4B_HDR_IS_OK(hdr)) {
73                 /*
74                  * OK, try byte-swapping the header fields.
75                  */
76                 hdr.length = GUINT32_SWAP_LE_BE(hdr.length);
77                 hdr.unit = GUINT32_SWAP_LE_BE(hdr.unit);
78                 hdr.type = GUINT32_SWAP_LE_BE(hdr.type);
79                 hdr.dir = GUINT32_SWAP_LE_BE(hdr.dir);
80                 hdr.trunc = GUINT32_SWAP_LE_BE(hdr.trunc);
81                 if (!I4B_HDR_IS_OK(hdr)) {
82                         /*
83                          * It doesn't look valid in either byte order.
84                          */
85                         return 0;
86                 }
87
88                 /*
89                  * It looks valid byte-swapped, so assume it's a
90                  * trace written in the opposite byte order.
91                  */
92                 byte_swapped = TRUE;
93         }
94
95         if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
96                 return -1;
97
98         /* Get capture start time */
99
100         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_I4BTRACE;
101         i4btrace = (i4btrace_t *)g_malloc(sizeof(i4btrace_t));
102         wth->priv = (void *)i4btrace;
103         wth->subtype_read = i4btrace_read;
104         wth->subtype_seek_read = i4btrace_seek_read;
105         wth->snapshot_length = 0;       /* not known */
106
107         i4btrace->byte_swapped = byte_swapped;
108
109         wth->file_encap = WTAP_ENCAP_ISDN;
110         wth->tsprecision = WTAP_FILE_TSPREC_USEC;
111
112         return 1;
113 }
114
115 /* Read the next packet */
116 static gboolean i4btrace_read(wtap *wth, int *err, gchar **err_info,
117     gint64 *data_offset)
118 {
119         *data_offset = file_tell(wth->fh);
120
121         return i4b_read_rec(wth, wth->fh, &wth->phdr, wth->frame_buffer,
122             err, err_info);
123 }
124
125 static gboolean
126 i4btrace_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
127     Buffer *buf, int length _U_, int *err, gchar **err_info)
128 {
129         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
130                 return FALSE;
131
132         if (!i4b_read_rec(wth, wth->random_fh, phdr, buf, err, err_info)) {
133                 /* Read error or EOF */
134                 if (*err == 0) {
135                         /* EOF means "short read" in random-access mode */
136                         *err = WTAP_ERR_SHORT_READ;
137                 }
138                 return FALSE;
139         }
140         return TRUE;
141 }
142
143 static int
144 i4b_read_rec(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
145     int *err, gchar **err_info)
146 {
147         i4btrace_t *i4btrace = (i4btrace_t *)wth->priv;
148         i4b_trace_hdr_t hdr;
149         int     bytes_read;
150         guint32 length;
151
152         errno = WTAP_ERR_CANT_READ;
153         bytes_read = file_read(&hdr, sizeof hdr, fh);
154         if (bytes_read != sizeof hdr) {
155                 *err = file_error(fh, err_info);
156                 if (*err == 0 && bytes_read != 0) {
157                         /* Read something, but not enough */
158                         *err = WTAP_ERR_SHORT_READ;
159                 }
160                 return FALSE;
161         }
162
163         if (i4btrace->byte_swapped) {
164                 /*
165                  * Byte-swap the header.
166                  */
167                 hdr.length = GUINT32_SWAP_LE_BE(hdr.length);
168                 hdr.unit = GUINT32_SWAP_LE_BE(hdr.unit);
169                 hdr.type = GUINT32_SWAP_LE_BE(hdr.type);
170                 hdr.dir = GUINT32_SWAP_LE_BE(hdr.dir);
171                 hdr.trunc = GUINT32_SWAP_LE_BE(hdr.trunc);
172                 hdr.count = GUINT32_SWAP_LE_BE(hdr.count);
173                 hdr.ts_sec = GUINT32_SWAP_LE_BE(hdr.ts_sec);
174                 hdr.ts_usec = GUINT32_SWAP_LE_BE(hdr.ts_usec);
175         }
176
177         if (hdr.length < sizeof(hdr)) {
178                 *err = WTAP_ERR_BAD_FILE;       /* record length < header! */
179                 *err_info = g_strdup_printf("i4btrace: record length %u < header length %lu",
180                     hdr.length, (unsigned long)sizeof(hdr));
181                 return FALSE;
182         }
183         length = hdr.length - (guint32)sizeof(hdr);
184         if (length > WTAP_MAX_PACKET_SIZE) {
185                 /*
186                  * Probably a corrupt capture file; don't blow up trying
187                  * to allocate space for an immensely-large packet.
188                  */
189                 *err = WTAP_ERR_BAD_FILE;
190                 *err_info = g_strdup_printf("i4btrace: File has %u-byte packet, bigger than maximum of %u",
191                     length, WTAP_MAX_PACKET_SIZE);
192                 return FALSE;
193         }
194
195         phdr->presence_flags = WTAP_HAS_TS;
196
197         phdr->len = length;
198         phdr->caplen = length;
199
200         phdr->ts.secs = hdr.ts_sec;
201         phdr->ts.nsecs = hdr.ts_usec * 1000;
202
203         switch (hdr.type) {
204
205         case TRC_CH_I:
206                 /*
207                  * XXX - what is it?  It's probably not WTAP_ENCAP_NULL,
208                  * as that means it has a 4-byte AF_ type as the
209                  * encapsulation header.
210                  */
211                 phdr->pkt_encap = WTAP_ENCAP_NULL;
212                 break;
213
214         case TRC_CH_D:
215                 /*
216                  * D channel, so it's LAPD; set "p2p.sent".
217                  */
218                 phdr->pkt_encap = WTAP_ENCAP_ISDN;
219                 phdr->pseudo_header.isdn.channel = 0;
220                 break;
221
222         case TRC_CH_B1:
223                 /*
224                  * B channel 1.
225                  */
226                 phdr->pkt_encap = WTAP_ENCAP_ISDN;
227                 phdr->pseudo_header.isdn.channel = 1;
228                 break;
229
230         case TRC_CH_B2:
231                 /*
232                  * B channel 2.
233                  */
234                 phdr->pkt_encap = WTAP_ENCAP_ISDN;
235                 phdr->pseudo_header.isdn.channel = 2;
236                 break;
237         }
238
239         phdr->pseudo_header.isdn.uton = (hdr.dir == FROM_TE);
240
241         /*
242          * Read the packet data.
243          */
244         return wtap_read_packet_bytes(fh, buf, length, err, err_info);
245 }