comparison uptools/sms-pdu-decode/sms-pdu-decode.c @ 598:9f7a263ad7f0

sms-pdu-decode split in preparation for pcm-sms-decode addition
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 08 Feb 2020 00:48:28 +0000
parents 542c6d733772
children 18bfc10ba20e
comparison
equal deleted inserted replaced
597:ca4433b714d2 598:9f7a263ad7f0
4 #include <stdlib.h> 4 #include <stdlib.h>
5 #include <string.h> 5 #include <string.h>
6 #include <strings.h> 6 #include <strings.h>
7 #include <unistd.h> 7 #include <unistd.h>
8 8
9 char *infname; 9 extern int ascii_ext_mode, global_hexdump_mode;
10 FILE *inf; 10 extern u_char pdu[176];
11 int ascii_ext_mode, global_hexdump_mode, keep_raw_pdu; 11 extern unsigned pdu_length;
12 12
13 char input_line[1024]; 13 static char *infname;
14 u_char pdu[176], first_octet; 14 static FILE *inf;
15 unsigned pdu_length, pdu_ptr; 15 static int keep_raw_pdu;
16 int dcs_distilled;
17 16
18 handle_sca() 17 static char input_line[1024];
19 {
20 unsigned sca_len;
21 char digits[21];
22 18
23 sca_len = pdu[0]; 19 static
24 pdu_ptr = 1;
25 if (!sca_len)
26 return(0);
27 if (sca_len < 2 || sca_len > 11) {
28 printf("Decode-Error: invalid SCA length\n");
29 return(-1);
30 }
31 if (pdu_ptr + sca_len > pdu_length) {
32 printf("Decode-Error: SCA goes past PDU end\n");
33 return(-1);
34 }
35 pdu_ptr += sca_len;
36 decode_address_digits(pdu + 2, digits, sc_addr_ndigits(pdu));
37 printf("SCA: %s%s (type 0x%02X)\n", pdu[1] == 0x91 ? "+" : "", digits,
38 pdu[1]);
39 return(0);
40 }
41
42 handle_first_octet()
43 {
44 if (pdu_ptr >= pdu_length) {
45 printf("Decode-Error: end of PDU before FO\n");
46 return(-1);
47 }
48 first_octet = pdu[pdu_ptr++];
49 printf("First-Octet: 0x%02X\n", first_octet);
50 return(0);
51 }
52
53 handle_mr()
54 {
55 if (pdu_ptr >= pdu_length) {
56 printf("Decode-Error: end of PDU before MR\n");
57 return(-1);
58 }
59 printf("MR: 0x%02X\n", pdu[pdu_ptr++]);
60 return(0);
61 }
62
63 handle_user_addr(direction)
64 char *direction;
65 {
66 unsigned addr_field_len, alpha_nsep;
67 char digits[21];
68 u_char alpha_gsm7[11], alpha_decoded[23];
69
70 if (pdu_ptr >= pdu_length) {
71 printf("Decode-Error: end of PDU before %s address\n",
72 direction);
73 return(-1);
74 }
75 if (pdu[pdu_ptr] > 20) {
76 printf("Decode-Error: %s address > 20 digits\n", direction);
77 return(-1);
78 }
79 addr_field_len = ((pdu[pdu_ptr] + 1) >> 1) + 2;
80 if (pdu_ptr + addr_field_len > pdu_length) {
81 printf("Decode-Error: %s address goes past PDU end\n",
82 direction);
83 return(-1);
84 }
85 if (!pdu[pdu_ptr])
86 printf("%s: empty-addr (type 0x%02X)\n", direction,
87 pdu[pdu_ptr+1]);
88 else if ((pdu[pdu_ptr+1] & 0x70) == 0x50 &&
89 alpha_addr_valid(pdu[pdu_ptr], &alpha_nsep)) {
90 gsm7_unpack(pdu + pdu_ptr + 2, alpha_gsm7, alpha_nsep);
91 gsm7_to_ascii_or_ext(alpha_gsm7, alpha_nsep, alpha_decoded,
92 (unsigned *) 0, ascii_ext_mode, 0,
93 (unsigned *) 0);
94 printf("%s: \"%s\" (type 0x%02X)\n", direction, alpha_decoded,
95 pdu[pdu_ptr+1]);
96 } else {
97 decode_address_digits(pdu + pdu_ptr + 2, digits, pdu[pdu_ptr]);
98 printf("%s: %s%s (type 0x%02X)\n", direction,
99 pdu[pdu_ptr+1] == 0x91 ? "+" : "", digits,
100 pdu[pdu_ptr+1]);
101 }
102 pdu_ptr += addr_field_len;
103 return(0);
104 }
105
106 handle_pid()
107 {
108 if (pdu_ptr >= pdu_length) {
109 printf("Decode-Error: end of PDU before PID\n");
110 return(-1);
111 }
112 printf("PID: 0x%02X\n", pdu[pdu_ptr++]);
113 return(0);
114 }
115
116 handle_dcs()
117 {
118 u_char dcs;
119 char *strtype;
120
121 if (pdu_ptr >= pdu_length) {
122 printf("Decode-Error: end of PDU before DCS\n");
123 return(-1);
124 }
125 dcs = pdu[pdu_ptr++];
126 dcs_distilled = sms_dcs_classify(dcs);
127 switch (dcs_distilled) {
128 case 7:
129 strtype = "7-bit";
130 break;
131 case 8:
132 strtype = "raw octets";
133 break;
134 case 9:
135 strtype = "compressed";
136 break;
137 case 16:
138 strtype = "UCS-2";
139 break;
140 }
141 printf("DCS: 0x%02X (%s)\n", dcs, strtype);
142 return(0);
143 }
144
145 handle_scts()
146 {
147 char str[21];
148
149 if (pdu_ptr + 7 > pdu_length) {
150 printf("Decode-Error: end of PDU before SCTS\n");
151 return(-1);
152 }
153 gsm_timestamp_decode(pdu + pdu_ptr, str);
154 printf("SC-Timestamp: %s\n", str);
155 pdu_ptr += 7;
156 return(0);
157 }
158
159 handle_vp_abs()
160 {
161 char str[21];
162
163 if (pdu_ptr + 7 > pdu_length) {
164 printf("Decode-Error: end of PDU before VP-abs\n");
165 return(-1);
166 }
167 gsm_timestamp_decode(pdu + pdu_ptr, str);
168 printf("VP-Absolute: %s\n", str);
169 pdu_ptr += 7;
170 return(0);
171 }
172
173 handle_vp_rel()
174 {
175 unsigned vprel, hours, min;
176
177 if (pdu_ptr >= pdu_length) {
178 printf("Decode-Error: end of PDU before VP-rel\n");
179 return(-1);
180 }
181 vprel = pdu[pdu_ptr++];
182 if (vprel <= 143) {
183 min = (vprel + 1) * 5;
184 goto hhmm;
185 } else if (vprel <= 167) {
186 min = (vprel - 143) * 30 + 12 * 60;
187 goto hhmm;
188 } else if (vprel <= 196) {
189 printf("VP-Relative: %u days\n", vprel - 166);
190 return(0);
191 } else {
192 printf("VP-Relative: %u weeks\n", vprel - 192);
193 return(0);
194 }
195
196 hhmm: hours = min / 60;
197 min %= 60;
198 printf("VP-Relative: ");
199 if (hours)
200 printf(" %u hour%s", hours, hours != 1 ? "s" : "");
201 if (min)
202 printf(" %u min", min);
203 putchar('\n');
204 return(0);
205 }
206
207 handle_vp_enh()
208 {
209 if (pdu_ptr + 7 > pdu_length) {
210 printf("Decode-Error: end of PDU before VP-enh\n");
211 return(-1);
212 }
213 printf("VP-Enhanced: %02X %02X %02X %02X %02X %02X %02X\n",
214 pdu[pdu_ptr], pdu[pdu_ptr+1], pdu[pdu_ptr+2], pdu[pdu_ptr+3],
215 pdu[pdu_ptr+4], pdu[pdu_ptr+5], pdu[pdu_ptr+6]);
216 pdu_ptr += 7;
217 return(0);
218 }
219
220 handle_vp()
221 {
222 int rc;
223
224 switch (first_octet & 0x18) {
225 case 0x00:
226 rc = 0;
227 break;
228 case 0x08:
229 rc = handle_vp_enh();
230 break;
231 case 0x10:
232 rc = handle_vp_rel();
233 break;
234 case 0x18:
235 rc = handle_vp_abs();
236 break;
237 }
238 return(rc);
239 }
240
241 process_pdu()
242 {
243 unsigned udl, udl_octets;
244 unsigned udhl, udh_octets, udh_chars, ud_chars;
245 u_char ud7[160], decode_buf[321];
246 int do_hexdump;
247 unsigned decoded_len, badchars;
248
249 if (handle_sca() < 0)
250 return(-1);
251 if (handle_first_octet() < 0)
252 return(-1);
253 if (first_octet & 2) {
254 printf("Decode-Error: MTI not supported\n");
255 return(-1);
256 }
257 if (first_octet & 1) {
258 if (handle_mr() < 0)
259 return(-1);
260 }
261 if (handle_user_addr(first_octet & 1 ? "To" : "From") < 0)
262 return(-1);
263 if (handle_pid() < 0)
264 return(-1);
265 if (handle_dcs() < 0)
266 return(-1);
267 if (first_octet & 1) {
268 if (handle_vp() < 0)
269 return(-1);
270 } else {
271 if (handle_scts() < 0)
272 return(-1);
273 }
274 if (pdu_ptr >= pdu_length) {
275 printf("Decode-Error: end of PDU before UDL\n");
276 return(-1);
277 }
278 udl = pdu[pdu_ptr++];
279 if (dcs_distilled == 7) {
280 if (udl > 160) {
281 printf("Decode-Error: UDL %u > 160\n", udl);
282 return(-1);
283 }
284 udl_octets = (udl * 7 + 7) / 8;
285 } else {
286 if (udl > 140) {
287 printf("Decode-Error: UDL %u > 140\n", udl);
288 return(-1);
289 }
290 udl_octets = udl;
291 }
292 if (pdu_length - pdu_ptr != udl_octets) {
293 printf("Decode-Error: UD length in PDU %u != expected %u\n",
294 pdu_length - pdu_ptr, udl_octets);
295 return(-1);
296 }
297 if (first_octet & 0x40) {
298 if (!udl) {
299 printf("Decode-Error: UDHI set with UDL=0\n");
300 return(-1);
301 }
302 udhl = pdu[pdu_ptr];
303 udh_octets = udhl + 1;
304 if (udh_octets > udl_octets) {
305 printf("Decode-Error: UDHL exceeds UDL\n");
306 return(-1);
307 }
308 printf("UDH-Length: %u\n", udhl);
309 if (dcs_distilled == 7)
310 udh_chars = (udh_octets * 8 + 6) / 7;
311 else
312 udh_chars = udh_octets;
313 } else {
314 udhl = 0;
315 udh_octets = 0;
316 udh_chars = 0;
317 }
318 if (udh_chars >= udl) {
319 ud_chars = 0;
320 printf("Length: 0\n");
321 } else {
322 ud_chars = udl - udh_chars;
323 if (dcs_distilled == 7)
324 gsm7_unpack(pdu + pdu_ptr, ud7, udl);
325 if (global_hexdump_mode)
326 do_hexdump = 1;
327 else switch (dcs_distilled) {
328 case 7:
329 do_hexdump = 0;
330 break;
331 case 8:
332 case 9:
333 do_hexdump = 1;
334 break;
335 case 16:
336 if (ud_chars & 1)
337 do_hexdump = 1;
338 else
339 do_hexdump = 0;
340 break;
341 }
342 if (do_hexdump)
343 printf("Length: %u (raw)\n", ud_chars);
344 else {
345 switch (dcs_distilled) {
346 case 7:
347 gsm7_to_ascii_or_ext(ud7 + udh_chars, ud_chars,
348 decode_buf, &decoded_len,
349 ascii_ext_mode, 1,
350 &badchars);
351 break;
352 case 16:
353 ucs2_to_ascii_or_ext(pdu + pdu_ptr + udh_chars,
354 ud_chars,
355 decode_buf, &decoded_len,
356 ascii_ext_mode, 1,
357 &badchars);
358 break;
359 }
360 printf("Length: %u", ud_chars);
361 if (decoded_len != ud_chars)
362 printf("->%u", decoded_len);
363 if (badchars)
364 printf(" (%u bad char%s)", badchars,
365 badchars != 1 ? "s" : "");
366 putchar('\n');
367 }
368 }
369
370 if (udhl) {
371 printf("\nUDH:\n");
372 msg_bits_hexdump(pdu + pdu_ptr + 1, udhl);
373 }
374 if (!ud_chars)
375 return(0);
376 putchar('\n');
377 if (do_hexdump) {
378 if (dcs_distilled == 7)
379 msg_bits_hexdump(ud7 + udh_chars, ud_chars);
380 else
381 msg_bits_hexdump(pdu + pdu_ptr + udh_chars, ud_chars);
382 } else
383 puts(decode_buf);
384 return(0);
385 }
386
387 process_cmdline(argc, argv) 20 process_cmdline(argc, argv)
388 char **argv; 21 char **argv;
389 { 22 {
390 int c; 23 int c;
391 extern int optind; 24 extern int optind;
410 } 43 }
411 if (argc > optind) 44 if (argc > optind)
412 infname = argv[optind]; 45 infname = argv[optind];
413 } 46 }
414 47
48 static
415 swallow_empty_line() 49 swallow_empty_line()
416 { 50 {
417 int c; 51 int c;
418 52
419 c = getc(inf); 53 c = getc(inf);