summaryrefslogtreecommitdiffabout
path: root/gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c
Unidiff
Diffstat (limited to 'gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c416
1 files changed, 416 insertions, 0 deletions
diff --git a/gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c b/gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c
new file mode 100644
index 0000000..44db64b
--- a/dev/null
+++ b/gammu/emb/gammu/depend/nokia/dct3trac/wmx-gsm.c
@@ -0,0 +1,416 @@
1/**
2 * Simple GSM frame decoder
3 * wumpus 2003 -- www.blacksphere.tk
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <signal.h>
10
11#include "wmx-util.h"
12#include "wmx-gsm.h"
13
14/* Administrative */
15GSMDecoder *GSMDecoder_new()
16{
17 GSMDecoder *self;
18
19 self = malloc(sizeof(GSMDecoder));
20 self->xmlout = NULL;
21
22 return self;
23}
24
25/**
26 * Set 'sniffer' XML output stream
27 */
28void GSMDecoder_xmlout(GSMDecoder *self, FILE *f)
29{
30 self->xmlout = f;
31 if(self->xmlout) {
32 /* Open XML doc */
33 fprintf(self->xmlout,"<?xml version=\"1.0\"?>\n");
34 fprintf(self->xmlout,"<dump>\n");
35 }
36}
37
38void GSMDecoder_free(GSMDecoder *self)
39{
40 if(self->xmlout) {
41 fprintf(self->xmlout,"</dump>\n");
42 fclose(self->xmlout);
43 }
44 free(self);
45}
46
47char *GSM_protocols[]={
48/*0*/ "Group call control",
49/*1*/ "Broadcast call control",
50/*2*/ "PDSS1",
51/*3*/ "Call Control; call related SS messages (TS 24.008)",
52/*4*/ "PDSS2",
53/*5*/ "Mobility Management messages (TS 24.008)",
54/*6*/ "Radio Resources management messages (GSM 04.18)",
55/*7*/ "RFU",
56/*8*/ "GPRS mobility management messages",
57/*9*/ "SMS messages (GSM 04.11)",
58/*A*/ "GPRS session management messages",
59/*B*/ "Non call related SS messages (GSM 04.80)",
60/*C*/ "Location services",
61/*D*/ "RFU",
62/*E*/ "Reserved for extension of the PD to one octet length",
63/*F*/ "Reserved for tests procedures described in GSM 11.10"
64};
65
66typedef struct GSMpackettypestruct {
67 int id;
68 char *section;
69 char *description;
70} GSMpackettype;
71
72/* Include the data */
73GSMpackettype GSM_RR_packettypes[] = {
74#include "type-rr.h"
75};
76GSMpackettype GSM_MM_packettypes[] = {
77#include "type-mm.h"
78};
79GSMpackettype GSM_CC_packettypes[] = {
80#include "type-cc.h"
81};
82GSMpackettype GSM_SS_packettypes[] = {
83#include "type-ss.h"
84};
85GSMpackettype GSM_SMS_packettypes[] = {
86#include "type-sms.h"
87};
88
89GSMpackettype *GSMpackettype_lookup(GSMpackettype list[], int id)
90{
91 GSMpackettype *ptr = list;
92
93 while(ptr->id != -1 && ptr->id != id) ptr++;
94 if(ptr->id == -1) {
95 return NULL;
96 } else {
97 return ptr;
98 }
99}
100
101/* disassemble L3 packet -- GSM 04.06
102tx=0 Network to MS
103tx=1 MS to Network
104*/
105void GSMDecoder_L3packet(GSMDecoder *self, GSMDecoder_l1l2data *l1, unsigned char *buffer, size_t length)
106{
107 int proto,type;
108 GSMpackettype *ptype;
109
110 dumpraw("Inform", buffer, length);
111 printf(" ");
112 if(length < 2) return;
113
114 /* Attempt at decoding first byte
115 -- protocol discriminator
116 */
117 proto = buffer[0]&0xF;
118 printf("\n %s ", GSM_protocols[proto]);
119
120 switch(proto) {
121 case 0x3: /* CC */
122 type = buffer[1]&0x3F;
123 ptype = GSMpackettype_lookup(GSM_CC_packettypes, type);
124 if (ptype == NULL) {
125 printf("\n Unknown %02X", type);
126 } else {
127 printf("\n %s (%s)", ptype->description, ptype->section);
128 }
129 break;
130 case 0x5: /* MM */
131 type = buffer[1]&0x3F;
132 ptype = GSMpackettype_lookup(GSM_MM_packettypes, type);
133 if (ptype == NULL) {
134 printf("\n Unknown %02X", type);
135 } else {
136 printf("\n %s (%s)", ptype->description, ptype->section);
137 }
138 break;
139 case 0x6: /* RR */
140 if (buffer[0]>>4) {
141 printf("\n RR:Invalid Skip Indicator");
142 return;
143 }
144 type = buffer[1];
145 ptype = GSMpackettype_lookup(GSM_RR_packettypes, type);
146 if (ptype == NULL) {
147 printf("\n Unknown %02X", type);
148 } else {
149 printf("\n %s (%s)", ptype->description, ptype->section);
150 }
151 break;
152 case 0x9: /* SMS */
153 type = buffer[1]&0x3F;
154 ptype = GSMpackettype_lookup(GSM_SMS_packettypes, type);
155 if (ptype == NULL) {
156 printf("\n Unknown %02X", type);
157 } else {
158 printf("\n %s (%s)", ptype->description, ptype->section);
159 }
160 break;
161 case 0xB: /* SS */
162 if (buffer[1]&0x80) {
163 printf("\n SS:Invalid Message Type");
164 return;
165 }
166 type = buffer[1]&0x3F;
167 ptype = GSMpackettype_lookup(GSM_SS_packettypes, type);
168 if (ptype == NULL) {
169 printf("\n Unknown %02X", type);
170 } else {
171 printf("\n %s (%s)", ptype->description, ptype->section);
172 }
173 break;
174 }
175}
176
177static void GSMDecoder_l1xml_open(GSMDecoder *self, GSMDecoder_l1l2data *l1, unsigned char *buffer, size_t length)
178{
179 unsigned int x;
180
181 if(self->xmlout) {
182 fprintf(self->xmlout, "<l1 ");
183 fprintf(self->xmlout, "direction=\"%s\" ", l1->tx==GSMDECODER_SEND?"up":"down");
184 fprintf(self->xmlout, "logicalchannel=\"%i\" ", l1->ch);
185 if(l1->tx == GSMDECODER_RECEIVE) {
186 fprintf(self->xmlout, "physicalchannel=\"%i\" ", l1->arfcn);
187 fprintf(self->xmlout, "sequence=\"%u\" ", l1->seq);
188 fprintf(self->xmlout, "error=\"%i\" ", l1->err);
189 fprintf(self->xmlout, "timeshift=\"%i\" ", l1->timeshift);
190 fprintf(self->xmlout, "bsic=\"%i\" ", l1->bsic);
191 fprintf(self->xmlout, "data=\"");
192 for(x=0; x<length; x++) {
193 fprintf(self->xmlout, "%02X", buffer[x]);
194 }
195 fprintf(self->xmlout, "\" ");
196 }
197 fprintf(self->xmlout, ">\n");
198 }
199}
200
201static void GSMDecoder_l1xml_close(GSMDecoder *self)
202{
203 if(self->xmlout) fprintf(self->xmlout, "</l1>\n");
204}
205
206/* disassemble L2 pseudo length header packet -- GSM 04.06
207 tx=0 Network to MS
208 tx=1 MS to Network
209 write XML stream
210*/
211void GSMDecoder_L2short_packet(GSMDecoder *self, GSMDecoder_l1l2data *l1, unsigned char *buffer, size_t length)
212{
213 size_t ptr,usedlength, x;
214
215 GSMDecoder_l1xml_open(self, l1, buffer, length);
216
217 if(length<1) {
218 /* too small to contain 1 header byte */
219 printf("L2 packet too small\n");
220 GSMDecoder_l1xml_close(self);
221 return;
222 }
223 ptr = 0;
224 //printf("L2 packet\n");
225
226 /* dump Length Indicator field */
227 usedlength = buffer[ptr]>>2;
228 if((buffer[ptr]&3) != 1) {
229 dumpraw("ErrPacket", buffer, length);
230 printf(" Invalid pseudo length byte\n");
231 GSMDecoder_l1xml_close(self);
232 return;
233 }
234 printf("Length : used=%i ID=%i\n",
235 usedlength,
236 (buffer[ptr]>>0)&3);
237 ptr++;
238 /* dump Information */
239 printf("Inform : ");
240 if((ptr+usedlength) > length) {
241 printf("Invalid used length\n");
242 }
243 if(self->xmlout) {
244 fprintf(self->xmlout, "<l2 ");
245 fprintf(self->xmlout, "data=\"");
246 for(x=0; x<usedlength; x++) fprintf(self->xmlout, "%02X", buffer[ptr+x]);
247 fprintf(self->xmlout, "\" ");
248 /* Rest octets */
249 fprintf(self->xmlout, "rest=\"");
250 for(x=(ptr+usedlength); x<length; x++) fprintf(self->xmlout, "%02X", buffer[x]);
251 fprintf(self->xmlout, "\" ");
252 fprintf(self->xmlout, ">\n");
253 }
254 GSMDecoder_L3packet(self, l1, &buffer[ptr], usedlength);
255 if(self->xmlout) fprintf(self->xmlout, "</l2>\n");
256 //dumpraw("Inform", &buffer[ptr], usedlength);
257 //printf("\n");
258 GSMDecoder_l1xml_close(self);
259}
260
261#define TYPE_I 0x01 /* Information */
262#define TYPE_S 0x02 /* Supervisory */
263#define TYPE_U 0x03 /* Unnumbered */
264
265/* disassemble L2 packet -- GSM 04.06
266tx=0 Network to MS
267tx=1 MS to Network
268*/
269void GSMDecoder_L2packet(GSMDecoder *self, GSMDecoder_l1l2data *l1, unsigned char *buffer, size_t length)
270{
271 size_t ptr,usedlength,x;
272 int more;
273 int type;
274 char temp[80];
275
276 GSMDecoder_l1xml_open(self, l1, buffer, length);
277
278 if(length<5) {
279 /* too small to contain 3 header bytes plus 20 data bytes */
280 printf("L2 packet too small\n");
281 GSMDecoder_l1xml_close(self);
282 return;
283 }
284 ptr = 0;
285 //printf("L2 packet\n");
286 /* dump Address field */
287 printf("Address: LPD=%i SAPI=%i C/R=%i EA=%i\n",
288 (buffer[ptr]>>5)&3,
289 (buffer[ptr]>>2)&7,
290 (buffer[ptr]>>1)&1,
291 (buffer[ptr]>>0)&1);
292 /* skip next address field bytes */
293 while((buffer[ptr]&1)==0) ptr++;
294 ptr++;
295 /* dump Control field */
296
297 type = TYPE_I;
298 // if(!(buffer[ptr]&1)) type = TYPE_I;
299 if((buffer[ptr]&1) && !(buffer[ptr]&2)) type = TYPE_S;
300 if((buffer[ptr]&1) && (buffer[ptr]&2)) type = TYPE_U;
301 switch(type) {
302 case TYPE_I:
303 printf("Control: I TXSeq=%i P=%i RXSeq=%i\n",
304 (buffer[ptr]>>5)&7,
305 (buffer[ptr]>>4)&1,
306 (buffer[ptr]>>1)&7);
307 break;
308 case TYPE_S: {
309 char *desc = "Unknown";
310 x = (buffer[ptr]>>2)&3;
311 switch(x) {
312 case 0: /* 00 */ desc="RR (Receive Ready)"; break; /* ALSO acknowledgement */
313 case 1: /* 01 */ desc="RNR (Receive Not Ready)"; break;
314 case 2: /* 10 */ desc="REJ (Reject)"; break;
315 }
316 printf("Control: S TXSeq=%i P/F=%i S=%i %s\n",
317 (buffer[ptr]>>5)&7,
318 (buffer[ptr]>>4)&1,
319 x, desc);
320 } break;
321 case TYPE_U: {
322 char *desc = "Unknown";
323 x = (((buffer[ptr]>>5)&7)<<2) | ((buffer[ptr]>>2)&3);
324 binstr(temp, x, 5);
325 switch(x) {
326 case 0: /* 00000 */ desc = "UI (Unnumbered information)"; break;
327 case 3: /* 00011 */ desc = "DM (Disconnect mode)"; break;
328 case 7: /* 00111 */ desc = "SABM (Set asynchronous balanced mode)"; break;
329 case 8: /* 01000 */ desc = "DISC (Disconnect)"; break;
330 case 12:/* 01100 */ desc = "UA (Unnumbered acknowledge)"; break;
331 }
332
333 printf("Control: U U=%s %s P/F=%i\n",
334 temp, desc,
335 (buffer[ptr]>>4)&1);
336 } break;
337 }
338 ptr++;
339 /* dump Length Indicator field */
340 usedlength = buffer[ptr]>>2;
341 more = (buffer[ptr]>>1)&1; /* more to go */
342 printf("Length : used=%i M=%i EL=%i\n",
343 usedlength, more,
344 (buffer[ptr]>>0)&1);
345 while((buffer[ptr]&1)==0) ptr++;
346 ptr++;
347 /* dump Information */
348 printf("Inform : ");
349 if((ptr+usedlength) > length) {
350 printf("Invalid used length\n");
351 }
352 /*
353 for(x=0; x<usedlength; x++) {
354 printf("%02x ",buffer[ptr]);
355 ptr++;
356 }
357 */
358 if(self->xmlout) {
359 char *desc;
360 fprintf(self->xmlout, "<l2 ");
361 switch(type) {
362 case TYPE_I:
363 fprintf(self->xmlout, "type=\"I\" ");
364 fprintf(self->xmlout, "txseq=\"%i\" p=\"%i\" rxseq=\"%i\" ",
365 (buffer[ptr]>>5)&7,
366 (buffer[ptr]>>4)&1,
367 (buffer[ptr]>>1)&7);
368 break;
369 case TYPE_S:
370 fprintf(self->xmlout, "type=\"S\" ");
371 desc = "Unknown";
372 x = (buffer[ptr]>>2)&3;
373 switch(x) {
374 case 0: /* 00 */ desc="RR"; break; /* ALSO acknowledgement */
375 case 1: /* 01 */ desc="RNR"; break;
376 case 2: /* 10 */ desc="REJ"; break;
377 }
378 fprintf(self->xmlout, "subtype=\"%s\" rxseq=\"%i\" p=\"%i\" ",
379 desc,
380 (buffer[ptr]>>5)&7,
381 (buffer[ptr]>>4)&1);
382 break;
383 case TYPE_U:
384 fprintf(self->xmlout, "type=\"U\" ");
385 desc = "Unknown";
386 x = (((buffer[ptr]>>5)&7)<<2) | ((buffer[ptr]>>2)&3);
387 switch(x) {
388 case 0: /* 00000 */ desc = "UI"; break;
389 case 3: /* 00011 */ desc = "DM"; break;
390 case 7: /* 00111 */ desc = "SABM"; break;
391 case 8: /* 01000 */ desc = "DISC"; break;
392 case 12:/* 01100 */ desc = "UA"; break;
393 }
394
395 fprintf(self->xmlout, "subtype=\"%s\" p=\"%i\" ",
396 desc,
397 (buffer[ptr]>>4)&1);
398 break;
399 default:
400 fprintf(self->xmlout, "type=\"Unknown\" ");
401 }
402 fprintf(self->xmlout, "data=\"");
403 for(x=0; x<usedlength; x++) fprintf(self->xmlout, "%02X", buffer[ptr+x]);
404 fprintf(self->xmlout, "\" ");
405 fprintf(self->xmlout, ">\n");
406 }
407 GSMDecoder_L3packet(self, l1, &buffer[ptr], usedlength);
408 if(self->xmlout) fprintf(self->xmlout, "</l2>\n");
409 GSMDecoder_l1xml_close(self);
410 //dumpraw("Inform", );
411 //printf("\n");
412}
413
414/* How should editor hadle tabs in this file? Add editor commands here.
415 * vim: noexpandtab sw=8 ts=8 sts=8:
416 */