2 * Very simple PDU decoder, just parses header and is independent to
3 * Gammu library. It is used for verification of Gammu test - anything
4 * this fails to process should also fail in Gammu.
12 #define BUFFER_SIZE 16384
15 * Converts hex digit to number, returns -1 on failure.
17 int hexdigit2number(const char digit
)
19 if (digit
>= '0' && digit
<= '9') {
22 if (digit
>= 'a' && digit
<= 'f') {
23 return 0xa + digit
- 'a';
25 if (digit
>= 'A' && digit
<= 'F') {
26 return 0xa + digit
- 'A';
28 printf("%c is not a digit!\n", digit
);
33 * Converts hex string of arbitrary length to number, returns -1 on
36 int hex2number(const char *buffer
, const size_t len
)
41 for (pos
= 0; pos
< len
; pos
++) {
43 tmp
= hexdigit2number(buffer
[pos
]);
52 * Reads single number encoded in PDU.
54 int pdu_get_number(const char *buffer
, const int semioctet
)
61 length
= hex2number(buffer
, 2);
65 length
= length
/ 2 + 1;
67 printf("Number length = %d\n", length
);
72 type
= hex2number(buffer
+ 2, 2);
73 printf("Number type = %d\n", type
);
75 out
= (char *)malloc((2 * length
) + 1);
78 memset(out
, 0, 2 * length
);
80 for (i
= 0; i
< (length
- 1) * 2; i
++) {
81 if (!isxdigit((int)buffer
[4 + i
])) {
82 printf("Non hex digit in PDU (%s)!\n", buffer
+ 4 + i
);
88 out
[i
+ 1] = buffer
[4 + i
];
89 if (out
[i
+ 1] == 'F') {
93 out
[i
- 1] = buffer
[4 + i
];
96 printf("Number = %s\n", out
);
99 return (length
* 2) + 2;
103 * Parses timestamp from PDU.
105 int pdu_get_timestamp(const char *buffer
)
109 for (i
= 0; i
< 14; i
++) {
110 if (!isxdigit((int)buffer
[i
]))
114 printf("Date: %d-%d-%d %d:%d:%d TZ=%d\n",
115 hex2number(buffer
+ 0, 2),
116 hex2number(buffer
+ 2, 2), hex2number(buffer
+ 4, 2), hex2number(buffer
+ 6, 2), hex2number(buffer
+ 8, 2), hex2number(buffer
+ 10, 2), hex2number(buffer
+ 12, 2)
123 * Decodes textual PDU.
125 int pdu_decode(const char *buffer
)
130 /* Status variables */
132 /* Message content */
133 int submit
= 0, deliver
= 0, report
= 0;
145 ret
= pdu_get_number(buffer
+ pos
, 0);
151 type
= hex2number(buffer
+ pos
, 2);
155 printf("Message type: %02x - ", type
);
157 switch (type
& 0x3) {
167 printf("Status report\n");
171 printf("Reserved\n");
174 if (submit
|| deliver
) {
175 if (type
& (1 << 7)) {
178 if (type
& (1 << 6)) {
183 printf(", Reply path set");
186 printf(", UDH included");
189 switch (type
& (0x3 << 3)) {
194 printf(", Reserved VP!\n");
197 printf(", Relative VP");
201 printf(", Absolute VP");
208 /* Message reference (for submit) */
209 if (submit
|| report
) {
210 mr
= hex2number(buffer
+ pos
, 2);
214 printf("MR = 0x%02X\n", mr
);
217 /* Address (sender for deliver, receiver for submit, recipient
219 ret
= pdu_get_number(buffer
+ pos
, 1);
226 ret
= pdu_get_timestamp(buffer
+ pos
);
232 ret
= pdu_get_timestamp(buffer
+ pos
);
237 if (submit
|| deliver
) {
239 pid
= hex2number(buffer
+ pos
, 2);
243 printf("PID = 0x%02X\n", pid
);
246 dcs
= hex2number(buffer
+ pos
, 2);
250 printf("DCS = 0x%02X\n", dcs
);
254 if (vpf
== 2 || vpf
== 0) {
255 vp
= hex2number(buffer
+ pos
, 2);
259 printf("VP = 0x%02X\n", vp
);
260 } else if (vpf
== 3) {
261 ret
= pdu_get_timestamp(buffer
+ pos
);
269 ret
= pdu_get_timestamp(buffer
+ pos
);
274 if (submit
|| deliver
) {
276 udhl
= hex2number(buffer
+ pos
, 2);
280 printf("UDL = 0x%02X\n", udhl
);
281 /* GSM 03.40 section 9.2.3.10 (TP-Data-Coding-Scheme) and GSM 03.38 section 4 */
282 if ((((dcs
& 0xC0) == 0) && ((dcs
== 0) || ((dcs
& 0x2C) == 0x00) || ((dcs
& 0x2C) == 0x20))) ||
283 ((((dcs
& 0xF0) == 0xC0) || ((dcs
& 0xF0) == 0xD0)) && ((dcs
& 4) != 4)) || (((dcs
& 0xF0) == 0xF0) && ((dcs
& 8) != 8) && ((dcs
& 4) == 0))) {
284 if ((udhl
* 7) % 8 != 0) {
285 udhl
= (udhl
* 7) / 8;
288 udhl
= (udhl
* 7) / 8;
290 printf("UDL[adjusted] = 0x%02X\n", udhl
);
293 for (i
= 0; i
< udhl
; i
++) {
294 ud
= hex2number(buffer
+ pos
, 2);
296 printf("\nData too short!\n");
305 if (buffer
[pos
] != '\r' && buffer
[pos
] != '\n' && buffer
[pos
] != '\0') {
306 printf("Did not reach end: %s\n", buffer
+ pos
);
313 int main(int argc
, char **argv
)
315 char buffer
[BUFFER_SIZE
];
320 /* Check parameters */
322 printf("Not enough parameters!\nUsage: pdu-decode comm.dump\n");
327 f
= fopen(argv
[1], "r");
329 printf("Could not open %s\n", argv
[1]);
334 len
= fread(buffer
, 1, sizeof(buffer
) - 1, f
);
336 printf("Could not read whole file %s\n", argv
[1]);
340 /* Zero terminate data */
346 pos
= strchr(buffer
, '\n');
351 pos
= strchr(pos
, '\n');
356 if (pdu_decode(pos
) < 0)
362 /* Editor configuration
363 * vim: noexpandtab sw=8 ts=8 sts=8 tw=72: