This source file includes following definitions.
- get_code_2_str
- get_bits
- sngisdn_trace_interpreted_q921
- sngisdn_trace_raw_q921
- sngisdn_decode_q921
- sngisdn_trace_interpreted_q931
- sngisdn_trace_raw_q931
- sngisdn_decode_q931
- sngisdn_decode_ie
- print_hex_dump
- sngisdn_get_frame_info
- sngisdn_map_call
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #include "ftmod_sangoma_isdn.h"
36 #include "ftmod_sangoma_isdn_trace.h"
37
38 #define OCTET(x) (ieData[x-1] & 0xFF)
39 #define MAX_DECODE_STR_LEN 2000
40
41 typedef struct sngisdn_trace_info
42 {
43 uint8_t call_ref_flag;
44 uint16_t call_ref;
45 uint8_t msgtype;
46 uint8_t bchan_no;
47 ftdm_trace_dir_t dir;
48 } sngisdn_frame_info_t;
49
50 void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end);
51 uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start);
52 static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found);
53 static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *frame_info);
54
55 uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi);
56 char* get_code_2_str(int code, struct code2str *pCodeTable);
57 void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len);
58 void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len);
59
60
61 char* get_code_2_str(int code, struct code2str *pCodeTable)
62 {
63 struct code2str* pCode2txt;
64 pCode2txt = pCodeTable;
65 while(pCode2txt) {
66 if(pCode2txt->code >= 0) {
67 if (pCode2txt->code == code) {
68 return pCode2txt->text;
69 }
70 pCode2txt++;
71 } else {
72
73 return pCode2txt->text;
74 }
75 }
76 return (char*)"unknown";
77 }
78
79
80 uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi)
81 {
82 if (!bitLo || !bitHi) {
83 return 0;
84 }
85 if (bitLo > bitHi) {
86 return 0;
87 }
88
89 bitLo--;
90 bitHi--;
91
92 switch(bitHi - bitLo) {
93 case 0:
94 return (octet >> bitLo) & 0x01;
95 case 1:
96 return (octet >> bitLo) & 0x03;
97 case 2:
98 return (octet >> bitLo) & 0x07;
99 case 3:
100 return (octet >> bitLo) & 0x0F;
101 case 4:
102 return (octet >> bitLo) & 0x1F;
103 case 5:
104 return (octet >> bitLo) & 0x3F;
105 case 6:
106 return (octet >> bitLo) & 0x7F;
107 case 7:
108 return (octet >> bitLo) & 0xFF;
109 }
110 return 0;
111 }
112
113 void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
114 {
115 char *data_str = ftdm_calloc(1,200);
116 sngisdn_decode_q921(data_str, data, data_len);
117 ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
118 ftdm_safe_free(data_str);
119 }
120
121 void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
122 {
123 uint8_t *raw_data;
124 ftdm_sigmsg_t sigev;
125
126 memset(&sigev, 0, sizeof(sigev));
127
128 sigev.span_id = signal_data->ftdm_span->span_id;
129 sigev.chan_id = signal_data->dchan->chan_id;
130 sigev.channel = signal_data->dchan;
131 sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
132
133 sigev.ev_data.trace.dir = dir;
134 sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q921;
135
136 raw_data = ftdm_malloc(data_len);
137 ftdm_assert(raw_data, "Failed to malloc");
138
139 memcpy(raw_data, data, data_len);
140 sigev.raw.data = raw_data;
141 sigev.raw.len = data_len;
142 sigev.raw.autofree = 1;
143 ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
144 }
145
146 void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len)
147 {
148 int str_len;
149 uint32_t i;
150 uint8_t sapi, cr, ea, tei, ns, nr, pf, p, cmd;
151 uint8_t frame_format = 0;
152
153 str_len = 0;
154
155 if(data_len >= 2) {
156 switch ((int)data[2] & 0x03) {
157 case 0: case 2:
158 frame_format = I_FRAME;
159 break;
160 case 1:
161 frame_format = S_FRAME;
162 break;
163 case 3:
164 frame_format = U_FRAME;
165 break;
166 }
167 }
168
169 str_len+= sprintf(&str[str_len], " format: %s\n",
170 get_code_2_str(frame_format, dcodQ921FrameFormatTable));
171
172 for(i=0; i < data_len; i++) {
173 switch(i) {
174 case 0:
175 sapi = (uint8_t)((data[i]>>2) & 0x3F);
176 cr = (uint8_t)((data[i]>>1) & 0x1);
177 ea = (uint8_t)(data[i] & 0x1);
178 str_len+= sprintf(&str[str_len], " sapi: %03d c/r: %01d ea: %01d\n", sapi, cr, ea);
179 break;
180 case 1:
181 tei = (uint8_t)((data[i]>>1) & 0x7F);
182 ea = (uint8_t)(data[i] & 0x1);
183 str_len+= sprintf(&str[str_len], " tei: %03d ea: %01d\n", tei, ea);
184 break;
185 case 2:
186 switch(frame_format) {
187 case I_FRAME:
188 ns = (uint8_t)((data[i]>>1) & 0x7F);
189 nr = (uint8_t)((data[i+1]>>1) & 0x7F);
190 p = (uint8_t)(data[i+1] & 0x01);
191 str_len+= sprintf(&str[str_len], " n(s): %03d\n n(r): %03d p: %01d\n", ns, nr, p);
192 break;
193 case S_FRAME:
194 nr = (uint8_t)((data[i+1]>>1) & 0x7F);
195 pf = (uint8_t)(data[i+1] & 0x01);
196 str_len+= sprintf(&str[str_len], " n(r): %03d p/f: %01d\n", nr, pf);
197
198 cmd = (uint8_t)((data[i]>>2) & 0x03);
199 str_len+= sprintf(&str[str_len], " cmd: %s\n", get_code_2_str(cmd, dcodQ921SupervisoryCmdTable));
200
201 break;
202 case U_FRAME:
203 pf = (uint8_t)((data[i]>>4) & 0x01);
204 str_len+= sprintf(&str[str_len], " p/f: %01d\n", pf);
205
206 cmd = (uint8_t)((data[i]>>2) & 0x03);
207 cmd |= (uint8_t)((data[i]>>5) & 0x07);
208
209 str_len+= sprintf(&str[str_len], " cmd: %s\n", get_code_2_str(cmd, dcodQ921UnnumberedCmdTable));
210 break;
211 }
212 break;
213 }
214 }
215 return;
216 }
217
218
219 void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
220 {
221 char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN);
222 sngisdn_decode_q931(data_str, data, data_len);
223 ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
224 ftdm_safe_free(data_str);
225 }
226
227 void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
228 {
229 uint8_t *raw_data;
230 ftdm_sigmsg_t sigev;
231 ftdm_channel_t *ftdmchan = NULL;
232 sngisdn_frame_info_t frame_info;
233
234 memset(&sigev, 0, sizeof(sigev));
235
236
237
238 if (sngisdn_get_frame_info(data, data_len, dir, &frame_info) == FTDM_SUCCESS) {
239 if (sngisdn_map_call(signal_data, frame_info, &ftdmchan) == FTDM_SUCCESS) {
240 sigev.call_id = ftdmchan->caller_data.call_id;
241 sigev.span_id = ftdmchan->physical_span_id;
242 sigev.chan_id = ftdmchan->physical_chan_id;
243 sigev.channel = ftdmchan;
244 }
245 sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
246
247 sigev.ev_data.trace.dir = dir;
248 sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q931;
249
250 raw_data = ftdm_malloc(data_len);
251 ftdm_assert(raw_data, "Failed to malloc");
252
253 memcpy(raw_data, data, data_len);
254 sigev.raw.data = raw_data;
255 sigev.raw.len = data_len;
256 sigev.raw.autofree = 1;
257 ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
258 }
259 }
260
261 void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len)
262 {
263 uint32_t str_len;
264 uint8_t prot_disc, callRefFlag;
265 uint16_t lenCallRef, c, i;
266 uint8_t current_codeset = 0;
267
268 str_len = 0;
269
270
271 prot_disc = (uint8_t)data[0];
272 str_len += sprintf(&str[str_len], " Prot Disc:%s (0x%02x)\n", get_code_2_str(prot_disc, dcodQ931ProtDiscTable), prot_disc);
273
274
275 lenCallRef = (uint8_t) (data[1] & 0x0F);
276
277 str_len += sprintf(&str[str_len], " Call Ref:");
278 c=2;
279 callRefFlag = get_bits(data[c], 8,8);
280 for(i=0; i<(2*lenCallRef);i++) {
281 if(i==0) {
282 str_len += sprintf(&str[str_len], "%s%s",
283 get_code_2_str((uint8_t)(data[c] & 0x70), dcodQ931CallRefHiTable),
284 get_code_2_str((uint8_t)(data[c] & 0x0F), dcodQ931CallRefLoTable));
285 } else {
286 str_len += sprintf(&str[str_len], "%s%s",
287 get_code_2_str((uint8_t)(data[c] & 0xF0), dcodQ931CallRefHiTable),
288 get_code_2_str((uint8_t)(data[c] & 0x0F), dcodQ931CallRefLoTable));
289 }
290
291 i=i+1;
292 c=c+1;
293 }
294 str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Originating");
295
296
297 str_len+= sprintf(&str[str_len], " Type:%s (0x%x)\n", get_code_2_str((int)(data[2+lenCallRef] & 0xFF), dcodQ931MsgTypeTable), (int)(data[2+lenCallRef] & 0xFF));
298
299
300 for(i=3+lenCallRef; i < data_len; i++) {
301 switch (data[i] & 0xF8) {
302 case Q931_LOCKING_SHIFT:
303 current_codeset = (data[i] & 0x7);
304 str_len+= sprintf(&str[str_len], "Codeset shift to %d (locking)\n", current_codeset);
305 continue;
306 case Q931_NON_LOCKING_SHIFT:
307 current_codeset = (data[i] & 0x7);
308 str_len+= sprintf(&str[str_len], "Codeset shift to %d (non-locking)\n", current_codeset);
309 continue;
310 }
311 i+= sngisdn_decode_ie(str, &str_len, current_codeset, data, i);
312 }
313 print_hex_dump(str, &str_len, (uint8_t*) data, 0, data_len);
314 return;
315 }
316
317 uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start)
318 {
319 unsigned char* ieData;
320 uint8_t ieId;
321 uint32_t len = 0;
322 int index_end;
323
324 ieData = (unsigned char*) &data[index_start];
325
326 ieId = OCTET(1);
327 len = OCTET(2);
328 index_end = index_start+len+1;
329
330 *str_len += sprintf(&str[*str_len], " %s:", get_code_2_str(data[index_start], dcodQ931IEIDTable));
331 switch(ieId) {
332 case PROT_Q931_IE_BEARER_CAP:
333 {
334 uint8_t codingStandard, infTransferCap, transferMode, infTransferRate, usrL1Prot;
335
336 codingStandard = get_bits(OCTET(3),6,7);
337 infTransferCap = get_bits(OCTET(3),1,5);
338 transferMode = get_bits(OCTET(4),6,7);
339 infTransferRate = get_bits(OCTET(4),1,5);
340 usrL1Prot = get_bits(OCTET(5),1,5);
341
342 *str_len+= sprintf(&str[*str_len], "Coding:%s(%d) TransferCap:%s(%d) TransferRate:%s(%d) L1Prot:%s(%d)\n",
343 get_code_2_str(codingStandard, dcodQ931BcCodingStandardTable), codingStandard,
344 get_code_2_str(infTransferCap, dcodQ931BcInfTransferCapTable), infTransferCap,
345 get_code_2_str(infTransferRate, dcodQ931BcInfTransferRateTable), infTransferRate,
346 get_code_2_str(usrL1Prot, dcodQ931BcusrL1ProtTable), usrL1Prot);
347 }
348 break;
349 case PROT_Q931_IE_CAUSE:
350 {
351 uint8_t codingStandard, location, cause,diagOct = 5;
352 codingStandard = get_bits(OCTET(3),6,7);
353 location = get_bits(OCTET(3),1,4);
354
355 cause = get_bits(OCTET(4),1,7);
356
357 *str_len+= sprintf(&str[*str_len], "coding:%s(%d) location:%s(%d) val:%s(%d)\n",
358 get_code_2_str(codingStandard, dcodQ931BcCodingStandardTable), codingStandard,
359 get_code_2_str(location,dcodQ931IelocationTable), location,
360 get_code_2_str(cause, dcodQ931CauseCodeTable),
361 cause);
362 switch(cause) {
363 case PROT_Q931_RELEASE_CAUSE_IE_NOT_EXIST:
364 while(diagOct++ < len) {
365 *str_len+= sprintf(&str[*str_len], " %d:IE %s(0x%02x)\n",
366 diagOct,
367 get_code_2_str(OCTET(diagOct), dcodQ931IEIDTable),
368 OCTET(diagOct));
369 }
370 break;
371 case PROT_Q931_RELEASE_CAUSE_WRONG_CALL_STATE:
372 while(diagOct++ < len) {
373 *str_len+= sprintf(&str[*str_len], " %d:Message %s(0x%02x)\n",
374 diagOct,
375 get_code_2_str(OCTET(diagOct), dcodQ931MsgTypeTable),
376 OCTET(diagOct));
377 }
378 break;
379 case PROT_Q931_RECOVERY_ON_TIMER_EXPIRE:
380 *str_len+= sprintf(&str[*str_len], " Timer T\n");
381 while(diagOct++ < len) {
382 if(OCTET(diagOct) >= ' ' && OCTET(diagOct) < 0x7f) {
383 *str_len+= sprintf(&str[*str_len], "%c", OCTET(diagOct));
384 } else {
385 *str_len+= sprintf(&str[*str_len], ".");
386 }
387 }
388 break;
389 default:
390 while(diagOct++ < len) {
391 *str_len+= sprintf(&str[*str_len], " %d: 0x%02x\n",
392 diagOct,
393 OCTET(diagOct));
394 }
395 break;
396 }
397 }
398 break;
399 case PROT_Q931_IE_CHANNEL_ID:
400 {
401 uint8_t infoChannelSelection=0;
402 uint8_t prefExclusive=0;
403 uint8_t ifaceIdPresent=0;
404 uint8_t ifaceIdentifier = 0;
405 uint8_t chanType=0, numberMap=0, codingStandard=0;
406 uint8_t channelNo = 0;
407
408 infoChannelSelection = get_bits(OCTET(3),1,2);
409 prefExclusive = get_bits(OCTET(3),4,4);
410 ifaceIdPresent = get_bits(OCTET(3),7,7);
411
412 if (ifaceIdPresent) {
413 ifaceIdentifier= get_bits(OCTET(4),1,7);
414 chanType = get_bits(OCTET(5),1,4);
415 numberMap = get_bits(OCTET(5),5,5);
416 codingStandard = get_bits(OCTET(5),6,7);
417 channelNo = get_bits(OCTET(6),1,7);
418 } else {
419 chanType = get_bits(OCTET(4),1,4);
420 numberMap = get_bits(OCTET(4),5,5);
421 codingStandard = get_bits(OCTET(4),6,7);
422 channelNo = get_bits(OCTET(5),1,7);
423 }
424
425 if (numberMap) {
426 *str_len+= sprintf(&str[*str_len], " MAP:%s ", get_code_2_str(infoChannelSelection, dcodQ931InfoChannelSelTable));
427 } else {
428 *str_len+= sprintf(&str[*str_len], "No:%d ", channelNo);
429 }
430
431 *str_len+= sprintf(&str[*str_len], "Type:%s(%d) %s ", get_code_2_str(chanType,dcodQ931ChanTypeTable), chanType, (numberMap)? "Map":"");
432 *str_len+= sprintf(&str[*str_len], "%s/%s \n",
433 (prefExclusive)? "Exclusive":"Preferred",
434 (ifaceIdPresent)? "Explicit":"Implicit");
435 }
436 break;
437 case PROT_Q931_IE_CALLING_PARTY_NUMBER:
438 {
439 uint8_t plan, type, screening = 0, presentation = 0, callingNumOct, j;
440 uint8_t screeningEnabled = 0, presentationEnabled = 0;
441 char callingNumDigits[32];
442 memset(callingNumDigits, 0, sizeof(callingNumDigits));
443
444 plan = get_bits(OCTET(3),1,4);
445 type = get_bits(OCTET(3),5,7);
446
447 if(!get_bits(OCTET(3),8,8)) {
448 screening = get_bits(OCTET(4),1,2);
449 presentation = get_bits(OCTET(4),6,7);
450 screeningEnabled = 1;
451 presentationEnabled = 1;
452 callingNumOct = 4;
453 } else {
454 callingNumOct = 3;
455 }
456 if(len >= sizeof(callingNumDigits)) {
457 len = sizeof(callingNumDigits)-1;
458 }
459 j = 0;
460 while(callingNumOct++ <= len+1) {
461 callingNumDigits[j++]=ia5[get_bits(OCTET(callingNumOct),1,4)][get_bits(OCTET(callingNumOct),5,8)];
462 }
463 callingNumDigits[j]='\0';
464 *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)",
465
466 callingNumDigits, j,
467 get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
468 get_code_2_str(type, dcodQ931TypeofNumberTable), type);
469
470 if (presentationEnabled||screeningEnabled) {
471 *str_len+= sprintf(&str[*str_len], "scr:%s(%d) pres:%s(%d)\n",
472 get_code_2_str(screening, dcodQ931ScreeningTable), screening,
473 get_code_2_str(presentation, dcodQ931PresentationTable), presentation);
474 } else {
475 *str_len+= sprintf(&str[*str_len], "\n");
476 }
477 }
478 break;
479
480 case PROT_Q931_IE_CALLED_PARTY_NUMBER:
481 {
482 uint8_t plan, type, calledNumOct,j;
483 char calledNumDigits[32];
484 memset(calledNumDigits, 0, sizeof(calledNumDigits));
485 plan = get_bits(OCTET(3),1,4);
486 type = get_bits(OCTET(3),5,7);
487
488 if(len >= sizeof(calledNumDigits)) {
489 len = sizeof(calledNumDigits)-1;
490 }
491 calledNumOct = 3;
492 j = 0;
493 while(calledNumOct++ <= len+1) {
494 calledNumDigits[j++]=ia5[get_bits(OCTET(calledNumOct),1,4)][get_bits(OCTET(calledNumOct),5,8)];
495 }
496 calledNumDigits[j]='\0';
497 *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)\n",
498 calledNumDigits, j,
499 get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
500 get_code_2_str(type, dcodQ931TypeofNumberTable), type);
501 }
502 break;
503 case PROT_Q931_IE_REDIRECTING_NUMBER:
504 {
505 uint8_t plan, type, screening = 0, presentation = 0, reason = 0, rdnisOct,j;
506 uint8_t screeningEnabled = 0, presentationEnabled = 0, reasonEnabled = 0;
507 char rdnis_string[32];
508 memset(rdnis_string, 0, sizeof(rdnis_string));
509 rdnisOct = 5;
510 plan = get_bits(OCTET(3),1,4);
511 type = get_bits(OCTET(3),5,7);
512
513 if(!get_bits(OCTET(3),8,8)) {
514 rdnisOct++;
515 screening = get_bits(OCTET(4),1,2);
516 presentation = get_bits(OCTET(4),6,7);
517 screeningEnabled = 1;
518 presentationEnabled = 1;
519 if (!get_bits(OCTET(4),8,8)) {
520 rdnisOct++;
521 reason = get_bits(OCTET(5),1,4);
522 reasonEnabled = 1;
523 }
524 }
525
526 if(len >= sizeof(rdnis_string)) {
527 len = sizeof(rdnis_string)-1;
528 }
529
530 j = 0;
531 while(rdnisOct++ <= len+1) {
532 rdnis_string[j++]=ia5[get_bits(OCTET(rdnisOct),1,4)][get_bits(OCTET(rdnisOct),5,8)];
533 }
534
535 rdnis_string[j]='\0';
536 *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)",
537 rdnis_string, j,
538 get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
539 get_code_2_str(type, dcodQ931TypeofNumberTable), type);
540
541 if(presentationEnabled || screeningEnabled) {
542 *str_len+= sprintf(&str[*str_len], "scr:%s(%d) pres:%s(%d)",
543 get_code_2_str(screening, dcodQ931ScreeningTable), screening,
544 get_code_2_str(presentation, dcodQ931PresentationTable), presentation);
545 }
546
547 if(reasonEnabled) {
548 *str_len+= sprintf(&str[*str_len], "reason:%s(%d)",
549 get_code_2_str(reason, dcodQ931ReasonTable), reason);
550 }
551 *str_len+= sprintf(&str[*str_len], "\n");
552 }
553 break;
554 case PROT_Q931_IE_USER_USER:
555 {
556 uint8_t protDiscr = 0x00, j, uui_stringOct;
557 char uui_string[32];
558 memset(uui_string, 0, sizeof(uui_string));
559 protDiscr = OCTET(3);
560 uui_stringOct = 3;
561 if (protDiscr != 0x04) {
562 *str_len+= sprintf(&str[*str_len], "%s (0x%02x)\n",
563 get_code_2_str(protDiscr, dcodQ931UuiProtDiscrTable), protDiscr);
564 } else {
565 j = 0;
566
567 if(len >= sizeof(uui_string)) {
568 len = sizeof(uui_string)-1;
569 }
570 while(uui_stringOct++ <= len+1) {
571 uui_string[j++]=ia5[get_bits(OCTET(uui_stringOct),1,4)][get_bits(OCTET(uui_stringOct),5,8)];
572 }
573 uui_string[j]='\0';
574 *str_len+= sprintf(&str[*str_len], " %s (0x%02x) <%s>\n",
575 get_code_2_str(protDiscr, dcodQ931UuiProtDiscrTable), protDiscr,
576 uui_string);
577 }
578 }
579 break;
580 case PROT_Q931_IE_DISPLAY:
581 {
582 uint8_t displayStrOct=2, j;
583 char displayStr[82];
584 memset(displayStr, 0, sizeof(displayStr));
585
586 if(get_bits(OCTET(3),8,8)) {
587 displayStrOct++;
588 }
589 j = 0;
590 if(len >= sizeof(displayStr)) {
591 len = sizeof(displayStr)-1;
592 }
593 while(displayStrOct++ <= len+1) {
594 displayStr[j++]=ia5[get_bits(OCTET(displayStrOct),1,4)][get_bits(OCTET(displayStrOct),5,8)];
595 }
596 displayStr[j]='\0';
597 *str_len+= sprintf(&str[*str_len], "%s(l:%d)\n",
598 displayStr, len);
599 }
600 break;
601 case PROT_Q931_IE_RESTART_IND:
602 {
603 uint8_t indClass;
604 indClass = get_bits(OCTET(3),1,3);
605 *str_len+= sprintf(&str[*str_len], "class:%s(%d)\n",
606 get_code_2_str(indClass,dcodQ931RestartIndClassTable), indClass);
607 }
608 break;
609 case PROT_Q931_IE_PROGRESS_IND:
610 {
611 uint8_t codingStandard, location, progressDescr;
612 codingStandard = get_bits(OCTET(3),6,7);
613 location = get_bits(OCTET(3),1,4);
614 progressDescr = get_bits(OCTET(4),1,7);
615 *str_len+= sprintf(&str[*str_len], "coding:%s(%d) location:%s(%d) descr:%s(%d)\n",
616 get_code_2_str(codingStandard,dcodQ931BcCodingStandardTable), codingStandard,
617 get_code_2_str(location,dcodQ931IelocationTable), location,
618 get_code_2_str(progressDescr,dcodQ931IeprogressDescrTable), progressDescr);
619 }
620 break;
621 case PROT_Q931_IE_KEYPAD_FACILITY:
622 {
623 uint8_t keypadFacilityStrOct = 3, j;
624 char keypadFacilityStr[82];
625 memset(keypadFacilityStr, 0, sizeof(keypadFacilityStr));
626
627 j = 0;
628 if(len >= sizeof(keypadFacilityStr)) {
629 len = sizeof(keypadFacilityStr)-1;
630 }
631 while(keypadFacilityStrOct++ < len+1) {
632 keypadFacilityStr[j++]=ia5[get_bits(OCTET(keypadFacilityStrOct),1,4)][get_bits(OCTET(keypadFacilityStrOct),5,8)];
633 }
634 keypadFacilityStr[j]='\0';
635 *str_len+= sprintf(&str[*str_len], " digits:%s(l:%d)\n",
636 keypadFacilityStr, len);
637 }
638 break;
639 case PROT_Q931_IE_FACILITY:
640 {
641 uint8_t protProfile;
642 protProfile = get_bits(OCTET(3),1,5);
643 *str_len+= sprintf(&str[*str_len], "Prot profile:%s(%d)\n",
644 get_code_2_str(protProfile,dcodQ931IeFacilityProtProfileTable), protProfile);
645 }
646 break;
647 case PROT_Q931_IE_GENERIC_DIGITS:
648 {
649 uint8_t encoding,type;
650 int value = 0;
651
652 encoding = get_bits(OCTET(3),6,8);
653 type = get_bits(OCTET(3),1,5);
654
655 *str_len+= sprintf(&str[*str_len], "encoding:%s(%d) type:%s(%d) ",
656 get_code_2_str(encoding,dcodQ931GenDigitsEncodingTable), encoding,
657 get_code_2_str(encoding,dcodQ931GenDigitsTypeTable), type);
658
659 if (len > 1) {
660 uint32_t j=0;
661
662 while(++j < len) {
663 switch(encoding) {
664 case 0:
665 case 1:
666 {
667 uint8_t byte = OCTET(j+3);
668 value = (get_bits(byte,1,4)*10) + get_bits(byte,5,8) + (value*10);
669 }
670 break;
671 case 2:
672 value = value*10 + OCTET(j+3)-'0';
673 *str_len+= sprintf(&str[*str_len], "%c", OCTET(j+3));
674 break;
675 case 3:
676
677 *str_len+= sprintf(&str[*str_len], "Binary encoded");
678 break;
679 }
680 }
681 *str_len+= sprintf(&str[*str_len], " ");
682 switch(type) {
683 case 4:
684 *str_len+= sprintf(&str[*str_len], "ani2:%s(%d)", get_code_2_str(value,dcodQ931LineInfoTable), value);
685 break;
686 case 5:
687 *str_len+= sprintf(&str[*str_len], "Caller ID not implemented\n");
688 break;
689 }
690 }
691 *str_len+= sprintf(&str[*str_len], "\n");
692 print_hex_dump(str, str_len, (uint8_t*) data, index_start, index_end);
693 }
694 break;
695 case PROT_Q931_IE_SENDING_COMPLETE:
696
697
698 *str_len+= sprintf(&str[*str_len], "\n");
699 return 0;
700 break;
701 case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS:
702 {
703 uint8_t type;
704 uint8_t currentOct, j=0;
705 char calling_subaddr_string[82];
706 memset(calling_subaddr_string, 0, sizeof(calling_subaddr_string));
707 type = get_bits(OCTET(3),5,7);
708 currentOct = 3;
709 while(currentOct++ <= len+1) {
710 calling_subaddr_string[j++]=ia5[get_bits(OCTET(currentOct),1,4)][get_bits(OCTET(currentOct),5,8)];
711 }
712 calling_subaddr_string[j++]='\0';
713 *str_len += sprintf(&str[*str_len], "%s (l:%d) type:%s(%d) \n",
714 calling_subaddr_string, (j-1), get_code_2_str(type, dcodQ931TypeOfSubaddressTable), type);
715 }
716 break;
717 case PROT_Q931_IE_REDIRECTION_NUMBER:
718 case PROT_Q931_IE_NOTIFICATION_IND:
719 case PROT_Q931_IE_DATE_TIME:
720 case PROT_Q931_IE_INFORMATION_REQUEST:
721 case PROT_Q931_IE_SIGNAL:
722 case PROT_Q931_IE_SWITCHOOK:
723 case PROT_Q931_IE_FEATURE_ACT:
724 case PROT_Q931_IE_FEATURE_IND:
725 case PROT_Q931_IE_INFORMATION_RATE:
726 case PROT_Q931_IE_END_TO_END_TRANSIT_DELAY:
727 case PROT_Q931_IE_TRANSIT_DELAY_SELECT_IND:
728 case PROT_Q931_IE_PACKET_LAYER_BINARY_PARAMS:
729 case PROT_Q931_IE_PACKET_LAYER_WINDOW_SIZE:
730 case PROT_Q931_IE_PACKET_LAYER_SIZE:
731 case PROT_Q931_IE_TRANSIT_NETWORK_SELECTION:
732 case PROT_Q931_IE_LOW_LAYER_COMPAT:
733 case PROT_Q931_IE_HIGH_LAYER_COMPAT:
734 case PROT_Q931_IE_ESCAPE_FOR_EXTENSION:
735 case PROT_Q931_IE_CALL_IDENTITY:
736 case PROT_Q931_IE_CALL_STATE:
737 case PROT_Q931_IE_SEGMENTED_MESSAGE:
738 case PROT_Q931_IE_NETWORK_SPF_FACILITY:
739 case PROT_Q931_IE_CALLING_PARTY_SUBADDRESS:
740 default:
741 {
742 *str_len += sprintf(&str[*str_len], "Undecoded");
743 print_hex_dump((char*)str, str_len, data, index_start, index_end);
744 }
745 break;
746 }
747
748 return len+1;
749 }
750
751 void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end)
752 {
753 uint32_t k;
754 *str_len += sprintf(&str[*str_len], " [ ");
755 for(k=index_start; k <= index_end; k++) {
756 if (k && !(k%32)) {
757 *str_len += sprintf(&str[*str_len], "\n ");
758 }
759 *str_len += sprintf(&str[*str_len], "%02x ", data[k]);
760 }
761 *str_len += sprintf(&str[*str_len], "]\n");
762 return;
763 }
764
765 static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *target)
766 {
767 uint8_t pos = 0;
768 uint8_t flag;
769 uint16_t ref = 0;
770 uint8_t ref_len = 0;
771 uint8_t bchan_no = 0;
772 uint8_t msgtype;
773
774
775 pos++;
776
777 ref_len = data[pos++] & 0x0F;
778
779
780 flag = (data[pos] & 0x80) >> 7;
781 if (ref_len == 2) {
782 ref = (data[pos++] & 0x7F) << 8;
783 ref |= (data[pos++] & 0xFF) ;
784 } else {
785 ref = (data[pos++] & 0x7F);
786 }
787
788
789 msgtype = data[pos++] & 0x7F;
790
791
792
793
794 if (!ref) {
795
796 return FTDM_FAIL;
797 }
798
799
800 if (msgtype == PROT_Q931_MSGTYPE_SETUP) {
801
802
803 for(; pos < data_len; pos++) {
804 uint8_t ie_id = data[pos];
805 uint8_t ie_len = data[pos+1];
806
807 switch(ie_id) {
808 case PROT_Q931_IE_SENDING_COMPLETE:
809
810 ie_len = 0;
811 break;
812 case PROT_Q931_IE_CHANNEL_ID:
813 {
814
815 uint8_t ie_pos = pos+2;
816
817 if (data[ie_pos] & 0x20) {
818
819 ie_pos+=2;
820 bchan_no = data[ie_pos] & 0x7F;
821 } else {
822
823
824 bchan_no = data[ie_pos] & 0x03;
825 }
826 ftdm_log(FTDM_LOG_DEBUG, "Found b-channel:%d\n", bchan_no);
827 goto parse_ies_done;
828 }
829 break;
830 default:
831 pos = pos+ie_len+1;
832 }
833
834 }
835 if (!bchan_no) {
836 char tmp[1000];
837 print_hex_dump(tmp, 0, data, 0, data_len);
838 ftdm_log(FTDM_LOG_WARNING, "Failed to determine b-channel on SETUP message\n%s\n", tmp);
839 }
840 }
841
842 parse_ies_done:
843
844 target->call_ref = ref;
845 target->call_ref_flag = flag;
846 target->msgtype = msgtype;
847 target->bchan_no = bchan_no;
848 target->dir = dir;
849
850 return FTDM_SUCCESS;
851 }
852
853 static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found)
854 {
855 sngisdn_chan_data_t *sngisdn_info;
856 ftdm_channel_t *ftdmchan = NULL;
857 ftdm_iterator_t *chaniter = NULL;
858 ftdm_iterator_t *curr = NULL;
859 ftdm_status_t status = FTDM_FAIL;
860 uint8_t outbound_call = 0;
861
862 if ((!frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_OUTGOING) ||
863 (frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_INCOMING)) {
864
865
866
867 outbound_call = 1;
868 } else {
869 outbound_call = 0;
870 }
871
872 switch (frame_info.msgtype) {
873 case PROT_Q931_MSGTYPE_SETUP:
874
875 if (!frame_info.bchan_no) {
876
877 status = FTDM_FAIL;
878 }
879
880 chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
881 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
882 ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr));
883 ftdm_channel_lock(ftdmchan);
884
885 if (outbound_call) {
886 sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
887 if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
888 if (ftdmchan->caller_data.call_id && ftdmchan->physical_chan_id == frame_info.bchan_no) {
889
890 sngisdn_info->call_ref = frame_info.call_ref;
891 *found = ftdmchan;
892 status = FTDM_SUCCESS;
893 }
894 }
895 } else {
896 if (ftdmchan->physical_chan_id == frame_info.bchan_no) {
897 *found = ftdmchan;
898 status = FTDM_SUCCESS;
899 }
900 }
901 ftdm_channel_unlock(ftdmchan);
902 }
903 ftdm_iterator_free(chaniter);
904 break;
905 case PROT_Q931_MSGTYPE_ALERTING:
906 case PROT_Q931_MSGTYPE_PROCEEDING:
907 case PROT_Q931_MSGTYPE_PROGRESS:
908 case PROT_Q931_MSGTYPE_CONNECT:
909 case PROT_Q931_MSGTYPE_SETUP_ACK:
910 case PROT_Q931_MSGTYPE_CONNECT_ACK:
911 case PROT_Q931_MSGTYPE_USER_INFO:
912 case PROT_Q931_MSGTYPE_DISCONNECT:
913 case PROT_Q931_MSGTYPE_RELEASE:
914 case PROT_Q931_MSGTYPE_RELEASE_ACK:
915 case PROT_Q931_MSGTYPE_RELEASE_COMPLETE:
916 case PROT_Q931_MSGTYPE_FACILITY:
917 case PROT_Q931_MSGTYPE_NOTIFY:
918 case PROT_Q931_MSGTYPE_STATUS_ENQUIRY:
919 case PROT_Q931_MSGTYPE_INFORMATION:
920 case PROT_Q931_MSGTYPE_STATUS:
921
922 chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
923 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
924 ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr));
925 ftdm_channel_lock(ftdmchan);
926 sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
927 if (outbound_call) {
928 if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
929 if (sngisdn_info->call_ref == frame_info.call_ref) {
930
931 *found = ftdmchan;
932 status = FTDM_SUCCESS;
933 }
934 }
935 } else {
936 if (sngisdn_info && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
937 if (sngisdn_info->call_ref && sngisdn_info->call_ref == frame_info.call_ref) {
938
939 *found = ftdmchan;
940 status = FTDM_SUCCESS;
941 }
942 }
943 }
944 ftdm_channel_unlock(ftdmchan);
945 }
946 ftdm_iterator_free(chaniter);
947 break;
948 default:
949
950 break;
951 }
952 if (status == FTDM_SUCCESS) {
953 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Mapped %s with Call Ref:%04x to call-id:%d\n", get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref, (*found)->caller_data.call_id);
954 } else {
955
956 ftdm_log(FTDM_LOG_DEBUG, "Failed to map %s with Call Ref:%04x to local call\n",
957 get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref);
958 }
959
960 return status;
961 }
962
963
964