epan: use json_dumper for json outputs.
[metze/wireshark/wip.git] / wiretap / aethra.c
1 /* aethra.c
2  *
3  * Wiretap Library
4  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8
9 #include "config.h"
10 #include <errno.h>
11 #include <string.h>
12 #include "wtap-int.h"
13 #include "file_wrappers.h"
14 #include "aethra.h"
15
16 /* Magic number in Aethra PC108 files. */
17 #define MAGIC_SIZE      5
18
19 static const guchar aethra_magic[MAGIC_SIZE] = {
20         'V', '0', '2', '0', '8'
21 };
22
23 /* Aethra file header. */
24 struct aethra_hdr {
25         guchar  magic[MAGIC_SIZE];
26         guint8  unknown1[39];   /* 5-43 */
27         guchar  sw_vers[60];    /* 44-103 - software version string, not null-terminated */
28         guint8  unknown2[118];  /* 104-221 */
29         guint8  start_sec;      /* 222 - seconds of capture start time */
30         guint8  start_min;      /* 223 - minutes of capture start time */
31         guint8  start_hour;     /* 224 - hour of capture start time */
32         guint8  unknown3[462];  /* 225-686 */
33         guchar  xxx_string[37]; /* 687-723 - null-terminated short comment string? */
34         guint8  unknown3_5[4];  /* 724-727 */
35         guchar  yyy_string[4504];/* 728-5231 - null-terminated long comment string? */
36         guint8  start_year[2];  /* 5232-5233 - year of capture start date */
37         guint8  start_month[2]; /* 5234-5235 - month of capture start date */
38         guint8  unknown4[2];    /* 5236-5237 */
39         guint8  start_day[2];   /* 5238-5239 - day of capture start date */
40         guint8  unknown5[8];    /* 5240-5247 */
41         guchar  com_info[16];   /* 5248-5263 - COM port and speed, null-padded(?) */
42         guint8  unknown6[107];  /* 5264-5370 */
43         guchar  xxx_vers[41];   /* 5371-5411 - unknown version string (longer, null-padded?) */
44 };
45
46 /* Aethra record header.  Yes, the alignment is weird.
47    All multi-byte fields are little-endian. */
48 struct aethrarec_hdr {
49         guint8 rec_size[2];     /* record length, not counting the length itself */
50         guint8 rec_type;        /* record type */
51         guint8 timestamp[4];    /* milliseconds since start of capture */
52         guint8 flags;           /* low-order bit: 0 = N->U, 1 = U->N */
53 };
54
55 /*
56  * Record types.
57  *
58  * As the indications from the device and signalling messages appear not
59  * to have the 8th bit set, and at least some B-channel records do, we
60  * assume, for now, that the 8th bit indicates bearer information.
61  *
62  * 0x9F is the record type seen for B31 channel records; that might be
63  * 0x80|31, so, for now, we assume that if the 8th bit is set, the B
64  * channel number is in the low 7 bits.
65  */
66 #define AETHRA_BEARER           0x80    /* bearer information */
67
68 #define AETHRA_DEVICE           0x00    /* indication from the monitoring device */
69 #define AETHRA_ISDN_LINK        0x01    /* information from the ISDN link */
70
71 /*
72  * In AETHRA_DEVICE records, the flags field has what appears to
73  * be a record subtype.
74  */
75 #define AETHRA_DEVICE_STOP_MONITOR      0x00    /* Stop Monitor */
76 #define AETHRA_DEVICE_START_MONITOR     0x04    /* Start Monitor */
77 #define AETHRA_DEVICE_ACTIVATION        0x05    /* Activation */
78 #define AETHRA_DEVICE_START_CAPTURE     0x5F    /* Start Capture */
79
80 /*
81  * In AETHRA_ISDN_LINK and bearer channel records, the flags field has
82  * a direction flag and possibly some other bits.
83  *
84  * In AETHRA_ISDN_LINK records, at least some of the other bits are
85  * a subtype.
86  *
87  * In bearer channel records, there are records with data and
88  * "Constant Value" records with a single byte.  Data has a
89  * flags value of 0x14 ORed with the direction flag, and Constant Value
90  * records have a flags value of 0x16 ORed with the direction flag.
91  * There are also records of an unknown type with 0x02, probably
92  * ORed with the direction flag.
93  */
94 #define AETHRA_U_TO_N                           0x01    /* set for TE->NT */
95
96 #define AETHRA_ISDN_LINK_SUBTYPE                0xFE
97 #define AETHRA_ISDN_LINK_LAPD                   0x00    /* LAPD frame */
98 #define AETHRA_ISDN_LINK_SA_BITS                0x2E    /* 2048K PRI Sa bits (G.704 section 2.3.2) */
99 #define AETHRA_ISDN_LINK_ALL_ALARMS_CLEARED     0x30    /* All Alarms Cleared */
100
101 typedef struct {
102         time_t  start;
103 } aethra_t;
104
105 static gboolean aethra_read(wtap *wth, int *err, gchar **err_info,
106     gint64 *data_offset);
107 static gboolean aethra_seek_read(wtap *wth, gint64 seek_off,
108     wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
109 static gboolean aethra_read_rec_header(wtap *wth, FILE_T fh, struct aethrarec_hdr *hdr,
110     wtap_rec *rec, int *err, gchar **err_info);
111
112 wtap_open_return_val aethra_open(wtap *wth, int *err, gchar **err_info)
113 {
114         struct aethra_hdr hdr;
115         struct tm tm;
116         aethra_t *aethra;
117
118         /* Read in the string that should be at the start of a "aethra" file */
119         if (!wtap_read_bytes(wth->fh, hdr.magic, sizeof hdr.magic, err,
120             err_info)) {
121                 if (*err != WTAP_ERR_SHORT_READ)
122                         return WTAP_OPEN_ERROR;
123                 return WTAP_OPEN_NOT_MINE;
124         }
125
126         if (memcmp(hdr.magic, aethra_magic, sizeof aethra_magic) != 0)
127                 return WTAP_OPEN_NOT_MINE;
128
129         /* Read the rest of the header. */
130         if (!wtap_read_bytes(wth->fh, (char *)&hdr + sizeof hdr.magic,
131             sizeof hdr - sizeof hdr.magic, err, err_info))
132                 return WTAP_OPEN_ERROR;
133         wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_AETHRA;
134         aethra = (aethra_t *)g_malloc(sizeof(aethra_t));
135         wth->priv = (void *)aethra;
136         wth->subtype_read = aethra_read;
137         wth->subtype_seek_read = aethra_seek_read;
138
139         /*
140          * Convert the time stamp to a "time_t".
141          */
142         tm.tm_year = pletoh16(&hdr.start_year) - 1900;
143         tm.tm_mon = pletoh16(&hdr.start_month) - 1;
144         tm.tm_mday = pletoh16(&hdr.start_day);
145         tm.tm_hour = hdr.start_hour;
146         tm.tm_min = hdr.start_min;
147         tm.tm_sec = hdr.start_sec;
148         tm.tm_isdst = -1;
149         aethra->start = mktime(&tm);
150
151         /*
152          * We've only seen ISDN files, so, for now, we treat all
153          * files as ISDN.
154          */
155         wth->file_encap = WTAP_ENCAP_ISDN;
156         wth->snapshot_length = 0;       /* not available in header */
157         wth->file_tsprec = WTAP_TSPREC_MSEC;
158         return WTAP_OPEN_MINE;
159 }
160
161 #if 0
162 static guint packet = 0;
163 #endif
164
165 /* Read the next packet */
166 static gboolean aethra_read(wtap *wth, int *err, gchar **err_info,
167     gint64 *data_offset)
168 {
169         struct aethrarec_hdr hdr;
170
171         /*
172          * Keep reading until we see an AETHRA_ISDN_LINK with a subtype
173          * of AETHRA_ISDN_LINK_LAPD record or get an end-of-file.
174          */
175         for (;;) {
176                 *data_offset = file_tell(wth->fh);
177
178                 /* Read record header. */
179                 if (!aethra_read_rec_header(wth, wth->fh, &hdr, &wth->rec, err, err_info))
180                         return FALSE;
181
182                 /*
183                  * XXX - if this is big, we might waste memory by
184                  * growing the buffer to handle it.
185                  */
186                 if (wth->rec.rec_header.packet_header.caplen != 0) {
187                         if (!wtap_read_packet_bytes(wth->fh, wth->rec_data,
188                             wth->rec.rec_header.packet_header.caplen, err, err_info))
189                                 return FALSE;   /* Read error */
190                 }
191 #if 0
192 packet++;
193 #endif
194                 switch (hdr.rec_type) {
195
196                 case AETHRA_ISDN_LINK:
197 #if 0
198 fprintf(stderr, "Packet %u: type 0x%02x (AETHRA_ISDN_LINK)\n",
199 packet, hdr.rec_type);
200 #endif
201                         switch (hdr.flags & AETHRA_ISDN_LINK_SUBTYPE) {
202
203                         case AETHRA_ISDN_LINK_LAPD:
204                                 /*
205                                  * The data is a LAPD frame.
206                                  */
207 #if 0
208 fprintf(stderr, "    subtype 0x%02x (AETHRA_ISDN_LINK_LAPD)\n", hdr.flags & AETHRA_ISDN_LINK_SUBTYPE);
209 #endif
210                                 goto found;
211
212                         case AETHRA_ISDN_LINK_SA_BITS:
213                                 /*
214                                  * These records have one data byte, which
215                                  * has the Sa bits in the lower 5 bits.
216                                  *
217                                  * XXX - what about stuff other than 2048K
218                                  * PRI lines?
219                                  */
220 #if 0
221 fprintf(stderr, "    subtype 0x%02x (AETHRA_ISDN_LINK_SA_BITS)\n", hdr.flags & AETHRA_ISDN_LINK_SUBTYPE);
222 #endif
223                                 break;
224
225                         case AETHRA_ISDN_LINK_ALL_ALARMS_CLEARED:
226                                 /*
227                                  * No data, just an "all alarms cleared"
228                                  * indication.
229                                  */
230 #if 0
231 fprintf(stderr, "    subtype 0x%02x (AETHRA_ISDN_LINK_ALL_ALARMS_CLEARED)\n", hdr.flags & AETHRA_ISDN_LINK_SUBTYPE);
232 #endif
233                                 break;
234
235                         default:
236 #if 0
237 fprintf(stderr, "    subtype 0x%02x, packet_size %u, direction 0x%02x\n",
238 hdr.flags & AETHRA_ISDN_LINK_SUBTYPE, wth->rec.rec_header.packet_header.caplen, hdr.flags & AETHRA_U_TO_N);
239 #endif
240                                 break;
241                         }
242                         break;
243
244                 default:
245 #if 0
246 fprintf(stderr, "Packet %u: type 0x%02x, packet_size %u, flags 0x%02x\n",
247 packet, hdr.rec_type, wth->rec.rec_header.packet_header.caplen, hdr.flags);
248 #endif
249                         break;
250                 }
251         }
252
253 found:
254         return TRUE;
255 }
256
257 static gboolean
258 aethra_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec,
259     Buffer *buf, int *err, gchar **err_info)
260 {
261         struct aethrarec_hdr hdr;
262
263         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
264                 return FALSE;
265
266         if (!aethra_read_rec_header(wth, wth->random_fh, &hdr, rec, err,
267             err_info)) {
268                 if (*err == 0)
269                         *err = WTAP_ERR_SHORT_READ;
270                 return FALSE;
271         }
272
273         /*
274          * Read the packet data.
275          */
276         if (!wtap_read_packet_bytes(wth->random_fh, buf, rec->rec_header.packet_header.caplen, err, err_info))
277                 return FALSE;   /* failed */
278
279         return TRUE;
280 }
281
282 static gboolean
283 aethra_read_rec_header(wtap *wth, FILE_T fh, struct aethrarec_hdr *hdr,
284     wtap_rec *rec, int *err, gchar **err_info)
285 {
286         aethra_t *aethra = (aethra_t *)wth->priv;
287         guint32 rec_size;
288         guint32 packet_size;
289         guint32 msecs;
290
291         /* Read record header. */
292         if (!wtap_read_bytes_or_eof(fh, hdr, sizeof *hdr, err, err_info))
293                 return FALSE;
294
295         rec_size = pletoh16(hdr->rec_size);
296         if (rec_size < (sizeof *hdr - sizeof hdr->rec_size)) {
297                 /* The record is shorter than a record header. */
298                 *err = WTAP_ERR_BAD_FILE;
299                 *err_info = g_strdup_printf("aethra: File has %u-byte record, less than minimum of %u",
300                     rec_size,
301                     (unsigned int)(sizeof *hdr - sizeof hdr->rec_size));
302                 return FALSE;
303         }
304         if (rec_size > WTAP_MAX_PACKET_SIZE_STANDARD) {
305                 /*
306                  * Probably a corrupt capture file; return an error,
307                  * so that our caller doesn't blow up trying to allocate
308                  * space for an immensely-large packet.
309                  */
310                 *err = WTAP_ERR_BAD_FILE;
311                 *err_info = g_strdup_printf("aethra: File has %u-byte packet, bigger than maximum of %u",
312                     rec_size, WTAP_MAX_PACKET_SIZE_STANDARD);
313                 return FALSE;
314         }
315
316         packet_size = rec_size - (guint32)(sizeof *hdr - sizeof hdr->rec_size);
317
318         msecs = pletoh32(hdr->timestamp);
319         rec->rec_type = REC_TYPE_PACKET;
320         rec->presence_flags = WTAP_HAS_TS;
321         rec->ts.secs = aethra->start + (msecs / 1000);
322         rec->ts.nsecs = (msecs % 1000) * 1000000;
323         rec->rec_header.packet_header.caplen = packet_size;
324         rec->rec_header.packet_header.len = packet_size;
325         rec->rec_header.packet_header.pseudo_header.isdn.uton = (hdr->flags & AETHRA_U_TO_N);
326         rec->rec_header.packet_header.pseudo_header.isdn.channel = 0;   /* XXX - D channel */
327
328         return TRUE;
329 }
330
331 /*
332  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
333  *
334  * Local variables:
335  * c-basic-offset: 8
336  * tab-width: 8
337  * indent-tabs-mode: t
338  * End:
339  *
340  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
341  * :indentSize=8:tabSize=8:noTabs=false:
342  */