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