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