The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / wiretap / dct3trace.c @ master

History | View | Annotate | Download (9.41 KB)

1 2925fdc2 Mr. Scottbert
/* dct3trace.c
2
 * Routines for reading signalling traces generated by Gammu (www.gammu.org)
3
 * from Nokia DCT3 phones in Netmonitor mode.
4
 *
5
 * gammu --nokiadebug nhm5_587.txt v18-19
6
 *
7
 * Duncan Salerno <duncan.salerno@googlemail.com>
8
 *
9
 * $Id$
10
 *
11
 * Wiretap Library
12
 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
13
 *
14
 * This program is free software; you can redistribute it and/or
15
 * modify it under the terms of the GNU General Public License
16
 * as published by the Free Software Foundation; either version 2
17
 * of the License, or (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27
 */
28
29
#include "config.h"
30
#include "wtap-int.h"
31
#include "buffer.h"
32
#include "dct3trace.h"
33
#include "file_wrappers.h"
34
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <ctype.h>
39
40
41
/*
42
   Example downlink data:
43

44
<?xml version="1.0"?>
45
<dump>
46
<l1 direction="down" logicalchannel="96" physicalchannel="19" sequence="268116" error="0" timeshift="2992" bsic="22" data="31063F100DD0297A53E1020103C802398E0B2B2B2B2B2B" >
47
<l2 data="063F100DD0297A53E1020103" rest="C802398E0B2B2B2B2B2B" >
48
</l2>
49
</l1>
50
</dump>
51

52
   Example uplink data (no raw L1):
53

54
<?xml version="1.0"?>
55
<dump>
56
<l1 direction="up" logicalchannel="112" >
57
<l2 type="U" subtype="Unknown" p="0" data="061500400000000000000000000000000000" >
58
</l2>
59
</l1>
60
</dump>
61

62
 */
63
64
65
/* Magic text to check */
66
static const char dct3trace_magic_line1[] = "<?xml version=\"1.0\"?>";
67
static const char dct3trace_magic_line2[] = "<dump>";
68
static const char dct3trace_magic_record_start[]  = "<l1 ";
69
static const char dct3trace_magic_record_end[]  = "</l1>";
70
static const char dct3trace_magic_l2_start[]  = "<l2 ";
71
static const char dct3trace_magic_l2_end[]  = "</l2>";
72
static const char dct3trace_magic_end[]  = "</dump>";
73
74
#define MAX_PACKET_LEN 23
75
76
static gboolean dct3trace_read(wtap *wth, int *err, gchar **err_info,
77
        gint64 *data_offset);
78
static gboolean dct3trace_seek_read(wtap *wth, gint64 seek_off,
79
        struct wtap_pkthdr *phdr, Buffer *buf, int len,
80
        int *err, gchar **err_info);
81
82
/*
83
 * Following 3 functions taken from gsmdecode-0.7bis, with permission - http://wiki.thc.org/gsm
84
 */
85
86
static int
87
hc2b(unsigned char hex)
88
{
89
        hex = tolower(hex);
90
        if ((hex >= '0') && (hex <= '9'))
91
                return hex - '0';
92
        if ((hex >= 'a') && (hex <= 'f'))
93
                return hex - 'a' + 10;
94
        return -1;
95
}
96
97
static int
98
hex2bin(guint8 *out, guint8 *out_end, char *in)
99
{
100
        guint8 *out_start = out;
101
        int is_low = 0;
102
        int c;
103
104
        while (*in != '\0')
105
        {
106
                c = hc2b(*(unsigned char *)in);
107
                if (c < 0)
108
                {
109
                        in++;
110
                        continue;
111
                }
112
                if (out == out_end)
113
                {
114
                        /* Too much data */
115
                        return -1;
116
                }
117
                if (is_low == 0)
118
                {
119
                        *out = c << 4;
120
                        is_low = 1;
121
                } else {
122
                        *out |= (c & 0x0f);
123
                        is_low = 0;
124
                        out++;
125
                }
126
                in++;
127
        }
128
129
        return (int)(out - out_start);
130
}
131
132
static int
133
xml_get_int(int *val, const char *str, const char *pattern)
134
{
135
        const char *ptr;
136
        char *start, *end;
137
        char buf[32];
138
139
        ptr = strstr(str, pattern);
140
        if (ptr == NULL)
141
                return -1;
142
        start = strchr(ptr, '"');
143
        if (start == NULL)
144
                return -2;
145
        start++;
146
        end = strchr(start, '"');
147
        if (end == NULL)
148
                return -3;
149
        if (end - start > 31)
150
                return -4;
151
152
        memcpy(buf, start, end - start);
153
        buf[end - start] = '\0';
154
        *val = atoi(buf);
155
        return 0;
156
}
157
158
159
int dct3trace_open(wtap *wth, int *err, gchar **err_info)
160
{
161
        char line1[64], line2[64];
162
163
        /* Look for Gammu DCT3 trace header */
164
        if (file_gets(line1, sizeof(line1), wth->fh) == NULL ||
165
                file_gets(line2, sizeof(line2), wth->fh) == NULL)
166
        {
167
                *err = file_error(wth->fh, err_info);
168
                if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
169
                        return -1;
170
                return 0;
171
        }
172
173
        /* Don't compare line endings */
174
        if( strncmp(dct3trace_magic_line1, line1, strlen(dct3trace_magic_line1)) != 0 ||
175
                strncmp(dct3trace_magic_line2, line2, strlen(dct3trace_magic_line2)) != 0)
176
        {
177
                return 0;
178
        }
179
180
        wth->file_encap = WTAP_ENCAP_GSM_UM;
181
        wth->file_type = WTAP_FILE_DCT3TRACE;
182
        wth->snapshot_length = 0; /* not known */
183
        wth->subtype_read = dct3trace_read;
184
        wth->subtype_seek_read = dct3trace_seek_read;
185
        wth->tsprecision = WTAP_FILE_TSPREC_SEC;
186
187
        return 1;
188
}
189
190
191
static gboolean dct3trace_get_packet(FILE_T fh, struct wtap_pkthdr *phdr,
192
        Buffer *buf, int *err, gchar **err_info)
193
{
194
        char line[1024];
195
        guint8 databuf[MAX_PACKET_LEN], *bufp;
196
        gboolean have_data = FALSE;
197
        int len = 0;
198
199
        bufp = &databuf[0];
200
        while (file_gets(line, sizeof(line), fh) != NULL)
201
        {
202
                if( memcmp(dct3trace_magic_end, line, strlen(dct3trace_magic_end)) == 0 )
203
                {
204
                        /* Return on end of file </dump> */
205
                        *err = 0;
206
                        return FALSE;
207
                }
208
                else if( memcmp(dct3trace_magic_record_end, line, strlen(dct3trace_magic_record_end)) == 0 )
209
                {
210
                        /* Return on end of record </l1> */
211
                        if( have_data )
212
                        {
213
                                /* We've got a full packet! */
214
                                phdr->presence_flags = 0; /* no time stamp, no separate "on the wire" length */
215
                                phdr->ts.secs = 0;
216
                                phdr->ts.nsecs = 0;
217
                                phdr->caplen = len;
218
                                phdr->len = len;
219
220
                                *err = 0;
221
222
                                /* Make sure we have enough room for the packet */
223
                                buffer_assure_space(buf, phdr->caplen);
224
                                memcpy( buffer_start_ptr(buf), databuf, phdr->caplen );
225
226
                                return TRUE;
227
                        }
228
                        else
229
                        {
230
                                /* If not got any data return error */
231
                                *err = WTAP_ERR_BAD_FILE;
232
                                *err_info = g_strdup_printf("dct3trace: record without data");
233
                                return FALSE;
234
                        }
235
                }
236
                else if( memcmp(dct3trace_magic_record_start, line, strlen(dct3trace_magic_record_start)) == 0 )
237
                {
238
                        /* Parse L1 header <l1 ...>*/
239
                        int channel, tmp;
240
                        char *ptr;
241
242
                        phdr->pseudo_header.gsm_um.uplink = !strstr(line, "direction=\"down\"");
243
                        if (xml_get_int(&channel, line, "logicalchannel") != 0)
244
                                goto baddata;
245
246
                        /* Parse downlink only fields */
247
                        if( !phdr->pseudo_header.gsm_um.uplink )
248
                        {
249
                                if (xml_get_int(&tmp, line, "physicalchannel") != 0)
250
                                        goto baddata;
251
                                phdr->pseudo_header.gsm_um.arfcn = tmp;
252
                                if (xml_get_int(&tmp, line, "sequence") != 0)
253
                                        goto baddata;
254
                                phdr->pseudo_header.gsm_um.tdma_frame = tmp;
255
                                if (xml_get_int(&tmp, line, "bsic") != 0)
256
                                        goto baddata;
257
                                phdr->pseudo_header.gsm_um.bsic = tmp;
258
                                if (xml_get_int(&tmp, line, "error") != 0)
259
                                        goto baddata;
260
                                phdr->pseudo_header.gsm_um.error = tmp;
261
                                if (xml_get_int(&tmp, line, "timeshift") != 0)
262
                                        goto baddata;
263
                                phdr->pseudo_header.gsm_um.timeshift = tmp;
264
                        }
265
266
                        switch( channel )
267
                        {
268
                                case 128: phdr->pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_SDCCH; break;
269
                                case 112: phdr->pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_SACCH; break;
270
                                case 176: phdr->pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_FACCH; break;
271
                                case 96: phdr->pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_CCCH; break;
272
                                case 80: phdr->pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_BCCH; break;
273
                                default: phdr->pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_UNKNOWN; break;
274
                        }
275
276
                        /* Read data (if have it) into databuf */
277
                        ptr = strstr(line, "data=\"");
278
                        if( ptr )
279
                        {
280
                                have_data = TRUE; /* If has data... */
281
                                len = hex2bin(bufp, &databuf[MAX_PACKET_LEN], ptr+6);
282
                                if (len == -1)
283
                                {
284
                                        *err = WTAP_ERR_BAD_FILE;
285
                                        *err_info = g_strdup_printf("dct3trace: record length %d too long", phdr->caplen);
286
                                        return FALSE;
287
                                }
288
                        }
289
                }
290
                else if( !have_data && memcmp(dct3trace_magic_l2_start, line, strlen(dct3trace_magic_l2_start)) == 0 )
291
                {
292
                        /* For uplink packets we might not get the raw L1, so have to recreate it from the L2 */
293
                        /* Parse L2 header if didn't get data from L1 <l2 ...> */
294
                        int data_len;
295
                        char *ptr = strstr(line, "data=\"");
296
297
                        if( !ptr )
298
                        {
299
                                continue;
300
                        }
301
302
                        have_data = TRUE;
303
304
                        /*
305
                         * We know we have no data already, so we know
306
                         * we have enough room for the header.
307
                         */
308
                        if( phdr->pseudo_header.gsm_um.channel == GSM_UM_CHANNEL_SACCH || phdr->pseudo_header.gsm_um.channel == GSM_UM_CHANNEL_FACCH || phdr->pseudo_header.gsm_um.channel == GSM_UM_CHANNEL_SDCCH )
309
                        {
310
                                /* Add LAPDm B header */
311
                                memset(bufp, 0x1, 2);
312
                                len = 3;
313
                        }
314
                        else
315
                        {
316
                                /* Add LAPDm Bbis header */
317
                                len = 1;
318
                        }
319
                        bufp += len;
320
321
                        data_len = hex2bin(bufp, &databuf[MAX_PACKET_LEN], ptr+6);
322
                        if (data_len == -1)
323
                        {
324
                                *err = WTAP_ERR_BAD_FILE;
325
                                *err_info = g_strdup_printf("dct3trace: record length %d too long", phdr->caplen);
326
                                return FALSE;
327
                        }
328
                        len += data_len;
329
330
                        /* Add LAPDm length byte */
331
                        *(bufp - 1) = data_len << 2 | 0x1;
332
                }
333
        }
334
335
        *err = file_error(fh, err_info);
336
        if (*err == 0)
337
        {
338
                *err = WTAP_ERR_SHORT_READ;
339
        }
340
        return FALSE;
341
342
baddata:
343
        *err = WTAP_ERR_BAD_FILE;
344
        *err_info = g_strdup_printf("dct3trace: record missing mandatory attributes");
345
        return FALSE;
346
}
347
348
349
/* Find the next packet and parse it; called from wtap_read(). */
350
static gboolean dct3trace_read(wtap *wth, int *err, gchar **err_info,
351
    gint64 *data_offset)
352
{
353
        *data_offset = file_tell(wth->fh);
354
355
        return dct3trace_get_packet(wth->fh, &wth->phdr, wth->frame_buffer,
356
            err, err_info);
357
}
358
359
360
/* Used to read packets in random-access fashion */
361
static gboolean dct3trace_seek_read(wtap *wth, gint64 seek_off,
362
        struct wtap_pkthdr *phdr, Buffer *buf, int len _U_,
363
        int *err, gchar **err_info)
364
{
365
        if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
366
        {
367
                return FALSE;
368
        }
369
370
        return dct3trace_get_packet(wth->random_fh, phdr, buf, err, err_info);
371
}