root/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c

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

DEFINITIONS

This source file includes following definitions.
  1. copy_cgPtyNum_from_sngss7
  2. copy_cgPtyNum_to_sngss7
  3. copy_cdPtyNum_from_sngss7
  4. copy_cdPtyNum_to_sngss7
  5. copy_tknStr_from_sngss7
  6. append_tknStr_from_sngss7
  7. check_for_state_change
  8. check_cics_in_range
  9. extract_chan_data
  10. check_for_reset
  11. get_unique_id
  12. check_if_rx_grs_started
  13. check_if_rx_grs_processed
  14. check_if_rx_gra_started
  15. check_for_res_sus_flag
  16. process_span_ucic
  17. clear_rx_grs_flags
  18. clear_rx_grs_data
  19. clear_rx_gra_data
  20. clear_tx_grs_flags
  21. clear_tx_grs_data
  22. clear_rx_rsc_flags
  23. clear_tx_rsc_flags
  24. encode_subAddrIE_nsap
  25. encode_subAddrIE_nat

   1 /*
   2  * Copyright (c) 2009, Konrad Hammel <konrad@sangoma.com>
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  *
   9  * * Redistributions of source code must retain the above copyright
  10  * notice, this list of conditions and the following disclaimer.
  11  *
  12  * * Redistributions in binary form must reproduce the above copyright
  13  * notice, this list of conditions and the following disclaimer in the
  14  * documentation and/or other materials provided with the distribution.
  15  *
  16  * * Neither the name of the original author; nor the names of any contributors
  17  * may be used to endorse or promote products derived from this software
  18  * without specific prior written permission.
  19  *
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  25  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 
  34 /* INCLUDE ********************************************************************/
  35 #include "ftmod_sangoma_ss7_main.h"
  36 /******************************************************************************/
  37 
  38 /* DEFINES ********************************************************************/
  39 /******************************************************************************/
  40 
  41 /* GLOBALS ********************************************************************/
  42 uint32_t sngss7_id;
  43 /******************************************************************************/
  44 
  45 /* PROTOTYPES *****************************************************************/
  46 uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
  47 uint8_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
  48 uint8_t copy_cgPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum);
  49 uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum);
  50 uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum);
  51 uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum);
  52 
  53 int check_for_state_change(ftdm_channel_t *ftdmchan);
  54 int check_cics_in_range(sngss7_chan_data_t *sngss7_info);
  55 int check_for_reset(sngss7_chan_data_t *sngss7_info);
  56 
  57 unsigned long get_unique_id(void);
  58 
  59 ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
  60 
  61 ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan);
  62 ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan);
  63 ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan);
  64 ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan);
  65 
  66 ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan);
  67 
  68 ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info);
  69 ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info);
  70 ftdm_status_t clear_rx_rsc_flags(sngss7_chan_data_t *sngss7_info);
  71 ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info);
  72 ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info);
  73 ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info);
  74 ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info);
  75 
  76 ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type);
  77 ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type);
  78 /******************************************************************************/
  79 
  80 /* FUNCTIONS ******************************************************************/
  81 uint8_t copy_cgPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
  82 {
  83 
  84         return 0;
  85 }
  86 
  87 /******************************************************************************/
  88 uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
  89 {
  90         int k;
  91         int j;
  92         int flag;
  93         int odd;
  94         char tmp[2];
  95         uint8_t lower;
  96         uint8_t upper;
  97 
  98         /**************************************************************************/
  99         cgPtyNum->eh.pres                  = PRSNT_NODEF;
 100         /**************************************************************************/
 101         cgPtyNum->natAddrInd.pres   = PRSNT_NODEF;
 102         cgPtyNum->natAddrInd.val        = 0x03;
 103         /**************************************************************************/
 104         cgPtyNum->scrnInd.pres    = PRSNT_NODEF;
 105         cgPtyNum->scrnInd.val      = ftdm->screen;
 106         /**************************************************************************/
 107         cgPtyNum->presRest.pres  = PRSNT_NODEF;
 108         cgPtyNum->presRest.val    = ftdm->pres;
 109         /**************************************************************************/
 110         cgPtyNum->numPlan.pres    = PRSNT_NODEF;
 111         cgPtyNum->numPlan.val      = 0x01;
 112         /**************************************************************************/
 113         cgPtyNum->niInd.pres            = PRSNT_NODEF;
 114         cgPtyNum->niInd.val              = 0x00;
 115         /**************************************************************************/
 116         cgPtyNum->addrSig.pres    = PRSNT_NODEF;
 117 
 118         /* atoi will search through memory starting from the pointer it is given until
 119          * it finds the \0...since tmp is on the stack it will start going through the
 120          * possibly causing corruption.  Hard code a \0 to prevent this
 121          */
 122         tmp[1] = '\0';
 123         k = 0;
 124         j = 0;
 125         flag = 0;
 126         odd = 0;
 127         upper = 0x0;
 128         lower = 0x0;
 129 
 130         while (1) {
 131                 /* grab a digit from the ftdm digits */
 132                 tmp[0] = ftdm->cid_num.digits[k];
 133 
 134                 /* check if the digit is a number and that is not null */
 135                 while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
 136                         SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
 137                         /* move on to the next value */
 138                         k++;
 139                         tmp[0] = ftdm->cid_num.digits[k];
 140                 } /* while(!(isdigit(tmp))) */
 141 
 142                 /* check if tmp is null or a digit */
 143                 if (tmp[0] != '\0') {
 144                         /* push it into the lower nibble */
 145                         lower = strtol(&tmp[0], (char **)NULL, 16);
 146                         /* move to the next digit */
 147                         k++;
 148                         /* grab a digit from the ftdm digits */
 149                         tmp[0] = ftdm->cid_num.digits[k];
 150 
 151                         /* check if the digit is a number and that is not null */
 152                         while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
 153                                 SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
 154                                 k++;
 155                                 tmp[0] = ftdm->cid_num.digits[k];
 156                         } /* while(!(isdigit(tmp))) */
 157 
 158                         /* check if tmp is null or a digit */
 159                         if (tmp[0] != '\0') {
 160                                 /* push the digit into the upper nibble */
 161                                 upper = (strtol(&tmp[0], (char **)NULL, 16)) << 4;
 162                         } else {
 163                                 /* there is no upper ... fill in 0 */
 164                                 upper = 0x0;
 165                                 /* throw the odd flag */
 166                                 odd = 1;
 167                                 /* throw the end flag */
 168                                 flag = 1;
 169                         } /* if (tmp != '\0') */
 170                 } else {
 171                         /* keep the odd flag down */
 172                         odd = 0;
 173                         /* break right away since we don't need to write the digits */
 174                         break;
 175                 }
 176 
 177                 /* push the digits into the trillium structure */
 178                 cgPtyNum->addrSig.val[j] = upper | lower;
 179 
 180                 /* increment the trillium pointer */
 181                 j++;
 182 
 183                 /* if the flag is up we're through all the digits */
 184                 if (flag) break;
 185 
 186                 /* move to the next digit */
 187                 k++;
 188         } /* while(1) */
 189 
 190         cgPtyNum->addrSig.len = j;
 191 
 192         /**************************************************************************/
 193         cgPtyNum->oddEven.pres    = PRSNT_NODEF;
 194         cgPtyNum->oddEven.val      = odd;
 195         /**************************************************************************/
 196         return 0;
 197 }
 198 
 199 /******************************************************************************/
 200 uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
 201 {
 202 
 203         return 0;
 204 }
 205 
 206 /******************************************************************************/
 207 uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
 208 {
 209         int k;
 210         int j;
 211         int flag;
 212         int odd;
 213         char tmp[2];
 214         uint8_t lower;
 215         uint8_t upper;
 216 
 217         /**************************************************************************/
 218         cdPtyNum->eh.pres                  = PRSNT_NODEF;
 219         /**************************************************************************/
 220         cdPtyNum->natAddrInd.pres   = PRSNT_NODEF;
 221         cdPtyNum->natAddrInd.val        = 0x03;
 222         /**************************************************************************/
 223         cdPtyNum->numPlan.pres    = PRSNT_NODEF;
 224         cdPtyNum->numPlan.val      = 0x01;
 225         /**************************************************************************/
 226         cdPtyNum->innInd.pres      = PRSNT_NODEF;
 227         cdPtyNum->innInd.val            = 0x01;
 228         /**************************************************************************/
 229         cdPtyNum->addrSig.pres    = PRSNT_NODEF;
 230 
 231         /* atoi will search through memory starting from the pointer it is given until
 232          * it finds the \0...since tmp is on the stack it will start going through the
 233          * possibly causing corruption.  Hard code a \0 to prevent this
 234          */ /* dnis */
 235         tmp[1] = '\0';
 236         k = 0;
 237         j = 0;
 238         flag = 0;
 239         odd = 0;
 240         upper = 0x0;
 241         lower = 0x0;
 242 
 243         while (1) {
 244                 /* grab a digit from the ftdm digits */
 245                 tmp[0] = ftdm->dnis.digits[k];
 246 
 247                 /* check if the digit is a number and that is not null */
 248                 while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
 249                         SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
 250                         /* move on to the next value */
 251                         k++;
 252                         tmp[0] = ftdm->dnis.digits[k];
 253                 } /* while(!(isdigit(tmp))) */
 254 
 255                 /* check if tmp is null or a digit */
 256                 if (tmp[0] != '\0') {
 257                         /* push it into the lower nibble */
 258                         lower = strtol(&tmp[0], (char **)NULL, 16);
 259                         /* move to the next digit */
 260                         k++;
 261                         /* grab a digit from the ftdm digits */
 262                         tmp[0] = ftdm->dnis.digits[k];
 263 
 264                         /* check if the digit is a number and that is not null */
 265                         while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
 266                                 SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
 267                                 k++;
 268                                 tmp[0] = ftdm->dnis.digits[k];
 269                         } /* while(!(isdigit(tmp))) */
 270 
 271                         /* check if tmp is null or a digit */
 272                         if (tmp[0] != '\0') {
 273                                 /* push the digit into the upper nibble */
 274                                 upper = (strtol(&tmp[0], (char **)NULL, 16)) << 4;
 275                         } else {
 276                                 /* there is no upper ... fill in ST */
 277                                 upper = 0xF0;
 278                                 /* keep the odd flag down */
 279                                 odd = 0;
 280                                 /* throw the end flag */
 281                                 flag = 1;
 282                         } /* if (tmp != '\0') */
 283                 } else {
 284                         /* throw the odd flag */
 285                         odd = 1;
 286                         /* need to add the ST */
 287                         lower = 0xF;
 288                         upper = 0x0;
 289                         /* throw the flag */
 290                         flag = 1;
 291                 }
 292 
 293                 /* push the digits into the trillium structure */
 294                 cdPtyNum->addrSig.val[j] = upper | lower;
 295 
 296                 /* increment the trillium pointer */
 297                 j++;
 298 
 299                 /* if the flag is up we're through all the digits */
 300                 if (flag) break;
 301 
 302                 /* move to the next digit */
 303                 k++;
 304         } /* while(1) */
 305 
 306         cdPtyNum->addrSig.len = j;
 307 
 308         /**************************************************************************/
 309         cdPtyNum->oddEven.pres    = PRSNT_NODEF;
 310 
 311         cdPtyNum->oddEven.val      = odd;
 312 
 313         /**************************************************************************/
 314         return 0;
 315 }
 316 
 317 /******************************************************************************/
 318 uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven)
 319 {
 320         uint8_t i;
 321         uint8_t j;
 322 
 323         /* check if the token string is present */
 324 
 325         if (str.pres == 1) {
 326                 j = 0;
 327 
 328                 for (i = 0; i < str.len; i++) {
 329                         sprintf(&ftdm[j], "%X", (str.val[i] & 0x0F));
 330                         j++;
 331                         sprintf(&ftdm[j], "%X", ((str.val[i] & 0xF0) >> 4));
 332                         j++;
 333                 }
 334 
 335                 /* if the odd flag is up the last digit is a fake "0" */
 336                 if ((oddEven.pres == 1) && (oddEven.val == 1)) {
 337                         ftdm[j-1] = '\0';
 338                 } else {
 339                         ftdm[j] = '\0';
 340                 }
 341 
 342                 
 343         } else {
 344                 SS7_ERROR("Asked to copy tknStr that is not present!\n");
 345                 return 1;
 346         }
 347 
 348         return 0;
 349 }
 350 
 351 /******************************************************************************/
 352 uint8_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven)
 353 {
 354         int i = 0;
 355         int j = 0;
 356 
 357         /* check if the token string is present */
 358         if (str.pres == 1) {
 359                 /* find the length of the digits so far */
 360                 j = strlen(ftdm);
 361 
 362                 /* confirm that we found an acceptable length */
 363                 if ( j > 25 ) {
 364                         SS7_ERROR("string length exceeds maxium value...aborting append!\n");
 365                         return 1;
 366                 } /* if ( j > 25 ) */
 367 
 368                 /* copy in digits */
 369                 for (i = 0; i < str.len; i++) {
 370                         /* convert 4 bit integer to char and copy into lower nibblet*/
 371                         sprintf(&ftdm[j], "%X", (str.val[i] & 0x0F));
 372                         /* move along */
 373                         j++;
 374                         /* convert 4 bit integer to char and copy into upper nibblet */
 375                         sprintf(&ftdm[j], "%X", ((str.val[i] & 0xF0) >> 4));
 376                         /* move along */
 377                         j++;
 378                 } /* for (i = 0; i < str.len; i++) */
 379 
 380                 /* if the odd flag is up the last digit is a fake "0" */
 381                 if ((oddEven.pres == 1) && (oddEven.val == 1)) {
 382                         ftdm[j-1] = '\0';
 383                 } else {
 384                         ftdm[j] = '\0';
 385                 } /* if ((oddEven.pres == 1) && (oddEven.val == 1)) */
 386         } else {
 387                 SS7_ERROR("Asked to copy tknStr that is not present!\n");
 388                 return 1;
 389         } /* if (str.pres == 1) */
 390 
 391         return 0;
 392 }
 393 
 394 /******************************************************************************/
 395 int check_for_state_change(ftdm_channel_t *ftdmchan)
 396 {
 397 
 398         /* check to see if there are any pending state changes on the channel and give them a sec to happen*/
 399         ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 500);
 400 
 401         /* check the flag to confirm it is clear now */
 402 
 403         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 404                 /* the flag is still up...so we have a problem */
 405                 SS7_DEBUG_CHAN(ftdmchan, "FTDM_CHANNEL_STATE_CHANGE flag set for over 500ms, channel state = %s\n",
 406                                                                         ftdm_channel_state2str (ftdmchan->state));
 407 
 408                 return 1;
 409         }
 410 
 411         return 0;
 412 }
 413 
 414 /******************************************************************************/
 415 int check_cics_in_range(sngss7_chan_data_t *sngss7_info)
 416 {
 417 
 418 
 419 #if 0
 420         ftdm_channel_t          *tmp_ftdmchan;
 421         sngss7_chan_data_t  *tmp_sngss7_info;
 422         int                             i = 0;
 423         
 424         /* check all the circuits in the range to see if we are the last ckt to reset */
 425         for ( i = sngss7_info->grs.circuit; i < ( sngss7_info->grs.range + 1 ); i++ ) {
 426                 if ( g_ftdm_sngss7_data.cfg.isupCircuit[i].siglink == 0 ) {
 427                 
 428                         /* get the ftdmchan and ss7_chan_data from the circuit */
 429                         if (extract_chan_data(g_ftdm_sngss7_data.cfg.isupCircuit[i].id, &tmp_sngss7_info, &tmp_ftdmchan)) {
 430                                 SS7_ERROR("Failed to extract channel data for circuit = %d!\n", g_ftdm_sngss7_data.cfg.isupCircuit[i].id);
 431                                 return 0;
 432                         }
 433 
 434                         /* check if the channel still has the reset flag done is up */
 435                         if (!sngss7_test_flag(tmp_sngss7_info, FLAG_GRP_RESET_RX_DN)) {
 436                                 SS7_DEBUG_CHAN(tmp_ftdmchan, "[CIC:%d] Still processing reset...\n", tmp_sngss7_info->circuit->cic);
 437                                 return 0;
 438                         }
 439                 } /* if not siglink */
 440         } /* for */
 441 
 442         SS7_DEBUG("All circuits out of reset: circuit=%d, range=%d\n",
 443                                 sngss7_info->grs.circuit,
 444                                 sngss7_info->grs.range);
 445         return 1;
 446 
 447 #endif
 448 
 449         return 0;
 450 
 451 }
 452 
 453 /******************************************************************************/
 454 ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan)
 455 {
 456         /*SS7_FUNC_TRACE_ENTER(__FUNCTION__);*/
 457 
 458         if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj == NULL) {
 459                 SS7_ERROR("sngss7_info is Null for circuit #%d\n", circuit);
 460                 return FTDM_FAIL;
 461         }
 462 
 463         ftdm_assert_return(g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj, FTDM_FAIL, "received message on signalling link or non-configured cic\n");
 464 
 465         *sngss7_info = g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj;
 466 
 467         ftdm_assert_return((*sngss7_info)->ftdmchan, FTDM_FAIL, "received message on signalling link or non-configured cic\n");
 468         *ftdmchan = (*sngss7_info)->ftdmchan;
 469 
 470         /*SS7_FUNC_TRACE_EXIT(__FUNCTION__);*/
 471         return FTDM_SUCCESS;
 472 }
 473 
 474 /******************************************************************************/
 475 int check_for_reset(sngss7_chan_data_t *sngss7_info)
 476 {
 477 
 478         if (sngss7_test_flag(sngss7_info,FLAG_RESET_RX)) {
 479                 return 1;
 480         }
 481         
 482         if (sngss7_test_flag(sngss7_info,FLAG_RESET_TX)) {
 483                 return 1;
 484         }
 485         
 486         if (sngss7_test_flag(sngss7_info,FLAG_GRP_RESET_RX)) {
 487                 return 1;
 488         }
 489         
 490         if (sngss7_test_flag(sngss7_info,FLAG_GRP_RESET_TX)) {
 491                 return 1;
 492         }
 493 
 494         return 0;
 495         
 496 }
 497 
 498 /******************************************************************************/
 499 unsigned long get_unique_id(void)
 500 {
 501 
 502         if (sngss7_id < 420000000) {
 503                 sngss7_id++;
 504         } else {
 505                 sngss7_id = 1;
 506         }
 507 
 508         return(sngss7_id);
 509 }
 510 
 511 /******************************************************************************/
 512 ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan)
 513 {
 514         ftdm_channel_t          *ftdmchan = NULL;
 515         sngss7_chan_data_t  *sngss7_info = NULL;
 516         sngss7_span_data_t      *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
 517         int                             i;
 518 
 519         for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
 520 
 521                 /* extract the channel in question */
 522                 if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
 523                         SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
 524                         continue;
 525                 }
 526 
 527                 /* check if the GRP_RESET_RX flag is already up */
 528                 if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) {
 529                         /* we have already processed this channel...move along */
 530                         continue;
 531                 }
 532 
 533                 /* lock the channel */
 534                 ftdm_mutex_lock(ftdmchan->mutex);
 535 
 536                 /* clear up any pending state changes */
 537                 while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 538                         ftdm_sangoma_ss7_process_state_change (ftdmchan);
 539                 }
 540 
 541                 SS7_INFO_CHAN(ftdmchan, "Rx GRS (%d:%d)\n", 
 542                                 g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic, 
 543                                 (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic + sngss7_span->rx_grs.range));
 544 
 545                 /* flag the channel as having received a reset */
 546                 sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX);
 547 
 548                 switch (ftdmchan->state) {
 549                 /**************************************************************************/
 550                 case FTDM_CHANNEL_STATE_RESTART:
 551 
 552                         /* go to idle so that we can redo the restart state*/
 553                         ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
 554 
 555                         break;
 556                 /**************************************************************************/
 557                 default:
 558 
 559                         /* set the state of the channel to restart...the rest is done by the chan monitor */
 560                         ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
 561                         break;
 562                 /**************************************************************************/
 563                 } /* switch (ftdmchan->state) */
 564 
 565                 /* unlock the channel again before we exit */
 566                 ftdm_mutex_unlock(ftdmchan->mutex);
 567 
 568         } /* for (chans in GRS */
 569 
 570         return FTDM_SUCCESS;
 571 }
 572 
 573 /******************************************************************************/
 574 ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
 575 {
 576         ftdm_channel_t          *ftdmchan = NULL;
 577         sngss7_chan_data_t  *sngss7_info = NULL;
 578         sngss7_span_data_t      *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
 579         int                             i;
 580         int                                     byte = 0;
 581         int                                     bit = 0;
 582 
 583 
 584         ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %s...checking circuits\n", ftdmspan->name);
 585 
 586         /* check all the circuits in the range to see if they are done resetting */
 587         for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
 588 
 589                 /* extract the channel in question */
 590                 if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
 591                         SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
 592                         continue;
 593                 }
 594 
 595                 /* lock the channel */
 596                 ftdm_mutex_lock(ftdmchan->mutex);
 597 
 598                 /* check if there is a state change pending on the channel */
 599                 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 600                         /* check the state to the GRP_RESET_RX_DN flag */
 601                         if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
 602                                 /* this channel is still resetting...do nothing */
 603                                         goto GRS_UNLOCK_ALL;
 604                         } /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
 605                 } else {
 606                         /* state change pending */
 607                         goto GRS_UNLOCK_ALL;
 608                 }
 609         } /* for ( i = circuit; i < (circuit + range + 1); i++) */
 610 
 611         SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
 612                                         sngss7_span->rx_grs.circuit,
 613                                         sngss7_span->rx_grs.range);
 614 
 615         /* check all the circuits in the range to see if they are done resetting */
 616         for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
 617 
 618                 /* extract the channel in question */
 619                 if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
 620                         SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
 621                         /* check if we need to die */
 622                         SS7_ASSERT;
 623                         /* move along */
 624                         continue;
 625                 }
 626 
 627                 /* throw the GRP reset flag complete flag */
 628                 sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
 629 
 630                 /* move the channel to the down state */
 631                 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 632 
 633                 /* update the status map if the ckt is in blocked state */
 634                 if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
 635                         (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
 636                         (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) ||
 637                         (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
 638                 
 639                         sngss7_span->rx_grs.status[byte] = (sngss7_span->rx_grs.status[byte] | (1 << bit));
 640                 } /* if blocked */
 641                 
 642                 /* update the bit and byte counter*/
 643                 bit ++;
 644                 if (bit == 8) {
 645                         byte++;
 646                         bit = 0;
 647                 }
 648         } /* for ( i = circuit; i < (circuit + range + 1); i++) */
 649 
 650 GRS_UNLOCK_ALL:
 651         for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
 652                 /* extract the channel in question */
 653                 if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
 654                         SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
 655                         continue;
 656                 }
 657 
 658                 /* unlock the channel */
 659                 ftdm_mutex_unlock(ftdmchan->mutex);
 660         }
 661 
 662         return FTDM_SUCCESS;
 663 }
 664 
 665 /******************************************************************************/
 666 ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan)
 667 {
 668         ftdm_channel_t          *ftdmchan = NULL;
 669         sngss7_chan_data_t  *sngss7_info = NULL;
 670         sngss7_span_data_t      *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
 671         int                             i;
 672 
 673         for (i = sngss7_span->rx_gra.circuit; i < (sngss7_span->rx_gra.circuit + sngss7_span->rx_gra.range + 1); i++) {
 674 
 675                 /* extract the channel in question */
 676                 if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
 677                         SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
 678                         continue;
 679                 }
 680 
 681                 /* check if the channel is already procoessing the GRA */
 682                 if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
 683                         /* move along */
 684                         continue;
 685                 }
 686 
 687                 /* lock the channel */
 688                 ftdm_mutex_lock(ftdmchan->mutex);
 689 
 690                 /* clear up any pending state changes */
 691                 while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 692                         ftdm_sangoma_ss7_process_state_change (ftdmchan);
 693                 }
 694 
 695                 SS7_INFO_CHAN(ftdmchan, "Rx GRA (%d:%d)\n", 
 696                                 g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic, 
 697                                 (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic + sngss7_span->rx_gra.range));
 698 
 699                 switch (ftdmchan->state) {
 700                 /**********************************************************************/
 701                 case FTDM_CHANNEL_STATE_RESTART:
 702                         
 703                         /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
 704                         sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
 705 
 706                         /* go to DOWN */
 707                         ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 708 
 709                         break;
 710                 /**********************************************************************/
 711                 case FTDM_CHANNEL_STATE_DOWN:
 712 
 713                         /* do nothing, just drop the message */
 714                         SS7_DEBUG("Receveived GRA in down state, dropping\n");
 715 
 716                         break;
 717                 /**********************************************************************/
 718                 case FTDM_CHANNEL_STATE_TERMINATING:
 719                 case FTDM_CHANNEL_STATE_HANGUP:
 720                 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 721                         
 722                         /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
 723                         sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
 724 
 725                         break;
 726                 /**********************************************************************/
 727                 default:
 728                         /* ITU Q764-2.9.5.1.c -> release the circuit */
 729                         if (sngss7_span->rx_gra.cause != 0) {
 730                                 ftdmchan->caller_data.hangup_cause = sngss7_span->rx_gra.cause;
 731                         } else {
 732                                 ftdmchan->caller_data.hangup_cause = 98;        /* Message not compatiable with call state */
 733                         }
 734 
 735                         /* go to terminating to hang up the call */
 736                         ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 737                         break;
 738                 /**********************************************************************/
 739                 }
 740 
 741                 /* unlock the channel again before we exit */
 742                 ftdm_mutex_unlock(ftdmchan->mutex);
 743 
 744         } /* for ( circuits in request */
 745 
 746 
 747         return FTDM_SUCCESS;
 748 }
 749 
 750 /******************************************************************************/
 751 ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan)
 752 {
 753         ftdm_channel_t          *ftdmchan = NULL;
 754         sngss7_chan_data_t      *sngss7_info = NULL;
 755         ftdm_sigmsg_t           sigev;
 756         int                             x;
 757 
 758         for (x = 1; x < (ftdmspan->chan_count + 1); x++) {
 759 
 760                 /* extract the channel structure and sngss7 channel data */
 761                 ftdmchan = ftdmspan->channels[x];
 762                 
 763                 /* if the call data is NULL move on */
 764                 if (ftdmchan->call_data == NULL) continue;
 765 
 766                 sngss7_info = ftdmchan->call_data;
 767 
 768                 /* lock the channel */
 769                 ftdm_mutex_lock(ftdmchan->mutex);
 770 
 771                 memset (&sigev, 0, sizeof (sigev));
 772 
 773                 sigev.chan_id = ftdmchan->chan_id;
 774                 sigev.span_id = ftdmchan->span_id;
 775                 sigev.channel = ftdmchan;
 776 
 777                 /* if we have the PAUSED flag and the sig status is still UP */
 778                 if ((sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) &&
 779                         (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP))) {
 780 
 781                         /* clear up any pending state changes */
 782                         while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 783                                 ftdm_sangoma_ss7_process_state_change (ftdmchan);
 784                         }
 785                         
 786                         /* throw the channel into SUSPENDED to process the flag */
 787                         /* after doing this once the sig status will be down */
 788                         ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
 789                 }
 790 
 791                 /* if the RESUME flag is up go to SUSPENDED to process the flag */
 792                 /* after doing this the flag will be cleared */
 793                 if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) {
 794 
 795                         /* clear up any pending state changes */
 796                         while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 797                                 ftdm_sangoma_ss7_process_state_change (ftdmchan);
 798                         }
 799 
 800                         /* got SUSPENDED state to clear the flag */
 801                         ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
 802                 }
 803 
 804                 /* unlock the channel */
 805                 ftdm_mutex_unlock(ftdmchan->mutex);
 806 
 807         } /* for (x = 1; x < (span->chan_count + 1); x++) */
 808 
 809         /* signal the core that sig events are queued for processing */
 810         ftdm_span_trigger_signals(ftdmspan);
 811 
 812         return FTDM_SUCCESS;
 813 }
 814 
 815 /******************************************************************************/
 816 ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan)
 817 {
 818         ftdm_channel_t          *ftdmchan = NULL;
 819         sngss7_chan_data_t  *sngss7_info = NULL;
 820         sngss7_span_data_t      *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
 821         int                             i;
 822 
 823         for (i = sngss7_span->ucic.circuit; i < (sngss7_span->ucic.circuit + sngss7_span->ucic.range + 1); i++) {
 824 
 825                 /* extract the channel in question */
 826                 if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
 827                         SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
 828                         continue;
 829                 }
 830 
 831                 /* lock the channel */
 832                 ftdm_mutex_lock(ftdmchan->mutex);
 833 
 834                 SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx UCIC\n", sngss7_info->circuit->cic);
 835 
 836                 /* clear up any pending state changes */
 837                 while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 838                         ftdm_sangoma_ss7_process_state_change (ftdmchan);
 839                 }
 840 
 841                 /* throw the ckt block flag */
 842                 sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
 843 
 844                 /* set the channel to suspended state */
 845                 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
 846 
 847                 /* unlock the channel again before we exit */
 848                 ftdm_mutex_unlock(ftdmchan->mutex);
 849         }
 850 
 851         /* clear out the ucic data since we're done with it */
 852         memset(&sngss7_span->ucic, 0x0, sizeof(sngss7_group_data_t));
 853 
 854         return FTDM_SUCCESS;
 855 }
 856 
 857 /******************************************************************************/
 858 ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info)
 859 {
 860         /* clear all the flags related to an incoming GRS */
 861         sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX);
 862         sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX_DN);
 863         sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
 864 
 865         return FTDM_SUCCESS;
 866 }
 867 
 868 /******************************************************************************/
 869 ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info)
 870 {
 871         ftdm_channel_t          *ftdmchan = sngss7_info->ftdmchan;
 872         sngss7_span_data_t      *sngss7_span = ftdmchan->span->signal_data;
 873 
 874         /* clear the rx_grs data fields */
 875         memset(&sngss7_span->rx_grs, 0x0, sizeof(sngss7_group_data_t));
 876 
 877         return FTDM_SUCCESS;
 878 }
 879 
 880 /******************************************************************************/
 881 ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info)
 882 {
 883         ftdm_channel_t          *ftdmchan = sngss7_info->ftdmchan;
 884         sngss7_span_data_t      *sngss7_span = ftdmchan->span->signal_data;
 885 
 886         /* clear the rx_grs data fields */
 887         memset(&sngss7_span->rx_gra, 0x0, sizeof(sngss7_group_data_t));
 888 
 889         return FTDM_SUCCESS;
 890 }
 891 /******************************************************************************/
 892 ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info)
 893 {
 894         /* clear all the flags related to an outgoing GRS */
 895         sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_BASE);
 896         sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_TX);
 897         sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_SENT);
 898         sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
 899 
 900         return FTDM_SUCCESS;
 901 }
 902 
 903 /******************************************************************************/
 904 ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info)
 905 {
 906         ftdm_channel_t          *ftdmchan = sngss7_info->ftdmchan;
 907         sngss7_span_data_t      *sngss7_span = ftdmchan->span->signal_data;
 908 
 909         /* clear the rx_grs data fields */
 910         memset(&sngss7_span->tx_grs, 0x0, sizeof(sngss7_group_data_t));
 911 
 912         return FTDM_SUCCESS;
 913 }
 914 
 915 /******************************************************************************/
 916 
 917 /******************************************************************************/
 918 ftdm_status_t clear_rx_rsc_flags(sngss7_chan_data_t *sngss7_info)
 919 {
 920         /* clear all the flags related to an incoming RSC */
 921         sngss7_clear_flag(sngss7_info, FLAG_RESET_RX);
 922 
 923         return FTDM_SUCCESS;
 924 }
 925 
 926 /******************************************************************************/
 927 ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info)
 928 {
 929         /* clear all the flags related to an outgoing RSC */
 930         sngss7_clear_flag(sngss7_info, FLAG_RESET_TX);
 931         sngss7_clear_flag(sngss7_info, FLAG_RESET_SENT);
 932         sngss7_clear_flag(sngss7_info, FLAG_RESET_TX_RSP);
 933 
 934         return FTDM_SUCCESS;
 935 }
 936 
 937 /******************************************************************************/
 938 ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type)
 939 {
 940         /* Q931 4.5.9 
 941          * 8    7       6       5       4       3       2       1       (octet)
 942          *
 943          * 0    1       1       1       0       0       0       1       (spare 8) ( IE id 1-7)
 944          * X    X       X       X       X       X       X       X       (length of IE contents)
 945          * 1    0       0       0       Z       0       0       0       (ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3)
 946          * X    X       X       X       X       X       X       X       (sub address encoded in ia5)
 947          */
 948 
 949         int     x = 0;
 950         int p = 0;
 951         int len = 0;
 952         char tmp[2];
 953 
 954         /* initalize the second element of tmp to \0 so that atoi doesn't go to far */
 955         tmp[1]='\0';
 956 
 957         /* set octet 1 aka IE id */
 958         p = 0;
 959         switch(type) {
 960         /**************************************************************************/
 961         case SNG_CALLED:                                                /* called party sub address */
 962                 subAddrIE[p] = 0x71;
 963                 break;
 964         /**************************************************************************/
 965         case SNG_CALLING:                                               /* calling party sub address */
 966                 subAddrIE[p] = 0x6d;
 967                 break;
 968         /**************************************************************************/
 969         default:                                                                /* not good */
 970                 SS7_ERROR("Sub-Address type is invalid: %d\n", type);
 971                 return FTDM_FAIL;
 972                 break;
 973         /**************************************************************************/
 974         } /* switch(type) */
 975 
 976         /* set octet 3 aka type and o/e */
 977         p = 2;
 978         subAddrIE[p] = 0x80;
 979 
 980         /* set the subAddrIE pointer octet 4 */
 981         p = 3;
 982 
 983         /* loop through all digits in subAddr and insert them into subAddrIE */
 984         while (subAddr[x] != '\0') {
 985 
 986                 /* grab a character */
 987                 tmp[0] = subAddr[x];
 988 
 989                 /* confirm it is a digit */
 990                 if (!isdigit(tmp[0])) {
 991                         SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
 992                         /* move to the next character in subAddr */
 993                         x++;
 994 
 995                         /* restart the loop */
 996                         continue;
 997                 }
 998 
 999                 /* convert the character to IA5 encoding and write into subAddrIE */
1000                 subAddrIE[p] = atoi(&tmp[0]);   /* lower nibble is the digit */
1001                 subAddrIE[p] |= 0x3 << 4;               /* upper nibble is 0x3 */
1002 
1003                 /* increment address length counter */
1004                 len++;
1005 
1006                 /* increment the subAddrIE pointer */
1007                 p++;
1008 
1009                 /* move to the next character in subAddr */
1010                 x++;
1011 
1012         } /* while (subAddr[x] != '\0') */
1013 
1014         /* set octet 2 aka length of subaddr */
1015         p = 1;
1016         subAddrIE[p] = len + 1;
1017 
1018 
1019         return FTDM_SUCCESS;
1020 }
1021 
1022 /******************************************************************************/
1023 ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type)
1024 {
1025         /* Q931 4.5.9 
1026          * 8    7       6       5       4       3       2       1       (octet)
1027          *
1028          * 0    1       1       1       0       0       0       1       (spare 8) ( IE id 1-7)
1029          * X    X       X       X       X       X       X       X       (length of IE contents)
1030          * 1    0       0       0       Z       0       0       0       (ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3)
1031          * X    X       X       X       X       X       X       X       (sub address encoded in ia5)
1032          */
1033 
1034         int             x = 0;
1035         int     p = 0;
1036         int     len = 0;
1037         char    tmp[2];
1038         int     flag = 0;
1039         int     odd = 0;
1040         uint8_t lower = 0x0;
1041         uint8_t upper = 0x0;
1042 
1043         /* initalize the second element of tmp to \0 so that atoi doesn't go to far */
1044         tmp[1]='\0';
1045 
1046         /* set octet 1 aka IE id */
1047         p = 0;
1048         switch(type) {
1049         /**************************************************************************/
1050         case SNG_CALLED:                                                /* called party sub address */
1051                 subAddrIE[p] = 0x71;
1052                 break;
1053         /**************************************************************************/
1054         case SNG_CALLING:                                               /* calling party sub address */
1055                 subAddrIE[p] = 0x6d;
1056                 break;
1057         /**************************************************************************/
1058         default:                                                                /* not good */
1059                 SS7_ERROR("Sub-Address type is invalid: %d\n", type);
1060                 return FTDM_FAIL;
1061                 break;
1062         /**************************************************************************/
1063         } /* switch(type) */
1064 
1065         /* set the subAddrIE pointer octet 4 */
1066         p = 3;
1067 
1068         /* loop through all digits in subAddr and insert them into subAddrIE */
1069         while (1) {
1070 
1071                 /* grab a character */
1072                 tmp[0] = subAddr[x];
1073 
1074                 /* confirm it is a hex digit */
1075                 while ((!isxdigit(tmp[0])) && (tmp[0] != '\0')) {
1076                         SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
1077                         /* move to the next character in subAddr */
1078                         x++;
1079                         tmp[0] = subAddr[x];
1080                 }
1081 
1082                 /* check if tmp is null or a digit */
1083                 if (tmp[0] != '\0') {
1084                         /* push it into the lower nibble using strtol to allow a-f chars */
1085                         lower = strtol(&tmp[0], (char **)NULL, 16);
1086                         /* move to the next digit */
1087                         x++;
1088                         /* grab a digit from the ftdm digits */
1089                         tmp[0] = subAddr[x];
1090 
1091                         /* check if the digit is a hex digit and that is not null */
1092                         while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
1093                                 SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
1094                                 x++;
1095                                 tmp[0] = subAddr[x];
1096                         } /* while(!(isdigit(tmp))) */
1097 
1098                         /* check if tmp is null or a digit */
1099                         if (tmp[0] != '\0') {
1100                                 /* push the digit into the upper nibble using strtol to allow a-f chars */
1101                                 upper = (strtol(&tmp[0], (char **)NULL, 16)) << 4;
1102                         } else {
1103                                 /* there is no upper ... fill in spare */
1104                                 upper = 0x00;
1105                                 /* throw the odd flag since we need to buffer */
1106                                 odd = 1;
1107                                 /* throw the end flag */
1108                                 flag = 1;
1109                         } /* if (tmp != '\0') */
1110                 } else {
1111                         /* keep the odd flag down */
1112                         odd = 0;
1113 
1114                         /* throw the flag */
1115                         flag = 1;
1116 
1117                         /* bounce out right away */
1118                         break;
1119                 }
1120 
1121                 /* fill in the octet */
1122                 subAddrIE[p] = upper | lower;
1123 
1124                 /* increment address length counter */
1125                 len++;
1126 
1127                 /* if the flag is we're through all the digits */
1128                 if (flag) break;
1129 
1130                 /* increment the subAddrIE pointer */
1131                 p++;
1132 
1133                 /* move to the next character in subAddr */
1134                 x++;
1135 
1136         } /* while (subAddr[x] != '\0') */
1137 
1138         /* set octet 2 aka length of subaddr */
1139         p = 1;
1140         subAddrIE[p] = len + 1;
1141 
1142         /* set octet 3 aka type and o/e */
1143         p = 2;
1144         subAddrIE[p] = 0xa0 | (odd << 3);
1145 
1146 
1147         return FTDM_SUCCESS;
1148 }
1149 
1150 /******************************************************************************/
1151 /* For Emacs:
1152  * Local Variables:
1153  * mode:c
1154  * indent-tabs-mode:t
1155  * tab-width:4
1156  * c-basic-offset:4
1157  * End:
1158  * For VIM:
1159  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
1160  */
1161 /******************************************************************************/

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