root/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get_code_2_str
  2. get_bits
  3. sngisdn_trace_q921
  4. sngisdn_trace_q931
  5. sngisdn_decode_ie
  6. print_hex_dump

   1 /*
   2  * Copyright (c) 2010, Sangoma Technologies
   3  * David Yat Sin <davidy@sangoma.com>
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * * Redistributions of source code must retain the above copyright
  11  * notice, this list of conditions and the following disclaimer.
  12  *
  13  * * Redistributions in binary form must reproduce the above copyright
  14  * notice, this list of conditions and the following disclaimer in the
  15  * documentation and/or other materials provided with the distribution.
  16  *
  17  * * Neither the name of the original author; nor the names of any contributors
  18  * may be used to endorse or promote products derived from this software
  19  * without specific prior written permission.
  20  *
  21  *
  22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  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 
  40 void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end);
  41 void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
  42 void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
  43 uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start);
  44 
  45 uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi);
  46 char* get_code_2_str(int code, struct code2str *pCodeTable);
  47 
  48 char* get_code_2_str(int code, struct code2str *pCodeTable)
  49 {
  50         struct code2str* pCode2txt;
  51         pCode2txt = pCodeTable; 
  52         while(pCode2txt) {
  53                 if(pCode2txt->code >= 0) {
  54                         if (pCode2txt->code == code) {
  55                                 return pCode2txt->text;
  56                         }
  57                         pCode2txt++;
  58                 } else {
  59                         /* This is the default value from the table */
  60                         return pCode2txt->text;
  61                 }
  62         }
  63         return (char*)"unknown";
  64 }
  65 
  66 
  67 uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi)
  68 {
  69         if (!bitLo || !bitHi) {
  70                 return 0;
  71         }
  72         if (bitLo > bitHi) {
  73                 return 0;
  74         }
  75 
  76         bitLo--;
  77         bitHi--;
  78 
  79         switch(bitHi - bitLo) {
  80                 case 0:
  81                         return (octet >> bitLo) & 0x01;
  82                 case 1:
  83                         return (octet >> bitLo) & 0x03;
  84                 case 2:
  85                         return (octet >> bitLo) & 0x07;
  86                 case 3:
  87                         return (octet >> bitLo) & 0x0F;
  88                 case 4:
  89                         return (octet >> bitLo) & 0x1F;
  90                 case 5:
  91                         return (octet >> bitLo) & 0x3F;
  92                 case 6:
  93                         return (octet >> bitLo) & 0x7F;
  94                 case 7:
  95                         return (octet >> bitLo) & 0xFF;
  96         }
  97         return 0;
  98 }
  99 
 100 void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len)
 101 {
 102         int str_len;
 103         int i;
 104         uint8_t sapi, cr, ea, tei, ns, nr, pf, p, cmd;
 105         uint8_t frame_format = 0;
 106 
 107         str_len = 0;
 108 
 109         if(data_len >= 2) {
 110                 switch ((int)data[2] & 0x03) {
 111                         case 0: case 2:
 112                                 frame_format = I_FRAME;
 113                                 break;
 114                         case 1: 
 115                                 frame_format = S_FRAME;
 116                                 break;
 117                         case 3:
 118                                 frame_format = U_FRAME;
 119                                 break;
 120                 }
 121         }
 122 
 123         str_len+= sprintf(&str[str_len], "  format: %s\n",
 124                                                                                 get_code_2_str(frame_format, dcodQ921FrameFormatTable));
 125                                                                                 
 126         for(i=0; i < data_len; i++) {
 127                 switch(i) {
 128                         case 0: // Octet 2
 129                                 sapi = (uint8_t)((data[i]>>2) & 0x3F);
 130                                 cr = (uint8_t)((data[i]>>1) & 0x1);
 131                                 ea = (uint8_t)(data[i] & 0x1);
 132                                 str_len+= sprintf(&str[str_len], "  sapi: %03d  c/r: %01d  ea: %01d\n", sapi, cr, ea);
 133                                 break;
 134                         case 1:
 135                                 tei = (uint8_t)((data[i]>>1) & 0x7F);
 136                                 ea = (uint8_t)(data[i] & 0x1);
 137                                 str_len+= sprintf(&str[str_len], "   tei: %03d          ea: %01d\n", tei, ea);
 138                                 break;
 139                         case 2:
 140                                 switch(frame_format) {
 141                                         case I_FRAME:
 142                                                 ns = (uint8_t)((data[i]>>1) & 0x7F);
 143                                                 nr = (uint8_t)((data[i+1]>>1) & 0x7F);
 144                                                 p = (uint8_t)(data[i+1] & 0x01);
 145                                                 str_len+= sprintf(&str[str_len], "  n(s): %03d\n  n(r): %03d  p: %01d\n", ns, nr, p);
 146                                                 break;
 147                                         case S_FRAME:
 148                                                 nr = (uint8_t)((data[i+1]>>1) & 0x7F);
 149                                                 pf = (uint8_t)(data[i+1] & 0x01);
 150                                                 str_len+= sprintf(&str[str_len], "  n(r): %03d  p/f: %01d\n", nr, pf);
 151 
 152                                                 cmd = (uint8_t)((data[i]>>2) & 0x03);
 153                                                 str_len+= sprintf(&str[str_len], "   cmd: %s\n", get_code_2_str(cmd, dcodQ921SupervisoryCmdTable));
 154                                                 
 155                                                 break;
 156                                         case U_FRAME:
 157                                                 pf = (uint8_t)((data[i]>>4) & 0x01);
 158                                                 str_len+= sprintf(&str[str_len], "   p/f: %01d\n", pf);
 159 
 160                                                 cmd = (uint8_t)((data[i]>>2) & 0x03);
 161                                                 cmd |= (uint8_t)((data[i]>>5) & 0x07);
 162                                                 
 163                                                 str_len+= sprintf(&str[str_len], "   cmd: %s\n", get_code_2_str(cmd, dcodQ921UnnumberedCmdTable));
 164                                                 break;
 165                                 }
 166                                 break;
 167                 }
 168         }
 169         return;
 170 }
 171 
 172 void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len)
 173 {
 174         uint32_t str_len;
 175         uint8_t  prot_disc, callRefFlag;
 176         uint16_t lenCallRef, c, i;
 177         uint8_t current_codeset = 0;
 178 
 179         str_len = 0;
 180 
 181         /* Decode Protocol Discrimator */
 182         prot_disc = (uint8_t)data[0];
 183         str_len += sprintf(&str[str_len], "  Prot Disc:%s (0x%02x)\n", get_code_2_str(prot_disc, dcodQ931ProtDiscTable), prot_disc);
 184         
 185 
 186         
 187 
 188         /* Decode Call Reference */
 189         lenCallRef = (uint8_t) (data[1] & 0x0F);
 190 
 191         str_len += sprintf(&str[str_len], "  Call Ref:");
 192         c=2;
 193         callRefFlag = get_bits(data[c], 8,8);
 194         for(i=0; i<(2*lenCallRef);i++) {
 195                 if(i==0) {
 196                         str_len += sprintf(&str[str_len], "%s%s",
 197                                                 get_code_2_str((uint8_t)(data[c] & 0x70), dcodQ931CallRefHiTable),
 198                                                 get_code_2_str((uint8_t)(data[c] & 0x0F), dcodQ931CallRefLoTable));
 199                 } else {
 200                         str_len += sprintf(&str[str_len], "%s%s",
 201                                                 get_code_2_str((uint8_t)(data[c] & 0xF0), dcodQ931CallRefHiTable),
 202                                                 get_code_2_str((uint8_t)(data[c] & 0x0F), dcodQ931CallRefLoTable));
 203                 }
 204 
 205                 i=i+1;
 206                 c=c+1;
 207         }
 208         str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Originating");
 209 
 210         /* Decode message type */
 211         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));
 212 
 213         /* go through rest of data and look for important info */
 214         for(i=3+lenCallRef; i < data_len; i++) {
 215                 switch (data[i] & 0xF8) {
 216                         case Q931_LOCKING_SHIFT:
 217                                 current_codeset = (data[i] & 0x7);
 218                                 str_len+= sprintf(&str[str_len], "Codeset shift to %d (locking)\n", current_codeset);
 219                                 continue;
 220                         case Q931_NON_LOCKING_SHIFT:
 221                                 current_codeset = (data[i] & 0x7);
 222                                 str_len+= sprintf(&str[str_len], "Codeset shift to %d (non-locking)\n", current_codeset);
 223                                 continue;
 224                 }
 225                 i+= sngisdn_decode_ie(str, &str_len, current_codeset, data, i);
 226         }
 227         print_hex_dump(str, &str_len, (uint8_t*) data, 0, data_len);
 228         return;
 229 }
 230 
 231 uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start)
 232 {
 233         unsigned char* ieData;
 234         uint8_t ieId;
 235         uint32_t len = 0;
 236         int index_end;
 237 
 238         ieData = (unsigned char*) &data[index_start];
 239 
 240         ieId = OCTET(1);
 241         len = OCTET(2); 
 242         index_end = index_start+len+1;
 243 
 244         *str_len += sprintf(&str[*str_len], "  %s:", get_code_2_str(data[index_start], dcodQ931IEIDTable));
 245         switch(ieId) {
 246                 case PROT_Q931_IE_BEARER_CAP:
 247                         {
 248                                 uint8_t codingStandard, infTransferCap, transferMode, infTransferRate, usrL1Prot;
 249                                 
 250                                 codingStandard = get_bits(OCTET(3),6,7);
 251                                 infTransferCap = get_bits(OCTET(3),1,5);
 252                                 transferMode = get_bits(OCTET(4),6,7);
 253                                 infTransferRate = get_bits(OCTET(4),1,5);
 254                                 usrL1Prot = get_bits(OCTET(5),1,5);
 255                                 
 256                                 *str_len+= sprintf(&str[*str_len], "Coding:%s(%d) TransferCap:%s(%d) TransferRate:%s(%d) L1Prot:%s(%d)\n",
 257                                                                                                                         get_code_2_str(codingStandard, dcodQ931BcCodingStandardTable), codingStandard,
 258                                                                                                                         get_code_2_str(infTransferCap, dcodQ931BcInfTransferCapTable), infTransferCap,
 259                                                                                                                         get_code_2_str(infTransferRate, dcodQ931BcInfTransferRateTable), infTransferRate,
 260                                                                                                                         get_code_2_str(usrL1Prot, dcodQ931BcusrL1ProtTable), usrL1Prot);
 261                         }
 262                         break;
 263                 case PROT_Q931_IE_CAUSE:
 264                         {
 265                                 uint8_t codingStandard, location, cause,diagOct = 5;
 266                                 codingStandard = get_bits(OCTET(3),6,7);
 267                                 location = get_bits(OCTET(3),1,4);
 268                                 
 269                                 cause = get_bits(OCTET(4),1,7);
 270 
 271                                 *str_len+= sprintf(&str[*str_len], "coding:%s(%d) location:%s(%d) val:%s(%d)\n",
 272                                                                                         get_code_2_str(codingStandard, dcodQ931BcCodingStandardTable), codingStandard,
 273                                                                                         get_code_2_str(location,dcodQ931IelocationTable), location,
 274                                                                                         get_code_2_str(cause, dcodQ931CauseCodeTable),
 275                                                                                         cause);
 276                                 switch(cause) {
 277                                         case PROT_Q931_RELEASE_CAUSE_IE_NOT_EXIST:
 278                                                 while(diagOct++ < len) {
 279                                                         *str_len+= sprintf(&str[*str_len], "  %d:IE %s(0x%02x)\n",
 280                                                                                                                         diagOct,
 281                                                                                                                         get_code_2_str(OCTET(diagOct), dcodQ931IEIDTable),
 282                                                                                                                         OCTET(diagOct));
 283                                                 }
 284                                                 break;
 285                                         case PROT_Q931_RELEASE_CAUSE_WRONG_CALL_STATE:
 286                                                 while(diagOct++ < len) {
 287                                                         *str_len+= sprintf(&str[*str_len], "  %d:Message %s(0x%02x)\n",
 288                                                                                                                         diagOct,
 289                                                                                                                         get_code_2_str(OCTET(diagOct), dcodQ931MsgTypeTable),
 290                                                                                                                         OCTET(diagOct));
 291                                                 }
 292                                                 break;
 293                                         case PROT_Q931_RECOVERY_ON_TIMER_EXPIRE:
 294                                                 *str_len+= sprintf(&str[*str_len], "  Timer T\n");
 295                                                 while(diagOct++ < len) {
 296                                                         if(OCTET(diagOct) >= ' ' && OCTET(diagOct) < 0x7f) {
 297                                                                 *str_len+= sprintf(&str[*str_len], "%c", OCTET(diagOct));
 298                                                         } else {
 299                                                                 *str_len+= sprintf(&str[*str_len], ".");
 300                                                         }
 301                                                 }
 302                                                 break;
 303                                         default:
 304                                                 while(diagOct++ < len) {
 305                                                         *str_len+= sprintf(&str[*str_len], " %d: 0x%02x\n",
 306                                                                                                                                         diagOct,
 307                                                                                                                                         OCTET(diagOct));
 308                                                 }
 309                                                 break;
 310                                 }
 311                         }               
 312                         break;          
 313                 case PROT_Q931_IE_CHANNEL_ID:
 314                         {
 315                                 uint8_t infoChannelSelection=0;
 316                                 uint8_t prefExclusive=0;
 317                                 uint8_t ifaceIdPresent=0;
 318                                 uint8_t ifaceIdentifier = 0; /* octet_3_1 */
 319                                 uint8_t chanType=0, numberMap=0, codingStandard=0;
 320                                 uint8_t channelNo = 0;
 321                                 
 322                                 infoChannelSelection = get_bits(OCTET(3),1,2);
 323                                 prefExclusive = get_bits(OCTET(3),4,4);
 324                                 ifaceIdPresent = get_bits(OCTET(3),7,7);
 325         
 326                                 if (ifaceIdPresent) {
 327                                         ifaceIdentifier= get_bits(OCTET(4),1,7);
 328                                         chanType = get_bits(OCTET(5),1,4);
 329                                         numberMap = get_bits(OCTET(5),5,5);
 330                                         codingStandard = get_bits(OCTET(5),6,7);
 331                                         channelNo = get_bits(OCTET(6),1,7);
 332                                 } else {
 333                                         chanType = get_bits(OCTET(4),1,4);
 334                                         numberMap = get_bits(OCTET(4),5,5);
 335                                         codingStandard = get_bits(OCTET(4),6,7);
 336                                         channelNo = get_bits(OCTET(5),1,7);
 337                                 }
 338                                 
 339                                 if (numberMap) {
 340                                         *str_len+= sprintf(&str[*str_len], " MAP:%s ", get_code_2_str(infoChannelSelection, dcodQ931InfoChannelSelTable));
 341                                 } else {
 342                                         *str_len+= sprintf(&str[*str_len], "No:%d ", channelNo);
 343                                 }
 344         
 345                                 *str_len+= sprintf(&str[*str_len], "Type:%s(%d) %s ", get_code_2_str(chanType,dcodQ931ChanTypeTable), chanType, (numberMap)? "Map":"");
 346                                 *str_len+= sprintf(&str[*str_len], "%s/%s \n",
 347                                                                         (prefExclusive)? "Exclusive":"Preferred", 
 348                                                                         (ifaceIdPresent)? "Explicit":"Implicit");
 349                         }
 350                         break;
 351                 case PROT_Q931_IE_CALLING_PARTY_NUMBER:
 352                         {
 353                                 uint8_t plan, type, screening = 0, presentation = 0, callingNumOct, j;
 354                                 uint8_t screeningEnabled = 0, presentationEnabled = 0;
 355                                 char callingNumDigits[32];
 356                                 memset(callingNumDigits, 0, sizeof(callingNumDigits));
 357                                 
 358                                 plan = get_bits(OCTET(3),1,4);
 359                                 type = get_bits(OCTET(3),5,7);
 360 
 361                                 if(!get_bits(OCTET(3),8,8)) {
 362                                         screening = get_bits(OCTET(4),1,2);
 363                                         presentation = get_bits(OCTET(4),6,7);
 364                                         screeningEnabled = 1;
 365                                         presentationEnabled = 1;
 366                                         callingNumOct = 4;
 367                                 } else {
 368                                         callingNumOct = 3;
 369                                 }
 370                                 if(len >= sizeof(callingNumDigits)) {   
 371                                         len = sizeof(callingNumDigits)-1;
 372                                 }
 373                                 j = 0;
 374                                 while(callingNumOct++ <= len+1) {
 375                                         callingNumDigits[j++]=ia5[get_bits(OCTET(callingNumOct),1,4)][get_bits(OCTET(callingNumOct),5,8)];
 376                                 }
 377                                 callingNumDigits[j]='\0';
 378                                 *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)",
 379                                                                                                                          
 380                                                                                                                         callingNumDigits, j,
 381                                                                                                                         get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
 382                                                                                                                         get_code_2_str(type, dcodQ931TypeofNumberTable), type);
 383                                                                                                                         
 384                                 if (presentationEnabled||screeningEnabled) {
 385                                         *str_len+= sprintf(&str[*str_len], "scr:%s(%d) pres:%s(%d)\n",
 386                                                                                                                 get_code_2_str(screening, dcodQ931ScreeningTable),      screening,
 387                                                                                                                 get_code_2_str(presentation, dcodQ931PresentationTable), presentation);
 388                                 } else {
 389                                         *str_len+= sprintf(&str[*str_len], "\n");
 390                                 }
 391                         }
 392                         break;
 393                 
 394                 case PROT_Q931_IE_CALLED_PARTY_NUMBER:
 395                         {
 396                                 uint8_t plan, type, calledNumOct,j;
 397                                 char calledNumDigits[32];
 398                                 memset(calledNumDigits, 0, sizeof(calledNumDigits));
 399                                 plan = get_bits(OCTET(3),1,4);
 400                                 type = get_bits(OCTET(3),5,7);
 401 
 402                                 if(len >= sizeof(calledNumDigits)) {    
 403                                         len = sizeof(calledNumDigits)-1;
 404                                 }
 405                                 calledNumOct = 3;
 406                                 j = 0;
 407                                 while(calledNumOct++ <= len+1) {
 408                                         calledNumDigits[j++]=ia5[get_bits(OCTET(calledNumOct),1,4)][get_bits(OCTET(calledNumOct),5,8)];
 409                                 }
 410                                 calledNumDigits[j]='\0';
 411                                 *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)\n",
 412                                                                                                                 calledNumDigits, j,
 413                                                                                                                 get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
 414                                                                                                                 get_code_2_str(type, dcodQ931TypeofNumberTable), type);
 415                         }
 416                         break;
 417                 case PROT_Q931_IE_REDIRECTING_NUMBER: //rdnis
 418                         {
 419                                 uint8_t plan, type, screening = 0, presentation = 0, reason = 0, rdnisOct,j;
 420                                 uint8_t screeningEnabled = 0, presentationEnabled = 0, reasonEnabled = 0;
 421                                 char rdnis_string[32];
 422                                 memset(rdnis_string, 0, sizeof(rdnis_string));
 423                                 rdnisOct = 5;
 424                                 plan = get_bits(OCTET(3),1,4);
 425                                 type = get_bits(OCTET(3),5,7);
 426                         
 427                                 if(!get_bits(OCTET(3),8,8)) { //Oct 3a exists
 428                                         rdnisOct++;
 429                                         screening = get_bits(OCTET(4),1,2);
 430                                         presentation = get_bits(OCTET(4),6,7);
 431                                         screeningEnabled = 1;
 432                                         presentationEnabled = 1;
 433                                         if (!get_bits(OCTET(4),8,8)) { //Oct 3b exists
 434                                                 rdnisOct++;
 435                                                 reason = get_bits(OCTET(5),1,4);
 436                                                 reasonEnabled = 1;
 437                                         }
 438                                 } 
 439         
 440                                 if(len >= sizeof(rdnis_string)) {       
 441                                         len = sizeof(rdnis_string)-1;
 442                                 }
 443                                 
 444                                 j = 0;
 445                                 while(rdnisOct++ <= len+1) {
 446                                         rdnis_string[j++]=ia5[get_bits(OCTET(rdnisOct),1,4)][get_bits(OCTET(rdnisOct),5,8)];
 447                                 }
 448         
 449                                 rdnis_string[j]='\0';   
 450                                 *str_len+= sprintf(&str[*str_len], "%s(l:%d) plan:%s(%d) type:%s(%d)",
 451                                                                                                                         rdnis_string, j,
 452                                                                                                                         get_code_2_str(plan, dcodQ931NumberingPlanTable), plan,
 453                                                                                                                         get_code_2_str(type, dcodQ931TypeofNumberTable), type);
 454                                                                                                                         
 455                                 if(presentationEnabled || screeningEnabled) {
 456                                         *str_len+= sprintf(&str[*str_len], "scr:%s(%d) pres:%s(%d)",
 457                                                                                                                 get_code_2_str(screening, dcodQ931ScreeningTable),      screening,
 458                                                                                                                 get_code_2_str(presentation, dcodQ931PresentationTable), presentation);
 459                                 }
 460         
 461                                 if(reasonEnabled) {
 462                                         *str_len+= sprintf(&str[*str_len], "reason:%s(%d)",
 463                                                                                                                 get_code_2_str(reason, dcodQ931ReasonTable), reason);
 464                                 }
 465                                 *str_len+= sprintf(&str[*str_len], "\n");
 466                         }
 467                         break;
 468                 case PROT_Q931_IE_USER_USER:
 469                         {
 470                                 uint8_t protDiscr = 0x00, j, uui_stringOct;
 471                                 char uui_string[32];
 472                                 memset(uui_string, 0, sizeof(uui_string));
 473                                 protDiscr = OCTET(3);
 474                                 uui_stringOct = 3;
 475                                 if (protDiscr != 0x04) { /* Non-IA5 */
 476                                         *str_len+= sprintf(&str[*str_len], "%s (0x%02x)\n",
 477                                                                                                                         get_code_2_str(protDiscr, dcodQ931UuiProtDiscrTable), protDiscr);
 478                                 } else {
 479                                         j = 0;
 480                                         
 481                                         if(len >= sizeof(uui_string)) { 
 482                                                 len = sizeof(uui_string)-1;
 483                                         }
 484                                         while(uui_stringOct++ <= len+1) {
 485                                                 uui_string[j++]=ia5[get_bits(OCTET(uui_stringOct),1,4)][get_bits(OCTET(uui_stringOct),5,8)];
 486                                         }
 487                                         uui_string[j]='\0';     
 488                                         *str_len+= sprintf(&str[*str_len], "  %s (0x%02x) <%s>\n",
 489                                                                                                                         get_code_2_str(protDiscr, dcodQ931UuiProtDiscrTable), protDiscr,
 490                                                                                                                         uui_string);
 491                                 }
 492                         }
 493                         break;
 494                 case PROT_Q931_IE_DISPLAY:
 495                         {
 496                                 uint8_t displayStrOct=2, j;
 497                                 char displayStr[82];
 498                                 memset(displayStr, 0, sizeof(displayStr));
 499                                 
 500                                 if(get_bits(OCTET(3),8,8)) {
 501                                         displayStrOct++;
 502                                 }
 503                                 j = 0;  
 504                                 if(len >= sizeof(displayStr)) { 
 505                                         len = sizeof(displayStr)-1;
 506                                 }
 507                                 while(displayStrOct++ <= len+1) {
 508                                         displayStr[j++]=ia5[get_bits(OCTET(displayStrOct),1,4)][get_bits(OCTET(displayStrOct),5,8)];
 509                                 }
 510                                 displayStr[j]='\0';
 511                                 *str_len+= sprintf(&str[*str_len], "%s(l:%d)\n",
 512                                                                                                                 displayStr, len);
 513                         }
 514                         break;
 515                 case PROT_Q931_IE_RESTART_IND:
 516                         {
 517                                 uint8_t indClass;
 518                                 indClass = get_bits(OCTET(3),1,3);
 519                                 *str_len+= sprintf(&str[*str_len], "class:%s(%d)\n",
 520                                                                                                         get_code_2_str(indClass,dcodQ931RestartIndClassTable), indClass);
 521                         }
 522                         break;
 523                 case PROT_Q931_IE_PROGRESS_IND:
 524                         {
 525                                 uint8_t codingStandard, location, progressDescr;
 526                                 codingStandard = get_bits(OCTET(3),6,7);
 527                                 location = get_bits(OCTET(3),1,4);
 528                                 progressDescr = get_bits(OCTET(4),1,7);
 529                                 *str_len+= sprintf(&str[*str_len], "coding:%s(%d) location:%s(%d) descr:%s(%d)\n",
 530                                                                                                         get_code_2_str(codingStandard,dcodQ931BcCodingStandardTable), codingStandard,
 531                                                                                                         get_code_2_str(location,dcodQ931IelocationTable), location,
 532                                                                                                         get_code_2_str(progressDescr,dcodQ931IeprogressDescrTable), progressDescr);
 533                         }
 534                         break;
 535                 case PROT_Q931_IE_KEYPAD_FACILITY:
 536                         {
 537                                 uint8_t keypadFacilityStrOct = 3, j;
 538                                 char keypadFacilityStr[82];
 539                                 memset(keypadFacilityStr, 0, sizeof(keypadFacilityStr));
 540                                 
 541                                 j = 0;  
 542                                 if(len >= sizeof(keypadFacilityStr)) {  
 543                                         len = sizeof(keypadFacilityStr)-1;
 544                                 }
 545                                 while(keypadFacilityStrOct++ < len+1) {
 546                                         keypadFacilityStr[j++]=ia5[get_bits(OCTET(keypadFacilityStrOct),1,4)][get_bits(OCTET(keypadFacilityStrOct),5,8)];
 547                                 }
 548                                 keypadFacilityStr[j]='\0';
 549                                 *str_len+= sprintf(&str[*str_len], "  digits:%s(l:%d)\n",
 550                                                                                                                 keypadFacilityStr, len);
 551                         }
 552                         break;
 553                 case PROT_Q931_IE_FACILITY:
 554                         {
 555                                 uint8_t protProfile;
 556                                 protProfile = get_bits(OCTET(3),1,5);
 557                                 *str_len+= sprintf(&str[*str_len], "Prot profile:%s(%d)\n",
 558                                                                                                         get_code_2_str(protProfile,dcodQ931IeFacilityProtProfileTable), protProfile);
 559                         }
 560                         break;
 561                 case PROT_Q931_IE_GENERIC_DIGITS:
 562                         {
 563                                 uint8_t encoding,type;
 564                                 int value = 0;
 565 
 566                                 encoding = get_bits(OCTET(3),6,8);
 567                                 type = get_bits(OCTET(3),1,5);
 568 
 569                                 *str_len+= sprintf(&str[*str_len], "encoding:%s(%d) type:%s(%d) ",
 570                                                                                                         get_code_2_str(encoding,dcodQ931GenDigitsEncodingTable), encoding,
 571                                                                                                         get_code_2_str(encoding,dcodQ931GenDigitsTypeTable), type);
 572 
 573                                 if (len > 1) {
 574                                         uint32_t j=0;
 575                                         
 576                                         while(++j < len) {
 577                                                 switch(encoding) {
 578                                                         case 0: /* BCD even */
 579                                                         case 1: /* BCD odd */
 580                                                                 {
 581                                                                         uint8_t byte = OCTET(j+3);
 582                                                                         value = (get_bits(byte,1,4)*10) + get_bits(byte,5,8) + (value*10);
 583                                                                 }
 584                                                                 break;
 585                                                         case 2: /* IA 5 */                                                      
 586                                                                 value = value*10 + OCTET(j+3)-'0';
 587                                                                 *str_len+= sprintf(&str[*str_len], "%c", OCTET(j+3));
 588                                                                 break;
 589                                                         case 3: 
 590                                                                 /* Don't know how to decode binary encoding yet */
 591                                                                 *str_len+= sprintf(&str[*str_len], "Binary encoded");
 592                                                                 break;
 593                                                 }
 594                                         }
 595                                         *str_len+= sprintf(&str[*str_len], " ");
 596                                         switch(type) {
 597                                                 case 4: /* info digits */
 598                                                         *str_len+= sprintf(&str[*str_len], "ani2:%s(%d)", get_code_2_str(value,dcodQ931LineInfoTable), value);
 599                                                         break;
 600                                                 case 5: /* Callid */
 601                                                         *str_len+= sprintf(&str[*str_len], "Caller ID not implemented\n");
 602                                                         break;
 603                                         }
 604                                 }
 605                                 *str_len+= sprintf(&str[*str_len], "\n");
 606                                 print_hex_dump(str, str_len, (uint8_t*) data, index_start, index_end);
 607                         }
 608                         break;
 609                 case PROT_Q931_IE_SENDING_COMPLETE:
 610                         /* No need to decode sending complete IE, as no additional info is available except that sending is done */
 611                         /* This is a single octet IE */
 612                         *str_len+= sprintf(&str[*str_len], "\n");
 613                         return 0;
 614                         break;
 615                 case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS:
 616                 case PROT_Q931_IE_REDIRECTION_NUMBER:
 617                 case PROT_Q931_IE_NOTIFICATION_IND:
 618                 case PROT_Q931_IE_DATE_TIME:
 619                 case PROT_Q931_IE_INFORMATION_REQUEST:
 620                 case PROT_Q931_IE_SIGNAL:
 621                 case PROT_Q931_IE_SWITCHOOK:
 622                 case PROT_Q931_IE_FEATURE_ACT:
 623                 case PROT_Q931_IE_FEATURE_IND:
 624                 case PROT_Q931_IE_INFORMATION_RATE:
 625                 case PROT_Q931_IE_END_TO_END_TRANSIT_DELAY:
 626                 case PROT_Q931_IE_TRANSIT_DELAY_SELECT_IND:
 627                 case PROT_Q931_IE_PACKET_LAYER_BINARY_PARAMS:
 628                 case PROT_Q931_IE_PACKET_LAYER_WINDOW_SIZE:
 629                 case PROT_Q931_IE_PACKET_LAYER_SIZE:
 630                 case PROT_Q931_IE_TRANSIT_NETWORK_SELECTION:
 631                 case PROT_Q931_IE_LOW_LAYER_COMPAT:
 632                 case PROT_Q931_IE_HIGH_LAYER_COMPAT:
 633                 case PROT_Q931_IE_ESCAPE_FOR_EXTENSION:
 634                 case PROT_Q931_IE_CALL_IDENTITY:
 635                 case PROT_Q931_IE_CALL_STATE:
 636                 case PROT_Q931_IE_SEGMENTED_MESSAGE:
 637                 case PROT_Q931_IE_NETWORK_SPF_FACILITY:
 638                 case PROT_Q931_IE_CALLING_PARTY_SUBADDRESS:
 639                 default:
 640                         {
 641                                 *str_len += sprintf(&str[*str_len], "Undecoded");
 642                                 print_hex_dump((char*)str, str_len, data, index_start, index_end);
 643                         }
 644                         break;
 645         }
 646 
 647         return len+1;
 648 }
 649 
 650 void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end)
 651 {
 652         int k;
 653         *str_len += sprintf(&str[*str_len], "  [ ");
 654         for(k=index_start; k <= index_end; k++) {
 655                 if (k && !(k%32)) {
 656                         *str_len += sprintf(&str[*str_len], "\n    ");
 657                 }
 658                 *str_len += sprintf(&str[*str_len], "%02x ", data[k]);
 659         }
 660         *str_len += sprintf(&str[*str_len], "]\n");
 661         return;
 662 }
 663 
 664 

/* [<][>][^][v][top][bottom][index][help] */