]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: merged konrad and david signaling work
authorMoises Silva <moy@sangoma.com>
Tue, 31 Aug 2010 17:29:31 +0000 (13:29 -0400)
committerMoises Silva <moy@sangoma.com>
Tue, 31 Aug 2010 17:29:31 +0000 (13:29 -0400)
27 files changed:
libs/freetdm/Makefile.am
libs/freetdm/configure.ac
libs/freetdm/src/ftdm_call_utils.c [new file with mode: 0644]
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c [new file with mode: 0644]
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_in.c [deleted file]
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c [new file with mode: 0644]
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c [new file with mode: 0644]
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c [new file with mode: 0644]
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c [new file with mode: 0644]
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c [new file with mode: 0644]
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c

index ff5e23beb143b65e8fe1de6d273b30c1318e3b1b..6ccc473ce3fbbf700b41cea06dbc8e63fd1bfa4e 100644 (file)
@@ -41,6 +41,9 @@ INCS +=   -I$(FT_SRCDIR)/$(SRC)/ftmod/ftmod_sangoma_boost
 if SNGSS7
 INCS += -I/usr/include/sng_ss7/
 endif 
+if SNGISDN
+INCS += -I/usr/include/sng_isdn/
+endif 
 
 MY_CFLAGS = $(INCS) $(FTDM_CFLAGS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_CFLAGS@ @DEFS@
 COMPILE   = $(CC) $(MY_CFLAGS) $(INCS)
@@ -70,6 +73,7 @@ $(SRC)/hashtable_itr.c \
 $(SRC)/ftdm_io.c \
 $(SRC)/ftdm_queue.c \
 $(SRC)/ftdm_sched.c \
+$(SRC)/ftdm_call_utils.c \
 $(SRC)/ftdm_config.c \
 $(SRC)/ftdm_callerid.c \
 $(SRC)/fsk.c \
@@ -271,7 +275,11 @@ ftmod_sangoma_ss7_la_SOURCES =  $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7
                                $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c \
                                $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c \
                                $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c \
-                               $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
+                               $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c \
+                               $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c \
+                               $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c \
+                               $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c \
+                               $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c
 ftmod_sangoma_ss7_la_CFLAGS  = $(AM_CFLAGS) $(MY_CFLAGS) -D_GNU_SOURCE
 ftmod_sangoma_ss7_la_LDFLAGS = -module  -avoid-version -lsng_ss7
 ftmod_sangoma_ss7_la_LIBADD  = $(MYLIB)
@@ -285,17 +293,16 @@ ftmod_sangoma_isdn_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_is
                                $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c \
                                $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c \
                                $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c \
-                               $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_in.c \
+                               $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c \
+                               $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c \
                                $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
 
 
-ftmod_sangoma_isdn_la_CFLAGS  = $(AM_CFLAGS) $(MY_CFLAGS)
+ftmod_sangoma_isdn_la_CFLAGS  = $(AM_CFLAGS) $(MY_CFLAGS) -D_GNU_SOURCE
 ftmod_sangoma_isdn_la_LDFLAGS = -module -avoid-version -lsng_isdn
 ftmod_sangoma_isdn_la_LIBADD  = $(MYLIB)
 endif
 
-
-
 if OPENR2
 ftmod_r2_la_SOURCES = $(SRC)/ftmod/ftmod_r2/ftmod_r2.c 
 ftmod_r2_la_CFLAGS  = $(AM_CFLAGS) $(MY_CFLAGS)
index 9ad8c4f6784e3d1cb2787251f02d15349dba4874..a8ed67f228a41955e38145435512af9b11f030eb 100644 (file)
@@ -193,6 +193,18 @@ AM_CONDITIONAL([SNGISDN],[test "${have_sng_isdn}" = "yes"])
 AC_CHECK_LIB([openr2], [openr2_context_set_io_type], [have_openr2="yes"])
 AM_CONDITIONAL([OPENR2],[test "${have_openr2}" = "yes"])
 
+if test "${have_sng_isdn}" = "yes"; then
+       if test "${build}" == "${host}"
+       then
+               case "${host}" in
+               x86_64-*)
+               # X86_64 machines need additional flags when compiling against libsng_isdn
+               CFLAGS="$CFLAGS -DBIT_64 -DALIGN_64BIT"
+               ;;
+               esac
+       fi
+fi
+
 COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS"
 AC_SUBST(COMP_VENDOR_CFLAGS)
 AC_CONFIG_FILES([Makefile
diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c
new file mode 100644 (file)
index 0000000..4d7317a
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2010, Sangoma Technologies
+ * David Yat Sin <dyatsin@sangoma.com>
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * 
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "private/ftdm_core.h"
+#include <ctype.h>
+
+
+FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target)
+{
+       if (!strcasecmp(npi_string, "isdn") || !strcasecmp(npi_string, "e164")) {
+               *target = FTDM_NPI_ISDN;
+       } else if (!strcasecmp(npi_string, "data")) {
+               *target = FTDM_NPI_DATA;
+       } else if (!strcasecmp(npi_string, "telex")) {
+               *target = FTDM_NPI_TELEX;
+       } else if (!strcasecmp(npi_string, "national")) {
+               *target = FTDM_NPI_NATIONAL;
+       } else if (!strcasecmp(npi_string, "private")) {
+               *target = FTDM_NPI_PRIVATE;
+       } else if (!strcasecmp(npi_string, "reserved")) {
+               *target = FTDM_NPI_RESERVED;
+       } else if (!strcasecmp(npi_string, "unknown")) {
+               *target = FTDM_NPI_UNKNOWN;
+       } else {
+               ftdm_log(FTDM_LOG_WARNING, "Invalid NPI value (%s)\n", npi_string);
+               *target = FTDM_NPI_UNKNOWN;
+               return FTDM_FAIL;
+       }
+       return FTDM_SUCCESS;
+}
+
+FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target)
+{
+       if (!strcasecmp(ton_string, "national")) {
+               *target = FTDM_TON_NATIONAL;
+       } else if (!strcasecmp(ton_string, "international")) {
+               *target = FTDM_TON_INTERNATIONAL;
+       } else if (!strcasecmp(ton_string, "local")) {
+               *target = FTDM_TON_SUBSCRIBER_NUMBER;
+       } else if (!strcasecmp(ton_string, "unknown")) {
+               *target = FTDM_TON_UNKNOWN;
+       } else {
+               ftdm_log(FTDM_LOG_WARNING, "Invalid TON value (%s)\n", ton_string);
+               *target = FTDM_TON_UNKNOWN;
+               return FTDM_FAIL;
+       }
+       return FTDM_SUCCESS;
+}
+
+FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number)
+{
+       if (!number) {
+               return FTDM_FAIL;
+       }
+
+       for ( ; *number; number++) {
+               if (!isdigit(*number)) {
+                       return FTDM_FAIL;
+               }
+       }
+       return FTDM_SUCCESS;
+}
+
index 1872d4adab6fa2ee7e2fc5e88953e827d471daac..b47660b0762a20d9fead1979ba42d7e3aaaa809a 100644 (file)
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+
 #include "ftmod_sangoma_isdn.h"
+#define FTDM_DEBUG_CHAN_MEMORY
+
+#ifdef FTDM_DEBUG_CHAN_MEMORY
+#include <sys/mman.h>
+#endif
 
 static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj);
-static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan);
 
 static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span);
 static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span);
 
+ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
+static void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan);
+
+static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan);
+static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
+
 static ftdm_io_interface_t                     g_sngisdn_io_interface;
 static sng_isdn_event_interface_t              g_sngisdn_event_interface;
 
 ftdm_sngisdn_data_t                            g_sngisdn_data;
 
 extern ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
+extern ftdm_status_t sngisdn_check_free_ids(void);
 
 ftdm_state_map_t sangoma_isdn_state_map = {
        {
@@ -66,7 +78,7 @@ ftdm_state_map_t sangoma_isdn_state_map = {
                ZSD_INBOUND,
                ZSM_UNACCEPTABLE,
                {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
-               {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
+               {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
        },
        {
                ZSD_INBOUND,
@@ -80,7 +92,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
                ZSD_INBOUND,
                ZSM_UNACCEPTABLE,
                {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
-               {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
+               {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
+       },
+       {
+               ZSD_INBOUND,
+               ZSM_UNACCEPTABLE,
+               {FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_END},
+               {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
        },
        {
                ZSD_INBOUND,
@@ -135,8 +153,7 @@ ftdm_state_map_t sangoma_isdn_state_map = {
                ZSM_UNACCEPTABLE,
                {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
                {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
-       },
-       /**************************************************************************/
+       },      
        {
                ZSD_OUTBOUND,
                ZSM_UNACCEPTABLE,
@@ -167,7 +184,7 @@ ftdm_state_map_t sangoma_isdn_state_map = {
                ZSD_OUTBOUND,
                ZSM_UNACCEPTABLE,
                {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
-               {FTDM_CHANNEL_STATE_DIALING, FTDM_END}
+               {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
        },
        {
                ZSD_OUTBOUND,
@@ -214,11 +231,22 @@ ftdm_state_map_t sangoma_isdn_state_map = {
        }
 };
 
+static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan)
+{
+       while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+               ftdm_sangoma_isdn_process_state_change(ftdmchan);
+       }
+}
+
 static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
 {
-       ftdm_interrupt_t        *ftdm_sangoma_isdn_int = NULL;
+       ftdm_interrupt_t        *ftdm_sangoma_isdn_int[2];
+       ftdm_status_t           ret_status;
        ftdm_span_t             *span   = (ftdm_span_t *) obj;
        ftdm_channel_t  *ftdmchan = NULL;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
+       sngisdn_event_data_t *sngisdn_event = NULL;
+       int32_t sleep = SNGISDN_EVENT_POLL_RATE;
 
        ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span=%u started.\n", span->span_id);
 
@@ -226,44 +254,55 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
        ftdm_set_flag(span, FTDM_SPAN_IN_THREAD);
 
        /* get an interrupt queue for this span */
-       if (ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_isdn_int) != FTDM_SUCCESS) {
+       if (ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_isdn_int[0]) != FTDM_SUCCESS) {
                ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a ftdm_interrupt for span = %s!\n", span->name);
                goto ftdm_sangoma_isdn_run_exit;
        }
 
-       while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
+       if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) {
+               ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a event interrupt for span = %s!\n", span->name);
+               goto ftdm_sangoma_isdn_run_exit;
+       }
 
+       while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
                /* find out why we returned from the interrupt queue */
-               switch ((ftdm_interrupt_wait(ftdm_sangoma_isdn_int, 100))) {
-               case FTDM_SUCCESS:  /* there was a state change on the span */
-                       /* process all pending state changes */
-                       while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) {
-                               /* double check that this channel has a state change pending */
-                               if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
-                                       ftdm_sangoma_isdn_process_state_change(ftdmchan);
-                               } else {
-                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "reported state change but state change flag not set\n");
+               ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 2, sleep);
+               /* Check if there are any timers to process */
+               ftdm_sched_run(signal_data->sched);
+               switch (ret_status) {
+                       case FTDM_SUCCESS:  /* there was a state change on the span */
+                               /* process all pending state changes */                 
+                               while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) {
+                                       /* double check that this channel has a state change pending */
+                                       ftdm_channel_lock(ftdmchan);
+                                       ftdm_sangoma_isdn_advance_chan_states(ftdmchan);
+                                       ftdm_channel_unlock(ftdmchan);
                                }
-                       }
-
-                       break;
-
-               case FTDM_TIMEOUT:
-                       /* twiddle */
-                       break;
-
-               case FTDM_FAIL:
-                       ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned error!\non span = %s\n", span->name);
-                       break;
 
-               default:
-                       ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned with unknown code on span = %s\n", span->name);
-                       break;
+                               /* Check if there are any timers to process */
+                               while ((sngisdn_event = ftdm_queue_dequeue(signal_data->event_queue))) {
+                                       ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event);
+                                       ftdm_safe_free(sngisdn_event);
+                               }
+                               break;
+                       case FTDM_TIMEOUT:
+                               /* twiddle */
+                               break;
+                       case FTDM_FAIL:
+                               ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned error!\non span = %s\n", span->name);
+                               break;
 
+                       default:
+                               ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned with unknown code on span = %s\n", span->name);
+                               break;
+               }
+               if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) {
+                       if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) {
+                               sleep = SNGISDN_EVENT_POLL_RATE;
+                       }
                }
-
        }
-
+       
        /* clear the IN_THREAD flag so that we know the thread is done */
        ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
 
@@ -281,11 +320,117 @@ ftdm_sangoma_isdn_run_exit:
        return NULL;
 }
 
-/******************************************************************************/
+
+/**
+ * \brief Checks if span has state changes pending and processes
+ * \param span Span where event was fired
+ * \param sngisdn_event Event to handle
+ * \return The locked FTDM channel associated to the event if any, NULL otherwise
+ */
+
+ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event)
+{
+       ftdm_channel_t *ftdmchan = NULL;
+       switch (sngisdn_event->event_id) {
+               /* Events that do not have a channel associated to them */
+               case SNGISDN_EVENT_SRV_IND:
+               case SNGISDN_EVENT_SRV_CFM:
+               case SNGISDN_EVENT_RST_CFM:
+               case SNGISDN_EVENT_RST_IND:
+                       return NULL;
+                       break;
+               case SNGISDN_EVENT_CON_IND:
+               case SNGISDN_EVENT_CON_CFM:
+               case SNGISDN_EVENT_CNST_IND:
+               case SNGISDN_EVENT_DISC_IND:
+               case SNGISDN_EVENT_REL_IND:
+               case SNGISDN_EVENT_DAT_IND:
+               case SNGISDN_EVENT_SSHL_IND:
+               case SNGISDN_EVENT_SSHL_CFM:
+               case SNGISDN_EVENT_RMRT_IND:
+               case SNGISDN_EVENT_RMRT_CFM:
+               case SNGISDN_EVENT_FLC_IND:
+               case SNGISDN_EVENT_FAC_IND:
+               case SNGISDN_EVENT_STA_CFM:
+                       ftdmchan = sngisdn_event->sngisdn_info->ftdmchan;
+                       ftdm_assert_return(ftdmchan, NULL,"Event should have a channel associated\n");
+                       break;
+       }
+       ftdm_channel_lock(ftdmchan);
+       ftdm_sangoma_isdn_advance_chan_states(ftdmchan);
+       return ftdmchan;
+}
+
+
+
+static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event)
+{
+       ftdm_channel_t *ftdmchan = NULL;
+       
+       ftdmchan = ftdm_sangoma_isdn_process_event_states(span, sngisdn_event);
+       switch(sngisdn_event->event_id) {
+               case SNGISDN_EVENT_CON_IND:
+                       sngisdn_process_con_ind(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_CON_CFM:
+                       sngisdn_process_con_cfm(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_CNST_IND:
+                       sngisdn_process_cnst_ind(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_DISC_IND:
+                       sngisdn_process_disc_ind(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_REL_IND:
+                       sngisdn_process_rel_ind(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_DAT_IND:
+                       sngisdn_process_dat_ind(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_SSHL_IND:
+                       sngisdn_process_sshl_ind(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_SSHL_CFM:
+                       sngisdn_process_sshl_cfm(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_RMRT_IND:
+                       sngisdn_process_rmrt_ind(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_RMRT_CFM:
+                       sngisdn_process_rmrt_cfm(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_FLC_IND:
+                       sngisdn_process_flc_ind(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_FAC_IND:
+                       sngisdn_process_fac_ind(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_STA_CFM:
+                       sngisdn_process_sta_cfm(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_SRV_IND:
+                       sngisdn_process_srv_ind(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_SRV_CFM:
+                       sngisdn_process_srv_cfm(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_RST_CFM:
+                       sngisdn_process_rst_cfm(sngisdn_event);
+                       break;
+               case SNGISDN_EVENT_RST_IND:
+                       sngisdn_process_rst_ind(sngisdn_event);
+                       break;
+       }
+       if(ftdmchan != NULL) {
+               ftdm_sangoma_isdn_advance_chan_states(ftdmchan);
+               ftdm_channel_unlock(ftdmchan);
+       }
+}
+
 static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
 {
        ftdm_sigmsg_t           sigev;
-       ftdm_signaling_status_t status;
+       ftdm_channel_state_t initial_state;
        sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
 
        memset(&sigev, 0, sizeof(sigev));
@@ -295,29 +440,33 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
        sigev.channel = ftdmchan;
 
        /*first lock the channel*/
-       ftdm_mutex_lock(ftdmchan->mutex);
-
+       ftdm_channel_lock(ftdmchan);
        /*clear the state change flag...since we might be setting a new state*/
        ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
+#ifdef FTDM_DEBUG_CHAN_MEMORY
+       if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
+               ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ)==0, "Failed to mprotect");
+       }
+#endif
+       
+       /* Only needed for debugging */
+       initial_state = ftdmchan->state;
 
        ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state change to %s\n", ftdm_channel_state2str(ftdmchan->state));
 
        switch (ftdmchan->state) {
-
-       case FTDM_CHANNEL_STATE_COLLECT:         /* SETUP received but wating on digits */
+       case FTDM_CHANNEL_STATE_COLLECT:         /* SETUP received but waiting on digits */
                {
-                       if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request - do nothing\n");
-                               break;
-                       }
-
-                       /* TODO: Overlap receive not implemented yet - cannot do it the same way as PRI requires sending complete bit */
-
-                       /* Go straight to ring state for now */
-
-                       /*now go to the RING state*/
-            ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
+                       /* TODO: Re-implement this. There is a way to re-evaluate new incoming digits from dialplan as they come */
+                       sngisdn_snd_setup_ack(ftdmchan);
+                       /* Just wait in this state until we get enough digits or T302 timeout */
+               }
+               break;
+       case FTDM_CHANNEL_STATE_GET_CALLERID:
+               {
+                       sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
+                       sngisdn_snd_proceed(ftdmchan);
+                       /* Wait in this state until we get FACILITY msg */                      
                }
                break;
        case FTDM_CHANNEL_STATE_RING: /* incoming call request */
@@ -329,34 +478,24 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
                        ftdm_span_send_signal(ftdmchan->span, &sigev);
                }
                break;
-
        case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */
                {
-                       if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n");
-                               break;
-                       }
                        sngisdn_snd_setup(ftdmchan);
                }
                break;
        case FTDM_CHANNEL_STATE_PROGRESS:
                {
-                       if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n");
-                               break;
-                       }
-
                        /*check if the channel is inbound or outbound*/
                        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
                                /*OUTBOUND...so we were told by the line of this so noifiy the user*/
                                sigev.event_id = FTDM_SIGEVENT_PROGRESS;
                                ftdm_span_send_signal(ftdmchan->span, &sigev);
-                       } else {
+                       } else if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
+                               sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
                                sngisdn_snd_proceed(ftdmchan);
                        }
                }
                break;
-
        case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
                {
                        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
@@ -367,86 +506,72 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
                        }
                }
                break; 
-
        case FTDM_CHANNEL_STATE_UP: /* call is answered */
                {
-                       if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n");
-                               break;
-                       }
-
+                       /* check if the channel is inbound or outbound */
                        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+                               /* OUTBOUND ... so we were told by the line that the other side answered */
+                               sigev.event_id = FTDM_SIGEVENT_UP;
+                               ftdm_span_send_signal(ftdmchan->span, &sigev);
+
                                if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
                                        ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
                                        /* Assign the call to a specific equipment */
                                        sngisdn_snd_con_complete(ftdmchan);
                                }
-                       }
-
-                       /* check if the channel is inbound or outbound */
-                       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
-                               /* OUTBOUND ... so we were told by the line that the other side answered */
-                               sigev.event_id = FTDM_SIGEVENT_UP;
-                               ftdm_span_send_signal(ftdmchan->span, &sigev);
                        } else {
                                /* INBOUND ... so FS told us it just answered ... tell the stack */
                                sngisdn_snd_connect(ftdmchan);
                        }
                }
                break;
-
        case FTDM_CHANNEL_STATE_CANCEL:
                {
-                       if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n");
-                               break;
-                       }
-
                        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call before informing user!\n");
 
                        /* Send a release complete */
-                       sngisdn_snd_release(ftdmchan);
+                       sngisdn_snd_release(ftdmchan, 0);
                        /*now go to the HANGUP complete state*/                         
-                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
+                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
                }
                break;
-
        case FTDM_CHANNEL_STATE_TERMINATING: /* call is hung up by the remote end */
                {
-                       if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n");
-                               break;
-                       }
-
                        /* this state is set when the line is hanging up */
                        sigev.event_id = FTDM_SIGEVENT_STOP;
                        ftdm_span_send_signal(ftdmchan->span, &sigev);
                }
                break;
-
        case FTDM_CHANNEL_STATE_HANGUP: /* call is hung up locally */
                {
-                       if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n");
-                               break;
-                       }
-
-                       if (ftdm_test_flag(sngisdn_info, FLAG_REMOTE_REL)) {
+                       if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT)) {
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote abort\n");
+                       } else if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_REL)) {
                                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote hangup\n");
-                               sngisdn_snd_release(ftdmchan);
-                       } else if (ftdm_test_flag(sngisdn_info, FLAG_REMOTE_ABORT)) {
-                               /* Do not send any messages to remote switch as they aborted */
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Clearing local states from remote abort\n");
+                               sngisdn_snd_release(ftdmchan, 0);
+                       } else if (sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) {
+                               /* We aborted this call before sending anything to the stack, so nothing to do anymore */
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Clearing local states from local abort\n");
+                       } else if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) {
+                               /* We are hangup local call because there was a glare, we are waiting for a
+                               RELEASE on this call, before we can process the saved call */
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for RELEASE on hungup glared call\n");
                        } else {
                                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call upon local request!\n");
 
                                 /* set the flag to indicate this hangup is started from the local side */
-                               ftdm_set_flag(sngisdn_info, FLAG_LOCAL_REL);
+                               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
 
                                /* If we never sent ack to incoming call, we need to send release instead of disconnect */
-                               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING) {
-                                       ftdm_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
-                                       sngisdn_snd_release(ftdmchan);
+                               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING ||
+                                       ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALING) {
+
+                                       if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
+                                               sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
+                                       }
+
+                                       sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+                                       sngisdn_snd_release(ftdmchan, 0);
                                } else {
                                        sngisdn_snd_disconnect(ftdmchan);
                                }
@@ -454,361 +579,114 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
                        }
 
                        /* now go to the HANGUP complete state */
-                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
+                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
                }
                break;
-
        case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
                {
-                       if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n");
-                               break;
-                       }
-
-                       if (ftdm_test_flag(sngisdn_info, FLAG_REMOTE_REL)) {                    
-                               if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_TX)) {
-                                       /* go to RESTART State until RSCa is received */
-                                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-                               }
-                               /* Do nothing as we will receive a RELEASE COMPLETE from remote switch */
-                       } else if (ftdm_test_flag(sngisdn_info, FLAG_REMOTE_ABORT) ||
-                                               ftdm_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) {
+                       if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT) ||
+                               sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) {
                                /* If the remote side aborted, we will not get anymore message for this call */
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
                        } else {
-                               /* twiddle, waiting on remote confirmation before moving to down */
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Completing locally requested hangup\n");
+                               /* waiting on remote confirmation before moving to down */
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for release from stack\n");
                        }
                }
                break;
-
        case FTDM_CHANNEL_STATE_DOWN: /* the call is finished and removed */
                {
-                       if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n");
-                               break;
-                       }
-
-                       /* check if there is a reset response that needs to be sent */
-                       if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_RX)) {
-                               /* send a RLC */
-                               sngisdn_snd_release(ftdmchan);
-
-                               /* inform Ftdm that the "sig" is up now for this channel */
-                               status = FTDM_SIG_STATE_UP;
-                               sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-                               sigev.raw_data = &status;
-                               ftdm_span_send_signal(ftdmchan->span, &sigev);
-                       }
+                       uint8_t glare = 0;
 
-                       /* check if we got the reset response */
-                       if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_TX)) {
-                               /* inform Ftdm that the "sig" is up now for this channel */
-                               status = FTDM_SIG_STATE_UP;
-                               sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-                               sigev.raw_data = &status;
-                               ftdm_span_send_signal(ftdmchan->span, &sigev);
-                       }
-
-                       /* check if the circuit has the glare flag up */
-                       if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Glare flag is up....spoofing incoming call\n");
-                               /* clear all the call specific data */
-                               clear_call_data(sngisdn_info);
+                       glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE);
+                       /* clear all of the call specific data store in the channel structure */
+                       clear_call_data(sngisdn_info);
 
+                       /* Close the channel even if we had a glare, we will re-open it when processing state COLLECT for the
+                               "glared call" */
+                       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
+                               ftdm_channel_t *close_chan = ftdmchan;
                                /* close the channel */
-                               if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
-                                       ftdm_channel_t *close_chan = ftdmchan;
-                                       /* close the channel */
-                                       ftdm_channel_close(&close_chan);
-                               }
-
-                               /* spoof an incoming call */
-                               sngisdn_rcv_con_ind(sngisdn_info->glare.suId,
-                                                                       sngisdn_info->glare.suInstId,
-                                                                       sngisdn_info->glare.spInstId,
-                                                                       &sngisdn_info->glare.setup,
-                                                                       sngisdn_info->glare.dChan,
-                                                                       sngisdn_info->glare.ces);
-
-                       } else {
-                               /* clear all of the call specific data store in the channel structure */
-                               clear_call_data(sngisdn_info);
-                       
-                               if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
-                                       ftdm_channel_t *close_chan = ftdmchan;
-                                       /* close the channel */
-                                       ftdm_channel_close(&close_chan);
-                               }
+                               ftdm_channel_close(&close_chan);
+                       }
+                       if (glare) {
+
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Glare detected, processing saved call\n");
+                               /* We are calling sngisdn_rcv_con_ind with ftdmchan->mutex being locked,
+                                       so no other threads will be able to touch this channel. The next time we will
+                                       process this channel is in this function, and it should be in state COLLECT (set inside
+                                       sngisdn_rcv_con_ind)*/
+                               sngisdn_rcv_con_ind(sngisdn_info->glare.suId, sngisdn_info->glare.suInstId, sngisdn_info->glare.spInstId, &sngisdn_info->glare.setup, sngisdn_info->glare.dChan, sngisdn_info->glare.ces);
                        }
                }
                break;
        case FTDM_CHANNEL_STATE_RESTART:
                {
-#if 0
-                       /* TODO: Go through channel restart call states. They do not make sense when running ISDN */
-                       
-                       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
-                               /* bring the call down first...then process the rest of the reset */
-                               switch (ftdmchan->last_state) {
-                               /******************************************************************/
-                               case(FTDM_CHANNEL_STATE_TERMINATING):
-                               case(FTDM_CHANNEL_STATE_HANGUP):
-                               case(FTDM_CHANNEL_STATE_HANGUP_COMPLETE):
-                                       /* go back to the last state after taking care of the rest of the restart state */
-                                       ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-                                       break;
-                               /******************************************************************/
-                               default:
-                                       /* KONRAD: find out what the cause code should be */
-                                       ftdmchan->caller_data.hangup_cause = 41;
-
-                                       /* change the state to terminatting, it will throw us back here
-                                       * once the call is done
-                                       */
-                                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-                                       break;
-                               /******************************************************************/
-                               }
-                       } else {
-
-                               /* check if this an incoming RSC */
-                               if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_RX)) {
-                                       /* go to a down state to clear the channel and send RSCa */
-                                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-                               } /* if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_RX)) */
-                       } /* if (inuse) */
-
-                       /* check if this is an outgoing RSC */
-                       if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_TX)) {
-               
-                               /* make sure we aren't coming from hanging up a call */
-                               if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP_COMPLETE) {
-                                       /* send a reset request */
-                                       sngisdn_snd_reset(ftdmchan);
-                               }
-               
-                               /* don't change to the DOWN state as we need to wait for the RSCa */
-                       } /* if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_TX)) */
-                       
-                       /* send a sig event to the core to disable the channel */
-                       status = FTDM_SIG_STATE_DOWN;
-                       sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-                       sigev.raw_data = &status;
-                       ftdm_span_send_signal(ftdmchan->span, &sigev);
-#endif
+                       /* IMPLEMENT ME */
                }
 
                break;
        case FTDM_CHANNEL_STATE_SUSPENDED:
                {
-                       if (sngisdn_test_flag(sngisdn_info, FLAG_INFID_PAUSED)) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "processing PAUSE\n");
-                               /* bring the channel signaling status to down */
-                               status = FTDM_SIG_STATE_DOWN;
-                               sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-                               sigev.raw_data = &status;
-                               ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-                               /* check the last state and return to it to allow the call to finish */
-                               ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-                       }
-                       if (sngisdn_test_flag(sngisdn_info, FLAG_INFID_RESUME)) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "processing RESUME\n");
-                               
-                               /* we just resumed...throw the channel into reset */
-                               sngisdn_set_flag(sngisdn_info, FLAG_RESET_TX);
-
-                               /* clear the resume flag */
-                               sngisdn_clear_flag(sngisdn_info, FLAG_INFID_RESUME);
-
-                               /* go to restart state */
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-                       }
-
-#if 0
-                       /* CHECK the equivalent for ISDN */
-                       if (sngisdn_test_flag(sngisdn_info, FLAG_CKT_MN_BLOCK_RX)) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "processing MN_BLOCK_RX\n");
-
-                               /* bring the channel signaling status to down */
-                               status = FTDM_SIG_STATE_DOWN;
-                               sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-                               sigev.raw_data = &status;
-                               ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-                               /* send a BLA */
-                               
-                               ft_to_sngss7_bla(ftdmchan);
-
-                               /* check the last state and return to it to allow the call to finish */
-                               ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-                       }
-                       if (sngisdn_test_flag(sngisdn_info, FLAG_CKT_MN_UNBLK_RX)) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "processing MN_UNBLK_RX\n");
-                               /* bring the channel signaling status to up */
-                               status = FTDM_SIG_STATE_UP;
-                               sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-                               sigev.raw_data = &status;
-                               ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-                               /* clear the unblock flag */
-                               sngisdn_clear_flag(sngisdn_info, FLAG_CKT_MN_UNBLK_RX);
-
-                               /* send a uba */
-                               ft_to_sngss7_uba(ftdmchan);
-
-                               /* check the last state and return to it to allow the call to finish */
-                               ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-                       }
-                       /**********************************************************************/
-                       if (sngisdn_test_flag(sngisdn_info, FLAG_CKT_MN_BLOCK_TX)) {
-                               ftdm_log_chan_msg(ftdm_chan, FTDM_LOG_DEBUG, "processing MN_BLOCK_TX\n");
-                               /* bring the channel signaling status to down */
-                               status = FTDM_SIG_STATE_DOWN;
-                               sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-                               sigev.raw_data = &status;
-                               ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-                               /* send a blo */
-                               ft_to_sngss7_blo(ftdmchan);
-
-                               /* check the last state and return to it to allow the call to finish */
-                               ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-                       }
-                       if (sngisdn_test_flag(sngisdn_info, FLAG_CKT_MN_UNBLK_TX)) {
-                               ftdm_log_chan_msg(ftdm_chan, FTDM_LOG_DEBUG, "processing MN_UNBLOCK_TX\n");
-                               /* bring the channel signaling status to up */
-                               status = FTDM_SIG_STATE_UP;
-                               sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-                               sigev.raw_data = &status;
-                               ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-                               /* clear the unblock flag */
-                               sngisdn_clear_flag(sngisdn_info, FLAG_CKT_MN_UNBLK_TX);
-
-                               /* send a ubl */
-                               ft_to_sngss7_ubl(ftdmchan);
-
-                               /* check the last state and return to it to allow the call to finish */
-                               ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-                       }
-#endif
+                       /* IMPLEMENT ME */
                }
                break;
        default:
                {
-                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state));
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state));
                }
                break;
-
        }
-
-       ftdm_mutex_unlock(ftdmchan->mutex);
+       
+       if (ftdmchan->state == initial_state) {
+               ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "state change flag is still set, but we did not change state\n");
+       }
+#ifdef FTDM_DEBUG_CHAN_MEMORY
+       if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
+               ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ|PROT_WRITE)==0, "Failed to mprotect");
+       }
+#endif
+       ftdm_channel_unlock(ftdmchan);
        return;
 }
 
 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
 {
-       sngisdn_chan_data_t  *sngisdn_info;
-       int c;
-
+       sngisdn_chan_data_t  *sngisdn_info = ftdmchan->call_data;
+       ftdm_status_t status = FTDM_FAIL;       
+       
        /* lock the channel while we check whether it is availble */
-       ftdm_mutex_lock(ftdmchan->mutex);
+       ftdm_channel_lock(ftdmchan);
 
        switch (ftdmchan->state) {
 
-       case FTDM_CHANNEL_STATE_DOWN:
-               {
-                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
-
-                       /* unlock the channel */
-                       ftdm_mutex_unlock(ftdmchan->mutex);
-
-                       /* now we have to wait for either the stack to reject the call because of
-                        * glare or for the network to acknowledge the call */
-                       c = 0;
+               case FTDM_CHANNEL_STATE_DOWN:
+                       {
+                               if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) {
+                                       /* A call came in after we called ftdm_channel_open_chan for this call, but before we got here */
+                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected - aborting outgoing call\n");
 
-                       while (c < 100) {
-
-                               /* lock the channel while we check whether it is availble */
-                               ftdm_mutex_lock(ftdmchan->mutex);
-
-                               /* extract the sngisdn_chan_data structure */
-                               sngisdn_info = (sngisdn_chan_data_t  *)ftdmchan->call_data;
-
-                               if (ftdm_test_flag(sngisdn_info, FLAG_GLARE)) {
-                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected\n");
-                                       goto outgoing_glare;
-                               }
+                                       sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+                                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
 
-                               switch (ftdmchan->state) {
-                                       case FTDM_CHANNEL_STATE_DIALING:
-                                               break;
-                                       case FTDM_CHANNEL_STATE_PROGRESS:
-                                       case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
-                                       case FTDM_CHANNEL_STATE_UP:
-                                               {
-                                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Outgoing call request successful\n");
-                                                       goto outgoing_successful;
-                                               }
-                                               break;
-                                       case FTDM_CHANNEL_STATE_TERMINATING:
-                                       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
-                                       case FTDM_CHANNEL_STATE_DOWN:
-                                               {
-                                                       /* Remote switch aborted this call */
-                                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Outgoing call request failed\n");
-                                                       goto outgoing_successful;
-                                               }
-                                               break;
-                                       default:
-                                               {
-                                                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Channel in invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
-                                                       goto outgoing_glare;
-                                               }
-                                               break;
+                                       status = FTDM_BREAK;
+                               } else {
+                                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
+                                       status = FTDM_SUCCESS;
                                }
-
-                               /* unlock the channel */
-                               ftdm_mutex_unlock(ftdmchan->mutex);
-
-                               /* sleep for a bit to let the state change */
-                               ftdm_sleep(10);
-
-                               /* increment the timeout counter */
-                               c++;
                        }
-
-                       /* only way we can get here is if we are still in STATE_DIALING. We did not get a glare, so exit thread and wait for PROCEED/PROGRESS/ALERT/CONNECT or RELEASE from remote switch  */
-                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Timeout waiting for outgoing call to be accepted by network, returning success anyways\n");
-
-                       /* consider the call good .... for now */
-                       goto outgoing_successful;
-               }
-               break;
-
-       default:
+                       break;
+               default:
                {
                        /* the channel is already used...this can't be, end the request */
                        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Outgoing call requested channel in already in use\n");
-                       goto outgoing_glare;
+                       status = FTDM_BREAK;
                }
                break;            
        }
 
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "WE SHOULD NOT BE HERE!!!!\n");
-
-       ftdm_mutex_unlock(ftdmchan->mutex);
-       return FTDM_FAIL;
-
-outgoing_glare:
-       ftdm_mutex_unlock(ftdmchan->mutex);  
-       return FTDM_BREAK;
-
-outgoing_successful:
-       ftdm_mutex_unlock(ftdmchan->mutex);
-       return FTDM_SUCCESS;
+       ftdm_channel_unlock(ftdmchan);
+       return status;
 }
 
 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_sig_status)
@@ -863,8 +741,8 @@ static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
                ftdm_sleep(10);
        }
 
-       /* FIXME: deconfigure any circuits, links, attached to this span */
-       /* TODO: confirm with Moy whether we should start channels at 1 or 0 */
+       /* FIXME: deconfigure any links, attached to this span */
+       /* TODO: Use Moy's channel Iterator when its implemented */
        for (i=1;i<=span->chan_count;i++) {
                ftdm_safe_free(span->channels[i]->call_data);
        }
@@ -906,9 +784,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
        span->start = ftdm_sangoma_isdn_start;
        span->stop = ftdm_sangoma_isdn_stop;
        span->signal_type = FTDM_SIGTYPE_ISDN;
-#if 0
-       span->signal_data = NULL;
-#endif
        span->outgoing_call = ftdm_sangoma_isdn_outgoing_call;
        span->channel_request = NULL;
        span->signal_cb = sig_cb;
@@ -917,6 +792,19 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
        span->state_map = &sangoma_isdn_state_map;
        ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
 
+       if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
+               span->trunk_type == FTDM_TRUNK_BRI) {
+
+               ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE);
+               sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
+       }
+
+       /* Initialize scheduling context */
+       ftdm_assert(ftdm_sched_create(&((sngisdn_span_data_t*)span->signal_data)->sched, "sngisdn_schedule") == FTDM_SUCCESS, "Failed to create a new schedule!!");
+
+       /* Initialize the event queue */
+       ftdm_assert(ftdm_queue_create(&((sngisdn_span_data_t*)span->signal_data)->event_queue, SNGISDN_EVENT_QUEUE_SIZE) == FTDM_SUCCESS, "Failed to create a new queue!!");
+
        ftdm_log(FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_isdn span = %s\n", span->name);
        return FTDM_SUCCESS;
 }
@@ -948,22 +836,22 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
        g_sngisdn_event_interface.cc.sng_rst_ind        = sngisdn_rcv_rst_ind;
        g_sngisdn_event_interface.cc.sng_rst_cfm        = sngisdn_rcv_rst_cfm;
 
-       g_sngisdn_event_interface.lg.sng_log                    = sngisdn_rcv_sng_log;
+       g_sngisdn_event_interface.lg.sng_log            = sngisdn_rcv_sng_log;
+       g_sngisdn_event_interface.lg.sng_assert         = sngisdn_rcv_sng_assert;
+       
        g_sngisdn_event_interface.sta.sng_phy_sta_ind   = sngisdn_rcv_phy_ind;
        g_sngisdn_event_interface.sta.sng_q921_sta_ind  = sngisdn_rcv_q921_ind;
        g_sngisdn_event_interface.sta.sng_q921_trc_ind  = sngisdn_rcv_q921_trace;
        g_sngisdn_event_interface.sta.sng_q931_sta_ind  = sngisdn_rcv_q931_ind;
        g_sngisdn_event_interface.sta.sng_q931_trc_ind  = sngisdn_rcv_q931_trace;
-       g_sngisdn_event_interface.sta.sng_cc_sta_ind    = sngisdn_rcv_cc_ind;
+       g_sngisdn_event_interface.sta.sng_cc_sta_ind    = sngisdn_rcv_cc_ind;   
 
        for(i=1;i<=MAX_VARIANTS;i++) {          
-               ftdm_mutex_create(&g_sngisdn_data.ccs[i].request_mutex);
+               ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex);
        }
+
        /* initalize sng_isdn library */
        sng_isdn_init(&g_sngisdn_event_interface);
-
-       /* crash on assert fail */
-       ftdm_global_set_crash_policy(FTDM_CRASH_ON_ASSERT);
        return FTDM_SUCCESS;
 }
 
@@ -975,7 +863,7 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_isdn_unload)
        sng_isdn_free();
        
        for(i=1;i<=MAX_VARIANTS;i++) {          
-               ftdm_mutex_destroy(&g_sngisdn_data.ccs[i].request_mutex);
+               ftdm_mutex_destroy(&g_sngisdn_data.ccs[i].mutex);
        }
 
        ftdm_log(FTDM_LOG_INFO, "Finished ftmod_sangoma_isdn unload!\n");
@@ -1026,6 +914,23 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
                        stream->write_function(stream, "-ERR invalid trace option <q921|q931> <span name>\n");
                }       
        }
+       if (!strcasecmp(argv[0], "l1_stats")) {
+               ftdm_span_t *span;
+               if (argc < 2) {
+                       ftdm_log(FTDM_LOG_ERROR, "Usage: ftdm sangoma_isdn l1_stats <span name>\n");
+                       status = FTDM_FAIL;
+                       goto done;
+               }
+               status = ftdm_span_find_by_name(argv[1], &span);
+               if (FTDM_SUCCESS != status) {
+                       stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]);
+                       goto done;
+               }
+               /* TODO: implement PHY stats */
+       }
+       if (!strcasecmp(argv[0], "check_ids")) {
+               sngisdn_check_free_ids();
+       }
 done:
        ftdm_safe_free(mycmd);
        return status;
index d3877defd308c46520a6e023d43ac3c960e0dddb..932db0e89e76c2c321dde42618bf52115439ad9e 100644 (file)
 
 #include <sng_isdn.h>
 
-#define MAX_SPANS_PER_NFAS_LINK          8 /* TODO: Confirm this value */
-#define NUM_E1_CHANNELS_PER_SPAN 32
-#define NUM_T1_CHANNELS_PER_SPAN 24
-#define NUM_BRI_CHANNELS_PER_SPAN 2
-
-/* Should never have DEBUG_MODE defined when used in production */
-#if 0
-#undef DEBUG_MODE
-#define FORCE_SEFGAULT
-#else
-#define DEBUG_MODE
-#define FORCE_SEGFAULT *(int *) 0 = 0;
-#endif
+/* Theoretical limit for MAX_SPANS_PER_NFAS_LINK is 31,
+   but set to 8 for now to save some memor */
+
+#define MAX_SPANS_PER_NFAS_LINK                8 
+#define NUM_E1_CHANNELS_PER_SPAN       32
+#define NUM_T1_CHANNELS_PER_SPAN       24
+#define NUM_BRI_CHANNELS_PER_SPAN      2
+#define SNGISDN_EVENT_QUEUE_SIZE       100
+#define SNGISDN_EVENT_POLL_RATE                100
 
 /* TODO: rename all *_cc_* to *_an_*  */
 
+typedef enum {
+       FLAG_RESET_RX           = (1 << 0),
+       FLAG_RESET_TX           = (1 << 1),
+       FLAG_REMOTE_REL         = (1 << 2),
+       FLAG_LOCAL_REL          = (1 << 3),
+       FLAG_REMOTE_ABORT       = (1 << 4),
+       FLAG_LOCAL_ABORT        = (1 << 5),
+       FLAG_GLARE              = (1 << 6),
+       FLAG_DELAYED_REL        = (1 << 7),
+       FLAG_SENT_PROCEED       = (1 << 8),
+} sngisdn_flag_t;
+
+
+typedef enum {
+       SNGISDN_SWITCH_INVALID = 0,     /* invalid */
+       SNGISDN_SWITCH_NI2 ,    /* national isdn-2 */
+       SNGISDN_SWITCH_5ESS,    /* att 5ess */
+       SNGISDN_SWITCH_4ESS,    /* att 4ess */
+       SNGISDN_SWITCH_DMS100,  /* nt dms100 */
+       SNGISDN_SWITCH_EUROISDN,/* etsi */
+       SNGISDN_SWITCH_QSIG,    /* etsi qsig */
+       SNGISDN_SWITCH_INSNET,  /* int - net */
+} sngisdn_switchtype_t;
+
+typedef enum {
+       SNGISDN_SIGNALING_INVALID = 0,          /* invalid */
+       SNGISDN_SIGNALING_CPE ,                         /* customer side emulation */
+       SNGISDN_SIGNALING_NET,                          /* network side emulation */
+} sngisdn_signalingtype_t;
+
+typedef enum {
+       SNGISDN_TRACE_DISABLE = 0,
+       SNGISDN_TRACE_Q921 = 1,
+       SNGISDN_TRACE_Q931 = 2,
+} sngisdn_tracetype_t;
+
+typedef enum {
+       SNGISDN_OPT_DEFAULT = 0,
+       SNGISDN_OPT_TRUE = 1,
+       SNGISDN_OPT_FALSE = 2,
+} sngisdn_opt_t;
+
+
+typedef enum {
+       SNGISDN_AVAIL_DOWN = 1,
+       SNGISDN_AVAIL_PWR_SAVING = 5,
+       SNGISDN_AVAIL_UP = 10,
+} sngisdn_avail_t;
+
+typedef enum {
+       SNGISDN_EVENT_CON_IND = 1,
+       SNGISDN_EVENT_CON_CFM,
+       SNGISDN_EVENT_CNST_IND,
+       SNGISDN_EVENT_DISC_IND,
+       SNGISDN_EVENT_REL_IND,
+       SNGISDN_EVENT_DAT_IND,
+       SNGISDN_EVENT_SSHL_IND,
+       SNGISDN_EVENT_SSHL_CFM,
+       SNGISDN_EVENT_RMRT_IND,
+       SNGISDN_EVENT_RMRT_CFM,
+       SNGISDN_EVENT_FLC_IND,
+       SNGISDN_EVENT_FAC_IND,
+       SNGISDN_EVENT_STA_CFM,
+       SNGISDN_EVENT_SRV_IND,
+       SNGISDN_EVENT_SRV_CFM,
+       SNGISDN_EVENT_RST_CFM,
+       SNGISDN_EVENT_RST_IND,
+} ftdm_sngisdn_event_id_t;
+
 typedef struct sngisdn_glare_data {
        int16_t         suId;
     uint32_t   suInstId;
@@ -76,7 +141,7 @@ typedef struct sngisdn_glare_data {
 typedef struct sngisdn_chan_data {
     ftdm_channel_t                     *ftdmchan;
     uint32_t                           flags;
-       uint8_t                                 ces;            /* not used for now */
+       uint8_t                                 ces;            /* used only for BRI, otherwise always 0 */
        uint8_t                                 dchan_id;
        uint32_t                                suInstId;       /* instance ID generated locally */
        uint32_t                                spInstId;       /* instance ID generated by stack */
@@ -88,17 +153,54 @@ typedef struct sngisdn_chan_data {
 /* Span specific data */
 typedef struct sngisdn_span_data {
        ftdm_span_t     *ftdm_span;
-       uint8_t         link_id;
-       uint8_t         switchtype;
-       uint8_t         signalling;                     /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
-       uint8_t         cc_id;
-       uint8_t         dchan_id;
-       uint8_t         span_id;
-       uint8_t         tei;
-       uint8_t         keep_link_up;
-       uint8_t         trace_flags;
+       uint8_t                 link_id;
+       uint8_t                 switchtype;
+       uint8_t                 signalling;                     /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
+       uint8_t                 cc_id;
+       uint8_t                 dchan_id;
+       uint8_t                 span_id;
+       uint8_t                 tei;
+       uint8_t                 min_digits;
+       uint8_t                 trace_flags;            /* TODO: change to flags, so we can use ftdm_test_flag etc.. */
+       uint8_t                 overlap_dial;
+       uint8_t                 setup_arb;
+       uint8_t                 facility;
+       ftdm_sched_t    *sched;
+       ftdm_queue_t    *event_queue;
 } sngisdn_span_data_t;
 
+typedef struct sngisdn_event_data {
+       
+       int16_t         suId;
+       int16_t         dChan;
+       uint32_t        suInstId;
+       uint32_t        spInstId;
+       uint8_t         ces;
+       uint8_t         action;
+       uint8_t         evntType;
+
+       sngisdn_chan_data_t *sngisdn_info;
+       sngisdn_span_data_t *signal_data;       
+       
+       ftdm_sngisdn_event_id_t event_id;
+       
+       union
+       {
+               ConEvnt         conEvnt;
+               CnStEvnt        cnStEvnt;
+               DiscEvnt        discEvnt;
+               RelEvnt         relEvnt;
+               InfoEvnt        infoEvnt;
+               SsHlEvnt        ssHlEvnt;
+               RmRtEvnt        rmRtEvnt;
+               StaEvnt         staEvnt;
+               FacEvnt         facEvnt;
+               Srv                     srvEvnt;
+               Rst                     rstEvnt;
+       }event;
+       
+} sngisdn_event_data_t;
+
 /* dchan_data can have more than 1 span when running NFAS */
 typedef struct sngisdn_dchan_data {
        uint8_t                         num_spans;
@@ -119,8 +221,8 @@ typedef struct sngisdn_cc {
        uint8_t                         activation_done;
        uint8_t                         switchtype;
        ftdm_trunk_type_t       trunktype;
-       uint32_t                        last_suInstId;
-       ftdm_mutex_t            *request_mutex;
+       uint32_t                        last_suInstId;  
+       ftdm_mutex_t            *mutex;
        sngisdn_chan_data_t     *active_spInstIds[MAX_INSTID];
        sngisdn_chan_data_t     *active_suInstIds[MAX_INSTID];
 }sngisdn_cc_t;
@@ -131,113 +233,83 @@ typedef struct ftdm_sngisdn_data {
        uint8_t num_cc;                                         /* 1 ent per switchtype */
        struct sngisdn_cc ccs[MAX_VARIANTS+1];
        uint8_t num_dchan;
-       sngisdn_dchan_data_t dchans[MAX_L1_LINKS+1];
+       sngisdn_dchan_data_t dchans[MAX_L1_LINKS+1];    
 }ftdm_sngisdn_data_t;
 
-typedef enum {
-       FLAG_RESET_RX           = (1 << 0),
-       FLAG_RESET_TX           = (1 << 1),
-       FLAG_REMOTE_REL         = (1 << 2),
-       FLAG_LOCAL_REL          = (1 << 3),
-       FLAG_REMOTE_ABORT       = (1 << 4),
-       FLAG_LOCAL_ABORT       = (1 << 4),
-       FLAG_GLARE              = (1 << 5),
-       FLAG_INFID_RESUME       = (1 << 17),
-       FLAG_INFID_PAUSED       = (1 << 18),
-       FLAG_CKT_MN_BLOCK_RX    = (1 << 19),
-       FLAG_CKT_MN_BLOCK_TX    = (1 << 20),
-       FLAG_CKT_MN_UNBLK_RX    = (1 << 21),
-       FLAG_CKT_MN_UNBLK_TX    = (1 << 22),
-       FLAG_GRP_HW_BLOCK_RX    = (1 << 23),
-       FLAG_GRP_HW_BLOCK_TX    = (1 << 24),
-       FLAG_GRP_MN_BLOCK_RX    = (1 << 25),
-       FLAG_GRP_MN_BLOCK_TX    = (1 << 28),
-       FLAG_GRP_HW_UNBLK_RX    = (1 << 27),
-       FLAG_GRP_HW_UNBLK_TX    = (1 << 28),
-       FLAG_GRP_MN_UNBLK_RX    = (1 << 29),
-       FLAG_GRP_MN_UNBLK_TX    = (1 << 30)
-} sngisdn_flag_t;
-
-
-typedef enum {
-       SNGISDN_SWITCH_INVALID = 0,     /* invalid */
-       SNGISDN_SWITCH_NI2 ,    /* national isdn-2 */
-       SNGISDN_SWITCH_5ESS,    /* att 5ess */
-       SNGISDN_SWITCH_4ESS,    /* att 4ess */
-       SNGISDN_SWITCH_DMS100,  /* nt dms100 */
-       SNGISDN_SWITCH_EUROISDN,/* etsi */
-       SNGISDN_SWITCH_QSIG,    /* etsi qsig */
-       SNGISDN_SWITCH_INSNET,  /* int - net */
-} sngisdn_switchtype_t;
-
-typedef enum {
-       SNGISDN_SIGNALING_INVALID = 0,          /* invalid */
-       SNGISDN_SIGNALING_CPE ,                         /* customer side emulation */
-       SNGISDN_SIGNALING_NET,                          /* network side emulation */
-} sngisdn_signalingtype_t;
-
-typedef enum {
-       SNGISDN_TRACE_DISABLE = 0,
-       SNGISDN_TRACE_Q921 = 1,
-       SNGISDN_TRACE_Q931 = 2,
-} sngisdn_tracetype_t;
-
-
-#define sngisdn_set_flag(obj, flag)   ((obj)->flags |= (flag))
-#define sngisdn_clear_flag(obj, flag) ((obj)->flags &= ~(flag))
-#define sngisdn_test_flag(obj, flag)  ((obj)->flags & flag)
-
-#define sngisdn_set_trace_flag(obj, flag)   ((obj)->trace_flags |= (flag))
-#define sngisdn_clear_trace_flag(obj, flag) ((obj)->trace_flags &= ~(flag))
-#define sngisdn_test_trace_flag(obj, flag)  ((obj)->trace_flags & flag)
 
 /* TODO implement these 2 functions */
 #define ISDN_FUNC_TRACE_ENTER(a)
 #define ISDN_FUNC_TRACE_EXIT(a)
 
+/* Global Structs */
+extern ftdm_sngisdn_data_t     g_sngisdn_data;
+
 /* Configuration functions */
 ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span);
 
 /* Support functions */
 uint32_t get_unique_suInstId(uint8_t cc_id);
 void clear_call_data(sngisdn_chan_data_t *sngisdn_info);
+void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info);
+
+
 void stack_hdr_init(Header *hdr);
 void stack_pst_init(Pst *pst);
 ftdm_status_t get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
 ftdm_status_t get_ftdmchan_by_suInstId(uint8_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
-
-ftdm_status_t check_for_state_change(ftdm_channel_t *ftdmchan);
+ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *ftdmspan, sngisdn_avail_t avail);
 
 /* Outbound Call Control functions */
 void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_progress(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_alert(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_release(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
 void sngisdn_snd_reset(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
 
 /* Inbound Call Control functions */
-void sngisdn_rcv_con_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, signed short dChan, uint8_t ces);
-void sngisdn_rcv_con_cfm (signed short suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, signed short dChan, uint8_t ces);
-void sngisdn_rcv_cnst_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, signed short dChan, uint8_t ces);
-void sngisdn_rcv_disc_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt);
-void sngisdn_rcv_rel_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt);
-void sngisdn_rcv_dat_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt);
-void sngisdn_rcv_sshl_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
-void sngisdn_rcv_sshl_cfm (signed short suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
-void sngisdn_rcv_rmrt_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
-void sngisdn_rcv_rmrt_cfm (signed short suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
-void sngisdn_rcv_flc_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
-void sngisdn_rcv_fac_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, signed short dChan, uint8_t ces);
-void sngisdn_rcv_sta_cfm ( signed short suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
-void sngisdn_rcv_srv_ind ( signed short suId, Srv *srvEvnt, signed short dChan, uint8_t ces);
-void sngisdn_rcv_srv_cfm ( signed short suId, Srv *srvEvnt, signed short dChan, uint8_t ces);
-void sngisdn_rcv_rst_cfm ( signed short suId, Rst *rstEvnt, signed short dChan, uint8_t ces, uint8_t evtType);
-void sngisdn_rcv_rst_ind ( signed short suId, Rst *rstEvnt, signed short dChan, uint8_t ces, uint8_t evtType);
-
+void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt);
+void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt);
+void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt);
+void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
+void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
+void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
+void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
+void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
+void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_sta_cfm ( int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
+void sngisdn_rcv_srv_ind ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_srv_cfm ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
+void sngisdn_rcv_rst_cfm ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
+void sngisdn_rcv_rst_ind ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
+
+void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_dat_ind (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_sshl_ind (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_sshl_cfm (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_rmrt_ind (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_rmrt_cfm (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_flc_ind (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event);
+
+void sngisdn_process_srv_ind (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event);
+void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event);
 
 void sngisdn_rcv_phy_ind(SuId suId, Reason reason);
 void sngisdn_rcv_q921_ind(BdMngmt *status);
@@ -246,14 +318,38 @@ void sngisdn_rcv_q931_ind(InMngmt *status);
 void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf);
 void sngisdn_rcv_cc_ind(CcMngmt *status);
 void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...);
+void sngisdn_rcv_sng_assert(char *message);
+
+static __inline__ uint32_t sngisdn_test_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag)
+{
+       return (uint32_t) sngisdn_info->flags & flag;
+}
+static __inline__ void sngisdn_clear_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag)
+{
+       sngisdn_info->flags &= ~flag;
+}
+
+static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag)
+{
+       sngisdn_info->flags |= flag;
+}
+
+#define sngisdn_set_trace_flag(obj, flag)   ((obj)->trace_flags |= (flag))
+#define sngisdn_clear_trace_flag(obj, flag) ((obj)->trace_flags &= ~(flag))
+#define sngisdn_test_trace_flag(obj, flag)  ((obj)->trace_flags & flag)
+
 
 void handle_sng_log(uint8_t level, char *fmt,...);
 void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
+void sngisdn_delayed_release(void* p_sngisdn_info);
+void sngisdn_delayed_connect(void* p_sngisdn_info);
+void sngisdn_delayed_disconnect(void* p_sngisdn_info);
 
 /* Stack management functions */
 ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span);
 ftdm_status_t sng_isdn_stack_activate(ftdm_span_t *span);
 
 
+
 #endif /* __FTMOD_SNG_ISDN_H__ */
 
index d0254fd7145853d2f02e893fd7577dbafaa20745..6124070cad1c848e98e6fee6df452b91eaa01929 100644 (file)
@@ -47,7 +47,8 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
        switch(span->trunk_type) {
                case FTDM_TRUNK_T1:
-                       if (!strcasecmp(switch_name, "ni2")) {
+                       if (!strcasecmp(switch_name, "ni2") ||
+                               !strcasecmp(switch_name, "national")) {
                                signal_data->switchtype = SNGISDN_SWITCH_NI2;
                        } else if (!strcasecmp(switch_name, "5ess")) {
                                signal_data->switchtype = SNGISDN_SWITCH_5ESS;
@@ -127,6 +128,7 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
                dchan_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data;
                dchan_data->num_chans++;
        }
+
        return FTDM_SUCCESS;
 }
 
@@ -144,7 +146,7 @@ ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span)
 
                signal_data->signalling = SNGISDN_SIGNALING_CPE;
        } else {
-               ftdm_log(FTDM_LOG_ERROR, "Unsupported signalling %s\n", signalling);
+               ftdm_log(FTDM_LOG_ERROR, "Unsupported signalling/interface %s\n", signalling);
                return FTDM_FAIL;
        }
        return FTDM_SUCCESS;
@@ -156,10 +158,29 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
        const char *var, *val;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
        /* Set defaults here */
-       signal_data->keep_link_up = 1;
        signal_data->tei = 0;
-       
-       
+       signal_data->min_digits = 8;
+       signal_data->overlap_dial = SNGISDN_OPT_DEFAULT;
+       signal_data->setup_arb = SNGISDN_OPT_DEFAULT;
+
+       if (span->trunk_type == FTDM_TRUNK_BRI ||
+               span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
+
+               ftdm_span_set_npi("unknown", &span->default_caller_data.dnis.plan);
+               ftdm_span_set_ton("unknown", &span->default_caller_data.dnis.type);
+               ftdm_span_set_npi("unknown", &span->default_caller_data.cid_num.plan);
+               ftdm_span_set_ton("unknown", &span->default_caller_data.cid_num.type);
+               ftdm_span_set_npi("unknown", &span->default_caller_data.rdnis.plan);
+               ftdm_span_set_ton("unknown", &span->default_caller_data.rdnis.type);
+       } else {
+               ftdm_span_set_npi("e164", &span->default_caller_data.dnis.plan);
+               ftdm_span_set_ton("national", &span->default_caller_data.dnis.type);
+               ftdm_span_set_npi("e164", &span->default_caller_data.cid_num.plan);
+               ftdm_span_set_ton("national", &span->default_caller_data.cid_num.type);
+               ftdm_span_set_npi("e164", &span->default_caller_data.rdnis.plan);
+               ftdm_span_set_ton("national", &span->default_caller_data.rdnis.type);
+       }
+
        for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) {
                ftdm_log(FTDM_LOG_DEBUG, "Sangoma ISDN key=value, %s=%s\n", ftdm_parameters[paramindex].var, ftdm_parameters[paramindex].val);
                var = ftdm_parameters[paramindex].var;
@@ -169,7 +190,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
                        if (parse_switchtype(val, span) != FTDM_SUCCESS) {
                                return FTDM_FAIL;
                        }
-               } else if (!strcasecmp(var, "signalling")) {
+               } else if (!strcasecmp(var, "signalling") ||
+                                  !strcasecmp(var, "interface")) {
                        if (parse_signalling(val, span) != FTDM_SUCCESS) {
                                return FTDM_FAIL;
                        }
@@ -180,15 +202,44 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
                                return FTDM_FAIL;
                        }
                        signal_data->tei = tei;
-               } else if (!strcasecmp(var, "keep_link_up")) {
+               } else if (!strcasecmp(var, "overlap")) {
                        if (!strcasecmp(val, "yes")) {
-                               signal_data->keep_link_up = 1;
+                               signal_data->overlap_dial = SNGISDN_OPT_TRUE;
                        } else if (!strcasecmp(val, "no")) {
-                               signal_data->keep_link_up = 0;
+                               signal_data->overlap_dial = SNGISDN_OPT_FALSE;
                        } else {
-                               ftdm_log(FTDM_LOG_ERROR, "Invalid keep_link_up value, valid values are (yes/no)");
-                               return FTDM_FAIL;
+                               ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
+                       }
+               } else if (!strcasecmp(var, "setup arbitration")) {
+                       if (!strcasecmp(val, "yes")) {
+                               signal_data->setup_arb = SNGISDN_OPT_TRUE;
+                       } else if (!strcasecmp(val, "no")) {
+                               signal_data->setup_arb = SNGISDN_OPT_FALSE;
+                       } else {
+                               ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
+                       }
+               } else if (!strcasecmp(var, "facility")) {
+                       if (!strcasecmp(val, "yes")) {
+                               signal_data->facility = SNGISDN_OPT_TRUE;
+                       } else if (!strcasecmp(val, "no")) {
+                               signal_data->facility = SNGISDN_OPT_FALSE;
+                       } else {
+                               ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
                        }
+               } else if (!strcasecmp(var, "min_digits")) {
+                       signal_data->min_digits = atoi(val);
+               } else if (!strcasecmp(var, "outbound-called-ton")) {
+                       ftdm_span_set_ton(val, &span->default_caller_data.dnis.type);
+               } else if (!strcasecmp(var, "outbound-called-npi")) {
+                       ftdm_span_set_npi(val, &span->default_caller_data.dnis.plan);
+               } else if (!strcasecmp(var, "outbound-calling-ton")) {
+                       ftdm_span_set_ton(val, &span->default_caller_data.cid_num.type);
+               } else if (!strcasecmp(var, "outbound-calling-npi")) {
+                       ftdm_span_set_npi(val, &span->default_caller_data.cid_num.plan);
+               } else if (!strcasecmp(var, "outbound-rdnis-ton")) {
+                       ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type);
+               } else if (!strcasecmp(var, "outbound-rdnis-npi")) {
+                       ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan);
                } else {
                        ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
                }
index c44228d033c1e0485885db136b6ea7f7aab69a2a..f84e018f1e1d33620542bc77cb7f804f1c4348a2 100644 (file)
@@ -223,17 +223,17 @@ ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span)
        switch(span->trunk_type) {
                case FTDM_TRUNK_E1:
                        cfg.t.cfg.s.l1PSAP.chan = 16;
-                       cfg.t.cfg.s.l1PSAP.type = SNG_LINKTYPE_PRI;
+                       cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI;
                        break;
                case FTDM_TRUNK_T1:
                case FTDM_TRUNK_J1:
                        cfg.t.cfg.s.l1PSAP.chan = 24;
-                       cfg.t.cfg.s.l1PSAP.type = SNG_LINKTYPE_PRI;
+                       cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI;
                        break;
                case FTDM_TRUNK_BRI:
                case FTDM_TRUNK_BRI_PTMP:
                        cfg.t.cfg.s.l1PSAP.chan = 3;
-                       cfg.t.cfg.s.l1PSAP.type = SNG_LINKTYPE_BRI;
+                       cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_BRI;
                        break;
                default:
                        ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunk type %d\n", span->name, span->trunk_type);
@@ -280,10 +280,10 @@ ftdm_status_t sng_isdn_stack_cfg_q921_gen(void)
        cfg.t.cfg.s.bdGen.nmbASPLnks = MAX_L1_LINKS+1;
 
 #ifdef LAPD_3_4
-       cfg.t.cfg.s.bdGen.timeRes     = 10;                              /* timer resolution */
+       cfg.t.cfg.s.bdGen.timeRes     = 100;      /* timer resolution = 1 sec */
 #endif
-    cfg.t.cfg.s.bdGen.poolTrUpper   = POOL_UP_TR;        /* upper pool threshold */
-    cfg.t.cfg.s.bdGen.poolTrLower   = POOL_LW_TR;        /* lower pool threshold */
+    cfg.t.cfg.s.bdGen.poolTrUpper   = 2;        /* upper pool threshold */
+    cfg.t.cfg.s.bdGen.poolTrLower   = 1;        /* lower pool threshold */
 
        if (sng_isdn_q921_config(&pst, &cfg)) {
                return FTDM_FAIL;
@@ -315,9 +315,9 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
 
        cfg.t.cfg.s.bdMSAP.lnkNmb      = signal_data->link_id;
        
-       cfg.t.cfg.s.bdMSAP.maxOutsFrms = 2;            /* MAC window */
-       cfg.t.cfg.s.bdMSAP.tQUpperTrs  = 16;           /* Tx Queue Upper Threshold */
-       cfg.t.cfg.s.bdMSAP.tQLowerTrs  = 8;            /* Tx Queue Lower Threshold */   
+       cfg.t.cfg.s.bdMSAP.maxOutsFrms = 24;            /* MAC window */
+       cfg.t.cfg.s.bdMSAP.tQUpperTrs  = 32;           /* Tx Queue Upper Threshold */
+       cfg.t.cfg.s.bdMSAP.tQLowerTrs  = 24;            /* Tx Queue Lower Threshold */
        cfg.t.cfg.s.bdMSAP.selector    = 0;       /* Selector 0 */
        /* TODO: check if bdMSAP parameters can be initialized by calling stack_pst_init */
        cfg.t.cfg.s.bdMSAP.mem.region  = S_REG;       /* Memory region */
@@ -327,8 +327,8 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
        cfg.t.cfg.s.bdMSAP.dstProcId   = SFndProcId(); /* destination proc id */
        cfg.t.cfg.s.bdMSAP.dstEnt      = ENTL1;        /* entity */
        cfg.t.cfg.s.bdMSAP.dstInst     = S_INST;      /* instance */    
-       cfg.t.cfg.s.bdMSAP.t201Tmr     = 5;            /* T201 */
-       cfg.t.cfg.s.bdMSAP.t202Tmr     = 200;          /* T202 */
+       cfg.t.cfg.s.bdMSAP.t201Tmr     = 1;            /* T201 - should be equal to t200Tmr */
+       cfg.t.cfg.s.bdMSAP.t202Tmr     = 2;          /* T202 */
        cfg.t.cfg.s.bdMSAP.bndRetryCnt = 2;            /* bind retry counter */
        cfg.t.cfg.s.bdMSAP.tIntTmr     = 200;          /* bind retry timer */
        cfg.t.cfg.s.bdMSAP.n202        = 3;            /* N202 */
@@ -341,7 +341,21 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
                cfg.t.cfg.s.bdMSAP.kpL1Up      = TRUE;        /* flag to keep l1 up or not */
        }
 
-       cfg.t.cfg.s.bdMSAP.type        = sng_isdn_stack_switchtype(signal_data->switchtype);
+       switch(signal_data->switchtype) {
+               case SNGISDN_SWITCH_NI2:
+               case SNGISDN_SWITCH_5ESS:
+               case SNGISDN_SWITCH_4ESS:
+               case SNGISDN_SWITCH_DMS100:
+                       cfg.t.cfg.s.bdMSAP.type = SW_NI2;
+                       break;
+               case SNGISDN_SWITCH_INSNET:
+                       cfg.t.cfg.s.bdMSAP.type = SW_CCITT;
+                       break;
+               case SNGISDN_SWITCH_EUROISDN:
+               case SNGISDN_SWITCH_QSIG:
+                       cfg.t.cfg.s.bdMSAP.type = SW_ETSI;
+                       break;
+       }
 
        if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
                cfg.t.cfg.s.bdMSAP.teiChkTmr   = 20;         /* Tei check timer */
@@ -357,6 +371,12 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
                cfg.t.cfg.s.bdMSAP.setUpArb    = ACTIVE;       /* set up arbitration */
        }
 
+       /* Overwrite setUpArb value if user forced it */
+       if (signal_data->setup_arb == SNGISDN_OPT_TRUE) {
+               cfg.t.cfg.s.bdMSAP.setUpArb    = ACTIVE;
+       } else if (signal_data->setup_arb == SNGISDN_OPT_FALSE) {
+               cfg.t.cfg.s.bdMSAP.setUpArb    = PASSIVE;
+       }
 
        if (sng_isdn_q921_config(&pst, &cfg)) {
                return FTDM_FAIL;
@@ -389,11 +409,18 @@ ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t managemen
        cfg.t.cfg.s.bdDLSAP.lnkNmb              = signal_data->link_id;
 
        cfg.t.cfg.s.bdDLSAP.n201                = 1028;                 /* n201 */
-       cfg.t.cfg.s.bdDLSAP.k                   = 7;                    /* k */
+       if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
+               span->trunk_type == FTDM_TRUNK_BRI) {
+
+               cfg.t.cfg.s.bdDLSAP.k                   = 1;                            /* Based on q.921 recommendations */
+       } else {
+               cfg.t.cfg.s.bdDLSAP.k                   = 7;                    /* k */
+       }
+       
        cfg.t.cfg.s.bdDLSAP.n200                = 3;                    /* n200 */
        cfg.t.cfg.s.bdDLSAP.congTmr             = 300;                  /* congestion timer */
-       cfg.t.cfg.s.bdDLSAP.t200Tmr             = 1;                            /* t1 changed from 25 */
-       cfg.t.cfg.s.bdDLSAP.t203Tmr             = 3;                            /* t3 changed from 50 */
+       cfg.t.cfg.s.bdDLSAP.t200Tmr             = 1;                            /* t1 changed from 25 */ 
+       cfg.t.cfg.s.bdDLSAP.t203Tmr             = 10;                           /* t3 changed from 50 */
        cfg.t.cfg.s.bdDLSAP.mod                 = 128;                  /* modulo */
        cfg.t.cfg.s.bdDLSAP.selector    = 0;                            /* Selector 0 */
        cfg.t.cfg.s.bdDLSAP.mem.region  = S_REG;                        /* Memory region */
@@ -483,7 +510,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_gen(void)
        /* upper pool threshold */
        cfg.t.cfg.s.inGen.poolTrUpper = INGEN_POOL_UP_TR;
        /* time resolution */
-       cfg.t.cfg.s.inGen.timeRes = 10;
+       cfg.t.cfg.s.inGen.timeRes = 100; /* timer resolution = 1 sec */
 
        cfg.t.cfg.s.inGen.sm.dstEnt = ENTSM;
 
@@ -594,6 +621,12 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
 
        cfg.t.cfg.s.inDLSAP.tCbId = signal_data->cc_id;
 
+       if (signal_data->facility == SNGISDN_OPT_TRUE) {
+               cfg.t.cfg.s.inDLSAP.facilityHandling = IN_FACILITY_STANDRD;
+       } else {
+               cfg.t.cfg.s.inDLSAP.facilityHandling = 0;
+       }
+
        /* TODO : NFAS configuration */
        cfg.t.cfg.s.inDLSAP.nfasInt = FALSE; /* pass this later */
 
@@ -687,38 +720,46 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
        cfg.t.cfg.s.inDLSAP.cndSubsc = TRUE;         /* calling adddress delivery service subscription */
 
        /* TODO: Fill in these timers with proper values - eventually pass them */
-       cfg.t.cfg.s.inDLSAP.tmr.t301.enb = FALSE;
-       cfg.t.cfg.s.inDLSAP.tmr.t301.val = 35;
-       cfg.t.cfg.s.inDLSAP.tmr.t302.enb = FALSE;
-       cfg.t.cfg.s.inDLSAP.tmr.t302.val = 35;
-       cfg.t.cfg.s.inDLSAP.tmr.t303.enb = FALSE;
-       cfg.t.cfg.s.inDLSAP.tmr.t303.val = 35;
+       cfg.t.cfg.s.inDLSAP.tmr.t301.enb = TRUE;
+       cfg.t.cfg.s.inDLSAP.tmr.t301.val = 180;
+       cfg.t.cfg.s.inDLSAP.tmr.t302.enb = TRUE;
+       cfg.t.cfg.s.inDLSAP.tmr.t302.val = 15;
+       cfg.t.cfg.s.inDLSAP.tmr.t303.enb = TRUE;
+       cfg.t.cfg.s.inDLSAP.tmr.t303.val = 4;
        cfg.t.cfg.s.inDLSAP.tmr.t304.enb = TRUE;
-       cfg.t.cfg.s.inDLSAP.tmr.t304.val = 35;
+       cfg.t.cfg.s.inDLSAP.tmr.t304.val = 30;
        cfg.t.cfg.s.inDLSAP.tmr.t305.enb = TRUE;
-       cfg.t.cfg.s.inDLSAP.tmr.t305.val = 35;
+       cfg.t.cfg.s.inDLSAP.tmr.t305.val = 30;
        cfg.t.cfg.s.inDLSAP.tmr.t306.enb = FALSE;
        cfg.t.cfg.s.inDLSAP.tmr.t306.val = 35;
        cfg.t.cfg.s.inDLSAP.tmr.t307.enb = FALSE;
        cfg.t.cfg.s.inDLSAP.tmr.t307.val = 35;
        cfg.t.cfg.s.inDLSAP.tmr.t308.enb = TRUE;
-       cfg.t.cfg.s.inDLSAP.tmr.t308.val = 35;
-       cfg.t.cfg.s.inDLSAP.tmr.t310.enb = FALSE;
-       cfg.t.cfg.s.inDLSAP.tmr.t310.val = 35;
-       cfg.t.cfg.s.inDLSAP.tmr.t312.enb = FALSE;
-       cfg.t.cfg.s.inDLSAP.tmr.t312.val = 35;
+       cfg.t.cfg.s.inDLSAP.tmr.t308.val = 4;
+
+       if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
+               cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
+               cfg.t.cfg.s.inDLSAP.tmr.t310.val = 10;
+               cfg.t.cfg.s.inDLSAP.tmr.t312.enb = TRUE;
+               cfg.t.cfg.s.inDLSAP.tmr.t312.val = cfg.t.cfg.s.inDLSAP.tmr.t303.val+2;
+       } else {
+               cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
+               cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120;
+               cfg.t.cfg.s.inDLSAP.tmr.t312.enb = FALSE;
+       }
+
        cfg.t.cfg.s.inDLSAP.tmr.t313.enb = TRUE;
-       cfg.t.cfg.s.inDLSAP.tmr.t313.val = 35;
+       cfg.t.cfg.s.inDLSAP.tmr.t313.val = 4;
        cfg.t.cfg.s.inDLSAP.tmr.t316.enb = TRUE;
-       cfg.t.cfg.s.inDLSAP.tmr.t316.val = 35;
-       cfg.t.cfg.s.inDLSAP.tmr.t316c.enb = TRUE;
+       cfg.t.cfg.s.inDLSAP.tmr.t316.val = 120;
+       cfg.t.cfg.s.inDLSAP.tmr.t316c.enb = FALSE;
        cfg.t.cfg.s.inDLSAP.tmr.t316c.val = 35;
-       cfg.t.cfg.s.inDLSAP.tmr.t318.enb = FALSE;
-       cfg.t.cfg.s.inDLSAP.tmr.t318.val = 35;
-       cfg.t.cfg.s.inDLSAP.tmr.t319.enb = FALSE;
-       cfg.t.cfg.s.inDLSAP.tmr.t319.val = 35;
+       cfg.t.cfg.s.inDLSAP.tmr.t318.enb = TRUE;
+       cfg.t.cfg.s.inDLSAP.tmr.t318.val = 4;
+       cfg.t.cfg.s.inDLSAP.tmr.t319.enb = TRUE;
+       cfg.t.cfg.s.inDLSAP.tmr.t319.val = 4;
        cfg.t.cfg.s.inDLSAP.tmr.t322.enb = TRUE;
-       cfg.t.cfg.s.inDLSAP.tmr.t322.val = 35;
+       cfg.t.cfg.s.inDLSAP.tmr.t322.val = 4;
        cfg.t.cfg.s.inDLSAP.tmr.t332.enb = FALSE;
        cfg.t.cfg.s.inDLSAP.tmr.t332.val = 35;
        cfg.t.cfg.s.inDLSAP.tmr.tRst.enb = TRUE;
@@ -893,8 +934,9 @@ ftdm_status_t sng_isdn_stack_cfg_cc_gen(void)
        stack_pst_init(&cfg.t.cfg.s.ccGenCfg.smPst);
        cfg.t.cfg.s.ccGenCfg.smPst.dstEnt = ENTSM;
 
-       cfg.t.cfg.s.ccGenCfg.poolTrLower = 2;
-       cfg.t.cfg.s.ccGenCfg.poolTrUpper = 4;
+       cfg.t.cfg.s.ccGenCfg.poolTrUpper = 2;
+       cfg.t.cfg.s.ccGenCfg.poolTrLower = 1;
+
        cfg.t.cfg.s.ccGenCfg.nmbSaps     = MAX_VARIANTS+1; /* Set to number of variants + 1 */
 
        if (sng_isdn_cc_config(&pst, &cfg)) {
@@ -1013,7 +1055,7 @@ uint8_t sng_isdn_stack_switchtype(sngisdn_switchtype_t switchtype)
                case SNGISDN_SWITCH_QSIG:
                        return SW_QSIG;
                case SNGISDN_SWITCH_INSNET:
-                       return SW_QSIG;
+                       return SW_INSNET;
                case SNGISDN_SWITCH_INVALID:
                        ftdm_log(FTDM_LOG_ERROR, "%s:Invalid switchtype:%d\n", switchtype);
                        break;
index d02314a82fac01bf34a72c50f5b58eb2da7c7f5d..f92eceda5e8a4d8e4ae6cc7176d16ee5def6fcce 100644 (file)
@@ -46,8 +46,11 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
 ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction);
 ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction);
 
+
 extern ftdm_sngisdn_data_t     g_sngisdn_data;
 
+ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span);
+
 
 ftdm_status_t sng_isdn_stack_activate(ftdm_span_t *span)
 {
@@ -77,6 +80,12 @@ ftdm_status_t sng_isdn_stack_activate(ftdm_span_t *span)
        return FTDM_SUCCESS;
 }
 
+ftdm_status_t  sng_isdn_stack_stop(ftdm_span_t *span)
+{
+
+       return FTDM_SUCCESS;
+}
+
 
 ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span)
 {
@@ -302,6 +311,7 @@ void stack_resp_hdr_init(Header *hdr)
 }
 
 
+
 /* For Emacs:
  * Local Variables:
  * mode:c
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
new file mode 100644 (file)
index 0000000..2520a3d
--- /dev/null
@@ -0,0 +1,978 @@
+/*
+ * Copyright (c) 2010, Sangoma Technologies
+ * David Yat Sin <dyatsin@sangoma.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ftmod_sangoma_isdn.h"
+
+extern ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
+extern ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
+extern ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb);
+extern ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, Display *display);
+
+/* Remote side transmit a SETUP */
+void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+       int16_t dChan = sngisdn_event->dChan;
+       uint8_t ces = sngisdn_event->ces;
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;        
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+       ConEvnt *conEvnt = &sngisdn_event->event.conEvnt;
+
+       ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
+       
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       switch (ftdmchan->state) {
+               case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
+                       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ||
+                               ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
+
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP but channel is in USE, saving call for later processing\n");
+                               /* the flag the channel as having a collision */
+                               sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
+
+                               /* save the SETUP for processing once the channel has gone to DOWN */
+                               memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
+                               sngisdn_info->glare.suId = suId;
+                               sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
+                               sngisdn_info->glare.spInstId = spInstId;
+                               sngisdn_info->glare.dChan = dChan;
+                               sngisdn_info->glare.ces = ces;
+                               break;
+                       }
+                       
+                       sngisdn_info->suInstId = get_unique_suInstId(suId);
+                       sngisdn_info->spInstId = spInstId;
+
+                       /* If this is a glared call that was previously saved, we moved
+                       all the info to the current call, so clear the glared saved data */
+
+                       if (sngisdn_info->glare.spInstId == spInstId) {
+                               clear_call_glare_data(sngisdn_info);
+                       }
+
+                       ftdm_assert(g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] == NULL, "Con Ind on busy spInstId");
+
+                       ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
+                       g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
+                       g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
+                       ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
+
+                       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
+
+                       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
+                               signal_data->signalling == SNGISDN_SIGNALING_NET) {
+                               sngisdn_info->ces = ces;
+                       }
+
+                       /* try to open the channel */
+                       if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
+                               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
+                               ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
+                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
+                               break;
+                       } 
+                       /* Fill in call information */
+                       cpy_calling_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
+                       cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
+                       cpy_calling_name_from_sngisdn(&ftdmchan->caller_data, &conEvnt->display);
+
+                       
+                       if (signal_data->switchtype == SNGISDN_SWITCH_NI2) {
+                               if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
+                                       if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
+                                               snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
+                                       }
+                               }
+
+                               
+                               if (conEvnt->facilityStr.eh.pres) {
+                                       /* Verify whether the Caller Name will come in a subsequent FACILITY message */
+                                       uint16_t ret_val;
+                                       uint8_t facility_str[255];
+                                       char retrieved_str[255];
+                                       memcpy(facility_str, (uint8_t*)&conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len);
+
+                                       ret_val = sng_isdn_retrieve_facility_caller_name(facility_str, conEvnt->facilityStr.facilityStr.len, retrieved_str);
+                                       /*
+                                               return values for "sng_isdn_retrieve_facility_information_following":
+                                               If there will be no information following, or fails to decode IE, returns -1
+                                               If there will be no information following, but current FACILITY IE contains a caller name, returns 0
+                                               If there will be information following, returns 1
+                                       */
+
+                                       if (ret_val == 1) {
+                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
+                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
+                                               break;
+                                       } else if (ret_val == 0) {
+                                               strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
+                                       }
+                               }
+                       }
+
+                       if (signal_data->overlap_dial == SNGISDN_OPT_TRUE && !conEvnt->sndCmplt.eh.pres) {
+                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
+                       } else {
+                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
+                       }
+                       break;
+               case FTDM_CHANNEL_STATE_TERMINATING:
+                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in TERMINATING state, saving SETUP info for later processing\n");
+                       ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare");
+                       
+                       sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
+
+                       /* save the SETUP for processing once the channel has gone to DOWN */
+                       memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
+                       sngisdn_info->glare.suId = suId;
+                       sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
+                       sngisdn_info->glare.spInstId = spInstId;
+                       sngisdn_info->glare.dChan = dChan;
+                       sngisdn_info->glare.ces = ces;
+                       
+                       /* We need to register the spInstId in case we get a release for that call while it is still stored in sngisdn_info->glare */
+                       ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
+                       g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
+                       ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
+                       
+                       break;
+               case FTDM_CHANNEL_STATE_DIALING:        /* glare */
+                       if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
+                               /* Save inbound call info so we can send a RELEASE when this channel goes to a different state */
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Processing SETUP in DIALING state, rejecting inbound call\n");
+                               sngisdn_set_flag(sngisdn_info, FLAG_DELAYED_REL);
+
+                               sngisdn_info->glare.suId = suId;
+                               sngisdn_info->glare.suInstId = get_unique_suInstId(suId);
+                               sngisdn_info->glare.spInstId = spInstId;
+
+                               ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
+                               g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
+                               g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
+                               ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
+
+                               sngisdn_info->glare.dChan = dChan;
+                               sngisdn_info->glare.ces = ces;
+                               ftdmchan->caller_data.hangup_cause = 0x2C; /* Channel requested not available */
+                               ftdm_sched_timer(signal_data->sched, "delayed_release", 1, sngisdn_delayed_release, (void*) sngisdn_info, NULL);
+                       } else {
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in DIALING state, saving SETUP info for later processing\n");
+                               
+                               /* the flag the channel as having a collision */
+                               ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare");
+                               sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
+
+                               /* save the SETUP for processing once the channel has gone to DOWN */
+                               memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
+                               sngisdn_info->glare.suId = suId;
+                               sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
+                               sngisdn_info->glare.spInstId = spInstId;
+                               sngisdn_info->glare.dChan = dChan;
+                               sngisdn_info->glare.ces = ces;
+
+                               /* We need to register the spInstId in case we get a release for that call while it is still stored in sngisdn_info->glare */
+                               ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
+                               g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
+                               ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
+                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                       }
+                       break;
+               default:
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
+                       break;
+       }
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+/* Remote side transmit a CONNECT or CONNECT ACK */
+void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+       uint8_t ces = sngisdn_event->ces;
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       
+       /* Function does not require any info from conStEvnt struct for now */
+       /* CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; */      
+                               
+       ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
+       
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing CONNECT/CONNECT ACK (suId:%u suInstId:%u spInstId:%u ces:%d)\n", suId, suInstId, spInstId, ces);
+       
+       if (!sngisdn_info->spInstId) {
+               ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
+               sngisdn_info->spInstId = spInstId;
+               g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
+               ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
+       }
+
+       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
+               ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
+
+               if(sngisdn_info->ces == CES_MNGMNT) {
+                       /* We assign the call to the first TE */
+                       sngisdn_info->ces = ces;
+               } else {
+                       /* We already assigned this call, do nothing */
+                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call already assigned, ignoring connect\n");
+                       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+                       return;
+               }
+       }
+
+       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+               switch(ftdmchan->state) {
+                       case FTDM_CHANNEL_STATE_PROGRESS:
+                       case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+                       case FTDM_CHANNEL_STATE_DIALING:
+                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
+                               break;
+                       default:
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
+
+                               /* Start the disconnect procedure */
+                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                               break;
+               }
+       } else {
+               switch(ftdmchan->state) {
+                       case FTDM_CHANNEL_STATE_UP:
+                               /* This is the only valid state we should get a CONNECT ACK on */
+                               /* do nothing */
+                               break;
+                       default:
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
+                               
+                               /* Start the disconnect procedure */
+                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                               break;
+               }
+       }
+
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+       uint8_t ces = sngisdn_event->ces;
+       uint8_t evntType = sngisdn_event->evntType;
+       
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       
+       CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt;
+
+       if (!sngisdn_info->spInstId) {
+               ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
+               sngisdn_info->spInstId = spInstId;
+               g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
+               ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
+       }
+
+       ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing %s (suId:%u suInstId:%u spInstId:%u ces:%d)\n",
+                                                                                                       (evntType == MI_ALERTING)?"ALERT":
+                                                                                                       (evntType == MI_CALLPROC)?"PROCEED":
+                                                                                                       (evntType == MI_PROGRESS)?"PROGRESS":
+                                                                                                       (evntType == MI_SETUPACK)?"SETUP ACK":
+                                                                                                                       (evntType == MI_INFO)?"INFO":"UNKNOWN",
+                                                                                                                       suId, suInstId, spInstId, ces);
+       
+       switch(evntType) {
+               case MI_ALERTING:
+               case MI_CALLPROC:
+               case MI_PROGRESS:
+                       switch(ftdmchan->state) {
+                               case FTDM_CHANNEL_STATE_DIALING:
+                                       if (evntType == MI_PROGRESS) {
+                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+                                       } else {
+                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
+                                       }
+                                       break;
+                               case FTDM_CHANNEL_STATE_PROGRESS:
+                                       if (evntType == MI_PROGRESS) {
+                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+                                       }
+                                       break;
+                               case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+                                       /* We are already in progress media, we can't go to any higher state except up */
+                                       /* Do nothing */
+                                       break;
+                               default:
+                                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing ALERT/PROCEED/PROGRESS in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
+
+                                       /* Start the disconnect procedure */
+                                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                                       break;
+                       }
+                       break;
+               case MI_SETUPACK:
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Processing SETUP_ACK, but overlap sending not implemented (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+                       break;
+               case MI_INFO:
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing INFO (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+
+                       if (cnStEvnt->cdPtyNmb.eh.pres) {
+                               switch(ftdmchan->state) {
+                                       case FTDM_CHANNEL_STATE_COLLECT:
+                                       {
+                                               ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits;
+                                               ftdm_size_t num_digits;
+
+                                               cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb);
+                                               num_digits = strlen(ftdmchan->caller_data.dnis.digits);
+
+                                               if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) {
+                                                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
+                                               } else {
+                                                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "received %d of %d digits\n", num_digits, min_digits);
+                                               }
+                                       }
+                                       break;
+                                       case FTDM_CHANNEL_STATE_RING:
+                                       case FTDM_CHANNEL_STATE_PROGRESS:
+                                       case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+                                       case FTDM_CHANNEL_STATE_UP:
+                                               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Receiving more digits %s, but we already proceeded with call\n", cnStEvnt->cdPtyNmb.nmbDigits.val);
+                                               break;
+                                       default:
+                                               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "\n", suId, suInstId, spInstId);
+                                               break;
+                               }
+                       }
+
+                       break;
+               default:
+                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unhandled STATUS event\n");
+                       break;
+       }
+
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       
+       DiscEvnt *discEvnt = &sngisdn_event->event.discEvnt;
+
+       if (!sngisdn_info->spInstId) {
+               ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
+               sngisdn_info->spInstId = spInstId;
+               g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
+               ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
+       }
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+
+       ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
+       switch (ftdmchan->state) {
+               case FTDM_CHANNEL_STATE_RING:
+               case FTDM_CHANNEL_STATE_DIALING:
+               case FTDM_CHANNEL_STATE_PROGRESS:
+               case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+               case FTDM_CHANNEL_STATE_UP:
+                       if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
+                               ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
+                       } else {
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "DISCONNECT did not have a cause code\n");
+                               ftdmchan->caller_data.hangup_cause = 0;
+                       }
+                       sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_REL);
+                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                       break;
+               case FTDM_CHANNEL_STATE_COLLECT:
+               case FTDM_CHANNEL_STATE_GET_CALLERID:
+                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
+                       break;
+               case FTDM_CHANNEL_STATE_DOWN:
+                       /* somehow we are in down, nothing we can do locally */
+                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT but we are in DOWN state\n");
+                       break;
+               case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+                       /* This is a race condition. We just sent a DISCONNECT, on this channel */
+                       /* Do nothing */
+                       break;
+               default:
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
+                                                 ftdm_channel_state2str(ftdmchan->state));
+                       /* start reset procedure */
+
+                       /* Start the release procedure */
+                       ftdm_set_flag(sngisdn_info, FLAG_REMOTE_REL);
+                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                       break;
+       }
+
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;        
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       
+       RelEvnt *relEvnt = &sngisdn_event->event.relEvnt;
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RELEASE/RELEASE COMPLETE (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
+       
+       if ((suInstId && (sngisdn_info->glare.suInstId == suInstId)) ||
+               (spInstId && (sngisdn_info->glare.spInstId == spInstId))) {
+
+               /* This hangup is for a glared saved call */
+               ftdm_clear_flag(sngisdn_info, FLAG_DELAYED_REL);
+               clear_call_glare_data(sngisdn_info);
+
+               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       /* check whether the ftdm channel is in a state to accept a call */
+       switch (ftdmchan->state) {
+               case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+                       /* go to DOWN */
+                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+                       break;
+               case FTDM_CHANNEL_STATE_DOWN:
+                       /* do nothing, just drop the message */
+                       break;
+               case FTDM_CHANNEL_STATE_DIALING:
+                       /* Remote side rejected our SETUP message on outbound call */
+                       if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
+                               sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
+                       }
+                       /* fall-through */
+               case FTDM_CHANNEL_STATE_PROGRESS:
+               case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+               case FTDM_CHANNEL_STATE_UP:
+               case FTDM_CHANNEL_STATE_RING:
+                       /* If we previously had a glare on this channel,
+                       this RELEASE could be for the previous call.  Confirm whether call_data has
+                       not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */
+                       if (((sngisdn_chan_data_t*)ftdmchan->call_data)->suInstId == suInstId ||
+                                                                       ((sngisdn_chan_data_t*)ftdmchan->call_data)->spInstId == spInstId) {
+                               if (relEvnt->causeDgn[0].eh.pres && relEvnt->causeDgn[0].causeVal.pres) {
+                                       ftdmchan->caller_data.hangup_cause = relEvnt->causeDgn[0].causeVal.val;
+                                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause);
+                               } else {
+                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "RELEASE COMPLETE did not have a cause code\n");
+                                       ftdmchan->caller_data.hangup_cause = 0;
+                               }
+
+                               sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
+                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+
+                       } else {
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "RELEASE was for previous call (suInstId:%u spInstId:%u)\n", suInstId, spInstId);
+                       }
+                       break;
+               case FTDM_CHANNEL_STATE_COLLECT:
+               case FTDM_CHANNEL_STATE_GET_CALLERID:
+                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
+                       break;
+               case FTDM_CHANNEL_STATE_TERMINATING:
+                       if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE) &&
+                                                               sngisdn_info->glare.suInstId != suInstId) {
+                               /* This release if for the outbound call that we already started clearing */
+
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Received RELEASE for local glared call\n");
+                               sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
+                       } else {
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received release before we could clear local call\n");
+                               /* FS core took too long to respond to the SIG STOP event */
+                               sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
+                               /* set abort flag so that we do not transmit another release complete on this channel once FS core is done */
+                       }
+                       break;
+               default:
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
+                                                       ftdm_channel_state2str(ftdmchan->state));
+
+                       break;
+       }
+
+
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_dat_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);    
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+
+       /* Function does not require any info from infoEvnt struct for now */
+       /* InfoEvnt *infoEvnt = &sngisdn_event->event.infoEvnt; */
+       
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DATA IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_sshl_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+
+       /* Function does not require any info from ssHlEvnt struct for now */
+       /* SsHlEvnt *ssHlEvnt = &sngisdn_event->event.ssHlEvnt; */
+       
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing SSHL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_sshl_cfm (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+       
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+
+       /* Function does not require any info from ssHlEvnt struct for now */
+       /* SsHlEvnt *ssHlEvnt = &sngisdn_event->event.ssHlEvnt; */
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing SSHL CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_rmrt_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+
+       /* Function does not require any info from ssHlEvnt struct for now */
+       /* RmRtEvnt *rmRtEvnt = &sngisdn_event->event.rmRtEvnt; */
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RESUME/RETRIEVE IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_rmrt_cfm (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       
+       /* Function does not require any info from ssHlEvnt struct for now */
+       /* RmRtEvnt *rmRtEvnt = &sngisdn_event->event.rmRtEvnt; */
+       
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RESUME/RETRIEVE CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_flc_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+
+       /* Function does not require any info from ssHlEvnt struct for now */
+       /* StaEvnt *staEvnt = &sngisdn_event->event.staEvnt; */
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing FLOW CONTROL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+
+       FacEvnt *facEvnt = &sngisdn_event->event.facEvnt;
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+
+       switch (ftdmchan->state) {
+               case FTDM_CHANNEL_STATE_GET_CALLERID:
+                       /* Update the caller ID Name */
+#if 1
+                       if (facEvnt->facElmt.facStr.pres) {
+                               uint8_t facility_str[255];
+                               memcpy(facility_str, (uint8_t*)&facEvnt->facElmt.facStr.val, facEvnt->facElmt.facStr.len);
+                               char retrieved_str[255];
+                               if (sng_isdn_retrieve_facility_caller_name(facility_str, facEvnt->facElmt.facStr.len, retrieved_str) != FTDM_SUCCESS) {
+                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n");
+                               }
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "DYDBG Name is:%s\n", retrieved_str);
+                       }
+#endif
+
+                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
+                       break;
+               default:
+                       /* We do not support other FACILITY types for now, so do nothing */
+                       break;
+       }
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       
+       int16_t suId = sngisdn_event->suId;
+       uint32_t suInstId = sngisdn_event->suInstId;
+       uint32_t spInstId = sngisdn_event->spInstId;
+       sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       
+       StaEvnt *staEvnt = &sngisdn_event->event.staEvnt;
+       
+       uint8_t call_state = 0;
+
+       if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
+               call_state = staEvnt->callSte.callGlblSte.val;
+       }
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+
+       ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
+
+       if (staEvnt->causeDgn[0].eh.pres && staEvnt->causeDgn[0].causeVal.pres) {
+               if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
+                       call_state = staEvnt->callSte.callGlblSte.val;
+               } else {
+                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received STATUS without call state\n");
+                       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+                       return;
+               }
+               switch (staEvnt->causeDgn[0].causeVal.val) {
+                       case FTDM_CAUSE_RESPONSE_TO_STATUS_ENQUIRY:
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Status Check OK:%d", call_state);
+                               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+                               return;
+                       case FTDM_CAUSE_WRONG_CALL_STATE:
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Message incompatible with call state (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId);
+                               break;
+                       case FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Recovery on timer expire (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId);
+                               break;
+                       default:
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "STATUS CONFIRM (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId);
+                               break;
+               }
+
+               /* Section 4.3.30 from INT Interface - Service Definition */
+               ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
+               
+               switch(call_state) {
+                       /* Sere ITU-T Q931 for definition of call states */
+                       case 0: /* Remote switch thinks there are no calls on this channel */
+                               switch (ftdmchan->state) {
+                                       case FTDM_CHANNEL_STATE_COLLECT:
+                                       case FTDM_CHANNEL_STATE_DIALING:
+                                       case FTDM_CHANNEL_STATE_UP:
+                                               sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
+                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                                               break;
+                                       case FTDM_CHANNEL_STATE_TERMINATING:
+                                               /* We are in the process of clearing local states,
+                                               just make sure we will not send any messages to remote switch */
+                                               sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
+                                               break;
+                                       case FTDM_CHANNEL_STATE_HANGUP:
+                                               /* This cannot happen, state_advance always sets
+                                               ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP
+                                               and we called check_for_state_change earlier so something is very wrong here!!! */
+                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n");
+                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+                                               break;
+                                       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+                                               /* We were waiting for remote switch to send RELEASE COMPLETE
+                                               but this will not happen, so just clear local state */
+                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+                                               break;
+                                       case FTDM_CHANNEL_STATE_DOWN:
+                                               /* If our local state is down as well, then there is nothing to do */
+                                               break;
+                                       default:
+                                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
+                                               break;
+                               }
+                               break;
+                       case 1:
+                               switch (ftdmchan->state) {
+                                       case FTDM_CHANNEL_STATE_UP:
+                                               /* Remote side is still waiting for our CONNECT message */
+                                               if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+                                                       ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL);
+                                                       break;
+                                               }
+                                               /* Fall-through */
+                                       default:
+                                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
+                                               break;
+                               }
+                               break;
+                               case 2: /* overlap sending/receiving */
+                                       switch (ftdmchan->state) {
+                                               case FTDM_CHANNEL_STATE_COLLECT:
+                                                       /* T302 Timeout reached */
+                                                       /* Send the call to user, and see if they accept it */
+                                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n");
+                                                       ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
+                                                       break;
+                                               case FTDM_CHANNEL_STATE_PROGRESS:
+                                               case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+                                                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n");
+                                                       sngisdn_snd_disconnect(ftdmchan);
+                                                       break;
+                                               case FTDM_CHANNEL_STATE_DOWN:
+                                               case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+                                                       /* We hung up locally, but remote switch doesn't know send disconnect again*/
+                                                       sngisdn_snd_disconnect(ftdmchan);
+                                                       break;
+                                               default:
+                                                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
+                                                       break;
+                                       }
+                                       break;
+                       case 3:
+                               switch (ftdmchan->state) {
+                                       case FTDM_CHANNEL_STATE_UP:
+                                               /* Remote side is still waiting for our CONNECT message */
+                                               if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+                                                       ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL);
+                                                       break;
+                                               }
+                                               /* Fall-through */
+                                       default:
+                                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
+                                               break;
+                               }
+                               break;
+                       case 8: /* Remote switch is in "Connect Request state" */
+                               switch (ftdmchan->state) {
+                                       case FTDM_CHANNEL_STATE_UP:
+                                               /* This is ok. We sent a Connect, and we are waiting for a connect ack */
+                                               /* Do nothing */
+                                               break;
+                                       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+                                               /* We hung up locally, but remote switch doesn't know send disconnect again*/
+                                               sngisdn_snd_disconnect(ftdmchan);
+                                               break;
+                                       default:
+                                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
+                                               break;
+                               }
+                               break;
+                       case 10: /* Remote switch is in active state */
+                               switch (ftdmchan->state) {
+                                       case FTDM_CHANNEL_STATE_UP:
+                                               /* This is ok, they are in active state and we are in active state */
+                                               /* Do nothing */
+                                               break;
+                                       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+                                               /* We sent a disconnect message, but remote side missed it ? */
+                                               ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_disconnect", 1, sngisdn_delayed_disconnect, (void*) sngisdn_info, NULL);
+                                               break;
+                                       default:
+                                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
+                                               break;
+                               }
+                               break;
+                       case 9:
+                               switch (ftdmchan->state) {
+                                       case FTDM_CHANNEL_STATE_PROGRESS:
+                                               /* Do nothing */
+                                               break;
+                                       default:
+                                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
+                                               break;
+                               }
+                               break;
+                       case 22:
+                               switch (ftdmchan->state) {
+                                       case FTDM_CHANNEL_STATE_UP:
+                                               /* Stack is in the process of clearing the call*/
+                                               ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                                               break;
+                                       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+                                               /* Do nothing as we will get a RELEASE COMPLETE */
+                                               break;
+                                       default:
+                                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
+                                               //ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+                                               break;
+                               }
+                       default:
+                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
+                                               //ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+                               break;
+               }
+       }
+
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+
+void sngisdn_process_srv_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       int16_t dChan = sngisdn_event->dChan;
+       uint8_t ces = sngisdn_event->ces;
+
+       /* Function does not require any info from ssHlEvnt struct for now */
+       /*Srv *srvEvnt = &sngisdn_event->event.srvEvnt;*/
+       
+       ftdm_log(FTDM_LOG_DEBUG, "Processing SERVICE IND (suId:%u dChan:%d ces:%d)\n", suId, dChan, ces);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       int16_t dChan = sngisdn_event->dChan;
+       uint8_t ces = sngisdn_event->ces;
+
+       /* Function does not require any info from ssHlEvnt struct for now */
+       /*Srv *srvEvnt = &sngisdn_event->event.srvEvnt;*/
+       
+       ftdm_log(FTDM_LOG_DEBUG, "Processing SERVICE CFM (suId:%u dChan:%d ces:%d)\n", suId, dChan, ces);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       int16_t dChan = sngisdn_event->dChan;
+       uint8_t ces = sngisdn_event->ces;
+       uint8_t evntType = sngisdn_event->evntType;
+
+       /* Function does not require any info from ssHlEvnt struct for now */
+       /*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
+       
+       ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+
+void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       int16_t suId = sngisdn_event->suId;
+       int16_t dChan = sngisdn_event->dChan;
+       uint8_t ces = sngisdn_event->ces;
+       uint8_t evntType = sngisdn_event->evntType;
+
+       /* Function does not require any info from ssHlEvnt struct for now */
+       /*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
+               
+       ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d %s)\n", suId, dChan, ces,
+                                                                                                       (evntType == IN_LNK_DWN)?"LNK_DOWN":
+                                                                                                       (evntType == IN_LNK_UP)?"LNK_UP":
+                                                                                                       (evntType == IN_INDCHAN)?"b-channel":
+                                                                                                       (evntType == IN_LNK_DWN_DM_RLS)?"Nfas service procedures":
+                                                                                                       (evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown");
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_in.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_in.c
deleted file mode 100644 (file)
index 04430cf..0000000
+++ /dev/null
@@ -1,935 +0,0 @@
-/*
- * Copyright (c) 2010, Sangoma Technologies
- * David Yat Sin <davidy@sangoma.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of the original author; nor the names of any contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
- * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "ftmod_sangoma_isdn.h"
-
-extern ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
-extern ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
-extern ftdm_status_t cpy_called_name_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
-extern ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt);
-extern void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
-extern void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
-extern void get_memory_info(void);
-
-extern ftdm_sngisdn_data_t     g_sngisdn_data;
-
-#define MAX_DECODE_STR_LEN 2000
-
-/* Remote side transmit a SETUP */
-void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       uint8_t bchan_no = 0;
-       sngisdn_chan_data_t *sngisdn_info;
-       ftdm_channel_t *ftdmchan;
-       /*sngisdn_span_data_t *span_info;*/
-       
-       ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
-
-       ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
-       ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
-       ftdm_assert(g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] == NULL, "Con Ind on busy spInstId");
-       
-       if (conEvnt->chanId.eh.pres != PRSNT_NODEF) {
-               /* TODO: Implement me */
-               ftdm_log(FTDM_LOG_ERROR, "Incoming call without Channel Id not supported yet\n");
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-               return;
-       }
-
-       if (conEvnt->chanId.chanNmbSlotMap.pres) {
-               bchan_no = conEvnt->chanId.chanNmbSlotMap.val[0];
-       } else if (conEvnt->chanId.infoChanSel.pres) {
-               bchan_no = conEvnt->chanId.infoChanSel.val;
-       }
-
-       if (!bchan_no) {
-               ftdm_log(FTDM_LOG_ERROR, "Failed to obtain b-channel number from SETUP message\n");
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-               return;
-       }
-
-       if (g_sngisdn_data.dchans[dChan].channels[bchan_no] == NULL) {
-               ftdm_log(FTDM_LOG_ERROR, "Incoming call on unconfigured b-channel:%d\n", bchan_no);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-               return;
-       }
-
-       sngisdn_info = g_sngisdn_data.dchans[dChan].channels[bchan_no];
-       ftdmchan = sngisdn_info->ftdmchan;
-       ftdm_mutex_lock(ftdmchan->mutex);
-
-       /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
-        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
-        ftdm_mutex_unlock(ftdmchan->mutex);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    }
-
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP\n");
-       switch (ftdmchan->state){
-               case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
-                       sngisdn_info->suInstId = get_unique_suInstId(suId);
-                       sngisdn_info->spInstId = spInstId;
-                       g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
-                       g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
-
-                       /* try to open the channel */
-                       if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
-                               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
-                               ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
-                       } else {
-                               /* Fill in call information */
-                               cpy_calling_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
-                               cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
-                               cpy_calling_name_from_sngisdn(&ftdmchan->caller_data, conEvnt);
-
-                               /* Get ani2 */
-#if 0
-                               /* TODO: confirm that this works in the field */
-                               if (conEvnt->niOperSysAcc.eh.pres) {
-                                       if (conEvnt->niOperSysAcc.typeAcc.pres) {
-                                               ftdmchan->caller_data.aniII = (uint8_t)conEvnt->niOperSysAcc.typeAcc.val;
-                                               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received ANI: type of access:%x", conEvnt->niOperSysAcc.typeAcc.val);
-                                       }
-                                       if (conEvnt->niOperSysAcc.typeServ.pres) {
-                                               ftdmchan->caller_data.aniII = (uint8_t)conEvnt->niOperSysAcc.typeServ.val;
-                                               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received ANI: type of service:%x", conEvnt->niOperSysAcc.typeServ.val);
-                                       }
-                               }
-#endif
-
-                               /* set the state of the channel to collecting...the rest is done by the chan monitor */
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
-
-                       }
-                       break;
-               case FTDM_CHANNEL_STATE_DIALING:        /* glare */
-                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received SETUP in DIALING state, glare, queueing incoming call\n");
-                        /* the flag the channel as having a collision */
-                       sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
-
-                       /* save the SETUP for processing once the channel has gone to DOWN */
-                       memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
-                       sngisdn_info->glare.suId = suId;
-                       sngisdn_info->glare.suInstId = suInstId;
-                       sngisdn_info->glare.spInstId = spInstId;
-                       sngisdn_info->glare.dChan = dChan;
-                       sngisdn_info->glare.ces = ces;
-                       break;
-               default:
-                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
-                       break;
-       }
-       ftdm_mutex_unlock(ftdmchan->mutex);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-/* Remote side transmit a CONNECT or CONNECT ACK */
-void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       sngisdn_chan_data_t *sngisdn_info;
-       ftdm_channel_t *ftdmchan;
-
-       ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
-
-       
-       ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
-       ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
-
-       if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
-               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-               return;
-       }
-
-       ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
-
-       if (!sngisdn_info->spInstId) {
-               sngisdn_info->spInstId = spInstId;
-               g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
-       }
-
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received CONNECT/CONNECT ACK\n");
-       ftdm_mutex_lock(ftdmchan->mutex);
-
-       /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
-        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
-        ftdm_mutex_unlock(ftdmchan->mutex);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    }
-
-       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
-               ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
-
-               if(sngisdn_info->ces == CES_MNGMNT) {
-                       /* We assign the call to the first TE */
-                       sngisdn_info->ces = ces;
-               } else {
-                       /* We already assigned this call, do nothing */
-                       ftdm_mutex_unlock(ftdmchan->mutex);
-                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call already assigned, ignoring connect\n");
-                       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-                       return;
-               }
-       }
-       
-       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
-               switch(ftdmchan->state) {
-                       case FTDM_CHANNEL_STATE_PROGRESS:
-                       case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
-                       case FTDM_CHANNEL_STATE_DIALING:
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
-                               break;
-                       default:
-                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received CONNECT/CONNECT ACK in an invalid state (%s)\n",
-                                               ftdm_channel_state2str(ftdmchan->state));
-
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-                               break;
-               }
-       } else {
-               switch(ftdmchan->state) {
-                       case FTDM_CHANNEL_STATE_UP:
-                               /* This is the only valid state we should get a CONNECT ACK on */
-                               /* do nothing */
-                               break;
-                       default:
-                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-                               break;
-               }
-       }
-       
-       ftdm_mutex_unlock(ftdmchan->mutex);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       sngisdn_chan_data_t *sngisdn_info;
-       ftdm_channel_t *ftdmchan;
-
-       ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
-
-       ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
-       ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
-
-       if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
-               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-               return;
-       }
-
-       if (!sngisdn_info->spInstId) {
-               sngisdn_info->spInstId = spInstId;
-               g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
-       }
-
-       ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
-       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Received %s\n",
-                                                               (evntType == MI_ALERTING)?"ALERT":
-                                                               (evntType == MI_CALLPROC)?"PROCEED":
-                                                               (evntType == MI_PROGRESS)?"PROGRESS":"UNKNOWN");
-       ftdm_mutex_lock(ftdmchan->mutex);
-
-               /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
-        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
-        ftdm_mutex_unlock(ftdmchan->mutex);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    }
-
-       switch(ftdmchan->state) {
-               case FTDM_CHANNEL_STATE_DIALING:
-                       if (evntType == MI_PROGRESS) {
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
-                       } else {
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
-                       }
-                       break;
-               case FTDM_CHANNEL_STATE_PROGRESS:
-                       if (evntType == MI_PROGRESS) {
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
-                       }
-                       break;
-               case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
-                       /* Do nothing */
-                       break;
-               default:
-                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received ALERT/PROCEED/PROGRESS in an invalid state (%s)\n",
-                                       ftdm_channel_state2str(ftdmchan->state));
-
-                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-                       break;
-       }
-
-       ftdm_mutex_unlock(ftdmchan->mutex);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       sngisdn_chan_data_t *sngisdn_info;
-       ftdm_channel_t *ftdmchan = NULL;
-
-       ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
-
-       ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id");
-
-       if (spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) {
-               ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
-       } else if (suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS) {
-               ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
-       } else {
-               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-               return;
-       }
-
-       if (!sngisdn_info->spInstId) {
-               sngisdn_info->spInstId = spInstId;
-               g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
-       }
-
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT\n");
-       ftdm_mutex_lock(ftdmchan->mutex);
-       /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
-        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
-        ftdm_mutex_unlock(ftdmchan->mutex);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    }
-
-       switch (ftdmchan->state) {
-               case FTDM_CHANNEL_STATE_RING:
-               case FTDM_CHANNEL_STATE_DIALING:
-               case FTDM_CHANNEL_STATE_PROGRESS:
-               case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
-               case FTDM_CHANNEL_STATE_COLLECT:
-               case FTDM_CHANNEL_STATE_UP:             
-                       if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
-                               ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
-                       } else {
-                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "DISCONNECT did not have a cause code\n");
-                               ftdmchan->caller_data.hangup_cause = 0;
-                       }
-                       sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_REL);
-                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-                       break;
-               default:
-                       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
-                                       ftdm_channel_state2str(ftdmchan->state));
-                       /* start reset procedure */
-                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-                       break;
-       }
-
-       ftdm_mutex_unlock(ftdmchan->mutex);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
-
-       sngisdn_chan_data_t  *sngisdn_info ;
-    ftdm_channel_t      *ftdmchan = NULL;
-
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-       if (suInstId && (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
-               ftdmchan = sngisdn_info->ftdmchan;
-       } else if (spInstId && (get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS)) {
-               ftdmchan = sngisdn_info->ftdmchan;
-       }
-
-       if (ftdmchan == NULL) {
-               ftdm_log(FTDM_LOG_CRIT, "Failed to find matching channel suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-               return;
-       }
-
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE\n");
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
-
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
-        ftdm_mutex_unlock(ftdmchan->mutex);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    };
-
-    /* check whether the ftdm channel is in a state to accept a call */
-    switch (ftdmchan->state) {
-    case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
-        /* go to DOWN */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-        break;
-    case FTDM_CHANNEL_STATE_DOWN:
-        /* do nothing, just drop the message */
-        break;
-       case FTDM_CHANNEL_STATE_PROGRESS:
-       case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
-               /* Remote side sent a SETUP, then a RELEASE COMPLETE to abort call - this is an abort */
-               sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
-               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-               break;
-       case FTDM_CHANNEL_STATE_DIALING:
-               /* Remote side rejected our SETUP message on outbound call */
-               sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
-               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-               break;
-       case FTDM_CHANNEL_STATE_UP:
-               sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
-               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-               break;
-    default:
-        /* Should just stop the call...but a reset is easier for now (since it does hangup the call) */
-               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
-                                       ftdm_channel_state2str(ftdmchan->state));
-
-        /* go to RESTART */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-
-        break;
-    /**************************************************************************/
-    }
-
-    /* unlock the channel */
-    ftdm_mutex_unlock(ftdmchan->mutex);
-
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received DATA IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received SSHL IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received SSHL CFM suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received RESUME/RETRIEVE ind suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received FLOW CONTROL IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received FACILITY IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_sta_cfm ( int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
-
-       sngisdn_chan_data_t  *sngisdn_info ;
-    ftdm_channel_t      *ftdmchan = NULL;
-       uint8_t                         call_state = 0;
-
-       if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
-               call_state = staEvnt->callSte.callGlblSte.val;
-       }
-
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-       if (suInstId && (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
-               ftdmchan = sngisdn_info->ftdmchan;
-       } else if (spInstId && (get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS)) {
-               ftdmchan = sngisdn_info->ftdmchan;
-       }
-
-       if (ftdmchan == NULL) {
-               ftdm_log(FTDM_LOG_CRIT, "Failed to find matching channel suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-               return;
-       }
-
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM\n");
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
-
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
-        ftdm_mutex_unlock(ftdmchan->mutex);
-               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    };
-
-       if (staEvnt->causeDgn[0].eh.pres && staEvnt->causeDgn[0].causeVal.pres) {
-               if (staEvnt->causeDgn[0].causeVal.val != 30) {
-                       
-                       if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
-                               call_state = staEvnt->callSte.callGlblSte.val;
-                               /* Section 4.3.30 from INT Interface - Service Definition */
-                               ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
-
-
-                               /* There is incompatibility between local and remote side call states some Q931 msgs probably got lost - initiate disconnect  */
-                               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Incompatible call states detected, remote side indicated state:%d our state:%s cause:%d\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val);
-
-                               switch(call_state) {
-                                       /* Sere ITU-T Q931 for definition of call states */
-                                       case 0: /* Remote switch thinks there are no calls on this channel */
-                                               switch (ftdmchan->state) {
-                                                       case FTDM_CHANNEL_STATE_COLLECT:
-                                                       case FTDM_CHANNEL_STATE_DIALING:                                        
-                                                               sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
-                                                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-                                                               break;
-                                                       case FTDM_CHANNEL_STATE_TERMINATING:
-                                                               /* We are in the process of clearing local states,
-                                                                       just make sure we will not send any messages to remote switch */
-                                                               sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
-                                                               break;
-                                                       case FTDM_CHANNEL_STATE_HANGUP:
-                                                               /* This cannot happen, state_advance always sets
-                                                                       ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP
-                                                                       and we called check_for_state_change earlier so something is very wrong here!!! */
-                                                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n");
-                                                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-                                                               break;
-                                                       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
-                                                               /* We were waiting for remote switch to send RELEASE COMPLETE
-                                                                       but this will not happen, so just clear local state */
-                                                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-                                                               break;
-                                                       case FTDM_CHANNEL_STATE_DOWN:
-                                                               /* If our local state is down as well, then there is nothing to do */
-                                                               break;
-                                                       default:
-                                                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
-                                                               break;
-                                               }
-                                               break;
-                                       case 8: /* Remote switch is in "Connect Request state" */
-                                               switch (ftdmchan->state) {
-                                                       case FTDM_CHANNEL_STATE_UP:
-                                                               /* This is ok. We sent a Connect, and we are waiting for a connect ack */
-                                                               /* Do nothing */
-                                                               break;
-                                                       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
-                                                               /* We hung up locally, but remote switch doesn't know send disconnect again*/
-                                                               sngisdn_snd_disconnect(ftdmchan);
-                                                               break;
-                                                       default:
-                                                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
-                                                               break;
-                                               }
-                                               break;
-                                       default:
-                                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
-                                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-                                               break;                                  
-                               }
-                       } else {
-                               ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
-                               /* We could not extract the call state */
-                               ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible call states detected, but could not determine call (cause:%d)\n", ftdmchan->caller_data.hangup_cause);
-                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-                       }
-
-               }
-    /**************************************************************************/
-    }
-
-    /* unlock the channel */
-    ftdm_mutex_unlock(ftdmchan->mutex);
-
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_srv_ind ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_srv_cfm ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evtType)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received RESTART IND suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-
-void sngisdn_rcv_rst_cfm ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evtType)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_phy_ind(SuId suId, Reason reason)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-    ftdm_log(FTDM_LOG_INFO, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason));
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
-} 
-
-void sngisdn_rcv_q921_ind(BdMngmt *status)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-
-       unsigned j,k;
-       ftdm_span_t *ftdmspan = NULL;
-
-       for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
-               for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
-                       if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.lnkNmb) {
-                               ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
-                       }
-               }
-       }
-       if (ftdmspan == NULL) {
-               ftdm_log(FTDM_LOG_CRIT, "Received q921 status on unconfigured span\n", status->t.usta.lnkNmb);
-#ifdef DEBUG_MODE
-               FORCE_SEGFAULT
-#endif
-               return;
-       }
-
-       switch (status->t.usta.alarm.category) {
-               case (LCM_CATEGORY_INTERFACE):
-                       ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
-                                                       ftdmspan->name,
-                                                       DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
-                                                       DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
-                                                       DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
-                       break;
-               default:
-                       ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
-                                       ftdmspan->name,
-                                       DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
-                                       DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
-                                       DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
-                       break;
-       }
-       
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__)
-    return;
-}
-void sngisdn_rcv_q931_ind(InMngmt *status)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-
-       
-
-       ftdm_span_t *ftdmspan = NULL;
-       
-       if (status->t.usta.alarm.cause == 287) {
-               get_memory_info();
-               return;
-       }
-
-       switch (status->t.usta.alarm.category) {
-               case (LCM_CATEGORY_INTERFACE):
-                       ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
-                                                       status->t.usta.suId,
-                                                       DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
-                                                       DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
-                                                       DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
-
-                       /* clean this up later */
-
-                       switch (status->t.usta.alarm.event) {
-                               case LCM_EVENT_UP:
-                               case LCM_EVENT_DOWN:
-                                       {
-                                               unsigned j,k;
-                                               for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
-                                                       for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
-                                                               if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.suId) {
-                                                                       ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
-                                                               }
-                                                       }
-                                               }
-
-                                               if (ftdmspan == NULL) {
-                                                       ftdm_log(FTDM_LOG_CRIT, "Received q931 LCM EVENT on unconfigured span (suId:%d)\n", status->t.usta.suId);
-                                                       return;
-                                               }
-
-                                               sngisdn_set_span_sig_status(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP)?FTDM_SIG_STATE_UP:FTDM_SIG_STATE_DOWN);
-                                       }
-                                       break;
-                       }
-                       break;
-               default:
-                       ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
-                                       status->t.usta.suId,
-                                       DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
-                                       DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
-                                       DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
-                       break;
-       }
-
-
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-       return;
-}
-
-void sngisdn_rcv_cc_ind(CcMngmt *status)
-{
-       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       ftdm_log(FTDM_LOG_INFO, "RECEIVED %s\n", __FUNCTION__);
-       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
-}
-
-#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
-                                                               (event == TL3PKTRX)?"RX":"UNKNOWN"
-
-void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
-{
-       MsgLen mlen;
-       MsgLen i;
-       int16_t j;
-       Buffer *tmp;
-       Data *cptr;
-       uint8_t data;
-       uint8_t tdata[1000];
-       char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
-       
-       ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
-       mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
-
-       if (mlen != 0) {
-               tmp = mBuf->b_cont;
-               cptr = tmp->b_rptr;
-               data = *cptr++;
-               i = 0;
-
-               for(j=0;j<mlen;j++) {
-                       tdata[j]= data;
-
-                       if (cptr == tmp->b_wptr) {
-                               tmp = tmp->b_cont;
-                               if (tmp) cptr = tmp->b_rptr;
-                       }
-                       data = *cptr++;
-               }
-
-               sngisdn_trace_q931(data_str, tdata, mlen);
-               ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] FRAME %s:%s\n", Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
-       }
-
-       ftdm_safe_free(data_str);
-       /* We do not need to free mBuf in this case because stack does it */
-       /* SPutMsg(mBuf); */
-       return;
-}
-
-
-#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
-                                                               (event == TL2FRMTX)?"TX": \
-                                                               (event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
-
-void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
-{
-       MsgLen mlen;
-       MsgLen i;
-       int16_t j;
-       Buffer *tmp;
-       Data *cptr;
-       uint8_t data;
-       uint8_t tdata[16];
-       char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
-       
-
-       if (trc->t.trc.evnt == TL2TMR) {
-               goto end_of_trace;
-       }
-
-       ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
-       mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
-
-       if (mlen != 0) {
-               tmp = mBuf->b_cont;
-               cptr = tmp->b_rptr;
-               data = *cptr++;
-               i = 0;
-               while (i < mlen) {
-                       j = 0;
-                       for(j=0;j<16;j++) {
-                               if (i<mlen) {
-                                       tdata[j]= data;
-                               
-                                       if (cptr == tmp->b_wptr) {
-                                               tmp = tmp->b_cont;
-                                               if (tmp) cptr = tmp->b_rptr;
-                                       }
-                                       i++;
-                                       if (i<mlen) data = *cptr++;
-                               }
-                       }
-
-               }
-               sngisdn_trace_q921(data_str, tdata, mlen);
-               ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] FRAME %s:%s\n", Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
-       }
-end_of_trace:
-       ftdm_safe_free(data_str);
-       SPutMsg(mBuf);
-       return;
-}
-
-
-
-void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
-{
-       char    *data;
-    int     ret;
-    va_list ap;
-
-    va_start(ap, fmt);
-    ret = ftdm_vasprintf(&data, fmt, ap);
-    if (ret == -1) {
-        return;
-    }
-
-    switch (level) {
-               case SNG_LOGLEVEL_DEBUG:
-                       ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
-                       break;
-               case SNG_LOGLEVEL_WARN:
-                       ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
-                       break;
-               case SNG_LOGLEVEL_INFO:
-                       ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
-                       break;
-               case SNG_LOGLEVEL_STATS:
-                       ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
-                       break;
-               case SNG_LOGLEVEL_ERROR:
-                       ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
-#ifdef DEBUG_MODE
-                       FORCE_SEGFAULT
-#endif
-                       break;
-               case SNG_LOGLEVEL_CRIT:
-                       ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
-#ifdef DEBUG_MODE
-                       FORCE_SEGFAULT
-#endif
-                       break;
-               default:
-                       ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
-                       break;
-    }
-       return;
-}
-
-/* For Emacs:
- * Local Variables:
- * mode:c
- * indent-tabs-mode:t
- * tab-width:4
- * c-basic-offset:4
- * End:
- * For VIM:
- * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
- */
-
-/******************************************************************************/
index c5e986bea3a1afde299adc30f523b20c691caf68..8247735cb98765253251aad82eed5468bc964a7f 100644 (file)
@@ -43,7 +43,7 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_progress(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_release(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
 
 
 void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
@@ -52,11 +52,15 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
        sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;  
 
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending SETUP\n");
-
+       ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n");
+       
        sngisdn_info->suInstId = get_unique_suInstId(signal_data->cc_id);
        sngisdn_info->spInstId = 0;
 
+       ftdm_mutex_lock(g_sngisdn_data.ccs[signal_data->cc_id].mutex);
+       g_sngisdn_data.ccs[signal_data->cc_id].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
+       ftdm_mutex_unlock(g_sngisdn_data.ccs[signal_data->cc_id].mutex);
+
        memset(&conEvnt, 0, sizeof(conEvnt));
        
        conEvnt.bearCap[0].eh.pres = PRSNT_NODEF;
@@ -92,18 +96,21 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
                conEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
        } else {
                /* PRI only params */
+
                if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
                        conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
-                       conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
+                       conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
                } else {
                        conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
-                       conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
+                       conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
                }
                conEvnt.bearCap[0].lyr1Ident.pres = PRSNT_NODEF;
                conEvnt.bearCap[0].lyr1Ident.val = IN_L1_IDENT;
 
                conEvnt.chanId.intType.pres = PRSNT_NODEF;
                conEvnt.chanId.intType.val = IN_IT_OTHER;
+               conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
+               conEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
                conEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
                conEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
                conEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
@@ -130,20 +137,81 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
                signal_data->signalling == SNGISDN_SIGNALING_NET) {
                sngisdn_info->ces = CES_MNGMNT;
        }
-       
-       cpy_calling_num_to_sngisdn(&conEvnt.cgPtyNmb, &ftdmchan->caller_data);
+
        cpy_called_num_to_sngisdn(&conEvnt.cdPtyNmb, &ftdmchan->caller_data);
+       cpy_calling_num_to_sngisdn(&conEvnt.cgPtyNmb, &ftdmchan->caller_data);
        cpy_calling_name_to_sngisdn(&conEvnt, ftdmchan);
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con request on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
 
        if (sng_isdn_con_request(signal_data->cc_id, sngisdn_info->suInstId, &conEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused SETUP request\n");
        }
+
        return;
 }
 
-/* Used only for BRI PTMP */
+/* Unsed only for overlap receive */
+void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan)
+{
+       CnStEvnt cnStEvnt;
+       
+       sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+       if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending SETUP ACK , but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+               return;
+       }
+       
+       memset(&cnStEvnt, 0, sizeof(cnStEvnt)); 
+
+       cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
+       cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
+       cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
+       cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
+       cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
+       cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
+       cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
+
+       
+       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
+               ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
+
+               /* BRI only params */
+               cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
+               cnStEvnt.chanId.intType.val = IN_IT_BASIC;
+               cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
+               cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
+       } else {
+               cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
+               cnStEvnt.chanId.intType.val = IN_IT_OTHER;
+               cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
+               cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
+               cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
+               cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
+               cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
+               cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
+               cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
+               cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
+               cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
+               cnStEvnt.chanId.chanNmbSlotMap.len = 1;
+               cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
+       }
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
+
+       if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_SETUPACK, signal_data->dchan_id, sngisdn_info->ces)) {
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused SETUP ACK request\n");
+       }
+       return;
+}
+
+
+/* Used only for BRI PTMP - This function is used when the NT side makes a call out,
+       and one or multiple TE's reply, then NT assigns the call by sending a con_complete*/
 void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
 {
        CnStEvnt cnStEvnt;
@@ -151,9 +219,15 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
+       if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending CONNECT COMPL , but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+               return;
+       }
+       
        memset(&cnStEvnt, 0, sizeof(cnStEvnt));
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT ACK\n");
-
+       
        cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
        cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
        cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
@@ -187,7 +261,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
        }
 
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending connect ACK on suId:%d suInstId:%u spInstId:%u ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_info->ces);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT COMPL (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
 
        if(sng_isdn_con_comp(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused CONNECT ACK request\n");
@@ -203,9 +277,15 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
+ if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+               return;
+       }
+       
        memset(&cnStEvnt, 0, sizeof(cnStEvnt));
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED\n");
-
+       
        cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
        cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
        cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
@@ -239,7 +319,7 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
        }
 
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con status on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
 
        if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_CALLPROC, signal_data->dchan_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused PROCEED request\n");
@@ -254,9 +334,20 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
-       memset(&cnStEvnt, 0, sizeof(cnStEvnt));
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS\n");
+ if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+               return;
+       }       
+       
+       if (signal_data->switchtype == SNGISDN_SWITCH_INSNET) {
+               /* Trillium Q931 layer complains of invalid event when receiving PROGRESS in
+                       INSNET variant, so PROGRESS event is probably invalid */
+               return;
+       }
 
+       memset(&cnStEvnt, 0, sizeof(cnStEvnt)); 
 
        cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
        cnStEvnt.progInd.location.pres = PRSNT_NODEF;
@@ -264,9 +355,9 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
        cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
        cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
        cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
-       cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN;
+       cnStEvnt.progInd.progDesc.val = IN_PD_IBAVAIL;
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con status on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
        if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused PROGRESS request\n");
        }
@@ -280,7 +371,12 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO,  "Sending ALERT\n");
+ if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending ALERT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+               return;
+       }       
 
        memset(&cnStEvnt, 0, sizeof(cnStEvnt));
 
@@ -292,7 +388,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
        cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
        cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN;
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con status on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
 
        if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_ALERTING, signal_data->dchan_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused ALERT request\n");
@@ -307,8 +403,13 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT\n");
-
+ if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending CONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+               return;
+       }
+       
        memset(&cnStEvnt, 0, sizeof(cnStEvnt));
 
 
@@ -344,21 +445,75 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
                cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
        }
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con response on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
        if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused CONNECT request\n");
        }
        return;
 }
 
+
+void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
+{
+       CnStEvnt cnStEvnt;
+       
+       sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+       if (ftdmchan->span->trunk_type != FTDM_TRUNK_BRI &&
+               ftdmchan->span->trunk_type != FTDM_TRUNK_BRI_PTMP) {
+
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring INFO REQ on non-BRI channel\n");
+               return;
+       }
+
+       memset(&cnStEvnt, 0, sizeof(cnStEvnt));
+       //ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ\n");
+
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, sngisdn_info->ces);
+
+       if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, signal_data->dchan_id, sngisdn_info->ces)) {
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused INFO request\n");
+       }
+       return;
+}
+
+
+void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan)
+{
+       StaEvnt staEvnt;
+
+       sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+
+       //ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending STATUS ENQ\n");
+
+       memset(&staEvnt, 0, sizeof(StaEvnt));
+
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d dchan:%d ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
+       if (sng_isdn_status_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &staEvnt, MI_STATENQ)) {
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT,      "stack refused Status ENQ request\n");
+       }
+       return;
+}
+
+
 void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
 {      
        DiscEvnt discEvnt;
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT\n");
 
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
+ if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending DISCONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+
+               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
+               return;
+       }
+       
        memset(&discEvnt, 0, sizeof(discEvnt));
        
        /* Fill discEvnt here */        
@@ -372,20 +527,28 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
        discEvnt.causeDgn[0].recommend.pres = NOTPRSNT;
        discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending disc request on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
        if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) {
                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused DISCONNECT request\n");
        }
        return;
 }
-void sngisdn_snd_release(ftdm_channel_t *ftdmchan)
+void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
 {
        RelEvnt relEvnt;
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE\n");
+       uint32_t suInstId, spInstId;
 
        sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
+       if (!sngisdn_info->suInstId) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending RELEASE, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+
+               sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
+               return;
+       }
+       
        memset(&relEvnt, 0, sizeof(relEvnt));
        
        /* Fill discEvnt here */        
@@ -400,20 +563,25 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan)
        relEvnt.causeDgn[0].recommend.pres = NOTPRSNT;
        relEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
 
-       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending release request on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
-
-       if (sng_isdn_release_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &relEvnt)) {
-               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RELEASE/RELEASE COMPLETE request\n");
-       }       
-       return;
-}
+       if (glare) {
+               suInstId = sngisdn_info->glare.suInstId;
+               spInstId = sngisdn_info->glare.spInstId;
+       } else {
+               suInstId = sngisdn_info->suInstId;
+               spInstId = sngisdn_info->spInstId;
+       }
 
+       ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId);
 
-void sngisdn_snd_reset(ftdm_channel_t *ftdmchan)
-{
-       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending RESET\n");
-       ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "%s not implemented\n", __FUNCTION__);
-       /* TODO: implement me */
+       if (glare) {
+               if (sng_isdn_release_request(signal_data->cc_id, suInstId, spInstId, &relEvnt)) {
+                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RELEASE/RELEASE COMPLETE request\n");
+               }
+       } else {        
+               if (sng_isdn_release_request(signal_data->cc_id, suInstId, spInstId, &relEvnt)) {
+                       ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RELEASE/RELEASE COMPLETE request\n");
+               }
+       }       
        return;
 }
 
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
new file mode 100644 (file)
index 0000000..1c49674
--- /dev/null
@@ -0,0 +1,901 @@
+/*
+ * Copyright (c) 2010, Sangoma Technologies
+ * David Yat Sin <dyatsin@sangoma.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ftmod_sangoma_isdn.h"
+
+extern void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
+extern void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
+extern void get_memory_info(void);
+
+#define MAX_DECODE_STR_LEN 2000
+
+
+void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       uint8_t bchan_no = 0;
+       sngisdn_chan_data_t *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;    
+
+       ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
+       ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
+               
+       if (conEvnt->chanId.eh.pres != PRSNT_NODEF) {
+               /* TODO: Implement me */
+               ftdm_log(FTDM_LOG_ERROR, "Incoming call without Channel Id not supported yet\n");
+               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       if (conEvnt->chanId.chanNmbSlotMap.pres) {
+               bchan_no = conEvnt->chanId.chanNmbSlotMap.val[0];
+       } else if (conEvnt->chanId.infoChanSel.pres) {
+               bchan_no = conEvnt->chanId.infoChanSel.val;
+       }
+
+       if (!bchan_no) {
+               ftdm_log(FTDM_LOG_ERROR, "Failed to obtain b-channel number from SETUP message\n");
+               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       if (g_sngisdn_data.dchans[dChan].channels[bchan_no] == NULL) {
+               ftdm_log(FTDM_LOG_ERROR, "Incoming call on unconfigured b-channel:%d\n", bchan_no);
+               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       sngisdn_info = g_sngisdn_data.dchans[dChan].channels[bchan_no];
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_CON_IND;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+       sngisdn_event->dChan = dChan;
+       sngisdn_event->ces = ces;
+
+       memcpy(&sngisdn_event->event.conEvnt, conEvnt, sizeof(*conEvnt));
+       
+       ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+
+       ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Cfm on unconfigured cc\n");
+       ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Cfm on unconfigured dchan\n");
+
+       if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received CONNECT/CONNECT ACK (suId:%u suInstId:%u spInstId:%u ces:%d)\n", suId, suInstId, spInstId, ces);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_CON_CFM;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+       sngisdn_event->dChan = dChan;
+       sngisdn_event->ces = ces;
+
+       memcpy(&sngisdn_event->event.cnStEvnt, cnStEvnt, sizeof(*cnStEvnt));
+       
+       ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
+{      
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+       
+       ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Cnst Ind on unconfigured cc\n");
+       ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Cnst Ind on unconfigured dchan\n");
+
+       if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+               ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received %s (suId:%u suInstId:%u spInstId:%u ces:%d)\n",
+                                                                                                       (evntType == MI_ALERTING)?"ALERT":
+                                                                                                       (evntType == MI_CALLPROC)?"PROCEED":
+                                                                                                       (evntType == MI_PROGRESS)?"PROGRESS":
+                                                                                                       (evntType == MI_SETUPACK)?"SETUP ACK":
+                                                                                                                       (evntType == MI_INFO)?"INFO":"UNKNOWN",
+                                                                                                                       suId, suInstId, spInstId, ces);
+
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_CNST_IND;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+       sngisdn_event->dChan = dChan;
+       sngisdn_event->ces = ces;
+       sngisdn_event->evntType = evntType;
+
+       memcpy(&sngisdn_event->event.cnStEvnt, cnStEvnt, sizeof(*cnStEvnt));
+       
+ ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+
+       ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id");
+
+       if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
+               !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
+
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_DISC_IND;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+
+       memcpy(&sngisdn_event->event.discEvnt, discEvnt, sizeof(*discEvnt));
+       
+ ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t  *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+       
+       if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
+               !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
+
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_REL_IND;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+
+       memcpy(&sngisdn_event->event.relEvnt, relEvnt, sizeof(*relEvnt));
+       
+       ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t  *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+       
+       if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
+               !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
+
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+               
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DATA IND suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_DAT_IND;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+
+       memcpy(&sngisdn_event->event.infoEvnt, infoEvnt, sizeof(*infoEvnt));
+
+       ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t  *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+       
+       if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
+               !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
+
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+               
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_SSHL_IND;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+       sngisdn_event->action = action;
+
+       memcpy(&sngisdn_event->event.ssHlEvnt, ssHlEvnt, sizeof(*ssHlEvnt));
+
+       ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t  *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+       
+       if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
+               !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
+
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+               
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_SSHL_CFM;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+       sngisdn_event->action = action;
+
+       memcpy(&sngisdn_event->event.ssHlEvnt, ssHlEvnt, sizeof(*ssHlEvnt));
+
+ ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t  *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+       
+       if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
+               !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
+
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+               
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RMRT IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_RMRT_IND;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+       sngisdn_event->action = action;
+
+       memcpy(&sngisdn_event->event.rmRtEvnt, rmRtEvnt, sizeof(*rmRtEvnt));
+
+ ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t  *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+       
+       if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
+               !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
+
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+               
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_RMRT_CFM;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+       sngisdn_event->action = action;
+
+       memcpy(&sngisdn_event->event.rmRtEvnt, rmRtEvnt, sizeof(*rmRtEvnt));
+
+       ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t  *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+       
+       if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
+                        !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
+
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+               
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FLOW CONTROL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_FLC_IND;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+
+       memcpy(&sngisdn_event->event.staEvnt, staEvnt, sizeof(*staEvnt));
+
+       ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+
+void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t  *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+       
+       if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
+               !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
+
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_FAC_IND;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+       sngisdn_event->evntType = evntType;
+       
+       memcpy(&sngisdn_event->event.facEvnt, facEvnt, sizeof(*facEvnt));
+
+       ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+
+void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       sngisdn_chan_data_t  *sngisdn_info;
+       sngisdn_event_data_t *sngisdn_event;
+       
+       if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
+               !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
+
+               ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
+
+               return;
+       }
+
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+       
+       sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+       ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+       memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+       sngisdn_event->event_id = SNGISDN_EVENT_STA_CFM;
+       sngisdn_event->sngisdn_info = sngisdn_info;
+       sngisdn_event->suId = suId;
+       sngisdn_event->suInstId = suInstId;
+       sngisdn_event->spInstId = spInstId;
+
+       memcpy(&sngisdn_event->event.staEvnt, staEvnt, sizeof(*staEvnt));
+
+       ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_srv_ind (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       unsigned i;
+       sngisdn_span_data_t     *signal_data;
+       sngisdn_event_data_t *sngisdn_event;
+
+       ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND (dChan:%d ces:%u)\n", dChan, ces);
+       
+       /* Enqueue the event to each span within the dChan */
+       for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
+               signal_data = g_sngisdn_data.dchans[dChan].spans[i];
+               sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+               ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+               memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+               sngisdn_event->event_id = SNGISDN_EVENT_SRV_IND;                
+               sngisdn_event->suId = suId;
+               sngisdn_event->dChan = dChan;
+               sngisdn_event->ces = ces;
+               sngisdn_event->signal_data = signal_data;
+               
+               memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt));
+               ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
+       }
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+
+void sngisdn_rcv_srv_cfm (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       unsigned i;
+       sngisdn_span_data_t     *signal_data;
+       sngisdn_event_data_t *sngisdn_event;
+
+       ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM (dChan:%d ces:%u)\n", dChan, ces);
+
+       /* Enqueue the event to each span within the dChan */
+       for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
+               signal_data = g_sngisdn_data.dchans[dChan].spans[i];
+               sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+               ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+               memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+               sngisdn_event->event_id = SNGISDN_EVENT_SRV_CFM;                
+               sngisdn_event->suId = suId;
+               sngisdn_event->dChan = dChan;
+               sngisdn_event->ces = ces;
+               sngisdn_event->signal_data = signal_data;
+
+               memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt));
+               ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
+       }
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       unsigned i;
+       sngisdn_span_data_t     *signal_data;
+       sngisdn_event_data_t *sngisdn_event;
+
+       ftdm_log(FTDM_LOG_INFO, "Received RESTART IND (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
+       
+       /* Enqueue the event to each span within the dChan */
+       for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
+               signal_data = g_sngisdn_data.dchans[dChan].spans[i];
+               sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+               ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+               memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+               sngisdn_event->event_id = SNGISDN_EVENT_RST_IND;
+               sngisdn_event->suId = suId;
+               sngisdn_event->dChan = dChan;
+               sngisdn_event->ces = ces;
+               sngisdn_event->evntType = evntType;
+               sngisdn_event->signal_data = signal_data;
+
+               memcpy(&sngisdn_event->event.rstEvnt, rstEvnt, sizeof(*rstEvnt));
+               ftdm_queue_enqueue(signal_data->event_queue, sngisdn_event);
+       }
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       unsigned i;
+       sngisdn_span_data_t     *signal_data;
+       sngisdn_event_data_t *sngisdn_event;
+
+       ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
+       
+       /* Enqueue the event to each span within the dChan */
+       for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
+               signal_data = g_sngisdn_data.dchans[dChan].spans[i];
+               sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
+               ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
+               memset(sngisdn_event, 0, sizeof(*sngisdn_event));
+
+               sngisdn_event->event_id = SNGISDN_EVENT_RST_CFM;
+               sngisdn_event->suId = suId;
+               sngisdn_event->dChan = dChan;
+               sngisdn_event->ces = ces;
+               sngisdn_event->evntType = evntType;
+               sngisdn_event->signal_data = signal_data;
+
+               memcpy(&sngisdn_event->event.rstEvnt, rstEvnt, sizeof(*rstEvnt));
+               ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
+       }
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+}
+
+
+void sngisdn_rcv_phy_ind(SuId suId, Reason reason)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       if (reason != LL1_REASON_CON_REQ_FAIL) {
+               ftdm_log(FTDM_LOG_INFO, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason));
+       }
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+    return;
+} 
+
+void sngisdn_rcv_q921_ind(BdMngmt *status)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       unsigned j,k;
+       ftdm_span_t *ftdmspan = NULL;
+
+       for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
+               for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
+                       if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.lnkNmb) {
+                               ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
+                       }
+               }
+       }
+       ftdm_assert(ftdmspan != NULL, "Received q921 status on unconfigured span\n");
+
+       switch (status->t.usta.alarm.category) {
+               case (LCM_CATEGORY_INTERFACE):
+                       ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
+                                                       ftdmspan->name,
+                                                       DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
+                                                       DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
+                                                       DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
+                       break;
+               default:
+                       ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
+                                       ftdmspan->name,
+                                       DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
+                                       DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
+                                       DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
+
+                       switch (status->t.usta.alarm.event) {
+                               case ENTR_CONG: /* Entering Congestion */
+                                       ftdm_log(FTDM_LOG_WARNING, "s%d: Entering Congestion\n", ftdmspan->span_id);
+                                       ftdm_set_flag(ftdmspan, FTDM_SPAN_SUSPENDED);
+                                       break;
+                               case EXIT_CONG: /* Exiting Congestion */
+                                       ftdm_log(FTDM_LOG_WARNING, "s%d: Exiting Congestion\n", ftdmspan->span_id);
+                                       ftdm_clear_flag(ftdmspan, FTDM_SPAN_SUSPENDED);
+                                       break;
+                       }
+                       break;
+       }
+       
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__)
+    return;
+}
+void sngisdn_rcv_q931_ind(InMngmt *status)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       ftdm_span_t *ftdmspan = NULL;
+       
+       if (status->t.usta.alarm.cause == 287) {
+               get_memory_info();
+               return;
+       }
+
+       switch (status->t.usta.alarm.category) {
+               case (LCM_CATEGORY_INTERFACE):
+                       ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
+                                                       status->t.usta.suId,
+                                                       DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
+                                                       DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
+                                                       DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
+
+                       /* clean this up later */
+
+                       switch (status->t.usta.alarm.event) {
+                               case LCM_EVENT_UP:
+                               case LCM_EVENT_DOWN:
+                                       {
+                                               unsigned j,k;
+                                               for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
+                                                       for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
+                                                               if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.suId) {
+                                                                       ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
+                                                               }
+                                                       }
+                                               }
+
+                                               if (ftdmspan == NULL) {
+                                                       ftdm_log(FTDM_LOG_CRIT, "Received q931 LCM EVENT on unconfigured span (suId:%u)\n", status->t.usta.suId);
+                                                       return;
+                                               }
+
+                                               if (status->t.usta.alarm.event == LCM_EVENT_UP) {
+                                                       sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
+                                                       sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
+                                               } else {
+                                                       sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
+                                                       sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
+                                               }
+                                       }
+                                       break;
+                       }
+                       break;
+               default:
+                       ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
+                                       status->t.usta.suId,
+                                       DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
+                                       DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
+                                       DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
+                       break;
+       }
+
+
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+void sngisdn_rcv_cc_ind(CcMngmt *status)
+{
+       ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+       ftdm_log(FTDM_LOG_INFO, "RECEIVED %s\n", __FUNCTION__);
+       ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+    return;
+}
+
+#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
+                                                               (event == TL3PKTRX)?"RX":"UNKNOWN"
+
+void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
+{
+       MsgLen mlen;
+       MsgLen i;
+       int16_t j;
+       Buffer *tmp;
+       Data *cptr;
+       uint8_t data;
+       uint8_t tdata[1000];
+       char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
+       
+       ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
+       mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
+
+       if (mlen != 0) {
+               tmp = mBuf->b_cont;
+               cptr = tmp->b_rptr;
+               data = *cptr++;
+               i = 0;
+
+               for(j=0;j<mlen;j++) {
+                       tdata[j]= data;
+
+                       if (cptr == tmp->b_wptr) {
+                               tmp = tmp->b_cont;
+                               if (tmp) cptr = tmp->b_rptr;
+                       }
+                       data = *cptr++;
+               }
+
+               sngisdn_trace_q931(data_str, tdata, mlen);
+               ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d FRAME %s:%s\n", trc->t.trc.suId, Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
+       }
+
+       ftdm_safe_free(data_str);
+       /* We do not need to free mBuf in this case because stack does it */
+       /* SPutMsg(mBuf); */
+       return;
+}
+
+
+#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
+                                                               (event == TL2FRMTX)?"TX": \
+                                                               (event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
+
+void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
+{
+       MsgLen mlen;
+       MsgLen i;
+       int16_t j;
+       Buffer *tmp;
+       Data *cptr;
+       uint8_t data;
+       uint8_t tdata[16];
+       char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
+       
+
+       if (trc->t.trc.evnt == TL2TMR) {
+               goto end_of_trace;
+       }
+
+       ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
+       mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
+
+       if (mlen != 0) {
+               tmp = mBuf->b_cont;
+               cptr = tmp->b_rptr;
+               data = *cptr++;
+               i = 0;
+               while (i < mlen) {
+                       j = 0;
+                       for(j=0;j<16;j++) {
+                               if (i<mlen) {
+                                       tdata[j]= data;
+                               
+                                       if (cptr == tmp->b_wptr) {
+                                               tmp = tmp->b_cont;
+                                               if (tmp) cptr = tmp->b_rptr;
+                                       }
+                                       i++;
+                                       if (i<mlen) data = *cptr++;
+                               }
+                       }
+
+               }
+               sngisdn_trace_q921(data_str, tdata, mlen);
+               ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", trc->t.trc.lnkNmb, Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
+       }
+end_of_trace:
+       ftdm_safe_free(data_str);
+       SPutMsg(mBuf);
+       return;
+}
+
+void sngisdn_rcv_sng_assert(char *message)
+{
+       ftdm_assert(0, message);
+}
+
+void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
+{
+       char    *data;
+    int     ret;
+    va_list ap;
+
+    va_start(ap, fmt);
+    ret = ftdm_vasprintf(&data, fmt, ap);
+    if (ret == -1) {
+        return;
+    }
+
+    switch (level) {
+               case SNG_LOGLEVEL_DEBUG:
+                       ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
+                       break;
+               case SNG_LOGLEVEL_WARN:
+                       ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
+                       break;
+               case SNG_LOGLEVEL_INFO:
+                       ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
+                       break;
+               case SNG_LOGLEVEL_STATS:
+                       ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
+                       break;
+               case SNG_LOGLEVEL_ERROR:
+                       ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
+                       /*ftdm_assert(0, "Got an error from stack");*/
+                       break;
+               case SNG_LOGLEVEL_CRIT:
+                       ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
+                       /*ftdm_assert(0, "Got an error from stack");*/
+                       break;
+               default:
+                       ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
+                       break;
+    }
+       return;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
+
+/******************************************************************************/
index b922efc8091a203d191774c3499cf1cfa83aecb6..f910eb31eb071c35c247b008f025a36378f5db1f 100644 (file)
 ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
 ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
 ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb);
-ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt);
+ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, Display *display);
 
 ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm);
 ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm);
 ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm);
 ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan);
 
+ftdm_status_t sngisdn_check_free_ids(void);
+
 extern ftdm_sngisdn_data_t     g_sngisdn_data;
 void get_memory_info(void);
 
-void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
+void __inline__ clear_call_data(sngisdn_chan_data_t *sngisdn_info)
 {
        uint32_t cc_id = ((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->cc_id;
 
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Clearing call data (suId:%u suInstId:%u spInstId:%u)\n", cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
+       ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].mutex);
        g_sngisdn_data.ccs[cc_id].active_spInstIds[sngisdn_info->spInstId]=NULL;
        g_sngisdn_data.ccs[cc_id].active_suInstIds[sngisdn_info->suInstId]=NULL;
+       ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex);
        
        sngisdn_info->suInstId = 0;
        sngisdn_info->spInstId = 0;
@@ -61,10 +66,33 @@ void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
        return;
 }
 
-uint32_t get_unique_suInstId(uint8_t cc_id)
+void __inline__ clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info)
+{
+       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Clearing glare data (suId:%d suInstId:%u spInstId:%u actv-suInstId:%u  actv-spInstId:%u)\n",
+                                                                               sngisdn_info->glare.suId,
+                                                                               sngisdn_info->glare.suInstId, sngisdn_info->glare.spInstId,
+                                                                               sngisdn_info->suInstId, sngisdn_info->spInstId);
+
+       ftdm_mutex_lock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex);
+       g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_spInstIds[sngisdn_info->glare.spInstId]=NULL;
+       g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_suInstIds[sngisdn_info->glare.suInstId]=NULL;
+       ftdm_mutex_unlock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex);
+
+       ftdm_clear_flag(sngisdn_info, FLAG_GLARE);
+       memset(&sngisdn_info->glare.setup, 0, sizeof(ConEvnt));
+       sngisdn_info->glare.suId = 0;
+       sngisdn_info->glare.suInstId = 0;
+       sngisdn_info->glare.spInstId = 0;
+       sngisdn_info->glare.dChan = 0;
+       sngisdn_info->glare.ces = 0;
+       return;
+}
+
+
+uint32_t __inline__ get_unique_suInstId(uint8_t cc_id)
 {
        uint32_t suInstId;
-       ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].request_mutex);
+       ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].mutex);
        suInstId = g_sngisdn_data.ccs[cc_id].last_suInstId;
 
        while(1) {
@@ -73,16 +101,16 @@ uint32_t get_unique_suInstId(uint8_t cc_id)
                }
                if (g_sngisdn_data.ccs[cc_id].active_suInstIds[suInstId] == NULL) {
                        g_sngisdn_data.ccs[cc_id].last_suInstId = suInstId;
-                       ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].request_mutex);
+                       ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex);
                        return suInstId;
                }
        }
        /* Should never reach here */
-       ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].request_mutex);
+       ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex);
        return 0;
 }
 
-ftdm_status_t get_ftdmchan_by_suInstId(uint8_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data)
+ftdm_status_t __inline__ get_ftdmchan_by_suInstId(uint8_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data)
 {
        ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n");
 
@@ -93,7 +121,7 @@ ftdm_status_t get_ftdmchan_by_suInstId(uint8_t cc_id, uint32_t suInstId, sngisdn
        return FTDM_SUCCESS;
 }
 
-ftdm_status_t get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data)
+ftdm_status_t __inline__ get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data)
 {
        ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n");
 
@@ -104,6 +132,19 @@ ftdm_status_t get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInstId, sngisdn
        return FTDM_SUCCESS;
 }
 
+ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *ftdmspan, sngisdn_avail_t avail)
+{
+       unsigned i;
+       if (ftdmspan->trunk_type == FTDM_TRUNK_BRI ||
+               ftdmspan->trunk_type == FTDM_TRUNK_BRI_PTMP) {
+
+               for(i=1; i<=ftdmspan->chan_count; i++) {
+                       ftdm_log_chan(ftdmspan->channels[i], FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
+                       ftdmspan->channels[i]->availability_rate = avail;
+               }
+       }
+       return FTDM_SUCCESS;
+}
 
 ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb)
 {
@@ -147,7 +188,9 @@ ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cd
        }
        
        if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
-               ftdm_copy_string(ftdm->dnis.digits, (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1);
+               unsigned i = strlen(ftdm->dnis.digits);
+               
+               ftdm_copy_string(&ftdm->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1);
        }
        return FTDM_SUCCESS;
 }
@@ -172,13 +215,16 @@ ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *red
        return FTDM_SUCCESS;
 }
 
-ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt)
+ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, Display *display)
 {
-       if (conEvnt->display.eh.pres && conEvnt->display.dispInfo.pres == PRSNT_NODEF) {
-               ftdm_copy_string(ftdm->cid_name, (const char*)conEvnt->display.dispInfo.val, conEvnt->display.dispInfo.len+1);
+       if (display->eh.pres != PRSNT_NODEF) {
+               return FTDM_FAIL;
        }
-
-       /* TODO check if caller name is contained in a Facility IE */
+       if (display->dispInfo.pres != PRSNT_NODEF) {
+               return FTDM_FAIL;
+       }
+       
+       ftdm_copy_string(ftdm->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1);
        return FTDM_SUCCESS;
 }
 
@@ -219,14 +265,23 @@ ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *
        cdPtyNmb->eh.pres           = PRSNT_NODEF;
 
        cdPtyNmb->nmbPlanId.pres      = PRSNT_NODEF;
-       cdPtyNmb->nmbPlanId.val       = ftdm->dnis.plan;
-
+       if (ftdm->dnis.plan == FTDM_NPI_INVALID) {
+               cdPtyNmb->nmbPlanId.val       = FTDM_NPI_UNKNOWN;
+       } else {
+               cdPtyNmb->nmbPlanId.val       = ftdm->dnis.plan;
+       }
+       
        cdPtyNmb->typeNmb0.pres       = PRSNT_NODEF;
-       cdPtyNmb->typeNmb0.val        = ftdm->dnis.type;
+       if (ftdm->dnis.type == FTDM_TON_INVALID) {
+               cdPtyNmb->typeNmb0.val        = FTDM_TON_UNKNOWN;
+       } else {
+               cdPtyNmb->typeNmb0.val        = ftdm->dnis.type;
+       }
 
        cdPtyNmb->nmbDigits.pres = PRSNT_NODEF;
        cdPtyNmb->nmbDigits.len = len;
 
+       
        memcpy(cdPtyNmb->nmbDigits.val, ftdm->dnis.digits, len);
     return FTDM_SUCCESS;
 }
@@ -241,10 +296,18 @@ ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *f
        redirNmb->eh.pres       = PRSNT_NODEF;
 
        redirNmb->nmbPlanId.pres        = PRSNT_NODEF;
-       redirNmb->nmbPlanId.val         = ftdm->rdnis.plan;
+       if (ftdm->rdnis.plan == FTDM_NPI_INVALID) {
+               redirNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
+       } else {
+               redirNmb->nmbPlanId.val = ftdm->rdnis.plan;
+       }
 
        redirNmb->typeNmb.pres          = PRSNT_NODEF;
-       redirNmb->typeNmb.val           = ftdm->rdnis.type;
+       if (ftdm->rdnis.type == FTDM_TON_INVALID) {
+               redirNmb->typeNmb.val           = FTDM_TON_UNKNOWN;
+       } else {
+               redirNmb->typeNmb.val           = ftdm->rdnis.type;
+       }
 
        redirNmb->nmbDigits.pres = PRSNT_NODEF;
        redirNmb->nmbDigits.len = len;
@@ -308,28 +371,99 @@ ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdm
        return FTDM_SUCCESS;
 }
 
+void sngisdn_delayed_release(void* p_sngisdn_info)
+{
+       sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;       
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;  
+
+       ftdm_mutex_lock(ftdmchan->mutex);
+       
+       if (ftdm_test_flag(sngisdn_info, FLAG_DELAYED_REL)) {
+               ftdm_clear_flag(sngisdn_info, FLAG_DELAYED_REL);
+               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed RELEASE (suId:%d suInstId:%u spInstId:%u)\n",
+                                                               signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
+
+               sngisdn_snd_release(ftdmchan, 1);
+#if 1  /* TODO: Confirm this */
+               clear_call_glare_data(sngisdn_info);
+#else
+               g_sngisdn_data.ccs[signal_data->cc_id].active_spInstIds[sngisdn_info->glare.spInstId] = NULL;
+               g_sngisdn_data.ccs[signal_data->cc_id].active_suInstIds[sngisdn_info->glare.suInstId] = NULL;
+#endif
+
+       } else {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Call was already released (suId:%d suInstId:%u spInstId:%u)\n",
+                                                               signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
+       }
+       ftdm_mutex_unlock(ftdmchan->mutex);
+       return;
+}
+
+void sngisdn_delayed_connect(void* p_sngisdn_info)
+{
+       sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;       
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;  
 
+       ftdm_mutex_lock(ftdmchan->mutex);
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed CONNECT (suId:%d suInstId:%u spInstId:%u)\n",
+                                                               signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
 
-ftdm_status_t check_for_state_change(ftdm_channel_t *ftdmchan)
+       sngisdn_snd_connect(ftdmchan);
+       ftdm_mutex_unlock(ftdmchan->mutex);
+       return;
+}
+
+void sngisdn_delayed_disconnect(void* p_sngisdn_info)
 {
+       sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;       
+       ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;  
 
-#if 0
-    ftdm_log_chan_msg(ftdmchan, "Checking for pending state change\n");
-#endif
-    /* check to see if there are any pending state changes on the channel and give them a sec to happen*/
-    ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 5000);
+       ftdm_mutex_lock(ftdmchan->mutex);
+       if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n",
+                                                                       signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
 
-    /* check the flag to confirm it is clear now */
-    if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
-        /* the flag is still up...so we have a problem */
-               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "FTDM_CHANNEL_STATE_CHANGE set for over 500ms\n");
+               sngisdn_snd_disconnect(ftdmchan);
+       }
 
-        /* move the state of the channel to RESTART to force a reset */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+       ftdm_mutex_unlock(ftdmchan->mutex);
+       return;
+}
 
-        return FTDM_FAIL;
-    }
-    return FTDM_SUCCESS;
+ftdm_status_t sngisdn_check_free_ids(void)
+{
+       unsigned i;
+       unsigned j;
+       ftdm_log(FTDM_LOG_INFO, "Checking suInstId's\n");
+       for(j=1;j<=MAX_VARIANTS;j++) {
+               if (g_sngisdn_data.ccs[j].config_done) {
+                       for(i=1;i<MAX_INSTID;i++) {
+                               if (g_sngisdn_data.ccs[j].active_suInstIds[i] != NULL) {
+                                       ftdm_log(FTDM_LOG_INFO, "suId:%u suInstId:%u is not free\n", j, i);
+                                       
+
+                               }
+                       }
+               }
+       }
+
+       ftdm_log(FTDM_LOG_INFO, "Checking spInstId's\n");
+       for(j=1;j<=MAX_VARIANTS;j++) {
+               if (g_sngisdn_data.ccs[j].config_done) {
+                       for(i=1;i<MAX_INSTID;i++) {
+                               if (g_sngisdn_data.ccs[j].active_spInstIds[i] != NULL) {
+                                       ftdm_log(FTDM_LOG_INFO, "suId:%u spInstId:%u is not free\n", j, i);
+                                       
+
+                               }
+                       }
+               }
+       }
+       ftdm_log(FTDM_LOG_INFO, "Checking ID's done\n");
+       return FTDM_SUCCESS;
 }
 
 void get_memory_info(void)
@@ -339,6 +473,7 @@ void get_memory_info(void)
        return;
 }
 
+
 /* For Emacs:
  * Local Variables:
  * mode:c
index 0084704322982983d304ddfa0ea9bed9942c945a..7d4d347eabe7e63d48787f2899bbe87d7e3fc6aa 100644 (file)
@@ -205,7 +205,7 @@ void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len)
                i=i+1;
                c=c+1;
        }
-       str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Origination");
+       str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Originating");
 
        /* Decode message type */
        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));
@@ -337,7 +337,7 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
                                }
                                
                                if (numberMap) {
-                                       *str_len+= sprintf(&str[*str_len], " MAP\n");
+                                       *str_len+= sprintf(&str[*str_len], " MAP:%s ", get_code_2_str(infoChannelSelection, dcodQ931InfoChannelSelTable));
                                } else {
                                        *str_len+= sprintf(&str[*str_len], "No:%d ", channelNo);
                                }
@@ -608,6 +608,9 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
                        break;
                case PROT_Q931_IE_SENDING_COMPLETE:
                        /* No need to decode sending complete IE, as no additional info is available except that sending is done */
+                       /* This is a single octet IE */
+                       *str_len+= sprintf(&str[*str_len], "\n");
+                       return 0;
                        break;
                case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS:
                case PROT_Q931_IE_REDIRECTION_NUMBER:
index 869b235f2a1fdc8b133cf3f60e42e0fc91f8c1ee..d210c50db9d0c04a4b02a13aa58bd2224d1270d1 100644 (file)
@@ -373,6 +373,14 @@ struct code2str dcodQ931ScreeningTable[] = {
        {-1, "invalid" },
 };
 
+struct code2str dcodQ931InfoChannelSelTable[] = {
+       {0, "No Chan"},
+       {1, "B1"},
+       {2, "B2"},
+       {3, "Any Chan"},
+       {-1, "invalid" },
+};
+
 struct code2str dcodQ931ReasonTable[] = {
        {0x0, "Unknown"},
        {0x1, "Call forwarding busy"},
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
new file mode 100644 (file)
index 0000000..c8c8bc3
--- /dev/null
@@ -0,0 +1,1448 @@
+/*
+ * Copyright (c) 2009|Konrad Hammel <konrad@sangoma.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms|with or without
+ * modification|are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice|this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice|this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
+ * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
+ * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* INCLUDE ********************************************************************/
+#include "ftmod_sangoma_ss7_main.h"
+/******************************************************************************/
+
+/* DEFINES ********************************************************************/
+/******************************************************************************/
+
+/* GLOBALS ********************************************************************/
+/******************************************************************************/
+
+/* PROTOTYPES *****************************************************************/
+int ft_to_sngss7_cfg_all(void);
+
+int ftmod_ss7_mtp1_gen_config(void);
+int ftmod_ss7_mtp2_gen_config(void);
+int ftmod_ss7_mtp3_gen_config(void);
+int ftmod_ss7_isup_gen_config(void);
+int ftmod_ss7_cc_gen_config(void);
+
+int ftmod_ss7_mtp1_psap_config(int id);
+
+int ftmod_ss7_mtp2_dlsap_config(int id);
+
+int ftmod_ss7_mtp3_dlsap_config(int id);
+int ftmod_ss7_mtp3_nsap_config(int id);
+int ftmod_ss7_mtp3_linkset_config(int id);
+int ftmod_ss7_mtp3_route_config(int id);
+
+int ftmod_ss7_isup_nsap_config(int id);
+int ftmod_ss7_isup_intf_config(int id);
+int ftmod_ss7_isup_ckt_config(int id);
+int ftmod_ss7_isup_isap_config(int id);
+
+int ftmod_ss7_cc_isap_config(int id);
+/******************************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+int  ft_to_sngss7_cfg_all(void)
+{
+       int x = 0;
+
+       /* check if we have done gen_config already */
+       if (!(g_ftdm_sngss7_data.gen_config)) {
+
+               if (sng_validate_license(g_ftdm_sngss7_data.cfg.license,
+                                                                g_ftdm_sngss7_data.cfg.signature,
+                                                                g_ftdm_sngss7_data.cfg.spc)) {
+
+                       SS7_CRITICAL("License verification failed..ending!\n");
+                       return 1;
+               }
+
+               if (ftmod_ss7_mtp1_gen_config()) {
+                       SS7_CRITICAL("MTP1 General configuration FAILED!\n");
+                       SS7_ASSERT
+               } else {
+                       SS7_INFO("MTP1 General configuration DONE\n");
+               }
+
+               if (ftmod_ss7_mtp2_gen_config()) {
+                       SS7_CRITICAL("MTP2 General configuration FAILED!\n");
+                       SS7_ASSERT
+               } else {
+                       SS7_INFO("MTP2 General configuration DONE\n");
+               }
+
+               if (ftmod_ss7_mtp3_gen_config()) {
+                       SS7_CRITICAL("MTP3 General configuration FAILED!\n");
+                       SS7_ASSERT
+               } else {
+                       SS7_INFO("MTP3 General configuration DONE\n");
+               }
+
+               if (ftmod_ss7_isup_gen_config()) {
+                       SS7_CRITICAL("ISUP General configuration FAILED!\n");
+                       SS7_ASSERT
+               } else {
+                       SS7_INFO("ISUP General configuration DONE\n");
+               }
+
+               if (ftmod_ss7_cc_gen_config()) {
+                       SS7_CRITICAL("CC General configuration FAILED!\n");
+                       SS7_ASSERT
+               } else {
+                       SS7_INFO("CC General configuration DONE\n");
+               }
+
+               /* update the global gen_config so we don't do it again */
+               g_ftdm_sngss7_data.gen_config = 1;
+       }
+
+
+       x = 1;
+       while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
+               /* check if this link has been configured already */
+               if (!(g_ftdm_sngss7_data.cfg.mtpLink[x].flags & CONFIGURED)) {
+
+                       /* configure mtp1 */
+                       if (ftmod_ss7_mtp1_psap_config(x)) {
+                               SS7_CRITICAL("MTP1 PSAP %d configuration FAILED!\n", x);
+                               SS7_ASSERT;
+                       } else {
+                               SS7_INFO("MTP1 PSAP %d configuration DONE!\n", x);
+                       }
+
+                       /* configure mtp2 */
+                       if (ftmod_ss7_mtp2_dlsap_config(x)) {
+                               SS7_CRITICAL("MTP2 DLSAP %d configuration FAILED!\n",x);
+                               SS7_ASSERT;
+                       } else {
+                               SS7_INFO("MTP2 DLSAP %d configuration DONE!\n", x);
+                       }
+
+                       /* configure mtp3 */
+                       if (ftmod_ss7_mtp3_dlsap_config(x)) {
+                               SS7_CRITICAL("MTP3 DLSAP %d configuration FAILED!\n", x);
+                               SS7_ASSERT;
+                       } else {
+                               SS7_INFO("MTP3 DLSAP %d configuration DONE!\n", x);
+                       }
+
+                       /* set the CONFIGURED flag */
+                       g_ftdm_sngss7_data.cfg.mtpLink[x].flags |= CONFIGURED;
+               }
+               
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) */
+
+       x = 1;
+       while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) {
+               /* check if this link has been configured already */
+               if (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & CONFIGURED)) {
+
+                       if (ftmod_ss7_mtp3_nsap_config(x)) {
+                               SS7_CRITICAL("MTP3 NSAP %d configuration FAILED!\n", x);
+                               SS7_ASSERT
+                       } else {
+                               SS7_INFO("MTP3 NSAP %d configuration DONE!\n", x);
+                       }
+
+                       if (ftmod_ss7_isup_nsap_config(x)) {
+                               SS7_CRITICAL("ISUP NSAP %d configuration FAILED!\n", x);
+                               SS7_ASSERT
+                       } else {
+                               SS7_INFO("ISUP NSAP %d configuration DONE!\n", x);
+                       }
+
+                       /* set the CONFIGURED flag */
+                       g_ftdm_sngss7_data.cfg.nsap[x].flags |= CONFIGURED;
+               } /* if !CONFIGURED */
+               
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) */
+
+       x = 1;
+       while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) {
+               /* check if this link has been configured already */
+               if (!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & CONFIGURED)) {
+
+                       if (ftmod_ss7_mtp3_linkset_config(x)) {
+                               SS7_CRITICAL("MTP3 LINKSET %d configuration FAILED!\n", x);
+                               SS7_ASSERT
+                       } else {
+                               SS7_INFO("MTP3 LINKSET %d configuration DONE!\n", x);
+                       }
+
+                       /* set the CONFIGURED flag */
+                       g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= CONFIGURED;
+               } /* if !CONFIGURED */
+               
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) */
+
+       x = 1;
+       while ((g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0)) {
+               /* check if this link has been configured already */
+               if (!(g_ftdm_sngss7_data.cfg.mtpRoute[x].flags & CONFIGURED)) {
+
+                       if (ftmod_ss7_mtp3_route_config(x)) {
+                               SS7_CRITICAL("MTP3 ROUTE %d configuration FAILED!\n", x);
+                               SS7_ASSERT
+                       } else {
+                               SS7_INFO("MTP3 ROUTE %d configuration DONE!\n");
+                       }
+
+                       /* set the CONFIGURED flag */
+                       g_ftdm_sngss7_data.cfg.mtpRoute[x].flags |= CONFIGURED;
+               } /* if !CONFIGURED */
+               
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) */
+
+       if (!(g_ftdm_sngss7_data.cfg.mtpRoute[0].flags & CONFIGURED)) {
+
+               if (ftmod_ss7_mtp3_route_config(0)) {
+                       SS7_CRITICAL("MTP3 ROUTE 0 configuration FAILED!\n");
+                       SS7_ASSERT
+               } else {
+                       SS7_INFO("MTP3 ROUTE %d configuration DONE!\n");
+               }
+
+               /* set the CONFIGURED flag */
+               g_ftdm_sngss7_data.cfg.mtpRoute[0].flags |= CONFIGURED;
+       } /* if !CONFIGURED */
+
+
+       x = 1;
+       while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) {
+               /* check if this link has been configured already */
+               if (!(g_ftdm_sngss7_data.cfg.isap[x].flags & CONFIGURED)) {
+                       
+                       if (ftmod_ss7_isup_isap_config(x)) {
+                               SS7_CRITICAL("ISUP ISAP %d configuration FAILED!\n", x);
+                               SS7_ASSERT
+                       } else {
+                               SS7_INFO("ISUP ISAP %d configuration DONE!\n", x);
+                       }
+
+                       if (ftmod_ss7_cc_isap_config(x)) {
+                               SS7_CRITICAL("CC ISAP %d configuration FAILED!\n", x);
+                               SS7_ASSERT
+                       } else {
+                               SS7_INFO("CC ISAP %d configuration DONE!\n", x);
+                       }
+
+                       /* set the CONFIGURED flag */
+                       g_ftdm_sngss7_data.cfg.isap[x].flags |= CONFIGURED;
+               } /* if !CONFIGURED */
+               
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) */
+
+       x = 1;
+       while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) {
+               /* check if this link has been configured already */
+               if (!(g_ftdm_sngss7_data.cfg.isupIntf[x].flags & CONFIGURED)) {
+
+                       if (ftmod_ss7_isup_intf_config(x)) {
+                               SS7_CRITICAL("ISUP INTF %d configuration FAILED!\n", x);
+                               SS7_ASSERT
+                       } else {
+                               SS7_INFO("ISUP INTF %d configuration DONE!\n", x);
+                       }
+
+                       /* set the CONFIGURED flag */
+                       g_ftdm_sngss7_data.cfg.isupIntf[x].flags |= CONFIGURED;
+               } /* if !CONFIGURED */
+               
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) */
+
+       x = 1;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+               /* check if this link has been configured already */
+               if (!(g_ftdm_sngss7_data.cfg.isupCkt[x].flags & CONFIGURED)) {
+                       if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == 0) {
+                               if (ftmod_ss7_isup_ckt_config(x)) {
+                                       SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", x);
+                                       SS7_ASSERT
+                               } else {
+                                       SS7_INFO("ISUP CKT %d configuration DONE!\n", x);
+                               }
+                       }
+
+                       /* set the CONFIGURED flag */
+                       g_ftdm_sngss7_data.cfg.isupCkt[x].flags |= CONFIGURED;
+               } /* if !CONFIGURED */
+               
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
+
+       return 0;
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp1_gen_config(void)
+{
+       L1Mngmt cfg;    /*configuration structure*/
+       Pst             pst;    /*post structure*/
+       
+       /* initalize the post structure */
+       smPstInit(&pst);
+       
+       /* insert the destination Entity */
+       pst.dstEnt = ENTL1;
+       
+       /* clear the configuration structure */
+       memset(&cfg, 0x0, sizeof(L1Mngmt));
+       
+       /* fill in some general sections of the header */
+       smHdrInit(&cfg.hdr);
+
+       /* fill in the post structure */
+       smPstInit( &cfg.t.cfg.s.l1Gen.sm );
+       
+       /*fill in the specific fields of the header */
+       cfg.hdr.msgType                                 = TCFG;
+       cfg.hdr.entId.ent                               = ENTL1;
+       cfg.hdr.entId.inst                              = S_INST;
+       cfg.hdr.elmId.elmnt                     = STGEN;
+
+       cfg.t.cfg.s.l1Gen.sm.srcEnt             = ENTL1;
+       cfg.t.cfg.s.l1Gen.sm.dstEnt             = ENTSM;
+       
+       cfg.t.cfg.s.l1Gen.nmbLnks               = MAX_L1_LINKS;
+       cfg.t.cfg.s.l1Gen.poolTrUpper   = POOL_UP_TR;           /* upper pool threshold */
+       cfg.t.cfg.s.l1Gen.poolTrLower   = POOL_LW_TR;           /* lower pool threshold */
+
+       return(sng_cfg_mtp1(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp2_gen_config(void)
+{
+       SdMngmt cfg;
+       Pst             pst;
+       
+       /* initalize the post structure */
+       smPstInit(&pst);
+       
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSD;
+       
+       /* clear the configuration structure */
+       memset(&cfg, 0x0, sizeof(SdMngmt));
+       
+       /* fill in some general sections of the header */
+       smHdrInit(&cfg.hdr);
+
+       /* fill in the post structure */
+       smPstInit( &cfg.t.cfg.s.sdGen.sm );
+       
+       /* fill in the specific fields of the header */
+       cfg.hdr.msgType                                 = TCFG;
+       cfg.hdr.entId.ent                               = ENTSD;
+       cfg.hdr.entId.inst                              = S_INST;
+       cfg.hdr.elmId.elmnt                             = STGEN;
+       
+       cfg.t.cfg.s.sdGen.sm.srcEnt             = ENTSD;
+       cfg.t.cfg.s.sdGen.sm.dstEnt             = ENTSM;
+       
+       cfg.t.cfg.s.sdGen.nmbLnks               = MAX_SD_LINKS;
+       cfg.t.cfg.s.sdGen.poolTrUpper   = POOL_UP_TR;
+       cfg.t.cfg.s.sdGen.poolTrLower   = POOL_LW_TR;
+
+       return(sng_cfg_mtp2(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp3_gen_config(void)
+{
+       SnMngmt cfg;
+       Pst             pst;
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSN;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(SnMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /* fill in the post structure */
+       smPstInit(&cfg.t.cfg.s.snGen.sm);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                 = TCFG;
+       cfg.hdr.entId.ent                               = ENTSN;
+       cfg.hdr.entId.inst                              = S_INST;
+       cfg.hdr.elmId.elmnt                     = STGEN;
+
+       cfg.t.cfg.s.snGen.sm.srcEnt             = ENTSN;
+       cfg.t.cfg.s.snGen.sm.dstEnt             = ENTSM;
+
+
+       cfg.t.cfg.s.snGen.typeSP                = LSN_TYPE_SP;          /* type of signalling postatic int */
+       cfg.t.cfg.s.snGen.spCode1               = g_ftdm_sngss7_data.cfg.spc;   /* our DPC for CCITT version */
+
+#if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA || defined(TDS_ROLL_UPGRADE_SUPPORT))
+       cfg.t.cfg.s.snGen.spCode2               = g_ftdm_sngss7_data.cfg.spc;   /* our DPC for ANSI or CHINA version */
+#endif
+
+       cfg.t.cfg.s.snGen.ssfValid              = TRUE;                         /* ssf validation required */
+       cfg.t.cfg.s.snGen.nmbDLSap              = MAX_SN_LINKS;         /* number of MTP Data Link SAPs */
+       cfg.t.cfg.s.snGen.nmbNSap               = MAX_SN_VARIANTS;      /* number of Upper Layer Saps */
+       cfg.t.cfg.s.snGen.nmbRouts              = MAX_SN_ROUTES;        /* maximum number of routing entries */
+       cfg.t.cfg.s.snGen.nmbLnkSets    = MAX_SN_LINKSETS;      /* number of link sets */
+       cfg.t.cfg.s.snGen.nmbRteInst    = MAX_SN_ROUTES*16;     /* number of simultaneous Rte instances */
+       cfg.t.cfg.s.snGen.cbTimeRes             = SN_CB_PERIOD;         /* link time resolution */
+       cfg.t.cfg.s.snGen.spTimeRes             = SN_SP_PERIOD;         /* general time resolution */
+       cfg.t.cfg.s.snGen.rteTimeRes    = SN_RTE_PERIOD;        /* route time resolution */
+       cfg.t.cfg.s.snGen.extCmbndLnkst = FALSE;                        /* enbale extended combined linkset feature */
+
+#if (defined(LSNV3) || defined(SN_MULTIPLE_NETWORK_RESTART))
+
+#else
+       cfg.t.cfg.s.snGen.rstReq                = LSN_NO_RST;           /* restarting procedure required */
+       cfg.t.cfg.s.snGen.tfrReq                = FALSE;                        /* TFR procedure required or not */
+       cfg.t.cfg.s.snGen.tmr.t15.enb   = TRUE;                         /* t15 - waiting to start route set congestion test */
+       cfg.t.cfg.s.snGen.tmr.t15.val   = 30;
+       cfg.t.cfg.s.snGen.tmr.t16.enb   = TRUE;                         /* t16 - waiting for route set congestion status update */
+       cfg.t.cfg.s.snGen.tmr.t16.val   = 20;
+       cfg.t.cfg.s.snGen.tmr.t18.enb   = TRUE;                         /* t18 - waiting for links to become available */
+       cfg.t.cfg.s.snGen.tmr.t18.val   = 200;
+       cfg.t.cfg.s.snGen.tmr.t19.enb   = TRUE;                         /* t19 - waiting to receive all traffic restart allowed */
+       cfg.t.cfg.s.snGen.tmr.t19.val   = 690;
+       cfg.t.cfg.s.snGen.tmr.t21.enb   = TRUE;                         /* t21 - waiting to restart traffic routed through adjacent SP */
+       cfg.t.cfg.s.snGen.tmr.t21.val   = 650;
+# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT))
+       cfg.t.cfg.s.snGen.t26.enb               = TRUE;                         /* t26 - waiting to repeat traffic restart waiting message for ANSI */
+       cfg.t.cfg.s.snGen.t26.val               = 600;
+# endif
+#endif
+
+#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS96)
+       cfg.t.cfg.s.snGen.mopc                  = FALSE;
+#endif
+
+       return(sng_cfg_mtp3(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_isup_gen_config(void)
+{
+       SiMngmt  cfg;
+       Pst              pst;
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSI;
+
+       /* clear the configuration structure */
+       memset(&cfg, 0x0, sizeof(SiMngmt));
+
+       /* fill in some general sections of the header */
+       smHdrInit(&cfg.hdr);
+
+       /* fill in the post structure */
+       smPstInit( &cfg.t.cfg.s.siGen.sm );
+
+       /*fill in the specific fields of the header */
+       cfg.hdr.msgType                                         = TCFG;
+       cfg.hdr.entId.ent                                       = ENTSI;
+       cfg.hdr.entId.inst                                      = S_INST;
+       cfg.hdr.elmId.elmnt                             = STGEN;
+
+       cfg.t.cfg.s.siGen.sm.srcEnt                     = ENTSI;
+       cfg.t.cfg.s.siGen.sm.dstEnt                     = ENTSM;
+
+       cfg.t.cfg.s.siGen.nmbSaps                       = MAX_CC_INTERFACE;             /* Number of ISUP Saps */
+       cfg.t.cfg.s.siGen.nmbNSaps                      = MAX_SN_INTERFACE;             /* Number of Network Saps */
+       cfg.t.cfg.s.siGen.nmbCir                        = MAX_SI_CIRCUITS;              /* Number of circuits */
+       cfg.t.cfg.s.siGen.nmbIntf                       = MAX_SI_INTERFACES;    /* Number of interfaces */
+       cfg.t.cfg.s.siGen.nmbCirGrp                     = MAX_SI_CIR_GRP;               /* Max number of circuit groups */
+       cfg.t.cfg.s.siGen.nmbCalRef                     = MAX_SI_CALL_REF;              /* Number of Call References */
+       cfg.t.cfg.s.siGen.timeRes                       = SI_PERIOD;                    /* time resolution */
+       cfg.t.cfg.s.siGen.sccpSup                       = FALSE;                                /* SCCP support */
+       cfg.t.cfg.s.siGen.handleTTBinCC         = FALSE;                                /* Flag used for controlling TTB feature */
+       cfg.t.cfg.s.siGen.mapCPCandFCI          = TRUE;                                 /* Flag used for controlling TTB feature */
+#if (LSIV3 || LSIV4 || LSIV5)
+       cfg.t.cfg.s.siGen.lnkSelOpt                     = SI_LINK_SELECTION;    /* link selector option */
+#endif  
+       cfg.t.cfg.s.siGen.poolTrUpper           = POOL_UP_TR;                   /* upper pool threshold */
+       cfg.t.cfg.s.siGen.poolTrLower           = POOL_LW_TR;                   /* lower pool threshold */
+       cfg.t.cfg.s.siGen.cirGrTmr.t18.enb      = TRUE;                                 /* t18 timer - group blocking sent */
+       cfg.t.cfg.s.siGen.cirGrTmr.t18.val      = 300;
+       cfg.t.cfg.s.siGen.cirGrTmr.t19.enb      = TRUE;                                 /* t19 timer - initial group blocking sent */
+       cfg.t.cfg.s.siGen.cirGrTmr.t19.val      = 3000;
+       cfg.t.cfg.s.siGen.cirGrTmr.t20.enb      = TRUE;                                 /* t20 timer - group unblocking sent */
+       cfg.t.cfg.s.siGen.cirGrTmr.t20.val      = 300;
+       cfg.t.cfg.s.siGen.cirGrTmr.t21.enb      = TRUE;                                 /* t21 timer - initial grp unblocking sent */
+       cfg.t.cfg.s.siGen.cirGrTmr.t21.val      = 3000;
+       cfg.t.cfg.s.siGen.cirGrTmr.t22.enb      = TRUE;                                 /* t22 timer - group reset sent */
+       cfg.t.cfg.s.siGen.cirGrTmr.t22.val      = 300;
+       cfg.t.cfg.s.siGen.cirGrTmr.t23.enb      = TRUE;                                 /* t23 timer - initial group reset sent */
+       cfg.t.cfg.s.siGen.cirGrTmr.t23.val      = 3000;
+#ifndef SS7_UK
+       cfg.t.cfg.s.siGen.cirGrTmr.t28.enb      = TRUE;                                 /* t28 timer - circuit group query sent */
+       cfg.t.cfg.s.siGen.cirGrTmr.t28.val      = 100;
+#endif
+#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL)
+       cfg.t.cfg.s.siGen.cirGrTmr.tFGR.enb = TRUE;                                     /* first group received timer */
+       cfg.t.cfg.s.siGen.cirGrTmr.tFGR.val = 50;
+#endif
+#if CGPN_CHK
+       cfg.t.cfg.s.siGen.cgPtyNumGenCfg        = TRUE;                                 /* Calling party number general config flag */
+#endif
+#ifdef SI_SUPPRESS_CFN
+       cfg.t.cfg.s.siGen.suppressCfn           = TRUE;                                 /* Flag used for 'suppress CFN' feature */
+#endif
+
+       return(sng_cfg_isup(&pst, &cfg));
+
+}
+
+/******************************************************************************/
+int ftmod_ss7_cc_gen_config(void)
+{
+       CcMngmt cfg;
+       Pst              pst;
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTCC;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(CcMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /* fill in the post structure */
+       smPstInit( &cfg.t.cfg.s.ccGen.sm );
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                 = TCFG;
+       cfg.hdr.entId.ent                               = ENTCC;
+       cfg.hdr.entId.inst                              = S_INST;
+       cfg.hdr.elmId.elmnt                     = STGEN;
+
+       cfg.t.cfg.s.ccGen.sm.srcEnt             = ENTCC;
+       cfg.t.cfg.s.ccGen.sm.dstEnt             = ENTSM;
+
+       cfg.t.cfg.s.ccGen.poolTrUpper   = POOL_UP_TR;           /* upper pool threshold */
+       cfg.t.cfg.s.ccGen.poolTrLower   = POOL_LW_TR;           /* lower pool threshold */
+
+       return(sng_cfg_cc(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp1_psap_config(int id)
+{
+       L1Mngmt                 cfg;
+       Pst                             pst;
+       sng_mtp_link_t  *k = &g_ftdm_sngss7_data.cfg.mtpLink[id];
+       
+       /* initalize the post structure */
+       smPstInit(&pst);
+       
+       /* insert the destination Entity */
+       pst.dstEnt = ENTL1;
+       
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(L1Mngmt));
+       
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+       
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                         = TCFG;
+       cfg.hdr.entId.ent                       = ENTL1;
+       cfg.hdr.entId.inst                      = S_INST;
+       cfg.hdr.elmId.elmnt             = STPSAP;
+       
+       cfg.hdr.elmId.elmntInst1        = k->id;
+       
+       cfg.t.cfg.s.l1PSAP.span         = k->mtp1.span;
+       cfg.t.cfg.s.l1PSAP.chan         = k->mtp1.chan;
+       cfg.t.cfg.s.l1PSAP.spId         = k->id;
+
+       return(sng_cfg_mtp1(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp2_dlsap_config(int id)
+{
+       SdMngmt cfg;
+       Pst             pst;
+       sng_mtp_link_t  *k = &g_ftdm_sngss7_data.cfg.mtpLink[id];
+
+       /* initalize the post structure */
+       smPstInit( &pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSD;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(SdMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                         = TCFG;
+       cfg.hdr.entId.ent                                       = ENTSD;
+       cfg.hdr.entId.inst                                      = S_INST;
+       cfg.hdr.elmId.elmnt                             = STDLSAP;
+
+       cfg.hdr.elmId.elmntInst1                        = k->id;
+
+       cfg.t.cfg.s.sdDLSAP.mem.region          = S_REG;                                        /* memory region */
+       cfg.t.cfg.s.sdDLSAP.mem.pool            = S_POOL;                                       /* memory pool */
+       cfg.t.cfg.s.sdDLSAP.swtch                       = k->mtp2.linkType;                     /* protocol type */
+       cfg.t.cfg.s.sdDLSAP.priorDl                     = PRIOR0;                                       /* priority for data link layer */
+       cfg.t.cfg.s.sdDLSAP.routeDl                     = RTESPEC;                                      /* route for data link layer */
+       cfg.t.cfg.s.sdDLSAP.selectorDl          = 0;                                            /* upper interface selector */
+       cfg.t.cfg.s.sdDLSAP.dstProcId           = SFndProcId();                         /* the procid of MAC/L1/MTP1 */
+       cfg.t.cfg.s.sdDLSAP.entMac                      = ENTL1;                                        /* entity for MAC */
+       cfg.t.cfg.s.sdDLSAP.instMac                     = S_INST;                                       /* instance for MAC */
+       cfg.t.cfg.s.sdDLSAP.priorMac            = PRIOR0;                                       /* priority for MAC layer */
+       cfg.t.cfg.s.sdDLSAP.routeMac            = RTESPEC;                                      /* route for MAC layer */
+       cfg.t.cfg.s.sdDLSAP.selectorMac         = 0;                                            /* lower interface selector */
+       cfg.t.cfg.s.sdDLSAP.memMac.region       = S_REG;                                        /* memory region and pool id for MAC */
+       cfg.t.cfg.s.sdDLSAP.memMac.pool         = S_POOL;
+       cfg.t.cfg.s.sdDLSAP.maxOutsFrms         = MAX_SD_OUTSTANDING;           /* maximum outstanding frames */
+       cfg.t.cfg.s.sdDLSAP.errType                     = SD_ERR_NRM;
+       cfg.t.cfg.s.sdDLSAP.t1.enb                      = TRUE;                                         /* timer 1 - Alignment Ready Timer */
+       cfg.t.cfg.s.sdDLSAP.t1.val                      = k->mtp2.t1;
+       cfg.t.cfg.s.sdDLSAP.t2.enb                      = TRUE;                                         /* timer 2 - Not Aligned Timer */
+       cfg.t.cfg.s.sdDLSAP.t2.val                      = k->mtp2.t2;
+       cfg.t.cfg.s.sdDLSAP.t3.enb                      = TRUE;                                         /* timer 3 - Aligned Timer */
+       cfg.t.cfg.s.sdDLSAP.t3.val                      = k->mtp2.t3;
+       cfg.t.cfg.s.sdDLSAP.t5.enb                      = TRUE;                                         /* timer 5 - Sending SIB timer */
+       cfg.t.cfg.s.sdDLSAP.t5.val                      = k->mtp2.t5;
+       cfg.t.cfg.s.sdDLSAP.t6.enb                      = TRUE;                                         /* timer 6 - Remote Congestion Timer */
+       cfg.t.cfg.s.sdDLSAP.t6.val                      = k->mtp2.t6;
+       cfg.t.cfg.s.sdDLSAP.t7.enb                      = TRUE;                                         /* timer 7 - Excessive delay of acknowledgement timer */
+       cfg.t.cfg.s.sdDLSAP.t7.val                      = k->mtp2.t7;
+       cfg.t.cfg.s.sdDLSAP.provEmrgcy          = k->mtp2.t4e;                          /* emergency proving period */
+       cfg.t.cfg.s.sdDLSAP.provNormal          = k->mtp2.t4n;                          /* normal proving period */
+       cfg.t.cfg.s.sdDLSAP.lssuLen                     = k->mtp2.lssuLength;                   /* one or two byte LSSU length */
+       cfg.t.cfg.s.sdDLSAP.maxFrmLen           = MAX_SD_FRAME_LEN;                     /* max frame length for MSU */
+       cfg.t.cfg.s.sdDLSAP.congDisc            = FALSE;                                        /* congestion discard TRUE or FALSE */
+       cfg.t.cfg.s.sdDLSAP.sdT                         = MAX_SD_SUERM;                         /* SUERM error rate threshold */
+       cfg.t.cfg.s.sdDLSAP.sdTie                       = MAX_SD_AERM_EMERGENCY;        /* AERM emergency error rate threshold */
+       cfg.t.cfg.s.sdDLSAP.sdTin                       = MAX_SD_AERM_NORMAL;           /* AERM normal error rate threshold */
+       cfg.t.cfg.s.sdDLSAP.sdN1                        = MAX_SD_MSU_RETRANS;           /* maximum number of MSUs for retransmission */
+       cfg.t.cfg.s.sdDLSAP.sdN2                        = MAX_SD_OCTETS_RETRANS;        /* maximum number of MSU octets for retrans */
+       cfg.t.cfg.s.sdDLSAP.sdCp                        = MAX_SD_ALIGN_ATTEMPTS;        /* maximum number of alignment attempts */
+       cfg.t.cfg.s.sdDLSAP.spIdSE                      = k->mtp2.mtp1Id;                               /* service provider id */
+       cfg.t.cfg.s.sdDLSAP.sdtFlcStartTr       = 256;                                          /* SDT interface flow control start thresh */
+       cfg.t.cfg.s.sdDLSAP.sdtFlcEndTr         = 512;                                          /* SDT interface flow control end thresh */
+
+#ifdef SD_HSL
+       cfg.t.cfg.s.sdDLSAP.sapType                     =;                                                      /* Indcates whether link is HSL or LSL */
+       cfg.t.cfg.s.sdDLSAP.sapFormat           =;                                                      /* The extened sequence no to be used or not */
+       cfg.t.cfg.s.sdDLSAP.t8.enb                      =;                                                      /* timer 8 configuration structure */
+       cfg.t.cfg.s.sdDLSAP.sdTe                        =;                                                      /* EIM threshold */
+       cfg.t.cfg.s.sdDLSAP.sdUe                        =;                                                      /* increment constant */
+       cfg.t.cfg.s.sdDLSAP.sdDe                        =;                                                      /* decrement constant */
+#endif /* HIGH_SPEED_SIGNALING_SUPPORT */
+
+#if (SS7_TTC || SS7_NTT)
+       cfg.t.cfg.s.sdDLSAP.numRtb                      =;                                                      /* outstanding number of messages in RTB */
+       cfg.t.cfg.s.sdDLSAP.tf                          =;                                                      /* FISU transmission interval */
+       cfg.t.cfg.s.sdDLSAP.tfv                         =;                                                      /* FISU transmission interval during verification */
+       cfg.t.cfg.s.sdDLSAP.to                          =;                                                      /* SIO transmission interval */
+       cfg.t.cfg.s.sdDLSAP.ta                          =;                                                      /* SIE transmission interval */
+       cfg.t.cfg.s.sdDLSAP.ts                          =;                                                      /* SIOS transmission interval */
+       cfg.t.cfg.s.sdDLSAP.tso                         =;                                                      /* SIOS transmission duration when out of service */
+       cfg.t.cfg.s.sdDLSAP.te                          =;                                                      /* SU normalization time */
+#endif /* (SS7_TTC || SS7_NTT) */
+
+#if (SS7_NTT)          /* NTTT - Q.703 */
+       cfg.t.cfg.s.sdDLSAP.repMsuNack          =;                                                      /* Nack on receipt of repeated MSU */
+       cfg.t.cfg.s.sdDLSAP.invFibIgnore        =;                                                      /* invalid FIB ignore or bring the link down */
+       cfg.t.cfg.s.sdDLSAP.invBsnIgnore        =;                                                      /* invalid BSN ignore or bring the link down */
+       cfg.t.cfg.s.sdDLSAP.congAbatOnNack      =;                                                      /* congestion abatement on nack or only on acks */
+#endif /* (SS7_NTT) */
+
+#ifdef TDS_ROLL_UPGRADE_SUPPORT 
+       cfg.t.cfg.s.sdDLSAP.hlremIntfValid      = FALSE;                                        /* Upper Sap Version number valid ? */
+       cfg.t.cfg.s.sdDLSAP.remIntfVer          = SDTIFVER;                                     /* remote version info */
+#endif /*RUG*/
+
+       return(sng_cfg_mtp2(&pst, &cfg));
+       return 0;
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp3_dlsap_config(int id)
+{
+       Pst                             pst;
+       SnMngmt                 cfg;
+       sng_mtp_link_t  *k = &g_ftdm_sngss7_data.cfg.mtpLink[id];
+
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSN;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(SnMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                         = TCFG;
+       cfg.hdr.entId.ent                                       = ENTSN;
+       cfg.hdr.entId.inst                                      = S_INST;
+       cfg.hdr.elmId.elmnt                             = STDLSAP;
+
+       cfg.hdr.elmId.elmntInst1                        = k->id;
+
+       cfg.t.cfg.s.snDLSAP.lnkSetId            = k->mtp3.linkSetId;    /* link set ID */
+       cfg.t.cfg.s.snDLSAP.opc                         = k->mtp3.spc;                  /* Originating Postatic int Code */
+       cfg.t.cfg.s.snDLSAP.adjDpc                      = k->mtp3.apc;                  /* Adlacent Destination Postatic int Code */
+       cfg.t.cfg.s.snDLSAP.lnkPrior            = 0;                                    /* link priority within the link set */
+       cfg.t.cfg.s.snDLSAP.msgSize                     = MAX_SN_MSG_SIZE;              /* message length */
+       cfg.t.cfg.s.snDLSAP.msgPrior            = 0;                                    /* management message priority */
+       cfg.t.cfg.s.snDLSAP.lnkType                     = k->mtp3.linkType;             /* link type ANSI, ITU, BICI or CHINA */
+       cfg.t.cfg.s.snDLSAP.upSwtch                     = k->mtp3.switchType;   /* user part switch type */
+# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA)
+       cfg.t.cfg.s.snDLSAP.l2Type                      = LSN_MTP2_56KBPS;              /* layer 2 type - 56kbps MTP2 link, 1.536Mbps MTP2 link or QSAAL link */
+       cfg.t.cfg.s.snDLSAP.isCLink                     = FALSE;                                /* identifies if the link is a C type link.Required to check if sls has to be rotated.*/
+# endif
+       cfg.t.cfg.s.snDLSAP.maxSLTtry           = MAX_SLTM_RETRIES;             /* maximun times to retry SLTM */
+       cfg.t.cfg.s.snDLSAP.p0QLen                      = 32;                                   /* size of the priority 0 Q */
+       cfg.t.cfg.s.snDLSAP.p1QLen                      = 32;                                   /* size of the priority 1 Q */
+       cfg.t.cfg.s.snDLSAP.p2QLen                      = 32;                                   /* size of the priority 2 Q */
+       cfg.t.cfg.s.snDLSAP.p3QLen                      = 32;                                   /* size of the priority 3 Q */
+       cfg.t.cfg.s.snDLSAP.discPrior           = 0;                                    /* discard priority */
+#ifndef SDT2
+       cfg.t.cfg.s.snDLSAP.maxCredit           = MAX_SN_CREDIT;                /* max credit */
+#endif /* SDT2 */
+       cfg.t.cfg.s.snDLSAP.lnkId                       = 0;                                    /* signalling link allocation procedure identity */
+       cfg.t.cfg.s.snDLSAP.lnkTstSLC           = k->mtp3.slc;                  /* link selection code for link test */
+       cfg.t.cfg.s.snDLSAP.tstLen                      = 6;                                    /* link test pattern length */
+       cfg.t.cfg.s.snDLSAP.tst[0]                      = 'K';                                  /* link test pattern */
+       cfg.t.cfg.s.snDLSAP.tst[1]                      = 'O';                                  /* link test pattern */
+       cfg.t.cfg.s.snDLSAP.tst[2]                      = 'N';                                  /* link test pattern */
+       cfg.t.cfg.s.snDLSAP.tst[3]                      = 'R';                                  /* link test pattern */
+       cfg.t.cfg.s.snDLSAP.tst[4]                      = 'A';                                  /* link test pattern */
+       cfg.t.cfg.s.snDLSAP.tst[5]                      = 'D';                                  /* link test pattern */
+       cfg.t.cfg.s.snDLSAP.ssf                         = k->mtp3.ssf;                  /* sub service field */ 
+       cfg.t.cfg.s.snDLSAP.dstProcId           = SFndProcId();                 /* destination processor id */
+       cfg.t.cfg.s.snDLSAP.dstEnt                      = ENTSD;                                /* entity */
+       cfg.t.cfg.s.snDLSAP.dstInst                     = S_INST;                               /* instance */
+       cfg.t.cfg.s.snDLSAP.prior                       = PRIOR0;                               /* priority */
+       cfg.t.cfg.s.snDLSAP.route                       = RTESPEC;                              /* route */
+       cfg.t.cfg.s.snDLSAP.selector            = 0;                                    /* lower layer selector */
+       cfg.t.cfg.s.snDLSAP.mem.region          = S_REG;                                /* memory region id */
+       cfg.t.cfg.s.snDLSAP.mem.pool            = S_POOL;                               /* memory pool id */
+#if( SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA )
+       cfg.t.cfg.s.snDLSAP.dpcLen                      = DPC24;                                /* dpc length 24 bits */
+#else
+       cfg.t.cfg.s.snDLSAP.dpcLen                      = DPC14;                                /* dpc length 14 bits */
+#endif
+       cfg.t.cfg.s.snDLSAP.spId                        = k->mtp3.mtp2Id                ;/* service provider id */
+#if (SS7_ITU88 || SS7_CHINA || SS7_TTC || SS7_NTT || SS7_BICI )
+       cfg.t.cfg.s.snDLSAP.flushContFlag       = FALSE;                                /* flush continue handling */
+#else
+       cfg.t.cfg.s.snDLSAP.flushContFlag       = TRUE;                                 /* flush continue handling */
+#endif
+       cfg.t.cfg.s.snDLSAP.tmr.t1.enb          = TRUE;                                 /* t1 - delay to avoid missequencing on changeover */
+       cfg.t.cfg.s.snDLSAP.tmr.t1.val          = k->mtp3.t1;
+       cfg.t.cfg.s.snDLSAP.tmr.t2.enb          = TRUE;                                 /* t2 - waiting for changeover ack */
+       cfg.t.cfg.s.snDLSAP.tmr.t2.val          = k->mtp3.t2;
+       cfg.t.cfg.s.snDLSAP.tmr.t3.enb          = TRUE;                                 /* t3 - delay to avoid missequencing on changeback */
+       cfg.t.cfg.s.snDLSAP.tmr.t3.val          = k->mtp3.t3;
+       cfg.t.cfg.s.snDLSAP.tmr.t4.enb          = TRUE;                                 /* t4 - waiting for first changeback ack */
+       cfg.t.cfg.s.snDLSAP.tmr.t4.val          = k->mtp3.t4;
+       cfg.t.cfg.s.snDLSAP.tmr.t5.enb          = TRUE;                                 /* t5 - waiting for second changeback ack */
+       cfg.t.cfg.s.snDLSAP.tmr.t5.val          = k->mtp3.t5;
+       cfg.t.cfg.s.snDLSAP.tmr.t7.enb          = TRUE;                                 /* t7 - waiting for link connection ack */
+       cfg.t.cfg.s.snDLSAP.tmr.t7.val          = k->mtp3.t7;
+       cfg.t.cfg.s.snDLSAP.tmr.t12.enb         = TRUE;                                 /* t12 - waiting for uninhibit ack */
+       cfg.t.cfg.s.snDLSAP.tmr.t12.val         = k->mtp3.t12;
+       cfg.t.cfg.s.snDLSAP.tmr.t13.enb         = TRUE;                                 /* t13 - waiting for forced uninhibit */
+       cfg.t.cfg.s.snDLSAP.tmr.t13.val         = k->mtp3.t13;
+       cfg.t.cfg.s.snDLSAP.tmr.t14.enb         = TRUE;                                 /* t14 - waiting for inhibition ack */
+       cfg.t.cfg.s.snDLSAP.tmr.t14.val         = k->mtp3.t14;
+       cfg.t.cfg.s.snDLSAP.tmr.t17.enb         = TRUE;                                 /* t17 - delay to avoid oscillation of initial alignment failure */
+       cfg.t.cfg.s.snDLSAP.tmr.t17.val         = k->mtp3.t17;
+       cfg.t.cfg.s.snDLSAP.tmr.t22.enb         = TRUE;                                 /* t22 - local inhibit test timer */
+       cfg.t.cfg.s.snDLSAP.tmr.t22.val         = k->mtp3.t22;
+       cfg.t.cfg.s.snDLSAP.tmr.t23.enb         = TRUE;                                 /* t23 - remote inhibit test timer */
+       cfg.t.cfg.s.snDLSAP.tmr.t23.val         = k->mtp3.t23;
+       cfg.t.cfg.s.snDLSAP.tmr.t24.enb         = TRUE;                                 /* t24 - stabilizing timer */
+       cfg.t.cfg.s.snDLSAP.tmr.t24.val         = k->mtp3.t24;
+       cfg.t.cfg.s.snDLSAP.tmr.t31.enb         = TRUE;                                 /* t31 - BSN requested timer */
+       cfg.t.cfg.s.snDLSAP.tmr.t31.val         = k->mtp3.t31;
+       cfg.t.cfg.s.snDLSAP.tmr.t32.enb         = TRUE;                                 /* t32 - SLT timer */
+       cfg.t.cfg.s.snDLSAP.tmr.t32.val         = k->mtp3.t32;
+       cfg.t.cfg.s.snDLSAP.tmr.t33.enb         = TRUE;                                 /* t33 - connecting timer */
+       cfg.t.cfg.s.snDLSAP.tmr.t33.val         = k->mtp3.t33;
+       cfg.t.cfg.s.snDLSAP.tmr.t34.enb         = TRUE;                                 /* t34 - periodic signalling link test timer */
+       cfg.t.cfg.s.snDLSAP.tmr.t34.val         = k->mtp3.t34;
+#if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT))
+       cfg.t.cfg.s.snDLSAP.tmr.t35.enb         = TRUE;                                 /* t35 - false link congestion timer, same as t31 of ANSI'96*/
+       cfg.t.cfg.s.snDLSAP.tmr.t35.val         = k->mtp3.t35;
+       cfg.t.cfg.s.snDLSAP.tmr.t36.enb         = TRUE;                                 /* t36 - false link congestion timer, same as t33 of ANSI'96*/
+       cfg.t.cfg.s.snDLSAP.tmr.t36.val         = k->mtp3.t36;  
+       cfg.t.cfg.s.snDLSAP.tmr.t37.enb         = TRUE;                                 /* t37 - false link congestion timer, same as t34 of ANSI'96*/
+       cfg.t.cfg.s.snDLSAP.tmr.t37.val         = k->mtp3.t37;
+       cfg.t.cfg.s.snDLSAP.tmr.tCraft.enb      = TRUE;                                 /* link referral craft timer - T19 in ANSI */
+       cfg.t.cfg.s.snDLSAP.tmr.tCraft.val      = k->mtp3.tcraft;
+#endif
+#ifdef SDT2
+       cfg.t.cfg.s.snDLSAP.tmr.tFlc.enb        = TRUE;                                 /* flow control timer */
+       cfg.t.cfg.s.snDLSAP.tmr.tFlc.val        = 300;
+       cfg.t.cfg.s.snDLSAP.tmr.tBnd.enb        = TRUE;                                 /* bind request timer */
+       cfg.t.cfg.s.snDLSAP.tmr.tBnd.val        = 20;
+#endif /* SDT2 */
+#ifdef TDS_ROLL_UPGRADE_SUPPORT
+       cfg.t.cfg.s.snDLSAP.remIntfValid        = FALSE;                                /* remote interface version is valid */
+       cfg.t.cfg.s.snDLSAP.remIntfVer          = SNTIFVER;                             /* remote interface version */
+#endif
+
+       return(sng_cfg_mtp3(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp3_nsap_config(int id)
+{
+       Pst                     pst;
+       SnMngmt         cfg;
+       sng_nsap_t      *k = &g_ftdm_sngss7_data.cfg.nsap[id];
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSN;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(SnMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                 = TCFG;
+       cfg.hdr.entId.ent                               = ENTSN;
+       cfg.hdr.entId.inst                              = S_INST;
+       cfg.hdr.elmId.elmnt                     = STNSAP;
+
+       cfg.hdr.elmId.elmntInst1                = k->spId;
+
+       cfg.t.cfg.s.snNSAP.ssf                  = k->ssf;                       /* sub service field */
+       cfg.t.cfg.s.snNSAP.lnkType              = k->linkType;          /* link type -ANSI, ITU, CHINA or BICI */
+       cfg.t.cfg.s.snNSAP.upSwtch              = k->switchType;        /* user part switch type */
+       cfg.t.cfg.s.snNSAP.selector             = 0;                            /* upper layer selector */
+       cfg.t.cfg.s.snNSAP.mem.region   = S_REG;                        /* memory region id */
+       cfg.t.cfg.s.snNSAP.mem.pool             = S_POOL;                       /* memory pool id */
+       cfg.t.cfg.s.snNSAP.prior                = PRIOR0;                       /* priority */
+       cfg.t.cfg.s.snNSAP.route                = RTESPEC;                      /* route */
+#if( SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA )
+       cfg.t.cfg.s.snNSAP.dpcLen               = DPC24;                        /* dpc length 14 or 24 bits */
+#else
+       cfg.t.cfg.s.snNSAP.dpcLen               = DPC14;                        /* dpc length 14 or 24 bits */
+#endif
+#if (defined(SN_SG) || defined(TDS_ROLL_UPGRADE_SUPPORT))
+       cfg.t.cfg.s.snNSAP.usrParts             = ;                                     /* user parts configured on self postatic int code on IP side */ 
+#endif
+#ifdef TDS_ROLL_UPGRADE_SUPPORT
+       cfg.t.cfg.s.snNSAP.remIntfValid = FALSE;                        /* remote interface version is valid */
+       cfg.t.cfg.s.snNSAP.remIntfVer   = SNTIFVER;                     /* remote interface version */
+#endif
+
+       return(sng_cfg_mtp3(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp3_linkset_config(int id)
+{
+       Pst                             pst;
+       SnMngmt                 cfg;
+       U16                             c;
+       sng_link_set_t  *k = &g_ftdm_sngss7_data.cfg.mtpLinkSet[id];
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSN;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(SnMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                         = TCFG;
+       cfg.hdr.entId.ent                                       = ENTSN;
+       cfg.hdr.entId.inst                                      = S_INST;
+       cfg.hdr.elmId.elmnt                             = STLNKSET;              /* link set */
+
+       cfg.hdr.elmId.elmntInst1                        = k->id;
+
+       cfg.t.cfg.s.snLnkSet.lnkSetId           = k->id;                        /* link set ID */
+       cfg.t.cfg.s.snLnkSet.lnkSetType         = k->linkType;          /* link type */
+       cfg.t.cfg.s.snLnkSet.adjDpc                     = k->apc;                       /* adjacent DPC */
+       cfg.t.cfg.s.snLnkSet.nmbActLnkReqd      = k->minActive;         /* minimum number of active links */
+       cfg.t.cfg.s.snLnkSet.nmbCmbLnkSet       = 1;                            /* number of combined link sets */
+       for (c = 0; c < LSN_MAXCMBLNK; c++) {
+               cfg.t.cfg.s.snLnkSet.cmbLnkSet[c].cmbLnkSetId = c+1;
+               cfg.t.cfg.s.snLnkSet.cmbLnkSet[c].lnkSetPrior = 0;
+       }
+
+       return(sng_cfg_mtp3(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtp3_route_config(int id)
+{
+       Pst                     pst;
+       SnMngmt         cfg;
+       sng_route_t     *k = &g_ftdm_sngss7_data.cfg.mtpRoute[id];
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSN;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(SnMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                         = TCFG;
+       cfg.hdr.entId.ent                                       = ENTSN;
+       cfg.hdr.entId.inst                                      = S_INST;
+       cfg.hdr.elmId.elmnt                             = STROUT;
+
+       cfg.hdr.elmId.elmntInst1                        = k->id;
+
+       cfg.t.cfg.s.snRout.dpc                          = k->dpc;                                       /* destination postatic int code */
+       cfg.t.cfg.s.snRout.spType                       = LSN_TYPE_SP;                          /* signalling postatic int type */
+       cfg.t.cfg.s.snRout.swtchType            = k->linkType;                          /* switch type */
+       cfg.t.cfg.s.snRout.upSwtch                      = k->switchType;                        /* user part switch type */
+       cfg.t.cfg.s.snRout.cmbLnkSetId          = k->cmbLinkSetId;                      /* combined link set ID */
+       if (k->id == 0) {
+               cfg.t.cfg.s.snRout.dir                          = LSN_RTE_UP;                           /* direction */
+       } else {
+               cfg.t.cfg.s.snRout.dir                          = LSN_RTE_DN;                           /* direction */
+       }
+       cfg.t.cfg.s.snRout.rteToAdjSp           = 0;                                            /* flag indicating this route to adjacent SP */ 
+       cfg.t.cfg.s.snRout.ssf                          = k->ssf;                                       /* sub service field */
+       cfg.t.cfg.s.snRout.brdcastFlg           = TRUE;                                         /* flag indicating to have TFP broadcast */
+       if (cfg.t.cfg.s.snRout.swtchType == LSN_SW_ITU) {
+               cfg.t.cfg.s.snRout.rstReq               = LSN_ITU92_RST;                        /* Restart type supported by the node */
+       } else if ((cfg.t.cfg.s.snRout.swtchType == LSN_SW_ANS) ||
+                          (cfg.t.cfg.s.snRout.swtchType == LSN_SW_ANS96)) {
+               cfg.t.cfg.s.snRout.rstReq               = LSN_ANS_RST;                  /* Restart type supported by the node */
+       } else {
+               cfg.t.cfg.s.snRout.rstReq               = LSN_NO_RST;                   /* Restart type supported by the node */
+       }
+       if ((cfg.t.cfg.s.snRout.swtchType == LSN_SW_ITU) || 
+               (cfg.t.cfg.s.snRout.swtchType == LSN_SW_CHINA) || 
+               (cfg.t.cfg.s.snRout.swtchType == LSN_SW_BICI)) {
+               cfg.t.cfg.s.snRout.slsRange             = LSN_ITU_SLS_RANGE;            /* max value of SLS for this DPC */
+       } else {
+               cfg.t.cfg.s.snRout.slsRange             = LSN_ANSI_5BIT_SLS_RANGE;      /* max value of SLS for this DPC */
+       }
+       cfg.t.cfg.s.snRout.lsetSel                      = 0x1;                                          /* linkset selection bit in SLS for STP */
+       cfg.t.cfg.s.snRout.multiMsgPrior        = FALSE;                                        /* TRUE if multiple cong priorities of messages */
+       cfg.t.cfg.s.snRout.rctReq                       = TRUE;                                         /* route set congestion test required or not */
+       cfg.t.cfg.s.snRout.slsLnk                       = FALSE;
+#ifdef LSNV2
+# if (SS7_NTT || defined(TDS_ROLL_UPGRADE_SUPPORT))
+       cfg.t.cfg.s.snRout.destSpec                     =;                                                      /* destination specfication A or B*/ 
+# endif  
+#endif  
+#if (defined(LSNV3) || defined(SN_MULTIPLE_NETWORK_RESTART))
+       cfg.t.cfg.s.snRout.tfrReq                       =;                                                      /* TFR procedure required or not */
+#endif
+       cfg.t.cfg.s.snRout.tmr.t6.enb           = TRUE;
+       cfg.t.cfg.s.snRout.tmr.t6.val           = k->t6;
+       cfg.t.cfg.s.snRout.tmr.t8.enb           = TRUE;                                         /* t8 - transfer prohibited inhibition timer */
+       cfg.t.cfg.s.snRout.tmr.t8.val           = k->t8;
+       cfg.t.cfg.s.snRout.tmr.t10.enb          = TRUE;                                         /* t10 - waiting to repeat route set test */
+       cfg.t.cfg.s.snRout.tmr.t10.val          = k->t10;
+       cfg.t.cfg.s.snRout.tmr.t11.enb          = TRUE;                                         /* t11 - transfer restrict timer */
+       cfg.t.cfg.s.snRout.tmr.t11.val          = k->t11;
+       cfg.t.cfg.s.snRout.tmr.t19.enb          = TRUE;                                         /* t19 - TRA sent timer */
+       cfg.t.cfg.s.snRout.tmr.t19.val          = k->t19;
+       cfg.t.cfg.s.snRout.tmr.t21.enb          = TRUE;                                         /* t21 - waiting to restart traffic routed through adjacent SP */
+       cfg.t.cfg.s.snRout.tmr.t21.val          = k->t21;
+
+#if (defined(LSNV3) || defined(SN_MULTIPLE_NETWORK_RESTART))
+       cfg.t.cfg.s.snRout.tmr.t15.enb          = TRUE;                                         /* t15 - waiting to start route set congestion test */
+       cfg.t.cfg.s.snRout.tmr.t15.val          = k->t15;
+       cfg.t.cfg.s.snRout.tmr.t16.enb          = TRUE;                                         /* t16 - waiting for route set congestion status update */
+       cfg.t.cfg.s.snRout.tmr.t16.val          = k->t16;
+       cfg.t.cfg.s.snRout.tmr.t18.enb          = TRUE;                                         /* t18 - transfer prohibited inhibition timer */
+       cfg.t.cfg.s.snRout.tmr.t18.val          = k->t18;
+# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT))
+       cfg.t.cfg.s.snRout.tmr.t25.enb          = TRUE;                                         /* t25 - waiting to traffic resatrt allowed message for ANSI */
+       cfg.t.cfg.s.snRout.tmr.t25.val          = k->t25;
+       cfg.t.cfg.s.snRout.tmr.t26.enb          = TRUE;                                         /* t26 - waiting to repeat traffic restart waiting message for ANSI */
+       cfg.t.cfg.s.snRout.tmr.t26.val          = k->t26;
+# endif
+#endif
+#if (SS7_TTC || SS7_NTT || defined(TDS_ROLL_UPGRADE_SUPPORT))
+       cfg.t.cfg.s.snRout.tmr.tc.enb           = TRUE;                                         /* tc - Waiting for congestion abatement */
+       cfg.t.cfg.s.snRout.tmr.tc.val           = k->tc;
+#endif
+#if (defined(SN_SG) || defined(TDS_ROLL_UPGRADE_SUPPORT))
+       cfg.t.cfg.s.snRout.tmr.tQry.enb         = TRUE;                                         /* Periodic query timer over the NIF */
+       cfg.t.cfg.s.snRout.tmr.tQry.val         = k->tqry;
+#endif
+
+       return(sng_cfg_mtp3(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_isup_nsap_config(int id)
+{
+       SiMngmt  cfg;
+       Pst              pst;
+       sng_nsap_t      *k = &g_ftdm_sngss7_data.cfg.nsap[id];
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSI;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(SiMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                 = TCFG;
+       cfg.hdr.entId.ent                               = ENTSI;
+       cfg.hdr.entId.inst                              = S_INST;
+       cfg.hdr.elmId.elmnt                     = STNSAP;
+
+       cfg.hdr.elmId.elmntInst1                = k->id;
+
+#if (SI_LMINT3 || SMSI_LMINT3)
+       cfg.t.cfg.s.siNSap.nsapId               = k->id;                        /* Id of the NSAP being configured */
+#endif
+       cfg.t.cfg.s.siNSap.nwId                 = k->nwId;                      /* Network Id */
+       cfg.t.cfg.s.siNSap.spId                 = k->spId;                      /* service providor id */
+       cfg.t.cfg.s.siNSap.ssf                  = k->ssf;                       /* sub service field */
+       cfg.t.cfg.s.siNSap.dstEnt               = ENTSN;                        /* entity */
+       cfg.t.cfg.s.siNSap.dstInst              = S_INST;                       /* instance */
+       cfg.t.cfg.s.siNSap.prior                = PRIOR0;                       /* priority */
+       cfg.t.cfg.s.siNSap.route                = RTESPEC;                      /* route */
+       cfg.t.cfg.s.siNSap.dstProcId    = SFndProcId();         /* destination processor id */
+       cfg.t.cfg.s.siNSap.sapType              = SAP_MTP;                      /* sap type */
+       cfg.t.cfg.s.siNSap.selector             = 0;                            /* selector */
+       cfg.t.cfg.s.siNSap.tINT.enb             = TRUE;                         /* interface (Bind Confirm) timer */
+       cfg.t.cfg.s.siNSap.tINT.val             = 50;
+       cfg.t.cfg.s.siNSap.mem.region   = S_REG;                        /* memory region & pool id */
+       cfg.t.cfg.s.siNSap.mem.pool             = S_POOL;
+
+#ifdef TDS_ROLL_UPGRADE_SUPPORT
+       cfg.t.cfg.s.siNSap.remIntfValid = FALSE;        /* remote interface version is valid */
+       cfg.t.cfg.s.siNSap.remIntfVer;                   /* remote interface version */
+#endif
+
+       return(sng_cfg_isup(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_isup_intf_config(int id)
+{
+       SiMngmt  cfg;
+       Pst              pst;
+       sng_isup_inf_t *k = &g_ftdm_sngss7_data.cfg.isupIntf[id];
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSI;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(SiMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                                         = TCFG;
+       cfg.hdr.entId.ent                                                       = ENTSI;
+       cfg.hdr.entId.inst                                                      = S_INST;
+       cfg.hdr.elmId.elmnt                                             = SI_STINTF;
+
+       cfg.hdr.elmId.elmntInst1                                        = k->id;
+
+       cfg.t.cfg.s.siIntfCb.intfId                                     = k->id;                                /* Interface id */
+       cfg.t.cfg.s.siIntfCb.nwId                                       = k->nwId;                              /* Network Id */
+       cfg.t.cfg.s.siIntfCb.sapId                                      = k->isap;                              /* Id of the Upper ISUP SAP */
+       cfg.t.cfg.s.siIntfCb.opc                                        = k->spc;                               /* physical originating postatic int code */
+       cfg.t.cfg.s.siIntfCb.phyDpc                                     = k->dpc;                               /* physical destination postatic int code */
+       cfg.t.cfg.s.siIntfCb.swtch                                      = k->switchType;                /* Protocol Switch */
+       cfg.t.cfg.s.siIntfCb.ssf                                        = k->ssf;                               /* subsystem service information */
+       cfg.t.cfg.s.siIntfCb.pauseActn                          = SI_PAUSE_CLRTRAN;             /* call clearing behavior upon rx. PAUSE */
+       cfg.t.cfg.s.siIntfCb.dpcCbTmr.t4.enb            = TRUE;                                 /* t4 timer - user part test sent */
+       cfg.t.cfg.s.siIntfCb.dpcCbTmr.t4.val            = k->t4;
+       cfg.t.cfg.s.siIntfCb.dpcCbTmr.tPAUSE.enb        = TRUE;                                 /* waiting for PAUSE to be effective */
+       cfg.t.cfg.s.siIntfCb.dpcCbTmr.tPAUSE.val        = k->tpause;
+       cfg.t.cfg.s.siIntfCb.dpcCbTmr.tSTAENQ.enb       = TRUE;                                 /* status enquiry timer */
+       cfg.t.cfg.s.siIntfCb.dpcCbTmr.tSTAENQ.val       = k->tstaenq;
+#if SS7_ANS95
+       cfg.t.cfg.s.siIntfCb.availTest                          = FALSE;                                /* circuit validation test */
+#endif
+#if (SS7_ITU97 || SS7_ETSIV3 || SS7_UK || SS7_NZL || SS7_ITU2000 || SS7_KZ)
+       cfg.t.cfg.s.siIntfCb.checkTable                         = LSI_CHKTBLE_MRATE;    /* Validation flag for Table 3 p1/p2 Q.763 */
+#endif
+#if (SS7_ANS95 || SS7_ITU97 || SS7_ETSIV3 || SS7_UK || SS7_NZL || SS7_ITU2000 || SS7_KZ)
+       switch (k->switchType) {
+       case LSI_SW_TST:
+       case LSI_SW_ITU:
+       case LSI_SW_ITU97:
+       case LSI_SW_ITU2000:
+       case LSI_SW_ETSI:
+       case LSI_SW_ETSIV3:
+       case LSI_SW_RUSSIA:
+       case LSI_SW_RUSS2000:
+       case LSI_SW_INDIA:
+       case LSI_SW_CHINA:
+               cfg.t.cfg.s.siIntfCb.trunkType                  = TRUE;                                 /* truck type E1(TRUE)/T1(FALSE) at intf */
+               break;
+       case LSI_SW_ANS88:
+       case LSI_SW_ANS92:
+       case LSI_SW_ANS95:
+       case LSI_SW_BELL:
+               cfg.t.cfg.s.siIntfCb.trunkType                  = FALSE;                                /* truck type E1(TRUE)/T1(FALSE) at intf */
+               break;
+       }
+
+#endif
+#if (LSIV4 || LSIV5)
+       cfg.t.cfg.s.siIntfCb.lnkSelOpt                          = LSI_LINSEK_CIC;               /* link select option */
+# if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL)
+       cfg.t.cfg.s.siIntfCb.lnkSelBits                         = LSI_LNKSEL_8BITS;             /* number of bits for link selection */
+# endif
+#endif
+
+       return(sng_cfg_isup(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_isup_ckt_config(int id)
+{
+       SiMngmt                  cfg;
+       Pst                              pst;
+       U32                              tmp_flag;
+       sng_isup_ckt_t  *k = &g_ftdm_sngss7_data.cfg.isupCkt[id];
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSI;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(SiMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                         = TCFG;
+       cfg.hdr.entId.ent                                       = ENTSI;
+       cfg.hdr.entId.inst                                      = S_INST;
+       cfg.hdr.elmId.elmnt                                     = STICIR;
+
+       cfg.hdr.elmId.elmntInst1                        = k->id;
+
+       cfg.t.cfg.s.siCir.cirId                         = k->id;                        /* circuit id code                                               */
+       cfg.t.cfg.s.siCir.cic                           = k->cic;                       /* cic                                                                   */
+       cfg.t.cfg.s.siCir.intfId                        = k->infId;                     /* interface id                                                  */
+       cfg.t.cfg.s.siCir.typeCntrl                     = k->typeCntrl;         /* type of control                                               */
+       cfg.t.cfg.s.siCir.contReq                       = FALSE;                        /* continuity check required                            */
+#if (SI_218_COMP || SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL)
+       cfg.t.cfg.s.siCir.firstCic                      =;                                      /* First cic in the circuit group                 */
+       cfg.t.cfg.s.siCir.numCir                        =;                                      /* Number of circuits in the circuit group */
+       cfg.t.cfg.s.siCir.nonSS7Con                     = TRUE;                         /* connecting to non SS7 network                        */
+       cfg.t.cfg.s.siCir.outTrkGrpN            =;                                      /* outgoing trunk group number (For EXM)        */
+       cfg.t.cfg.s.siCir.cvrTrkClli            =;                                      /* Trunk Group number (For CVR validation) */
+       cfg.t.cfg.s.siCir.clli                          =;                                      /* common language location identifier   */
+#endif
+       cfg.t.cfg.s.siCir.cirTmr.t3.enb         = TRUE;                         /* t3 timer - overload received                 */
+       cfg.t.cfg.s.siCir.cirTmr.t3.val         = k->t3;
+       cfg.t.cfg.s.siCir.cirTmr.t12.enb        = TRUE;                         /* t12 timer - blocking sent                            */
+       cfg.t.cfg.s.siCir.cirTmr.t12.val        = k->t12;
+       cfg.t.cfg.s.siCir.cirTmr.t13.enb        = TRUE;                         /* t13 timer - initial blocking sent            */
+       cfg.t.cfg.s.siCir.cirTmr.t13.val        = k->t13;
+       cfg.t.cfg.s.siCir.cirTmr.t14.enb        = TRUE;                         /* t14 timer - unblocking sent                   */
+       cfg.t.cfg.s.siCir.cirTmr.t14.val        = k->t14;
+       cfg.t.cfg.s.siCir.cirTmr.t15.enb        = TRUE;                         /* t15 timer - initial unblocking sent   */
+       cfg.t.cfg.s.siCir.cirTmr.t15.val        = k->t15;
+       cfg.t.cfg.s.siCir.cirTmr.t16.enb        = TRUE;                         /* t16 timer - reset sent                                 */
+       cfg.t.cfg.s.siCir.cirTmr.t16.val        = k->t16;
+       cfg.t.cfg.s.siCir.cirTmr.t17.enb        = TRUE;                         /* t17 timer - initial reset sent                 */
+       cfg.t.cfg.s.siCir.cirTmr.t17.val        = k->t17;
+#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL)
+       cfg.t.cfg.s.siCir.cirTmr.tVal.enb       = TRUE;                         /* circuit validation timer                              */
+       cfg.t.cfg.s.siCir.cirTmr.tVal.val       = k->tval;
+#endif
+#if (SS7_ANS95 || SS7_ITU97 || SS7_ETSIV3 || SS7_UK)
+       tmp_flag = 0x0;
+       /* bit 0 - 4 is the timeslot on the span for this circuit */
+       tmp_flag = ( 1 );
+
+       /* bit 5 -> can this timeslot be used for contigous M-rate call */
+       tmp_flag |= !(0x20);
+
+       /* bit 6 -> does this timeslot support contigous M-rate call */
+       tmp_flag |= !(0x40);
+
+       cfg.t.cfg.s.siCir.slotId                = tmp_flag ;             /* physical slot id bit wise flag                */
+       cfg.t.cfg.s.siCir.ctrlMult              = 0;                            /* Controller for multirate calls                 */
+#endif
+
+       tmp_flag = 0x0;
+       /* bit 0 -> ANSI international support or national support */
+       tmp_flag = k->ssf;
+
+       /* bit 1 -> confusion message on */
+       tmp_flag |= LSI_CIRFLG_CFN_ON;
+
+       /*bit 2-3 -> circuit group carrier information */
+       tmp_flag |= LSI_CFCI_ANALDIG;
+
+       /*bit 4-5 -> alarm carrier */
+       tmp_flag |= LSI_CFAC_UNKNOWN;
+
+       /*bit 6-7 -> continuity check requirement*/
+       tmp_flag |= LSI_CFCO_NONE;
+
+       cfg.t.cfg.s.siCir.cirFlg                = tmp_flag;              /* Flag indicating diff cfg options for ckt */
+
+       return(sng_cfg_isup(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_isup_isap_config(int id)
+{
+       SiMngmt          cfg;
+       Pst                      pst;
+       sng_isap_t      *k = &g_ftdm_sngss7_data.cfg.isap[id];
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSI;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(SiMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                                 = TCFG;
+       cfg.hdr.entId.ent                                               = ENTSI;
+       cfg.hdr.entId.inst                                              = S_INST;
+       cfg.hdr.elmId.elmnt                                     = STISAP;
+
+       cfg.hdr.elmId.elmntInst1                                = k->id;
+
+#if (SI_LMINT3 || SMSI_LMINT3)
+       cfg.t.cfg.s.siSap.sapId                                 = k->id;                                        /* Id of the SAP being configured */
+#endif
+       cfg.t.cfg.s.siSap.swtch                                 = k->switchType;                        /* Protocol Switch */
+       cfg.t.cfg.s.siSap.ssf                                   = k->ssf;                                       /* Sub service field */
+       cfg.t.cfg.s.siSap.sidIns                                = FALSE;                                        /* SID insertion Flag */
+       cfg.t.cfg.s.siSap.sidVer                                = FALSE;                                        /* SID verification Flag */
+       if ( cfg.t.cfg.s.siSap.sidIns == TRUE ) {                                                       /* SID */
+               #if 0
+               cfg.t.cfg.s.siSap.sid                           =;
+               cfg.t.cfg.s.siSap.natAddrInd            =;                                                      /* SID Nature of Addres Indicator */
+               cfg.t.cfg.s.siSap.sidNPlan                      =;                                                      /* SID Numbering Plan */
+               cfg.t.cfg.s.siSap.sidPresInd            =;                                                      /* default presentation indicator */
+               cfg.t.cfg.s.siSap.incSidPresRes         =;                                                      /* Presentation Restriction of incoming SID */
+               cfg.t.cfg.s.siSap.sidPresRes            =;                                                      /* Presentation Restriction */
+               #endif
+       } else {
+               cfg.t.cfg.s.siSap.sid.length    = 0;
+               /*cfg.t.cfg.s.siSap.sid.strg[0]  =*/
+               cfg.t.cfg.s.siSap.natAddrInd            = ADDR_NOTPRSNT;                        /* SID Nature of Addres Indicator */
+               cfg.t.cfg.s.siSap.sidNPlan                      = NP_ISDN;                                      /* SID Numbering Plan */
+               cfg.t.cfg.s.siSap.sidPresInd            = FALSE;                                        /* default presentation indicator */
+               cfg.t.cfg.s.siSap.incSidPresRes         = TRUE;                                         /* Presentation Restriction of incoming SID */
+               cfg.t.cfg.s.siSap.sidPresRes            = 0;                                            /* Presentation Restriction */
+       }
+       cfg.t.cfg.s.siSap.reqOpt                                = FALSE;                                        /* Request option */
+       cfg.t.cfg.s.siSap.allCallMod                    = TRUE;                                         /* call modification allowed flag */
+       cfg.t.cfg.s.siSap.maxLenU2U                             = MAX_SI_USER_2_USER_LEN;       /* Max length of user to user messages */
+       cfg.t.cfg.s.siSap.passOnFlag                    = TRUE;                                         /* flag for passing unknown par/msg */
+       cfg.t.cfg.s.siSap.relLocation                   = ILOC_PRIVNETLU;                       /* release location indicator in cause val */
+       cfg.t.cfg.s.siSap.prior                                 = PRIOR0;                                       /* priority */
+       cfg.t.cfg.s.siSap.route                                 = RTESPEC;                                      /* route */
+       cfg.t.cfg.s.siSap.selector                              = 0;                                            /* selector */
+       cfg.t.cfg.s.siSap.mem.region                    = S_REG;                                        /* memory region & pool id */
+       cfg.t.cfg.s.siSap.mem.pool                              = S_POOL;                                       /* memory region & pool id */
+
+       cfg.t.cfg.s.siSap.tmr.t1.enb                    = TRUE;                                         /* t1 timer - release sent                               */
+       cfg.t.cfg.s.siSap.tmr.t1.val                    = k->t1;
+       cfg.t.cfg.s.siSap.tmr.t2.enb                    = TRUE;                                         /* t2 timer - suspend received                   */
+       cfg.t.cfg.s.siSap.tmr.t2.val                    = k->t2;
+       cfg.t.cfg.s.siSap.tmr.t5.enb                    = TRUE;                                         /* t5 timer - initial release sent               */
+       cfg.t.cfg.s.siSap.tmr.t5.val                    = k->t5;
+       cfg.t.cfg.s.siSap.tmr.t6.enb                    = TRUE;                                         /* t6 timer - suspend received                   */
+       cfg.t.cfg.s.siSap.tmr.t6.val                    = k->t6;
+       cfg.t.cfg.s.siSap.tmr.t7.enb                    = TRUE;                                         /* t7 timer - latest address sent                 */
+       cfg.t.cfg.s.siSap.tmr.t7.val                    = k->t7;
+       cfg.t.cfg.s.siSap.tmr.t8.enb                    = TRUE;                                         /* t8 timer - initial address received   */
+       cfg.t.cfg.s.siSap.tmr.t8.val                    = k->t8;
+       cfg.t.cfg.s.siSap.tmr.t9.enb                    = TRUE;                                         /* t9 timer - latest address sent after ACM */
+       cfg.t.cfg.s.siSap.tmr.t9.val                    = k->t9;
+       cfg.t.cfg.s.siSap.tmr.t27.enb                   = TRUE;                                         /* t27 timer - wait. for continuity recheck */
+       cfg.t.cfg.s.siSap.tmr.t27.val                   = k->t27;
+       cfg.t.cfg.s.siSap.tmr.t31.enb                   = TRUE;                                         /* t31 timer - call reference frozen period */
+       cfg.t.cfg.s.siSap.tmr.t31.val                   = k->t31;
+       cfg.t.cfg.s.siSap.tmr.t33.enb                   = TRUE;                                         /* t33 timer - INR sent                                  */
+       cfg.t.cfg.s.siSap.tmr.t33.val                   = k->t33;
+       cfg.t.cfg.s.siSap.tmr.t34.enb                   = TRUE;                                         /* t34 timer - wait. for continuity after recheck */
+       cfg.t.cfg.s.siSap.tmr.t34.val                   = k->t34;
+       cfg.t.cfg.s.siSap.tmr.t36.enb                   = TRUE;                                         /* waiting SGM                                                   */
+       cfg.t.cfg.s.siSap.tmr.t36.val                   = k->t36;
+       cfg.t.cfg.s.siSap.tmr.tCCR.enb                  = TRUE;                                         /* tCCR timer - continuity recheck timer        */
+       cfg.t.cfg.s.siSap.tmr.tCCR.val                  = k->tccr;
+       cfg.t.cfg.s.siSap.tmr.tRELRSP.enb               = TRUE;                                         /* waiting for release response                  */
+       cfg.t.cfg.s.siSap.tmr.tRELRSP.val               = k->trelrsp;
+       cfg.t.cfg.s.siSap.tmr.tFNLRELRSP.enb    = TRUE;                                         /* waiting for final release response     */
+       cfg.t.cfg.s.siSap.tmr.tFNLRELRSP.val    = k->tfnlrelrsp;
+#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL)
+       cfg.t.cfg.s.siSap.tmr.tEx.enb                   = TRUE;                                         /* tEx timer - Exit to be sent                   */
+       cfg.t.cfg.s.siSap.tmr.tEx.val                   = k->tex;
+       cfg.t.cfg.s.siSap.tmr.tCCRt.enb                 = TRUE;                                         /* tCCR timer (o/g side) - continuity recheck timer */
+       cfg.t.cfg.s.siSap.tmr.tCCRt.val                 = k->tccrt;
+#endif
+#if (SS7_ANS92 || SS7_ANS95 || SS7_BELL)
+       cfg.t.cfg.s.siSap.tmr.tCRM.enb                  = TRUE;                                         /* circuit reservation message timer            */
+       cfg.t.cfg.s.siSap.tmr.tCRM.val                  = k->tcrm;
+       cfg.t.cfg.s.siSap.tmr.tCRA.enb                  = TRUE;                                         /* circuit reservation ack. timer                */
+       cfg.t.cfg.s.siSap.tmr.tCRA.val                  = k->tcra;
+#endif
+#if (SS7_ETSI || SS7_ITU97 || SS7_ETSIV3 || SS7_UK || SS7_NZL || SS7_KZ)
+       cfg.t.cfg.s.siSap.tmr.tECT.enb                  = TRUE;                                         /* Explicit Call Transfer - waiting for loop prvnt rsp */
+       cfg.t.cfg.s.siSap.tmr.tECT.val                  = k->tect;
+#endif
+
+#ifdef TDS_ROLL_UPGRADE_SUPPORT
+       cfg.t.cfg.s.siSap.remIntfValid                  = FALSE;                                        /* remote interface version is valid */
+       cfg.t.cfg.s.siSap.remIntfVer                    =;                                                      /* remote interface version */
+#endif
+
+       return(sng_cfg_isup(&pst, &cfg));
+}
+
+/******************************************************************************/
+int ftmod_ss7_cc_isap_config(int id)
+{
+       CcMngmt  cfg;
+       Pst              pst;
+       sng_isap_t      *k = &g_ftdm_sngss7_data.cfg.isap[id];
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTCC;
+
+       /*clear the configuration structure*/
+       memset(&cfg, 0x0, sizeof(CcMngmt));
+
+       /*fill in some general sections of the header*/
+       smHdrInit(&cfg.hdr);
+
+       /*fill in the specific fields of the header*/
+       cfg.hdr.msgType                                         = TCFG;
+       cfg.hdr.entId.ent                                       = ENTCC;
+       cfg.hdr.entId.inst                                      = S_INST;
+       cfg.hdr.elmId.elmnt                                     = STISAP;
+
+       cfg.hdr.elmId.elmntInst1                        = k->id;
+
+       cfg.t.cfg.s.ccISAP.suId                         = k->suId;
+       cfg.t.cfg.s.ccISAP.spId                         = k->spId;
+       cfg.t.cfg.s.ccISAP.pst.dstProcId        = SFndProcId();
+       cfg.t.cfg.s.ccISAP.pst.dstEnt           = ENTSI;
+       cfg.t.cfg.s.ccISAP.pst.dstInst          = S_INST;
+       cfg.t.cfg.s.ccISAP.pst.srcProcId        = SFndProcId();
+       cfg.t.cfg.s.ccISAP.pst.srcEnt           = ENTCC;
+       cfg.t.cfg.s.ccISAP.pst.srcInst          = S_INST;
+       cfg.t.cfg.s.ccISAP.pst.prior            = PRIOR0;
+       cfg.t.cfg.s.ccISAP.pst.route            = RTESPEC;
+       cfg.t.cfg.s.ccISAP.pst.region           = S_REG;
+       cfg.t.cfg.s.ccISAP.pst.pool                     = S_POOL;
+       cfg.t.cfg.s.ccISAP.pst.selector         = 0;
+
+       return(sng_cfg_cc(&pst, &cfg));
+}
+
+/******************************************************************************/
+
+/******************************************************************************/
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
+/******************************************************************************/
index eaf36cffaba8207850a4d64350be5de82307152e..7d0488ce7d23f065d1c82f01e0b8a09bf7659c18 100644 (file)
@@ -50,6 +50,8 @@ static ftdm_status_t handle_set_function_trace(ftdm_stream_handle_t *stream, int
 static ftdm_status_t handle_set_message_trace(ftdm_stream_handle_t *stream, int on, int level);
 static ftdm_status_t handle_set_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
 static ftdm_status_t handle_set_unblks(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
+static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name);
+static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *name);
 
 static ftdm_status_t handle_show_free(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
 static ftdm_status_t handle_show_inuse(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
@@ -68,946 +70,1077 @@ static ftdm_status_t check_arg_count(int args, int min);
 /* FUNCTIONS ******************************************************************/
 ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data)
 {
-    char    *mycmd = NULL;
-    char    *argv[10] = { 0 };
-    int     argc = 0;
-    int     span = 0;
-    int     chan = 0;
-    int     trace = 0;
-    int     trace_level = 7;
-    int     verbose = 1;
-    int     c = 0;
-
-    if (data) {
-        mycmd = ftdm_strdup(data);
-        argc = ftdm_separate_string(mycmd,' ',argv,(sizeof(argv) / sizeof(argv[0])));
-    }
-
-    if (check_arg_count(argc, 1)) goto handle_cli_error_argc;
-    
-    if (!strcasecmp(argv[c], "show")) {
-    /**************************************************************************/   
-        if (check_arg_count(argc, 4)) goto handle_cli_error_argc;
-        c++;
-
-        if (!strcasecmp(argv[c], "status")) {
-        /**********************************************************************/
-            c++;
-
-            if (!strcasecmp(argv[c], "link")) {
-            /******************************************************************/
-                c++;
-                handle_status_link(stream, argv[c]);
-            /******************************************************************/
-            } else if (!strcasecmp(argv[c], "linkset")) {
-            /******************************************************************/
-                c++;
-                handle_status_linkset(stream, argv[c]);
-            /******************************************************************/
-            } else if (!strcasecmp(argv[c], "span")) {
-            /******************************************************************/
-                if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-
-                if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
-
-                handle_show_status(stream, span, chan, verbose);
-            /******************************************************************/
-            } else {
-            /******************************************************************/
-                stream->write_function(stream, "Unknown \"status\" command\n");
-                goto handle_cli_error;
-            /******************************************************************/
-            }
-        /**********************************************************************/
-        } else if (!strcasecmp(argv[c], "inuse")) {
-        /**********************************************************************/
-            if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-            c++;
-
-            if (!strcasecmp(argv[c], "span")) {
-            /******************************************************************/
-                if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-
-                if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
-
-                handle_show_inuse(stream, span, chan, verbose);
-            /******************************************************************/
-            } else {
-            /******************************************************************/
-                stream->write_function(stream, "Unknown \"inuse\" command\n");
-                goto handle_cli_error;
-            /******************************************************************/
-            }           
-        /**********************************************************************/
-        } else if (!strcasecmp(argv[c], "inreset")) {
-        /**********************************************************************/
-            if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-            c++;
-
-            if (!strcasecmp(argv[c], "span")) {
-            /******************************************************************/
-                if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-
-                if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
-
-                handle_show_inreset(stream, span, chan, verbose);
-            /******************************************************************/
-            } else {
-            /******************************************************************/
-                stream->write_function(stream, "Unknown \"inreset\" command\n");
-                goto handle_cli_error;
-            /******************************************************************/
-            }   
-        /**********************************************************************/
-        } else if (!strcasecmp(argv[c], "free")) {
-        /**********************************************************************/
-            if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-            c++;
-
-            if (!strcasecmp(argv[c], "span")) {
-            /******************************************************************/
-                if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-
-                if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
-
-                handle_show_free(stream, span, chan, verbose);
-            /******************************************************************/
-            } else {
-            /******************************************************************/
-                stream->write_function(stream, "Unknown \"free\" command\n");
-                goto handle_cli_error;
-            /******************************************************************/
-            }   
-        /**********************************************************************/
-        } else if (!strcasecmp(argv[c], "blocks")) {
-        /**********************************************************************/
-            if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-            c++;
-
-            if (!strcasecmp(argv[c], "span")) {
-            /******************************************************************/
-                if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-
-                if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
-
-                handle_show_blocks(stream, span, chan, verbose);
-            /******************************************************************/
-            } else {
-            /******************************************************************/
-                stream->write_function(stream, "Unknown \"blocks\" command\n");
-                goto handle_cli_error;
-            /******************************************************************/
-            }   
-        /**********************************************************************/
-        } else if (!strcasecmp(argv[c], "flags")) {
-        /**********************************************************************/
-            if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-            c++;
-
-            if (!strcasecmp(argv[c], "span")) {
-            /******************************************************************/
-                if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-
-                if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
-
-                handle_show_flags(stream, span, chan, verbose);
-            /******************************************************************/
-            } else {
-            /******************************************************************/
-                stream->write_function(stream, "Unknown \"flags\" command\n");
-                goto handle_cli_error;
-            /******************************************************************/
-            }   
-        /**********************************************************************/
-        } else {
-        /**********************************************************************/
-            stream->write_function(stream, "Unknown \"show\" command\n");
-            goto handle_cli_error;
-        /**********************************************************************/
-        }
-    /**************************************************************************/
-    } else if (!strcasecmp(argv[c], "set")) {
-    /**************************************************************************/
-        if (check_arg_count(argc, 4)) goto handle_cli_error_argc;
-        c++;
-
-        if (!strcasecmp(argv[c], "ftrace")) {
-        /**********************************************************************/
-            c++;
-            trace = atoi(argv[c]);
-            c++;
-            trace_level = atoi(argv[c]);
-            c++;
-            handle_set_function_trace(stream, trace, trace_level);
-        /**********************************************************************/
-        } else if (!strcasecmp(argv[c], "mtrace")) {
-        /**********************************************************************/
-            c++;
-            trace = atoi(argv[c]);
-            c++;
-            trace_level = atoi(argv[c]);
-            c++;
-            handle_set_message_trace(stream, trace, trace_level);
-        /**********************************************************************/
-        } else {
-        /**********************************************************************/
-            stream->write_function(stream, "Unknown \"set\" command\n");
-            goto handle_cli_error;
-        /**********************************************************************/
-        }  
-    /**************************************************************************/
-    } else if (!strcasecmp(argv[c], "block")) {
-    /**************************************************************************/
-        if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-        c++;
-
-        if (!strcasecmp(argv[c], "span")) {
-        /**********************************************************************/
-            if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-
-            if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
-
-            handle_set_blocks(stream, span, chan, verbose);
-        /**********************************************************************/
-        } else {
-        /**********************************************************************/
-            stream->write_function(stream, "Unknown \"block\" command\n");
-            goto handle_cli_error;
-        /**********************************************************************/
-        }   
-    /**************************************************************************/
-    } else if (!strcasecmp(argv[c], "unblock")) {
-    /**************************************************************************/
-        if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-        c++;
-
-        if (!strcasecmp(argv[c], "span")) {
-        /**********************************************************************/
-            if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
-
-            if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
-
-            handle_set_unblks(stream, span, chan, verbose);
-        /**********************************************************************/
-        } else {
-        /**********************************************************************/
-            stream->write_function(stream, "Unknown \"unblock\" command\n");
-            goto handle_cli_error;
-        /**********************************************************************/
-        } 
-    /**************************************************************************/
-    } else {
-    /**************************************************************************/
-        goto handle_cli_error;
-    /**************************************************************************/
-    }
-
-    return FTDM_SUCCESS;
+       char    *mycmd = NULL;
+       char    *argv[10] = { 0 };
+       int      argc = 0;
+       int      span = 0;
+       int      chan = 0;
+       int      trace = 0;
+       int      trace_level = 7;
+       int      verbose = 1;
+       int      c = 0;
+
+       if (data) {
+               mycmd = ftdm_strdup(data);
+               argc = ftdm_separate_string(mycmd,' ',argv,(sizeof(argv) / sizeof(argv[0])));
+       }
+
+       if (check_arg_count(argc, 1)) goto handle_cli_error_argc;
+       
+       if (!strcasecmp(argv[c], "show")) {
+       /**************************************************************************/   
+               if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
+               c++;
+
+               if (!strcasecmp(argv[c], "status")) {
+               /**********************************************************************/
+                       c++;
+
+                       if (!strcasecmp(argv[c], "link")) {
+                       /******************************************************************/
+                               c++;
+                               handle_status_link(stream, argv[c]);
+                       /******************************************************************/
+                       } else if (!strcasecmp(argv[c], "linkset")) {
+                       /******************************************************************/
+                               c++;
+                               handle_status_linkset(stream, argv[c]);
+                       /******************************************************************/
+                       } else if (!strcasecmp(argv[c], "span")) {
+                       /******************************************************************/
+                               if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+
+                               if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
+
+                               handle_show_status(stream, span, chan, verbose);
+                       /******************************************************************/
+                       } else {
+                       /******************************************************************/
+                               stream->write_function(stream, "Unknown \"status\" command\n");
+                               goto handle_cli_error;
+                       /******************************************************************/
+                       }
+               /**********************************************************************/
+               } else if (!strcasecmp(argv[c], "inuse")) {
+               /**********************************************************************/
+                       if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+                       c++;
+
+                       if (!strcasecmp(argv[c], "span")) {
+                       /******************************************************************/
+                               if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+
+                               if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
+
+                               handle_show_inuse(stream, span, chan, verbose);
+                       /******************************************************************/
+                       } else {
+                       /******************************************************************/
+                               stream->write_function(stream, "Unknown \"inuse\" command\n");
+                               goto handle_cli_error;
+                       /******************************************************************/
+                       }
+               /**********************************************************************/
+               } else if (!strcasecmp(argv[c], "inreset")) {
+               /**********************************************************************/
+                       if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+                       c++;
+
+                       if (!strcasecmp(argv[c], "span")) {
+                       /******************************************************************/
+                               if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+
+                               if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
+
+                               handle_show_inreset(stream, span, chan, verbose);
+                       /******************************************************************/
+                       } else {
+                       /******************************************************************/
+                               stream->write_function(stream, "Unknown \"inreset\" command\n");
+                               goto handle_cli_error;
+                       /******************************************************************/
+                       }   
+               /**********************************************************************/
+               } else if (!strcasecmp(argv[c], "free")) {
+               /**********************************************************************/
+                       if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+                       c++;
+
+                       if (!strcasecmp(argv[c], "span")) {
+                       /******************************************************************/
+                               if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+
+                               if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
+
+                               handle_show_free(stream, span, chan, verbose);
+                       /******************************************************************/
+                       } else {
+                       /******************************************************************/
+                               stream->write_function(stream, "Unknown \"free\" command\n");
+                               goto handle_cli_error;
+                       /******************************************************************/
+                       }   
+               /**********************************************************************/
+               } else if (!strcasecmp(argv[c], "blocks")) {
+               /**********************************************************************/
+                       if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+                       c++;
+
+                       if (!strcasecmp(argv[c], "span")) {
+                       /******************************************************************/
+                               if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+
+                               if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
+
+                               handle_show_blocks(stream, span, chan, verbose);
+                       /******************************************************************/
+                       } else {
+                       /******************************************************************/
+                               stream->write_function(stream, "Unknown \"blocks\" command\n");
+                               goto handle_cli_error;
+                       /******************************************************************/
+                       }   
+               /**********************************************************************/
+               } else if (!strcasecmp(argv[c], "flags")) {
+               /**********************************************************************/
+                       if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+                       c++;
+
+                       if (!strcasecmp(argv[c], "span")) {
+                       /******************************************************************/
+                               if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
+
+                               if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
+
+                               handle_show_flags(stream, span, chan, verbose);
+                       /******************************************************************/
+                       } else {
+                       /******************************************************************/
+                               stream->write_function(stream, "Unknown \"flags\" command\n");
+                               goto handle_cli_error;
+                       /******************************************************************/
+                       }
+               /**********************************************************************/
+               } else if (!strcasecmp(argv[c], "mem")) {
+               /**********************************************************************/
+                       /*uint32_t availMem;*/
+
+                       /*sng_sta_mem(&availMem);*/
+               /**********************************************************************/
+               } else if (!strcasecmp(argv[c], "stats")) {
+               /**********************************************************************/
+/*                     sng_mtp1_sts_t sts;
+
+                       memset(&sts, 0x0, sizeof(sng_mtp1_sts_t));
+
+                       sng_mtp1_sts(1, &sts);
+
+                       stream->write_function(stream,"MTP1 tx stats:|tx_frm=%d|tx_err=%d|tx_fisu=%d|tx_lssu=%d|tx_msu=%d|\n",
+                                                                                       sts.tx_frm, sts.tx_err, sts.tx_fisu, sts.tx_lssu, sts.tx_msu);
+                       stream->write_function(stream,"MTP1 rx stats:|rx_frm=%d|rx_err=%d|rx_fisu=%d|rx_lssu=%d|rx_msu=%d|\n",
+                                                                                       sts.rx_frm, sts.rx_err, sts.rx_fisu, sts.rx_lssu, sts.rx_msu);
+*/
+               /**********************************************************************/
+               } else {
+               /**********************************************************************/
+                       stream->write_function(stream, "Unknown \"show\" command\n");
+                       goto handle_cli_error;
+               /**********************************************************************/
+               }
+       /**************************************************************************/
+       } else if (!strcasecmp(argv[c], "set")) {
+       /**************************************************************************/
+               if (check_arg_count(argc, 4)) goto handle_cli_error_argc;
+               c++;
+
+               if (!strcasecmp(argv[c], "ftrace")) {
+               /**********************************************************************/
+                       c++;
+                       trace = atoi(argv[c]);
+                       c++;
+                       trace_level = atoi(argv[c]);
+                       c++;
+                       handle_set_function_trace(stream, trace, trace_level);
+               /**********************************************************************/
+               } else if (!strcasecmp(argv[c], "mtrace")) {
+               /**********************************************************************/
+                       c++;
+                       trace = atoi(argv[c]);
+                       c++;
+                       trace_level = atoi(argv[c]);
+                       c++;
+                       handle_set_message_trace(stream, trace, trace_level);
+               /**********************************************************************/
+               } else {
+               /**********************************************************************/
+                       stream->write_function(stream, "Unknown \"set\" command\n");
+                       goto handle_cli_error;
+               /**********************************************************************/
+               }  
+       /**************************************************************************/
+       } else if (!strcasecmp(argv[c], "block")) {
+       /**************************************************************************/
+               if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
+               c++;
+
+               if (!strcasecmp(argv[c], "span")) {
+               /**********************************************************************/
+                       if (check_arg_count(argc, 5)) goto handle_cli_error_argc;
+
+                       if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
+
+                       handle_set_blocks(stream, span, chan, verbose);
+               /**********************************************************************/
+               } else if (!strcasecmp(argv[c], "link")) {
+               /**********************************************************************/
+                       if (check_arg_count(argc, 3)) goto handle_cli_error_argc;
+                       c++;
+                       
+                       handle_set_inhibit(stream, argv[c]);
+               /**********************************************************************/
+               } else {
+               /**********************************************************************/
+                       stream->write_function(stream, "Unknown \"block\" command\n");
+                       goto handle_cli_error;
+               /**********************************************************************/
+               }   
+       /**************************************************************************/
+       } else if (!strcasecmp(argv[c], "unblock")) {
+       /**************************************************************************/
+               if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
+               c++;
+
+               if (!strcasecmp(argv[c], "span")) {
+               /**********************************************************************/
+                       if (check_arg_count(argc, 5)) goto handle_cli_error_argc;
+
+                       if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
+
+                       handle_set_unblks(stream, span, chan, verbose);
+               /**********************************************************************/
+               } else if (!strcasecmp(argv[c], "link")) {
+               /**********************************************************************/
+                       if (check_arg_count(argc, 3)) goto handle_cli_error_argc;
+                       c++;
+                       
+                       handle_set_uninhibit(stream, argv[c]);
+               /**********************************************************************/
+               } else {
+               /**********************************************************************/
+                       stream->write_function(stream, "Unknown \"unblock\" command\n");
+                       goto handle_cli_error;
+               /**********************************************************************/
+               } 
+       /**************************************************************************/
+       } else {
+       /**************************************************************************/
+               goto handle_cli_error;
+       /**************************************************************************/
+       }
+
+       return FTDM_SUCCESS;
 
 handle_cli_error_argc:
-    stream->write_function(stream, "Invalid # of arguments in command\n");
-    handle_print_usuage(stream);
-    return FTDM_SUCCESS;
+       stream->write_function(stream, "Invalid # of arguments in command\n");
+       handle_print_usuage(stream);
+       return FTDM_SUCCESS;
 
 handle_cli_error_span_chan:
-    stream->write_function(stream, "Unknown \"span\\chan\" command\n");
-    handle_print_usuage(stream);
-    return FTDM_SUCCESS;
+       stream->write_function(stream, "Unknown \"span\\chan\" command\n");
+       handle_print_usuage(stream);
+       return FTDM_SUCCESS;
 
 handle_cli_error:
-    stream->write_function(stream, "Unknown command requested\n");
-    handle_print_usuage(stream);
-    return FTDM_SUCCESS;
+       stream->write_function(stream, "Unknown command requested\n");
+       handle_print_usuage(stream);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream)
 {
-    stream->write_function(stream, "Sangoma SS7 CLI usuage:\n\n");
-
-    stream->write_function(stream, "Ftmod_sangoma_ss7 general control:\n");
-    stream->write_function(stream, "ftdm ss7 set ftace X Y\n");
-    stream->write_function(stream, "ftdm ss7 set mtace X Y\n");
-    stream->write_function(stream, "\n");
-    stream->write_function(stream, "Ftmod_sangoma_ss7 information:\n");
-    stream->write_function(stream, "ftdm ss7 show status link X\n");
-    stream->write_function(stream, "ftdm ss7 show status linkset X\n");
-    stream->write_function(stream, "ftdm ss7 show status span X chan Y\n");
-    stream->write_function(stream, "ftdm ss7 show free span X chan Y\n");
-    stream->write_function(stream, "ftdm ss7 show inuse span X chan Y\n");
-    stream->write_function(stream, "ftdm ss7 show inreset span X chan Y\n");
-    stream->write_function(stream, "\n");
-    stream->write_function(stream, "Ftmod_sangoma_ss7 circuit control:\n");
-    stream->write_function(stream, "ftdm ss7 set block span X chan Y\n");
-    stream->write_function(stream, "ftdm ss7 set unblk span X chan Y\n");
-    stream->write_function(stream, "\n");
-
-    return FTDM_SUCCESS;
+       stream->write_function(stream, "Sangoma SS7 CLI usuage:\n\n");
+
+       stream->write_function(stream, "Ftmod_sangoma_ss7 general control:\n");
+       stream->write_function(stream, "ftdm ss7 set ftace X Y\n");
+       stream->write_function(stream, "ftdm ss7 set mtace X Y\n");
+       stream->write_function(stream, "\n");
+       stream->write_function(stream, "Ftmod_sangoma_ss7 information:\n");
+       stream->write_function(stream, "ftdm ss7 show status link X\n");
+       stream->write_function(stream, "ftdm ss7 show status linkset X\n");
+       stream->write_function(stream, "ftdm ss7 show status span X chan Y\n");
+       stream->write_function(stream, "ftdm ss7 show free span X chan Y\n");
+       stream->write_function(stream, "ftdm ss7 show inuse span X chan Y\n");
+       stream->write_function(stream, "ftdm ss7 show inreset span X chan Y\n");
+       stream->write_function(stream, "\n");
+       stream->write_function(stream, "Ftmod_sangoma_ss7 circuit control:\n");
+       stream->write_function(stream, "ftdm ss7 block span X chan Y\n");
+       stream->write_function(stream, "ftdm ss7 unblk span X chan Y\n");
+       stream->write_function(stream, "\n");
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_set_function_trace(ftdm_stream_handle_t *stream, int on, int level)
 {
-    stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace was %s, level = %d\n",
-                            (g_ftdm_sngss7_data.function_trace == 1) ? "ON" : "OFF",
-                            g_ftdm_sngss7_data.function_trace_level);
+       stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace was %s, level = %d\n",
+                                                       (g_ftdm_sngss7_data.function_trace == 1) ? "ON" : "OFF",
+                                                       g_ftdm_sngss7_data.function_trace_level);
 
-    g_ftdm_sngss7_data.function_trace = on;
-    g_ftdm_sngss7_data.function_trace_level = level;
+       g_ftdm_sngss7_data.function_trace = on;
+       g_ftdm_sngss7_data.function_trace_level = level;
 
-    stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace now is %s, level = %d\n",
-                            (g_ftdm_sngss7_data.function_trace == 1) ? "ON" : "OFF",
-                            g_ftdm_sngss7_data.function_trace_level);
+       stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace now is %s, level = %d\n",
+                                                       (g_ftdm_sngss7_data.function_trace == 1) ? "ON" : "OFF",
+                                                       g_ftdm_sngss7_data.function_trace_level);
 
-    return FTDM_SUCCESS;
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_set_message_trace(ftdm_stream_handle_t *stream, int on, int level)
 {
-    stream->write_function(stream, "ftmod_sangoma_ss7 Message Trace was %s, level = %d\n",
-                            (g_ftdm_sngss7_data.message_trace == 1) ? "ON" : "OFF",
-                            g_ftdm_sngss7_data.message_trace_level);
+       stream->write_function(stream, "ftmod_sangoma_ss7 Message Trace was %s, level = %d\n",
+                                                       (g_ftdm_sngss7_data.message_trace == 1) ? "ON" : "OFF",
+                                                       g_ftdm_sngss7_data.message_trace_level);
 
-    g_ftdm_sngss7_data.message_trace = on;
-    g_ftdm_sngss7_data.message_trace_level = level;
+       g_ftdm_sngss7_data.message_trace = on;
+       g_ftdm_sngss7_data.message_trace_level = level;
 
-    stream->write_function(stream, "ftmod_sangoma_ss7 Message Trace now is %s, level = %d\n",
-                            (g_ftdm_sngss7_data.message_trace == 1) ? "ON" : "OFF",
-                            g_ftdm_sngss7_data.message_trace_level);
+       stream->write_function(stream, "ftmod_sangoma_ss7 Message Trace now is %s, level = %d\n",
+                                                       (g_ftdm_sngss7_data.message_trace == 1) ? "ON" : "OFF",
+                                                       g_ftdm_sngss7_data.message_trace_level);
 
-    return FTDM_SUCCESS;
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_show_free(ftdm_stream_handle_t *stream, int span, int chan, int verbose)
 {
-    int                 x;
-    int                 free;
-    sngss7_chan_data_t  *ss7_info;
-    ftdm_channel_t      *ftdmchan;
-    int                 lspan;
-    int                 lchan;
-
-    x=1;
-    free = 0;
-    while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) {
-            ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj;
-            ftdmchan = ss7_info->ftdmchan;
-
-            /* if span == 0 then all spans should be printed */
-            if (span == 0) {
-                lspan = ftdmchan->physical_span_id;
-            } else {
-                lspan = span;
-            }
-
-            /* if chan == 0 then all chans should be printed */
-            if (chan == 0) {
-                lchan = ftdmchan->physical_chan_id;
-            } else {
-                lchan = chan;
-            }
-
-            if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
-                switch (ftdmchan->state) {
-                /******************************************************************/
-                case (FTDM_CHANNEL_STATE_DOWN):
-                    if (verbose) {
-                        stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|state=%s\n",
-                                    ftdmchan->physical_span_id,
-                                    ftdmchan->physical_chan_id,
-                                    ss7_info->circuit->cic,
-                                    ftdm_channel_state2str(ftdmchan->state));
-                    } /* if (verbose) */
-
-                    /*increment the count of circuits in reset */
-                    free++;
-                    break;
-                /******************************************************************/
-                default:
-                    break;
-                /******************************************************************/
-                } /* switch (ftdmchan->state) */
-            } /* if ( span and chan) */
-        } /* if ( cic != 0) */
-
-        /* go the next circuit */
-        x++;
-    } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
-
-    stream->write_function(stream, "\nTotal # of CICs free = %d\n",free);
-
-    return FTDM_SUCCESS;
+       int                              x;
+       int                              free;
+       sngss7_chan_data_t  *ss7_info;
+       ftdm_channel_t    *ftdmchan;
+       int                              lspan;
+       int                              lchan;
+
+       x=1;
+       free = 0;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+               if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+                       ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+                       ftdmchan = ss7_info->ftdmchan;
+
+                       /* if span == 0 then all spans should be printed */
+                       if (span == 0) {
+                               lspan = ftdmchan->physical_span_id;
+                       } else {
+                               lspan = span;
+                       }
+
+                       /* if chan == 0 then all chans should be printed */
+                       if (chan == 0) {
+                               lchan = ftdmchan->physical_chan_id;
+                       } else {
+                               lchan = chan;
+                       }
+
+                       if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
+                               switch (ftdmchan->state) {
+                               /******************************************************************/
+                               case (FTDM_CHANNEL_STATE_DOWN):
+                                       if (verbose) {
+                                               stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|state=%s\n",
+                                                                       ftdmchan->physical_span_id,
+                                                                       ftdmchan->physical_chan_id,
+                                                                       ss7_info->circuit->cic,
+                                                                       ftdm_channel_state2str(ftdmchan->state));
+                                       } /* if (verbose) */
+
+                                       /*increment the count of circuits in reset */
+                                       free++;
+                                       break;
+                               /******************************************************************/
+                               default:
+                                       break;
+                               /******************************************************************/
+                               } /* switch (ftdmchan->state) */
+                       } /* if ( span and chan) */
+               } /* if ( cic != 0) */
+
+               /* go the next circuit */
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+       stream->write_function(stream, "\nTotal # of CICs free = %d\n",free);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_show_inuse(ftdm_stream_handle_t *stream, int span, int chan, int verbose)
 {
-    int                 x;
-    int                 in_use;
-    sngss7_chan_data_t  *ss7_info;
-    ftdm_channel_t      *ftdmchan;
-    int                 lspan;
-    int                 lchan;
-
-    x=1;
-    in_use = 0;
-    while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) {
-            ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj;
-            ftdmchan = ss7_info->ftdmchan;
-
-            /* if span == 0 then all spans should be printed */
-            if (span == 0) {
-                lspan = ftdmchan->physical_span_id;
-            } else {
-                lspan = span;
-            }
-
-            /* if chan == 0 then all chans should be printed */
-            if (chan == 0) {
-                lchan = ftdmchan->physical_chan_id;
-            } else {
-                lchan = chan;
-            }
-
-            if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
-                switch (ftdmchan->state) {
-                /******************************************************************/
-                case (FTDM_CHANNEL_STATE_COLLECT):
-                case (FTDM_CHANNEL_STATE_RING):
-                case (FTDM_CHANNEL_STATE_DIALING):
-                case (FTDM_CHANNEL_STATE_PROGRESS):
-                case (FTDM_CHANNEL_STATE_PROGRESS_MEDIA):
-                case (FTDM_CHANNEL_STATE_UP):
-                case (FTDM_CHANNEL_STATE_TERMINATING):
-                case (FTDM_CHANNEL_STATE_HANGUP):
-                    if (verbose) {
-                        stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|state=%s\n",
-                                    ftdmchan->physical_span_id,
-                                    ftdmchan->physical_chan_id,
-                                    ss7_info->circuit->cic,
-                                    ftdm_channel_state2str(ftdmchan->state));
-                    } /* if (verbose) */
-
-                    /*increment the count of circuits in reset */
-                    in_use++;
-                    break;
-                /******************************************************************/
-                default:
-                    break;
-                /******************************************************************/
-                } /* switch (ftdmchan->state) */
-            } /* if ( span and chan) */
-        } /* if ( cic != 0) */
-
-        /* go the next circuit */
-        x++;
-    } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
-
-    stream->write_function(stream, "\nTotal # of CICs in use = %d\n",in_use);
-
-    return FTDM_SUCCESS;
+       int                              x;
+       int                              in_use;
+       sngss7_chan_data_t  *ss7_info;
+       ftdm_channel_t    *ftdmchan;
+       int                              lspan;
+       int                              lchan;
+
+       x=1;
+       in_use = 0;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+               if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+                       ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+                       ftdmchan = ss7_info->ftdmchan;
+
+                       /* if span == 0 then all spans should be printed */
+                       if (span == 0) {
+                               lspan = ftdmchan->physical_span_id;
+                       } else {
+                               lspan = span;
+                       }
+
+                       /* if chan == 0 then all chans should be printed */
+                       if (chan == 0) {
+                               lchan = ftdmchan->physical_chan_id;
+                       } else {
+                               lchan = chan;
+                       }
+
+                       if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
+                               switch (ftdmchan->state) {
+                               /******************************************************************/
+                               case (FTDM_CHANNEL_STATE_COLLECT):
+                               case (FTDM_CHANNEL_STATE_RING):
+                               case (FTDM_CHANNEL_STATE_DIALING):
+                               case (FTDM_CHANNEL_STATE_PROGRESS):
+                               case (FTDM_CHANNEL_STATE_PROGRESS_MEDIA):
+                               case (FTDM_CHANNEL_STATE_UP):
+                               case (FTDM_CHANNEL_STATE_TERMINATING):
+                               case (FTDM_CHANNEL_STATE_HANGUP):
+                                       if (verbose) {
+                                               stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|state=%s\n",
+                                                                       ftdmchan->physical_span_id,
+                                                                       ftdmchan->physical_chan_id,
+                                                                       ss7_info->circuit->cic,
+                                                                       ftdm_channel_state2str(ftdmchan->state));
+                                       } /* if (verbose) */
+
+                                       /*increment the count of circuits in reset */
+                                       in_use++;
+                                       break;
+                               /******************************************************************/
+                               default:
+                                       break;
+                               /******************************************************************/
+                               } /* switch (ftdmchan->state) */
+                       } /* if ( span and chan) */
+               } /* if ( cic != 0) */
+
+               /* go the next circuit */
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+       stream->write_function(stream, "\nTotal # of CICs in use = %d\n",in_use);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span, int chan, int verbose)
 {
-    int                 x;
-    int                 in_reset;
-    sngss7_chan_data_t  *ss7_info;
-    ftdm_channel_t      *ftdmchan;
-    int                 lspan;
-    int                 lchan;
-
-    x=1;
-    in_reset = 0;
-    while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) {
-            ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj;
-            ftdmchan = ss7_info->ftdmchan;
-
-            /* if span == 0 then all spans should be printed */
-            if (span == 0) {
-                lspan = ftdmchan->physical_span_id;
-            } else {
-                lspan = span;
-            }
-
-            /* if chan == 0 then all chans should be printed */
-            if (chan == 0) {
-                lchan = ftdmchan->physical_chan_id;
-            } else {
-                lchan = chan;
-            }
-
-            if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
-                if ((sngss7_test_flag(ss7_info, FLAG_RESET_RX)) || (sngss7_test_flag(ss7_info, FLAG_RESET_TX))) {
-                    if (verbose) {
-                        stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|in_reset=Y\n",
-                                    ftdmchan->physical_span_id,
-                                    ftdmchan->physical_chan_id,
-                                    ss7_info->circuit->cic);
-                    } /* if (verbose) */
-        
-                    /*increment the count of circuits in reset */
-                    in_reset++;
-                } /* if ((sngss7_test_flag(ss7_info, FLAG_RESET_RX) ... */
-            } /* if ( span and chan) */
-        } /* if ( cic != 0) */
-
-        /* go the next circuit */
-        x++;
-    } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
-
-    stream->write_function(stream, "\nTotal # of CICs in reset = %d\n",in_reset);
-
-    return FTDM_SUCCESS;
+       int                              x;
+       int                              in_reset;
+       sngss7_chan_data_t  *ss7_info;
+       ftdm_channel_t    *ftdmchan;
+       int                              lspan;
+       int                              lchan;
+
+       x=1;
+       in_reset = 0;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+               if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+                       ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+                       ftdmchan = ss7_info->ftdmchan;
+
+                       /* if span == 0 then all spans should be printed */
+                       if (span == 0) {
+                               lspan = ftdmchan->physical_span_id;
+                       } else {
+                               lspan = span;
+                       }
+
+                       /* if chan == 0 then all chans should be printed */
+                       if (chan == 0) {
+                               lchan = ftdmchan->physical_chan_id;
+                       } else {
+                               lchan = chan;
+                       }
+
+                       if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
+                               if ((sngss7_test_flag(ss7_info, FLAG_RESET_RX)) ||
+                                       (sngss7_test_flag(ss7_info, FLAG_RESET_TX)) ||
+                                       (sngss7_test_flag(ss7_info, FLAG_GRP_RESET_RX)) ||
+                                       (sngss7_test_flag(ss7_info, FLAG_GRP_RESET_TX))) {
+                                       
+                                       if (verbose) {
+                                               stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|in_reset=Y\n",
+                                                                       ftdmchan->physical_span_id,
+                                                                       ftdmchan->physical_chan_id,
+                                                                       ss7_info->circuit->cic);
+                                       } /* if (verbose) */
+               
+                                       /*increment the count of circuits in reset */
+                                       in_reset++;
+                               } /* if ((sngss7_test_flag(ss7_info, FLAG_RESET_RX) ... */
+                       } /* if ( span and chan) */
+               } /* if ( cic != 0) */
+
+               /* go the next circuit */
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+       stream->write_function(stream, "\nTotal # of CICs in reset = %d\n",in_reset);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, int chan, int verbose)
 {
-    int                 x;
-    int                 bit;
-    sngss7_chan_data_t  *ss7_info;
-    ftdm_channel_t      *ftdmchan;
-    int                 lspan;
-    int                 lchan;
-
-    x=1;
-    while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) {
-            ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj;
-            ftdmchan = ss7_info->ftdmchan;
-
-            /* if span == 0 then all spans should be printed */
-            if (span == 0) {
-                lspan = ftdmchan->physical_span_id;
-            } else {
-                lspan = span;
-            }
-
-            /* if chan == 0 then all chans should be printed */
-            if (chan == 0) {
-                lchan = ftdmchan->physical_chan_id;
-            } else {
-                lchan = chan;
-            }
-
-            if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
-                stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d",
-                            ftdmchan->physical_span_id,
-                            ftdmchan->physical_chan_id,
-                            ss7_info->circuit->cic);
-    
-                for (bit = 0; bit < 33; bit++) {
-                    stream->write_function(stream, "|");
-                    if (ss7_info->flags & ( 0x1 << bit)) {
-                        stream->write_function(stream, "%2d=1", bit);
-                    } else {
-                        stream->write_function(stream, "%2d=0", bit);
-                    }
-                }
-
-                stream->write_function(stream, "\n");
-            } /* if ( span and chan) */
-
-        } /* if ( cic != 0) */
-
-        /* go the next circuit */
-        x++;
-    } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
-
-    return FTDM_SUCCESS;
+       int                              x;
+       int                              bit;
+       sngss7_chan_data_t  *ss7_info;
+       ftdm_channel_t    *ftdmchan;
+       int                              lspan;
+       int                              lchan;
+
+       x=1;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+               if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+                       ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+                       ftdmchan = ss7_info->ftdmchan;
+
+                       /* if span == 0 then all spans should be printed */
+                       if (span == 0) {
+                               lspan = ftdmchan->physical_span_id;
+                       } else {
+                               lspan = span;
+                       }
+
+                       /* if chan == 0 then all chans should be printed */
+                       if (chan == 0) {
+                               lchan = ftdmchan->physical_chan_id;
+                       } else {
+                               lchan = chan;
+                       }
+
+                       if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
+                               stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d",
+                                                       ftdmchan->physical_span_id,
+                                                       ftdmchan->physical_chan_id,
+                                                       ss7_info->circuit->cic);
+       
+                               for (bit = 0; bit < 33; bit++) {
+                                       stream->write_function(stream, "|");
+                                       if (ss7_info->flags & ( 0x1 << bit)) {
+                                               stream->write_function(stream, "%2d=1", bit);
+                                       } else {
+                                               stream->write_function(stream, "%2d=0", bit);
+                                       }
+                               }
+
+                               stream->write_function(stream, "\n");
+                       } /* if ( span and chan) */
+
+               } /* if ( cic != 0) */
+
+               /* go the next circuit */
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose)
 {
-    int                 x;
-    sngss7_chan_data_t  *ss7_info;
-    ftdm_channel_t      *ftdmchan;
-    int                 lspan;
-    int                 lchan;
-
-    x=1;
-    while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) {
-            ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj;
-            ftdmchan = ss7_info->ftdmchan;
-
-            /* if span == 0 then all spans should be printed */
-            if (span == 0) {
-                lspan = ftdmchan->physical_span_id;
-            } else {
-                lspan = span;
-            }
-
-            /* if chan == 0 then all chans should be printed */
-            if (chan == 0) {
-                lchan = ftdmchan->physical_chan_id;
-            } else {
-                lchan = chan;
-            }
-
-            if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
-                stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|",
-                            ftdmchan->physical_span_id,
-                            ftdmchan->physical_chan_id,
-                            ss7_info->circuit->cic);
-
-                if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) {
-                    stream->write_function(stream, "l_mn=Y|");
-                }else {
-                    stream->write_function(stream, "l_mn=N|");
-                }
-
-                if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) {
-                    stream->write_function(stream, "r_mn=Y|");
-                }else {
-                    stream->write_function(stream, "r_mn=N|");
-                }
-
-                if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) {
-                    stream->write_function(stream, "l_hw=Y|");
-                }else {
-                    stream->write_function(stream, "l_hw=N|");
-                }
-
-                if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
-                    stream->write_function(stream, "r_hw=Y\n");
-                }else {
-                    stream->write_function(stream, "r_hw=N\n");
-                }
-            } /* if ( span and chan) */
-
-        } /* if ( cic != 0) */
-
-        /* go the next circuit */
-        x++;
-    } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
-
-    return FTDM_SUCCESS;
+       int                              x;
+       sngss7_chan_data_t  *ss7_info;
+       ftdm_channel_t    *ftdmchan;
+       int                              lspan;
+       int                              lchan;
+
+       x=1;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+               if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+                       ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+                       ftdmchan = ss7_info->ftdmchan;
+
+                       /* if span == 0 then all spans should be printed */
+                       if (span == 0) {
+                               lspan = ftdmchan->physical_span_id;
+                       } else {
+                               lspan = span;
+                       }
+
+                       /* if chan == 0 then all chans should be printed */
+                       if (chan == 0) {
+                               lchan = ftdmchan->physical_chan_id;
+                       } else {
+                               lchan = chan;
+                       }
+
+                       if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
+                               stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|",
+                                                       ftdmchan->physical_span_id,
+                                                       ftdmchan->physical_chan_id,
+                                                       ss7_info->circuit->cic);
+
+                               if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) {
+                                       stream->write_function(stream, "l_mn=Y|");
+                               }else {
+                                       stream->write_function(stream, "l_mn=N|");
+                               }
+
+                               if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+                                       stream->write_function(stream, "r_mn=Y|");
+                               }else {
+                                       stream->write_function(stream, "r_mn=N|");
+                               }
+
+                               if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) {
+                                       stream->write_function(stream, "l_hw=Y|");
+                               }else {
+                                       stream->write_function(stream, "l_hw=N|");
+                               }
+
+                               if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
+                                       stream->write_function(stream, "r_hw=Y|");
+                               }else {
+                                       stream->write_function(stream, "r_hw=N|");
+                               }
+
+                               if(sngss7_test_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) {
+                                       stream->write_function(stream, "l_mngmt=Y|");
+                               }else {
+                                       stream->write_function(stream, "l_mngmt=N|");
+                               }
+
+                               if(sngss7_test_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) {
+                                       stream->write_function(stream, "l_ucic=Y|");
+                               }else {
+                                       stream->write_function(stream, "l_ucic=N|");
+                               } 
+
+                               stream->write_function(stream, "\n");                           
+                       } /* if ( span and chan) */
+
+               } /* if ( cic != 0) */
+
+               /* go the next circuit */
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, int chan, int verbose)
 {
-    int                 x;
-    sngss7_chan_data_t  *ss7_info;
-    ftdm_channel_t      *ftdmchan;
-    int                 lspan;
-    int                 lchan;
-    ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN;
-
-    x=1;
-    while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) {
-            ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj;
-            ftdmchan = ss7_info->ftdmchan;
-
-            /* if span == 0 then all spans should be printed */
-            if (span == 0) {
-                lspan = ftdmchan->physical_span_id;
-            } else {
-                lspan = span;
-            }
-
-            /* if chan == 0 then all chans should be printed */
-            if (chan == 0) {
-                lchan = ftdmchan->physical_chan_id;
-            } else {
-                lchan = chan;
-            }
-
-            if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
-                /* grab the signaling_status */
-                ftdm_channel_get_sig_status(ftdmchan, &sigstatus);
-
-                stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%s|state=%s|",
-                            ftdmchan->physical_span_id,
-                            ftdmchan->physical_chan_id,
-                            ss7_info->circuit->cic,
-                            ftdm_signaling_status2str(sigstatus),
-                            ftdm_channel_state2str(ftdmchan->state));
-
-                if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) {
-                    stream->write_function(stream, "l_mn=Y|");
-                }else {
-                    stream->write_function(stream, "l_mn=N|");
-                }
-
-                if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) {
-                    stream->write_function(stream, "r_mn=Y|");
-                }else {
-                    stream->write_function(stream, "r_mn=N|");
-                }
-
-                if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) {
-                    stream->write_function(stream, "l_hw=Y|");
-                }else {
-                    stream->write_function(stream, "l_hw=N|");
-                }
-
-                if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
-                    stream->write_function(stream, "r_hw=Y\n");
-                }else {
-                    stream->write_function(stream, "r_hw=N\n");
-                }
-            } /* if ( span and chan) */
-
-        } /* if ( cic != 0) */
-
-        /* go the next circuit */
-        x++;
-    } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
-
-    return FTDM_SUCCESS;
-
-    return FTDM_SUCCESS;
+       int                              x;
+       sngss7_chan_data_t  *ss7_info;
+       ftdm_channel_t    *ftdmchan;
+       int                              lspan;
+       int                              lchan;
+       ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN;
+
+       x=1;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+               if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+                       ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+                       ftdmchan = ss7_info->ftdmchan;
+
+                       /* if span == 0 then all spans should be printed */
+                       if (span == 0) {
+                               lspan = ftdmchan->physical_span_id;
+                       } else {
+                               lspan = span;
+                       }
+
+                       /* if chan == 0 then all chans should be printed */
+                       if (chan == 0) {
+                               lchan = ftdmchan->physical_chan_id;
+                       } else {
+                               lchan = chan;
+                       }
+
+                       if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
+                               /* grab the signaling_status */
+                               ftdm_channel_get_sig_status(ftdmchan, &sigstatus);
+
+                               stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%s|state=%s|",
+                                                       ftdmchan->physical_span_id,
+                                                       ftdmchan->physical_chan_id,
+                                                       ss7_info->circuit->cic,
+                                                       ftdm_signaling_status2str(sigstatus),
+                                                       ftdm_channel_state2str(ftdmchan->state));
+
+                               if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) {
+                                       stream->write_function(stream, "l_mn=Y|");
+                               }else {
+                                       stream->write_function(stream, "l_mn=N|");
+                               }
+
+                               if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+                                       stream->write_function(stream, "r_mn=Y|");
+                               }else {
+                                       stream->write_function(stream, "r_mn=N|");
+                               }
+
+                               if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) {
+                                       stream->write_function(stream, "l_hw=Y|");
+                               }else {
+                                       stream->write_function(stream, "l_hw=N|");
+                               }
+
+                               if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
+                                       stream->write_function(stream, "r_hw=Y|");
+                               }else {
+                                       stream->write_function(stream, "r_hw=N|");
+                               }
+
+                               if(sngss7_test_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) {
+                                       stream->write_function(stream, "l_mngmt=Y|");
+                               }else {
+                                       stream->write_function(stream, "l_mngmt=N|");
+                               }
+
+                               if(sngss7_test_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) {
+                                       stream->write_function(stream, "l_ucic=Y|");
+                               }else {
+                                       stream->write_function(stream, "l_ucic=N|");
+                               }                               
+
+                               stream->write_function(stream, "flags=0x%X",ss7_info->flags);
+
+                               stream->write_function(stream, "\n");   
+                       } /* if ( span and chan) */
+
+               } /* if ( cic != 0) */
+
+               /* go the next circuit */
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+       return FTDM_SUCCESS;
 }
 /******************************************************************************/
 static ftdm_status_t handle_set_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose)
 {
-    int                 x;
-    sngss7_chan_data_t  *ss7_info;
-    ftdm_channel_t      *ftdmchan;
-    int                 lspan;
-    int                 lchan;
-
-    x=1;
-    while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) {
-            ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj;
-            ftdmchan = ss7_info->ftdmchan;
-
-            /* if span == 0 then all spans should be printed */
-            if (span == 0) {
-                lspan = ftdmchan->physical_span_id;
-            } else {
-                lspan = span;
-            }
-
-            /* if chan == 0 then all chans should be printed */
-            if (chan == 0) {
-                lchan = ftdmchan->physical_chan_id;
-            } else {
-                lchan = chan;
-            }
-
-            if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
-                /* now that we have the right channel...put a lock on it so no-one else can use it */
-                ftdm_mutex_lock(ftdmchan->mutex);
-
-                /* check if there is a pending state change|give it a bit to clear */
-                if (check_for_state_change(ftdmchan)) {
-                    SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic);
-                } else {
-                    /* throw the ckt block flag */
-                    sngss7_set_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
-
-                    /* set the channel to suspended state */
-                    ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
-                }
-
-                /* unlock the channel again before we exit */
-                ftdm_mutex_unlock(ftdmchan->mutex);
-
-            } /* if ( span and chan) */
-
-        } /* if ( cic != 0) */
-
-        /* go the next circuit */
-        x++;
-    } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
-
-    handle_show_blocks(stream, span, chan, verbose);
-
-    return FTDM_SUCCESS;
+       int                              x;
+       sngss7_chan_data_t  *ss7_info;
+       ftdm_channel_t    *ftdmchan;
+       int                              lspan;
+       int                              lchan;
+
+       x=1;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+               if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+                       ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+                       ftdmchan = ss7_info->ftdmchan;
+
+                       /* if span == 0 then all spans should be printed */
+                       if (span == 0) {
+                               lspan = ftdmchan->physical_span_id;
+                       } else {
+                               lspan = span;
+                       }
+
+                       /* if chan == 0 then all chans should be printed */
+                       if (chan == 0) {
+                               lchan = ftdmchan->physical_chan_id;
+                       } else {
+                               lchan = chan;
+                       }
+
+                       if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
+                               /* now that we have the right channel...put a lock on it so no-one else can use it */
+                               ftdm_mutex_lock(ftdmchan->mutex);
+
+                               /* check if there is a pending state change|give it a bit to clear */
+                               if (check_for_state_change(ftdmchan)) {
+                                       SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic);
+                                       SS7_ASSERT;
+                               } else {
+                                       /* throw the ckt block flag */
+                                       sngss7_set_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
+
+                                       /* set the channel to suspended state */
+                                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+                               }
+
+                               /* unlock the channel again before we exit */
+                               ftdm_mutex_unlock(ftdmchan->mutex);
+
+                       } /* if ( span and chan) */
+
+               } /* if ( cic != 0) */
+
+               /* go the next circuit */
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+       handle_show_blocks(stream, span, chan, verbose);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_set_unblks(ftdm_stream_handle_t *stream, int span, int chan, int verbose)
 {
-    int                 x;
-    sngss7_chan_data_t  *ss7_info;
-    ftdm_channel_t      *ftdmchan;
-    int                 lspan;
-    int                 lchan;
-
-    x=1;
-    while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) {
-            ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj;
-            ftdmchan = ss7_info->ftdmchan;
-
-            /* if span == 0 then all spans should be printed */
-            if (span == 0) {
-                lspan = ftdmchan->physical_span_id;
-            } else {
-                lspan = span;
-            }
-
-            /* if chan == 0 then all chans should be printed */
-            if (chan == 0) {
-                lchan = ftdmchan->physical_chan_id;
-            } else {
-                lchan = chan;
-            }
-
-            if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
-                /* now that we have the right channel...put a lock on it so no-one else can use it */
-                ftdm_mutex_lock(ftdmchan->mutex);
-
-                /* check if there is a pending state change|give it a bit to clear */
-                if (check_for_state_change(ftdmchan)) {
-                    SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic);
-                } else {
-                    /* throw the ckt block flag */
-                    sngss7_set_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX);
-
-                    /* clear the block flag */
-                    sngss7_clear_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
-
-                    /* set the channel to suspended state */
-                    ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
-                }
-
-                /* unlock the channel again before we exit */
-                ftdm_mutex_unlock(ftdmchan->mutex);
-
-            } /* if ( span and chan) */
-
-        } /* if ( cic != 0) */
-
-        /* go the next circuit */
-        x++;
-    } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
-
-    handle_show_blocks(stream, span, chan, verbose);
-
-    return FTDM_SUCCESS;
+       int                              x;
+       sngss7_chan_data_t  *ss7_info;
+       ftdm_channel_t    *ftdmchan;
+       int                              lspan;
+       int                              lchan;
+
+       x=1;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+               if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+                       ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+                       ftdmchan = ss7_info->ftdmchan;
+
+                       /* if span == 0 then all spans should be printed */
+                       if (span == 0) {
+                               lspan = ftdmchan->physical_span_id;
+                       } else {
+                               lspan = span;
+                       }
+
+                       /* if chan == 0 then all chans should be printed */
+                       if (chan == 0) {
+                               lchan = ftdmchan->physical_chan_id;
+                       } else {
+                               lchan = chan;
+                       }
+
+                       if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
+                               /* now that we have the right channel...put a lock on it so no-one else can use it */
+                               ftdm_mutex_lock(ftdmchan->mutex);
+
+                               /* check if there is a pending state change|give it a bit to clear */
+                               if (check_for_state_change(ftdmchan)) {
+                                       SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic);
+                                       SS7_ASSERT;
+                               } else {
+                                       /* throw the ckt block flag */
+                                       sngss7_set_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX);
+
+                                       /* clear the block flag */
+                                       sngss7_clear_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
+
+                                       /* set the channel to suspended state */
+                                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+                               }
+
+                               /* unlock the channel again before we exit */
+                               ftdm_mutex_unlock(ftdmchan->mutex);
+
+                       } /* if ( span and chan) */
+
+               } /* if ( cic != 0) */
+
+               /* go the next circuit */
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+       handle_show_blocks(stream, span, chan, verbose);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name)
 {
-    int x;
-    sng_mtp3Link_sta_t  sta;
-
-    /* find the link request by it's name */
-    x = 1;
-    while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) {
-        if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
-            /* send the status request */
-            if (sng_sta_mtp3_link(&g_ftdm_sngss7_data.cfg, x, &sta)) {
-                stream->write_function(stream, "Failed to read link=%s status\n", name);
-                return FTDM_FAIL;
-            }
-
-            /* print the results */
-            stream->write_function(stream, "%s|state=%s|l_blk=%s|r_blk=%s|l_inhbt=%s|r_inhbt=%s\n",
-                        name,
-                        DECODE_LSN_LINK_STATUS(sta.state),
-                        (sta.lblkd) ? "Y":"N",
-                        (sta.rblkd) ? "Y":"N",
-                        (sta.linhbt) ? "Y":"N",
-                        (sta.rinhbt) ? "Y":"N");
-            break;
-        }
-        
-        /* move to the next link */
-        x++;
-    } /* while (id != 0) */
-
-    return FTDM_SUCCESS;
+       int             x = 0;
+       SnMngmt         sta;
+       
+       /* find the link request by it's name */
+       x = 1;
+       while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
+               if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
+
+                       /* send the status request */
+                       if (ftmod_ss7_mtplink_sta(x, &sta)) {
+                               stream->write_function(stream, "Failed to read link=%s status\n", name);
+                               return FTDM_FAIL;
+                       }
+
+                       /* print the results */
+                       stream->write_function(stream, "%s|span=%d|chan=%d|sap=%d|state=%s|l_blk=%s|r_blk=%s|l_inhbt=%s|r_inhbt=%s\n",
+                                               name,
+                                               g_ftdm_sngss7_data.cfg.mtpLink[x].mtp1.span,
+                                               g_ftdm_sngss7_data.cfg.mtpLink[x].mtp1.chan,
+                                               g_ftdm_sngss7_data.cfg.mtpLink[x].id,
+                                               DECODE_LSN_LINK_STATUS(sta.t.ssta.s.snDLSAP.state),
+                                               (sta.t.ssta.s.snDLSAP.locBlkd) ? "Y":"N",
+                                               (sta.t.ssta.s.snDLSAP.remBlkd) ? "Y":"N",
+                                               (sta.t.ssta.s.snDLSAP.locInhbt) ? "Y":"N",
+                                               (sta.t.ssta.s.snDLSAP.rmtInhbt) ? "Y":"N");
+                       break;
+               }
+               
+               /* move to the next link */
+               x++;
+       } /* while (id != 0) */
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name)
 {
-    int x;
-    sng_mtp3LinkSet_sta_t  sta;
-
-    /* find the linkset request by it's name */
-    x = 1;
-    while(g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].id != 0) {
-        if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].name, name)) {
-            /* send the status request */
-            if (sng_sta_mtp3_linkset(&g_ftdm_sngss7_data.cfg, x, 0, &sta)) {
-                stream->write_function(stream, "Failed to read linkset=%s status\n", name);
-                return FTDM_FAIL;
-            }
-
-            /* print the results */
-            stream->write_function(stream, "%s|state=%s|nmbActLnk=%d\n",
-                        name,
-                        DECODE_LSN_LINKSET_STATUS(sta.state),
-                        sta.nmbActLnks);
-            break;
-        }
+       int             x = 0;
+       SnMngmt         sta;
+
+       /* find the linkset request by it's name */
+       x = 1;
+       while(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) {
+               if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, name)) {
+
+                       /* send the status request */
+                       if (ftmod_ss7_mtplinkSet_sta(x, &sta)) {
+                               stream->write_function(stream, "Failed to read linkset=%s status\n", name);
+                               return FTDM_FAIL;
+                       }
+
+                       /* print the results */
+                       stream->write_function(stream, "%s|state=%s|nmbActLnk=%d\n",
+                                               name,
+                                               DECODE_LSN_LINKSET_STATUS(sta.t.ssta.s.snLnkSet.state),
+                                               sta.t.ssta.s.snLnkSet.nmbActLnks);
+                       break;
+               }
  
-        /* move to the next linkset */
-        x++;
-    } /* while (id != 0) */
+               /* move to the next linkset */
+               x++;
+       } /* while (id != 0) */
 
-    return FTDM_SUCCESS;
+       return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name)
+{
+       int             x = 0;
+
+       /* find the link request by it's name */
+       x = 1;
+       while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
+               if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
+
+                       /* send the inhibit request */
+                       if (ftmod_ss7_inhibit_mtplink(x)) {
+                               stream->write_function(stream, "Failed to inhibit link=%s\n", name);
+                               return FTDM_FAIL;
+                       }
+
+                       /* print the new status of the link */
+                       handle_status_link(stream, &name[0]);
+
+                       break;
+               }
+               /* move to the next linkset */
+               x++;
+       } /* while (id != 0) */
+
+       return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *name)
+{
+       int             x = 0;
+
+       /* find the link request by it's name */
+       x = 1;
+       while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
+               if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
+
+                       /* send the uninhibit request */
+                       if (ftmod_ss7_uninhibit_mtplink(x)) {
+                               stream->write_function(stream, "Failed to uninhibit link=%s\n", name);
+                               return FTDM_FAIL;
+                       }
+
+                       /* print the new status of the link */
+                       handle_status_link(stream, &name[0]);
+
+                       break;
+               }
+               /* move to the next linkset */
+               x++;
+       } /* while (id != 0) */
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan)
 {
 
-    if (!strcasecmp(argv[pos], "span")) {
-    /**************************************************************************/
-        pos++;
-        *span = atoi(argv[pos]);
-
-        pos++;
-        if (!strcasecmp(argv[pos], "chan")) {
-        /**********************************************************************/
-            pos++;
-            *chan = atoi(argv[pos]);
-        /**********************************************************************/
-        } else {
-        /**********************************************************************/
-            return FTDM_FAIL;
-        /**********************************************************************/
-        }
-    /**************************************************************************/
-    } else {
-    /**************************************************************************/
-        *span = atoi(argv[pos]);
-
-        pos++;
-        if (!strcasecmp(argv[pos], "chan")) {
-        /**********************************************************************/
-            pos++;
-            *chan = atoi(argv[pos]);
-        /**********************************************************************/
-        } else {
-        /**********************************************************************/
-            return FTDM_FAIL;
-        /**********************************************************************/
-        }
-    /**************************************************************************/
-    }
-
-    return FTDM_SUCCESS;
+       if (!strcasecmp(argv[pos], "span")) {
+       /**************************************************************************/
+               pos++;
+               *span = atoi(argv[pos]);
+
+               pos++;
+               if (!strcasecmp(argv[pos], "chan")) {
+               /**********************************************************************/
+                       pos++;
+                       *chan = atoi(argv[pos]);
+               /**********************************************************************/
+               } else {
+               /**********************************************************************/
+                       return FTDM_FAIL;
+               /**********************************************************************/
+               }
+       /**************************************************************************/
+       } else {
+       /**************************************************************************/
+               *span = atoi(argv[pos]);
+
+               pos++;
+               if (!strcasecmp(argv[pos], "chan")) {
+               /**********************************************************************/
+                       pos++;
+                       *chan = atoi(argv[pos]);
+               /**********************************************************************/
+               } else {
+               /**********************************************************************/
+                       return FTDM_FAIL;
+               /**********************************************************************/
+               }
+       /**************************************************************************/
+       }
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static ftdm_status_t check_arg_count(int args, int min)
 {
-    if ( args < min ) {
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
-}        
+       if ( args < min ) {
+               return FTDM_FAIL;
+       } else {
+               return FTDM_SUCCESS;
+       }
+}              
 
 /******************************************************************************/
 /* For Emacs:
index 66f3003832939693b432d661ab03e3c34e185590..52b3860375ad54a7429a44feed231972bc34658a 100644 (file)
 /******************************************************************************/
 
 /* PROTOTYPES *****************************************************************/
-void handle_sng_log(uint8_t level, char *fmt,...);
-void handle_sng_alarm(sng_alrm_t t_alarm);
+int ft_to_sngss7_activate_all(void);
 
-static void handle_entsi_alarm(sng_alrm_t t_alarm);
+static int ftmod_ss7_enable_isap(int suId);
+static int ftmod_ss7_enable_nsap(int suId);
+static int ftmod_ss7_enable_mtpLinkSet(int lnkSetId);
 
-int ft_to_sngss7_cfg(void);
-int ft_to_sngss7_activate_all(void);
+int ftmod_ss7_inhibit_mtplink(uint32_t id);
+int ftmod_ss7_uninhibit_mtplink(uint32_t id);
+/******************************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+int ft_to_sngss7_activate_all(void)
+{
+       int x;
+
+       x = 1;
+       while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) {
+               /* check if this link has already been actived */
+               if (!(g_ftdm_sngss7_data.cfg.isap[x].flags & ACTIVE)) {
+
+                       if (ftmod_ss7_enable_isap(x)) { 
+                               SS7_CRITICAL("ISAP %d Enable: NOT OK\n", x);
+                               SS7_ASSERT;
+                       } else {
+                               SS7_INFO("ISAP %d Enable: OK\n", x);
+                       }
+
+                       /* set the ACTIVE flag */
+                       g_ftdm_sngss7_data.cfg.isap[x].flags |= ACTIVE;
+               } /* if !ACTIVE */
+               
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) */
+
+       x = 1;
+       while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) {
+               /* check if this link has already been actived */
+               if (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & ACTIVE)) {
+
+                       if (ftmod_ss7_enable_nsap(x)) { 
+                               SS7_CRITICAL("NSAP %d Enable: NOT OK\n", x);
+                               SS7_ASSERT;
+                       } else {
+                               SS7_INFO("NSAP %d Enable: OK\n", x);
+                       }
+
+                       /* set the ACTIVE flag */
+                       g_ftdm_sngss7_data.cfg.nsap[x].flags |= ACTIVE;
+               } /* if !ACTIVE */
+               
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) */
+
+       x = 1;
+       while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) {
+               /* check if this link has already been actived */
+               if (!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & ACTIVE)) {
+
+                       if (ftmod_ss7_enable_mtpLinkSet(x)) {   
+                               SS7_CRITICAL("LinkSet \"%s\" Enable: NOT OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
+                               SS7_ASSERT;
+                       } else {
+                               SS7_INFO("LinkSet \"%s\" Enable: OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
+                       }
+
+                       /* set the ACTIVE flag */
+                       g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= ACTIVE;
+               } /* if !ACTIVE */
+               
+               x++;
+       } /* while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) */
+
+       return 0;
+}
 
-static int ftmod_ss7_general_configuration(void);
+/******************************************************************************/
+static int ftmod_ss7_enable_isap(int suId)
+{
+       CcMngmt cntrl;
+       Pst pst;
 
-static int ftmod_ss7_configure_mtp1_link(int id);
+       /* initalize the post structure */
+       smPstInit(&pst);
 
-static int ftmod_ss7_configure_mtp2_link(int id);
+       /* insert the destination Entity */
+       pst.dstEnt = ENTCC;
 
-static int ftmod_ss7_configure_mtp3_link(int id);
-static int ftmod_ss7_configure_mtp3_linkset(int id);
-static int ftmod_ss7_configure_mtp3_route(int id);
-static int ftmod_ss7_configure_mtp3_isup(int id);
+       /* initalize the control structure */
+       memset(&cntrl, 0x0, sizeof(CcMngmt));
 
-static int ftmod_ss7_configure_isup_mtp3(int id);
-static int ftmod_ss7_configure_isup_interface(int id);
-static int ftmod_ss7_configure_isup_circuit(int id);
-static int ftmod_ss7_configure_isup_cc(int id);
+       /* initalize the control header */
+       smHdrInit(&cntrl.hdr);
 
-static int ftmod_ss7_configure_cc_isup(int id);
+       cntrl.hdr.msgType                       = TCNTRL;               /* this is a control request */
+       cntrl.hdr.entId.ent                     = ENTCC;
+       cntrl.hdr.entId.inst            = S_INST;
+       cntrl.hdr.elmId.elmnt           = STISAP;
 
-/******************************************************************************/
+       cntrl.hdr.elmId.elmntInst1      = suId;                 /* this is the SAP to bind */
 
-/* FUNCTIONS ******************************************************************/
+       cntrl.t.cntrl.action            = ABND_ENA;             /* bind and activate */
+       cntrl.t.cntrl.subAction         = SAELMNT;              /* specificed element */
 
-/* LOGGIGING ******************************************************************/
-void handle_sng_log(uint8_t level, char *fmt,...)
-{
-    char    *data;
-    int     ret;
-    va_list ap;
-
-    va_start(ap, fmt);
-    ret = vasprintf(&data, fmt, ap);
-    if (ret == -1) {
-        return;
-    }
-
-    switch (level) {
-    /**************************************************************************/
-    case SNG_LOGLEVEL_DEBUG:
-        ftdm_log(FTDM_LOG_DEBUG, "sng_ss7->%s", data);
-        break;
-    /**************************************************************************/
-    case SNG_LOGLEVEL_WARN:
-        ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
-        break;
-    /**************************************************************************/
-    case SNG_LOGLEVEL_INFO:
-        ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
-        break;
-    /**************************************************************************/
-    case SNG_LOGLEVEL_STATS:
-        ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
-        break;
-    /**************************************************************************/
-    case SNG_LOGLEVEL_ERROR:
-        ftdm_log(FTDM_LOG_ERROR, "sng_ss7->%s", data);
-        break;
-    /**************************************************************************/
-    case SNG_LOGLEVEL_CRIT:
-        printf("%s",data);
-        /*ftdm_log(FTDM_LOG_CRIT, "sng_ss7->%s", data);*/
-        break;
-    /**************************************************************************/
-    default:
-        ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
-        break;
-    /**************************************************************************/
-    }
-
-    return;
+       return (sng_cntrl_cc(&pst, &cntrl));
 }
 
 /******************************************************************************/
-void handle_sng_alarm(sng_alrm_t t_alarm)
+static int ftmod_ss7_enable_nsap(int suId)
 {
+       SiMngmt cntrl;
+       Pst pst;
 
-    switch (t_alarm.entity) {
-    /**************************************************************************/
-    case (ENTL1):
-        ftdm_log(FTDM_LOG_WARNING,"[SNG-MTP1] %s : %s : %s \n",
-                                    DECODE_LL1_EVENT(t_alarm.event),
-                                    DECODE_LL1_CAUSE(t_alarm.cause),
-                                    DECODE_LL1_PARM(t_alarm.eventParm[0]));
-        break;
-    /**************************************************************************/
-    case (ENTSD):
-        ftdm_log(FTDM_LOG_WARNING,"[SNG-MTP2] %s : %s \n",
-                                    DECODE_LSD_EVENT(t_alarm.event),
-                                    DECODE_LSD_CAUSE(t_alarm.cause));
-        break;
-    /**************************************************************************/
-    case (ENTSN):
-        ftdm_log(FTDM_LOG_WARNING,"[SNG-MTP3] %s on %d: %s \n",
-                                    DECODE_LSN_EVENT(t_alarm.event),
-                                    t_alarm.id,
-                                    DECODE_LSN_CAUSE(t_alarm.cause));
-        break;
-    /**************************************************************************/
-    case (ENTSI):
-        handle_entsi_alarm(t_alarm);
-        break;
-    /**************************************************************************/
-    case (ENTCC):
-        ftdm_log(FTDM_LOG_DEBUG,"[SNG-CC] %s : %s \n",
-                                    DECODE_LCC_EVENT(t_alarm.event),
-                                    DECODE_LCC_CAUSE(t_alarm.cause));
-        break;
-    /**************************************************************************/
-    default:
-        ftdm_log(FTDM_LOG_WARNING,"Received alarm from unknown entity");
-        break;
-    /**************************************************************************/
-    } /* switch (t_alarm.entity) */
-
-    return;
-}
+       /* initalize the post structure */
+       smPstInit(&pst);
 
-/******************************************************************************/
-static void handle_entsi_alarm(sng_alrm_t alarm)
-{
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSI;
 
-    switch (alarm.event) {
-    /**************************************************************************/
-    case (LCM_EVENT_TIMEOUT):
-        /* this event always has the circuit value embedded */
-        SS7_WARN("[ISUP] Timer %d expired on CIC %d\n",
-                    alarm.eventParm[8],
-                    g_ftdm_sngss7_data.cfg.isupCircuit[alarm.eventParm[0]].cic);
-        break;
-    /**************************************************************************/
-    case (LSI_EVENT_REMOTE):
-        SS7_WARN("[ISUP] %s received on CIC %d\n",
-                    DECODE_LSI_CAUSE(alarm.cause),
-                    g_ftdm_sngss7_data.cfg.isupCircuit[alarm.eventParm[0]].cic);
-        break;
-    /**************************************************************************/
-    case (LSI_EVENT_LOCAL):
-        SS7_WARN("[ISUP] %s transmitted on CIC %d\n",
-                    DECODE_LSI_CAUSE(alarm.cause),
-                    g_ftdm_sngss7_data.cfg.isupCircuit[alarm.eventParm[0]].cic);
-        break;
-    /**************************************************************************/
-    case (LSI_EVENT_MTP):
-        SS7_WARN("[ISUP] Received %s on %d\n",
-                    DECODE_LSI_CAUSE(alarm.cause),
-                    g_ftdm_sngss7_data.cfg.mtp3_isup[alarm.eventParm[2]].id);
-        break;
-    /**************************************************************************/
-    case (LCM_EVENT_UI_INV_EVT):
-        switch (alarm.cause) {
-        /**********************************************************************/
-        case (LSI_CAUSE_INV_CIRCUIT):
-            SS7_WARN("[ISUP] Invalid circuit = %d (CIC = %d)\n",
-                        alarm.eventParm[0],
-                        g_ftdm_sngss7_data.cfg.isupCircuit[alarm.eventParm[0]].cic);
-            break;
-        /**********************************************************************/
-        }
-        break;
-    /**************************************************************************/
-    case (LCM_EVENT_LI_INV_EVT):
-        switch (alarm.cause) {
-        /**********************************************************************/
-        case (LCM_CAUSE_INV_SAP):
-            SS7_WARN("[ISUP] Invalid spId = %d\n",
-                        alarm.eventParm[3]);
-            break;
-        /**********************************************************************/
-        }
-        break;
-    /**************************************************************************/
-    default:
-        SS7_WARN("[ISUP] %s : %s \n", DECODE_LSI_EVENT(alarm.event), DECODE_LSI_CAUSE(alarm.cause));
-        break;
-    /**************************************************************************/
-    } /* switch (alarm.event) */
-    return;
-}
+       /* initalize the control structure */
+       memset(&cntrl, 0x0, sizeof(SiMngmt));
 
-/* ACTIVATION *****************************************************************/
-int ft_to_sngss7_activate_all(void)
-{
-    sng_isup_cc_t       *cc_isup = NULL;
-    sng_mtp3_isup_t     *isup_mtp3 = NULL;
-    sng_mtp3LinkSet_t   *mtp3_linkset = NULL;
-    int                 x;
-
-    /* CC to ISUP *************************************************************/
-    x = 1;
-    cc_isup = &g_ftdm_sngss7_data.cfg.isup_cc[x];
-    while (cc_isup->id != 0) {
-        if (sngss7_test_flag(cc_isup, SNGSS7_FLAG_ACTIVE)) {
-            SS7_DEBUG("CC-ISUP interface already active = %d\n", cc_isup->id);
-        } else {
-            if (sng_activate_cc_isup_inf(cc_isup->ccId)) {
-                SS7_ERROR("Failed to activate CC-ISUP = %d\n",cc_isup->id);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Started CC-ISUP interface = %d\n", cc_isup->id);
-                sngss7_set_flag(cc_isup, SNGSS7_FLAG_ACTIVE);
-            }
-        } /* if (sngss7_test_flag(cc_isup, SNGSS7_FLAG_ACTIVE) */
-
-        x++;
-        cc_isup = &g_ftdm_sngss7_data.cfg.isup_cc[x];
-    } /* while (cc_isup->id != 0) */
-
-    /* ISUP - MTP3 ************************************************************/
-    x = 1;
-    isup_mtp3 = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
-    while (isup_mtp3->id != 0) {
-        if (sngss7_test_flag(isup_mtp3, SNGSS7_FLAG_ACTIVE)) {
-            SS7_DEBUG("ISUP-MTP3 interface already active = %d\n", isup_mtp3->id);
-        } else {
-            if (sng_activate_isup_mtp3_inf(isup_mtp3->id)) {
-                SS7_ERROR("Failed to activate ISUP-MTP3 = %d\n",isup_mtp3->id);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Started ISUP-MTP3interface = %d\n", isup_mtp3->id);
-                sngss7_set_flag(isup_mtp3, SNGSS7_FLAG_ACTIVE);
-            }
-        } /* if (sngss7_test_flag(isup_mtp3, SNGSS7_FLAG_ACTIVE) */
-
-        x++;
-        isup_mtp3 = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
-    } /* while (isup_mtp3->id != 0) */
-
-    /* MTP3 Linkset (MTP3 - MTP2 - MTP1) **************************************/
-    x = 1;
-    mtp3_linkset = &g_ftdm_sngss7_data.cfg.mtp3LinkSet[x];
-    while (mtp3_linkset->id != 0) {
-        if (sngss7_test_flag(mtp3_linkset, SNGSS7_FLAG_ACTIVE)) {
-            SS7_DEBUG("MTP3 Linkset already active = %s\n", mtp3_linkset->name);
-        } else {
-            if (sng_activate_mtp3_linkset(mtp3_linkset->id)) {
-                SS7_ERROR("Failed to activate MTP3 Linkset = %s\n",mtp3_linkset->name);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Started MTP3 Linkset = %s\n", mtp3_linkset->name);
-                sngss7_set_flag(mtp3_linkset, SNGSS7_FLAG_ACTIVE);
-            }
-        } /* if (sngss7_test_flag(mtp3_linkset, SNGSS7_FLAG_ACTIVE) */
-
-        x++;
-        mtp3_linkset = &g_ftdm_sngss7_data.cfg.mtp3LinkSet[x];
-    } /* while (mtp3_linkset->id != 0) */
-
-    return FTDM_SUCCESS;
-}
+       /* initalize the control header */
+       smHdrInit(&cntrl.hdr);
 
-/* CONFIGURATION **************************************************************/
-int  ft_to_sngss7_cfg(void)
-{
-    sng_mtp1Link_t      *mtp1_link = NULL;
-    sng_mtp2Link_t      *mtp2_link = NULL;
-    sng_mtp3Link_t      *mtp3_link = NULL;
-    sng_mtp3LinkSet_t   *mtp3_linkset = NULL;
-    sng_mtp3Route_t     *mtp3_route = NULL;
-    sng_mtp3_isup_t     *mtp3_isup = NULL;
-    sng_mtp3_isup_t     *isup_mtp3 = NULL;
-    sng_isupInterface_t *isup_interface = NULL;
-    sng_isupCircuit_t   *isup_circuit = NULL;
-    sng_isup_cc_t       *isup_cc = NULL;
-    sng_isup_cc_t       *cc_isup = NULL;
-    int x;
-
-    SS7_DEBUG("Starting LibSngSS7 configuration...\n");
-
-    if (g_ftdm_sngss7_data.gen_config_done == 0) {
-        /* perform general configuration */
-        if(ftmod_ss7_general_configuration()) {
-            SS7_ERROR("Failed to run general configuration!\n");
-            return FTDM_FAIL;
-        } else {
-            SS7_INFO("General Configuration was successful\n");
-            g_ftdm_sngss7_data.gen_config_done = 1;
-        }
-    } else {
-        SS7_DEBUG("General configuration already done.\n");
-    }
-
-    /* MTP1 *******************************************************************/
-    x=1;
-    mtp1_link = &g_ftdm_sngss7_data.cfg.mtp1Link[x];
-    while (mtp1_link->id != 0) {
-
-        if (sngss7_test_flag(mtp1_link, SNGSS7_FLAG_CONFIGURED)) {
-            SS7_DEBUG("MTP1 Link already configured = %s\n",mtp1_link->name);
-        } else {
-            if (ftmod_ss7_configure_mtp1_link(x)) {
-                SS7_ERROR("Failed to configure MTP1 link = %s\n!", mtp1_link->name);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Successfully configured MTP1 link = %s\n", mtp1_link->name);
-                sngss7_set_flag(mtp1_link, SNGSS7_FLAG_CONFIGURED);
-            }
-        }
-
-        /* next link */
-        x++;
-        mtp1_link = &g_ftdm_sngss7_data.cfg.mtp1Link[x];
-    } /* while (g_ftdm_sngss7_data.cfg.mtp1Link[x]->id != 0) */
-
-    /* MTP2 *******************************************************************/
-    x=1;
-    mtp2_link = &g_ftdm_sngss7_data.cfg.mtp2Link[x];
-    while (mtp2_link->id != 0) {
-        if (sngss7_test_flag(mtp2_link, SNGSS7_FLAG_CONFIGURED)) {
-            SS7_DEBUG("MTP2 Link already configured = %s\n",mtp2_link->name);
-        } else {
-            if (ftmod_ss7_configure_mtp2_link(x)) {
-                SS7_ERROR("Failed to configure MTP2 link = %s\n!", mtp2_link->name);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Successfully configured MTP2 link = %s\n", mtp2_link->name);
-                sngss7_set_flag(mtp2_link, SNGSS7_FLAG_CONFIGURED);
-            }
-        }
-        /* next link */
-        x++;
-        mtp2_link = &g_ftdm_sngss7_data.cfg.mtp2Link[x];
-    } /* while (g_ftdm_sngss7_data.cfg.mtp2Link[x]->id != 0) */
-
-    /* MTP3 *******************************************************************/
-    x=1;
-    mtp3_link = &g_ftdm_sngss7_data.cfg.mtp3Link[x];
-    while (mtp3_link->id != 0) {
-        if (sngss7_test_flag(mtp3_link, SNGSS7_FLAG_CONFIGURED)) {
-            SS7_DEBUG("MTP3 Link already configured = %s\n", mtp3_link->name);
-        } else {
-            if (ftmod_ss7_configure_mtp3_link(x)) {
-                SS7_ERROR("Failed to configure MTP3 link = %s\n!", mtp3_link->name);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Successfully configured MTP3 link = %s\n", mtp3_link->name);
-                sngss7_set_flag(mtp3_link, SNGSS7_FLAG_CONFIGURED);
-            }
-        }
-        /* next link */
-        x++;
-        mtp3_link = &g_ftdm_sngss7_data.cfg.mtp3Link[x];
-    } /* while (g_ftdm_sngss7_data.cfg.mtp3Link[x]->id != 0) */
-
-    x=1;
-    mtp3_linkset = &g_ftdm_sngss7_data.cfg.mtp3LinkSet[x];
-    while (mtp3_linkset->id != 0) {
-        if (sngss7_test_flag(mtp3_linkset, SNGSS7_FLAG_CONFIGURED)) {
-            SS7_DEBUG("MTP3 LinkSet already configured = %s\n", mtp3_linkset->name);
-        } else {
-            if (ftmod_ss7_configure_mtp3_linkset(x)) {
-                SS7_ERROR("Failed to configure MTP3 link = %s\n!", mtp3_linkset->name);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Successfully configured MTP3 link = %s\n", mtp3_linkset->name);
-                sngss7_set_flag(mtp3_linkset, SNGSS7_FLAG_CONFIGURED);
-            }
-        }
-        /* next link */
-        x++;
-        mtp3_linkset = &g_ftdm_sngss7_data.cfg.mtp3LinkSet[x];
-    } /* while (g_ftdm_sngss7_data.cfg.mtp1Link[x]->id != 0) */
-
-    x=1;
-    mtp3_route = &g_ftdm_sngss7_data.cfg.mtp3Route[x];
-    while (mtp3_route->id != 0) {
-        if (sngss7_test_flag(mtp3_route, SNGSS7_FLAG_CONFIGURED)) {
-            SS7_DEBUG("MTP3 Route already configured = %s\n", mtp3_route->name);
-        } else {
-            if (ftmod_ss7_configure_mtp3_route(x)) {
-                SS7_ERROR("Failed to configure MTP3 route = %s\n!", mtp3_route->name);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Successfully configured MTP3 route = %s\n", mtp3_route->name);
-                sngss7_set_flag(mtp3_route, SNGSS7_FLAG_CONFIGURED);
-            }
-        }
-        /* next link */
-        x++;
-        mtp3_route = &g_ftdm_sngss7_data.cfg.mtp3Route[x];
-    } /* while (g_ftdm_sngss7_data.cfg.mtp3Route[x]->id != 0) */
-
-    mtp3_route = &g_ftdm_sngss7_data.cfg.mtp3Route[0];
-    if (sngss7_test_flag(mtp3_route, SNGSS7_FLAG_CONFIGURED)) {
-        SS7_DEBUG("MTP3 Self Route already configured\n");
-    } else {
-        if (ftmod_ss7_configure_mtp3_route(0)) {
-            SS7_ERROR("Failed to configure MTP3 Route = SelfRoute\n!");
-            return FTDM_FAIL;
-        } else {
-            SS7_INFO("Successfully configured MTP3 Route = SelfRoute\n");
-            sngss7_set_flag(mtp3_route, SNGSS7_FLAG_CONFIGURED);
-        }
-    }
-
-    x=1;
-    mtp3_isup = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
-    while (mtp3_isup->id != 0) {
-        if (sngss7_test_flag(mtp3_isup, SNGSS7_FLAG_CONFIGURED)) {
-            SS7_DEBUG("MTP3-ISUP interface already configured = %d\n", mtp3_isup->id);
-        } else {
-            if (ftmod_ss7_configure_mtp3_isup(x)) {
-                SS7_ERROR("Failed to configure MTP3-ISUP interface = %d\n!", mtp3_isup->id);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Successfully configured MTP3-ISUP interface = %d\n", mtp3_isup->id);
-            }
-        }
-        /* next link */
-        x++;
-        mtp3_isup = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
-    } /* while (g_ftdm_sngss7_data.cfg.mtp3_isup[x]->id != 0) */
-
-    /* ISUP *******************************************************************/
-    x=1;
-    isup_mtp3 = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
-    while (isup_mtp3->id != 0) {
-        if (sngss7_test_flag(isup_mtp3, SNGSS7_FLAG_CONFIGURED)) {
-            SS7_DEBUG("ISUP-MTP3 interface already configured = %d\n", isup_mtp3->id);
-        } else {
-            if (ftmod_ss7_configure_isup_mtp3(x)) {
-                SS7_ERROR("Failed to configure ISUP-MTP3 interface = %d\n!", isup_mtp3->id);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Successfully configured ISUP-MTP3 interface = %d\n", isup_mtp3->id);
-                sngss7_set_flag(isup_mtp3, SNGSS7_FLAG_CONFIGURED);
-            }
-        }
-        /* next link */
-        x++;
-        isup_mtp3 = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
-    } /* while (g_ftdm_sngss7_data.cfg.isup_mtp3[x]->id != 0) */
-
-    x=1;
-    isup_cc = &g_ftdm_sngss7_data.cfg.isup_cc[x];
-    while (isup_cc->id != 0) {
-        if (sngss7_test_flag(isup_cc, SNGSS7_FLAG_CONFIGURED)) {
-            SS7_DEBUG("ISUP-CC interface already configured = %d\n", isup_cc->id);
-        } else {
-            if (ftmod_ss7_configure_isup_cc(x)) {
-                SS7_ERROR("Failed to configure ISUP-CC interface = %d\n!", isup_cc->id);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Successfully configured ISUP-CC interface = %d\n", isup_cc->id);
-            }
-        }
-        /* next link */
-        x++;
-        isup_cc = &g_ftdm_sngss7_data.cfg.isup_cc[x];
-    } /* while (g_ftdm_sngss7_data.cfg.isup_cc[x]->id != 0) */
-
-    x=1;
-    isup_interface = &g_ftdm_sngss7_data.cfg.isupInterface[x];
-    while (isup_interface->id != 0) {
-        if (sngss7_test_flag(isup_interface, SNGSS7_FLAG_CONFIGURED)) {
-            SS7_DEBUG("ISUP interface already configured = %s\n", isup_interface->name);
-        } else {
-            if (ftmod_ss7_configure_isup_interface(x)) {
-                SS7_ERROR("Failed to configure ISUP interface = %s\n", isup_interface->name);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Successfully configured ISUP interface = %s\n", isup_interface->name);
-                sngss7_set_flag(isup_interface, SNGSS7_FLAG_CONFIGURED);
-            }
-        }
-        /* next link */
-        x++;
-        isup_interface = &g_ftdm_sngss7_data.cfg.isupInterface[x];
-    } /* while (g_ftdm_sngss7_data.cfg.isup_interface[x]->id != 0) */
-
-    x=1;
-    isup_circuit = &g_ftdm_sngss7_data.cfg.isupCircuit[x];
-    while (isup_circuit->id != 0) {
-        if (isup_circuit->cic != 0) {
-            if (sngss7_test_flag(isup_circuit, SNGSS7_FLAG_CONFIGURED)) {
-                SS7_DEBUG("ISUP Circuit already configured = %d\n", isup_circuit->id);
-            } else {
-                if (ftmod_ss7_configure_isup_circuit(x)) {
-                    SS7_ERROR("Failed to configure ISUP circuit = %d\n!", isup_circuit->id);
-                    return FTDM_FAIL;
-                } else {
-                    SS7_INFO("Successfully configured ISUP circuit = %d\n", isup_circuit->id);
-                    sngss7_set_flag(isup_circuit, SNGSS7_FLAG_CONFIGURED);
-                }
-            }
-        }
-        /* next link */
-        x++;
-        isup_circuit = &g_ftdm_sngss7_data.cfg.isupCircuit[x];
-    } /* while (g_ftdm_sngss7_data.cfg.isup_circuit[x]->id != 0) */
-
-    /* CC *********************************************************************/
-
-    x=1;
-    cc_isup = &g_ftdm_sngss7_data.cfg.isup_cc[x];
-    while (cc_isup->id != 0) {
-        if (sngss7_test_flag(cc_isup, SNGSS7_FLAG_CONFIGURED)) {
-            SS7_DEBUG("CC-ISUP interface already configured = %d\n", cc_isup->id);
-        } else {
-            if (ftmod_ss7_configure_cc_isup(x)) {
-                SS7_ERROR("Failed to configure CC-ISUP interface = %d\n!", cc_isup->id);
-                return FTDM_FAIL;
-            } else {
-                SS7_INFO("Successfully configured CC-ISUP interface = %d\n", cc_isup->id);
-                sngss7_set_flag(cc_isup, SNGSS7_FLAG_CONFIGURED);
-            }
-        }
-        /* next link */
-        x++;
-        cc_isup = &g_ftdm_sngss7_data.cfg.isup_cc[x];
-    } /* while (g_ftdm_sngss7_data.cfg.cc_isup[x]->id != 0) */
-    
-    SS7_DEBUG("Finished LibSngSS7 configuration...\n");
-    return FTDM_SUCCESS;
-}
+       cntrl.hdr.msgType                       = TCNTRL;          /* this is a control request */
+       cntrl.hdr.entId.ent                     = ENTSI;
+       cntrl.hdr.entId.inst            = S_INST;
+       cntrl.hdr.elmId.elmnt           = STNSAP;
 
-/******************************************************************************/
-static int ftmod_ss7_general_configuration(void)
-{
+       cntrl.t.cntrl.s.siElmnt.elmntId.sapId                           = suId; 
+       cntrl.t.cntrl.s.siElmnt.elmntParam.nsap.nsapType        = SAP_MTP; 
 
-    if(sng_cfg_mtp1_gen(&g_ftdm_sngss7_data.cfg)) {
-        SS7_ERROR("General configuration for MTP1 failed!\n");
-        return FTDM_FAIL;
-    } else {
-        SS7_INFO("General configuration for MTP1 was successful\n");
-    }
-
-    if(sng_cfg_mtp2_gen(&g_ftdm_sngss7_data.cfg)) {
-        SS7_ERROR("General configuration for MTP2 failed!\n");
-        return FTDM_FAIL;
-    } else {
-        SS7_INFO("General configuration for MTP2 was successful\n");
-    }
-
-    if(sng_cfg_mtp3_gen(&g_ftdm_sngss7_data.cfg)) {
-        SS7_ERROR("General configuration for MTP3 failed!\n");
-        return FTDM_FAIL;
-    } else {
-        SS7_INFO("General configuration for MTP3 was successful\n");
-    }
-
-    if(sng_cfg_isup_gen(&g_ftdm_sngss7_data.cfg)) {
-        SS7_ERROR("General configuration for ISUP failed!\n");
-        return FTDM_FAIL;
-    } else {
-        SS7_INFO("General configuration for ISUP was successful\n");
-    }
-
-    if(sng_cfg_cc_gen(&g_ftdm_sngss7_data.cfg)) {
-        SS7_ERROR("General configuration for Call-Control failed!\n");
-        return FTDM_FAIL;
-    } else {
-        SS7_INFO("General configuration for Call-Control was successful\n");
-    }
-
-    return FTDM_SUCCESS;
-}
 
-/******************************************************************************/
-static int ftmod_ss7_configure_mtp1_link(int id)
-{
-    if(sng_cfg_mtp1_link(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
-}
+       cntrl.t.cntrl.action            = ABND_ENA;             /* bind and activate */
+       cntrl.t.cntrl.subAction         = SAELMNT;              /* specificed element */
 
-/******************************************************************************/
-static int ftmod_ss7_configure_mtp2_link(int id)
-{
-    if(sng_cfg_mtp2_link(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
+       return (sng_cntrl_isup(&pst, &cntrl));
 }
 
 /******************************************************************************/
-static int ftmod_ss7_configure_mtp3_link(int id)
+static int ftmod_ss7_enable_mtpLinkSet(int lnkSetId)
 {
-    if(sng_cfg_mtp3_link(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
-}
+       SnMngmt cntrl;
+       Pst pst;
 
-/******************************************************************************/
-static int ftmod_ss7_configure_mtp3_linkset(int id)
-{
-    if(sng_cfg_mtp3_linkset(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
-}
+       /* initalize the post structure */
+       smPstInit(&pst);
 
-/******************************************************************************/
-static int ftmod_ss7_configure_mtp3_route(int id)
-{
-    if(sng_cfg_mtp3_route(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
-}
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSN;
 
-/******************************************************************************/
-static int ftmod_ss7_configure_mtp3_isup(int id)
-{
-    if(sng_cfg_mtp3_isup_interface(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
-}
+       /* initalize the control structure */
+       memset(&cntrl, 0x0, sizeof(SnMngmt));
 
-/******************************************************************************/
-static int ftmod_ss7_configure_isup_mtp3(int id)
-{
-    if(sng_cfg_isup_mtp3_interface(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
-}
+       /* initalize the control header */
+       smHdrInit(&cntrl.hdr);
 
-/******************************************************************************/
-static int ftmod_ss7_configure_isup_interface(int id)
-{
-    if(sng_cfg_isup_interface(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
-}
+       cntrl.hdr.msgType                       = TCNTRL;               /* this is a control request */
+       cntrl.hdr.entId.ent                     = ENTSN;
+       cntrl.hdr.entId.inst            = S_INST;
+       cntrl.hdr.elmId.elmnt           = STLNKSET;
+       cntrl.hdr.elmId.elmntInst1      = lnkSetId;             /* this is the linkset to bind */
 
-/******************************************************************************/
-static int ftmod_ss7_configure_isup_circuit(int id)
-{
-    if(sng_cfg_isup_circuit(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
+       cntrl.t.cntrl.action            = ABND_ENA;             /* bind and activate */
+       cntrl.t.cntrl.subAction         = SAELMNT;              /* specificed element */
+
+       return (sng_cntrl_mtp3(&pst, &cntrl));
 }
 
 /******************************************************************************/
-static int ftmod_ss7_configure_isup_cc(int id)
+int ftmod_ss7_inhibit_mtplink(uint32_t id)
 {
-    if(sng_cfg_isup_cc_interface(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
+       SnMngmt cntrl;
+       Pst pst;
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSN;
+
+       /* initalize the control structure */
+       memset(&cntrl, 0x0, sizeof(SnMngmt));
+
+       /* initalize the control header */
+       smHdrInit(&cntrl.hdr);
+
+       cntrl.hdr.msgType                       = TCNTRL;       /* this is a control request */
+       cntrl.hdr.entId.ent                     = ENTSN;
+       cntrl.hdr.entId.inst            = S_INST;
+       cntrl.hdr.elmId.elmnt           = STDLSAP;
+       cntrl.hdr.elmId.elmntInst1      = id;           /* the DSLAP to inhibit  */
+
+       cntrl.t.cntrl.action            = AINH;         /* Inhibit */
+       cntrl.t.cntrl.subAction         = SAELMNT;      /* specificed element */
+
+       return (sng_cntrl_mtp3(&pst, &cntrl));
 }
 
 /******************************************************************************/
-static int ftmod_ss7_configure_cc_isup(int id)
+int ftmod_ss7_uninhibit_mtplink(uint32_t id)
 {
-    if(sng_cfg_cc_isup_interface(&g_ftdm_sngss7_data.cfg, id)){
-        return FTDM_FAIL;
-    } else {
-        return FTDM_SUCCESS;
-    }
-}
+       SnMngmt cntrl;
+       Pst pst;
+
+       /* initalize the post structure */
+       smPstInit(&pst);
+
+       /* insert the destination Entity */
+       pst.dstEnt = ENTSN;
+
+       /* initalize the control structure */
+       memset(&cntrl, 0x0, sizeof(SnMngmt));
 
+       /* initalize the control header */
+       smHdrInit(&cntrl.hdr);
+
+       cntrl.hdr.msgType                       = TCNTRL;       /* this is a control request */
+       cntrl.hdr.entId.ent                     = ENTSN;
+       cntrl.hdr.entId.inst            = S_INST;
+       cntrl.hdr.elmId.elmnt           = STDLSAP;
+       cntrl.hdr.elmId.elmntInst1      = id;           /* the DSLAP to inhibit  */
+
+       cntrl.t.cntrl.action            = AUNINH;               /* Inhibit */
+       cntrl.t.cntrl.subAction         = SAELMNT;      /* specificed element */
+
+       return (sng_cntrl_mtp3(&pst, &cntrl));
+}
 
 /******************************************************************************/
 /* For Emacs:
index b947bc7304776e329e97de163065cba476d65332..98554db6a42c52d3a72ae686221dabcc74dca314 100644 (file)
@@ -62,1472 +62,1905 @@ static ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint3
 static ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
 
 static ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
-static ftdm_status_t handle_local_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
+static ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
 static ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
 
+static ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
+static ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
+
 static ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
 static ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
 static ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
 static ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
 
-static ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
-
+static ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
+static ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
 
+static ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
 
 /******************************************************************************/
 
 /* FUNCTIONS ******************************************************************/
 void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info ;
-    ftdm_channel_t      *ftdmchan;
-
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    }
-
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
-
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    };
-
-    SS7_MSG_TRACE("Received IAM on CIC # %d\n", sngss7_info->circuit->cic);
-
-    /* check whether the ftdm channel is in a state to accept a call */
-    switch (ftdmchan->state) {
-    /**************************************************************************/
-    case (FTDM_CHANNEL_STATE_DOWN):     /* only state it is fully valid to get IAM */
-
-        /* fill in the channels SS7 Stack information */
-        sngss7_info->suInstId = get_unique_id();
-        sngss7_info->spInstId = spInstId;
-
-        /* try to open the ftdm channel */
-        if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
-            SS7_ERROR("Failed to open span: %d, chan: %d\n",
-                        ftdmchan->physical_span_id,
-                        ftdmchan->physical_chan_id);
-
-             /* set the flag to indicate this hangup is started from the local side */
-            sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL);
-
-            ftdmchan->caller_data.hangup_cause = 41;
-
-            /* move the state to CANCEL */
-            ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
-
-        } else {
-
-            /* fill in cid/ani number */
-            if (siConEvnt->cgPtyNum.addrSig.pres) {
-                copy_tknStr_from_sngss7(siConEvnt->cgPtyNum.addrSig,
-                                        ftdmchan->caller_data.cid_num.digits, 
-                                        siConEvnt->cgPtyNum.oddEven);
-
-                /* fill in cid Name */
-                ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.cid_num.digits);
-
-                ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits);
-
-            } else {
-                SS7_INFO("No Calling party (ANI) information in IAM!\n");
-            }
-
-            /* fill in dnis */
-            if (siConEvnt->cdPtyNum.addrSig.pres) {
-                copy_tknStr_from_sngss7(siConEvnt->cdPtyNum.addrSig, 
-                                        ftdmchan->caller_data.dnis.digits, 
-                                        siConEvnt->cdPtyNum.oddEven);
-            }   else {
-                SS7_INFO("No Called party (DNIS) information in IAM!\n");
-            }
-
-            /* fill in rdnis */
-            if (siConEvnt->redirgNum.addrSig.pres) {
-                copy_tknStr_from_sngss7(siConEvnt->redirgNum.addrSig, 
-                                        ftdmchan->caller_data.rdnis.digits, 
-                                        siConEvnt->cgPtyNum.oddEven);
-            }   else {
-                SS7_INFO("No RDNIS party information in IAM!\n");
-            }
-
-            /* fill in screening/presentation */
-            ftdmchan->caller_data.screen = siConEvnt->cgPtyNum.scrnInd.val;
-            ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val;
-
-            /* set the state of the channel to collecting...the rest is done by the chan monitor */
-            ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
-
-        } /* if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) */
-
-        break;
-    /**************************************************************************/
-    case (FTDM_CHANNEL_STATE_DIALING):             /* glare */
-        SS7_ERROR("Got IAM in DIALING state...glare!\n");
-        
-        /* the flag the channel as having a collision */
-        sngss7_set_flag(sngss7_info, FLAG_GLARE);
-
-        /* save the IAM for processing once the channel has gone to DOWN */
-        memcpy(&sngss7_info->glare.iam, siConEvnt, sizeof(*siConEvnt));
-        sngss7_info->glare.suInstId = suInstId;
-        sngss7_info->glare.spInstId = spInstId;
-        sngss7_info->glare.circuit  = circuit;
-               SS7_DEBUG("Queuing incoming cal request on Circuit = %d (CIC # %d\n",
-                                       sngss7_info->glare.circuit,
-                                       sngss7_info->circuit->cic);
-
-        break;
-    /**************************************************************************/
-    default:    /* should not have gotten an IAM while in this state */
-        SS7_ERROR("Got IAM in an invalid state (%s) on span=%d, chan=%d!\n", 
-                    ftdm_channel_state2str(ftdmchan->state),
-                    ftdmchan->physical_span_id,
-                    ftdmchan->physical_chan_id);
-
-        /* move the state of the channel to RESTART to force a reset */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-
-        break;
-    /**************************************************************************/
-    } /* switch (ftdmchan->state) */
-
-    /* unlock the channel */
-    ftdm_mutex_unlock(ftdmchan->mutex);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       sngss7_chan_data_t  *sngss7_info ;
+       ftdm_channel_t    *ftdmchan;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM\n");
+
+       /* check if the circuit has a remote block */
+       if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
+               (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) ||
+               (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+
+               /* as per Q.764, 2.8.2.3 xiv ... remove the block from this channel */
+               sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
+               sngss7_clear_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
+               sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX);
+
+               /* KONRAD FIX ME : check in case there is a ckt and grp block */
+       }
+
+       /* check whether the ftdm channel is in a state to accept a call */
+       switch (ftdmchan->state) {
+       /**************************************************************************/
+       case (FTDM_CHANNEL_STATE_DOWN):  /* only state it is fully valid to get IAM */
+
+               /* fill in the channels SS7 Stack information */
+               sngss7_info->suInstId = get_unique_id();
+               sngss7_info->spInstId = spInstId;
+
+               /* try to open the ftdm channel */
+               if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
+                       SS7_ERROR("Failed to open span: %d, chan: %d\n",
+                                               ftdmchan->physical_span_id,
+                                               ftdmchan->physical_chan_id);
+
+                        /* set the flag to indicate this hangup is started from the local side */
+                       sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL);
+
+                       ftdmchan->caller_data.hangup_cause = 41;
+
+                       /* move the state to CANCEL */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
+
+               } else {
+
+                       /* fill in cid/ani number */
+                       if (siConEvnt->cgPtyNum.addrSig.pres) {
+                               copy_tknStr_from_sngss7(siConEvnt->cgPtyNum.addrSig,
+                                                                               ftdmchan->caller_data.cid_num.digits, 
+                                                                               siConEvnt->cgPtyNum.oddEven);
+
+                               /* fill in cid Name */
+                               ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.cid_num.digits);
+
+                               ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits);
+
+                       } else {
+                               SS7_INFO("No Calling party (ANI) information in IAM!\n");
+                       }
+
+                       /* fill in dnis */
+                       if (siConEvnt->cdPtyNum.addrSig.pres) {
+                               copy_tknStr_from_sngss7(siConEvnt->cdPtyNum.addrSig, 
+                                                                               ftdmchan->caller_data.dnis.digits, 
+                                                                               siConEvnt->cdPtyNum.oddEven);
+                       }   else {
+                               SS7_INFO("No Called party (DNIS) information in IAM!\n");
+                       }
+
+                       /* fill in rdnis */
+                       if (siConEvnt->redirgNum.addrSig.pres) {
+                               copy_tknStr_from_sngss7(siConEvnt->redirgNum.addrSig, 
+                                                                               ftdmchan->caller_data.rdnis.digits, 
+                                                                               siConEvnt->cgPtyNum.oddEven);
+                       }   else {
+                               SS7_INFO("No RDNIS party information in IAM!\n");
+                       }
+
+                       /* fill in screening/presentation */
+                       ftdmchan->caller_data.screen = siConEvnt->cgPtyNum.scrnInd.val;
+                       ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val;
+
+                       /* set the state of the channel to collecting...the rest is done by the chan monitor */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
+
+               } /* if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) */
+
+               break;
+       /**************************************************************************/
+       default:        /* should not have gotten an IAM while in this state */
+               SS7_ERROR("Got IAM in an invalid state (%s) on span=%d, chan=%d!\n", 
+                                       ftdm_channel_state2str(ftdmchan->state),
+                                       ftdmchan->physical_span_id,
+                                       ftdmchan->physical_chan_id);
+
+               /* move the state of the channel to RESTART to force a reset */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+
+               break;
+       /**************************************************************************/
+       } /* switch (ftdmchan->state) */
+
+       /* unlock the channel */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
 }
 
 /******************************************************************************/
 void sngss7_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       sngss7_chan_data_t  *sngss7_info ;
+       ftdm_channel_t    *ftdmchan;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+
+       /* check whether the ftdm channel is in a state to accept a call */
+       switch (ftdmchan->state) {
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_PROGRESS:
+       case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ANM\n");
+
+               /* go to UP */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
+
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_DIALING:
+
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CON\n");
+
+               /* go to UP */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
+
+               break;          
+       /**************************************************************************/
+       default:        /* incorrect state...reset the CIC */
+
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ANM/CON\n");
+
+               /* throw the TX reset flag */
+               sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
+
+               /* go to RESTART */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+
+               break;
+       /**************************************************************************/
+       }
+
+       /* unlock the channel */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+/******************************************************************************/
+void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       sngss7_chan_data_t  *sngss7_info ;
+       ftdm_channel_t    *ftdmchan;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       }
+
+       switch (evntType) {
+       /**************************************************************************/
+       case (ADDRCMPLT):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ACM\n");
+               switch (ftdmchan->state) {
+               /**********************************************************************/
+               case FTDM_CHANNEL_STATE_DIALING:
+                       /* KONRAD: should we confirm the instance ids ? */
+
+                       /* need to grab the sp instance id */ 
+                       sngss7_info->spInstId = spInstId;
+
+                       /* go to PROGRESS */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
+               break;
+               /**********************************************************************/
+               default:        /* incorrect state...reset the CIC */
+                       /* go to RESTART */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
+               break;
+               /**********************************************************************/
+               } /* switch (ftdmchan->state) */
+       /**************************************************************************/
+       case (MODIFY):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY\n");
+               break;
+       /**************************************************************************/
+       case (MODCMPLT):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY-COMPLETE\n");
+               break;
+       /**************************************************************************/
+       case (MODREJ):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY-REJECT\n");
+               break;
+       /**************************************************************************/
+       case (PROGRESS):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CPG\n");
+               break;
+       /**************************************************************************/
+       case (FRWDTRSFR):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FOT\n");
+               break;
+       /**************************************************************************/
+       case (INFORMATION):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx INF\n");
+               break;
+       /**************************************************************************/
+       case (INFORMATREQ):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx INR\n");
+               break;
+       /**************************************************************************/
+       case (SUBSADDR):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SAM\n");
+               break;
+       /**************************************************************************/
+       case (EXIT):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx EXIT\n");
+               break;
+       /**************************************************************************/
+       case (NETRESMGT):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx NRM\n");
+               break;
+       /**************************************************************************/
+       case (IDENTREQ):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IDR\n");
+               break;
+       /**************************************************************************/
+       case (IDENTRSP):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IRS\n");
+               break;
+       /**************************************************************************/
+       case (MALCLLPRNT):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MALICIOUS CALL\n");
+               break;
+       /**************************************************************************/
+       case (CHARGE):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG\n");
+               break;
+       /**************************************************************************/
+       case (TRFFCHGE):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG-TARIFF\n");
+               break;
+       /**************************************************************************/
+       case (CHARGEACK):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG-ACK\n");
+               break;
+       /**************************************************************************/
+       case (CALLOFFMSG):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALL-OFFER\n");
+               break;
+       /**************************************************************************/
+       case (LOOPPRVNT):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LOP\n");
+               break;
+       /**************************************************************************/
+       case (TECT_TIMEOUT):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ECT-Timeout\n");
+               break;
+       /**************************************************************************/
+       case (RINGSEND):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RINGING-SEND\n");
+               break;
+       /**************************************************************************/
+       case (CALLCLEAR):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALL-LINE Clear\n");
+               break;
+       /**************************************************************************/
+       case (PRERELEASE):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx PRI\n");
+               break;
+       /**************************************************************************/
+       case (APPTRANSPORT):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx APM\n");
+               break;
+       /**************************************************************************/
+       case (OPERATOR):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx OPERATOR\n");
+               break;
+       /**************************************************************************/
+       case (METPULSE):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx METERING-PULSE\n");
+               break;
+       /**************************************************************************/
+       case (CLGPTCLR):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALLING_PARTY_CLEAR\n");
+               break;
+       /**************************************************************************/
+       case (SUBDIRNUM):
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SUB-DIR\n");
+               break;
+       /**************************************************************************/
+       default:
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Unknown Msg\n");
+               break;
+       /**************************************************************************/
+       }
+
+       /* unlock the channel */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+/******************************************************************************/
+void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       sngss7_chan_data_t  *sngss7_info ;
+       ftdm_channel_t    *ftdmchan;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx REL\n");
+
+       /* check whether the ftdm channel is in a state to release a call */
+       switch (ftdmchan->state) {
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_DIALING:
+
+               /* pass the release code up to FTDM */
+               if (siRelEvnt->causeDgn.causeVal.pres) {
+                       ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val;
+               } else {
+                       SS7_ERROR("REL does not have a cause code!\n");
+                       ftdmchan->caller_data.hangup_cause = 0;
+               }
+
+               /* this is a remote hangup request */
+               sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL);
+
+               /* move the state of the channel to CANCEL to end the call */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_RING:
+       case FTDM_CHANNEL_STATE_PROGRESS:
+       case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+       case FTDM_CHANNEL_STATE_UP:
+
+               /* pass the release code up to FTDM */
+               if (siRelEvnt->causeDgn.causeVal.pres) {
+                       ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val;
+               } else {
+                       SS7_ERROR("REL does not have a cause code!\n");
+                       ftdmchan->caller_data.hangup_cause = 0;
+               }
+
+               /* this is a remote hangup request */
+               sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL);
+
+               /* move the state of the channel to TERMINATING to end the call */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+
+               break;
+       /**************************************************************************/
+       default:
+
+               /* fill in the channels SS7 Stack information */
+               sngss7_info->suInstId = get_unique_id();
+               sngss7_info->spInstId = spInstId;
+
+               /* throw the reset flag */
+               sngss7_set_flag(sngss7_info, FLAG_RESET_RX);
+
+               /* set the state to RESTART */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+               break;
+       /**************************************************************************/
+       } /* switch (ftdmchan->state) */
+
+
+       /* unlock the channel */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+
+/******************************************************************************/
+void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       
+       sngss7_chan_data_t  *sngss7_info ;
+       ftdm_channel_t    *ftdmchan;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RLC\n");
+
+       /* check whether the ftdm channel is in a state to accept a call */
+       switch (ftdmchan->state) {
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+
+               /* go to DOWN */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_DOWN:
+               /* do nothing, just drop the message */
+               break;
+       /**************************************************************************/
+       default:        
+               /* KONRAD: should just stop the call...but a reset is easier for now (since it does hangup the call) */
+
+               /* go to RESTART */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+
+               break;
+       /**************************************************************************/
+       }
+
+       /* unlock the channel */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+/******************************************************************************/
+void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       
+       sngss7_chan_data_t  *sngss7_info ;
+       ftdm_channel_t    *ftdmchan;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx DATA IND\n");
+
+       /* unlock the channel */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+/******************************************************************************/
+void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       
+       sngss7_chan_data_t  *sngss7_info ;
+       ftdm_channel_t    *ftdmchan;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
 
-    sngss7_chan_data_t  *sngss7_info ;
-    ftdm_channel_t      *ftdmchan;
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    }
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
 
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FAC\n");
 
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    };
+       /* unlock the channel */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-    SS7_MSG_TRACE("Received ANM on CIC # %d\n", sngss7_info->circuit->cic);
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
 
-    /* check whether the ftdm channel is in a state to accept a call */
-    switch (ftdmchan->state) {
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_PROGRESS:
-    case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+/******************************************************************************/
+void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       
+       sngss7_chan_data_t  *sngss7_info ;
+       ftdm_channel_t    *ftdmchan;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
 
-        /* go to UP */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-        break;
-    /**************************************************************************/
-    default:    /* incorrect state...reset the CIC */
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FAC-CON\n");
+
+       /* unlock the channel */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+/******************************************************************************/
+void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       
+       sngss7_chan_data_t  *sngss7_info ;
+       ftdm_channel_t    *ftdmchan;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx USER-USER msg\n");
+
+       /* unlock the channel */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+/* GENERAL STATUS *************************************************************/
+void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+{
+       sngss7_chan_data_t  *sngss7_info ;
+       ftdm_channel_t    *ftdmchan;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return;
+       }
+
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       switch (evntType) {
+       /**************************************************************************/
+       case SIT_STA_REATTEMPT:          /* reattempt indication */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Reattempt indication\n");
+               handle_reattempt(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_ERRORIND:            /* error indication */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Error indication\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CONTCHK:              /* continuity check */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT start\n");
+               handle_cot_start(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CONTREP:              /* continuity report */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT report\n");
+               handle_cot(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_STPCONTIN:          /* stop continuity */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT stop\n");
+               handle_cot_stop(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CGQRYRSP:            /* circuit grp query response from far end forwarded to upper layer by ISUP */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CQM\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CONFUSION:          /* confusion */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CFN\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_LOOPBACKACK:          /* loop-back acknowledge */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LPA\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRRSRVREQ:                /* circuit reservation request */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Ckt Resveration req\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRRSRVACK:                /* circuit reservation acknowledgement */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Ckt Res ack\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRBLOREQ:          /* circuit blocking request */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx BLO\n");
+               handle_blo_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRBLORSP:          /* circuit blocking response   */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx BLA\n");
+               handle_blo_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRUBLREQ:          /* circuit unblocking request */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UBL\n");
+               handle_ubl_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRUBLRSP:          /* circuit unblocking response */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UBA\n");
+               handle_ubl_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRRESREQ:          /* circuit reset request - RSC */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RSC\n");
+               handle_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRLOCRES:          /* reset initiated locally by the software */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local RSC\n");
+               handle_local_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRRESRSP:          /* circuit reset response */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RSC-RLC\n");
+               handle_rsc_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CGBREQ:                    /* CGB request */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CGUREQ:                    /* CGU request */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGU\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CGQRYREQ:            /* circuit group query request */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CQM\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CGBRSP:                    /* mntc. oriented CGB response */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGB\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CGURSP:                    /* mntc. oriented CGU response */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGU\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_GRSREQ:                    /* circuit group reset request */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx GRS\n");
+               handle_grs_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRUNEQPD:          /* circuit unequipped indication */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UCIC\n");
+               handle_ucic(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_GRSRSP:                    /* circuit group reset response */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx GRA\n");
+               handle_grs_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_PAUSEIND:            /* pause indication */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SUS\n");
+               handle_pause(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_RESUMEIND:          /* resume indication */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RES\n");
+               handle_resume(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_USRPARTA:            /* user part available */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UPA\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_RMTUSRUNAV:                /* remote user not available */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Remote User not Available\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_MTPCONG0:            /* congestion indication level 0 */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L0\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_MTPCONG1:            /* congestion indication level 1 */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L1\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_MTPCONG2:            /* congestion indication level 2 */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L2\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_MTPCONG3:            /* congestion indication level 3 */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L3\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_MTPSTPCONG:                /* stop congestion indication level 0 */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Stop Congestion\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break; 
+       /**************************************************************************/
+       case SIT_STA_CIRLOCALBLOIND:    /* Mngmt local blocking */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local BLO\n");
+               handle_local_blk(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRLOCALUBLIND:    /* Mngmt local unblocking */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local UBL\n");
+               handle_local_ubl(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
+               break;
+       /**************************************************************************/
+       case SIT_STA_OVERLOAD:            /* Overload */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Overload\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_LMCGBREQ:            /* when LM requests ckt grp blocking */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CGB\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_LMCGUREQ:            /* when LM requests ckt grp unblocking */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CGU\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_LMGRSREQ:            /* when LM requests ckt grp reset */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM RSC\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CGBINFOIND:                /* circuit grp blking ind , no resp req */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB no resp req\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_LMCQMINFOREQ:        /* when LM requests ckt grp query */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CQM\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       case SIT_STA_CIRLOCGRS:          /* group reset initiated locally by the software */
+               SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local GRS\n");
+               SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+               break;
+       /**************************************************************************/
+       default:
+               SS7_INFO("[SNG-CC] Received Unknown indication %d\n", evntType);
+               break;
+       } /* switch (evntType) */
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return;
+}
+
+/******************************************************************************/
+static ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
+
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       /* glare, throw the flag, go to down state*/
+       sngss7_set_flag(sngss7_info, FLAG_GLARE);
+
+       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
+
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
+       int                              infId;
+       int                              i;
+       
+       /* extract the affect infId from the circuit structure */
+       infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId;
+       
+       /* go through all the circuits now and find any other circuits on this infId */
+       i = 1;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) {
+               
+               /* check that the infId matches and that this is not a siglink */
+               if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && 
+                       (g_ftdm_sngss7_data.cfg.isupCkt[i].type == VOICE)) {
+       
+                       /* get the ftdmchan and ss7_chan_data from the circuit */
+                       if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+                               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+                               i++;
+                               continue;
+                       }
+       
+                       /* lock the channel */
+                       ftdm_mutex_lock(ftdmchan->mutex);
+       
+                       /* check if there is a pending state change, give it a bit to clear */
+                       if (check_for_state_change(ftdmchan)) {
+                               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+                               ftdm_mutex_unlock(ftdmchan->mutex);
+                               i++;
+                               SS7_ASSERT;
+                       };
+       
+                       /* check if the circuit is fully started */
+                       if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_IN_THREAD)) {
+                               /* set the pause flag on the channel */
+                               sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED);
+       
+                               /* set the statet o SUSPENDED to bring the sig status down */ 
+                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+                       }
+       
+                       /* unlock the channel again before we exit */
+                       ftdm_mutex_unlock(ftdmchan->mutex);
+       
+               } /* if (g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) */
+       
+               /* move to the next circuit */
+               i++;
+       
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) */
+       
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
+}
 
-        /* go to RESTART */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
+/******************************************************************************/
+static ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
+       int                              infId;
+       int                              i;
+
+       /* extract the affect infId from the circuit structure */
+       infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId;
+
+       /* go through all the circuits now and find any other circuits on this infId */
+       i = 1;
+       while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) {
+
+               /* check that the infId matches and that this is not a siglink */
+               if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && 
+                       (g_ftdm_sngss7_data.cfg.isupCkt[i].type == VOICE)) {
+
+                       /* get the ftdmchan and ss7_chan_data from the circuit */
+                       if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+                               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+                               i++;
+                               continue;
+                       }
+
+                       /* lock the channel */
+                       ftdm_mutex_lock(ftdmchan->mutex);
+
+                       /* check if there is a pending state change, give it a bit to clear */
+                       if (check_for_state_change(ftdmchan)) {
+                               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+                               ftdm_mutex_unlock(ftdmchan->mutex);
+                               i++;
+                               SS7_ASSERT;
+                       };
+
+                       /* only resume if we are paused */
+                       if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) {
+                               /* set the resume flag on the channel */
+                               sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME);
+
+                               /* clear the paused flag */
+                               sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED);
+
+                               /* set the statet to SUSPENDED to bring the sig status up */ 
+                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+                       }
+                       
+                       /* unlock the channel again before we exit */
+                       ftdm_mutex_unlock(ftdmchan->mutex);
 
-        break;
-    /**************************************************************************/
-    }
+               } /* if (g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) */
 
-    /* unlock the channel */
-    ftdm_mutex_unlock(ftdmchan->mutex);
+               /* move to the next circuit */
+               i++;
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
-}
+       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) */
 
-/******************************************************************************/
-void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType)
-{
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info ;
-    ftdm_channel_t      *ftdmchan;
-
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    }
-
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
-
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    }
-
-    switch (evntType) {
-    /**************************************************************************/
-    case (ADDRCMPLT):
-        SS7_MSG_TRACE("Received ACM on CIC # %d\n", sngss7_info->circuit->cic);
-        switch (ftdmchan->state) {
-        /**********************************************************************/
-        case FTDM_CHANNEL_STATE_DIALING:
-            /* KONRAD: should we confirm the instance ids ? */
-
-            /* need to grab the sp instance id */ 
-            sngss7_info->spInstId = spInstId;
-
-            /* go to PROGRESS */
-            ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
-        break;
-        /**********************************************************************/
-        default:    /* incorrect state...reset the CIC */
-            /* go to RESTART */
-            ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
-        break;
-        /**********************************************************************/
-        } /* switch (ftdmchan->state) */
-    /**************************************************************************/
-    case (MODIFY):
-        SS7_MSG_TRACE("Received MODIFY on CIC # %d\n", sngss7_info->circuit->cic);
-        break;
-    /**************************************************************************/
-    case (MODCMPLT):
-        SS7_MSG_TRACE( "Received MODIFY_COMPLETE on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (MODREJ):
-        SS7_MSG_TRACE( "Received MODIFY_REJECT on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (PROGRESS):
-        SS7_MSG_TRACE( "Received CPG on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (FRWDTRSFR):
-        SS7_MSG_TRACE( "Received FOT on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (INFORMATION):
-        SS7_MSG_TRACE( "Received INF on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (INFORMATREQ):
-        SS7_MSG_TRACE( "Received INR on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (SUBSADDR):
-        SS7_MSG_TRACE( "Received SAM on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (EXIT):
-        SS7_MSG_TRACE( "Received EXIT on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (NETRESMGT):
-        SS7_MSG_TRACE( "Received NRM on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (IDENTREQ):
-        SS7_MSG_TRACE( "Received IDR on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (IDENTRSP):
-        SS7_MSG_TRACE( "Received IRS on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (MALCLLPRNT):
-        SS7_MSG_TRACE( "Received MALICIOUS CALL on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (CHARGE):
-        SS7_MSG_TRACE( "Received CRG on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (TRFFCHGE):
-        SS7_MSG_TRACE( "Received CRG-Tariff Change on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (CHARGEACK):
-        SS7_MSG_TRACE( "Received CRG-Acknowledge on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (CALLOFFMSG):
-        SS7_MSG_TRACE( "Received CALL_OFFER on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (LOOPPRVNT):
-        SS7_MSG_TRACE( "Received LOP on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (TECT_TIMEOUT):
-        SS7_MSG_TRACE( "Received ECT Timeout on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (RINGSEND):
-        SS7_MSG_TRACE( "Received Ringing Send on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (CALLCLEAR):
-        SS7_MSG_TRACE( "Received Call_Line_clear on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (PRERELEASE):
-        SS7_MSG_TRACE( "Received PRI on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (APPTRANSPORT):
-        SS7_MSG_TRACE( "Received APM on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (OPERATOR):
-        SS7_MSG_TRACE( "Received Operator on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (METPULSE):
-        SS7_MSG_TRACE( "Received Metering Pulse on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (CLGPTCLR):
-        SS7_MSG_TRACE( "Received Calling_Party_Clear on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    case (SUBDIRNUM):
-        SS7_MSG_TRACE( "Received subsequent directory number on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    default:
-        ftdm_log(FTDM_LOG_ERROR, "Received Unknown message on circuit # %d\n", circuit);
-        break;
-    /**************************************************************************/
-    }
-
-    /* unlock the channel */
-    ftdm_mutex_unlock(ftdmchan->mutex);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt)
+static ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-    sngss7_chan_data_t  *sngss7_info ;
-    ftdm_channel_t      *ftdmchan;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    }
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    };
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       /* open the channel if it is not open */
+       if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
+               if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
+                       SS7_ERROR("Failed to open CIC %d for COT test!\n", sngss7_info->circuit->cic);
+                       /* KONRAD FIX ME */
+                       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+                       return FTDM_FAIL;
+               }
+       }
 
-    SS7_MSG_TRACE("Received REL on CIC # %d\n", sngss7_info->circuit->cic);
+       /* tell the core to loop the channel */
+       ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL);
 
-    /* check whether the ftdm channel is in a state to release a call */
-    switch (ftdmchan->state) {
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_RING:
-    case FTDM_CHANNEL_STATE_PROGRESS:
-    case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
-    case FTDM_CHANNEL_STATE_UP:
+       /* switch to the IN_LOOP state */
+       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP);
 
-        /* pass the release code up to FTDM */
-        if (siRelEvnt->causeDgn.causeVal.pres) {
-            ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val;
-        } else {
-            SS7_ERROR("REL does not have a cause code!\n");
-            ftdmchan->caller_data.hangup_cause = 0;
-        }
+       /* store the sngss7 ids */
+       if (suInstId == 0) {
+               sngss7_info->suInstId = get_unique_id();
+       } else {
+               sngss7_info->suInstId = suInstId;
+       }
+       sngss7_info->spInstId = spInstId;
+       sngss7_info->globalFlg = globalFlg;
 
-        /* move the state of the channel to TERMINATING to end the call */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_DIALING:
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
+}
 
-        /* pass the release code up to FTDM */
-        if (siRelEvnt->causeDgn.causeVal.pres) {
-            ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val;
-        } else {
-            SS7_ERROR("REL does not have a cause code!\n");
-            ftdmchan->caller_data.hangup_cause = 0;
-        }
+/******************************************************************************/
+static ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-        /* move the state of the channel to TERMINATING to end the call */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-               break;
-       /**************************************************************************/
-    default:
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-        /* fill in the channels SS7 Stack information */
-        sngss7_info->suInstId = get_unique_id();
-        sngss7_info->spInstId = spInstId;
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-        /* throw the reset flag */
-        sngss7_set_flag(sngss7_info, FLAG_RESET_RX);
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
 
-        /* set the state to RESTART */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-        break;
-    /**************************************************************************/
-    } /* switch (ftdmchan->state) */
+       /* tell the core to stop looping the channel */
+       ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
 
+       /* exit out of the LOOP state to the last state */
+       ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
 
-    /* unlock the channel */
-    ftdm_mutex_unlock(ftdmchan->mutex);
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
-
 /******************************************************************************/
-void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt)
+static ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-    
-    sngss7_chan_data_t  *sngss7_info ;
-    ftdm_channel_t      *ftdmchan;
-
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    }
-
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
-
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return;
-    };
-
-    SS7_MSG_TRACE("Received RLC on CIC # %d\n", sngss7_info->circuit->cic);
-
-    /* check whether the ftdm channel is in a state to accept a call */
-    switch (ftdmchan->state) {
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
-
-        /* go to DOWN */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_DOWN:
-        /* do nothing, just drop the message */
-        break;
-    /**************************************************************************/
-    default:    
-        /* KONRAD: should just stop the call...but a reset is easier for now (since it does hangup the call) */
-
-        /* go to RESTART */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-
-        break;
-    /**************************************************************************/
-    }
-
-    /* unlock the channel */
-    ftdm_mutex_unlock(ftdmchan->mutex);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
-}
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       if ( (siStaEvnt->contInd.eh.pres > 0) && (siStaEvnt->contInd.contInd.pres > 0)) {
+               SS7_INFO("Continuity Test result for CIC = %d (span %d, chan %d) is: \"%s\"\n",
+                                       g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic,
+                                       g_ftdm_sngss7_data.cfg.isupCkt[circuit].span,
+                                       g_ftdm_sngss7_data.cfg.isupCkt[circuit].chan,
+                                       (siStaEvnt->contInd.contInd.val) ? "PASS" : "FAIL");
+       } else {
+               SS7_ERROR("Recieved Continuity report containing no results!\n");
+       }
 
-/******************************************************************************/
-void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt)
-{
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-    SS7_MSG_TRACE( "Received DATA indication on circuit # %d\n", circuit);
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt)
-{
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-    SS7_MSG_TRACE( "Received FAC request on circuit # %d\n", circuit);
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
-}
 
-/******************************************************************************/
-void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt)
-{
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-    SS7_MSG_TRACE( "Received FAC confirm on circuit # %d\n", circuit);
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
-}
 
 /******************************************************************************/
-void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit)
+static ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-    SS7_MSG_TRACE( "Received User to User message on circuit # %d\n", circuit);
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
-}
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-/* GENERAL STATUS *************************************************************/
-void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
-{
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    SS7_MSG_TRACE("[SNG-CC] Received %s indicaton on cic = %d\n", 
-                DECODE_LCC_EVENT(evntType),
-                g_ftdm_sngss7_data.cfg.isupCircuit[circuit].cic);
-
-    switch (evntType) {
-    /**************************************************************************/
-    case SIT_STA_REATTEMPT:         /* reattempt indication */
-        handle_reattempt(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_ERRORIND:          /* error indication */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CONTCHK:           /* continuity check */
-        handle_cot_start(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_CONTREP:           /* continuity report */
-        handle_cot(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_STPCONTIN:         /* stop continuity */
-        handle_cot_stop(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_CGQRYRSP:          /* circuit grp query response from far end forwarded to upper layer by ISUP */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CONFUSION:         /* confusion */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_LOOPBACKACK:       /* loop-back acknowledge */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRRSRVREQ:        /* circuit reservation request */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRRSRVACK:        /* circuit reservation acknowledgement */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRBLOREQ:         /* circuit blocking request */
-        handle_blo_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRBLORSP:         /* circuit blocking response   */
-        handle_blo_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRUBLREQ:         /* circuit unblocking request */
-        handle_ubl_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRUBLRSP:         /* circuit unblocking response */
-        handle_ubl_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRRESREQ:         /* circuit reset request - RSC */
-        handle_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRLOCRES:         /* reset initiated locally by the software */
-        handle_local_rsc_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRRESRSP:         /* circuit reset response */
-        handle_rsc_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_CGBREQ:            /* CGB request */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CGUREQ:            /* CGU request */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CGQRYREQ:          /* circuit group query request */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CGBRSP:            /* mntc. oriented CGB response */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CGURSP:            /* mntc. oriented CGU response */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_GRSREQ:            /* circuit group reset request */
-        handle_grs_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRUNEQPD:         /* circuit unequipped indication */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_GRSRSP:            /* circuit group reset response */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_PAUSEIND:          /* pause indication */
-        handle_pause(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_RESUMEIND:         /* resume indication */
-        handle_resume(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);
-        break;
-    /**************************************************************************/
-    case SIT_STA_USRPARTA:          /* user part available */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_RMTUSRUNAV:        /* remote user not available */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_MTPCONG0:          /* congestion indication level 0 */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_MTPCONG1:          /* congestion indication level 1 */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_MTPCONG2:          /* congestion indication level 2 */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_MTPCONG3:          /* congestion indication level 3 */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_MTPSTPCONG:        /* stop congestion indication level 0 */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break; 
-    /**************************************************************************/
-    case SIT_STA_CIRLOCALBLOIND:    /* Mngmt local blocking */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRLOCALUBLIND:    /* Mngmt local unblocking */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_OVERLOAD:          /* Overload */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_LMCGBREQ:          /* when LM requests ckt grp blocking */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_LMCGUREQ:          /* when LM requests ckt grp unblocking */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_LMGRSREQ:          /* when LM requests ckt grp reset */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CGBINFOIND:        /* circuit grp blking ind , no resp req */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_LMCQMINFOREQ:      /* when LM requests ckt grp query */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_CIRLOCGRS:         /* group reset initiated locally by the software */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_GRSRSPIND:         /* indication to IW to idle the RM */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    case SIT_STA_RLCIND:            /* RLC indicattion to IW to idle the RM */
-        SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
-        break;
-    /**************************************************************************/
-    default:
-        SS7_INFO("[SNG-CC] Received Unknown indication %d\n", evntType);
-        break;
-    } /* switch (evntType) */
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       /* check if the circuit is already blocked or not */
+       if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
+               SS7_WARN("Received BLO on circuit that is already blocked!\n");
+       }
+
+       /* throw the ckt block flag */
+       sngss7_set_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
+
+       /* set the channel to suspended state */
+       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+static ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
-
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-    /* glare, throw the flag, go to down state*/
-    sngss7_set_flag(sngss7_info, FLAG_GLARE);
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
 
-    ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+       /* KONRAD FIX ME */
 
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+static ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
-    int                 infId;
-    int                 i;
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-    /* extract the affect infId from the circuit structure */
-    infId = g_ftdm_sngss7_data.cfg.isupCircuit[circuit].infId;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-    /* go through all the circuits now and find any other circuits on this infId */
-    i = 1;
-    while (g_ftdm_sngss7_data.cfg.isupCircuit[i].id != 0) {
-        
-        /* check that the infId matches and that this is not a siglink */
-        if ((g_ftdm_sngss7_data.cfg.isupCircuit[i].infId == infId) && 
-            (g_ftdm_sngss7_data.cfg.isupCircuit[i].siglink == 0)) {
-
-            /* get the ftdmchan and ss7_chan_data from the circuit */
-            if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
-                SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-                i++;
-                continue;
-            }
-
-            /* lock the channel */
-            ftdm_mutex_lock(ftdmchan->mutex);
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-            /* check if there is a pending state change, give it a bit to clear */
-            if (check_for_state_change(ftdmchan)) {
-                SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-                ftdm_mutex_unlock(ftdmchan->mutex);
-                i++;
-                continue;
-            };
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-            /* set the pause flag on the channel */
-            sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED);
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
 
-            /* set the statet o SUSPENDED to bring the sig status down */ 
-            ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+       /* check if the channel is blocked */
+       if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) {
+               SS7_WARN("Received UBL on circuit that is not blocked!\n");
+       }
 
-            /* unlock the channel again before we exit */
-            ftdm_mutex_unlock(ftdmchan->mutex);
+       /* throw the unblock flag */
+       sngss7_set_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX);
 
-        } /* if (g_ftdm_sngss7_data.cfg.isupCircuit[i].infId == infId) */
+       /* clear the block flag */
+       sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
 
-        /* move to the next circuit */
-        i++;
+       /* set the channel to suspended state */
+       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
 
-    } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[i].id != 0) */
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+static ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
-    int                 infId;
-    int                 i;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-    /* extract the affect infId from the circuit structure */
-    infId = g_ftdm_sngss7_data.cfg.isupCircuit[circuit].infId;
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-    /* go through all the circuits now and find any other circuits on this infId */
-    i = 1;
-    while (g_ftdm_sngss7_data.cfg.isupCircuit[i].id != 0) {
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-        /* check that the infId matches and that this is not a siglink */
-        if ((g_ftdm_sngss7_data.cfg.isupCircuit[i].infId == infId) && 
-            (g_ftdm_sngss7_data.cfg.isupCircuit[i].siglink == 0)) {
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
 
-            /* get the ftdmchan and ss7_chan_data from the circuit */
-            if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
-                SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-                i++;
-                continue;
-            }
+       /* KONRAD FIX ME */
 
-            /* lock the channel */
-            ftdm_mutex_lock(ftdmchan->mutex);
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-            /* check if there is a pending state change, give it a bit to clear */
-            if (check_for_state_change(ftdmchan)) {
-                SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-                ftdm_mutex_unlock(ftdmchan->mutex);
-                i++;
-                continue;
-            };
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
+}
 
-            /* set the resume flag on the channel */
-            sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME);
+/******************************************************************************/
+static ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+{
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-            /* clear the paused flag */
-            sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED);
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-            /* set the statet to SUSPENDED to bring the sig status up */ 
-            ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-            /* unlock the channel again before we exit */
-            ftdm_mutex_unlock(ftdmchan->mutex);
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-        } /* if (g_ftdm_sngss7_data.cfg.isupCircuit[i].infId == infId) */
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
 
-        /* move to the next circuit */
-        i++;
+       /* throw the reset flag */
+       sngss7_set_flag(sngss7_info, FLAG_RESET_RX);
 
-    } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[i].id != 0) */
+       switch (ftdmchan->state) {
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_RESTART:
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
-}
+               /* go to idle so that we can redo the restart state*/
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
 
-/******************************************************************************/
-static ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
-{
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
-
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
-
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
-
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
-
-    /* open the channel if it is not open */
-    if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
-        if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
-            SS7_ERROR("Failed to open CIC %d for COT test!\n", sngss7_info->circuit->cic);
-            /* KONRAD FIX ME */
-            SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-            return FTDM_FAIL;
-        }
-    }
-
-    /* tell the core to loop the channel */
-    ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL);
-
-    /* switch to the IN_LOOP state */
-    ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP);
-
-    /* store the sngss7 ids */
-    if (suInstId == 0) {
-        sngss7_info->suInstId = get_unique_id();
-    } else {
-        sngss7_info->suInstId = suInstId;
-    }
-    sngss7_info->spInstId = spInstId;
-    sngss7_info->globalFlg = globalFlg;
-
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+               break;
+       /**************************************************************************/
+       default:
+
+               /* set the state of the channel to restart...the rest is done by the chan monitor */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+               break;
+       /**************************************************************************/
+       }
+
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
+
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+static ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
 
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
+       /* throw the reset flag */
+       sngss7_set_flag(sngss7_info, FLAG_RESET_RX);
 
-    /* tell the core to stop looping the channel */
-    ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
+       switch (ftdmchan->state) {
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_RESTART:
 
-    /* exit out of the LOOP state to the last state */
-    ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
+               /* go to idle so that we can redo the restart state*/
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
 
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
+               break;
+       /**************************************************************************/
+       default:
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
-}
+               /* set the state of the channel to restart...the rest is done by the chan monitor */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+               break;
+       /**************************************************************************/
+       }
 
-/******************************************************************************/
-static ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
-{
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    if ( (siStaEvnt->contInd.eh.pres > 0) && (siStaEvnt->contInd.contInd.pres > 0)) {
-        SS7_INFO("Continuity Test result for CIC = %d (span %d, chan %d) is: \"%s\"\n",
-                    g_ftdm_sngss7_data.cfg.isupCircuit[circuit].cic,
-                    g_ftdm_sngss7_data.cfg.isupCircuit[circuit].span,
-                    g_ftdm_sngss7_data.cfg.isupCircuit[circuit].chan,
-                    (siStaEvnt->contInd.contInd.val) ? "PASS" : "FAIL");
-    } else {
-        SS7_ERROR("Recieved Continuity report containing no results!\n");
-    }
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
-}
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-/******************************************************************************/
-static ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
-{
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
-
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
-
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
-
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
-
-    switch (ftdmchan->state) {
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_RESTART:
-        /* since we are already in RESTART, the channel is already free...
-         * just waitng for the other side to clean up it's channel.
-         * just send an acknowledge to this reset, don't go through the master
-         * state handler....bad but...
-         */
-
-        sngss7_info->spInstId = 0;
-        sngss7_info->suInstId = 0;
-        sngss7_info->globalFlg = globalFlg;
-
-        ft_to_sngss7_rsca(ftdmchan);
-        break;
-    /**************************************************************************/
-    default:
-        /* throw the channels RESET_RX flag */
-        sngss7_set_flag(sngss7_info, FLAG_RESET_RX);
-
-        sngss7_info->spInstId = 0;
-        sngss7_info->suInstId = 0;
-        sngss7_info->globalFlg = globalFlg;
-
-        /* set the state of the channel to restart...the rest is done by the chan monitor */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-        break;
-    /**************************************************************************/
-    }
-
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static ftdm_status_t handle_local_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+static ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       switch (ftdmchan->state) {
+       /**********************************************************************/
+       case FTDM_CHANNEL_STATE_RESTART:
+               
+               if ( sngss7_test_flag(sngss7_info, FLAG_RESET_TX) ) {
+                       /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
+                       sngss7_set_flag(sngss7_info, FLAG_RESET_TX_RSP);
+
+                       /* go to DOWN */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+               } else {
+                       SS7_ERROR("Received RSC-RLC but we're not waiting on a RSC-RLC on CIC #, dropping\n", sngss7_info->circuit->cic);
+               }
 
-    /* the stack is sending out a RSC for us */
-    sngss7_set_flag(sngss7_info, FLAG_RESET_RX);
+               break;
+       /**********************************************************************/
+       case FTDM_CHANNEL_STATE_DOWN:
+               
+               /* do nothing, just drop the message */
+               SS7_DEBUG("Receveived RSC-RLC in down state, dropping\n");
+               
+               break;
+       /**********************************************************************/
+       case FTDM_CHANNEL_STATE_TERMINATING:
+       case FTDM_CHANNEL_STATE_HANGUP:
+       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+               
+               /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
+               sngss7_set_flag(sngss7_info, FLAG_RESET_TX_RSP);
 
-    sngss7_info->spInstId = 0;
-    sngss7_info->suInstId = 0;
-    sngss7_info->globalFlg = globalFlg;
+               /* go to DOWN */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 
-    /* set the state of the channel to restart...the rest is done by the chan monitor */
-    ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+               break;
+       /**********************************************************************/
+       default:
+               /* ITU Q764-2.9.5.1.c -> release the circuit */
+               if ((siStaEvnt != NULL) &&
+                       (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) &&
+                       (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) {
+                       ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val;
+               } else {
+                       ftdmchan->caller_data.hangup_cause = 98;        /* Message not compatiable with call state */
+               }
 
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+               break;
+       /**********************************************************************/
+       }
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
-}
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-/******************************************************************************/
-static ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
-{
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
-
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
-
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
-
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
-
-    switch (ftdmchan->state) {
-    /**********************************************************************/
-    case FTDM_CHANNEL_STATE_RESTART:
-
-        /* go to DOWN */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-
-        break;
-    /**********************************************************************/
-    case FTDM_CHANNEL_STATE_DOWN:
-        /* do nothing, just drop the message */
-        break;
-    /**********************************************************************/
-    case FTDM_CHANNEL_STATE_TERMINATING:
-    case FTDM_CHANNEL_STATE_HANGUP:
-    case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
-    /**********************************************************************/
-        /* go to DOWN */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-
-        break;
-    /**********************************************************************/
-    default:    
-        /* ITU Q764-2.9.5.1.c -> release the circuit */
-        if ((siStaEvnt != NULL) && 
-            (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) && 
-            (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) {
-            ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val;
-        } else {
-            ftdmchan->caller_data.hangup_cause = 98;    /* Message not compatiable with call state */
-        }
-
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-        break;
-    /**********************************************************************/
-    }
-
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
-
 /******************************************************************************/
-static ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+static ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
+       sngss7_span_data_t      *span = NULL; 
+       int                                     range;
+       int                             x;
+
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
+
+       /* extract the range value from the event structure */
+       if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) {
+               range = siStaEvnt->rangStat.range.val;
+       } else {
+               SS7_ERROR("Received GRS with no range value on CIC = %d\n", sngss7_info->circuit->cic);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
+
+       /* loop over the cics starting from circuit until range+1 */
+       for (x = circuit; x < (circuit + range + 1); x++) {
+               /* grab the circuit in question */
+               if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
+                       SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x);
+                       break;
+               }
+       
+               /* now that we have the right channel...put a lock on it so no-one else can use it */
+               ftdm_mutex_lock(ftdmchan->mutex);
+       
+               /* check if there is a pending state change, give it a bit to clear */
+               if (check_for_state_change(ftdmchan)) {
+                       SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+                       ftdm_mutex_unlock(ftdmchan->mutex);
+                       SS7_ASSERT;
+               };
 
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
+               /* fill in the span structure for this circuit */
+               span = ftdmchan->span->mod_data;
+               span->grs.circuit = circuit; 
+               span->grs.range = range;
 
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
+               SS7_DEBUG_CHAN(ftdmchan, "Rx GRS (%d:%d)\n", 
+                                                               g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, 
+                                                               (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range));
+
+               /* flag the channel as having received a reset */
+               sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX);
 
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
+               switch (ftdmchan->state) {
+               /**************************************************************************/
+               case FTDM_CHANNEL_STATE_RESTART:
 
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
+                       /* go to idle so that we can redo the restart state*/
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
 
-    /* check if the circuit is already blocked or not */
-    if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
-        SS7_WARN("Received BLO on circuit that is already blocked!\n");
-    }
+                       break;
+               /**************************************************************************/
+               default:
 
-    /* throw the ckt block flag */
-    sngss7_set_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
+                       /* set the state of the channel to restart...the rest is done by the chan monitor */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+                       break;
+               /**************************************************************************/
+               }
 
-    /* set the channel to suspended state */
-    ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+               /* unlock the channel again before we exit */
+               ftdm_mutex_unlock(ftdmchan->mutex);
 
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
+       }
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+static ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
+       int                                     range;
+       int                             x;
 
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
+       /* extract the range value from the event structure */
+       if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) {
+               range = siStaEvnt->rangStat.range.val;
+       } else {
+               SS7_ERROR("Received GRA with no range value on CIC = %d\n", sngss7_info->circuit->cic);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
+       /* go through all the circuits in the range */
+       for ( x = circuit; x < (circuit + range + 1); x++) {
 
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
+               /* grab the circuit in question */
+               if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
+                       SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+                       break;
+               }
 
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
+               /* now that we have the right channel...put a lock on it so no-one else can use it */
+               ftdm_mutex_lock(ftdmchan->mutex);
 
-    /* KONRAD FIX ME */
+               /* check if there is a pending state change, give it a bit to clear */
+               if (check_for_state_change(ftdmchan)) {
+                       SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+                       ftdm_mutex_unlock(ftdmchan->mutex);
+                       SS7_ASSERT;
+               };
+               
+               SS7_DEBUG_CHAN(ftdmchan, "Rx GRA (%d:%d)\n", 
+                                                               g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, 
+                                                               (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range));
+
+               switch (ftdmchan->state) {
+               /**********************************************************************/
+               case FTDM_CHANNEL_STATE_RESTART:
+                       
+                       /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
+                       sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
+
+                       /* go to DOWN */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+
+                       break;
+               /**********************************************************************/
+               case FTDM_CHANNEL_STATE_DOWN:
+
+                       /* do nothing, just drop the message */
+                       SS7_DEBUG("Receveived GRA in down state, dropping\n");
+
+                       break;
+               /**********************************************************************/
+               case FTDM_CHANNEL_STATE_TERMINATING:
+               case FTDM_CHANNEL_STATE_HANGUP:
+               case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+                       
+                       /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
+                       sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
+
+                       break;
+               /**********************************************************************/
+               default:
+                       /* ITU Q764-2.9.5.1.c -> release the circuit */
+                       if ((siStaEvnt != NULL) &&
+                               (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) &&
+                               (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) {
+                               ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val;
+                       } else {
+                               ftdmchan->caller_data.hangup_cause = 98;        /* Message not compatiable with call state */
+                       }
+
+                       /* go to terminating to hang up the call */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                       break;
+               /**********************************************************************/
+               }
 
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
+               /* unlock the channel again before we exit */
+               ftdm_mutex_unlock(ftdmchan->mutex);
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       } /* for (( x = 0; x < (circuit + range); x++) */
+       
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+static ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
-
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-    /* check if the channel is blocked */
-    if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) {
-        SS7_WARN("Received UBL on circuit that is not blocked!\n");
-    }
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
 
-    /* throw the unblock flag */
-    sngss7_set_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX);
+       /* check if the circuit is already blocked or not */
+       if (sngss7_test_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) {
+               SS7_WARN("Received local BLO on circuit that is already blocked!\n");
+       }
 
-    /* clear the block flag */
-    sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
+       /* throw the ckt block flag */
+       sngss7_set_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX);
 
-    /* set the channel to suspended state */
-    ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+       /* set the channel to suspended state */
+       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
 
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+static ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
+
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
 
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
+       /* check if the circuit is already blocked or not */
+       if (sngss7_test_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX)) {
+               SS7_WARN("Received local UBL on circuit that is already unblocked!\n");
+       }
 
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
+       /* throw the ckt block flag */
+       sngss7_set_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX);
 
-    /* KONRAD FIX ME */
+       /* set the channel to suspended state */
+       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
 
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
+static ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
-       int                                     range;
-       int                             x;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-       /* extract the range value from the event structure */
-       if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) {
-               range = siStaEvnt->rangStat.range.val;
-       } else {
-               SS7_ERROR("Received GRS with no range value on CIC = %d\n", sngss7_info->circuit->cic);
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
                SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-       return FTDM_FAIL;
-       }               
-
-       /* loop over the cics starting from circuit until range+1 */
-    for (x = circuit; x < (circuit + range + 1); x++) {
-               /* grab the circuit in question */
-               if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-                       SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-                       /* konrad fix me */
-               }
-       
-               /* now that we have the right channel...put a lock on it so no-one else can use it */
-               ftdm_mutex_lock(ftdmchan->mutex);
-       
-               /* check if there is a pending state change, give it a bit to clear */
-               if (check_for_state_change(ftdmchan)) {
-                       SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-                       ftdm_mutex_unlock(ftdmchan->mutex);
-                       /* konrad fix me */
-               };
+               return FTDM_FAIL;
+       }
 
-               /* store the circuit and range into the sngss7 info so that we can figure out when to send GRA */
-               sngss7_info->grs.circuit = circuit;
-               sngss7_info->grs.range   = range;
-               sngss7_info->globalFlg   = globalFlg;
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-               /* flag the channel as having received a reset */
-               sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX);
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
 
-               /* throw the channel into RESTART state */
-               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+       /* throw the ckt block flag */
+       sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
 
-               /* unlock the channel again before we exit */
-               ftdm_mutex_unlock(ftdmchan->mutex);
+       /* set the channel to suspended state */
+       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
 
-       }
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 
 /******************************************************************************/
 #if 0
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-    sngss7_chan_data_t  *sngss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       ftdm_channel_t    *ftdmchan = NULL;
 
-    /* get the ftdmchan and ss7_chan_data from the circuit */
-    if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
-        SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    }
+       /* get the ftdmchan and ss7_chan_data from the circuit */
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
-    /* now that we have the right channel...put a lock on it so no-one else can use it */
-    ftdm_mutex_lock(ftdmchan->mutex);
+       /* now that we have the right channel...put a lock on it so no-one else can use it */
+       ftdm_mutex_lock(ftdmchan->mutex);
 
-    /* check if there is a pending state change, give it a bit to clear */
-    if (check_for_state_change(ftdmchan)) {
-        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-        ftdm_mutex_unlock(ftdmchan->mutex);
-        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-        return FTDM_FAIL;
-    };
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       };
 
-    /* fill in here */
+       /* fill in here */
 
-    /* unlock the channel again before we exit */
-    ftdm_mutex_unlock(ftdmchan->mutex);
+       /* unlock the channel again before we exit */
+       ftdm_mutex_unlock(ftdmchan->mutex);
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 #endif
 /******************************************************************************/
+
 /******************************************************************************/
 /* For Emacs:
  * Local Variables:
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c
new file mode 100644 (file)
index 0000000..b666f72
--- /dev/null
@@ -0,0 +1,592 @@
+/*
+ * Copyright (c) 2009|Konrad Hammel <konrad@sangoma.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms|with or without
+ * modification|are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice|this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice|this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
+ * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
+ * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* INCLUDE ********************************************************************/
+#include "ftmod_sangoma_ss7_main.h"
+/******************************************************************************/
+
+/* DEFINES ********************************************************************/
+/******************************************************************************/
+
+/* GLOBALS ********************************************************************/
+/******************************************************************************/
+
+/* PROTOTYPES *****************************************************************/
+void handle_sng_log(uint8_t level, char *fmt,...);
+void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta);
+void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta);
+void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta);
+void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta);
+void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta);
+/******************************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+void handle_sng_log(uint8_t level, char *fmt,...)
+{
+       char    *data;
+       int             ret;
+       va_list ap;
+
+       va_start(ap, fmt);
+       ret = vasprintf(&data, fmt, ap);
+       if (ret == -1) {
+               return;
+       }
+
+       switch (level) {
+       /**************************************************************************/
+       case SNG_LOGLEVEL_DEBUG:
+               ftdm_log(FTDM_LOG_DEBUG, "sng_ss7->%s", data);
+               break;
+       /**************************************************************************/
+       case SNG_LOGLEVEL_WARN:
+               ftdm_log(FTDM_LOG_WARNING, "sng_ss7->%s", data);
+               break;
+       /**************************************************************************/
+       case SNG_LOGLEVEL_INFO:
+               ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
+               break;
+       /**************************************************************************/
+       case SNG_LOGLEVEL_STATS:
+               ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
+               break;
+       /**************************************************************************/
+       case SNG_LOGLEVEL_ERROR:
+               ftdm_log(FTDM_LOG_ERROR, "sng_ss7->%s", data);
+               break;
+       /**************************************************************************/
+       case SNG_LOGLEVEL_CRIT:
+               /*printf("%s",data);*/
+               ftdm_log(FTDM_LOG_CRIT, "sng_ss7->%s", data);
+               break;
+       /**************************************************************************/
+       default:
+               ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
+               break;
+       /**************************************************************************/
+       }
+
+       return;
+}
+
+/******************************************************************************/
+void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta)
+{
+
+
+}   /* handle_mtp1_alarm */
+
+/******************************************************************************/
+void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
+{
+
+       switch (sta->t.usta.alarm.category) {
+       /**************************************************************************/
+       case (LCM_CATEGORY_PROTOCOL):
+       case (LCM_CATEGORY_INTERFACE):
+
+               switch (sta->t.usta.alarm.event) {
+               /**********************************************************************/
+               case (LSD_EVENT_ENTR_CONG):
+               case (LSD_EVENT_EXIT_CONG):
+               case (LSD_EVENT_PROT_ST_UP):
+               case (LSD_EVENT_PROT_ST_DN):
+               case (LSD_EVENT_LINK_ALIGNED):
+               case (LSD_EVENT_REMOTE_CONG_START):
+               case (LSD_EVENT_REMOTE_CONG_END):
+               case (LSD_EVENT_RX_REMOTE_SIPO):
+
+                       switch (sta->t.usta.alarm.cause) {
+                       /******************************************************************/
+                       case (LCM_CAUSE_UNKNOWN):
+                               ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s\n",
+                                                                                       sta->t.usta.evntParm[0],
+                                                                                       DECODE_LSD_EVENT(sta->t.usta.alarm.event));
+                               break;
+                       /******************************************************************/
+                       case (LCM_CAUSE_MGMT_INITIATED):
+                               ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d][MGMT] %s\n",
+                                                                                       sta->t.usta.evntParm[0],
+                                                                                       DECODE_LSD_EVENT(sta->t.usta.alarm.event));
+                               break;
+                       /******************************************************************/
+                       default:
+                               ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s (***unknown cause***)\n",
+                                                                                       sta->t.usta.evntParm[0],
+                                                                                       DECODE_LSD_EVENT(sta->t.usta.alarm.event));
+                               break;
+                       /******************************************************************/
+                       } /* switch (sta->t.usta.alarm.cause) */
+                       break;
+               /**********************************************************************/
+               case (LSD_EVENT_PROT_ERR):
+                       ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %s\n",
+                                                                               sta->t.usta.evntParm[0],
+                                                                               DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+                                                                               DECODE_LSD_CAUSE(sta->t.usta.alarm.cause));
+                       break;
+               /**********************************************************************/
+               case (LSD_EVENT_ALIGN_LOST):
+                       ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %s\n",
+                                                                               sta->t.usta.evntParm[0],
+                                                                               DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+                                                                               DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
+                       break;
+               /**********************************************************************/
+               case (LSD_EVENT_RTB_FULL):
+               case (LSD_EVENT_RTB_FULL_OVER):
+                       ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : RTB Queue Len(%d)|Oldest BSN(%d)|Tx Queue Len(%d)|Outstanding Frames(%d)\n",
+                                                                               sta->t.usta.evntParm[0],
+                                                                               DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+                                                                               sta->t.usta.evntParm[1],
+                                                                               sta->t.usta.evntParm[2],
+                                                                               sta->t.usta.evntParm[3],
+                                                                               sta->t.usta.evntParm[4]);
+                       break;
+               /**********************************************************************/
+               case (LSD_EVENT_NEG_ACK):
+                       ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : RTB Queue Len(%d)\n",
+                                                                               sta->t.usta.evntParm[0],
+                                                                               DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+                                                                               sta->t.usta.evntParm[1]);
+                       break;
+               /**********************************************************************/
+               case (LSD_EVENT_DAT_CFM_SDT):
+                       ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %d\n",
+                                                                               sta->t.usta.evntParm[0],
+                                                                               DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+                                                                               DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
+                       break;
+               /**********************************************************************/
+               case (LCM_EVENT_UI_INV_EVT):
+               case (LCM_EVENT_LI_INV_EVT):
+                       ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Primitive (%d)\n",
+                                                                               DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+                                                                               DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
+                                                                               sta->t.usta.evntParm[0]);
+                       break;
+               /**********************************************************************/
+               case (LCM_EVENT_INV_EVT):
+
+                       switch (sta->t.usta.alarm.cause) {
+                       /******************************************************************/
+                       case (LCM_CAUSE_UNKNOWN):
+                       case (LCM_CAUSE_SWVER_NAVAIL):
+                               ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Event (%d)\n",
+                                                                                       DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+                                                                                       DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
+                                                                                       sta->t.usta.evntParm[0]);
+                               break;
+                       /******************************************************************/
+                       case (LCM_CAUSE_DECODE_ERR):
+                               ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Primitive (%d)|Version (%d)\n",
+                                                                                       DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+                                                                                       DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
+                                                                                       sta->t.usta.evntParm[0],
+                                                                                       sta->t.usta.evntParm[1]);
+                               break;
+                       /******************************************************************/
+                       default:
+                               ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d)\n",
+                                                                                       DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+                                                                                       sta->t.usta.alarm.event,
+                                                                                       DECODE_LSD_CAUSE(sta->t.usta.alarm.cause),
+                                                                                       sta->t.usta.alarm.cause);
+                               break;
+                       /******************************************************************/
+                       } /* switch (sta->t.usta.alarm.cause) */
+                       break;
+               /**********************************************************************/
+               default:
+                       ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d)\n",
+                                                                               DECODE_LSD_EVENT(sta->t.usta.alarm.event),
+                                                                               sta->t.usta.alarm.event,
+                                                                               DECODE_LSD_CAUSE(sta->t.usta.alarm.cause),
+                                                                               sta->t.usta.alarm.cause);
+                       break;
+               /**********************************************************************/
+               } /* switch (sta->t.usta.alarm.event) */
+               break;
+       /**************************************************************************/
+       default:
+               ftdm_log(FTDM_LOG_ERROR,"[MTP2] Unknown alarm category %d\n",
+                                                                       sta->t.usta.alarm.category);
+               break;
+       /**************************************************************************/
+       } /* switch(sta->t.usta.alarm.category) */
+
+       return;
+}   /* handle_mtp2_alarm */
+
+/******************************************************************************/
+void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
+{
+
+       switch (sta->hdr.elmId.elmnt) {
+       /**************************************************************************/
+       case (STDLSAP):
+               switch (sta->t.usta.alarm.event) {
+               /**********************************************************************/
+               case (LSN_EVENT_INV_OPC_OTHER_END):
+                       ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s : OPC(0x%X%X%X%X)\n",
+                                                                               sta->hdr.elmId.elmntInst1,
+                                                                               DECODE_LSN_EVENT(sta->t.usta.alarm.event),
+                                                                               DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
+                                                                               sta->t.usta.evntParm[3],
+                                                                               sta->t.usta.evntParm[2],
+                                                                               sta->t.usta.evntParm[1],
+                                                                               sta->t.usta.evntParm[0]);
+                       break;
+               /**********************************************************************/
+               case (LSN_EVENT_INV_SLC_OTHER_END):
+                       ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s : SLC(%d)\n",
+                                                                               sta->hdr.elmId.elmntInst1,
+                                                                               DECODE_LSN_EVENT(sta->t.usta.alarm.event),
+                                                                               DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
+                                                                               sta->t.usta.evntParm[0]);
+                       break;
+               /**********************************************************************/
+               default:
+                       ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s(%d) : %s(%d)\n",
+                                                                               sta->hdr.elmId.elmntInst1,
+                                                                               DECODE_LSN_EVENT(sta->t.usta.alarm.event),
+                                                                               sta->t.usta.alarm.event,
+                                                                               DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
+                                                                               sta->t.usta.alarm.cause);
+                       break;
+               /**********************************************************************/
+               } /* sta->t.usta.alarm.event */
+               break;
+       /**************************************************************************/
+       case (STNSAP):
+               ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s\n",
+                                                                       sta->hdr.elmId.elmntInst1,
+                                                                       DECODE_LSN_EVENT(sta->t.usta.alarm.event),
+                                                                       DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
+               break;
+       /**************************************************************************/
+       case (STLNKSET):
+               ftdm_log(FTDM_LOG_ERROR,"[MTP3][LNKSET:%d] %s : %s\n",
+                                                                       sta->hdr.elmId.elmntInst1,
+                                                                       DECODE_LSN_EVENT(sta->t.usta.alarm.event),
+                                                                       DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
+               break;
+       /**************************************************************************/
+       case (STROUT):
+               ftdm_log(FTDM_LOG_ERROR,"[MTP3][DPC:0x%d%d%d%d] %s : %s\n",
+                                                                       sta->t.usta.evntParm[0],
+                                                                       sta->t.usta.evntParm[1],
+                                                                       sta->t.usta.evntParm[2],
+                                                                       sta->t.usta.evntParm[3],
+                                                                       DECODE_LSN_EVENT(sta->t.usta.alarm.event),
+                                                                       DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
+               break;
+       /**************************************************************************/
+       default:
+               ftdm_log(FTDM_LOG_ERROR,"[MTP3] %s(%d) : %s(%d)\n",
+                                                                       DECODE_LSN_EVENT(sta->t.usta.alarm.event),
+                                                                       sta->t.usta.alarm.event,
+                                                                       DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
+                                                                       sta->t.usta.alarm.cause);
+               break;
+       /**************************************************************************/
+       } /* switch (sta->hdr.elmId.elmnt) */
+
+       return;
+}   /* handle_mtp3_alarm */
+
+/******************************************************************************/
+void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
+{
+       char    msg[250];
+       char    tmp[25];
+       char    *p = NULL;
+       int             x = 0;
+
+       /* initalize the msg variable to NULLs */
+       memset(&msg[0], '\0', sizeof(&msg));
+
+
+       /* point p to the first spot in msg */
+       p = &msg[0];
+
+       p = strcat(p, "[ISUP]");
+
+       /* go through the dgnVals */
+       for (x = 0; x < 5; x++) {
+               switch (sta->t.usta.dgn.dgnVal[x].type) {
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_NONE):
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_EVENT):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[EVENT:%d]",sta->t.usta.dgn.dgnVal[x].t.event);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_SPID):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[SPID:%d]",sta->t.usta.dgn.dgnVal[x].t.spId);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_SUID):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[SUID:%d]",sta->t.usta.dgn.dgnVal[x].t.suId);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_SPINSTID):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[SPINSTID:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.spInstId);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_SUINSTID):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[SUINSTID:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.suInstId);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_CIRCUIT):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[CKT:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.cirId);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_CIC):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[CIC:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.cic);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_INTF):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[INTF:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.intfId);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_DPC):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[DPC:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.dpc);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_ADDRS):
+#if 0
+                       /*
+                        *typedef struct addrs
+                        *{
+                        *U8 length;
+                        *U8 strg[ADRLEN];
+                        *} Addrs;
+                        */
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[ADDRS:%d]",sta->t.usta.dgn.dgnVal[x].t.);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+#endif
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_SWTCH):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[SWTCH:%d]",sta->t.usta.dgn.dgnVal[x].t.swtch);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_RANGE):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[RANGE:0x%X]",sta->t.usta.dgn.dgnVal[x].t.range);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_STATUS_OCTS):
+#if 0
+                       /*
+                        *typedef struct addrs
+                        *{
+                        *U8 length;
+                        *U8 strg[ADRLEN];
+                        *} Addrs;
+                        */
+                       /* init tmp with NULLs */
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[STATUS_OCT:0x%X]",sta->t.usta.dgn.dgnVal[x].t.);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+#endif
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_VER):
+#ifdef SI_RUG
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[VER:%d]",sta->t.usta.dgn.dgnVal[x].t.intfVer);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+#endif
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_TIMER):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[TIMER:0x%X]",sta->t.usta.dgn.dgnVal[x].t.tmrInfo);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_MSGTYPE):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[MSGTYPE:%d]",sta->t.usta.dgn.dgnVal[x].t.msgType);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               case (LSI_USTA_DGNVAL_STATE):
+                       /* init tmp with NULLs */
+                       memset(&tmp[0], '\0', sizeof(&tmp));
+
+                       /* fill in the dgn val to tmp */
+                       sprintf(&tmp[0], "[STATE:%d]",sta->t.usta.dgn.dgnVal[x].t.state);
+
+                       /* concat tmp to msg */
+                       p = strcat(p, &tmp[0]);
+                       break;
+               /**********************************************************************/
+               default:
+                       break;
+               /**********************************************************************/
+               } /* switch (sta->t.usta.dgn.dgnVal[x].t.type) */
+       } /* for  (x = 0; x < 5; x++) */
+               
+       ftdm_log(FTDM_LOG_ERROR,"%s %s : %s\n",
+                                                               msg,
+                                                               DECODE_LSI_EVENT(sta->t.usta.alarm.event),
+                                                               DECODE_LSI_CAUSE(sta->t.usta.alarm.cause));
+
+}   /* handle_isup_alarm */
+
+/******************************************************************************/
+void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
+{
+
+       return;
+}   /* handle_cc_alarm */
+/******************************************************************************/
+
+/******************************************************************************/
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
+/******************************************************************************/
index 7259931ca756bbf5aa72de34c69baa11d33d6a21..fc2c1a66b724771e953a0b6e960691ff5cb9794a 100644 (file)
 /******************************************************************************/
 
 /* GLOBALS ********************************************************************/
-static sng_isup_event_interface_t   sng_event;
-static ftdm_io_interface_t          g_ftdm_sngss7_interface;
-ftdm_sngss7_data_t                  g_ftdm_sngss7_data;
-ftdm_sched_t                        *sngss7_sched;
+static sng_isup_event_interface_t sng_event;
+static ftdm_io_interface_t g_ftdm_sngss7_interface;
+ftdm_sngss7_data_t g_ftdm_sngss7_data;
 /******************************************************************************/
 
 /* PROTOTYPES *****************************************************************/
-static void *ftdm_sangoma_ss7_run(ftdm_thread_t *me, void *obj);
-static void ftdm_sangoma_ss7_process_state_change(ftdm_channel_t *ftdmchan);
+static void *ftdm_sangoma_ss7_run (ftdm_thread_t * me, void *obj);
+static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan);
 
-static ftdm_status_t ftdm_sangoma_ss7_stop(ftdm_span_t *span);
-static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t *span);
+static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span);
+static ftdm_status_t ftdm_sangoma_ss7_start (ftdm_span_t * span);
 /******************************************************************************/
 
 /* STATE MAP ******************************************************************/
 ftdm_state_map_t sangoma_ss7_state_map = {
-    {
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_ANY_STATE, FTDM_END},
-            {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
-            {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
-            {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
-            {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_DIALING,
-             FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
-             FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
-            {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_COLLECT, FTDM_END},
-            {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END},
-            {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_RING, FTDM_END},
-            {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
-            {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
-            {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_END},
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_UP, FTDM_END},
-            {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
-            {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
-            {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
-        },
-        {
-            ZSD_INBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
-            {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
-        },
-    /**************************************************************************/
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_ANY_STATE, FTDM_END},
-            {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
-            {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
-            {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
-            {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_DIALING,
-             FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
-             FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
-            {FTDM_CHANNEL_STATE_DIALING, FTDM_END}
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
-            {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_CANCEL, FTDM_END}
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
-            {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
-            {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_END},
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_UP, FTDM_END},
-            {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
-            {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
-            {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
-        },
-        {
-            ZSD_OUTBOUND,
-            ZSM_UNACCEPTABLE,
-            {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
-            {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
-        }
-    }
+  {
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
+       {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_DOWN,
+        FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_COLLECT,
+        FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_PROGRESS,
+        FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
+        FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_TERMINATING,
+        FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING,
+        FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE,
+        FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_IDLE, FTDM_END}
+       },
+       {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_IDLE, FTDM_END},
+       {FTDM_CHANNEL_STATE_RESTART, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_COLLECT, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_RING, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_RING, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
+        FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
+        FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
+        FTDM_CHANNEL_STATE_UP, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_UP, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
+       },
+   {
+       ZSD_INBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_DOWN, FTDM_END}
+       },
+       /**************************************************************************/
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
+       {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_DOWN,
+        FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_DIALING,
+        FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
+        FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_CANCEL,
+        FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
+        FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING,
+        FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE,
+        FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_IDLE, FTDM_END}
+       },
+       {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_IDLE, FTDM_END},
+       {FTDM_CHANNEL_STATE_RESTART, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_TERMINATING,
+        FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS,
+        FTDM_CHANNEL_STATE_UP, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
+        FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
+        FTDM_CHANNEL_STATE_UP, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_UP, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
+       },
+   {
+       ZSD_OUTBOUND,
+       ZSM_UNACCEPTABLE,
+       {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
+       {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
+        FTDM_CHANNEL_STATE_DOWN, FTDM_END}
+       },
+   }
 };
+
 /******************************************************************************/
 
 /* MONITIOR THREADS ***********************************************************/
-static void *ftdm_sangoma_ss7_run(ftdm_thread_t *me, void *obj)
+static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
 {
-    ftdm_interrupt_t    *ftdm_sangoma_ss7_int = NULL;
-    ftdm_span_t         *span   = (ftdm_span_t *) obj;
-    ftdm_channel_t      *ftdmchan = NULL;
-
-    ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", span->span_id);
-
-    /* set IN_THREAD flag so that we know this thread is running */
-    ftdm_set_flag(span, FTDM_SPAN_IN_THREAD);
-
-    /* get an interrupt queue for this span */
-    if(ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_ss7_int) != FTDM_SUCCESS) {
-        SS7_CRITICAL("Failed to get a ftdm_interrupt for span = %d!\n", span->span_id);
-        goto ftdm_sangoma_ss7_run_exit;
-    }
-
-    while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
-
-        /* find out why we returned from the interrupt queue */
-        switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) {
-        /**********************************************************************/
-        case FTDM_SUCCESS:  /* there was a state change on the span */
-            /* process all pending state changes */
-            while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) {
-                /* double check that this channel has a state change pending */
-                if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
-                    ftdm_sangoma_ss7_process_state_change(ftdmchan);
-                } else {
-                    SS7_ERROR("ftdm_core reported state change, but state change flag not set on ft-span = %d, ft-chan = %d\n",
-                                ftdmchan->physical_span_id,
-                                ftdmchan->physical_chan_id);
-                }
-            } /* while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans)))  */
-
-            break;
-        /**********************************************************************/
-        case FTDM_TIMEOUT:
-            SS7_DEVEL_DEBUG("ftdm_interrupt_wait timed-out on span = %d\n", span->span_id);
-            break;
-        /**********************************************************************/
-        case FTDM_FAIL:
-            SS7_ERROR("ftdm_interrupt_wait returned error!\non span = %d\n", span->span_id);
-            break;
-        /**********************************************************************/
-        default:
-            SS7_ERROR("ftdm_interrupt_wait returned with unknown code on span = %d\n", span->span_id);
-            break;
-        /**********************************************************************/
-        } /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */
-
-    } /* master while loop */
-
-    /* clear the IN_THREAD flag so that we know the thread is done */
-    ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
-
-    ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u stopping.\n", span->span_id);
-
-    return NULL;
+       ftdm_interrupt_t        *ftdm_sangoma_ss7_int = NULL;
+       ftdm_span_t             *ftdmspan = (ftdm_span_t *) obj;
+       ftdm_channel_t          *ftdmchan = NULL;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       sngss7_span_data_t      *sngss7_span = NULL;
+       int                             i;
+
+       ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id);
+
+       /* set IN_THREAD flag so that we know this thread is running */
+       ftdm_set_flag (ftdmspan, FTDM_SPAN_IN_THREAD);
+
+       /* get an interrupt queue for this span */
+       if (ftdm_queue_get_interrupt (ftdmspan->pendingchans, &ftdm_sangoma_ss7_int) != FTDM_SUCCESS) {
+               SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d!\n", ftdmspan->span_id);
+               goto ftdm_sangoma_ss7_run_exit;
+       }
+
+       while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) {
+
+               /* find out why we returned from the interrupt queue */ 
+               switch ((ftdm_interrupt_wait (ftdm_sangoma_ss7_int, 100))) {
+               /**********************************************************************/
+               case FTDM_SUCCESS:      /* there was a state change on the span */
+                                                       /* process all pending state changes */
+
+                       while ((ftdmchan = ftdm_queue_dequeue (ftdmspan->pendingchans))) {
+                               /* double check that this channel has a state change pending */
+                               if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+                                       ftdm_sangoma_ss7_process_state_change (ftdmchan);
+                               } else {
+                                       SS7_ERROR("ftdm_core reported state change, but state change flag not set on ft-span = %d, ft-chan = %d\n",
+                                                               ftdmchan->physical_span_id,
+                                                               ftdmchan->physical_chan_id);
+                               }
+                       }/* while ((ftdmchan = ftdm_queue_dequeue(ftdmspan->pendingchans)))  */
+
+                       break;
+               /**********************************************************************/
+               case FTDM_TIMEOUT:
+                       SS7_DEVEL_DEBUG ("ftdm_interrupt_wait timed-out on span = %d\n",ftdmspan->span_id);
+
+                       break;
+               /**********************************************************************/
+               case FTDM_FAIL:
+                       SS7_ERROR ("ftdm_interrupt_wait returned error!\non span = %d\n", ftdmspan->span_id);
+
+                       break;
+               /**********************************************************************/
+               default:
+                       SS7_ERROR("ftdm_interrupt_wait returned with unknown code on span = %d\n",ftdmspan->span_id);
+
+                       break;
+               /**********************************************************************/
+               } /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */
+
+               /* extract the span data structure */
+               sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
+
+               /* check if there is a GRS being processed on the span */
+               if (sngss7_span->grs.range > 0) {
+                       ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id);
+                       /*SS7_DEBUG("Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id);*/
+
+                       /* check all the circuits in the range to see if they are done resetting */
+                       for ( i = sngss7_span->grs.circuit; i < (sngss7_span->grs.circuit + sngss7_span->grs.range + 1); i++) {
+
+                               /* extract the channel in question */
+                               if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+                                       SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
+                                       SS7_ASSERT;
+                               }
+
+                               /* lock the channel */
+                               ftdm_mutex_lock(ftdmchan->mutex);
+
+                               /* check if there is a state change pending on the channel */
+                               if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+                                       /* check the state to the GRP_RESET_RX_DN flag */
+                                       if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
+                                               /* this channel is still resetting...do nothing */
+                                               goto GRS_UNLOCK_ALL;
+                                       } /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
+                               } else {
+                                       /* state change pending */
+                                       goto GRS_UNLOCK_ALL;
+                               }
+                       } /* for ( i = circuit; i < (circuit + range + 1); i++) */
+
+                       SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
+                                               sngss7_span->grs.circuit,
+                                               sngss7_span->grs.range);
+
+                       /* check all the circuits in the range to see if they are done resetting */
+                       for ( i = sngss7_span->grs.circuit; i < (sngss7_span->grs.circuit + sngss7_span->grs.range + 1); i++) {
+
+                               /* extract the channel in question */
+                               if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+                                       SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
+                                       SS7_ASSERT;
+                               }
+
+                               /* throw the GRP reset flag complete flag */
+                               sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
+
+                               /* move the channel to the down state */
+                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+
+                       } /* for ( i = circuit; i < (circuit + range + 1); i++) */
+
+GRS_UNLOCK_ALL:
+                       for ( i = sngss7_span->grs.circuit; i < (sngss7_span->grs.circuit + sngss7_span->grs.range + 1); i++) {
+                               /* extract the channel in question */
+                               if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+                                       SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
+                                       SS7_ASSERT;
+                               }
+
+                               /* unlock the channel */
+                               ftdm_mutex_unlock(ftdmchan->mutex);
+                       }
+
+               } /* if (ftdmspan->grs.range > 0) */
+       } /* master while loop */
+
+       /* clear the IN_THREAD flag so that we know the thread is done */
+       ftdm_clear_flag (ftdmspan, FTDM_SPAN_IN_THREAD);
+
+       ftdm_log (FTDM_LOG_INFO,"ftmod_sangoma_ss7 monitor thread for span=%u stopping.\n",ftdmspan->span_id);
+
+       return NULL;
 
 ftdm_sangoma_ss7_run_exit:
 
-    /* clear the IN_THREAD flag so that we know the thread is done */
-    ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
+       /* clear the IN_THREAD flag so that we know the thread is done */
+       ftdm_clear_flag (ftdmspan, FTDM_SPAN_IN_THREAD);
 
-    ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u stopping due to error.\n", span->span_id);
+       ftdm_log (FTDM_LOG_INFO,"ftmod_sangoma_ss7 monitor thread for span=%u stopping due to error.\n",ftdmspan->span_id);
 
-    ftdm_sangoma_ss7_stop(span);
+       ftdm_sangoma_ss7_stop (ftdmspan);
 
-    return NULL;
+       return NULL;
 }
 
 /******************************************************************************/
-static void ftdm_sangoma_ss7_process_state_change(ftdm_channel_t *ftdmchan)
+static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 {
-    ftdm_sigmsg_t           sigev;
-    ftdm_signaling_status_t status;
-    sngss7_chan_data_t      *sngss7_info = ftdmchan->call_data;
-       sngss7_chan_data_t              *tmp_ss7info = NULL;
-       ftdm_channel_t                  *tmp_chan = NULL;
-    int                                        i = 0;
-
-    memset(&sigev, 0, sizeof(sigev));
-
-    sigev.chan_id = ftdmchan->chan_id;
-    sigev.span_id = ftdmchan->span_id;
-    sigev.channel = ftdmchan;
-
-    /*first lock the channel*/
-    ftdm_mutex_lock(ftdmchan->mutex);
-
-    /*clear the state change flag...since we might be setting a new state*/
-    ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
-
-    /*check what state we are supposed to be in*/
-    switch (ftdmchan->state) {
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_COLLECT:     /* IAM received but wating on digits */
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                            ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
-
-        while (ftdmchan->caller_data.cid_num.digits[i] != '\0') {
-            i++;
-        }
-
-        /* check if the end of pulsing character has arrived or the right number of digits */
-        if (ftdmchan->caller_data.cid_num.digits[i] == 0xF) {
-            SS7_DEBUG("Received the end of pulsing character\n");
-
-            /*now go to the RING state*/
-            ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
-        } else if (i >= g_ftdm_sngss7_data.min_digits) {
-            SS7_DEBUG("Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits);
-
-            /*now go to the RING state*/
-            ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
-        } else {
-            SS7_INFO("Received %d out of %d so far: %s...starting T35\n",
-                        i,
-                        g_ftdm_sngss7_data.min_digits,
-                        ftdmchan->caller_data.cid_num.digits);
-
-            /* start ISUP t35 */
-            if (ftdm_sched_timer(sngss7_info->t35.sched, 
-                                 "t35", 
-                                 sngss7_info->t35.beat, 
-                                 sngss7_info->t35.callback, 
-                                 &sngss7_info->t35,
-                                 &sngss7_info->t35.heartbeat_timer)) {
-
-                SS7_ERROR("Unable to schedule timer, hanging up call!\n");
-
-                ftdmchan->caller_data.hangup_cause = 41;
-
-                 /* set the flag to indicate this hangup is started from the local side */
-                sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL);
-
-                /* end the call */
-                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
-            } else {
-                if(ftdm_sched_free_run(sngss7_info->t35.sched)) {
-                    SS7_ERROR("Unable to run timer, hanging up call!\n");
-
-                    ftdmchan->caller_data.hangup_cause = 41;
-
-                    /* set the flag to indicate this hangup is started from the local side */
-                    sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL);
-
-                    /* end the call */
-                    ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
-                } /* if(ftdm_sched_free_run(sngss7_info->t35.sched)) */
-            } /* if (ftdm_sched_timer(sngss7_info->t35.sched, */
-
-        } /* checking ST/#digits */
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_RING:                      /*incoming call request*/
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
+       ftdm_sigmsg_t sigev;
+       ftdm_signaling_status_t status;
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       int i = 0;
+
+       memset (&sigev, 0, sizeof (sigev));
+
+       sigev.chan_id = ftdmchan->chan_id;
+       sigev.span_id = ftdmchan->span_id;
+       sigev.channel = ftdmchan;
+
+       /*first lock the channel */
+       ftdm_mutex_lock (ftdmchan->mutex);
+
+       SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s\n", ftdm_channel_state2str (ftdmchan->state));
+
+       /* clear the state change flag...since we might be setting a new state */
+       ftdm_clear_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
+       
+       /*check what state we are supposed to be in */
+       switch (ftdmchan->state) {
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_COLLECT:        /* IAM received but wating on digits */
+
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
+
+               while (ftdmchan->caller_data.dnis.digits[i] != '\0'){
+                       i++;
+               }
+
+               /* check if the end of pulsing character has arrived or the right number of digits */
+               if (ftdmchan->caller_data.dnis.digits[i] == 0xF) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Received the end of pulsing character %s\n", "");
+
+                       /*now go to the RING state */
+                       ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
+                       
+               } else if (i >= g_ftdm_sngss7_data.min_digits) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits);
+
+                       /*now go to the RING state */
+                       ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
+                       
+               } else {
+                       SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n",
+                                               i,
+                                               g_ftdm_sngss7_data.min_digits,
+                                               ftdmchan->caller_data.dnis.digits);
+
+                       /* start ISUP t35 */
+                       if (ftdm_sched_timer (sngss7_info->t35.sched,
+                                                                       "t35",
+                                                                       sngss7_info->t35.beat,
+                                                                       sngss7_info->t35.callback,
+                                                                       &sngss7_info->t35,
+                                                                       &sngss7_info->t35.heartbeat_timer)) {
+
+                               SS7_ERROR ("Unable to schedule timer, hanging up call!\n");
+
+                               ftdmchan->caller_data.hangup_cause = 41;
+
+                               /* set the flag to indicate this hangup is started from the local side */
+                               sngss7_set_flag (sngss7_info, FLAG_LOCAL_REL);
+
+                               /* end the call */
+                               ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
+                       } /* if (ftdm_sched_timer(sngss7_info->t35.sched, */
+               } /* checking ST/#digits */
+
+         break;
+
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_RING:   /*incoming call request */
+
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
 
                /* kill t35 if active */
                if (sngss7_info->t35.heartbeat_timer) {
-                       ftdm_sched_cancel_timer(sngss7_info->t35.sched, &sngss7_info->t35.heartbeat_timer);
-               } 
-
-
-
-        SS7_DEBUG("Sending incoming call from %s to %s to FTDM core\n",
-                        ftdmchan->caller_data.ani.digits,
-                        ftdmchan->caller_data.dnis.digits);
-
-
-        /* we have enough information to inform FTDM of the call*/
-        sigev.event_id = FTDM_SIGEVENT_START;
-        ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_DIALING:                   /*outgoing call request*/
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
-
-               /* clear the glare flag if it is on from a preivous call */
-               sngss7_clear_flag(sngss7_info, FLAG_GLARE);
-
-        /*call sangoma_ss7_dial to make outgoing call*/
-        ft_to_sngss7_iam(ftdmchan);
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_PROGRESS:
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
-
-        /*check if the channel is inbound or outbound*/
-        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
-
-                /*OUTBOUND...so we were told by the line of this so noifiy the user*/
-                sigev.event_id = FTDM_SIGEVENT_PROGRESS;
-                ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
-
-        } else {
-            /* inbound call so we need to send out ACM */
-            ft_to_sngss7_acm(ftdmchan);
-        }
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
-
-        /* nothing to do at this time */
-        break; 
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_UP: /*call is accpeted...both incoming and outgoing*/
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
-
-        /*check if the channel is inbound or outbound*/
-        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
-                /*OUTBOUND...so we were told by the line that the other side answered*/
-                sigev.event_id = FTDM_SIGEVENT_UP;
-                ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-        } else {
-                /*INBOUND...so FS told us it was going to answer...tell the stack*/
-                ft_to_sngss7_anm(ftdmchan);
-        }
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_CANCEL:
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
-
-        SS7_ERROR("Hanging up call before informing user on span = %d, chan = %d!\n", ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        /*now go to the HANGUP complete state*/
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_TERMINATING:            /*call is hung up remotely*/
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
-
-        /* set the flag to indicate this hangup is started from the remote side */
-        sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL);
-
-        /*this state is set when the line is hanging up*/
-        sigev.event_id = FTDM_SIGEVENT_STOP;
-        ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_HANGUP:                  /*call is hung up locally*/
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
-
-        /* check for remote hangup flag */
-        if (sngss7_test_flag(sngss7_info, FLAG_REMOTE_REL)) {
-            SS7_DEBUG("Hanging up remotely requested call!\n"); 
-        } else {
-            SS7_DEBUG("Hanging up Locally requested call!\n");
-
-             /* set the flag to indicate this hangup is started from the local side */
-            sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL);
-
-            /*this state is set when FS is hanging up...so tell the stack*/
-            ft_to_sngss7_rel(ftdmchan);
-        }
-
-        /*now go to the HANGUP complete state*/
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
-
-        if (sngss7_test_flag(sngss7_info, FLAG_REMOTE_REL)) {
-
-            /* check if this hangup is from a tx RSC */
-            if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) {
-
-                /* go to RESTART State until RSCa is received */
-                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-            } else {
-                if (!(sngss7_test_flag(sngss7_info, FLAG_RESET_RX))) {
-                    /* send out the release complete */
-                    ft_to_sngss7_rlc(ftdmchan);
-                }
-                /*now go to the DOWN state*/
-                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-            }
-
-            SS7_DEBUG("Completing remotely requested hangup!\n");
-        } else {
-            SS7_DEBUG("Completing locally requested hangup!\n");
-        }
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_DOWN:           /*the call is finished and removed*/
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
-            SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
-            break;
-        }
+                       ftdm_sched_cancel_timer (sngss7_info->t35.sched,&sngss7_info->t35.heartbeat_timer);
+               }
 
-               /* check if t35 is active */
-               if (sngss7_info->t35.heartbeat_timer) {
-                       ftdm_sched_cancel_timer(sngss7_info->t35.sched, &sngss7_info->t35.heartbeat_timer);
+               SS7_DEBUG_CHAN(ftdmchan, "Sending incoming call from %s to %s to FTDM core\n",
+                                       ftdmchan->caller_data.ani.digits,
+                                       ftdmchan->caller_data.dnis.digits);
+
+
+               /* we have enough information to inform FTDM of the call */
+               sigev.event_id = FTDM_SIGEVENT_START;
+               ftdm_span_send_signal (ftdmchan->span, &sigev);
+
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_DIALING:        /*outgoing call request */
+
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
+
+               SS7_DEBUG_CHAN(ftdmchan, "Sending outgoing call from \"%s\" to \"%s\" to LibSngSS7\n",
+                                          ftdmchan->caller_data.ani.digits,
+                                          ftdmchan->caller_data.dnis.digits);
+
+               /*call sangoma_ss7_dial to make outgoing call */
+               ft_to_sngss7_iam(ftdmchan);
+
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_PROGRESS:
+
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
+
+               /*check if the channel is inbound or outbound */
+               if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND))   {
+                       /*OUTBOUND...so we were told by the line of this so noifiy the user */
+                       sigev.event_id = FTDM_SIGEVENT_PROGRESS;
+                       ftdm_span_send_signal (ftdmchan->span, &sigev);
+
+                       ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
+               } else {
+                       /* inbound call so we need to send out ACM */
+                       ft_to_sngss7_acm (ftdmchan);
                }
 
-        /* check if there is a reset response that needs to be sent */
-        if (sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) {
-            /* send a RLC */
-            ft_to_sngss7_rsca(ftdmchan);
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
 
-            /* inform Ftdm that the "sig" is up now for this channel */
-            status = FTDM_SIG_STATE_UP;
-            sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-            sigev.raw_data = &status;
-            ftdm_span_send_signal(ftdmchan->span, &sigev);
-        }
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
+
+               /* nothing to do at this time */
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_UP:     /*call is accpeted...both incoming and outgoing */
+
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
+
+               /*check if the channel is inbound or outbound */
+               if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+                       /*OUTBOUND...so we were told by the line that the other side answered */
+                       sigev.event_id = FTDM_SIGEVENT_UP;
+                       ftdm_span_send_signal(ftdmchan->span, &sigev);
+               } else {
+                       /*INBOUND...so FS told us it was going to answer...tell the stack */
+                       ft_to_sngss7_anm(ftdmchan);
+               }
+
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_CANCEL:
+
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
+
+               SS7_ERROR_CHAN(ftdmchan,"Hanging up call before informing user%s\n", " ");
+
+               /*now go to the HANGUP complete state */
+               ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
+
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_TERMINATING:    /*call is hung up remotely */
+
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
+
+               /* set the flag to indicate this hangup is started from the remote side */
+               sngss7_set_flag (sngss7_info, FLAG_REMOTE_REL);
+
+               /*this state is set when the line is hanging up */
+               sigev.event_id = FTDM_SIGEVENT_STOP;
+               ftdm_span_send_signal (ftdmchan->span, &sigev);
+
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_HANGUP: /*call is hung up locally */
+
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
+
+               /* check for remote hangup flag */
+               if (sngss7_test_flag (sngss7_info, FLAG_REMOTE_REL)) {
+                       /* remote release ...do nothing here */
+                       SS7_DEBUG_CHAN(ftdmchan,"Hanging up remotely requested call!%s\n", "");
+               } else if (sngss7_test_flag (sngss7_info, FLAG_GLARE)) {
+                       /* release due to glare */
+                       SS7_DEBUG_CHAN(ftdmchan,"Hanging up requested call do to glare%s\n", "");
+               } else  {
+                       /* set the flag to indicate this hangup is started from the local side */
+                       sngss7_set_flag (sngss7_info, FLAG_LOCAL_REL);
+
+                       /*this state is set when FS is hanging up...so tell the stack */
+                       ft_to_sngss7_rel (ftdmchan);
+
+                       SS7_DEBUG_CHAN(ftdmchan,"Hanging up locally requested call!%s\n", "");
+               }
+
+               /*now go to the HANGUP complete state */
+               ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
+
+               break;
+
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
+
+               if (sngss7_test_flag (sngss7_info, FLAG_REMOTE_REL)) {
+                       /* check if this hangup is from a tx RSC */
+                       if (sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) {
+                               /* go to RESTART State until RSCa is received */
+                               ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+                       } else {
+                               if (!(sngss7_test_flag (sngss7_info, FLAG_RESET_RX))) {
+                                       /* send out the release complete */
+                                       ft_to_sngss7_rlc (ftdmchan);
+                               }
+
+                               /*now go to the DOWN state */
+                               ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+                       }
+
+                       SS7_DEBUG_CHAN(ftdmchan,"Completing remotely requested hangup!%s\n", "");
+               } else if (sngss7_test_flag (sngss7_info, FLAG_LOCAL_REL)) {
+
+                       /* if this hang up is do to a rx RESET we need to sit here till the RSP arrives */
+                       if (sngss7_test_flag (sngss7_info, FLAG_RESET_TX_RSP)) {
+                               /* go to the down state as we have already received RSC-RLC */
+                               ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+                       }
+
+                       /* if it's a local release the user sends us to down */
+                       SS7_DEBUG_CHAN(ftdmchan,"Completing locally requested hangup!%s\n", "");
+               } else if (sngss7_test_flag (sngss7_info, FLAG_GLARE)) {
+                       SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup due to glare!%s\n", "");
+
+                       ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+               } else {
+                       SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup for unknown reason!%s\n", "");
+               }
+
+               break;
+
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_DOWN:   /*the call is finished and removed */
+
+               /* check if there is a reset response that needs to be sent */
+               if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) {
+                       /* send a RSC-RLC */
+                       ft_to_sngss7_rsca (ftdmchan);
+
+                       /* clear the reset flag  */
+                       sngss7_clear_flag (sngss7_info, FLAG_RESET_RX);
+               }
 
                /* check if there was a GRS that needs a GRA */
-               if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) {
-                       /* check all the circuits in the range to see if we are the last ckt to reset */
-                       for (i = sngss7_info->grs.circuit; i < (sngss7_info->grs.range + 1); i++) {
-                               if (g_ftdm_sngss7_data.cfg.isupCircuit[i].siglink == 0) {
-                                       /* extract the sngss7_info for the circuit */
-                                       tmp_ss7info = g_ftdm_sngss7_data.cfg.isupCircuit[i].obj;
-                                       tmp_chan = tmp_ss7info->ftdmchan;
-                                       /* check if the circuit is done going through reset */ /* KONRAD FIX ME...better way to check this??? */
-                                       if (!(tmp_chan->state == FTDM_CHANNEL_STATE_DOWN) && (sngss7_test_flag(tmp_ss7info, FLAG_GRP_RESET_RX))) {
-                                               /* exit the for loop since we found a circuit still in reset */
-                                               continue;
-                                       } /* if inreset */
-                               } /* if not siglink */
-                       } /* for */
-
-                       /* if we got through the whole range send out a GRA */
-                       if (i == (sngss7_info->grs.range + 1)) {
+               if ((sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) &&
+                       (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) &&
+                       (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT))) {
+
+                       /* check if this is the base circuit and send out the GRA
+                        * we insure that this is the last circuit to have the state change queued
+                        */
+                       sngss7_span_data_t *span = ftdmchan->span->mod_data;
+                       if (span->grs.circuit == sngss7_info->circuit->id) {
+                               /* send out the GRA */
                                ft_to_sngss7_gra(ftdmchan);
+
+                               /* clean out the spans GRS structure */
+                               sngss7_span_data_t *span = ftdmchan->span->mod_data;
+                               span->grs.circuit = 0;
+                               span->grs.range = 0;
                        }
+
+                       /* clear the grp reset flag */
+                       sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX);
+                       sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX_DN);
+                       sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
+
+               }/*  if ( sngss7_test_flag ( sngss7_info, FLAG_GRP_RESET_RX ) ) */
+
+               /* check if we got the reset response */
+               if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX_RSP)) {
+                       /* clear the reset flag  */
+                       sngss7_clear_flag(sngss7_info, FLAG_RESET_TX_RSP);
+                       sngss7_clear_flag(sngss7_info, FLAG_RESET_TX);
                }
 
-        /* check if we got the reset response */
-        if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) {
-            /* inform Ftdm that the "sig" is up now for this channel */
-            status = FTDM_SIG_STATE_UP;
-            sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-            sigev.raw_data = &status;
-            ftdm_span_send_signal(ftdmchan->span, &sigev);
-        }
-
-        /* check if the circuit has the glare flag up */
-        if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
-                               sngss7_info->suInstId = 0;
-                               sngss7_info->spInstId = 0;
-                               sngss7_info->globalFlg = 0;
-                               sngss7_info->spId = 0;
-                               sngss7_info->flags = 0;
-                               sngss7_set_flag(sngss7_info, FLAG_GLARE);
-
-                               /* close the channel */
-                               if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
-                                       ftdm_channel_t *close_chan = ftdmchan;
-                                       /* close the channel */
-                                       ftdm_channel_close(&close_chan);
+               if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
+                       /* clear the reset flag  */
+                       sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
+                       sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_TX);
+                       sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_BASE);
+                       sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_SENT);
+               }
+
+               /* check if we came from reset (aka we just processed a reset) */
+               if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) || 
+                       (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED)) {
+
+                       /* check if reset flags are up indicating there is more processing to do yet */
+                       if (!(sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) &&
+                               !(sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) &&
+                               !(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) &&
+                               !(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX))) {
+
+                               /* check if the sig status is down, and bring it up if it isn't */
+                               if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
+                                       SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
+                                       /* all flags are down so we can bring up the sig status */
+                                       status = FTDM_SIG_STATE_UP;
+                                       sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
+                                       sigev.raw_data = &status;
+                                       ftdm_span_send_signal (ftdmchan->span, &sigev);
                                }
+                       } else {
+                       
+                               SS7_DEBUG_CHAN(ftdmchan,"Reset flags present (0x%X)\n", sngss7_info->flags);
+                       
+                               /* there is still another reset pending so go back to reset*/
+                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+                       }
+               } /* if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) */
 
-                       /* check if the glare was caused by in incoming call aka glare structure is valid */
-                       if (sngss7_info->glare.circuit != 0) {
-                               SS7_DEBUG("Glare flag is up....spoofing incoming call on span=%d, chan=%d (Cir=%d)\n",
-                                                       ftdmchan->physical_span_id,
-                                                       ftdmchan->physical_chan_id,
-                                                       sngss7_info->glare.circuit);
-                               /* clear all the call specific data */  
-
-                               /* spoof an incoming call */
-                               sngss7_con_ind(sngss7_info->glare.suInstId, 
-                                                       sngss7_info->glare.spInstId, 
-                                                       sngss7_info->glare.circuit, 
-                                                       &sngss7_info->glare.iam);
+               /* check if t35 is active */
+               if (sngss7_info->t35.heartbeat_timer) {
+                       ftdm_sched_cancel_timer (sngss7_info->t35.sched, &sngss7_info->t35.heartbeat_timer);
+               }
+
+               /* clear all of the call specific data store in the channel structure */
+               sngss7_info->suInstId = 0;
+               sngss7_info->spInstId = 0;
+               sngss7_info->globalFlg = 0;
+               sngss7_info->spId = 0;
+
+               /* clear any call related flags */
+               sngss7_clear_flag (sngss7_info, FLAG_REMOTE_REL);
+               sngss7_clear_flag (sngss7_info, FLAG_LOCAL_REL);
+
+
+               if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) {
+                       ftdm_channel_t *close_chan = ftdmchan;
+                       /* close the channel */
+                       ftdm_channel_close (&close_chan);
+               }
+
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_RESTART:        /* CICs needs a Reset */
+
+               if (sngss7_test_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK)) {
+                       if ((sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) ||
+                               (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX))) {
+
+                               SS7_DEBUG_CHAN(ftdmchan,"Incoming Reset request on CIC in UCIC block, removing UCIC block%s\n", "");
+
+                               /* set the unblk flag */
+                               sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK);
+                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+
+                               /* break out of the processing for now */
+                               break;
                        }
-        } else {
-            /* clear all of the call specific data store in the channel structure */
-            sngss7_info->suInstId = 0;
-            sngss7_info->spInstId = 0;
-            sngss7_info->globalFlg = 0;
-            sngss7_info->spId = 0;
-            sngss7_info->flags = 0;
-        
-            if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
-                ftdm_channel_t *close_chan = ftdmchan;
-                /* close the channel */
-                ftdm_channel_close(&close_chan);
-            }
-        }
-
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_RESTART:                    /* CICs needs a Reset */
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
-            /* bring the call down first...then process the rest of the reset */
-            switch (ftdmchan->last_state) {
-            /******************************************************************/
-            case(FTDM_CHANNEL_STATE_TERMINATING):
-            case(FTDM_CHANNEL_STATE_HANGUP):
-            case(FTDM_CHANNEL_STATE_HANGUP_COMPLETE):
-                /* go back to the last state after taking care of the rest of the restart state */
-                ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-                break;
-            /******************************************************************/
-            default:
-                /* KONRAD: find out what the cause code should be */
-                ftdmchan->caller_data.hangup_cause = 41;
-
-                /* change the state to terminatting, it will throw us back here 
-                 * once the call is done 
-                 */
-                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-                break;
-            /******************************************************************/
-            }
-        } else {
-
-            /* check if this an incoming RSC */
-            if (sngss7_test_flag(sngss7_info, FLAG_RESET_RX) || sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) {
-                /* go to a down state to clear the channel and send RSCa */
-                ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-            } /* if (sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) */
-        } /* if (inuse) */
-
-        /* check if this is an outgoing RSC */
-        if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) {
-    
-            /* make sure we aren't coming from hanging up a call */
-            if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP_COMPLETE) {
-                /* send a reset request */
-                ft_to_sngss7_rsc(ftdmchan);
-            }
-    
-            /* don't change to the DOWN state as we need to wait for the RSCa */
-        } /* if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) */
-        
-        /* send a sig event to the core to disable the channel */
-        status = FTDM_SIG_STATE_DOWN;
-        sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-        sigev.raw_data = &status;
-        ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_SUSPENDED:            /* circuit has been blocked */
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        /**********************************************************************/
-        if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) {
-            SS7_DEBUG("processing pause for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-            /* bring the channel signaling status to down */
-            status = FTDM_SIG_STATE_DOWN;
-            sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-            sigev.raw_data = &status;
-            ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-            /* check the last state and return to it to allow the call to finish */
-            ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-        }
-        if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) {
-            SS7_DEBUG("processing resume for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-            /* we just resumed...throw the channel into reset */
-            sngss7_set_flag(sngss7_info, FLAG_RESET_TX);
-
-            /* clear the resume flag */
-            sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME);
-
-            /* go to restart state */
-            ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-        }
-        /**********************************************************************/
-        if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
-            SS7_DEBUG("processing rx Mn ckt block for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-            /* bring the channel signaling status to down */
-            status = FTDM_SIG_STATE_DOWN;
-            sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-            sigev.raw_data = &status;
-            ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-            /* send a BLA */
-            ft_to_sngss7_bla(ftdmchan);
-
-            /* check the last state and return to it to allow the call to finish */
-            ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-        }
-        if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX)) {
-            SS7_DEBUG("processing rx Mn ckt unblock for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-            /* bring the channel signaling status to up */
-            status = FTDM_SIG_STATE_UP;
-            sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-            sigev.raw_data = &status;
-            ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-            /* clear the unblock flag */
-            sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX);
-
-            /* send a uba */
-            ft_to_sngss7_uba(ftdmchan);
-
-            /* check the last state and return to it to allow the call to finish */
-            ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-        }
-        /**********************************************************************/
-        if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) {
-            SS7_DEBUG("processing tx Mn ckt block for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-            /* bring the channel signaling status to down */
-            status = FTDM_SIG_STATE_DOWN;
-            sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-            sigev.raw_data = &status;
-            ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-            /* send a blo */
-            ft_to_sngss7_blo(ftdmchan);
-
-            /* check the last state and return to it to allow the call to finish */
-            ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-        }
-        if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX)) {
-            SS7_DEBUG("processing tx Mn ckt unblock for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-            /* bring the channel signaling status to up */
-            status = FTDM_SIG_STATE_UP;
-            sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
-            sigev.raw_data = &status;
-            ftdm_span_send_signal(ftdmchan->span, &sigev);
-
-            /* clear the unblock flag */
-            sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX);
-
-            /* send a ubl */
-            ft_to_sngss7_ubl(ftdmchan);
-
-            /* check the last state and return to it to allow the call to finish */
-            ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
-        }
-        /**********************************************************************/
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_IN_LOOP:                              /* COT test */
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        /* send the lpa */
-        ft_to_sngss7_lpa(ftdmchan);
-
-        break;
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_HOLD:
-    case FTDM_CHANNEL_STATE_DIALTONE:
-    case FTDM_CHANNEL_STATE_BUSY:
-    case FTDM_CHANNEL_STATE_ATTN:
-    case FTDM_CHANNEL_STATE_GENRING:
-    case FTDM_CHANNEL_STATE_GET_CALLERID:
-    case FTDM_CHANNEL_STATE_CALLWAITING:
-    case FTDM_CHANNEL_STATE_IDLE:
-    case FTDM_CHANNEL_STATE_INVALID:
-        ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 does not support state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-        break;
-    /**************************************************************************/
-    default:
-        /*this is bad...we're in an unknown state...should we kill this channel???*/
-        ftdm_log(FTDM_LOG_ERROR, "ftmod_sangoma_ss7 in unknown state %s on span=%u,chan=%u\n",
-                                    ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-        break;
-    } /*switch (ftdmchan->state)*/
-
-    /*unlock*/
-    ftdm_mutex_unlock(ftdmchan->mutex);
-
-    return;
-}
-/******************************************************************************/
+               }
 
-/******************************************************************************/
-static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
-{
-    sngss7_chan_data_t  *sngss7_info;
-    int c;
+               /* if we're not coming from HANGUP_COMPLETE we need to check for resets
+                * we can also check if we are in a PAUSED state (no point in sending message
+                */
+               if ((ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP_COMPLETE) &&
+                       (!sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED))) {
+
+                       /* check if this is an outgoing RSC */
+                       if ((sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) &&
+                               !(sngss7_test_flag(sngss7_info, FLAG_RESET_SENT))) {
+
+                               /* send a reset request */
+                               ft_to_sngss7_rsc (ftdmchan);
+                               sngss7_set_flag(sngss7_info, FLAG_RESET_SENT);
+
+                       } /* if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) */
+       
+                       /* check if this is the first channel of a GRS (this flag is thrown when requesting reset) */
+                       if ( (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) &&
+                               !(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_SENT)) &&
+                               (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_BASE))) {
+
+                                       /* send out the grs */
+                                       ft_to_sngss7_grs (ftdmchan);
+                                       sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_SENT);
+
+                       }/* if ( sngss7_test_flag ( sngss7_info, FLAG_GRP_RESET_TX ) ) */
+               } /* if ( last_state != HANGUP && !PAUSED */
+       
+               /* if the sig_status is up...bring it down */
+               if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
+                       status = FTDM_SIG_STATE_DOWN;
+                       sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
+                       sigev.raw_data = &status;
+                       ftdm_span_send_signal (ftdmchan->span, &sigev);
+               }
 
-    /* lock the channel while we check whether it is availble */
-    ftdm_mutex_lock(ftdmchan->mutex);
+               if (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX)) {
+                       /* set the grp reset done flag so we know we have finished this reset */
+                       sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_DN);
+               } /* if (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX)) */
+
+
+               if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_INUSE)) {
+                       /* bring the call down first...then process the rest of the reset */
+                       switch (ftdmchan->last_state){
+                       /******************************************************************/
+                       case (FTDM_CHANNEL_STATE_TERMINATING):
+                               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);     
+                               break;
+                       /******************************************************************/
+                       case (FTDM_CHANNEL_STATE_HANGUP):
+                       case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE):
+                               /* go back to the last state after taking care of the rest of the restart state */
+                               ftdm_set_state_locked (ftdmchan, ftdmchan->last_state);
+                       break;
+                       /******************************************************************/
+                       default:
+                               /* KONRAD: find out what the cause code should be */
+                               ftdmchan->caller_data.hangup_cause = 41;
+
+                               /* change the state to terminatting, it will throw us back here
+                                * once the call is done
+                                */
+                               ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                       break;
+                       /******************************************************************/
+                       } /* switch (ftdmchan->last_state) */
+               } else {
+                       /* check if this an incoming RSC or we have a response already */
+                       if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX) ||
+                               sngss7_test_flag (sngss7_info, FLAG_RESET_TX_RSP) ||
+                               sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX_RSP) ||
+                               sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX_CMPLT)) {
+       
+                               SS7_DEBUG_CHAN(ftdmchan, "Reset processed moving to DOWN (0x%X)\n", sngss7_info->flags);
+       
+                               /* go to a down state to clear the channel and send the response */
+                               ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+                       } else {
+                               SS7_DEBUG_CHAN(ftdmchan, "Waiting on Reset Rsp/Grp Reset to move to DOWN (0x%X)\n", sngss7_info->flags);
+                       }
+               }
 
-    switch (ftdmchan->state) {
-    /**************************************************************************/
-    case FTDM_CHANNEL_STATE_DOWN:
-        /* inform the monitor thread that we want to make a call */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_SUSPENDED:      /* circuit has been blocked */
 
-        /* unlock the channel */
-        ftdm_mutex_unlock(ftdmchan->mutex);
+                 SS7_DEBUG_CHAN(ftdmchan,"Current flags: 0x%X\n", sngss7_info->flags);
 
-        /* now we have to wait for either the stack to reject the call because of
-         * glare or for the network to acknowledge the call
-         */
-        c = 0;
-        while (c < 100) {
+               /**********************************************************************/
+               if (sngss7_test_flag (sngss7_info, FLAG_INFID_PAUSED))  {
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing PAUSE flag %s\n", "");
+                       
+                       /* bring the channel signaling status to down */
+                       status = FTDM_SIG_STATE_DOWN;
+                       sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
+                       sigev.raw_data = &status;
+                       ftdm_span_send_signal (ftdmchan->span, &sigev);
 
-            /* lock the channel while we check whether it is availble */
-            ftdm_mutex_lock(ftdmchan->mutex);
+                       /* check the last state and return to it to allow the call to finish */
+                       goto suspend_goto_last;
+               }
 
-                       /* check if there is a pending state change, give it a bit to clear */
-                       if (check_for_state_change(ftdmchan)) {
-                               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-                               ftdm_mutex_unlock(ftdmchan->mutex);
-                               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-                               return FTDM_FAIL;
-                       };
+               if (sngss7_test_flag (sngss7_info, FLAG_INFID_RESUME)) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing RESUME flag %s\n", "");
 
-            /* extract the sngss7_chan_data structure */
-            sngss7_info = (sngss7_chan_data_t  *)ftdmchan->call_data;
+                       /* the reset flag is set for the first channel in the span at handle_resume */
 
-            if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
-                SS7_ERROR("Glare flag on span=%d,chan=%d\n",
-                            ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
+                       /* clear the resume flag */
+                       sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME);
 
-                               /* kill the timer */
-                               if (sngss7_info->t35.heartbeat_timer) {
-                                       ftdm_sched_cancel_timer(sngss7_info->t35.sched, &sngss7_info->t35.heartbeat_timer);
-                               }
+                       /* go to restart state */
+                       goto suspend_goto_last;
+               }
 
-                goto outgoing_glare;
-            }
-
-            switch (ftdmchan->state) {
-            /******************************************************************/
-            case FTDM_CHANNEL_STATE_DIALING:
-                break;
-            /******************************************************************/
-            case FTDM_CHANNEL_STATE_PROGRESS:
-            case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
-            case FTDM_CHANNEL_STATE_UP:
-                goto outgoing_successful;
-                break;
-            /******************************************************************/
-            default:
-                SS7_ERROR("Channel in invalid state (%s) on span=%d,chan=%d...fail\n",
-                        ftdm_channel_state2str(ftdmchan->state),
-                        ftdmchan->physical_span_id,
-                        ftdmchan->physical_chan_id);
-                goto outgoing_fail;
-                break;
-            /******************************************************************/
-            }
-
-            /* unlock the channel */
-            ftdm_mutex_unlock(ftdmchan->mutex);
-
-            /* sleep for a bit to let the state change */
-            ftdm_sleep(10);
-
-            /* increment the timeout counter */
-            c++;
-
-        } /* while (c < 4) */
-
-        /* if we got here we have timed-out waiting for acknowledgment, kill the call */
-        SS7_DEBUG("Timeout waiting for outgoing call to be accepted by network, ok'ing outgoing call on span=%d,chan=%d\n",
-                        ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-
-        /* consider the call good .... for now */
-        goto outgoing_successful;
-
-        break;
-    /**************************************************************************/
-    default:
-        /* the channel is already used...this can't be, end the request */
-        SS7_ERROR("Outgoing call requested channel in already in use...indicating glare on span=%d,chan=%d\n",
-                            ftdmchan->physical_span_id,ftdmchan->physical_chan_id);
-        goto outgoing_glare;
-        break;        
-    /**************************************************************************/
-    }
+               /**********************************************************************/
+               if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_RX flag %s\n", "");
 
-outgoing_fail:
-    SS7_DEBUG("Call Request on span=%d, chan=%d failed\n");
-    /* unlock the channel */
-    ftdm_mutex_unlock(ftdmchan->mutex);  
+                       /* send a BLA */
+                       ft_to_sngss7_bla (ftdmchan);
 
-    return FTDM_FAIL;
+                       /* check the last state and return to it to allow the call to finish */
+                       goto suspend_goto_last;
+               }
 
-outgoing_glare:
-    SS7_DEBUG("Indicating glare on span=%d, chan=%d\n");
-    /* unlock the channel */
-    ftdm_mutex_unlock(ftdmchan->mutex);  
-    return FTDM_BREAK;
+               if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX)){
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_RX flag %s\n", "");
 
-outgoing_successful:
-    SS7_DEBUG("Call Request on span=%d, chan=%d successful\n");
-    /* unlock the channel */
-    ftdm_mutex_unlock(ftdmchan->mutex);
-    return FTDM_SUCCESS;
+                       /* clear the unblock flag */
+                       sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
+
+                       /* send a uba */
+                       ft_to_sngss7_uba (ftdmchan);
+
+                       /* check the last state and return to it to allow the call to finish */
+                       goto suspend_goto_last;
+               }
+
+               /**********************************************************************/
+               if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_TX)) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_TX flag %s\n", "");
+
+                       /* send a blo */
+                       ft_to_sngss7_blo (ftdmchan);
+
+                       /* check the last state and return to it to allow the call to finish */
+                       goto suspend_goto_last;
+               }
+
+               if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX)){
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_TX flag %s\n", "");
+
+                       /* clear the unblock flag */
+                       sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX);
+
+                       /* send a ubl */
+                       ft_to_sngss7_ubl (ftdmchan);
+
+                       /* check the last state and return to it to allow the call to finish */
+                       goto suspend_goto_last;
+               }
+
+               /**********************************************************************/
+               if (sngss7_test_flag (sngss7_info, FLAG_CKT_LC_BLOCK_RX)) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_BLOCK_RX flag %s\n", "");
+
+                       /* send a BLA */
+                       /*ft_to_sngss7_bla(ftdmchan);*/
+
+                       /* check the last state and return to it to allow the call to finish */
+                       goto suspend_goto_last;
+               }
+
+               if (sngss7_test_flag (sngss7_info, FLAG_CKT_LC_UNBLK_RX)) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_UNBLK_RX flag %s\n", "");
+                       
+                       /* clear the unblock flag */
+                       sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
+
+                       /* send a uba */
+                       /*ft_to_sngss7_uba(ftdmchan);*/
+
+                       /* check the last state and return to it to allow the call to finish */
+                       goto suspend_goto_last;
+               }
+               /**********************************************************************/
+               if (sngss7_test_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK)) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_BLOCK flag %s\n", "");
+
+                       /* bring the channel signaling status to down */
+                       status = FTDM_SIG_STATE_DOWN;
+                       sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
+                       sigev.raw_data = &status;
+                       ftdm_span_send_signal (ftdmchan->span, &sigev);
+
+                       /* remove any reset flags */
+                       sngss7_clear_flag (sngss7_info, FLAG_GRP_RESET_TX_RSP);
+                       sngss7_clear_flag (sngss7_info, FLAG_GRP_RESET_TX);
+                       sngss7_clear_flag (sngss7_info, FLAG_RESET_TX_RSP);
+                       sngss7_clear_flag (sngss7_info, FLAG_RESET_TX);
+                       sngss7_clear_flag (sngss7_info, FLAG_RESET_SENT);
+                       sngss7_clear_flag (sngss7_info, FLAG_GRP_RESET_RX);
+                       sngss7_clear_flag (sngss7_info, FLAG_RESET_RX);
+                       sngss7_clear_flag (sngss7_info, FLAG_GRP_RESET_BASE);
+                       
+                       /* bring the channel down */
+                       goto suspend_goto_last;
+               }
+
+               if (sngss7_test_flag (sngss7_info, FLAG_CKT_UCIC_UNBLK)) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_UNBLK flag %s\n", "");;
+
+                       /* throw the channel into reset from our side since it is already in reset from the remote side */
+                       sngss7_set_flag (sngss7_info, FLAG_RESET_TX);
+
+                       /* bring the channel into restart again */
+                       goto suspend_goto_restart;
+               }
+
+suspend_goto_last:
+               ftdm_set_state_locked (ftdmchan, ftdmchan->last_state);
+               break;
+
+suspend_goto_restart:
+               ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+               break;
+
+/**************************************************************************/
+       case FTDM_CHANNEL_STATE_IN_LOOP:        /* COT test */
+
+               /* send the lpa */
+               ft_to_sngss7_lpa (ftdmchan);
+
+               break;
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_IDLE:
+                       ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
+               break;
+       /**************************************************************************/
+       default:
+               /* we don't handle any of the other states */
+               SS7_ERROR_CHAN(ftdmchan, "ftmod_sangoma_ss7 does not support %s state\n",  ftdm_channel_state2str (ftdmchan->state));
+               
+               break;
+       /**************************************************************************/
+       }/*switch (ftdmchan->state) */
+
+       /*unlock */
+       ftdm_mutex_unlock (ftdmchan->mutex);
+
+       return;
 }
+
 /******************************************************************************/
-#if 0
-static FIO_CHANNEL_REQUEST_FUNCTION(ftdm_sangoma_ss7_request_chan)
+static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
 {
-    SS7_INFO("KONRAD-> I got called %s\n",__FUNCTION__);
-    return FTDM_SUCCESS;
+       sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
+
+       /* lock the channel while we check whether it is availble */
+       ftdm_mutex_lock (ftdmchan->mutex);
+
+       /* check if there is a pending state change, give it a bit to clear */
+       if (check_for_state_change(ftdmchan)) {
+               SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+               ftdm_mutex_unlock(ftdmchan->mutex);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               SS7_ASSERT;
+       };
+
+       if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
+               SS7_ERROR_CHAN(ftdmchan, "Requested channel sig state is down, cancelling call!%s\n", " ");
+               goto outgoing_fail;
+       }
+
+       if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
+               (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) ||
+               (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
+
+               /* the channel is blocked...can't send any calls here */
+               SS7_ERROR_CHAN(ftdmchan, "Requested channel is remotely blocked, re-hunt channel!%s\n", " ");
+               goto outgoing_break;
+       }
+
+       if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
+               (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) ||
+               (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) {
+
+               /* the channel is blocked...can't send any calls here */
+               SS7_ERROR_CHAN(ftdmchan, "Requested channel is locally blocked, re-hunt channel!%s\n", " ");
+               goto outgoing_break;
+       }
+
+       switch (ftdmchan->state){
+       /**************************************************************************/
+       case FTDM_CHANNEL_STATE_DOWN:
+               /* inform the monitor thread that we want to make a call */
+               ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DIALING);
+
+               /* unlock the channel */
+               ftdm_mutex_unlock (ftdmchan->mutex);
+               
+               goto outgoing_successful;
+               break;
+       /**************************************************************************/
+       default:
+               /* the channel is already used...this can't be, end the request */
+               SS7_ERROR("Outgoing call requested channel in already in use...indicating glare on span=%d,chan=%d\n",
+                                       ftdmchan->physical_span_id,
+                                       ftdmchan->physical_chan_id);
+
+               goto outgoing_fail;
+               break;
+       /**************************************************************************/
+       } /* switch (ftdmchan->state) (original call) */
+
+outgoing_fail:
+       SS7_DEBUG_CHAN(ftdmchan, "Call Request failed%s\n", " ");
+       /* unlock the channel */
+       ftdm_mutex_unlock (ftdmchan->mutex);
+       return FTDM_FAIL;
+
+outgoing_break:
+       SS7_DEBUG_CHAN(ftdmchan, "Call Request re-hunt%s\n", " ");
+       /* unlock the channel */
+       ftdm_mutex_unlock (ftdmchan->mutex);
+       return FTDM_BREAK;
+
+outgoing_successful:
+       SS7_DEBUG_CHAN(ftdmchan, "Call Request successful%s\n", " ");
+       /* unlock the channel */
+       ftdm_mutex_unlock (ftdmchan->mutex);
+       return FTDM_SUCCESS;
 }
+
+/******************************************************************************/
+#if 0
+         static FIO_CHANNEL_REQUEST_FUNCTION (ftdm_sangoma_ss7_request_chan)
+         {
+       SS7_INFO ("KONRAD-> I got called %s\n", __FUNCTION__);
+       return FTDM_SUCCESS;
+         }
+
 #endif
 
 /******************************************************************************/
 
-/* FT-CORE SIG STATUS FUNCTIONS ***********************************************/
+/* FT-CORE SIG STATUS FUNCTIONS ********************************************** */
 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_ss7_get_sig_status)
 {
-    
-    if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
-        *status = FTDM_SIG_STATE_UP;
-    } else {
-        *status = FTDM_SIG_STATE_DOWN;
-    }
-
-    return FTDM_SUCCESS;
+       if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
+               *status = FTDM_SIG_STATE_UP;
+       } else {
+               *status = FTDM_SIG_STATE_DOWN;
+       }
+
+       return FTDM_SUCCESS;
 }
 
+/******************************************************************************/
 static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_ss7_set_sig_status)
 {
-    SS7_ERROR("Cannot set channel status in this module\n");
-
-    return FTDM_NOTIMPL;
+       SS7_ERROR ("Cannot set channel status in this module\n");
+       return FTDM_NOTIMPL;
 }
 
-/* FT-CORE SIG FUNCTIONS *******************************************************/
-static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t *span)
+/* FT-CORE SIG FUNCTIONS ******************************************************/
+static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
 {
-    SS7_INFO("Starting span %s:%u.\n",span->name,span->span_id);
+       ftdm_channel_t          *ftdmchan = NULL;
+       sngss7_chan_data_t      *sngss7_info = NULL;
+       int                             x;
+
 
-    /* clear the monitor thread stop flag */
-    ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
-    ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
+       SS7_INFO ("Starting span %s:%u.\n", span->name, span->span_id);
 
-    /* activate all the configured ss7 links */
-    if (ft_to_sngss7_activate_all()) {
-        SS7_CRITICAL("Failed to activate LibSngSS7!\n");
-        return FTDM_FAIL;
-    }
+       /* throw the channels in pause */
+       for (x = 1; x < (span->chan_count + 1); x++) {
+               /* extract the channel structure and sngss7 channel data */
+               ftdmchan = span->channels[x];
+               sngss7_info = ftdmchan->call_data;
 
-    /*start the span monitor thread*/
-    if(ftdm_thread_create_detached(ftdm_sangoma_ss7_run, span) != FTDM_SUCCESS) {
-        SS7_CRITICAL("Failed to start Span Monitor Thread!\n");
-        return FTDM_FAIL;
-    }
+               /* lock the channel */
+               ftdm_mutex_lock(ftdmchan->mutex);
 
-    SS7_DEBUG("Finished starting span %s:%u.\n",span->name,span->span_id);
+               /* throw the pause flag */
+               sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED);
 
-    return FTDM_SUCCESS;
+               /* throw the grp reset flag */
+               sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
+               if (x == 1) {
+                       sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE);
+               }
+
+               /* throw the channel to suspend */
+               ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
+
+               /* unlock the channel */
+               ftdm_mutex_unlock(ftdmchan->mutex);
+       }
+
+       /* clear the monitor thread stop flag */
+       ftdm_clear_flag (span, FTDM_SPAN_STOP_THREAD);
+       ftdm_clear_flag (span, FTDM_SPAN_IN_THREAD);
+
+       /* activate all the configured ss7 links */
+       if (ft_to_sngss7_activate_all()) {
+               SS7_CRITICAL ("Failed to activate LibSngSS7!\n");
+               return FTDM_FAIL;
+       }
+
+       /*start the span monitor thread */
+       if (ftdm_thread_create_detached (ftdm_sangoma_ss7_run, span) != FTDM_SUCCESS) {
+               SS7_CRITICAL ("Failed to start Span Monitor Thread!\n");
+               return FTDM_FAIL;
+       }
+
+       SS7_DEBUG ("Finished starting span %s:%u.\n", span->name, span->span_id);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static ftdm_status_t ftdm_sangoma_ss7_stop(ftdm_span_t *span)
+static ftdm_status_t ftdm_sangoma_ss7_stop(ftdm_span_t * span)
 {
-    /*this function is called by the FT-Core to stop this span*/
-    
-    ftdm_log(FTDM_LOG_INFO, "Stopping span %s:%u.\n",span->name,span->span_id);
-    
-    /* throw the STOP_THREAD flag to signal monitor thread stop */
-    ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD);
-    
-    /* wait for the thread to stop */
-    while(ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) {
-        ftdm_log(FTDM_LOG_DEBUG, "Waiting for monitor thread to end for %s:%u.\n",span->name,span->span_id);
-        ftdm_sleep(1);
-    }
-
-    /* KONRAD FIX ME - deconfigure any circuits, links, attached to this span */
-
-    ftdm_log(FTDM_LOG_DEBUG, "Finished stopping span %s:%u.\n",span->name,span->span_id);
-
-    return FTDM_SUCCESS;
+       /*this function is called by the FT-Core to stop this span */
+
+       ftdm_log (FTDM_LOG_INFO, "Stopping span %s:%u.\n", span->name,span->span_id);
+
+       /* throw the STOP_THREAD flag to signal monitor thread stop */
+       ftdm_set_flag (span, FTDM_SPAN_STOP_THREAD);
+
+       /* wait for the thread to stop */
+       while (ftdm_test_flag (span, FTDM_SPAN_IN_THREAD)) {
+               ftdm_log (FTDM_LOG_DEBUG,"Waiting for monitor thread to end for %s:%u.\n",
+                                                                       span->name,
+                                                                       span->span_id);
+               ftdm_sleep (1);
+       }
+
+       /* KONRAD FIX ME - deconfigure any circuits, links, attached to this span */
+
+       ftdm_log (FTDM_LOG_DEBUG, "Finished stopping span %s:%u.\n", span->name, span->span_id);
+
+       return FTDM_SUCCESS;
 }
-/******************************************************************************/
 
 /* SIG_FUNCTIONS ***************************************************************/
 static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config)
 {
-    ftdm_log(FTDM_LOG_INFO, "Configuring ftmod_sangoma_ss7 span = %s(%d)...\n", 
-                    span->name,
-                    span->span_id);
-
-    /* parse the configuration and apply to the global config structure */
-    if (ftmod_ss7_parse_xml(ftdm_parameters, span)) {
-        ftdm_log(FTDM_LOG_CRIT, "Failed to parse configuration!\n");
-
-        return FTDM_FAIL;
-    }
-
-    /* configure libsngss7 */
-    if (ft_to_sngss7_cfg()) {
-        ftdm_log(FTDM_LOG_CRIT, "Failed to configure LibSngSS7!\n");
-        return FTDM_FAIL;
-    }
-
-    /*setup the span structure with the info so far*/
-    g_ftdm_sngss7_data.sig_cb = sig_cb;
-
-    span->start                     = ftdm_sangoma_ss7_start;
-    span->stop                      = ftdm_sangoma_ss7_stop;
-    span->signal_type               = FTDM_SIGTYPE_SS7;
-    span->signal_data               = NULL;
-    span->outgoing_call             = ftdm_sangoma_ss7_outgoing_call;
-    span->channel_request           = NULL;
-    span->signal_cb                 = sig_cb;
-    span->get_channel_sig_status    = ftdm_sangoma_ss7_get_sig_status;
-    span->set_channel_sig_status    = ftdm_sangoma_ss7_set_sig_status;
-    span->state_map                 = &sangoma_ss7_state_map;
-    ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
-
-    ftdm_log(FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_ss7 span = %s(%d)...\n", 
-                    span->name,
-                    span->span_id);
-#if 0
-    /* start the span up */
-    ftdm_sangoma_ss7_start(span);
-#endif
-    return FTDM_SUCCESS;
+       sngss7_span_data_t *ss7_span_info;
+
+       ftdm_log (FTDM_LOG_INFO, "Configuring ftmod_sangoma_ss7 span = %s(%d)...\n",
+                                                               span->name,
+                                                               span->span_id);
+
+       /* initalize the span's data structure */
+       ss7_span_info = ftdm_calloc (1, sizeof (sngss7_span_data_t));
+
+       /* create a timer schedule */
+       if (ftdm_sched_create (&ss7_span_info->sched, "SngSS7_Schedule")) {
+               SS7_CRITICAL ("Unable to create timer schedule!\n");
+               return FTDM_FAIL;
+       }
+
+       /* start the free run thread for the schedule */
+       if (ftdm_sched_free_run (ss7_span_info->sched)) {
+               SS7_CRITICAL ("Unable to schedule free run!\n");
+               return FTDM_FAIL;
+       }
+
+       /* attach the span info to the span */
+       span->mod_data = ss7_span_info;
+
+       /* parse the configuration and apply to the global config structure */
+       if (ftmod_ss7_parse_xml(ftdm_parameters, span)) {
+               ftdm_log (FTDM_LOG_CRIT, "Failed to parse configuration!\n");
+               return FTDM_FAIL;
+       }
+
+       /* configure libsngss7 */
+       if (ft_to_sngss7_cfg_all()) {
+               ftdm_log (FTDM_LOG_CRIT, "Failed to configure LibSngSS7!\n");
+               return FTDM_FAIL;
+       }
+
+       /*setup the span structure with the info so far */
+       g_ftdm_sngss7_data.sig_cb               = sig_cb;
+       span->start                                     = ftdm_sangoma_ss7_start;
+       span->stop                                              = ftdm_sangoma_ss7_stop;
+       span->signal_type                               = FTDM_SIGTYPE_SS7;
+       span->signal_data                               = NULL;
+       span->outgoing_call                     = ftdm_sangoma_ss7_outgoing_call;
+       span->channel_request                   = NULL;
+       span->signal_cb                                 = sig_cb;
+       span->get_channel_sig_status    = ftdm_sangoma_ss7_get_sig_status;
+       span->set_channel_sig_status    = ftdm_sangoma_ss7_set_sig_status;
+       span->state_map                                 = &sangoma_ss7_state_map;
+
+       ftdm_set_flag (span, FTDM_SPAN_USE_CHAN_QUEUE);
+
+       ftdm_log (FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_ss7 span = %s(%d)...\n",
+                                                               span->name,
+                                                               span->span_id);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
 {
-    /*this function is called by the FT-core to load the signaling module*/
-
-    ftdm_log(FTDM_LOG_INFO, "Loading ftmod_sangoma_ss7...\n");
-
-    /* default the global structure */
-    memset(&g_ftdm_sngss7_data, 0x0, sizeof(ftdm_sngss7_data_t));
-
-    sngss7_id = 0;
-
-    /* global flag indicating that general configuration has been done */
-    g_ftdm_sngss7_data.gen_config_done = 0;
-
-    /* min. number of digitis to wait for */
-    g_ftdm_sngss7_data.min_digits = 7;
-
-    /* function trace initizalation */
-    g_ftdm_sngss7_data.function_trace = 1;
-    g_ftdm_sngss7_data.function_trace_level = 7;
-
-    /* message (IAM, ACM, ANM, etc) trace initizalation */
-    g_ftdm_sngss7_data.message_trace = 1;
-    g_ftdm_sngss7_data.message_trace_level = 7;
-
-    /* create a timer schedule */
-    if (ftdm_sched_create(&sngss7_sched, "SngSS7_Schedule")) {
-        SS7_CRITICAL("Unable to create timer schedule!\n");
-        return FTDM_FAIL;
-    }
-
-    /* setup the call backs needed by Sangoma_SS7 library */
-    sng_event.cc.sng_con_ind = sngss7_con_ind;
-    sng_event.cc.sng_con_cfm = sngss7_con_cfm;
-    sng_event.cc.sng_con_sta = sngss7_con_sta;
-    sng_event.cc.sng_rel_ind = sngss7_rel_ind;
-    sng_event.cc.sng_rel_cfm = sngss7_rel_cfm;
-    sng_event.cc.sng_dat_ind = sngss7_dat_ind;
-    sng_event.cc.sng_fac_ind = sngss7_fac_ind;
-    sng_event.cc.sng_fac_cfm = sngss7_fac_cfm;
-    sng_event.cc.sng_sta_ind = sngss7_sta_ind;
-    sng_event.cc.sng_umsg_ind = sngss7_umsg_ind;
-    sng_event.cc.sng_susp_ind = NULL;
-    sng_event.cc.sng_resm_ind = NULL;
-    sng_event.cc.sng_ssp_sta_cfm = NULL;
-
-    sng_event.sm.sng_log = handle_sng_log;
-    sng_event.sm.sng_mtp1_alarm = handle_sng_alarm;
-    sng_event.sm.sng_mtp2_alarm = handle_sng_alarm;
-    sng_event.sm.sng_mtp3_alarm = handle_sng_alarm;
-    sng_event.sm.sng_isup_alarm = handle_sng_alarm;
-    sng_event.sm.sng_cc_alarm = handle_sng_alarm;
-
-    /* initalize sng_ss7 library */
-    sng_isup_init(&sng_event);
-
-    /* crash on assert fail */
-    ftdm_global_set_crash_policy(FTDM_CRASH_ON_ASSERT);
-
-    return FTDM_SUCCESS;
+       /*this function is called by the FT-core to load the signaling module */
+
+       ftdm_log (FTDM_LOG_INFO, "Loading ftmod_sangoma_ss7...\n");
+
+       /* default the global structure */
+       memset (&g_ftdm_sngss7_data, 0x0, sizeof (ftdm_sngss7_data_t));
+
+       sngss7_id = 0;
+
+       /* initalize the global gen_config flag */
+       g_ftdm_sngss7_data.gen_config = 0;
+
+       /* min. number of digitis to wait for */
+       g_ftdm_sngss7_data.min_digits = 7;
+
+       /* function trace initizalation */
+       g_ftdm_sngss7_data.function_trace = 1;
+       g_ftdm_sngss7_data.function_trace_level = 7;
+
+       /* message (IAM, ACM, ANM, etc) trace initizalation */
+       g_ftdm_sngss7_data.message_trace = 1;
+       g_ftdm_sngss7_data.message_trace_level = 7;
+
+       /* setup the call backs needed by Sangoma_SS7 library */
+       sng_event.cc.sng_con_ind = sngss7_con_ind;
+       sng_event.cc.sng_con_cfm = sngss7_con_cfm;
+       sng_event.cc.sng_con_sta = sngss7_con_sta;
+       sng_event.cc.sng_rel_ind = sngss7_rel_ind;
+       sng_event.cc.sng_rel_cfm = sngss7_rel_cfm;
+       sng_event.cc.sng_dat_ind = sngss7_dat_ind;
+       sng_event.cc.sng_fac_ind = sngss7_fac_ind;
+       sng_event.cc.sng_fac_cfm = sngss7_fac_cfm;
+       sng_event.cc.sng_sta_ind = sngss7_sta_ind;
+       sng_event.cc.sng_umsg_ind = sngss7_umsg_ind;
+       sng_event.cc.sng_susp_ind = NULL;
+       sng_event.cc.sng_resm_ind = NULL;
+       sng_event.cc.sng_ssp_sta_cfm = NULL;
+
+       sng_event.sm.sng_log = handle_sng_log;
+       sng_event.sm.sng_mtp1_alarm = handle_sng_mtp1_alarm;
+       sng_event.sm.sng_mtp2_alarm = handle_sng_mtp2_alarm;
+       sng_event.sm.sng_mtp3_alarm = handle_sng_mtp3_alarm;
+       sng_event.sm.sng_isup_alarm = handle_sng_isup_alarm;
+       sng_event.sm.sng_cc_alarm = handle_sng_cc_alarm;
+
+       /* initalize sng_ss7 library */
+       sng_isup_init (&sng_event);
+
+       /* crash on assert fail */
+       ftdm_global_set_crash_policy (FTDM_CRASH_ON_ASSERT);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
 {
-    /*this function is called by the FT-core to unload the signaling module*/
+       /*this function is called by the FT-core to unload the signaling module */
 
-    ftdm_log(FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n");
+       ftdm_log (FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n");
 
-    sng_isup_free(); 
+       sng_isup_free();
 
-    ftdm_log(FTDM_LOG_INFO, "Finished ftmod_sangoma_ss7 unload!\n");
-    return FTDM_SUCCESS;
+       ftdm_log (FTDM_LOG_INFO, "Finished ftmod_sangoma_ss7 unload!\n");
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static FIO_API_FUNCTION(ftdm_sangoma_ss7_api)
 {
-    /* handle this in it's own file....so much to do */
-    return (ftdm_sngss7_handle_cli_cmd(stream, data));
+       /* handle this in it's own file....so much to do */
+       return (ftdm_sngss7_handle_cli_cmd (stream, data));
 }
 
 /******************************************************************************/
 static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_ss7_io_init)
 {
-    assert(fio != NULL);
-    memset(&g_ftdm_sngss7_interface, 0, sizeof(g_ftdm_sngss7_interface));
+       assert (fio != NULL);
+       memset (&g_ftdm_sngss7_interface, 0, sizeof (g_ftdm_sngss7_interface));
 
-    g_ftdm_sngss7_interface.name = "ss7";
-    g_ftdm_sngss7_interface.api = ftdm_sangoma_ss7_api;
+       g_ftdm_sngss7_interface.name = "ss7";
+       g_ftdm_sngss7_interface.api = ftdm_sangoma_ss7_api;
 
-    *fio = &g_ftdm_sngss7_interface;
+       *fio = &g_ftdm_sngss7_interface;
 
-    return FTDM_SUCCESS;
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 
 
 /* START **********************************************************************/
-ftdm_module_t ftdm_module =
-{
-    "sangoma_ss7",                  /*char name[256];                   */
-    ftdm_sangoma_ss7_io_init,       /*fio_io_load_t                     */
-    NULL,                           /*fio_io_unload_t                   */
-    ftdm_sangoma_ss7_init,          /*fio_sig_load_t                    */
-    NULL,                           /*fio_sig_configure_t               */
-    ftdm_sangoma_ss7_unload,        /*fio_sig_unload_t                  */
-    ftdm_sangoma_ss7_span_config    /*fio_configure_span_signaling_t    */
+ftdm_module_t ftdm_module = {
+       "sangoma_ss7",                                  /*char name[256];                                  */
+       ftdm_sangoma_ss7_io_init,               /*fio_io_load_t                                  */
+       NULL,                                                   /*fio_io_unload_t                                  */
+       ftdm_sangoma_ss7_init,                  /*fio_sig_load_t                                        */
+       NULL,                                                   /*fio_sig_configure_t                      */
+       ftdm_sangoma_ss7_unload,                /*fio_sig_unload_t                                */
+       ftdm_sangoma_ss7_span_config    /*fio_configure_span_signaling_t        */
 };
 /******************************************************************************/
 
-/*****************************************************************************/
+/******************************************************************************/
 /* For Emacs:
- * Local Variables:
- * mode:c
- * indent-tabs-mode:t
- * tab-width:4
- * c-basic-offset:4
- * End:
- * For VIM:
- * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
- */
-
+* Local Variables:
+* mode:c
+* indent-tabs-mode:t
+* tab-width:4
+* c-basic-offset:4
+* End:
+* For VIM:
+* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+*/
 /******************************************************************************/
-
-
index 3f1eb37549a559537d9aee4676ad60557e163473..6bfc38e588faa2cc8c63b7d1c9aca16ab8e2c895 100644 (file)
 #include <ctype.h>
 
 #include "private/ftdm_core.h"
-/*
-#include "sng_sit.h"
-#include "sng_ss7_error.h"
-*/
+
 #include "sng_ss7.h"
 
 /******************************************************************************/
 
 /* DEFINES ********************************************************************/
-#define MAX_CIC_LENGTH      5
-#define MAX_CIC_MAP_LENGTH  256 
-#define MAX_MTP_LINKS       MAX_SN_LINKSETS
+#define MAX_NAME_LEN           10
+#define MAX_PATH                       255
+
+#define MAX_CIC_LENGTH         5
+#define MAX_CIC_MAP_LENGTH     1000 
 
-#if 0
-#define SS7_HARDCODED
-#endif
-#define SNG_BASE    1
 
 typedef enum {
-    SNG_IAM = 1,
-    SNG_ACM,
-    SNG_CPG,
-    SNG_ANM,
-    SNG_REL,
-    SNG_RLC
-}sng_msg_type_t;
+       VOICE = 0,
+       SIG,
+       HOLE
+} sng_ckt_type_t;
+
+typedef enum {
+       CONFIGURED              = (1 << 0),
+       ACTIVE                  = (1 << 1)
+} sng_flag_t;
+
+typedef struct sng_mtp_link {
+       char                    name[MAX_NAME_LEN];
+       uint32_t                id;
+       uint32_t                flags;
+       struct {
+               uint32_t        span;
+               uint32_t        chan;
+       } mtp1;
+       struct {
+               uint32_t        lssuLength;
+               uint32_t        errorType;
+               uint32_t        linkType;
+               uint32_t        mtp1Id;
+               uint32_t        t1;
+               uint32_t        t2;
+               uint32_t        t3;
+               uint32_t        t4n;
+               uint32_t        t4e;
+               uint32_t        t5;
+               uint32_t        t6;
+               uint32_t        t7;
+       } mtp2;
+       struct {
+               uint32_t        priority;
+               uint32_t        linkType;
+               uint32_t        switchType;
+               uint32_t        apc;
+               uint32_t        spc;
+               uint32_t        ssf;
+               uint32_t        slc;
+               uint32_t        linkSetId;
+               uint32_t        mtp2Id;
+               uint32_t        t1;
+               uint32_t        t2;
+               uint32_t        t3;
+               uint32_t        t4;
+               uint32_t        t5;
+               uint32_t        t6;
+               uint32_t        t7;
+               uint32_t        t8;
+               uint32_t        t9;
+               uint32_t        t10;
+               uint32_t        t11;
+               uint32_t        t12;
+               uint32_t        t13;
+               uint32_t        t14;
+               uint32_t        t15;
+               uint32_t        t16;
+               uint32_t        t17;
+               uint32_t        t18;
+               uint32_t        t19;
+               uint32_t        t20;
+               uint32_t        t21;
+               uint32_t        t22;
+               uint32_t        t23;
+               uint32_t        t24;
+               uint32_t        t25;
+               uint32_t        t26;
+               uint32_t        t27;
+               uint32_t        t28;
+               uint32_t        t29;
+               uint32_t        t30;
+               uint32_t        t31;
+               uint32_t        t32;
+               uint32_t        t33;
+               uint32_t        t34;
+               uint32_t        t35;
+               uint32_t        t36;
+               uint32_t        t37;
+               uint32_t        tcraft;
+               uint32_t        tflc;
+               uint32_t        tbnd;
+       } mtp3;
+} sng_mtp_link_t;
+
+typedef struct sng_link_set {
+       uint32_t                id;
+       char                    name[MAX_NAME_LEN];
+       uint32_t                flags;
+       uint32_t                apc;
+       uint32_t                linkType;
+       uint32_t                minActive;
+       uint32_t                numLinks;
+       uint32_t                links[16];
+} sng_link_set_t;
+
+typedef struct sng_route {
+       uint32_t                id;
+       char                    name[MAX_NAME_LEN];
+       uint32_t                flags;
+       uint32_t                dpc;
+       uint32_t                cmbLinkSetId;
+       uint32_t                linkType;
+       uint32_t                switchType;
+       uint32_t                ssf;
+       uint32_t                isSTP;
+       uint32_t                t6;
+       uint32_t                t8;
+       uint32_t                t10;
+       uint32_t                t11;
+       uint32_t                t15;
+       uint32_t                t16;
+       uint32_t                t18;
+       uint32_t                t19;
+       uint32_t                t21;
+       uint32_t                t25;
+} sng_route_t;
+
+typedef struct sng_isup_intf {
+       uint32_t                id;
+       char                    name[MAX_NAME_LEN];
+       uint32_t                flags;
+       uint32_t                spc;
+       uint32_t                dpc;
+       uint32_t                switchType;
+       uint32_t                nwId;
+       uint32_t                mtpRouteId;
+       uint32_t                ssf;
+       uint32_t                isap;
+       uint16_t                t4;
+       uint32_t                t10;
+       uint32_t                t11;
+       uint32_t                t18;
+       uint32_t                t19;
+       uint32_t                t20;
+       uint32_t                t21;
+       uint32_t                t22;
+       uint32_t                t23;
+       uint32_t                t24;
+       uint32_t                t25;
+       uint32_t                t26;
+       uint32_t                t28;
+       uint32_t                t29;
+       uint32_t                t30;
+       uint32_t                t32;
+       uint32_t                t35;
+       uint32_t                t37;
+       uint32_t                t38;
+       uint32_t                t39;
+       uint32_t                tfgr;
+       uint32_t                tpause;
+       uint32_t                tstaenq;
+} sng_isup_inf_t;
+
+typedef struct sng_isup_ckt {
+       uint32_t                id;
+       uint32_t                flags;
+       uint32_t                span;
+       uint32_t                chan;
+       uint32_t                type;   /* VOICE/SIG/HOLE */
+       uint32_t                cic;
+       uint32_t                infId;
+       uint32_t                ssf;
+       uint32_t                typeCntrl;
+       void                    *obj;
+       uint16_t                t3;
+       uint16_t                t12;
+       uint16_t                t13;
+       uint16_t                t14;
+       uint16_t                t15;
+       uint16_t                t16;
+       uint16_t                t17;
+       uint16_t                tval;
+} sng_isup_ckt_t;
+
+typedef struct sng_nsap {
+       uint32_t                id;
+       uint32_t                flags;
+       uint32_t                suId;
+       uint32_t                spId;
+       uint32_t                nwId;
+       uint32_t                linkType;
+       uint32_t                switchType;
+       uint32_t                ssf;
+} sng_nsap_t;
+
+typedef struct sng_isap {
+       uint32_t                id;
+       uint32_t                suId;
+       uint32_t                spId;
+       uint32_t                switchType;
+       uint32_t                ssf;
+       uint32_t                flags;
+       uint32_t                t1;
+       uint32_t                t2;
+       uint32_t                t5;
+       uint32_t                t6;
+       uint32_t                t7;
+       uint32_t                t8;
+       uint32_t                t9;
+       uint32_t                t27;
+       uint32_t                t31;
+       uint32_t                t33;
+       uint32_t                t34;
+       uint32_t                t36;
+       uint32_t                tccr;
+       uint32_t                tccrt;
+       uint32_t                tex;
+       uint32_t                tcrm;
+       uint32_t                tcra;
+       uint32_t                tect;
+       uint32_t                trelrsp;
+       uint32_t                tfnlrelrsp;
+} sng_isap_t;
+
+typedef struct sng_ss7_cfg {
+       uint32_t                        spc;
+       char                            license[MAX_PATH];
+       char                            signature[MAX_PATH];
+       sng_mtp_link_t          mtpLink[MAX_MTP_LINKS+1];
+       sng_link_set_t          mtpLinkSet[MAX_MTP_LINKSETS+1];
+       sng_route_t                     mtpRoute[MAX_MTP_ROUTES+1];
+       sng_isup_inf_t          isupIntf[MAX_ISUP_INFS+1];
+       sng_isup_ckt_t          isupCkt[MAX_ISUP_CKTS+1];
+       sng_nsap_t                      nsap[MAX_NSAPS+1];
+       sng_isap_t                      isap[MAX_ISAPS+1];      
+}sng_ss7_cfg_t;
 
 typedef struct ftdm_sngss7_data {
-    sng_config_t        cfg;
-    int                 gen_config_done;
-    int                 min_digits;
-    int                 function_trace;
-    int                 function_trace_level;
-    int                 message_trace;
-    int                 message_trace_level;
-    fio_signal_cb_t     sig_cb;
+       sng_ss7_cfg_t           cfg;
+       int                                     gen_config;
+       int                                     min_digits;
+       int                                     function_trace;
+       int                                     function_trace_level;
+       int                                     message_trace;
+       int                                     message_trace_level;
+       fio_signal_cb_t         sig_cb;
 }ftdm_sngss7_data_t;
 
 typedef struct sngss7_timer_data {
-    ftdm_timer_t            *heartbeat_timer;
-    int                     beat;
-    int                     counter;
-    ftdm_sched_callback_t   callback;
-    ftdm_sched_t            *sched;
-    void                    *sngss7_info;
+       ftdm_timer_t                    *heartbeat_timer;
+       int                                             beat;
+       int                                             counter;
+       ftdm_sched_callback_t   callback;
+       ftdm_sched_t                    *sched;
+       void                                    *sngss7_info;
 }sngss7_timer_data_t;
 
 typedef struct sngss7_glare_data {
-    uint32_t                suInstId; 
-    uint32_t                spInstId;
-    uint32_t                circuit; 
-    SiConEvnt               iam;
+       uint32_t                                suInstId; 
+       uint32_t                                spInstId;
+       uint32_t                                circuit; 
+       SiConEvnt                               iam;
 }sngss7_glare_data_t;
 
 typedef struct sngss7_group_data {
@@ -104,56 +319,99 @@ typedef struct sngss7_group_data {
 }sngss7_group_data_t;
 
 typedef struct sngss7_chan_data {
-    ftdm_channel_t          *ftdmchan;
-    sng_isupCircuit_t       *circuit;
-    uint32_t                suInstId;
-    uint32_t                spInstId;
-    uint32_t                spId;
-    uint8_t                 globalFlg;
-    uint32_t                flags;
-    sngss7_glare_data_t     glare;
-    sngss7_timer_data_t     t35;
-       sngss7_group_data_t             grs;
+       ftdm_channel_t                  *ftdmchan;
+       sng_isup_ckt_t                  *circuit;
+       uint32_t                                base_chan;
+       uint32_t                                suInstId;
+       uint32_t                                spInstId;
+       uint32_t                                spId;
+       uint8_t                                 globalFlg;
+       uint32_t                                flags;
+       sngss7_glare_data_t             glare;
+       sngss7_timer_data_t             t35;
 }sngss7_chan_data_t;
 
+typedef struct sngss7_span_data {
+       ftdm_sched_t                    *sched;
+       sngss7_group_data_t             grs;
+}sngss7_span_data_t;
+
 
 
 typedef enum {
-    FLAG_RESET_RX           = (1 << 0),
-    FLAG_RESET_TX           = (1 << 1),
-       FLAG_GRP_RESET_RX               = (1 << 2),
-       FLAG_GRP_RESET_TX               = (1 << 3),
-    FLAG_REMOTE_REL         = (1 << 4),
-    FLAG_LOCAL_REL          = (1 << 5),
-    FLAG_GLARE              = (1 << 6),
-    FLAG_INFID_RESUME       = (1 << 17),
-    FLAG_INFID_PAUSED       = (1 << 18),
-    FLAG_CKT_MN_BLOCK_RX    = (1 << 19),
-    FLAG_CKT_MN_BLOCK_TX    = (1 << 20),
-    FLAG_CKT_MN_UNBLK_RX    = (1 << 21),
-    FLAG_CKT_MN_UNBLK_TX    = (1 << 22),
-    FLAG_GRP_HW_BLOCK_RX    = (1 << 23),
-    FLAG_GRP_HW_BLOCK_TX    = (1 << 24),
-    FLAG_GRP_MN_BLOCK_RX    = (1 << 25),
-    FLAG_GRP_MN_BLOCK_TX    = (1 << 28),
-    FLAG_GRP_HW_UNBLK_RX    = (1 << 27),
-    FLAG_GRP_HW_UNBLK_TX    = (1 << 28),
-    FLAG_GRP_MN_UNBLK_RX    = (1 << 29),
-    FLAG_GRP_MN_UNBLK_TX    = (1 << 30)
+       FLAG_RESET_RX              = (1 << 0),
+       FLAG_RESET_TX              = (1 << 1),
+       FLAG_RESET_SENT                 = (1 << 2),
+       FLAG_RESET_TX_RSP               = (1 << 3),
+       FLAG_GRP_RESET_RX               = (1 << 4),
+       FLAG_GRP_RESET_RX_DN    = (1 << 5),
+       FLAG_GRP_RESET_RX_CMPLT = (1 << 6),
+       FLAG_GRP_RESET_BASE             = (1 << 7),
+       FLAG_GRP_RESET_TX               = (1 << 8),
+       FLAG_GRP_RESET_SENT             = (1 << 9),
+       FLAG_GRP_RESET_TX_RSP   = (1 << 10),
+       FLAG_REMOTE_REL          = (1 << 11),
+       FLAG_LOCAL_REL            = (1 << 12),
+       FLAG_GLARE                        = (1 << 13),
+       FLAG_INFID_RESUME          = (1 << 14),
+       FLAG_INFID_PAUSED          = (1 << 15),
+       FLAG_CKT_UCIC_BLOCK             = (1 << 16),
+       FLAG_CKT_UCIC_UNBLK             = (1 << 17),
+       FLAG_CKT_LC_BLOCK_RX    = (1 << 18),
+       FLAG_CKT_LC_UNBLK_RX    = (1 << 19),
+       FLAG_CKT_MN_BLOCK_RX    = (1 << 20),
+       FLAG_CKT_MN_BLOCK_TX    = (1 << 21),
+       FLAG_CKT_MN_UNBLK_RX    = (1 << 22),
+       FLAG_CKT_MN_UNBLK_TX    = (1 << 23),
+       FLAG_GRP_HW_BLOCK_RX    = (1 << 24),
+       FLAG_GRP_HW_BLOCK_TX    = (1 << 25),
+       FLAG_GRP_MN_BLOCK_RX    = (1 << 26),
+       FLAG_GRP_MN_BLOCK_TX    = (1 << 27),
+       FLAG_GRP_HW_UNBLK_RX    = (1 << 28),
+       FLAG_GRP_HW_UNBLK_TX    = (1 << 29),
+       FLAG_GRP_MN_UNBLK_RX    = (1 << 30),
+       FLAG_GRP_MN_UNBLK_TX    = (1 << 31)
 } flag_t;
 /******************************************************************************/
 
 /* GLOBALS ********************************************************************/
 extern ftdm_sngss7_data_t   g_ftdm_sngss7_data;
-extern uint32_t             sngss7_id;
-extern ftdm_sched_t         *sngss7_sched;
+extern uint32_t                         sngss7_id;
+extern ftdm_sched_t             *sngss7_sched;
 /******************************************************************************/
 
 /* PROTOTYPES *****************************************************************/
 void handle_sng_log(uint8_t level, char *fmt,...);
-void handle_sng_alarm(sng_alrm_t t_alarm);
+void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta);
+void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta);
+void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta);
+void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta);
+void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta);
+
+int ft_to_sngss7_cfg_all(void);
+int ftmod_ss7_mtp1_gen_config(void);
+int ftmod_ss7_mtp2_gen_config(void);
+int ftmod_ss7_mtp3_gen_config(void);
+int ftmod_ss7_isup_gen_config(void);
+int ftmod_ss7_cc_gen_config(void);
+int ftmod_ss7_mtp1_psap_config(int id);
+int ftmod_ss7_mtp2_dlsap_config(int id);
+int ftmod_ss7_mtp3_dlsap_config(int id);
+int ftmod_ss7_mtp3_nsap_config(int id);
+int ftmod_ss7_mtp3_linkset_config(int id);
+int ftmod_ss7_mtp3_route_config(int id);
+int ftmod_ss7_isup_nsap_config(int id);
+int ftmod_ss7_isup_intf_config(int id);
+int ftmod_ss7_isup_ckt_config(int id);
+int ftmod_ss7_isup_isap_config(int id);
+int ftmod_ss7_cc_isap_config(int id);
+
+int ftmod_ss7_inhibit_mtplink(uint32_t id);
+int ftmod_ss7_uninhibit_mtplink(uint32_t id);
+
+int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm);
+int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm);
 
-int  ft_to_sngss7_cfg(void);
 int  ft_to_sngss7_activate_all(void);
 
 void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan);
@@ -169,6 +427,7 @@ void ft_to_sngss7_ubl(ftdm_channel_t *ftdmchan);
 void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan);
 void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan);
 void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan);
+void ft_to_sngss7_grs(ftdm_channel_t *ftdmchan);
 
 void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
 void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt);
@@ -188,6 +447,8 @@ uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum
 uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum);
 uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
 int check_for_state_change(ftdm_channel_t *ftdmchan);
+int check_cics_in_range(sngss7_chan_data_t *sngss7_info);
+int check_for_reset(sngss7_chan_data_t *sngss7_info);
 ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
 unsigned long get_unique_id(void);
 
@@ -199,11 +460,17 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
 /******************************************************************************/
 
 /* MACROS *********************************************************************/
-#define SS7_DEBUG(a,...)    ftdm_log(FTDM_LOG_DEBUG,a,##__VA_ARGS__ );
-#define SS7_INFO(a,...)     ftdm_log(FTDM_LOG_INFO,a,##__VA_ARGS__ );
-#define SS7_WARN(a,...)     ftdm_log(FTDM_LOG_WARNING,a,##__VA_ARGS__ );
-#define SS7_ERROR(a,...)    ftdm_log(FTDM_LOG_ERROR,a,##__VA_ARGS__ );
-#define SS7_CRITICAL(a,...) ftdm_log(FTDM_LOG_CRIT,a,##__VA_ARGS__ );
+#define SS7_DEBUG(a,...)       ftdm_log(FTDM_LOG_DEBUG,a , ##__VA_ARGS__ );
+#define SS7_INFO(a,...)         ftdm_log(FTDM_LOG_INFO,a , ##__VA_ARGS__ );
+#define SS7_WARN(a,...)         ftdm_log(FTDM_LOG_WARNING,a , ##__VA_ARGS__ );
+#define SS7_ERROR(a,...)       ftdm_log(FTDM_LOG_ERROR,a , ##__VA_ARGS__ );
+#define SS7_CRITICAL(a,...) ftdm_log(FTDM_LOG_CRIT,a , ##__VA_ARGS__ );
+
+#define SS7_DEBUG_CHAN(fchan, msg, args...)    ftdm_log_chan(fchan, FTDM_LOG_DEBUG, msg , ##args)
+#define SS7_INFO_CHAN(fchan, msg, args...)     ftdm_log_chan(fchan, FTDM_LOG_INFO, msg , ##args)
+#define SS7_WARN_CHAN(fchan, msg, args...)     ftdm_log_chan(fchan, FTDM_LOG_WARNING, msg , ##args)
+#define SS7_ERROR_CHAN(fchan, msg, args...)    ftdm_log_chan(fchan, FTDM_LOG_ERROR, msg , ##args)
+#define SS7_CTRIT_CHAN(fchan, msg, args...)    ftdm_log_chan(fchan, FTDM_LOG_CRIT, msg , ##args)
 
 #ifdef KONRAD_DEVEL
 #define SS7_DEVEL_DEBUG(a,...)   ftdm_log(FTDM_LOG_DEBUG,a,##__VA_ARGS__ );
@@ -212,107 +479,121 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
 #endif
 
 #define SS7_FUNC_TRACE_ENTER(a) if (g_ftdm_sngss7_data.function_trace) { \
-                                    switch (g_ftdm_sngss7_data.function_trace_level) { \
-                                        case 0: \
-                                            ftdm_log(FTDM_LOG_EMERG,"Entering %s\n", a); \
-                                            break; \
-                                        case 1: \
-                                            ftdm_log(FTDM_LOG_ALERT,"Entering %s\n", a); \
-                                            break; \
-                                        case 2: \
-                                            ftdm_log(FTDM_LOG_CRIT,"Entering %s\n", a); \
-                                            break; \
-                                        case 3: \
-                                            ftdm_log(FTDM_LOG_ERROR,"Entering %s\n", a); \
-                                            break; \
-                                        case 4: \
-                                            ftdm_log(FTDM_LOG_WARNING,"Entering %s\n", a); \
-                                            break; \
-                                        case 5: \
-                                            ftdm_log(FTDM_LOG_NOTICE,"Entering %s\n", a); \
-                                            break; \
-                                        case 6: \
-                                            ftdm_log(FTDM_LOG_INFO,"Entering %s\n", a); \
-                                            break; \
-                                        case 7: \
-                                            ftdm_log(FTDM_LOG_DEBUG,"Entering %s\n", a); \
-                                            break; \
-                                        default: \
-                                            ftdm_log(FTDM_LOG_INFO,"Entering %s\n", a); \
-                                            break; \
-                                        } /* switch (g_ftdm_sngss7_data.function_trace_level) */ \
-                                } /*  if(g_ftdm_sngss7_data.function_trace) */
+                                                                       switch (g_ftdm_sngss7_data.function_trace_level) { \
+                                                                               case 0: \
+                                                                                       ftdm_log(FTDM_LOG_EMERG,"Entering %s\n", a); \
+                                                                                       break; \
+                                                                               case 1: \
+                                                                                       ftdm_log(FTDM_LOG_ALERT,"Entering %s\n", a); \
+                                                                                       break; \
+                                                                               case 2: \
+                                                                                       ftdm_log(FTDM_LOG_CRIT,"Entering %s\n", a); \
+                                                                                       break; \
+                                                                               case 3: \
+                                                                                       ftdm_log(FTDM_LOG_ERROR,"Entering %s\n", a); \
+                                                                                       break; \
+                                                                               case 4: \
+                                                                                       ftdm_log(FTDM_LOG_WARNING,"Entering %s\n", a); \
+                                                                                       break; \
+                                                                               case 5: \
+                                                                                       ftdm_log(FTDM_LOG_NOTICE,"Entering %s\n", a); \
+                                                                                       break; \
+                                                                               case 6: \
+                                                                                       ftdm_log(FTDM_LOG_INFO,"Entering %s\n", a); \
+                                                                                       break; \
+                                                                               case 7: \
+                                                                                       ftdm_log(FTDM_LOG_DEBUG,"Entering %s\n", a); \
+                                                                                       break; \
+                                                                               default: \
+                                                                                       ftdm_log(FTDM_LOG_INFO,"Entering %s\n", a); \
+                                                                                       break; \
+                                                                               } /* switch (g_ftdm_sngss7_data.function_trace_level) */ \
+                                                               } /*  if(g_ftdm_sngss7_data.function_trace) */
 
 #define SS7_FUNC_TRACE_EXIT(a) if (g_ftdm_sngss7_data.function_trace) { \
-                                    switch (g_ftdm_sngss7_data.function_trace_level) { \
-                                        case 0: \
-                                            ftdm_log(FTDM_LOG_EMERG,"Exitting %s\n", a); \
-                                            break; \
-                                        case 1: \
-                                            ftdm_log(FTDM_LOG_ALERT,"Exitting %s\n", a); \
-                                            break; \
-                                        case 2: \
-                                            ftdm_log(FTDM_LOG_CRIT,"Exitting %s\n", a); \
-                                            break; \
-                                        case 3: \
-                                            ftdm_log(FTDM_LOG_ERROR,"Exitting %s\n", a); \
-                                            break; \
-                                        case 4: \
-                                            ftdm_log(FTDM_LOG_WARNING,"Exitting %s\n", a); \
-                                            break; \
-                                        case 5: \
-                                            ftdm_log(FTDM_LOG_NOTICE,"Exitting %s\n", a); \
-                                            break; \
-                                        case 6: \
-                                            ftdm_log(FTDM_LOG_INFO,"Exitting %s\n", a); \
-                                            break; \
-                                        case 7: \
-                                            ftdm_log(FTDM_LOG_DEBUG,"Exitting %s\n", a); \
-                                            break; \
-                                        default: \
-                                            ftdm_log(FTDM_LOG_INFO,"Exitting %s\n", a); \
-                                            break; \
-                                        } /* switch (g_ftdm_sngss7_data.function_trace_level) */ \
-                                } /*  if(g_ftdm_sngss7_data.function_trace) */
-
-#define SS7_MSG_TRACE(a,...) if (g_ftdm_sngss7_data.message_trace) { \
-                                    switch (g_ftdm_sngss7_data.message_trace_level) { \
-                                        case 0: \
-                                            ftdm_log(FTDM_LOG_EMERG,a,##__VA_ARGS__ ); \
-                                            break; \
-                                        case 1: \
-                                            ftdm_log(FTDM_LOG_ALERT,a,##__VA_ARGS__ ); \
-                                            break; \
-                                        case 2: \
-                                            ftdm_log(FTDM_LOG_CRIT,a,##__VA_ARGS__ ); \
-                                            break; \
-                                        case 3: \
-                                            ftdm_log(FTDM_LOG_ERROR,a,##__VA_ARGS__ ); \
-                                            break; \
-                                        case 4: \
-                                            ftdm_log(FTDM_LOG_WARNING,a,##__VA_ARGS__ ); \
-                                            break; \
-                                        case 5: \
-                                            ftdm_log(FTDM_LOG_NOTICE,a,##__VA_ARGS__ ); \
-                                            break; \
-                                        case 6: \
-                                            ftdm_log(FTDM_LOG_INFO,a,##__VA_ARGS__ ); \
-                                            break; \
-                                        case 7: \
-                                            ftdm_log(FTDM_LOG_DEBUG,a,##__VA_ARGS__ ); \
-                                            break; \
-                                        default: \
-                                            ftdm_log(FTDM_LOG_INFO,a,##__VA_ARGS__ ); \
-                                            break; \
-                                        } /* switch (g_ftdm_sngss7_data.message_trace_level) */ \
-                                } /* if(g_ftdm_sngss7_data.message_trace) */
+                                                                       switch (g_ftdm_sngss7_data.function_trace_level) { \
+                                                                               case 0: \
+                                                                                       ftdm_log(FTDM_LOG_EMERG,"Exitting %s\n", a); \
+                                                                                       break; \
+                                                                               case 1: \
+                                                                                       ftdm_log(FTDM_LOG_ALERT,"Exitting %s\n", a); \
+                                                                                       break; \
+                                                                               case 2: \
+                                                                                       ftdm_log(FTDM_LOG_CRIT,"Exitting %s\n", a); \
+                                                                                       break; \
+                                                                               case 3: \
+                                                                                       ftdm_log(FTDM_LOG_ERROR,"Exitting %s\n", a); \
+                                                                                       break; \
+                                                                               case 4: \
+                                                                                       ftdm_log(FTDM_LOG_WARNING,"Exitting %s\n", a); \
+                                                                                       break; \
+                                                                               case 5: \
+                                                                                       ftdm_log(FTDM_LOG_NOTICE,"Exitting %s\n", a); \
+                                                                                       break; \
+                                                                               case 6: \
+                                                                                       ftdm_log(FTDM_LOG_INFO,"Exitting %s\n", a); \
+                                                                                       break; \
+                                                                               case 7: \
+                                                                                       ftdm_log(FTDM_LOG_DEBUG,"Exitting %s\n", a); \
+                                                                                       break; \
+                                                                               default: \
+                                                                                       ftdm_log(FTDM_LOG_INFO,"Exitting %s\n", a); \
+                                                                                       break; \
+                                                                               } /* switch (g_ftdm_sngss7_data.function_trace_level) */ \
+                                                               } /*  if(g_ftdm_sngss7_data.function_trace) */
+
+#define SS7_MSG_TRACE(fchan, sngss7info ,msg) if (g_ftdm_sngss7_data.message_trace) { \
+                                                               switch (g_ftdm_sngss7_data.message_trace_level) { \
+                                                                       case 0: \
+                                                                               ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+                                                                               break; \
+                                                                       case 1: \
+                                                                               ftdm_log_chan(fchan, FTDM_LOG_ALERT, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+                                                                               break; \
+                                                                       case 2: \
+                                                                               ftdm_log_chan(fchan, FTDM_LOG_CRIT, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+                                                                               break; \
+                                                                       case 3: \
+                                                                               ftdm_log_chan(fchan, FTDM_LOG_ERROR, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+                                                                               break; \
+                                                                       case 4: \
+                                                                               ftdm_log_chan(fchan, FTDM_LOG_WARNING, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+                                                                               break; \
+                                                                       case 5: \
+                                                                               ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+                                                                               break; \
+                                                                       case 6: \
+                                                                               ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+                                                                               break; \
+                                                                       case 7: \
+                                                                               ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+                                                                               break; \
+                                                                       default: \
+                                                                               ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+                                                                               break; \
+                                                                       } /* switch (g_ftdm_sngss7_data.message_trace_level) */ \
+                                                       } /* if(g_ftdm_sngss7_data.message_trace) */
 
 #define sngss7_test_flag(obj, flag)  ((obj)->flags & flag)
 #define sngss7_clear_flag(obj, flag) ((obj)->flags &= ~(flag))
 #define sngss7_set_flag(obj, flag)   ((obj)->flags |= (flag))
 
+# define SS7_ASSERT    *(int*)0=0;
 /******************************************************************************/
 
 /******************************************************************************/
 #endif /* __FTMOD_SNG_SS7_H__ */
 /******************************************************************************/
+
+/******************************************************************************/
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
+/******************************************************************************/
index edaf36d64491fc32ac68c91e534a10c1fc006879..53d0f9d93717afc8ec7d2e90d2ad830cc5bc7d41 100644 (file)
 /******************************************************************************/
 
 /* PROTOTYPES *****************************************************************/
-void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan);
-void ft_to_sngss7_acm(ftdm_channel_t *ftdmchan);
-void ft_to_sngss7_anm(ftdm_channel_t *ftdmchan);
-void ft_to_sngss7_rel(ftdm_channel_t *ftdmchan);
-void ft_to_sngss7_rlc(ftdm_channel_t *ftdmchan);
+void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan);
+void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan);
+void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan);
+void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan);
+void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan);
 
-void ft_to_sngss7_rsc(ftdm_channel_t *ftdmchan);
-void ft_to_sngss7_rsca(ftdm_channel_t *ftdmchan);
+void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan);
+void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan);
 
-void ft_to_sngss7_blo(ftdm_channel_t *ftdmchan);
-void ft_to_sngss7_bla(ftdm_channel_t *ftdmchan);
-void ft_to_sngss7_ubl(ftdm_channel_t *ftdmchan);
-void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan);
+void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan);
+void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan);
+void ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan);
+void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan);
 
-void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan);
+void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan);
 
-void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan);
+void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan);
+void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan);
 /* FUNCTIONS ******************************************************************/
-void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan)
+void
+ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;;
-    SiConEvnt           iam;
-
-    sngss7_info->suInstId = get_unique_id();
-    sngss7_info->spInstId = 0;
-    sngss7_info->spId = 1;
-
-    memset(&iam, 0x0, sizeof(iam));
-
-    /* copy down the nature of connection indicators */
-    iam.natConInd.eh.pres              = PRSNT_NODEF;
-    iam.natConInd.satInd.pres          = PRSNT_NODEF;
-    iam.natConInd.satInd.val           = 0;
-    iam.natConInd.contChkInd.pres      = PRSNT_NODEF;
-    iam.natConInd.contChkInd.val       = 0x00;
-    iam.natConInd.echoCntrlDevInd.pres = PRSNT_NODEF;
-    iam.natConInd.echoCntrlDevInd.val  = 0x01;
-
-    /* copy down the forward call indicators */
-    iam.fwdCallInd.eh.pres                 = PRSNT_NODEF;
-    iam.fwdCallInd.natIntCallInd.pres      = PRSNT_NODEF;
-    iam.fwdCallInd.natIntCallInd.val       = 0x00;
-    iam.fwdCallInd.end2EndMethInd.pres     = PRSNT_NODEF;
-    iam.fwdCallInd.end2EndMethInd.val      = 0x00;
-    iam.fwdCallInd.intInd.pres             = PRSNT_NODEF;
-    iam.fwdCallInd.intInd.val              = 0x01;
-    iam.fwdCallInd.end2EndInfoInd.pres     = PRSNT_NODEF;
-    iam.fwdCallInd.end2EndInfoInd.val      = 0x00;
-    iam.fwdCallInd.isdnUsrPrtInd.pres      = PRSNT_NODEF;
-    iam.fwdCallInd.isdnUsrPrtInd.val       = 0x01;
-    iam.fwdCallInd.isdnUsrPrtPrfInd.pres   = PRSNT_NODEF;
-    iam.fwdCallInd.isdnUsrPrtPrfInd.val    = 0x02;
-    iam.fwdCallInd.isdnAccInd.pres         = PRSNT_NODEF;
-    iam.fwdCallInd.isdnAccInd.val          = 0x01;
-    iam.fwdCallInd.sccpMethInd.pres        = PRSNT_NODEF;
-    iam.fwdCallInd.sccpMethInd.val         = 0x00;
-
-    /* copy down the calling number information */
-    iam.cgPtyCat.eh.pres       = PRSNT_NODEF;
-    iam.cgPtyCat.cgPtyCat.pres = PRSNT_NODEF;
-    iam.cgPtyCat.cgPtyCat.val  = 0x0a;
-
-    /* copy down the transmission medium requirements */
-    iam.txMedReq.eh.pres       = PRSNT_NODEF;
-    iam.txMedReq.trMedReq.pres = PRSNT_NODEF;
-    iam.txMedReq.trMedReq.val  = 0;    /* SPEECH = 0, 3.1Khz = 3, 64k unres = 2 */
-
-    /* copy down the called number information */
-    copy_cdPtyNum_to_sngss7(&ftdmchan->caller_data, &iam.cdPtyNum);
-
-    /* copy down the calling number information */
-    copy_cgPtyNum_to_sngss7(&ftdmchan->caller_data, &iam.cgPtyNum);
-
-    sng_cc_con_request(sngss7_info->spId, 
-                        sngss7_info->suInstId, 
-                        sngss7_info->spInstId, 
-                        sngss7_info->circuit->id, 
-                        &iam, 
-                        0);
-
-    SS7_MSG_TRACE("Transmitted IAM on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+  SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+
+  sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;;
+  SiConEvnt iam;
+
+  sngss7_info->suInstId = get_unique_id ();
+  sngss7_info->spInstId = 0;
+  sngss7_info->spId = 1;
+
+  memset (&iam, 0x0, sizeof (iam));
+
+  /* copy down the nature of connection indicators */
+  iam.natConInd.eh.pres = PRSNT_NODEF;
+  iam.natConInd.satInd.pres = PRSNT_NODEF;
+  iam.natConInd.satInd.val = 0;
+  iam.natConInd.contChkInd.pres = PRSNT_NODEF;
+  iam.natConInd.contChkInd.val = 0x00;
+  iam.natConInd.echoCntrlDevInd.pres = PRSNT_NODEF;
+  iam.natConInd.echoCntrlDevInd.val = 0x01;
+
+  /* copy down the forward call indicators */
+  iam.fwdCallInd.eh.pres = PRSNT_NODEF;
+  iam.fwdCallInd.natIntCallInd.pres = PRSNT_NODEF;
+  iam.fwdCallInd.natIntCallInd.val = 0x00;
+  iam.fwdCallInd.end2EndMethInd.pres = PRSNT_NODEF;
+  iam.fwdCallInd.end2EndMethInd.val = 0x00;
+  iam.fwdCallInd.intInd.pres = PRSNT_NODEF;
+  iam.fwdCallInd.intInd.val = 0x01;
+  iam.fwdCallInd.end2EndInfoInd.pres = PRSNT_NODEF;
+  iam.fwdCallInd.end2EndInfoInd.val = 0x00;
+  iam.fwdCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF;
+  iam.fwdCallInd.isdnUsrPrtInd.val = 0x01;
+  iam.fwdCallInd.isdnUsrPrtPrfInd.pres = PRSNT_NODEF;
+  iam.fwdCallInd.isdnUsrPrtPrfInd.val = 0x02;
+  iam.fwdCallInd.isdnAccInd.pres = PRSNT_NODEF;
+  iam.fwdCallInd.isdnAccInd.val = 0x01;
+  iam.fwdCallInd.sccpMethInd.pres = PRSNT_NODEF;
+  iam.fwdCallInd.sccpMethInd.val = 0x00;
+
+  /* copy down the calling number information */
+  iam.cgPtyCat.eh.pres = PRSNT_NODEF;
+  iam.cgPtyCat.cgPtyCat.pres = PRSNT_NODEF;
+  iam.cgPtyCat.cgPtyCat.val = 0x0a;
+
+  /* copy down the transmission medium requirements */
+  iam.txMedReq.eh.pres = PRSNT_NODEF;
+  iam.txMedReq.trMedReq.pres = PRSNT_NODEF;
+  iam.txMedReq.trMedReq.val = 0;       /* SPEECH = 0, 3.1Khz = 3, 64k unres = 2 */
+
+  /* copy down the called number information */
+  copy_cdPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cdPtyNum);
+
+  /* copy down the calling number information */
+  copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum);
+
+  sng_cc_con_request (sngss7_info->spId,
+                         sngss7_info->suInstId,
+                         sngss7_info->spInstId,
+                         sngss7_info->circuit->id, &iam, 0);
+
+  SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx IAM\n");
+
+  SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+  return;
 }
+
 /******************************************************************************/
 
-void ft_to_sngss7_acm(ftdm_channel_t *ftdmchan)
+void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-    SiCnStEvnt          acm;
-
-    memset(&acm, 0x0, sizeof(acm));
-
-    /* fill in the needed information for the ACM */
-    acm.bckCallInd.eh.pres              = PRSNT_NODEF;
-    acm.bckCallInd.chrgInd.pres         = PRSNT_NODEF;
-    acm.bckCallInd.chrgInd.val          = 0x00;
-    acm.bckCallInd.cadPtyStatInd.pres   = PRSNT_NODEF;
-    acm.bckCallInd.cadPtyStatInd.val    = 0x01;
-    acm.bckCallInd.cadPtyCatInd.pres    = PRSNT_NODEF;
-    acm.bckCallInd.cadPtyCatInd.val     = 0x00;
-    acm.bckCallInd.end2EndMethInd.pres  = PRSNT_NODEF;
-    acm.bckCallInd.end2EndMethInd.val   = 0x00;
-    acm.bckCallInd.intInd.pres          = PRSNT_NODEF;
-    acm.bckCallInd.intInd.val           = 0x00;
-    acm.bckCallInd.end2EndInfoInd.pres  = PRSNT_NODEF;
-    acm.bckCallInd.end2EndInfoInd.val   = 0x00;
-    acm.bckCallInd.isdnUsrPrtInd.pres   = PRSNT_NODEF;
-    acm.bckCallInd.isdnUsrPrtInd.val    = 0x0;
-    acm.bckCallInd.holdInd.pres         = PRSNT_NODEF;
-    acm.bckCallInd.holdInd.val          = 0x00;
-    acm.bckCallInd.isdnAccInd.pres      = PRSNT_NODEF;
-    acm.bckCallInd.isdnAccInd.val       = 0x0;
-    acm.bckCallInd.echoCtrlDevInd.pres  = PRSNT_NODEF;
-    acm.bckCallInd.echoCtrlDevInd.val   = 0x0;
-    acm.bckCallInd.sccpMethInd.pres     = PRSNT_NODEF;
-    acm.bckCallInd.sccpMethInd.val      = 0x00;
-
-    /* send the ACM request to LibSngSS7 */
-    sng_cc_con_status(1, 
-                      sngss7_info->suInstId, 
-                      sngss7_info->spInstId, 
-                      sngss7_info->circuit->id,
-                      &acm, 
-                      ADDRCMPLT);
-
-    SS7_MSG_TRACE("Transmitted ACM on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       SiCnStEvnt acm;
+       
+       memset (&acm, 0x0, sizeof (acm));
+       
+       /* fill in the needed information for the ACM */
+       acm.bckCallInd.eh.pres = PRSNT_NODEF;
+       acm.bckCallInd.chrgInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.chrgInd.val = 0x00;
+       acm.bckCallInd.cadPtyStatInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.cadPtyStatInd.val = 0x01;
+       acm.bckCallInd.cadPtyCatInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.cadPtyCatInd.val = 0x00;
+       acm.bckCallInd.end2EndMethInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.end2EndMethInd.val = 0x00;
+       acm.bckCallInd.intInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.intInd.val = 0x00;
+       acm.bckCallInd.end2EndInfoInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.end2EndInfoInd.val = 0x00;
+       acm.bckCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.isdnUsrPrtInd.val = 0x0;
+       acm.bckCallInd.holdInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.holdInd.val = 0x00;
+       acm.bckCallInd.isdnAccInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.isdnAccInd.val = 0x0;
+       acm.bckCallInd.echoCtrlDevInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.echoCtrlDevInd.val = 0x0;
+       acm.bckCallInd.sccpMethInd.pres = PRSNT_NODEF;
+       acm.bckCallInd.sccpMethInd.val = 0x00;
+       
+       /* send the ACM request to LibSngSS7 */
+       sng_cc_con_status  (1,
+                                               sngss7_info->suInstId,
+                                               sngss7_info->spInstId,
+                                               sngss7_info->circuit->id, 
+                                               &acm, 
+                                               ADDRCMPLT);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx ACM\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+       return;
 }
-/******************************************************************************/
 
-void ft_to_sngss7_anm(ftdm_channel_t *ftdmchan)
+/******************************************************************************/
+void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-    SiConEvnt           anm;
-
-    memset(&anm, 0x0, sizeof(anm));
-
-    /* send the ANM request to LibSngSS7 */
-    sng_cc_con_response(1, 
-                        sngss7_info->suInstId, 
-                        sngss7_info->spInstId, 
-                        sngss7_info->circuit->id, 
-                        &anm, 
-                        5);
-
-    SS7_MSG_TRACE("Transmitted ANM on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       SiConEvnt anm;
+       
+       memset (&anm, 0x0, sizeof (anm));
+       
+       /* send the ANM request to LibSngSS7 */
+       sng_cc_con_response(1,
+                                               sngss7_info->suInstId,
+                                               sngss7_info->spInstId,
+                                               sngss7_info->circuit->id, 
+                                               &anm, 
+                                               5);
+
+  SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx ANM\n");
+
+  SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+  return;
 }
 
 /******************************************************************************/
-void ft_to_sngss7_rel(ftdm_channel_t *ftdmchan)
+void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-    SiRelEvnt           rel;
-
-    memset(&rel, 0x0, sizeof(rel));
-
-    rel.causeDgn.eh.pres           = PRSNT_NODEF;
-    rel.causeDgn.location.pres     = PRSNT_NODEF;
-    rel.causeDgn.location.val      = 0x01;
-    rel.causeDgn.cdeStand.pres     = PRSNT_NODEF;
-    rel.causeDgn.cdeStand.val      = 0x00;
-    rel.causeDgn.recommend.pres    = NOTPRSNT;
-    rel.causeDgn.causeVal.pres     = PRSNT_NODEF;
-    rel.causeDgn.causeVal.val      = (uint8_t)ftdmchan->caller_data.hangup_cause;
-    rel.causeDgn.dgnVal.pres       = NOTPRSNT;
-
-    /* send the REL request to LibSngSS7 */
-    sng_cc_rel_request(1, 
-                       sngss7_info->suInstId, 
-                       sngss7_info->spInstId, 
-                       sngss7_info->circuit->id, 
-                       &rel);
-
-    SS7_MSG_TRACE("Transmitted REL on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       SiRelEvnt rel;
+       
+       memset (&rel, 0x0, sizeof (rel));
+       
+       rel.causeDgn.eh.pres = PRSNT_NODEF;
+       rel.causeDgn.location.pres = PRSNT_NODEF;
+       rel.causeDgn.location.val = 0x01;
+       rel.causeDgn.cdeStand.pres = PRSNT_NODEF;
+       rel.causeDgn.cdeStand.val = 0x00;
+       rel.causeDgn.recommend.pres = NOTPRSNT;
+       rel.causeDgn.causeVal.pres = PRSNT_NODEF;
+       rel.causeDgn.causeVal.val = (uint8_t) ftdmchan->caller_data.hangup_cause;
+       rel.causeDgn.dgnVal.pres = NOTPRSNT;
+       
+       /* send the REL request to LibSngSS7 */
+       sng_cc_rel_request (1,
+                                               sngss7_info->suInstId,
+                                               sngss7_info->spInstId, 
+                                               sngss7_info->circuit->id, 
+                                               &rel);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx REL\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+       return;
 }
 
 /******************************************************************************/
-void ft_to_sngss7_rlc(ftdm_channel_t *ftdmchan)
+void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-    SiRelEvnt           rlc;
-
-    memset(&rlc, 0x0, sizeof(rlc));
-
-    /* send the RLC request to LibSngSS7 */
-    sng_cc_rel_response(1, 
-                        sngss7_info->suInstId, 
-                        sngss7_info->spInstId, 
-                        sngss7_info->circuit->id, 
-                        &rlc);
-
-    SS7_MSG_TRACE("Transmitted RLC on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       SiRelEvnt rlc;
+       
+       memset (&rlc, 0x0, sizeof (rlc));
+       
+       /* send the RLC request to LibSngSS7 */
+       sng_cc_rel_response (1,
+                                               sngss7_info->suInstId,
+                                               sngss7_info->spInstId, 
+                                               sngss7_info->circuit->id, 
+                                               &rlc);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RLC\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+       return;
 }
 
 /******************************************************************************/
-void ft_to_sngss7_rsc(ftdm_channel_t *ftdmchan)
+void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-
-    sng_cc_sta_request(1, 
-                        sngss7_info->suInstId, 
-                        sngss7_info->spInstId, 
-                        sngss7_info->circuit->id, 
-                        sngss7_info->globalFlg, 
-                        SIT_STA_CIRRESREQ, 
-                        NULL);
-
-    SS7_MSG_TRACE("Transmitted RSC on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       
+       sng_cc_sta_request (1,
+                                               sngss7_info->suInstId,
+                                               sngss7_info->spInstId,
+                                               sngss7_info->circuit->id,
+                                               sngss7_info->globalFlg, 
+                                               SIT_STA_CIRRESREQ, 
+                                               NULL);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RSC\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+       return;
 }
 
 /******************************************************************************/
-void ft_to_sngss7_rsca(ftdm_channel_t *ftdmchan)
+void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-
-    sng_cc_sta_request(1, 
-                        sngss7_info->suInstId, 
-                        sngss7_info->spInstId, 
-                        sngss7_info->circuit->id, 
-                        sngss7_info->globalFlg, 
-                        SIT_STA_CIRRESRSP, 
-                        NULL);
-
-    SS7_MSG_TRACE("Transmitted RSC-RLC on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       
+       sng_cc_sta_request (1,
+                                               sngss7_info->suInstId,
+                                               sngss7_info->spInstId,
+                                               sngss7_info->circuit->id,
+                                               sngss7_info->globalFlg, 
+                                               SIT_STA_CIRRESRSP, 
+                                               NULL);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RSC-RLC\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+  return;
 }
 
 /******************************************************************************/
-void ft_to_sngss7_blo(ftdm_channel_t *ftdmchan)
+void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-
-    sng_cc_sta_request(1, 
-                       0, 
-                       0, 
-                       sngss7_info->circuit->id, 
-                       sngss7_info->globalFlg, 
-                       SIT_STA_CIRBLOREQ, 
-                       NULL);
-
-    SS7_MSG_TRACE("Transmitted BLO on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       
+       sng_cc_sta_request (1,
+                                               0,
+                                               0,
+                                               sngss7_info->circuit->id,
+                                               sngss7_info->globalFlg, 
+                                               SIT_STA_CIRBLOREQ, 
+                                               NULL);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx BLO\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+       return;
 }
 
 /******************************************************************************/
-void ft_to_sngss7_bla(ftdm_channel_t *ftdmchan)
+void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-
-    sng_cc_sta_request(1, 
-                       0, 
-                       0, 
-                       sngss7_info->circuit->id, 
-                       sngss7_info->globalFlg, 
-                       SIT_STA_CIRBLORSP, 
-                       NULL);
-
-    SS7_MSG_TRACE("Transmitted BLA on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       
+       sng_cc_sta_request (1,
+                                               0,
+                                               0,
+                                               sngss7_info->circuit->id,
+                                               sngss7_info->globalFlg, 
+                                               SIT_STA_CIRBLORSP, 
+                                               NULL);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx BLA\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+       return;
 }
 
 /******************************************************************************/
-void ft_to_sngss7_ubl(ftdm_channel_t *ftdmchan)
+void
+ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-
-    sng_cc_sta_request(1, 
-                       0, 
-                       0, 
-                       sngss7_info->circuit->id, 
-                       sngss7_info->globalFlg, 
-                       SIT_STA_CIRUBLREQ, 
-                       NULL);
-
-    SS7_MSG_TRACE("Transmitted UBL on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       
+       sng_cc_sta_request (1,
+                                               0,
+                                               0,
+                                               sngss7_info->circuit->id,
+                                               sngss7_info->globalFlg, 
+                                               SIT_STA_CIRUBLREQ, 
+                                               NULL);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx UBL\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+       return;
 }
 
 /******************************************************************************/
-void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan)
+void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-
-    sng_cc_sta_request(1, 
-                       0, 
-                       0, 
-                       sngss7_info->circuit->id, 
-                       sngss7_info->globalFlg, 
-                       SIT_STA_CIRUBLRSP, 
-                       NULL);
-
-    SS7_MSG_TRACE("Transmitted UBA on CIC # %d\n", sngss7_info->circuit->cic);
-
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       
+       sng_cc_sta_request (1,
+                                               0,
+                                               0,
+                                               sngss7_info->circuit->id,
+                                               sngss7_info->globalFlg, 
+                                               SIT_STA_CIRUBLRSP, 
+                                               NULL);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx UBA\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+       return;
 }
 
 /******************************************************************************/
-void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan)
+void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
-
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
-
-    sng_cc_sta_request(1, 
-                       sngss7_info->suInstId, 
-                       sngss7_info->spInstId, 
-                       sngss7_info->circuit->id, 
-                       sngss7_info->globalFlg, 
-                       SIT_STA_LOOPBACKACK, 
-                       NULL);
-
-    SS7_MSG_TRACE("Transmitted LPA on CIC # %d\n", sngss7_info->circuit->cic);
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       
+       sng_cc_sta_request (1,
+                                               sngss7_info->suInstId,
+                                               sngss7_info->spInstId,
+                                               sngss7_info->circuit->id,
+                                               sngss7_info->globalFlg, 
+                                               SIT_STA_LOOPBACKACK, 
+                                               NULL);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx LPA\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+return;
+}
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+/******************************************************************************/
+void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
+{
+       SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+       
+       sngss7_span_data_t *span = ftdmchan->span->mod_data;
+       sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+       SiStaEvnt       gra;
+       
+       /* clean out the gra struct */
+       memset (&gra, 0x0, sizeof (gra));
+
+       gra.rangStat.eh.pres = PRSNT_NODEF;
+
+       /* fill in the range */ 
+       gra.rangStat.range.pres = PRSNT_NODEF;
+       gra.rangStat.range.val = span->grs.range;
+
+       /* fill in the status */
+       gra.rangStat.status.pres = PRSNT_NODEF;
+       gra.rangStat.status.len = ((span->grs.range + 1) >> 3) + (((span->grs.range + 1) & 0x07) ? 1 : 0); 
+       
+       /* the status field should be 1 if blocked for maintenace reasons 
+       * and 0 is not blocked....since we memset the struct nothing to do
+       */
+       
+       /* send the GRA to LibSng-SS7 */
+       sng_cc_sta_request (1,
+                                               0,
+                                               0,
+                                               span->grs.circuit,
+                                               0,
+                                               SIT_STA_GRSRSP,
+                                               &gra);
+       
+       SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx GRA\n");
+       
+       SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+       return;
 }
 
 /******************************************************************************/
-void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan)
+void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+
+sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+ftdm_span_t *span = ftdmchan->span;
+
+SiStaEvnt grs;
 
-    sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
+memset (&grs, 0x0, sizeof (grs));
 
-       /* get the original channel the message came in on */
-       sngss7_info = g_ftdm_sngss7_data.cfg.isupCircuit[sngss7_info->grs.circuit].obj;
+grs.rangStat.eh.pres = PRSNT_NODEF;
+grs.rangStat.range.pres = PRSNT_NODEF;
+grs.rangStat.range.val = span->chan_count-1;
 
-    sng_cc_sta_request(1, 
-                       0, 
-                       0, 
-                       sngss7_info->circuit->id, 
-                       sngss7_info->globalFlg, 
-                       SIT_STA_GRSRSP, 
-                       NULL);
+sng_cc_sta_request (1,
+                                       0,
+                                       0,
+                                       sngss7_info->circuit->id,
+                                       0,
+                                       SIT_STA_GRSREQ,
+                                       &grs);
 
-    SS7_MSG_TRACE("Transmitted GRA on CIC # %d\n", sngss7_info->circuit->cic);
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return;
+SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx GRS\n");
+
+SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+return;
 }
+
 /******************************************************************************/
 /* For Emacs:
  * Local Variables:
@@ -441,4 +492,3 @@ void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan)
  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
  */
 /******************************************************************************/
-
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c
new file mode 100644 (file)
index 0000000..305e1a5
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2009 Konrad Hammel <konrad@sangoma.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms|with or without
+ * modification|are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice|this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice|this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
+ * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
+ * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* INCLUDE ********************************************************************/
+#include "ftmod_sangoma_ss7_main.h"
+/******************************************************************************/
+
+/* DEFINES ********************************************************************/
+/******************************************************************************/
+
+/* GLOBALS ********************************************************************/
+/******************************************************************************/
+
+/* PROTOTYPES *****************************************************************/
+int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm);
+int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm);
+/******************************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm)
+{
+       SnMngmt sta;
+
+       memset(&sta, 0x0, sizeof(sta));
+
+       sta.hdr.elmId.elmnt             = STDLSAP;
+       sta.hdr.elmId.elmntInst1        = g_ftdm_sngss7_data.cfg.mtpLink[id].id;
+
+       return(sng_sta_mtp3(&sta, cfm));
+}
+
+/******************************************************************************/
+int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm)
+{
+       SnMngmt sta;
+
+       memset(&sta, 0x0, sizeof(sta));
+
+       sta.hdr.elmId.elmnt             = STLNKSET;
+       sta.hdr.elmId.elmntInst1        = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id;
+       sta.hdr.elmId.elmntInst2        = 1;
+
+       return(sng_sta_mtp3(&sta, cfm));
+}
+/******************************************************************************/
+
+/******************************************************************************/
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
+/******************************************************************************/
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c
new file mode 100644 (file)
index 0000000..f760ac4
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2009 Konrad Hammel <konrad@sangoma.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms|with or without
+ * modification|are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice|this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice|this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
+ * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
+ * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* INCLUDE ********************************************************************/
+#include "ftmod_sangoma_ss7_main.h"
+/******************************************************************************/
+
+/* DEFINES ********************************************************************/
+/******************************************************************************/
+
+/* GLOBALS ********************************************************************/
+/******************************************************************************/
+
+/* PROTOTYPES *****************************************************************/
+/******************************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+/******************************************************************************/
+
+/******************************************************************************/
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
+/******************************************************************************/
index 7852829295ca85886cd61b13466957cd49ccd6a7..97957f3c821740c34e61c4bf79366ac47323d711 100644 (file)
@@ -50,6 +50,9 @@ uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum
 uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum);
 
 int check_for_state_change(ftdm_channel_t *ftdmchan);
+int check_cics_in_range(sngss7_chan_data_t *sngss7_info);
+int check_for_reset(sngss7_chan_data_t *sngss7_info);
+
 unsigned long get_unique_id(void);
 
 ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
@@ -60,309 +63,391 @@ ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_in
 uint8_t copy_cgPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
 {
 
-    return 0;
+       return 0;
 }
 
 /******************************************************************************/
 uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
 {
-    int k;
-    int j;
-    int flag;
-    char tmp;
-    unsigned char lower;
-    unsigned char upper;
-
-    /**************************************************************************/
-    cgPtyNum->eh.pres           = PRSNT_NODEF;
-    /**************************************************************************/
-    cgPtyNum->natAddrInd.pres   = PRSNT_NODEF;
-    cgPtyNum->natAddrInd.val    = 0x03;
-    /**************************************************************************/
-    cgPtyNum->scrnInd.pres      = PRSNT_NODEF;
-    cgPtyNum->scrnInd.val       = ftdm->screen;
-    /**************************************************************************/
-    cgPtyNum->presRest.pres     = PRSNT_NODEF;
-    cgPtyNum->presRest.val      = ftdm->pres;
-    /**************************************************************************/
-    cgPtyNum->numPlan.pres      = PRSNT_NODEF;
-    cgPtyNum->numPlan.val       = 0x01;
-    /**************************************************************************/
-    cgPtyNum->niInd.pres        = PRSNT_NODEF;
-    cgPtyNum->niInd.val         = 0x00;
-    /**************************************************************************/
-    cgPtyNum->addrSig.pres      = PRSNT_NODEF;
-
-    k = 0;
-    j = 0;
-    flag = 0;
-    while (1) {
-        tmp = ftdm->cid_num.digits[k];
-        if (tmp != '\0') {
-            if (isdigit(tmp)) {
-                lower = atoi(&tmp);
-                k++;
-                tmp = ftdm->cid_num.digits[k];
-            } else {
-                while (!(isdigit(tmp)) && (tmp != '\0')) {
-                    k++;
-                    tmp = ftdm->cid_num.digits[k];
-                } /* while(!(isdigit(tmp))) */
-
-                if (tmp != '\0') {
-                    lower = atoi(&tmp);
-                    k++;
-                    tmp = ftdm->cid_num.digits[k];
-                } else {
-                    flag = 1;
-                    lower = 0xf;
-                } /* if (tmp != '\0') */
-            } /* (isdigit(tmp)) */
-        } else {
-            flag = 1;
-            lower = 0xf;
-        } /* if (tmp != '\0') */
-
-        tmp = ftdm->cid_num.digits[k];
-        if (tmp != '\0') {
-            if (isdigit(tmp)) {
-                upper = (atoi(&tmp)) << 4;
-            } else {
-                 while (!(isdigit(tmp)) && (tmp != '\0')) {
-                    k++;
-                    tmp = ftdm->cid_num.digits[k];
-                } /* while(!(isdigit(tmp))) */
-
-                if (tmp != '\0') {
-                    upper = (atoi(&tmp)) << 4;
-                    k++;
-                } else {
-                    flag = 1;
-                    upper = 0xf;
-                } /*  if (tmp != '\0') */
-            } /* if (isdigit(tmp)) */
-        } else {
-            if (flag == 1){
-                upper = 0x0;
-            } else {
-                flag = 1;
-                upper = 0xf;
-            } /* if (flag == 1) */
-        } /* if (tmp != '\0') */
-
-        cgPtyNum->addrSig.val[j] = upper | lower;
-        j++;
-
-        if (flag) {
-            break;
-        } else {
-            k++;
-        }
-    } /* while(1) */
-
-    cgPtyNum->addrSig.len = j;
-    /**************************************************************************/
-    cgPtyNum->oddEven.pres      = PRSNT_NODEF;
-    cgPtyNum->oddEven.val       = ((cgPtyNum->addrSig.val[j] >>4) == 0x0 ) ? 0x01 : 0x00;
-    /**************************************************************************/
-    return 0;
+       int k;
+       int j;
+       int flag;
+       char tmp[2];
+       unsigned char lower;
+       unsigned char upper;
+
+       /**************************************************************************/
+       cgPtyNum->eh.pres                  = PRSNT_NODEF;
+       /**************************************************************************/
+       cgPtyNum->natAddrInd.pres   = PRSNT_NODEF;
+       cgPtyNum->natAddrInd.val        = 0x03;
+       /**************************************************************************/
+       cgPtyNum->scrnInd.pres    = PRSNT_NODEF;
+       cgPtyNum->scrnInd.val      = ftdm->screen;
+       /**************************************************************************/
+       cgPtyNum->presRest.pres  = PRSNT_NODEF;
+       cgPtyNum->presRest.val    = ftdm->pres;
+       /**************************************************************************/
+       cgPtyNum->numPlan.pres    = PRSNT_NODEF;
+       cgPtyNum->numPlan.val      = 0x01;
+       /**************************************************************************/
+       cgPtyNum->niInd.pres            = PRSNT_NODEF;
+       cgPtyNum->niInd.val              = 0x00;
+       /**************************************************************************/
+       cgPtyNum->addrSig.pres    = PRSNT_NODEF;
+
+       /* atoi will search through memory starting from the pointer it is given until
+        * it finds the \0...since tmp is on the stack it will start going through the
+        * possibly causing corruption.  Hard code a \0 to prevent this
+        */
+       tmp[1] = '\0';
+       k = 0;
+       j = 0;
+       flag = 0;
+
+       while (1) {
+               tmp[0] = ftdm->cid_num.digits[k];
+
+               if (tmp[0] != '\0') {
+                       if (isdigit(tmp[0])) {
+                               lower = atoi(&tmp[0]);
+                               k++;
+                               tmp[0] = ftdm->cid_num.digits[k];
+                       } else {
+                               while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
+                                       k++;
+                                       tmp[0] = ftdm->cid_num.digits[k];
+                               } /* while(!(isdigit(tmp))) */
+
+                               if (tmp[0] != '\0') {
+                                       lower = atoi(&tmp[0]);
+                                       k++;
+                                       tmp[0] = ftdm->cid_num.digits[k];
+                               } else {
+                                       flag = 1;
+                                       lower = 0xf;
+                               } /* if (tmp != '\0') */
+                       } /* (isdigit(tmp)) */
+               } else {
+                       flag = 1;
+                       lower = 0xf;
+               } /* if (tmp != '\0') */
+
+               tmp[0] = ftdm->cid_num.digits[k];
+
+               if (tmp[0] != '\0') {
+                       if (isdigit(tmp[0])) {
+                               upper = (atoi(&tmp[0])) << 4;
+                       } else {
+                               while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
+                                       k++;
+                                       tmp[0] = ftdm->cid_num.digits[k];
+                               } /* while(!(isdigit(tmp))) */
+
+                               if (tmp[0] != '\0') {
+                                       upper = (atoi(&tmp[0])) << 4;
+                                       k++;
+                               } else {
+                                       flag = 1;
+                                       upper = 0xf;
+                               } /*  if (tmp != '\0') */
+                       } /* if (isdigit(tmp)) */
+               } else {
+                       if (flag == 1) {
+                               upper = 0x0;
+                       } else {
+                               flag = 1;
+                               upper = 0xf;
+                       } /* if (flag == 1) */
+               } /* if (tmp != '\0') */
+
+               cgPtyNum->addrSig.val[j] = upper | lower;
+
+               j++;
+
+               if (flag) {
+                       break;
+               } else {
+                       k++;
+               }
+       } /* while(1) */
+
+       cgPtyNum->addrSig.len = j;
+
+       /**************************************************************************/
+       cgPtyNum->oddEven.pres    = PRSNT_NODEF;
+
+       cgPtyNum->oddEven.val      = ((cgPtyNum->addrSig.val[j] >> 4) == 0x0 ) ? 0x01 : 0x00;
+
+       /**************************************************************************/
+       return 0;
 }
 
 /******************************************************************************/
 uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
 {
 
-    return 0;
+       return 0;
 }
 
 /******************************************************************************/
 uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
 {
-    int k;
-    int j;
-    int flag;
-    char tmp;
-    unsigned char lower;
-    unsigned char upper;
-
-    /**************************************************************************/
-    cdPtyNum->eh.pres           = PRSNT_NODEF;
-    /**************************************************************************/
-    cdPtyNum->natAddrInd.pres   = PRSNT_NODEF;
-    cdPtyNum->natAddrInd.val    = 0x03;
-    /**************************************************************************/
-    cdPtyNum->numPlan.pres      = PRSNT_NODEF;
-    cdPtyNum->numPlan.val       = 0x01;
-    /**************************************************************************/
-    cdPtyNum->innInd.pres       = PRSNT_NODEF;
-    cdPtyNum->innInd.val        = 0x01;
-    /**************************************************************************/
-    cdPtyNum->addrSig.pres      = PRSNT_NODEF;
-
-    k = 0;
-    j = 0;
-    flag = 0;
-    while (1) {
-        tmp = ftdm->dnis.digits[k];
-        if (tmp != '\0') {
-            if (isdigit(tmp)) {
-                lower = atoi(&tmp);
-                k++;
-                tmp = ftdm->dnis.digits[k];
-            } else {
-                while (!(isdigit(tmp)) && (tmp != '\0')) {
-                    k++;
-                    tmp = ftdm->dnis.digits[k];
-                } /* while(!(isdigit(tmp))) */
-
-                if (tmp != '\0') {
-                    lower = atoi(&tmp);
-                    k++;
-                    tmp = ftdm->dnis.digits[k];
-                } else {
-                    flag = 1;
-                    lower = 0xf;
-                } /* if (tmp != '\0') */
-            } /* (isdigit(tmp)) */
-        } else {
-            flag = 1;
-            lower = 0xf;
-        } /* if (tmp != '\0') */
-
-        tmp = ftdm->dnis.digits[k];
-        if (tmp != '\0') {
-            if (isdigit(tmp)) {
-                upper = (atoi(&tmp)) << 4;
-            } else {
-                 while (!(isdigit(tmp)) && (tmp != '\0')) {
-                    k++;
-                    tmp = ftdm->dnis.digits[k];
-                } /* while(!(isdigit(tmp))) */
-
-                if (tmp != '\0') {
-                    upper = (atoi(&tmp)) << 4;
-                    k++;
-                } else {
-                    flag = 1;
-                    upper = 0xf;
-                } /*  if (tmp != '\0') */
-            } /* if (isdigit(tmp)) */
-        } else {
-            if (flag == 1){
-                upper = 0x0;
-            } else {
-                flag = 1;
-                upper = 0xf;
-            } /* if (flag == 1) */
-        } /* if (tmp != '\0') */
-
-        cdPtyNum->addrSig.val[j] = upper | lower;
-        j++;
-
-        if (flag) {
-            break;
-        } else {
-            k++;
-        }
-    } /* while(1) */
-
-    cdPtyNum->addrSig.len = j;
-    /**************************************************************************/
-    cdPtyNum->oddEven.pres      = PRSNT_NODEF;
-    cdPtyNum->oddEven.val       = ((cdPtyNum->addrSig.val[j] >>4) == 0x0 ) ? 0x01 : 0x00;
-    /**************************************************************************/
-    return 0;
+       int k;
+       int j;
+       int flag;
+       char tmp[2];
+       unsigned char lower;
+       unsigned char upper;
+
+       /**************************************************************************/
+       cdPtyNum->eh.pres                  = PRSNT_NODEF;
+       /**************************************************************************/
+       cdPtyNum->natAddrInd.pres   = PRSNT_NODEF;
+       cdPtyNum->natAddrInd.val        = 0x03;
+       /**************************************************************************/
+       cdPtyNum->numPlan.pres    = PRSNT_NODEF;
+       cdPtyNum->numPlan.val      = 0x01;
+       /**************************************************************************/
+       cdPtyNum->innInd.pres      = PRSNT_NODEF;
+       cdPtyNum->innInd.val            = 0x01;
+       /**************************************************************************/
+       cdPtyNum->addrSig.pres    = PRSNT_NODEF;
+
+       /* atoi will search through memory starting from the pointer it is given until
+        * it finds the \0...since tmp is on the stack it will start going through the
+        * possibly causing corruption.  Hard code a \0 to prevent this
+        */
+       tmp[1] = '\0';
+       k = 0;
+       j = 0;
+       flag = 0;
+
+       while (1) {
+               tmp[0] = ftdm->dnis.digits[k];
+
+               if (tmp[0] != '\0') {
+                       if (isdigit(tmp[0])) {
+                               lower = atoi(&tmp[0]);
+                               k++;
+                               tmp[0] = ftdm->dnis.digits[k];
+                       } else {
+                               while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
+                                       k++;
+                                       tmp[0] = ftdm->dnis.digits[k];
+                               } /* while(!(isdigit(tmp))) */
+
+                               if (tmp[0] != '\0') {
+                                       lower = atoi(&tmp[0]);
+                                       k++;
+                                       tmp[0] = ftdm->dnis.digits[k];
+                               } else {
+                                       flag = 1;
+                                       lower = 0xf;
+                               } /* if (tmp != '\0') */
+                       } /* (isdigit(tmp)) */
+               } else {
+                       flag = 1;
+                       lower = 0xf;
+               } /* if (tmp != '\0') */
+
+               tmp[0] = ftdm->dnis.digits[k];
+
+               if (tmp[0] != '\0') {
+                       if (isdigit(tmp[0])) {
+                               upper = (atoi(&tmp[0])) << 4;
+                       } else {
+                               while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
+                                       k++;
+                                       tmp[0] = ftdm->dnis.digits[k];
+                               } /* while(!(isdigit(tmp))) */
+
+                               if (tmp[0] != '\0') {
+                                       upper = (atoi(&tmp[0])) << 4;
+                                       k++;
+                               } else {
+                                       flag = 1;
+                                       upper = 0xf;
+                               } /*  if (tmp != '\0') */
+                       } /* if (isdigit(tmp)) */
+               } else {
+                       if (flag == 1) {
+                               upper = 0x0;
+                       } else {
+                               flag = 1;
+                               upper = 0xf;
+                       } /* if (flag == 1) */
+               } /* if (tmp != '\0') */
+
+               cdPtyNum->addrSig.val[j] = upper | lower;
+
+               j++;
+
+               if (flag) {
+                       break;
+               } else {
+                       k++;
+               }
+       } /* while(1) */
+
+       cdPtyNum->addrSig.len = j;
+
+       /**************************************************************************/
+       cdPtyNum->oddEven.pres    = PRSNT_NODEF;
+
+       cdPtyNum->oddEven.val      = ((cdPtyNum->addrSig.val[j] >> 4) == 0x0 ) ? 0x01 : 0x00;
+
+       /**************************************************************************/
+       return 0;
 }
 
 /******************************************************************************/
 uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven)
 {
-    uint8_t i;
-    uint8_t j;
-
-    /* check if the token string is present */
-    if (str.pres == 1) {
-        j=0;
-
-        for (i=0; i < str.len; i++) {
-            sprintf(&ftdm[j], "%d", (str.val[i] & 0x0F));
-            j++;
-            sprintf(&ftdm[j], "%d", ((str.val[i] & 0xF0) >> 4));
-            j++;
-        }
-
-        /* if the odd flag is up the last digit is a fake "0" */
-        if ((oddEven.pres == 1) && (oddEven.val == 1)) {
-            ftdm[j-1] = '\0';
-        } else {
-            ftdm[j] = '\0';
-        }
-    } else {
-        SS7_ERROR("Asked to copy tknStr that is not present!\n");
-        return 1;
-    }
-
-    return 0;
+       uint8_t i;
+       uint8_t j;
+
+       /* check if the token string is present */
+
+       if (str.pres == 1) {
+               j = 0;
+
+               for (i = 0; i < str.len; i++) {
+                       sprintf(&ftdm[j], "%d", (str.val[i] & 0x0F));
+                       j++;
+                       sprintf(&ftdm[j], "%d", ((str.val[i] & 0xF0) >> 4));
+                       j++;
+               }
+
+               /* if the odd flag is up the last digit is a fake "0" */
+               if ((oddEven.pres == 1) && (oddEven.val == 1)) {
+                       ftdm[j-1] = '\0';
+               } else {
+                       ftdm[j] = '\0';
+               }
+       } else {
+               SS7_ERROR("Asked to copy tknStr that is not present!\n");
+               return 1;
+       }
+
+       return 0;
 }
 
 /******************************************************************************/
 int check_for_state_change(ftdm_channel_t *ftdmchan)
 {
 
+       /* check to see if there are any pending state changes on the channel and give them a sec to happen*/
+       ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 500);
+
+       /* check the flag to confirm it is clear now */
+
+       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+               /* the flag is still up...so we have a problem */
+               SS7_DEBUG_CHAN(ftdmchan, "FTDM_CHANNEL_STATE_CHANGE flag set for over 500ms, channel state = %s\n",
+                                                                       ftdm_channel_state2str (ftdmchan->state));
+
+               return 1;
+       }
+
+       return 0;
+}
+
+/******************************************************************************/
+int check_cics_in_range(sngss7_chan_data_t *sngss7_info)
+{
+
+
 #if 0
-    SS7_DEBUG("Checking for pending state change on span: %d, chan: %d\n!",
-                ftdmchan->physical_span_id, 
-                ftdmchan->physical_chan_id);
+       ftdm_channel_t          *tmp_ftdmchan;
+       sngss7_chan_data_t  *tmp_sngss7_info;
+       int                             i = 0;
+       
+       /* check all the circuits in the range to see if we are the last ckt to reset */
+       for ( i = sngss7_info->grs.circuit; i < ( sngss7_info->grs.range + 1 ); i++ ) {
+               if ( g_ftdm_sngss7_data.cfg.isupCircuit[i].siglink == 0 ) {
+               
+                       /* get the ftdmchan and ss7_chan_data from the circuit */
+                       if (extract_chan_data(g_ftdm_sngss7_data.cfg.isupCircuit[i].id, &tmp_sngss7_info, &tmp_ftdmchan)) {
+                               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", g_ftdm_sngss7_data.cfg.isupCircuit[i].id);
+                               return 0;
+                       }
+
+                       /* check if the channel still has the reset flag done is up */
+                       if (!sngss7_test_flag(tmp_sngss7_info, FLAG_GRP_RESET_RX_DN)) {
+                               SS7_DEBUG_CHAN(tmp_ftdmchan, "[CIC:%d] Still processing reset...\n", tmp_sngss7_info->circuit->cic);
+                               return 0;
+                       }
+               } /* if not siglink */
+       } /* for */
+
+       SS7_DEBUG("All circuits out of reset: circuit=%d, range=%d\n",
+                               sngss7_info->grs.circuit,
+                               sngss7_info->grs.range);
+       return 1;
+
 #endif
-    /* check to see if there are any pending state changes on the channel and give them a sec to happen*/
-    ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 500);
-
-    /* check the flag to confirm it is clear now */
-    if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
-        /* the flag is still up...so we have a problem */
-        SS7_ERROR("FTDM_CHANNEL_STATE_CHANGE set for over 500ms on span: %d, chan: %d\n", 
-                    ftdmchan->physical_span_id,
-                    ftdmchan->physical_chan_id);
-
-        /* move the state of the channel to RESTART to force a reset */
-        ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-
-        return 1;
-    }
-    return 0;
+
+       return 0;
+
 }
 
 /******************************************************************************/
 ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan)
 {
-    SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+       /*SS7_FUNC_TRACE_ENTER(__FUNCTION__);*/
+
+       if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj == NULL) {
+               SS7_ERROR("sngss7_info is Null for circuit #%d\n", circuit);
+               return FTDM_FAIL;
+       }
 
-    if (g_ftdm_sngss7_data.cfg.isupCircuit[circuit].obj == NULL) {
-        SS7_ERROR("sngss7_info is Null for circuit #%d\n", circuit);
-        return FTDM_FAIL;
-    }
+       ftdm_assert_return(g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj, FTDM_FAIL, "received message on signalling link or non-configured cic\n");
 
-    ftdm_assert_return(g_ftdm_sngss7_data.cfg.isupCircuit[circuit].obj,FTDM_FAIL,"received message on signalling link or non-configured cic\n");
-    *sngss7_info = g_ftdm_sngss7_data.cfg.isupCircuit[circuit].obj;
+       *sngss7_info = g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj;
 
-    ftdm_assert_return((*sngss7_info)->ftdmchan,FTDM_FAIL,"received message on signalling link or non-configured cic\n");
-    *ftdmchan = (*sngss7_info)->ftdmchan;
+       ftdm_assert_return((*sngss7_info)->ftdmchan, FTDM_FAIL, "received message on signalling link or non-configured cic\n");
+       *ftdmchan = (*sngss7_info)->ftdmchan;
+
+       /*SS7_FUNC_TRACE_EXIT(__FUNCTION__);*/
+       return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+int check_for_reset(sngss7_chan_data_t *sngss7_info)
+{
 
-    SS7_FUNC_TRACE_EXIT(__FUNCTION__);
-    return FTDM_SUCCESS;
+       if (sngss7_test_flag(sngss7_info,FLAG_RESET_RX)) {
+               return 1;
+       }
+       
+       if (sngss7_test_flag(sngss7_info,FLAG_RESET_TX)) {
+               return 1;
+       }
+       
+       if (sngss7_test_flag(sngss7_info,FLAG_GRP_RESET_RX)) {
+               return 1;
+       }
+       
+       if (sngss7_test_flag(sngss7_info,FLAG_GRP_RESET_TX)) {
+               return 1;
+       }
+
+       return 0;
+       
 }
 
 /******************************************************************************/
 unsigned long get_unique_id(void)
 {
 
-    if (sngss7_id < 420000000) {
-        sngss7_id++;
-    } else {
-        sngss7_id = 1;
-    }
+       if (sngss7_id < 420000000) {
+               sngss7_id++;
+       } else {
+               sngss7_id = 1;
+       }
 
-    return(sngss7_id);
+       return(sngss7_id);
 }
 
 /******************************************************************************/
index 2d3aed66fb3e32b1ce7085265fefbbde32236b15..aa639d1c3a35d76ac8b5a3991693368325af2ea6 100644 (file)
 /* GLOBALS ********************************************************************/
 typedef struct sng_timeslot
 {
-    int     channel;
-    int     siglink;
-    int     gap;
-    int     hole;
+       int      channel;
+       int      siglink;
+       int      gap;
+       int      hole;
 }sng_timeslot_t;
 /******************************************************************************/
 
@@ -55,8 +55,7 @@ static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup);
 
 static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets);
 static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset);
-static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp1Link_t *mtp1_link,
-                                     sng_mtp2Link_t *mtp2_link, sng_mtp3Link_t *mtp3_link);
+static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *mtpLink);
 
 static int ftmod_ss7_parse_mtp_routes(ftdm_conf_node_t *mtp_routes);
 static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route);
@@ -64,14 +63,15 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route);
 static int ftmod_ss7_parse_isup_interfaces(ftdm_conf_node_t *isup_interfaces);
 static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface);
 
-static int ftmod_ss7_fill_in_mtp1_link(sng_mtp1Link_t *mtp1_link);
-static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2Link_t *mtp2_link);
-static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3Link_t *mtp3_link);
-static int ftmod_ss7_fill_in_mtp3_linkset(sng_mtp3LinkSet_t *mtp3_linkset);
-static int ftmod_ss7_fill_in_mtp3_route(sng_mtp3Route_t *mtp3_route);
-static int ftmod_ss7_fill_in_mtp3_isup_interface(sng_mtp3Route_t *mtp3_route);
-static int ftmod_ss7_fill_in_isup_interface(sng_isupInterface_t *sng_isup);
-static int ftmod_ss7_fill_in_isup_cc_interface(sng_isup_cc_t *sng_cc);
+static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink);
+
+static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet);
+
+static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route);
+static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route);
+
+static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup);
+static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap);
 
 static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, int ssf);
 
@@ -83,736 +83,750 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot);
 /* FUNCTIONS ******************************************************************/
 int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span)
 {
-    int              i = 0;
-    int              x = 0;
-    const char       *var = NULL;
-    const char       *val = NULL;
-    ftdm_conf_node_t *ptr = NULL;
-    sng_mtp3Route_t  self_route;
-    char             ch_map[MAX_CIC_MAP_LENGTH];
-    int              typeCntrl = 0;
-    int              cicbase = 0;
-
-    /* clean out the self route */
-    memset(&self_route, 0x0, sizeof(sng_mtp3Route_t));
-
-    var = ftdm_parameters[i].var;
-    val = ftdm_parameters[i].val;
-    ptr = (ftdm_conf_node_t *)ftdm_parameters[i].ptr;
-
-    /* confirm that the first parameter is the "confnode" */
-    if (!strcasecmp(var, "confnode")) {
-        /* parse the confnode and fill in the global libsng_ss7 config structure */
-        if (ftmod_ss7_parse_sng_isup(ptr)) {
-            SS7_ERROR("Failed to parse the \"confnode\"!\n");
-            goto ftmod_ss7_parse_xml_error;
-        }
-    } else {
-        /* ERROR...exit */
-        SS7_ERROR("The \"confnode\" configuration was not the first parameter!\n");
-        SS7_ERROR("\tFound \"%s\" in the first slot\n", var);
-        goto ftmod_ss7_parse_xml_error;
-    }
-
-    i++;
-    while (ftdm_parameters[i].var != NULL) {
-
-        var = ftdm_parameters[i].var;
-        val = ftdm_parameters[i].val;
-
-        if (!strcasecmp(var, "ch_map")) {
-        /**********************************************************************/
-            strcpy(ch_map, val);
-            SS7_DEBUG("\tFound channel map \"%s\"\n", ch_map);
-        /**********************************************************************/
-        } else if (!strcasecmp(var, "typeCntrl")) {
-            if (!strcasecmp(val, "bothway")) {
-                typeCntrl = SNG_BOTHWAY;
-                SS7_DEBUG("\tFound control type \"bothway\"\n");
-            } else if (!strcasecmp(val, "incoming")) {
-                typeCntrl = SNG_INCOMING;
-                SS7_DEBUG("\tFound control type \"incoming\"\n");
-            } else if (!strcasecmp(val, "outgoing")) {
-                typeCntrl = SNG_OUTGOING;
-                SS7_DEBUG("\tFound control type \"outgoing\"\n");
-            } else if (!strcasecmp(val, "controlled")) {
-                typeCntrl = SNG_CONTROLLED;
-                SS7_DEBUG("\tFound control type \"controlled\"\n");
-            } else if (!strcasecmp(val, "controlling")) {
-                typeCntrl = SNG_CONTROLLING;
-                SS7_DEBUG("\tFound control type \"controlling\"\n");
-            } else {
-                SS7_ERROR("Found invalid circuit control type \"%s\"!", val);
-                goto ftmod_ss7_parse_xml_error;
-            }
-        /**********************************************************************/
-        } else if (!strcasecmp(var, "cicbase")) {
-            cicbase = atoi(val);
-            SS7_DEBUG("\tFound cicbase = %d\n", cicbase);
-        /**********************************************************************/
-        } else if (!strcasecmp(var, "dialplan")) {
-            /* do i give a shit about this??? */
-        /**********************************************************************/
-        } else if (!strcasecmp(var, "context")) {
-            /* do i give a shit about this??? */
-        /**********************************************************************/
-        } else if (!strcasecmp(var, "isup_interface")) {
-            /* go through all the existing interfaces and see if we find a match */
-            x = 1;
-            while (g_ftdm_sngss7_data.cfg.isupInterface[x].id != 0) {
-                if (!strcasecmp(g_ftdm_sngss7_data.cfg.isupInterface[x].name, val)) {
-                    /* we have a match so break out of this loop */
-                    break;
-                }
-                /* move on to the next one */
-                x++;
-            }
-            SS7_DEBUG("\tFound isup_interface = %s\n",g_ftdm_sngss7_data.cfg.isupInterface[x].name );
-        /**********************************************************************/
-        } else {
-            SS7_ERROR("Unknown parameter found =\"%s\"...ignoring it!\n", var);
-        /**********************************************************************/
-        }
-
-        i++;
-    } /* while (ftdm_parameters[i].var != NULL) */
-
-    /* setup the self mtp3 route */
-    i = g_ftdm_sngss7_data.cfg.isupInterface[x].mtp3RouteId;
-
-    if(ftmod_ss7_fill_in_self_route(atoi(g_ftdm_sngss7_data.cfg.spc),
-                                    g_ftdm_sngss7_data.cfg.mtp3Route[i].linkType,
-                                    g_ftdm_sngss7_data.cfg.isupInterface[x].switchType,
-                                    g_ftdm_sngss7_data.cfg.mtp3Route[i].ssf)) {
-        SS7_ERROR("Failed to fill in self route structure!\n");
-        goto ftmod_ss7_parse_xml_error;
-    }
-
-
-    /* setup the circuits structure */
-    if(ftmod_ss7_fill_in_circuits(ch_map, 
-                                  cicbase, 
-                                  typeCntrl, 
-                                  g_ftdm_sngss7_data.cfg.isupInterface[x].id,
-                                  span)) {
-        SS7_ERROR("Failed to fill in circuits structure!\n");
-        goto ftmod_ss7_parse_xml_error;
-    }
-
-    return FTDM_SUCCESS;
+       int                                     i = 0;
+       int                                     x = 0;
+       const char                      *var = NULL;
+       const char                      *val = NULL;
+       ftdm_conf_node_t        *ptr = NULL;
+       sng_route_t                     self_route;
+       char                            ch_map[MAX_CIC_MAP_LENGTH];
+       int                                     typeCntrl = 0;
+       int                                     cicbase = 0;
+
+       /* clean out the self route */
+       memset(&self_route, 0x0, sizeof(sng_route_t));
+
+       var = ftdm_parameters[i].var;
+       val = ftdm_parameters[i].val;
+       ptr = (ftdm_conf_node_t *)ftdm_parameters[i].ptr;
+
+       /* confirm that the first parameter is the "confnode" */
+       if (!strcasecmp(var, "confnode")) {
+               /* parse the confnode and fill in the global libsng_ss7 config structure */
+               if (ftmod_ss7_parse_sng_isup(ptr)) {
+                       SS7_ERROR("Failed to parse the \"confnode\"!\n");
+                       goto ftmod_ss7_parse_xml_error;
+               }
+       } else {
+               /* ERROR...exit */
+               SS7_ERROR("The \"confnode\" configuration was not the first parameter!\n");
+               SS7_ERROR("\tFound \"%s\" in the first slot\n", var);
+               goto ftmod_ss7_parse_xml_error;
+       }
+
+       i++;
+       while (ftdm_parameters[i].var != NULL) {
+
+               var = ftdm_parameters[i].var;
+               val = ftdm_parameters[i].val;
+
+               if (!strcasecmp(var, "ch_map")) {
+               /**********************************************************************/
+                       strcpy(ch_map, val);
+                       SS7_DEBUG("\tFound channel map \"%s\"\n", ch_map);
+               /**********************************************************************/
+               } else if (!strcasecmp(var, "typeCntrl")) {
+                       if (!strcasecmp(val, "bothway")) {
+                               typeCntrl = BOTHWAY;
+                               SS7_DEBUG("\tFound control type \"bothway\"\n");
+                       } else if (!strcasecmp(val, "incoming")) {
+                               typeCntrl = INCOMING;
+                               SS7_DEBUG("\tFound control type \"incoming\"\n");
+                       } else if (!strcasecmp(val, "outgoing")) {
+                               typeCntrl = OUTGOING;
+                               SS7_DEBUG("\tFound control type \"outgoing\"\n");
+                       } else if (!strcasecmp(val, "controlled")) {
+                               typeCntrl = CONTROLLED;
+                               SS7_DEBUG("\tFound control type \"controlled\"\n");
+                       } else if (!strcasecmp(val, "controlling")) {
+                               typeCntrl = CONTROLLING;
+                               SS7_DEBUG("\tFound control type \"controlling\"\n");
+                       } else {
+                               SS7_ERROR("Found invalid circuit control type \"%s\"!", val);
+                               goto ftmod_ss7_parse_xml_error;
+                       }
+               /**********************************************************************/
+               } else if (!strcasecmp(var, "cicbase")) {
+                       cicbase = atoi(val);
+                       SS7_DEBUG("\tFound cicbase = %d\n", cicbase);
+               /**********************************************************************/
+               } else if (!strcasecmp(var, "dialplan")) {
+                       /* do i give a shit about this??? */
+               /**********************************************************************/
+               } else if (!strcasecmp(var, "context")) {
+                       /* do i give a shit about this??? */
+               /**********************************************************************/
+               } else if (!strcasecmp(var, "isup_interface")) {
+                       /* go through all the existing interfaces and see if we find a match */
+                       x = 1;
+                       while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) {
+                               if (!strcasecmp(g_ftdm_sngss7_data.cfg.isupIntf[x].name, val)) {
+                                       /* we have a match so break out of this loop */
+                                       break;
+                               }
+                               /* move on to the next one */
+                               x++;
+                       }
+                       SS7_DEBUG("\tFound isup_interface = %s\n",g_ftdm_sngss7_data.cfg.isupIntf[x].name );
+               /**********************************************************************/
+               } else {
+                       SS7_ERROR("Unknown parameter found =\"%s\"...ignoring it!\n", var);
+               /**********************************************************************/
+               }
+
+               i++;
+       } /* while (ftdm_parameters[i].var != NULL) */
+
+       /* setup the self mtp3 route */
+       i = g_ftdm_sngss7_data.cfg.isupIntf[x].mtpRouteId;
+
+       if(ftmod_ss7_fill_in_self_route(g_ftdm_sngss7_data.cfg.isupIntf[x].spc,
+                                                                       g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType,
+                                                                       g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType,
+                                                                       g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf)) {
+
+               SS7_ERROR("Failed to fill in self route structure!\n");
+               goto ftmod_ss7_parse_xml_error;
+
+       }
+
+
+       /* setup the circuits structure */
+       if(ftmod_ss7_fill_in_circuits(ch_map, cicbase, typeCntrl, 
+                                                                 g_ftdm_sngss7_data.cfg.isupIntf[x].id, span)) {
+               SS7_ERROR("Failed to fill in circuits structure!\n");
+               goto ftmod_ss7_parse_xml_error;
+       }
+
+       return FTDM_SUCCESS;
 
 ftmod_ss7_parse_xml_error:
-    return FTDM_FAIL;
+       return FTDM_FAIL;
 }
 
 /******************************************************************************/
 static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup)
 {
-    ftdm_conf_node_t    *mtp_linksets = NULL;
-    ftdm_conf_node_t    *mtp_routes = NULL;
-    ftdm_conf_node_t    *isup_interfaces = NULL;
-    ftdm_conf_node_t    *tmp_node = NULL;
-
-    /* confirm that we are looking at sng_isup */
-    if (strcasecmp(sng_isup->name, "sng_isup")) {
-        SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"sng_isup\"!\n",sng_isup->name);
-        return FTDM_FAIL;
-    }  else {
-        SS7_DEBUG("Parsing \"sng_isup\"...\n");
-    }
-
-    /* extract the 3 main sections of the sng_isup block */
-    tmp_node = sng_isup->child;
-    while (tmp_node != NULL) {
-
-        if (!strcasecmp(tmp_node->name, "mtp_linksets")) {
-            if (mtp_linksets == NULL) {
-                mtp_linksets = tmp_node;
-                SS7_DEBUG("\tFound a \"mtp_linksets section!\n");
-            } else {
-                SS7_ERROR("\tFound a second \"mtp_linksets\" section!\n");
-                return FTDM_FAIL;
-            }
-        } else if (!strcasecmp(tmp_node->name, "mtp_routes")) {
-            if (mtp_routes == NULL) {
-                mtp_routes = tmp_node;
-                SS7_DEBUG("\tFound a \"mtp_routes\" section!\n");
-            } else {
-                SS7_ERROR("\tFound a second \"mtp_routes\" section!\n");
-                return FTDM_FAIL;
-            }
-        } else if (!strcasecmp(tmp_node->name, "isup_interfaces")) {
-            if (isup_interfaces == NULL) {
-                isup_interfaces = tmp_node;
-                SS7_DEBUG("\tFound a \"isup_interfaces\" section!\n");
-            } else {
-                SS7_ERROR("\tFound a second \"isup_interfaces\" section\n!");
-                return FTDM_FAIL;
-            }
-        } else {
-            SS7_ERROR("\tFound an unknown section \"%s\"!\n", tmp_node->name);
-            return FTDM_FAIL;
-        }
-
-        /* go to the next sibling */
-        tmp_node = tmp_node->next;
-
-    } /* while (tmp_node != NULL) */
-
-    /* now try to parse the sections */
-    if (ftmod_ss7_parse_mtp_linksets(mtp_linksets)) {
-        SS7_ERROR("Failed to parse \"mtp_linksets\"!\n");
-        return FTDM_FAIL;
-    }
-
-    if (ftmod_ss7_parse_mtp_routes(mtp_routes)) {
-        SS7_ERROR("Failed to parse \"mtp_routes\"!\n");
-        return FTDM_FAIL;
-    }
-
-    if (ftmod_ss7_parse_isup_interfaces(isup_interfaces)) {
-        SS7_ERROR("Failed to parse \"isup_interfaces\"!\n");
-        return FTDM_FAIL;
-    }
-
-    return FTDM_SUCCESS;
+       ftdm_conf_node_t        *mtp_linksets = NULL;
+       ftdm_conf_node_t        *mtp_routes = NULL;
+       ftdm_conf_node_t        *isup_interfaces = NULL;
+       ftdm_conf_node_t        *tmp_node = NULL;
+
+       /* confirm that we are looking at sng_isup */
+       if (strcasecmp(sng_isup->name, "sng_isup")) {
+               SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"sng_isup\"!\n",sng_isup->name);
+               return FTDM_FAIL;
+       }  else {
+               SS7_DEBUG("Parsing \"sng_isup\"...\n");
+       }
+
+       /* extract the 3 main sections of the sng_isup block */
+       tmp_node = sng_isup->child;
+       while (tmp_node != NULL) {
+
+               if (!strcasecmp(tmp_node->name, "mtp_linksets")) {
+                       if (mtp_linksets == NULL) {
+                               mtp_linksets = tmp_node;
+                               SS7_DEBUG("\tFound a \"mtp_linksets section!\n");
+                       } else {
+                               SS7_ERROR("\tFound a second \"mtp_linksets\" section!\n");
+                               return FTDM_FAIL;
+                       }
+               } else if (!strcasecmp(tmp_node->name, "mtp_routes")) {
+                       if (mtp_routes == NULL) {
+                               mtp_routes = tmp_node;
+                               SS7_DEBUG("\tFound a \"mtp_routes\" section!\n");
+                       } else {
+                               SS7_ERROR("\tFound a second \"mtp_routes\" section!\n");
+                               return FTDM_FAIL;
+                       }
+               } else if (!strcasecmp(tmp_node->name, "isup_interfaces")) {
+                       if (isup_interfaces == NULL) {
+                               isup_interfaces = tmp_node;
+                               SS7_DEBUG("\tFound a \"isup_interfaces\" section!\n");
+                       } else {
+                               SS7_ERROR("\tFound a second \"isup_interfaces\" section\n!");
+                               return FTDM_FAIL;
+                       }
+               } else {
+                       SS7_ERROR("\tFound an unknown section \"%s\"!\n", tmp_node->name);
+                       return FTDM_FAIL;
+               }
+
+               /* go to the next sibling */
+               tmp_node = tmp_node->next;
+
+       } /* while (tmp_node != NULL) */
+
+       /* now try to parse the sections */
+       if (ftmod_ss7_parse_mtp_linksets(mtp_linksets)) {
+               SS7_ERROR("Failed to parse \"mtp_linksets\"!\n");
+               return FTDM_FAIL;
+       }
+
+       if (ftmod_ss7_parse_mtp_routes(mtp_routes)) {
+               SS7_ERROR("Failed to parse \"mtp_routes\"!\n");
+               return FTDM_FAIL;
+       }
+
+       if (ftmod_ss7_parse_isup_interfaces(isup_interfaces)) {
+               SS7_ERROR("Failed to parse \"isup_interfaces\"!\n");
+               return FTDM_FAIL;
+       }
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets)
 {
-    ftdm_conf_node_t    *mtp_linkset = NULL;
+       ftdm_conf_node_t        *mtp_linkset = NULL;
 
-    /* confirm that we are looking at mtp_linksets */
-    if (strcasecmp(mtp_linksets->name, "mtp_linksets")) {
-        SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linksets\"!\n",mtp_linksets->name);
-        return FTDM_FAIL;
-    }  else {
-        SS7_DEBUG("Parsing \"mtp_linksets\"...\n");
-    }
+       /* confirm that we are looking at mtp_linksets */
+       if (strcasecmp(mtp_linksets->name, "mtp_linksets")) {
+               SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linksets\"!\n",mtp_linksets->name);
+               return FTDM_FAIL;
+       }  else {
+               SS7_DEBUG("Parsing \"mtp_linksets\"...\n");
+       }
 
-    /* extract the mtp_links */
-    mtp_linkset = mtp_linksets->child;
+       /* extract the mtp_links */
+       mtp_linkset = mtp_linksets->child;
 
-    /* run through all of the mtp_linksets found  */
-    while (mtp_linkset != NULL) {
-        /* try to the parse mtp_linkset */
-        if (ftmod_ss7_parse_mtp_linkset(mtp_linkset)) {
-            SS7_ERROR("Failed to parse \"mtp_linkset\"!\n");
-            return FTDM_FAIL;
-        }
+       /* run through all of the mtp_linksets found  */
+       while (mtp_linkset != NULL) {
+               /* try to the parse mtp_linkset */
+               if (ftmod_ss7_parse_mtp_linkset(mtp_linkset)) {
+                       SS7_ERROR("Failed to parse \"mtp_linkset\"!\n");
+                       return FTDM_FAIL;
+               }
 
-        /* move on to the next linkset */
-        mtp_linkset = mtp_linkset->next;
+               /* move on to the next linkset */
+               mtp_linkset = mtp_linkset->next;
 
-    } /* while (mtp_linkset != NULL) */
+       } /* while (mtp_linkset != NULL) */
 
-    return FTDM_SUCCESS;
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset)
 {
-    ftdm_conf_parameter_t   *parm = mtp_linkset->parameters;
-    int                     num_parms = mtp_linkset->n_parameters;
-    ftdm_conf_node_t        *mtp_link = NULL;
-    sng_mtp1Link_t          mtp1_link[MAX_MTP_LINKS];
-    sng_mtp2Link_t          mtp2_link[MAX_MTP_LINKS];
-    sng_mtp3Link_t          mtp3_link[MAX_MTP_LINKS];
-    sng_mtp3LinkSet_t       mtp3_linkset;
-    int                     count;
-    int                     i;
-
-    /* initialize the mtp_link structures */
-    for (i = 0; i < MAX_MTP_LINKS; i++) {
-        memset(&mtp1_link[i], 0x0, sizeof(mtp1_link[i]));
-        memset(&mtp2_link[i], 0x0, sizeof(mtp2_link[i]));
-        memset(&mtp3_link[i], 0x0, sizeof(mtp3_link[i]));
-    }
-    memset(&mtp3_linkset, 0x0, sizeof(mtp3_linkset));
-
-    /* confirm that we are looking at mtp_linkset */
-    if (strcasecmp(mtp_linkset->name, "mtp_linkset")) {
-        SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linkset\"!\n",mtp_linkset->name);
-        return FTDM_FAIL;
-    } else {
-        SS7_DEBUG("Parsing \"mtp_linkset\"...\n");
-    }
-
-    /* extract all the information from the parameters */
-    for (i = 0; i < num_parms; i++) {
-        /**********************************************************************/
-        if (!strcasecmp(parm->var, "name")) {
-            strcpy((char *)mtp3_linkset.name, parm->val);
-            SS7_DEBUG("\tFound an \"mtp_linkset\" named = %s\n", mtp3_linkset.name);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "apc")) {
-            mtp3_linkset.apc = atoi(parm->val);
-            SS7_DEBUG("\tFound mtp3_linkSet->apc = %d\n", mtp3_linkset.apc);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "minActive")) {
-            mtp3_linkset.minActive = atoi(parm->val);
-            SS7_DEBUG("\tFound mtp3_linkSet->minActive = %d\n", mtp3_linkset.minActive);
-        /**********************************************************************/
-        } else {
-            SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
-            return FTDM_FAIL;
-        }
-
-        /* move to the next parmeter */
-        parm = parm + 1;
-
-    } /* for (i = 0; i < num_parms; i++) */
-
-    /* grab the first mtp-link (which sits below the mtp_links section) */
-    mtp_link = mtp_linkset->child->child;
-
-    /* initalize the link counter */
-    count = 0;
-
-    /* run through all of the mtp_links found  */
-    while (mtp_link != NULL) {
-        /* try to the parse mtp_linkset */
-        if (ftmod_ss7_parse_mtp_link(mtp_link, &mtp1_link[count], &mtp2_link[count], &mtp3_link[count] )) {
-            SS7_ERROR("Failed to parse \"mtp_link\"!\n");
-            return FTDM_FAIL;
-        }
-
-        /* incremenet the link counter */
-        count++;
-
-        /* move on to the next link */
-        mtp_link = mtp_link->next;
-
-    } /* while (mtp_link != NULL) */
-
-    /* confirm we have the right number of links */
-    if (count < 1 || count > 15 ) {
-        SS7_ERROR("Invalid number of mtp_links found (%d)\n", count);
-        return FTDM_FAIL;
-    } else {
-        mtp3_linkset.numLinks = count;
-    }
-
-    /* now we need to see if this linkset exists already or not and grab an Id */
-    i = 1;
-    while (g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].id != 0) {
-        if (!strcasecmp((const char *)g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].name, (const char *)mtp3_linkset.name)) {
-            /* we've found the linkset...so it has already been configured */
-            break;
-        }
-        i++;
-        /* add in error check to make sure we don't go out-of-bounds */
-    }
-
-    /* if the id value is 0 that means we didn't find the linkset */
-    if (g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].id  == 0) {
-        mtp3_linkset.id = i;
-        SS7_DEBUG("found new mtp3_linkset, id is = %d\n", mtp3_linkset.id);
-    } else {
-        mtp3_linkset.id = i;
-        SS7_DEBUG("found existing mtp3_linkset, id is = %d\n", mtp3_linkset.id);
-    }
-
-    /* we now have all the information to fill in the Libsng_ss7 structures */
-    i = 0;
-    count = 0;
-    while (mtp1_link[i].span != 0 ){
-        /* fill in the mtp1 link structure */
-        mtp2_link[i].spId = ftmod_ss7_fill_in_mtp1_link(&mtp1_link[i]);
-        /* fill in the mtp2 link structure */
-        mtp3_link[i].mtp2LinkId = ftmod_ss7_fill_in_mtp2_link(&mtp2_link[i]);
-        /* have to grab a couple of values from the linkset */
-        mtp3_link[i].apc = mtp3_linkset.apc;
-        mtp3_link[i].linkSetId = mtp3_linkset.id;
-        /* fill in the mtp3 link structure */
-        mtp3_linkset.links[count] = ftmod_ss7_fill_in_mtp3_link(&mtp3_link[i]);
-        /* increment the links counter */
-        count++;
-        /* increment the index value */
-        i++;
-    }
-
-    ftmod_ss7_fill_in_mtp3_linkset(&mtp3_linkset);
-
-    return FTDM_SUCCESS;
+       ftdm_conf_parameter_t   *parm = mtp_linkset->parameters;
+       int                                             num_parms = mtp_linkset->n_parameters;
+       ftdm_conf_node_t                *mtp_link = NULL;
+       sng_mtp_link_t                  mtpLink[MAX_MTP_LINKS+1];
+       sng_link_set_t                  mtpLinkSet;
+       int                                             count;
+       int                                             i;
+
+       /* initialize the mtp_link structures */
+       for (i = 0; i < (MAX_MTP_LINKS  + 1); i++) {
+               memset(&mtpLink[i], 0x0, sizeof(mtpLink[i]));
+       }
+       memset(&mtpLinkSet, 0x0, sizeof(mtpLinkSet));
+
+       /* confirm that we are looking at mtp_linkset */
+       if (strcasecmp(mtp_linkset->name, "mtp_linkset")) {
+               SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linkset\"!\n",mtp_linkset->name);
+               return FTDM_FAIL;
+       } else {
+               SS7_DEBUG("Parsing \"mtp_linkset\"...\n");
+       }
+
+       /* extract all the information from the parameters */
+       for (i = 0; i < num_parms; i++) {
+               /**********************************************************************/
+               if (!strcasecmp(parm->var, "name")) {
+                       strcpy((char *)mtpLinkSet.name, parm->val);
+                       SS7_DEBUG("\tFound an \"mtp_linkset\" named = %s\n", mtpLinkSet.name);
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "apc")) {
+                       mtpLinkSet.apc = atoi(parm->val);
+                       SS7_DEBUG("\tFoundmtpLinkSet->apc = %d\n", mtpLinkSet.apc);
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "minActive")) {
+                       mtpLinkSet.minActive = atoi(parm->val);
+                       SS7_DEBUG("\tFoundmtpLinkSet->minActive = %d\n", mtpLinkSet.minActive);
+               /**********************************************************************/
+               } else {
+                       SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
+                       return FTDM_FAIL;
+               }
+
+               /* move to the next parmeter */
+               parm = parm + 1;
+
+       } /* for (i = 0; i < num_parms; i++) */
+
+       /* grab the first mtp-link (which sits below the mtp_links section) */
+       mtp_link = mtp_linkset->child->child;
+
+       /* initalize the link counter */
+       count = 0;
+
+       /* run through all of the mtp_links found  */
+       while (mtp_link != NULL) {
+               /* try to the parse mtp_linkset */
+               if (ftmod_ss7_parse_mtp_link(mtp_link, &mtpLink[count] )) {
+                       SS7_ERROR("Failed to parse \"mtp_link\"!\n");
+                       return FTDM_FAIL;
+               }
+
+               /* incremenet the link counter */
+               count++;
+
+               /* move on to the next link */
+               mtp_link = mtp_link->next;
+
+       } /* while (mtp_link != NULL) */
+
+       /* confirm we have the right number of links */
+       if (count < 1 || count > 15 ) {
+               SS7_ERROR("Invalid number of mtp_links found (%d)\n", count);
+               return FTDM_FAIL;
+       } else {
+               mtpLinkSet.numLinks = count;
+       }
+
+       /* now we need to see if this linkset exists already or not and grab an Id */
+       i = 1;
+       while (g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id != 0) {
+               if (!strcasecmp((const char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (const char *)mtpLinkSet.name)) {
+                       /* we've found the linkset...so it has already been configured */
+                       break;
+               }
+               i++;
+               /* add in error check to make sure we don't go out-of-bounds */
+       }
+
+       /* if the id value is 0 that means we didn't find the linkset */
+       if (g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id  == 0) {
+               mtpLinkSet.id = i;
+               SS7_DEBUG("found new mtpLinkSet, id is = %d\n", mtpLinkSet.id);
+       } else {
+               mtpLinkSet.id = i;
+               SS7_DEBUG("found existing mtpLinkSet, id is = %d\n", mtpLinkSet.id);
+       }
+
+       /* we now have all the information to fill in the Libsng_ss7 structures */
+       i = 0;
+       count = 0;
+       while (mtpLink[i].mtp1.span != 0 ){
+
+               /* have to grab a couple of values from the linkset */
+               mtpLink[i].mtp3.apc                     = mtpLinkSet.apc;
+               mtpLink[i].mtp3.linkSetId       = mtpLinkSet.id;
+
+               /* fill in the mtplink structure */
+               mtpLinkSet.links[count] = ftmod_ss7_fill_in_mtpLink(&mtpLink[i]);
+
+               /* increment the links counter */
+               count++;
+
+               /* increment the index value */
+               i++;
+       }
+
+       ftmod_ss7_fill_in_mtpLinkSet(&mtpLinkSet);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp1Link_t *mtp1_link,
-            sng_mtp2Link_t *mtp2_link, sng_mtp3Link_t *mtp3_link)
+static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *mtpLink)
 {
-    ftdm_conf_parameter_t   *parm = mtp_link->parameters;
-    int                     num_parms = mtp_link->n_parameters;
-    int                     i;
-
-    /* confirm that we are looking at an mtp_link */
-    if (strcasecmp(mtp_link->name, "mtp_link")) {
-        SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_link\"!\n",mtp_link->name);
-        return FTDM_FAIL;
-    } else {
-        SS7_DEBUG("Parsing \"mtp_link\"...\n");
-    }
-
-    for (i = 0; i < num_parms; i++) {
-        /* try to match the parameter to what we expect */
-        /**********************************************************************/
-        if (!strcasecmp(parm->var, "name")) {
-            strcpy((char *)mtp1_link->name, parm->val);
-            strcpy((char *)mtp2_link->name, parm->val);
-            strcpy((char *)mtp3_link->name, parm->val);
-            SS7_DEBUG("\tFound an \"mtp_link\" named = %s\n", mtp1_link->name);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "span")) {
-            mtp1_link->span = atoi(parm->val);
-            SS7_DEBUG("\tFound mtp1_link->span = %d\n", mtp1_link->span);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "chan")) {
-            mtp1_link->chan = atoi(parm->val);
-            SS7_DEBUG("\tFound mtp1_link->chan = %d\n", mtp1_link->chan);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "span")) {
-            mtp1_link->span = atoi(parm->val);
-            SS7_DEBUG("\tFound mtp1_link->span = %d\n", mtp1_link->span);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "errorType")) {
-            if (!strcasecmp(parm->val, "basic")) {
-                mtp2_link->errorType = SNG_BASIC_ERR;
-            } else if (!strcasecmp(parm->val, "pcr")) {
-                mtp2_link->errorType = SNG_PCR_ERR;
-            } else {
-                SS7_ERROR("\tFound an invalid \"errorType\" = %s\n", parm->var);
-                return FTDM_FAIL;
-            }
-            SS7_DEBUG("\tFound mtp2_link->errorType=%s\n", parm->val);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "lssuLength")) {
-            mtp2_link->lssuLength = atoi(parm->val);
-            if ((mtp2_link->lssuLength != 1) && (mtp2_link->lssuLength != 2)) {
-                SS7_ERROR("\tFound an invalid \"lssuLength\" = %d\n", mtp2_link->lssuLength);
-                return FTDM_FAIL;
-            } else {
-                SS7_DEBUG("\tFound mtp2_link->lssuLength=%d\n", mtp2_link->lssuLength);
-            }
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "priority")) {
-            mtp3_link->priority = atoi(parm->val);
-            if ((mtp3_link->priority == 0) || (mtp3_link->priority == 1) || 
-                (mtp3_link->priority == 2) || (mtp3_link->priority == 3)) {
-                SS7_DEBUG("\tFound mtp3_link->priority = %d\n",mtp3_link->priority);
-            } else {
-                SS7_ERROR("\tFound an invalid \"priority\"=%d\n", mtp3_link->priority);
-                return FTDM_FAIL;
-            } 
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "linkType")) {
-            if (!strcasecmp(parm->val, "itu92")) {
-                mtp2_link->linkType = SNG_MTP2_ITU92;
-                mtp3_link->linkType = SNG_MTP3_ITU92;
-                SS7_DEBUG("\tFound mtp3_link->linkType = \"ITU92\"\n");
-            } else if (!strcasecmp(parm->val, "itu88")) {
-                mtp2_link->linkType = SNG_MTP2_ITU88;
-                mtp3_link->linkType = SNG_MTP3_ITU88;
-                SS7_DEBUG("\tFound mtp3_link->linkType = \"ITU88\"\n");
-            } else {
-                SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val);
-                return FTDM_FAIL;
-            }
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "switchType")) {
-            if (!strcasecmp(parm->val, "itu97")) {
-                mtp3_link->switchType = SNG_ISUP_ITU97;
-                SS7_DEBUG("\tFound mtp3_link->switchType = \"ITU97\"\n");
-            } else if (!strcasecmp(parm->val, "itu88")) {
-                mtp3_link->switchType = SNG_ISUP_ITU88;
-                SS7_DEBUG("\tFound mtp3_link->switchType = \"ITU88\"\n");
-            } else if (!strcasecmp(parm->val, "itu92")) {
-                mtp3_link->switchType = SNG_ISUP_ITU92;
-                SS7_DEBUG("\tFound mtp3_link->switchType = \"ITU92\"\n");
-            } else if (!strcasecmp(parm->val, "itu00")) {
-                mtp3_link->switchType = SNG_ISUP_ITU00;
-                SS7_DEBUG("\tFound mtp3_link->switchType = \"ITU00\"\n");
-            } else if (!strcasecmp(parm->val, "ETSIV2")) {
-                mtp3_link->switchType = SNG_ISUP_ETSIV2;
-                SS7_DEBUG("\tFound mtp3_link->switchType = \"ETSIV2\"\n");
-            } else if (!strcasecmp(parm->val, "ETSIV3")) {
-                mtp3_link->switchType = SNG_ISUP_ETSIV3;
-                SS7_DEBUG("\tFound mtp3_link->switchType = \"ETSIV3\"\n");
-            } else if (!strcasecmp(parm->val, "UK")) {
-                mtp3_link->switchType = SNG_ISUP_UK;
-                SS7_DEBUG("\tFound mtp3_link->switchType = \"UK\"\n");
-            } else if (!strcasecmp(parm->val, "RUSSIA")) {
-                mtp3_link->switchType = SNG_ISUP_RUSSIA;
-                SS7_DEBUG("\tFound mtp3_link->switchType = \"RUSSIA\"\n");
-            } else if (!strcasecmp(parm->val, "INDIA")) {
-                mtp3_link->switchType = SNG_ISUP_INDIA;
-                SS7_DEBUG("\tFound mtp3_link->switchType = \"INDIA\"\n");
-            } else {
-                SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val);
-                return FTDM_FAIL;
-            }
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "ssf")) {
-            if (!strcasecmp(parm->val, "nat")) {
-                mtp3_link->ssf = SNG_SSF_NAT;
-            } else if (!strcasecmp(parm->val, "int")) {
-                mtp3_link->ssf = SNG_SSF_INTER;
-            } else {
-                SS7_ERROR("\tFound an invalid ssf of \"%s\"!\n", parm->val);
-                return FTDM_FAIL;
-            }
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "slc")) {
-            mtp3_link->lnkTstSLC = atoi(parm->val);
-            SS7_DEBUG("\tFound mtp3_link->slc = \"%d\"\n",mtp3_link->lnkTstSLC);
-        /**********************************************************************/
-        } else {
-            SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
-            return FTDM_FAIL;
-        }
-
-        /* move to the next parameter */
-        parm = parm + 1;
-    }
-
-    return FTDM_SUCCESS;
+       ftdm_conf_parameter_t   *parm = mtp_link->parameters;
+       int                                             num_parms = mtp_link->n_parameters;
+       int                                             i;
+       
+       /* confirm that we are looking at an mtp_link */
+       if (strcasecmp(mtp_link->name, "mtp_link")) {
+               SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_link\"!\n",mtp_link->name);
+               return FTDM_FAIL;
+       } else {
+               SS7_DEBUG("Parsing \"mtp_link\"...\n");
+       }
+       
+       for (i = 0; i < num_parms; i++) {
+               /* try to match the parameter to what we expect */
+               /**********************************************************************/
+               if (!strcasecmp(parm->var, "name")) {
+                       strcpy((char *)mtpLink->name, parm->val);
+                       SS7_DEBUG("\tFound an \"mtp_link\" named = %s\n", mtpLink->name);
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "span")) {
+                       mtpLink->mtp1.span = atoi(parm->val);
+                       SS7_DEBUG("\tFound mtpLink->span = %d\n", mtpLink->mtp1.span);
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "chan")) {
+                       mtpLink->mtp1.chan = atoi(parm->val);
+                       SS7_DEBUG("\tFound mtpLink->chan = %d\n", mtpLink->mtp1.chan);
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "errorType")) {
+                       if (!strcasecmp(parm->val, "basic")) {
+                               mtpLink->mtp2.errorType = SD_ERR_NRM;
+                       } else if (!strcasecmp(parm->val, "pcr")) {
+                               mtpLink->mtp2.errorType = SD_ERR_CYC;
+                       } else {
+                               SS7_ERROR("\tFound an invalid \"errorType\" = %s\n", parm->var);
+                               return FTDM_FAIL;
+                       }
+                       SS7_DEBUG("\tFound mtpLink->errorType=%s\n", parm->val);
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "lssuLength")) {
+                       mtpLink->mtp2.lssuLength = atoi(parm->val);
+                       if ((mtpLink->mtp2.lssuLength != 1) && (mtpLink->mtp2.lssuLength != 2)) {
+                               SS7_ERROR("\tFound an invalid \"lssuLength\" = %d\n", mtpLink->mtp2.lssuLength);
+                               return FTDM_FAIL;
+                       } else {
+                               SS7_DEBUG("\tFound mtpLink->lssuLength=%d\n", mtpLink->mtp2.lssuLength);
+                       }
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "priority")) {
+                       mtpLink->mtp3.priority = atoi(parm->val);
+                       if ((mtpLink->mtp3.priority == 0) || (mtpLink->mtp3.priority == 1) || 
+                               (mtpLink->mtp3.priority == 2) || (mtpLink->mtp3.priority == 3)) {
+                               SS7_DEBUG("\tFound mtpLink->priority = %d\n",mtpLink->mtp3.priority);
+                       } else {
+                               SS7_ERROR("\tFound an invalid \"priority\"=%d\n",mtpLink->mtp3.priority);
+                               return FTDM_FAIL;
+                       } 
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "linkType")) {
+                       if (!strcasecmp(parm->val, "itu92")) {
+                               mtpLink->mtp2.linkType = LSD_SW_ITU92;
+                               mtpLink->mtp3.linkType = LSN_SW_ITU;
+                               SS7_DEBUG("\tFoundmtpLink->linkType = \"ITU92\"\n");
+                       } else if (!strcasecmp(parm->val, "itu88")) {
+                               mtpLink->mtp2.linkType = LSD_SW_ITU88;
+                               mtpLink->mtp3.linkType = LSN_SW_ITU;
+                               SS7_DEBUG("\tFoundmtpLink->linkType = \"ITU88\"\n");
+                       } else if (!strcasecmp(parm->val, "ansi96")) {
+                               mtpLink->mtp2.linkType = LSD_SW_ANSI92;
+                               mtpLink->mtp3.linkType = LSN_SW_ANS96;
+                               SS7_DEBUG("\tFoundmtpLink->linkType = \"ANSI96\"\n");
+                       } else if (!strcasecmp(parm->val, "ansi92")) {
+                               mtpLink->mtp2.linkType = LSD_SW_ANSI92;
+                               mtpLink->mtp3.linkType = LSN_SW_ANS;
+                               SS7_DEBUG("\tFoundmtpLink->linkType = \"ANSI92\"\n");
+                       } else if (!strcasecmp(parm->val, "ansi88")) {
+                               mtpLink->mtp2.linkType = LSD_SW_ANSI88;
+                               mtpLink->mtp3.linkType = LSN_SW_ANS;
+                               SS7_DEBUG("\tFoundmtpLink->linkType = \"ANSI88\"\n");
+                       } else if (!strcasecmp(parm->val, "etsi")) {
+                               mtpLink->mtp2.linkType = LSD_SW_ITU92;
+                               mtpLink->mtp3.linkType = LSN_SW_ITU;
+                               SS7_DEBUG("\tFoundmtpLink->linkType = \"ETSI\"\n");
+                       } else {
+                               SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val);
+                               return FTDM_FAIL;
+                       }
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "switchType")) {
+                       if (!strcasecmp(parm->val, "itu97")) {
+                               mtpLink->mtp3.switchType = LSI_SW_ITU97;
+                               SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU97\"\n");
+                       } else if (!strcasecmp(parm->val, "itu88")) {
+                               mtpLink->mtp3.switchType = LSI_SW_ITU;
+                               SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU88\"\n");
+                       } else if (!strcasecmp(parm->val, "itu92")) {
+                               mtpLink->mtp3.switchType = LSI_SW_ITU;
+                               SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU92\"\n");
+                       } else if (!strcasecmp(parm->val, "itu00")) {
+                               mtpLink->mtp3.switchType = LSI_SW_ITU2000;
+                               SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU00\"\n");
+                       } else if (!strcasecmp(parm->val, "ETSIV2")) {
+                               mtpLink->mtp3.switchType = LSI_SW_ETSI;
+                               SS7_DEBUG("\tFoundmtpLink->switchType = \"ETSIV2\"\n");
+                       } else if (!strcasecmp(parm->val, "ETSIV3")) {
+                               mtpLink->mtp3.switchType = LSI_SW_ETSIV3;
+                               SS7_DEBUG("\tFoundmtpLink->switchType = \"ETSIV3\"\n");
+                       } else if (!strcasecmp(parm->val, "UK")) {
+                               mtpLink->mtp3.switchType = LSI_SW_UK;
+                               SS7_DEBUG("\tFoundmtpLink->switchType = \"UK\"\n");
+                       } else if (!strcasecmp(parm->val, "RUSSIA")) {
+                               mtpLink->mtp3.switchType = LSI_SW_RUSSIA;
+                               SS7_DEBUG("\tFoundmtpLink->switchType = \"RUSSIA\"\n");
+                       } else if (!strcasecmp(parm->val, "INDIA")) {
+                               mtpLink->mtp3.switchType = LSI_SW_INDIA;
+                               SS7_DEBUG("\tFoundmtpLink->switchType = \"INDIA\"\n");
+                       } else {
+                               SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val);
+                               return FTDM_FAIL;
+                       }
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "ssf")) {
+                       if (!strcasecmp(parm->val, "nat")) {
+                               mtpLink->mtp3.ssf = SSF_NAT;
+                       } else if (!strcasecmp(parm->val, "int")) {
+                               mtpLink->mtp3.ssf = SSF_INTL;
+                       } else {
+                               SS7_ERROR("\tFound an invalid ssf of \"%s\"!\n", parm->val);
+                               return FTDM_FAIL;
+                       }
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "slc")) {
+                       mtpLink->mtp3.slc = atoi(parm->val);
+                       SS7_DEBUG("\tFoundmtpLink->slc = \"%d\"\n",mtpLink->mtp3.slc);
+               /**********************************************************************/
+               } else {
+                       SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
+                       return FTDM_FAIL;
+               }
+       
+               /* move to the next parameter */
+               parm = parm + 1;
+       }
+       
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static int ftmod_ss7_parse_mtp_routes(ftdm_conf_node_t *mtp_routes)
 {
-    ftdm_conf_node_t    *mtp_route = NULL;
-
-    /* confirm that we are looking at an mtp_routes */
-    if (strcasecmp(mtp_routes->name, "mtp_routes")) {
-        SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_routes\"!\n",mtp_routes->name);
-        return FTDM_FAIL;
-    } else {
-        SS7_DEBUG("Parsing \"mtp_routes\"...\n");
-    }
-
-    /* extract the mtp_routes */
-    mtp_route = mtp_routes->child;
-
-    while (mtp_route != NULL) {
-        /* parse the found mtp_route */
-        if (ftmod_ss7_parse_mtp_route(mtp_route)) {
-            SS7_ERROR("Failed to parse \"mtp_route\"\n");
-            return FTDM_FAIL;
-        }
-
-        /* go to the next mtp_route */
-        mtp_route = mtp_route->next;
-    }
-
-    return FTDM_SUCCESS;
+       ftdm_conf_node_t        *mtp_route = NULL;
+
+       /* confirm that we are looking at an mtp_routes */
+       if (strcasecmp(mtp_routes->name, "mtp_routes")) {
+               SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_routes\"!\n",mtp_routes->name);
+               return FTDM_FAIL;
+       } else {
+               SS7_DEBUG("Parsing \"mtp_routes\"...\n");
+       }
+
+       /* extract the mtp_routes */
+       mtp_route = mtp_routes->child;
+
+       while (mtp_route != NULL) {
+               /* parse the found mtp_route */
+               if (ftmod_ss7_parse_mtp_route(mtp_route)) {
+                       SS7_ERROR("Failed to parse \"mtp_route\"\n");
+                       return FTDM_FAIL;
+               }
+
+               /* go to the next mtp_route */
+               mtp_route = mtp_route->next;
+       }
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
 {
-    sng_mtp3Route_t         mtp3_route;
-    ftdm_conf_parameter_t   *parm = mtp_route->parameters;
-    int                     num_parms = mtp_route->n_parameters;
-    int                     i;
-
-    memset(&mtp3_route, 0x0, sizeof(sng_mtp3Route_t));
-
-    /* confirm that we are looking at an mtp_link */
-    if (strcasecmp(mtp_route->name, "mtp_route")) {
-        SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_route\"!\n",mtp_route->name);
-        return FTDM_FAIL;
-    } else {
-        SS7_DEBUG("Parsing \"mtp_route\"...\n");
-    }
-
-    for (i = 0; i < num_parms; i++) {
-        /* try to match the parameter to what we expect */
-        /**********************************************************************/
-        if (!strcasecmp(parm->var, "name")) {
-            strcpy((char *)mtp3_route.name, parm->val);
-            SS7_DEBUG("\tFound an \"mtp_route\" named = %s\n", mtp3_route.name);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "dpc")) {
-            mtp3_route.dpc = atoi(parm->val);
-            SS7_DEBUG("\tFound mtp3_route->dpc = %d\n", mtp3_route.dpc);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "mtp_linkset")) {
-            /* find the linkset by it's name */
-            int x = 1;
-            while (g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].id != 0) {
-                /* check if the name matches */
-                if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].name, parm->val)) {
-                    /* grab the mtp3_link id value first*/
-                    int id = g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].links[0];
-                    /* now, harvest the required infomormation from the global structure */
-                    mtp3_route.linkType     = g_ftdm_sngss7_data.cfg.mtp3Link[id].linkType;
-                    mtp3_route.switchType   = g_ftdm_sngss7_data.cfg.mtp3Link[id].switchType;
-                    mtp3_route.ssf          = g_ftdm_sngss7_data.cfg.mtp3Link[id].ssf;
-                    mtp3_route.cmbLinkSetId = g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].id;
-                    break;
-                }
-                x++;
-            }
-
-            /* check why we exited the wile loop ... and react accordingly */
-            if (mtp3_route.cmbLinkSetId == 0) {
-                SS7_ERROR("\tFailed to find the linkset = \"%s\"!\n", parm->val);
-                return FTDM_FAIL;
-            } else {
-                SS7_DEBUG("\tFound mtp3_route->linkset = %s\n", parm->val);
-            }
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "isSTP")) {
-            if (!strcasecmp(parm->val, "no")) {
-                mtp3_route.isSTP = 0;
-                SS7_DEBUG("\tFound mtp3_route->isSTP = no\n");
-            } else if (!strcasecmp(parm->val, "yes")) {
-                mtp3_route.isSTP = 1;
-                SS7_DEBUG("\tFound mtp3_route->isSTP = yes\n");
-            } else {
-                SS7_ERROR("\tFound an invalid parameter for isSTP \"%s\"!\n", parm->val);
-               return FTDM_FAIL;
-            }
-        /**********************************************************************/
-        } else {
-            SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
-            return FTDM_FAIL;
-
-        }
-
-        /* move to the next parameter */
-        parm = parm + 1;
-    }
-
-    ftmod_ss7_fill_in_mtp3_route(&mtp3_route);
-
-    ftmod_ss7_fill_in_mtp3_isup_interface(&mtp3_route);
-
-    return FTDM_SUCCESS;
+       sng_route_t                             mtpRoute;
+       ftdm_conf_parameter_t   *parm = mtp_route->parameters;
+       int                                             num_parms = mtp_route->n_parameters;
+       int                                             i;
+
+       memset(&mtpRoute, 0x0, sizeof(mtpRoute));
+
+       /* confirm that we are looking at an mtp_link */
+       if (strcasecmp(mtp_route->name, "mtp_route")) {
+               SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_route\"!\n",mtp_route->name);
+               return FTDM_FAIL;
+       } else {
+               SS7_DEBUG("Parsing \"mtp_route\"...\n");
+       }
+
+       for (i = 0; i < num_parms; i++) {
+               /* try to match the parameter to what we expect */
+               /**********************************************************************/
+               if (!strcasecmp(parm->var, "name")) {
+                       strcpy((char *)mtpRoute.name, parm->val);
+                       SS7_DEBUG("\tFound an \"mtp_route\" named = %s\n", mtpRoute.name);
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "dpc")) {
+                       mtpRoute.dpc = atoi(parm->val);
+                       SS7_DEBUG("\tFound mtpRoute->dpc = %d\n", mtpRoute.dpc);
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "mtp_linkset")) {
+
+                       /* find the linkset by it's name */
+                       int x = 1;
+                       while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) {
+                               /* check if the name matches */
+                               if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, parm->val)) {
+
+                                       /* grab the mtpLink id value first*/
+                                       int id = g_ftdm_sngss7_data.cfg.mtpLinkSet[x].links[0];
+
+                                       /* now, harvest the required infomormation from the global structure */
+                                       mtpRoute.linkType               = g_ftdm_sngss7_data.cfg.mtpLink[id].mtp3.linkType;
+                                       mtpRoute.switchType             = g_ftdm_sngss7_data.cfg.mtpLink[id].mtp3.switchType;
+                                       mtpRoute.ssf                    = g_ftdm_sngss7_data.cfg.mtpLink[id].mtp3.ssf;
+                                       mtpRoute.cmbLinkSetId   = g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id;
+                                       break;
+                               }
+                               x++;
+                       }
+
+                       /* check why we exited the wile loop ... and react accordingly */
+                       if (mtpRoute.cmbLinkSetId == 0) {
+                               SS7_ERROR("\tFailed to find the linkset = \"%s\"!\n", parm->val);
+                               return FTDM_FAIL;
+                       } else {
+                               SS7_DEBUG("\tFound mtp3_route->linkset = %s\n", parm->val);
+                       }
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "isSTP")) {
+                       if (!strcasecmp(parm->val, "no")) {
+                               mtpRoute.isSTP = 0;
+                               SS7_DEBUG("\tFound mtpRoute->isSTP = no\n");
+                       } else if (!strcasecmp(parm->val, "yes")) {
+                               mtpRoute.isSTP = 1;
+                               SS7_DEBUG("\tFound mtpRoute->isSTP = yes\n");
+                       } else {
+                               SS7_ERROR("\tFound an invalid parameter for isSTP \"%s\"!\n", parm->val);
+                          return FTDM_FAIL;
+                       }
+               /**********************************************************************/
+               } else {
+                       SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
+                       return FTDM_FAIL;
+
+               }
+
+               /* move to the next parameter */
+               parm = parm + 1;
+       }
+
+       ftmod_ss7_fill_in_mtp3_route(&mtpRoute);
+
+       ftmod_ss7_fill_in_nsap(&mtpRoute);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static int ftmod_ss7_parse_isup_interfaces(ftdm_conf_node_t *isup_interfaces)
 {
-    ftdm_conf_node_t    *isup_interface = NULL;
-
-    /* confirm that we are looking at isup_interfaces */
-    if (strcasecmp(isup_interfaces->name, "isup_interfaces")) {
-        SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"isup_interfaces\"!\n",isup_interfaces->name);
-        return FTDM_FAIL;
-    } else {
-        SS7_DEBUG("Parsing \"isup_interfaces\"...\n");
-    }
-
-    /* extract the isup_interfaces */
-    isup_interface = isup_interfaces->child;
-
-    while (isup_interface != NULL) {
-        /* parse the found mtp_route */
-        if (ftmod_ss7_parse_isup_interface(isup_interface)) {
-            SS7_ERROR("Failed to parse \"isup_interface\"\n");
-            return FTDM_FAIL;
-        }
-
-        /* go to the next mtp_route */
-        isup_interface = isup_interface->next;
-    }
-
-    return FTDM_SUCCESS;
+       ftdm_conf_node_t        *isup_interface = NULL;
+
+       /* confirm that we are looking at isup_interfaces */
+       if (strcasecmp(isup_interfaces->name, "isup_interfaces")) {
+               SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"isup_interfaces\"!\n",isup_interfaces->name);
+               return FTDM_FAIL;
+       } else {
+               SS7_DEBUG("Parsing \"isup_interfaces\"...\n");
+       }
+
+       /* extract the isup_interfaces */
+       isup_interface = isup_interfaces->child;
+
+       while (isup_interface != NULL) {
+               /* parse the found mtp_route */
+               if (ftmod_ss7_parse_isup_interface(isup_interface)) {
+                       SS7_ERROR("Failed to parse \"isup_interface\"\n");
+                       return FTDM_FAIL;
+               }
+
+               /* go to the next mtp_route */
+               isup_interface = isup_interface->next;
+       }
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
 static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
 {
-    sng_isupInterface_t     sng_isup;
-    sng_isup_cc_t           sng_cc;
-    ftdm_conf_parameter_t   *parm = isup_interface->parameters;
-    int                     num_parms = isup_interface->n_parameters;
-    int                     i;
-
-    memset(&sng_isup, 0x0, sizeof(sng_isupInterface_t));
-    memset(&sng_cc, 0x0, sizeof(sng_isup_cc_t));
-
-    /* confirm that we are looking at an mtp_link */
-    if (strcasecmp(isup_interface->name, "isup_interface")) {
-        SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"isup_interface\"!\n",isup_interface->name);
-        return FTDM_FAIL;
-    } else {
-        SS7_DEBUG("Parsing \"isup_interface\"...\n");
-    }
-
-
-    for (i = 0; i < num_parms; i++) {
-        /* try to match the parameter to what we expect */
-        /**********************************************************************/
-        if (!strcasecmp(parm->var, "name")) {
-            strcpy((char *)sng_isup.name, parm->val);
-            SS7_DEBUG("\tFound an \"isup_interface\" named = %s\n", sng_isup.name);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "spc")) {
-                       strcpy(g_ftdm_sngss7_data.cfg.spc, parm->val);
-            SS7_DEBUG("\tFound SPC = %s\n", g_ftdm_sngss7_data.cfg.spc);
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "mtp_route")) {
-            /* find the route by it's name */
-            int x = 1;
-            while (g_ftdm_sngss7_data.cfg.mtp3Route[x].id != 0) {
-                /* check if the name matches */
-                if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtp3Route[x].name, parm->val)) {
-                    /* now, harvest the required information from the global structure */
-                    sng_isup.mtp3RouteId    = g_ftdm_sngss7_data.cfg.mtp3Route[x].id;
-                    sng_isup.dpc            = g_ftdm_sngss7_data.cfg.mtp3Route[x].dpc;
-                    sng_isup.switchType     = g_ftdm_sngss7_data.cfg.mtp3Route[x].switchType;
-                    sng_cc.switchType       = g_ftdm_sngss7_data.cfg.mtp3Route[x].switchType;
-
-                    /* find the nwID from the mtp3_isup_interface */
-                    int y = 1;
-                    while (g_ftdm_sngss7_data.cfg.mtp3_isup[y].id != 0) {
-                        if (g_ftdm_sngss7_data.cfg.mtp3_isup[y].linkType == g_ftdm_sngss7_data.cfg.mtp3Route[x].linkType &&
-                            g_ftdm_sngss7_data.cfg.mtp3_isup[y].switchType == g_ftdm_sngss7_data.cfg.mtp3Route[x].switchType &&
-                            g_ftdm_sngss7_data.cfg.mtp3_isup[y].ssf == g_ftdm_sngss7_data.cfg.mtp3Route[x].ssf) {
-
-                            /* we have a match so break out of this loop */
-                            break;
-                        }
-                        /* move on to the next one */
-                        y++;
-                    } /* while (g_ftdm_sngss7_data.cfg.mtp3_isup[y].id != 0) */
-
-                    /* check how we exited the last while loop */
-                    if (g_ftdm_sngss7_data.cfg.mtp3_isup[y].id == 0) {
-                        SS7_ERROR("\tFailed to find the nwID for = \"%s\"!\n", parm->val);
-                        return FTDM_FAIL;
-                    } else {
-                        sng_isup.nwId = g_ftdm_sngss7_data.cfg.mtp3_isup[y].nwId;
-                    }
-
-                    break;
-                }
-                x++;
-            } /* while (g_ftdm_sngss7_data.cfg.mtp3Route[x].id != 0) */
-
-            /* check why we exited the while loop ... and react accordingly */
-            if (sng_isup.mtp3RouteId == 0) {
-                SS7_ERROR("\tFailed to find the MTP3 Route = \"%s\"!\n", parm->val);
-                return FTDM_FAIL;
-            } else {
-                SS7_DEBUG("\tFound MTP3 Route = %s\n", parm->val);
-            }
-        /**********************************************************************/
-        } else if (!strcasecmp(parm->var, "ssf")) {
-            if (!strcasecmp(parm->val, "nat")) {
-                sng_isup.ssf = SNG_SSF_NAT;
-                sng_cc.ssf   = SNG_SSF_NAT;
-            } else if (!strcasecmp(parm->val, "int")) {
-                sng_isup.ssf = SNG_SSF_INTER;
-                sng_cc.ssf      = SNG_SSF_INTER;
-            } else {
-                SS7_ERROR("\tFound an invalid ssf of \"%s\"!\n", parm->val);
-                return FTDM_FAIL;
-            }
-        /**********************************************************************/
+       sng_isup_inf_t                  sng_isup;
+       sng_isap_t                              sng_isap;
+       ftdm_conf_parameter_t   *parm = isup_interface->parameters;
+       int                                             num_parms = isup_interface->n_parameters;
+       int                                             i;
+       int                                             linkSetId;
+       int                                             linkId;
+
+       memset(&sng_isup, 0x0, sizeof(sng_isup));
+       memset(&sng_isap, 0x0, sizeof(sng_isap));
+
+       /* confirm that we are looking at an mtp_link */
+       if (strcasecmp(isup_interface->name, "isup_interface")) {
+               SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"isup_interface\"!\n",isup_interface->name);
+               return FTDM_FAIL;
+       } else {
+               SS7_DEBUG("Parsing \"isup_interface\"...\n");
+       }
+
+
+       for (i = 0; i < num_parms; i++) {
+               /* try to match the parameter to what we expect */
+               /**********************************************************************/
+               if (!strcasecmp(parm->var, "name")) {
+                       strcpy((char *)sng_isup.name, parm->val);
+                       SS7_DEBUG("\tFound an \"isup_interface\" named = %s\n", sng_isup.name);
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "spc")) {
+                       sng_isup.spc = atoi(parm->val);
+                       g_ftdm_sngss7_data.cfg.spc = sng_isup.spc;
+                       SS7_DEBUG("\tFound SPC = %d\n", sng_isup.spc);
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "mtp_route")) {
+                       /* find the route by it's name */
+                       int x = 1;
+
+                       while (g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) {
+
+                               /* check if the name matches */
+                               if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtpRoute[x].name, parm->val)) {
+
+                                       /* now, harvest the required information from the global structure */
+                                       sng_isup.mtpRouteId             = g_ftdm_sngss7_data.cfg.mtpRoute[x].id;
+                                       sng_isup.dpc                    = g_ftdm_sngss7_data.cfg.mtpRoute[x].dpc;
+                                       sng_isup.switchType             = g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType;
+                                       sng_isap.switchType             = g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType;
+
+                                       /* find the nwID from the nsap */
+                                       int y = 1;
+                                       while (g_ftdm_sngss7_data.cfg.nsap[y].id != 0) {
+
+                                               if ((g_ftdm_sngss7_data.cfg.nsap[y].linkType == g_ftdm_sngss7_data.cfg.mtpRoute[x].linkType) &&
+                                                       (g_ftdm_sngss7_data.cfg.nsap[y].switchType == g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType) &&
+                                                       (g_ftdm_sngss7_data.cfg.nsap[y].ssf == g_ftdm_sngss7_data.cfg.mtpRoute[x].ssf)) {
+
+                                                       /* we have a match so break out of this loop */
+                                                       break;
+                                               }
+                                               /* move on to the next one */
+                                               y++;
+                                       } /* while (g_ftdm_sngss7_data.cfg.mtp3_isup[y].id != 0) */
+
+                                       /* check how we exited the last while loop */
+                                       if (g_ftdm_sngss7_data.cfg.nsap[y].id == 0) {
+                                               SS7_ERROR("\tFailed to find the nwID for = \"%s\"!\n", parm->val);
+                                               return FTDM_FAIL;
+                                       } else {
+                                               sng_isup.nwId = g_ftdm_sngss7_data.cfg.nsap[y].nwId;
+                                       }
+
+                                       break;
+                               }
+                               x++;
+                       } /* while (g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) */
+
+                       /* check why we exited the while loop ... and react accordingly */
+                       if (sng_isup.mtpRouteId == 0) {
+                               SS7_ERROR("\tFailed to find the MTP3 Route = \"%s\"!\n", parm->val);
+                               return FTDM_FAIL;
+                       } else {
+                               SS7_DEBUG("\tFound MTP3 Route = %s\n", parm->val);
+                       }
+               /**********************************************************************/
+               } else if (!strcasecmp(parm->var, "ssf")) {
+                       if (!strcasecmp(parm->val, "nat")) {
+                               sng_isup.ssf = SSF_NAT;
+                               sng_isap.ssf = SSF_NAT;
+                       } else if (!strcasecmp(parm->val, "int")) {
+                               sng_isup.ssf = SSF_INTL;
+                               sng_isap.ssf = SSF_INTL;
+                       } else {
+                               SS7_ERROR("\tFound an invalid ssf of \"%s\"!\n", parm->val);
+                               return FTDM_FAIL;
+                       }
+               /**********************************************************************/
                } else if (!strcasecmp(parm->var, "license")) {
                /**********************************************************************/
                        strcpy(g_ftdm_sngss7_data.cfg.license, parm->val);
@@ -821,1055 +835,1047 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
                        SS7_DEBUG("\tFound license file = %s\n", g_ftdm_sngss7_data.cfg.license);
                        SS7_DEBUG("\tFound signature file = %s\n", g_ftdm_sngss7_data.cfg.signature);   
                /**********************************************************************/
-        } else {
-            SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
-            return FTDM_FAIL;
+               } else {
+                       SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
+                       return FTDM_FAIL;
 
-        }
+               }
 
-        /* move to the next parameter */
-        parm = parm + 1;
-    }
+               /* move to the next parameter */
+               parm = parm + 1;
+       }
 
-    ftmod_ss7_fill_in_isup_interface(&sng_isup);
+       /* trickle down the SPC to all sub entities */
+       linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].cmbLinkSetId;
+       for (i = 0; i < g_ftdm_sngss7_data.cfg.mtpLinkSet[linkSetId].numLinks; i ++) {
+               linkId = g_ftdm_sngss7_data.cfg.mtpLinkSet[linkSetId].links[i];
+               g_ftdm_sngss7_data.cfg.mtpLink[linkId].mtp3.spc = g_ftdm_sngss7_data.cfg.spc;
+       }
 
-    ftmod_ss7_fill_in_isup_cc_interface(&sng_cc);
+       ftmod_ss7_fill_in_isap(&sng_isap);
 
-    return FTDM_SUCCESS;
-}
+       sng_isup.isap = sng_isap.id;
 
-/******************************************************************************/
-static int ftmod_ss7_fill_in_mtp1_link(sng_mtp1Link_t *mtp1_link)
-{
-    int i;
-
-    /* go through all the existing links and see if we find a match */
-    i = 1;
-    while (g_ftdm_sngss7_data.cfg.mtp1Link[i].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.mtp1Link[i].span == mtp1_link->span &&
-            g_ftdm_sngss7_data.cfg.mtp1Link[i].chan == mtp1_link->chan) {
-
-            /* we have a match so break out of this loop */
-            break;
-        }
-        /* move on to the next one */
-        i++;
-    }
-
-    /* if the id value is 0 that means we didn't find the link */
-    if (g_ftdm_sngss7_data.cfg.mtp1Link[i].id  == 0) {
-        mtp1_link->id = i;
-        SS7_DEBUG("found new mtp1_link on span=%d, chan=%d, id = %d\n", 
-                    mtp1_link->span, 
-                    mtp1_link->chan, 
-                    mtp1_link->id);
-    } else {
-        mtp1_link->id = i;
-        SS7_DEBUG("found existing mtp1_link on span=%d, chan=%d, id = %d\n", 
-                    mtp1_link->span, 
-                    mtp1_link->chan, 
-                    mtp1_link->id);
-    }
-
-    /* fill in the information */
-
-    strcpy((char *)g_ftdm_sngss7_data.cfg.mtp1Link[i].name, (char *)mtp1_link->name);
-
-    g_ftdm_sngss7_data.cfg.mtp1Link[i].id = mtp1_link->id;
-    g_ftdm_sngss7_data.cfg.mtp1Link[i].span = mtp1_link->span;
-    g_ftdm_sngss7_data.cfg.mtp1Link[i].chan = mtp1_link->chan;
-
-    return (mtp1_link->id);
-}
+       ftmod_ss7_fill_in_isup_interface(&sng_isup);
 
-/******************************************************************************/
-static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2Link_t *mtp2_link)
-{
-    /* the mtp2link->spId is also the index value */
-
-    int i = mtp2_link->spId;
-
-    mtp2_link->id = i;
-
-    if (g_ftdm_sngss7_data.cfg.mtp2Link[i].id == 0) {
-        SS7_DEBUG("found new mtp2_link, id is = %d\n", mtp2_link->id);
-    } else {
-        SS7_DEBUG("found existing mtp2_link, id is = %d\n", mtp2_link->id);
-    } 
-
-    strcpy((char *)g_ftdm_sngss7_data.cfg.mtp2Link[i].name, (char *)mtp2_link->name);
-
-    g_ftdm_sngss7_data.cfg.mtp2Link[i].id           = mtp2_link->id;
-    g_ftdm_sngss7_data.cfg.mtp2Link[i].spId         = mtp2_link->spId;
-    g_ftdm_sngss7_data.cfg.mtp2Link[i].linkType     = mtp2_link->linkType;
-    g_ftdm_sngss7_data.cfg.mtp2Link[i].errorType    = mtp2_link->errorType;
-    g_ftdm_sngss7_data.cfg.mtp2Link[i].lssuLength   = mtp2_link->lssuLength;
-
-    if ( mtp2_link->t1 != 0 ) {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t1       = mtp2_link->t1;
-    }else {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t1       = 500;
-    }
-    if ( mtp2_link->t2 != 0 ) {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t2       = mtp2_link->t2;
-    }else {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t2       = 250;
-    }
-    if ( mtp2_link->t3 != 0 ) {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t3       = mtp2_link->t3;
-    }else {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t3       = 20;
-    }
-    if ( mtp2_link->t4n != 0 ) {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t4n      = mtp2_link->t4n;
-    }else {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t4n      = 80;
-    }
-    if ( mtp2_link->t4e != 0 ) {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t4e      = mtp2_link->t4e;
-    }else {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t4e      = 5;
-    }
-    if ( mtp2_link->t5 != 0 ) {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t5       = mtp2_link->t5;
-    }else {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t5       = 1;
-    }
-    if ( mtp2_link->t6 != 0 ) {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t6       = mtp2_link->t6;
-    }else {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t6       = 60;
-    }
-    if ( mtp2_link->t7 != 0 ) {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t7       = mtp2_link->t7;
-    }else {
-        g_ftdm_sngss7_data.cfg.mtp2Link[i].t7       = 20;
-    }
-
-    return(mtp2_link->id);
+       g_ftdm_sngss7_data.cfg.isap[sng_isap.id].spId = sng_isup.id;
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
-static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3Link_t *mtp3_link)
+static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink)
 {
-    int i = mtp3_link->mtp2LinkId;
-
-    mtp3_link->id = i;
-
-    if (g_ftdm_sngss7_data.cfg.mtp3Link[i].id == 0) {
-        SS7_DEBUG("found new mtp3_link, id is = %d\n", mtp3_link->id);
-    } else {
-        SS7_DEBUG("found existing mtp3_link, id is = %d\n", mtp3_link->id);
-    }
-
-    strcpy((char *)g_ftdm_sngss7_data.cfg.mtp3Link[i].name, (char *)mtp3_link->name);
-
-    g_ftdm_sngss7_data.cfg.mtp3Link[i].id           = mtp3_link->id;
-    g_ftdm_sngss7_data.cfg.mtp3Link[i].mtp2LinkId   = mtp3_link->mtp2LinkId;
-    g_ftdm_sngss7_data.cfg.mtp3Link[i].linkSetId    = mtp3_link->linkSetId;
-    g_ftdm_sngss7_data.cfg.mtp3Link[i].priority     = mtp3_link->priority;
-    g_ftdm_sngss7_data.cfg.mtp3Link[i].linkType     = mtp3_link->linkType;
-    g_ftdm_sngss7_data.cfg.mtp3Link[i].switchType   = mtp3_link->switchType;
-    g_ftdm_sngss7_data.cfg.mtp3Link[i].apc          = mtp3_link->apc;
-    g_ftdm_sngss7_data.cfg.mtp3Link[i].ssf          = mtp3_link->ssf;
-    g_ftdm_sngss7_data.cfg.mtp3Link[i].lnkTstSLC    = mtp3_link->lnkTstSLC;
-    if (mtp3_link->t1 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t1       = mtp3_link->t1;
-    } else { 
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t1       = 8;
-    }
-    if (mtp3_link->t2 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t2       = mtp3_link->t2;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t2       = 14;
-    }
-    if (mtp3_link->t3 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t3       = mtp3_link->t3;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t3       = 8;
-    }
-    if (mtp3_link->t4 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t4       = mtp3_link->t4;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t4       = 8;
-    }
-    if (mtp3_link->t5 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t5       = mtp3_link->t5;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t5       = 8;
-    }
-    if (mtp3_link->t7 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t7       = mtp3_link->t7;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t7       = 15;
-    }
-    if (mtp3_link->t12 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t12      = mtp3_link->t12;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t12      = 15;
-    }
-    if (mtp3_link->t13 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t13      = mtp3_link->t13;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t13      = 15;
-    }
-    if (mtp3_link->t14 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t14      = mtp3_link->t14;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t14      = 30;
-    }
-    if (mtp3_link->t17 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t17      = mtp3_link->t17;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t17      = 15;
-    }
-    if (mtp3_link->t22 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t22      = mtp3_link->t22;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t22      = 1800;
-    }
-    if (mtp3_link->t23 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t23      = mtp3_link->t23;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t23      = 1800;
-    }
-    if (mtp3_link->t24 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t24      = mtp3_link->t24;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t24      = 5;
-    }
-    if (mtp3_link->t31 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t31       = mtp3_link->t31;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t31      = 50;
-    }
-    if (mtp3_link->t32 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t32      = mtp3_link->t32;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t32      = 120;
-    }
-    if (mtp3_link->t33 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t33       = mtp3_link->t33;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t33      = 3000;
-    }
-    if (mtp3_link->t34 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t34       = mtp3_link->t34;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].t34      = 600;
-    }
-    if (mtp3_link->tflc != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].tflc       = mtp3_link->tflc;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Link[i].tflc     = 300;
-    }
-
-    return(mtp3_link->id);
+       int i;
+
+       /* go through all the existing links and see if we find a match */
+       i = 1;
+       while (g_ftdm_sngss7_data.cfg.mtpLink[i].id != 0) {
+               if ((g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.span == mtpLink->mtp1.span) &&
+                       (g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.chan == mtpLink->mtp1.chan)) {
+
+                       /* we have a match so break out of this loop */
+                       break;
+               }
+               /* move on to the next one */
+               i++;
+       }
+
+       /* if the id value is 0 that means we didn't find the link */
+       if (g_ftdm_sngss7_data.cfg.mtpLink[i].id  == 0) {
+               mtpLink->id = i;
+               SS7_DEBUG("found new mtpLink on span=%d, chan=%d, id = %d\n", 
+                                       mtpLink->mtp1.span, 
+                                       mtpLink->mtp1.chan, 
+                                       mtpLink->id);
+       } else {
+               mtpLink->id = i;
+               SS7_DEBUG("found existing mtpLink on span=%d, chan=%d, id = %d\n", 
+                                       mtpLink->mtp1.span, 
+                                       mtpLink->mtp1.chan, 
+                                       mtpLink->id);
+       }
+
+       /* fill in the information */
+       strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name);
+
+       g_ftdm_sngss7_data.cfg.mtpLink[i].id                            = mtpLink->id;
+
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.span             = mtpLink->mtp1.span;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.chan             = mtpLink->mtp1.chan;
+
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.linkType         = mtpLink->mtp2.linkType;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.errorType        = mtpLink->mtp2.errorType;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.lssuLength       = mtpLink->mtp2.lssuLength;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.mtp1Id           = mtpLink->id;
+
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.priority         = mtpLink->mtp3.priority;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.linkType         = mtpLink->mtp3.linkType;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.switchType       = mtpLink->mtp3.switchType;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.apc                      = mtpLink->mtp3.apc;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.spc                      = g_ftdm_sngss7_data.cfg.spc;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.ssf                      = mtpLink->mtp3.ssf;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.slc                      = mtpLink->mtp3.slc;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.linkSetId        = mtpLink->mtp3.linkSetId;
+       g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.mtp2Id           = mtpLink->id;
+
+       if ( mtpLink->mtp2.t1 != 0 ) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t1               = mtpLink->mtp2.t1;
+       }else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t1               = 500;
+       }
+       if ( mtpLink->mtp2.t2 != 0 ) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t2               = mtpLink->mtp2.t2;
+       }else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t2               = 250;
+       }
+       if ( mtpLink->mtp2.t3 != 0 ) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t3               = mtpLink->mtp2.t3;
+       }else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t3               = 20;
+       }
+       if ( mtpLink->mtp2.t4n != 0 ) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4n              = mtpLink->mtp2.t4n;
+       }else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4n              = 80;
+       }
+       if ( mtpLink->mtp2.t4e != 0 ) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4e              = mtpLink->mtp2.t4e;
+       }else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4e              = 5;
+       }
+       if ( mtpLink->mtp2.t5 != 0 ) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t5               = mtpLink->mtp2.t5;
+       }else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t5               = 1;
+       }
+       if ( mtpLink->mtp2.t6 != 0 ) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t6               = mtpLink->mtp2.t6;
+       }else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t6               = 60;
+       }
+       if ( mtpLink->mtp2.t7 != 0 ) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t7               = mtpLink->mtp2.t7;
+       }else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t7               = 20;
+       }
+
+       if (mtpLink->mtp3.t1 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t1               = mtpLink->mtp3.t1;
+       } else { 
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t1               = 8;
+       }
+       if (mtpLink->mtp3.t2 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t2               = mtpLink->mtp3.t2;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t2               = 14;
+       }
+       if (mtpLink->mtp3.t3 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t3               = mtpLink->mtp3.t3;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t3               = 8;
+       }
+       if (mtpLink->mtp3.t4 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t4               = mtpLink->mtp3.t4;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t4               = 8;
+       }
+       if (mtpLink->mtp3.t5 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t5               = mtpLink->mtp3.t5;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t5               = 8;
+       }
+       if (mtpLink->mtp3.t7 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t7               = mtpLink->mtp3.t7;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t7               = 15;
+       }
+       if (mtpLink->mtp3.t12 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t12              = mtpLink->mtp3.t12;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t12              = 15;
+       }
+       if (mtpLink->mtp3.t13 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t13              = mtpLink->mtp3.t13;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t13              = 15;
+       }
+       if (mtpLink->mtp3.t14 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t14              = mtpLink->mtp3.t14;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t14              = 30;
+       }
+       if (mtpLink->mtp3.t17 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t17              = mtpLink->mtp3.t17;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t17              = 15;
+       }
+       if (mtpLink->mtp3.t22 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t22              = mtpLink->mtp3.t22;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t22              = 1800;
+       }
+       if (mtpLink->mtp3.t23 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t23              = mtpLink->mtp3.t23;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t23              = 1800;
+       }
+       if (mtpLink->mtp3.t24 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t24              = mtpLink->mtp3.t24;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t24              = 5;
+       }
+       if (mtpLink->mtp3.t31 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t31              = mtpLink->mtp3.t31;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t31              = 50;
+       }
+       if (mtpLink->mtp3.t32 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t32              = mtpLink->mtp3.t32;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t32              = 120;
+       }
+       if (mtpLink->mtp3.t33 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t33              = mtpLink->mtp3.t33;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t33              = 3000;
+       }
+       if (mtpLink->mtp3.t34 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t34              = mtpLink->mtp3.t34;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t34              = 600;
+       }
+       if (mtpLink->mtp3.tflc != 0) {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.tflc             = mtpLink->mtp3.tflc;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.tflc             = 300;
+       }
+       return (mtpLink->id);
 }
 
+
 /******************************************************************************/
-static int ftmod_ss7_fill_in_mtp3_linkset(sng_mtp3LinkSet_t *mtp3_linkset)
+static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet)
 {
-    int count;
-    int i = mtp3_linkset->id;
+       int     count;
+       int     i = mtpLinkSet->id;
 
-    strcpy((char *)g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].name, (char *)mtp3_linkset->name);
+       strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name);
 
-    g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].id          = mtp3_linkset->id;
-    g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].apc         = mtp3_linkset->apc;
-    g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].minActive   = mtp3_linkset->minActive;
-    g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].numLinks    = mtp3_linkset->numLinks;
+       g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id                 = mtpLinkSet->id;
+       g_ftdm_sngss7_data.cfg.mtpLinkSet[i].apc                = mtpLinkSet->apc;
+       g_ftdm_sngss7_data.cfg.mtpLinkSet[i].linkType   = g_ftdm_sngss7_data.cfg.mtpLink[1].mtp3.linkType; /* KONRAD FIX ME */
+       g_ftdm_sngss7_data.cfg.mtpLinkSet[i].minActive  = mtpLinkSet->minActive;
+       g_ftdm_sngss7_data.cfg.mtpLinkSet[i].numLinks   = mtpLinkSet->numLinks;
 
-    for (count = 0; count < mtp3_linkset->numLinks; count++) {
-        g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].links[count]    = mtp3_linkset->links[count];
-    }
+       for (count = 0; count < mtpLinkSet->numLinks; count++) {
+               g_ftdm_sngss7_data.cfg.mtpLinkSet[i].links[count]       = mtpLinkSet->links[count];
+       }
 
-    return 0;
+       return 0;
 }
 
 /******************************************************************************/
-static int ftmod_ss7_fill_in_mtp3_route(sng_mtp3Route_t *mtp3_route)
+static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
 {
-    int i;
-
-    /* go through all the existing routes and see if we find a match */
-    i = 1;
-    while (g_ftdm_sngss7_data.cfg.mtp3Route[i].id != 0) {
-            if (g_ftdm_sngss7_data.cfg.mtp3Route[i].dpc == mtp3_route->dpc) {
-
-            /* we have a match so break out of this loop */
-            break;
-        }
-        /* move on to the next one */
-        i++;
-    }
-
-    if (g_ftdm_sngss7_data.cfg.mtp3Route[i].id == 0) {
-        mtp3_route->id = i;
-        SS7_DEBUG("found new mtp3_route, id is = %d\n", mtp3_route->id);
-    } else {
-        mtp3_route->id = i;
-        SS7_DEBUG("found existing mtp3_route, id is = %d\n", mtp3_route->id);
-    }
-
-    strcpy((char *)g_ftdm_sngss7_data.cfg.mtp3Route[i].name, (char *)mtp3_route->name);
-
-    g_ftdm_sngss7_data.cfg.mtp3Route[i].id            = mtp3_route->id;
-    g_ftdm_sngss7_data.cfg.mtp3Route[i].dpc           = mtp3_route->dpc;
-    g_ftdm_sngss7_data.cfg.mtp3Route[i].linkType      = mtp3_route->linkType;
-    g_ftdm_sngss7_data.cfg.mtp3Route[i].switchType    = mtp3_route->switchType;
-    g_ftdm_sngss7_data.cfg.mtp3Route[i].cmbLinkSetId  = 1; /* mtp3_route->cmbLinkSetId;*/
-    g_ftdm_sngss7_data.cfg.mtp3Route[i].isSTP         = mtp3_route->isSTP;
-    g_ftdm_sngss7_data.cfg.mtp3Route[i].ssf           = mtp3_route->ssf;
-    if (mtp3_route->t6 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t6        = mtp3_route->t6;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t6        = 8;
-    }
-    if (mtp3_route->t8 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t8        = mtp3_route->t8;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t8        = 12;
-    }
-    if (mtp3_route->t10 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t10        = mtp3_route->t10;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t10       = 300;
-    }
-    if (mtp3_route->t11 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t11        = mtp3_route->t11;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t11       = 300;
-    }
-    if (mtp3_route->t15 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t15        = mtp3_route->t15;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t15       = 30;
-    }
-    if (mtp3_route->t16 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t16        = mtp3_route->t16;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t16       = 20;
-    }
-    if (mtp3_route->t18 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t18        = mtp3_route->t18;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t18       = 200;
-    }
-    if (mtp3_route->t19 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t19        = mtp3_route->t19;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t19       = 690;
-    }
-    if (mtp3_route->t21 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t21        = mtp3_route->t21;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t21       = 650; 
-    }
-    if (mtp3_route->t25 != 0) {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t25        = mtp3_route->t25;
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3Route[i].t25       = 100;
-    }
-
-    return 0;
+       int i;
+
+       /* go through all the existing routes and see if we find a match */
+       i = 1;
+       while (g_ftdm_sngss7_data.cfg.mtpRoute[i].id != 0) {
+                       if (g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc == mtp3_route->dpc) {
+
+                       /* we have a match so break out of this loop */
+                       break;
+               }
+               /* move on to the next one */
+               i++;
+       }
+
+       if (g_ftdm_sngss7_data.cfg.mtpRoute[i].id == 0) {
+               mtp3_route->id = i;
+               SS7_DEBUG("found new mtp3_route, id is = %d\n", mtp3_route->id);
+       } else {
+               mtp3_route->id = i;
+               SS7_DEBUG("found existing mtp3_route, id is = %d\n", mtp3_route->id);
+       }
+
+       strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name);
+
+       g_ftdm_sngss7_data.cfg.mtpRoute[i].id                   = mtp3_route->id;
+       g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc                  = mtp3_route->dpc;
+       g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType             = mtp3_route->linkType;
+       g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType   = mtp3_route->switchType;
+       g_ftdm_sngss7_data.cfg.mtpRoute[i].cmbLinkSetId = 1; /* mtp3_route->cmbLinkSetId;*/
+       g_ftdm_sngss7_data.cfg.mtpRoute[i].isSTP                = mtp3_route->isSTP;
+       g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf                  = mtp3_route->ssf;
+       if (mtp3_route->t6 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t6           = mtp3_route->t6;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t6           = 8;
+       }
+       if (mtp3_route->t8 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t8           = mtp3_route->t8;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t8           = 12;
+       }
+       if (mtp3_route->t10 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t10          = mtp3_route->t10;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t10     = 300;
+       }
+       if (mtp3_route->t11 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t11          = mtp3_route->t11;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t11     = 300;
+       }
+       if (mtp3_route->t15 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t15          = mtp3_route->t15;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t15     = 30;
+       }
+       if (mtp3_route->t16 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t16          = mtp3_route->t16;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t16     = 20;
+       }
+       if (mtp3_route->t18 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t18          = mtp3_route->t18;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t18     = 200;
+       }
+       if (mtp3_route->t19 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t19          = mtp3_route->t19;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t19     = 690;
+       }
+       if (mtp3_route->t21 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t21          = mtp3_route->t21;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t21     = 650; 
+       }
+       if (mtp3_route->t25 != 0) {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t25          = mtp3_route->t25;
+       } else {
+               g_ftdm_sngss7_data.cfg.mtpRoute[i].t25     = 100;
+       }
+
+       return 0;
 }
 
 /******************************************************************************/
-static int ftmod_ss7_fill_in_mtp3_isup_interface(sng_mtp3Route_t *mtp3_route)
+static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route)
 {
-
-    int i;
-
-    /* go through all the existing interfaces and see if we find a match */
-    i = 1;
-    while (g_ftdm_sngss7_data.cfg.mtp3_isup[i].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.mtp3_isup[i].linkType == mtp3_route->linkType &&
-            g_ftdm_sngss7_data.cfg.mtp3_isup[i].switchType == mtp3_route->switchType &&
-            g_ftdm_sngss7_data.cfg.mtp3_isup[i].ssf == mtp3_route->ssf) {
-
-            /* we have a match so break out of this loop */
-            break;
-        }
-        /* move on to the next one */
-        i++;
-    }
-
-    if (g_ftdm_sngss7_data.cfg.mtp3_isup[i].id == 0) {
-        g_ftdm_sngss7_data.cfg.mtp3_isup[i].id = i;
-        SS7_DEBUG("found new mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.mtp3_isup[i].id);
-    } else {
-        g_ftdm_sngss7_data.cfg.mtp3_isup[i].id = i;
-        SS7_DEBUG("found existing mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.mtp3_isup[i].id);
-    }
-
-    g_ftdm_sngss7_data.cfg.mtp3_isup[i].nwId          = g_ftdm_sngss7_data.cfg.mtp3_isup[i].id;
-    g_ftdm_sngss7_data.cfg.mtp3_isup[i].linkType      = mtp3_route->linkType;
-    g_ftdm_sngss7_data.cfg.mtp3_isup[i].switchType    = mtp3_route->switchType;
-    g_ftdm_sngss7_data.cfg.mtp3_isup[i].ssf           = mtp3_route->ssf;
-
-    return 0;
+       int i;
+
+       /* go through all the existing interfaces and see if we find a match */
+       i = 1;
+       while (g_ftdm_sngss7_data.cfg.nsap[i].id != 0) {
+               if ((g_ftdm_sngss7_data.cfg.nsap[i].linkType == mtp3_route->linkType) &&
+                       (g_ftdm_sngss7_data.cfg.nsap[i].switchType == mtp3_route->switchType) &&
+                       (g_ftdm_sngss7_data.cfg.nsap[i].ssf == mtp3_route->ssf)) {
+
+                       /* we have a match so break out of this loop */
+                       break;
+               }
+               /* move on to the next one */
+               i++;
+       }
+
+       if (g_ftdm_sngss7_data.cfg.nsap[i].id == 0) {
+               g_ftdm_sngss7_data.cfg.nsap[i].id = i;
+               SS7_DEBUG("found new mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.nsap[i].id);
+       } else {
+               g_ftdm_sngss7_data.cfg.nsap[i].id = i;
+               SS7_DEBUG("found existing mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.nsap[i].id);
+       }
+       
+       g_ftdm_sngss7_data.cfg.nsap[i].spId                     = g_ftdm_sngss7_data.cfg.nsap[i].id;
+       g_ftdm_sngss7_data.cfg.nsap[i].suId                     = g_ftdm_sngss7_data.cfg.nsap[i].id;
+       g_ftdm_sngss7_data.cfg.nsap[i].nwId                     = g_ftdm_sngss7_data.cfg.nsap[i].id;
+       g_ftdm_sngss7_data.cfg.nsap[i].linkType         = mtp3_route->linkType;
+       g_ftdm_sngss7_data.cfg.nsap[i].switchType       = mtp3_route->switchType;
+       g_ftdm_sngss7_data.cfg.nsap[i].ssf                      = mtp3_route->ssf;
+
+       return 0;
 }
 
 /******************************************************************************/
-static int ftmod_ss7_fill_in_isup_interface(sng_isupInterface_t *sng_isup)
+static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
 {
-
-    int i;
-
-    /* go through all the existing interfaces and see if we find a match */
-    i = 1;
-    while (g_ftdm_sngss7_data.cfg.isupInterface[i].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.isupInterface[i].nwId == sng_isup->nwId) {
-
-            /* we have a match so break out of this loop */
-            break;
-        }
-        /* move on to the next one */
-        i++;
-    }
-
-    if (g_ftdm_sngss7_data.cfg.isupInterface[i].id == 0) {
-        sng_isup->id = i;
-        SS7_DEBUG("found new isup interface, id is = %d\n", sng_isup->id);
-    } else {
-        sng_isup->id = i;
-        SS7_DEBUG("found existing isup interface, id is = %d\n", sng_isup->id);
-    }
-
-    strcpy((char *)g_ftdm_sngss7_data.cfg.isupInterface[i].name, (char *)sng_isup->name);
-
-    g_ftdm_sngss7_data.cfg.isupInterface[i].id             = sng_isup->id;
-    g_ftdm_sngss7_data.cfg.isupInterface[i].mtp3RouteId    = sng_isup->mtp3RouteId;
-    g_ftdm_sngss7_data.cfg.isupInterface[i].nwId           = sng_isup->nwId;
-    g_ftdm_sngss7_data.cfg.isupInterface[i].dpc            = sng_isup->dpc;
-    g_ftdm_sngss7_data.cfg.isupInterface[i].switchType     = sng_isup->switchType;
-    g_ftdm_sngss7_data.cfg.isupInterface[i].ssf            = sng_isup->ssf;
-    if (sng_isup->t4 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t4         = sng_isup->t4;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t4         = 3000;
-    }
-    if (sng_isup->t10 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t10        = sng_isup->t10;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t10        = 50;
-    }
-    if (sng_isup->t11 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t11        = sng_isup->t11;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t11        = 170;
-    }
-    if (sng_isup->t18 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t18        = sng_isup->t18;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t18        = 300;
-    }
-    if (sng_isup->t19 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t19        = sng_isup->t19;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t19        = 3000;
-    }
-    if (sng_isup->t20 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t20        = sng_isup->t20;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t20        = 300;
-    }
-    if (sng_isup->t21 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t21        = sng_isup->t21;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t21        = 3000;
-    }
-    if (sng_isup->t22 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t22        = sng_isup->t22;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t22        = 300;
-    }
-    if (sng_isup->t23 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t23        = sng_isup->t23;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t23        = 3000;
-    }
-    if (sng_isup->t24 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t24        = sng_isup->t24;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t24        = 10;
-    }
-    if (sng_isup->t25 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t25        = sng_isup->t25;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t25        = 20;
-    }
-    if (sng_isup->t26 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t26        = sng_isup->t26;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t26        = 600;
-    }
-    if (sng_isup->t28 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t28        = sng_isup->t28;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t28        = 100;
-    }
-    if (sng_isup->t29 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t29        = sng_isup->t29;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t29        = 6;
-    }
-    if (sng_isup->t30 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t30        = sng_isup->t30;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t30        = 50;
-    }
-    if (sng_isup->t32 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t32        = sng_isup->t32;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t32        = 30;
-    }
-    if (sng_isup->t35 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t35        = sng_isup->t35;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t35        = 170;
-    }
-    if (sng_isup->t37 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t37        = sng_isup->t37;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t37        = 20;
-    }
-    if (sng_isup->t38 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t38        = sng_isup->t38;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t38        = 1200;
-    }
-    if (sng_isup->t39 != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t39        = sng_isup->t39;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].t39        = 300;
-    }
-    if (sng_isup->tfgr != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].tfgr       = sng_isup->tfgr;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].tfgr       = 50;
-    }
-    if (sng_isup->tpause != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].tpause     = sng_isup->tpause;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].tpause     = 150;
-    }
-    if (sng_isup->tstaenq != 0) {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].tstaenq    = sng_isup->tstaenq;
-    } else {
-        g_ftdm_sngss7_data.cfg.isupInterface[i].tstaenq    = 5000;
-    }
-
-    return 0;
+       int i;
+
+       /* go through all the existing interfaces and see if we find a match */
+       i = 1;
+       while (g_ftdm_sngss7_data.cfg.isupIntf[i].id != 0) {
+               if (g_ftdm_sngss7_data.cfg.isupIntf[i].nwId == sng_isup->nwId) {
+
+                       /* we have a match so break out of this loop */
+                       break;
+               }
+               /* move on to the next one */
+               i++;
+       }
+
+       if (g_ftdm_sngss7_data.cfg.isupIntf[i].id == 0) {
+               sng_isup->id = i;
+               SS7_DEBUG("found new isup interface, id is = %d\n", sng_isup->id);
+       } else {
+               sng_isup->id = i;
+               SS7_DEBUG("found existing isup interface, id is = %d\n", sng_isup->id);
+       }
+
+       strcpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name);
+
+       g_ftdm_sngss7_data.cfg.isupIntf[i].id                   = sng_isup->id;
+       g_ftdm_sngss7_data.cfg.isupIntf[i].mtpRouteId   = sng_isup->mtpRouteId;
+       g_ftdm_sngss7_data.cfg.isupIntf[i].nwId                 = sng_isup->nwId;
+       g_ftdm_sngss7_data.cfg.isupIntf[i].dpc                  = sng_isup->dpc;
+       g_ftdm_sngss7_data.cfg.isupIntf[i].spc                  = sng_isup->spc;
+       g_ftdm_sngss7_data.cfg.isupIntf[i].switchType   = sng_isup->switchType;
+       g_ftdm_sngss7_data.cfg.isupIntf[i].ssf                  = sng_isup->ssf;
+       g_ftdm_sngss7_data.cfg.isupIntf[i].isap                 = sng_isup->isap;
+
+       if (sng_isup->t4 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t4           = sng_isup->t4;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t4           = 3000;
+       }
+       if (sng_isup->t10 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t10          = sng_isup->t10;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t10          = 50;
+       }
+       if (sng_isup->t11 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t11          = sng_isup->t11;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t11          = 170;
+       }
+       if (sng_isup->t18 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t18          = sng_isup->t18;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t18          = 300;
+       }
+       if (sng_isup->t19 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t19          = sng_isup->t19;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t19          = 3000;
+       }
+       if (sng_isup->t20 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t20          = sng_isup->t20;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t20          = 300;
+       }
+       if (sng_isup->t21 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t21          = sng_isup->t21;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t21          = 3000;
+       }
+       if (sng_isup->t22 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t22          = sng_isup->t22;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t22          = 300;
+       }
+       if (sng_isup->t23 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t23          = sng_isup->t23;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t23          = 3000;
+       }
+       if (sng_isup->t24 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t24          = sng_isup->t24;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t24          = 10;
+       }
+       if (sng_isup->t25 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t25          = sng_isup->t25;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t25          = 20;
+       }
+       if (sng_isup->t26 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t26          = sng_isup->t26;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t26          = 600;
+       }
+       if (sng_isup->t28 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t28          = sng_isup->t28;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t28          = 100;
+       }
+       if (sng_isup->t29 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t29          = sng_isup->t29;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t29          = 6;
+       }
+       if (sng_isup->t30 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t30          = sng_isup->t30;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t30          = 50;
+       }
+       if (sng_isup->t32 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t32          = sng_isup->t32;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t32          = 30;
+       }
+       if (sng_isup->t35 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t35          = sng_isup->t35;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t35          = 170;
+       }
+       if (sng_isup->t37 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t37          = sng_isup->t37;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t37          = 20;
+       }
+       if (sng_isup->t38 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t38          = sng_isup->t38;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t38          = 1200;
+       }
+       if (sng_isup->t39 != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t39          = sng_isup->t39;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].t39          = 300;
+       }
+       if (sng_isup->tfgr != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].tfgr         = sng_isup->tfgr;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].tfgr         = 50;
+       }
+       if (sng_isup->tpause != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].tpause       = sng_isup->tpause;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].tpause       = 150;
+       }
+       if (sng_isup->tstaenq != 0) {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].tstaenq      = sng_isup->tstaenq;
+       } else {
+               g_ftdm_sngss7_data.cfg.isupIntf[i].tstaenq      = 5000;
+       }
+
+       return 0;
 }
 
 /******************************************************************************/
-static int ftmod_ss7_fill_in_isup_cc_interface(sng_isup_cc_t *sng_cc)
+static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap)
 {
-
-    int i;
-
-    /* go through all the existing interfaces and see if we find a match */
-    i = 1;
-    while (g_ftdm_sngss7_data.cfg.isup_cc[i].id != 0) {
-        if (g_ftdm_sngss7_data.cfg.isup_cc[i].switchType == sng_cc->switchType) {
-
-            /* we have a match so break out of this loop */
-            break;
-        }
-        /* move on to the next one */
-        i++;
-    }
-
-    if (g_ftdm_sngss7_data.cfg.isup_cc[i].id == 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].id = i;
-        SS7_DEBUG("found new isup to cc interface, id is = %d\n", g_ftdm_sngss7_data.cfg.isup_cc[i].id);
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].id = i;
-        SS7_DEBUG("found existing isup to cc interface, id is = %d\n", g_ftdm_sngss7_data.cfg.isup_cc[i].id);
-    }
-
-    SS7_ERROR("KONRAD -> you're hard coding the CC id....fix me!!!!\n");
-    g_ftdm_sngss7_data.cfg.isup_cc[i].ccId          = 1; /*KONRAD FIX ME */
-    g_ftdm_sngss7_data.cfg.isup_cc[i].switchType    = sng_cc->switchType;
-    g_ftdm_sngss7_data.cfg.isup_cc[i].ssf           = sng_cc->ssf;
-    if (sng_cc->t1 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t1        = sng_cc->t1;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t1        = 200;
-    }
-    if (sng_cc->t2 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t2        = sng_cc->t2;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t2        = 1800;
-    }
-    if (sng_cc->t5 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t5        = sng_cc->t5;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t5        = 3000;
-    }
-    if (sng_cc->t6 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t6        = sng_cc->t6;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t6        = 200;
-    }
-    if (sng_cc->t7 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t7        = sng_cc->t7;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t7        = 250;
-    }
-    if (sng_cc->t8 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t8        = sng_cc->t8;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t8        = 120;
-    }
-    if (sng_cc->t9 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t9        = sng_cc->t9;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t9        = 1800;
-    }
-    if (sng_cc->t27 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t27       = sng_cc->t27;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t27       = 2400;
-    }
-    if (sng_cc->t31 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t31       = sng_cc->t31;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t31       = 3650;
-    }
-    if (sng_cc->t33 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t33       = sng_cc->t33;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t33       = 120;
-    }
-    if (sng_cc->t34 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t34       = sng_cc->t34;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t34       = 40;
-    }
-    if (sng_cc->t36 != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t36       = sng_cc->t36;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].t36       = 120;
-    }
-    if (sng_cc->tccr != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tccr      = sng_cc->tccr;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tccr      = 200;
-    }
-    if (sng_cc->tccrt != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tccrt     = sng_cc->tccrt;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tccrt     = 20;
-    }
-    if (sng_cc->tex != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tex       = sng_cc->tex;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tex       = 10;
-    }
-    if (sng_cc->tcrm != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tcrm      = sng_cc->tcrm;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tcrm      = 30;
-    }
-    if (sng_cc->tcra != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tcra      = sng_cc->tcra;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tcra      = 100;
-    }
-    if (sng_cc->tect != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tect      = sng_cc->tect;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tect      = 10;
-    }
-    if (sng_cc->trelrsp != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].trelrsp   = sng_cc->trelrsp;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].trelrsp   = 10;
-    }
-    if (sng_cc->tfnlrelrsp != 0) {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tfnlrelrsp= sng_cc->tfnlrelrsp;
-    } else {
-        g_ftdm_sngss7_data.cfg.isup_cc[i].tfnlrelrsp= 10;
-    }
-
-    return 0;
+       int i;
+
+       /* go through all the existing interfaces and see if we find a match */
+       i = 1;
+       while (g_ftdm_sngss7_data.cfg.isap[i].id != 0) {
+               if (g_ftdm_sngss7_data.cfg.isap[i].switchType == sng_isap->switchType) {
+
+                       /* we have a match so break out of this loop */
+                       break;
+               }
+               /* move on to the next one */
+               i++;
+       }
+
+       if (g_ftdm_sngss7_data.cfg.isap[i].id == 0) {
+               sng_isap->id = i;
+               SS7_DEBUG("found new isup to cc interface, id is = %d\n", g_ftdm_sngss7_data.cfg.isap[i].id);
+       } else {
+               sng_isap->id = i;
+               SS7_DEBUG("found existing isup to cc interface, id is = %d\n", g_ftdm_sngss7_data.cfg.isap[i].id);
+       }
+
+       g_ftdm_sngss7_data.cfg.isap[i].id                       = sng_isap->id;
+       g_ftdm_sngss7_data.cfg.isap[i].suId                     = 1; /*KONRAD FIX ME */
+       g_ftdm_sngss7_data.cfg.isap[i].switchType       = sng_isap->switchType;
+       g_ftdm_sngss7_data.cfg.isap[i].ssf                      = sng_isap->ssf;
+
+       if (sng_isap->t1 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t1               = sng_isap->t1;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t1               = 200;
+       }
+       if (sng_isap->t2 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t2               = sng_isap->t2;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t2               = 1800;
+       }
+       if (sng_isap->t5 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t5               = sng_isap->t5;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t5               = 3000;
+       }
+       if (sng_isap->t6 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t6               = sng_isap->t6;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t6               = 200;
+       }
+       if (sng_isap->t7 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t7               = sng_isap->t7;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t7               = 250;
+       }
+       if (sng_isap->t8 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t8               = sng_isap->t8;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t8               = 120;
+       }
+       if (sng_isap->t9 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t9               = sng_isap->t9;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t9               = 1800;
+       }
+       if (sng_isap->t27 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t27              = sng_isap->t27;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t27              = 2400;
+       }
+       if (sng_isap->t31 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t31              = sng_isap->t31;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t31              = 3650;
+       }
+       if (sng_isap->t33 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t33              = sng_isap->t33;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t33              = 120;
+       }
+       if (sng_isap->t34 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t34              = sng_isap->t34;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t34              = 40;
+       }
+       if (sng_isap->t36 != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].t36              = sng_isap->t36;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].t36              = 120;
+       }
+       if (sng_isap->tccr != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].tccr             = sng_isap->tccr;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].tccr             = 200;
+       }
+       if (sng_isap->tccrt != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].tccrt    = sng_isap->tccrt;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].tccrt    = 20;
+       }
+       if (sng_isap->tex != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].tex              = sng_isap->tex;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].tex              = 10;
+       }
+       if (sng_isap->tcrm != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].tcrm             = sng_isap->tcrm;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].tcrm             = 30;
+       }
+       if (sng_isap->tcra != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].tcra             = sng_isap->tcra;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].tcra             = 100;
+       }
+       if (sng_isap->tect != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].tect             = sng_isap->tect;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].tect             = 10;
+       }
+       if (sng_isap->trelrsp != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].trelrsp  = sng_isap->trelrsp;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].trelrsp  = 10;
+       }
+       if (sng_isap->tfnlrelrsp != 0) {
+               g_ftdm_sngss7_data.cfg.isap[i].tfnlrelrsp       = sng_isap->tfnlrelrsp;
+       } else {
+               g_ftdm_sngss7_data.cfg.isap[i].tfnlrelrsp       = 10;
+       }
+
+       return 0;
 }
 
 /******************************************************************************/
 static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, int ssf)
 {
 
-    if (g_ftdm_sngss7_data.cfg.mtp3Route[0].dpc == 0){
-        SS7_DEBUG("found new mtp3 self route\n");
-    } else if (g_ftdm_sngss7_data.cfg.mtp3Route[0].dpc == spc) {
-        SS7_DEBUG("found existing mtp3 self route\n");
-        return FTDM_SUCCESS;
-    } else {
-        SS7_ERROR("found new mtp3 self route but it does not much the route already configured\n");
-        return FTDM_FAIL;
-    }
-
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].id            = 0;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].dpc           = spc;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].linkType      = linkType;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].switchType    = switchType;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].cmbLinkSetId  = 0;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].isSTP         = 0;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].ssf           = 0;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].t6        = 8;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].t8        = 12;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].t10       = 300;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].t11       = 300;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].t15       = 30;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].t16       = 20;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].t18       = 200;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].t19       = 690;
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].t21       = 650; 
-    g_ftdm_sngss7_data.cfg.mtp3Route[0].t25        = 100;
-
-
-    return 0;
+       if (g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc == 0){
+               SS7_DEBUG("found new mtp3 self route\n");
+       } else if (g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc == spc) {
+               SS7_DEBUG("found existing mtp3 self route\n");
+               return FTDM_SUCCESS;
+       } else {
+               SS7_ERROR("found new mtp3 self route but it does not much the route already configured\n");
+               return FTDM_FAIL;
+       }
+
+       strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route");
+
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].id                   = 0;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc                  = spc;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].linkType             = linkType;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].switchType   = switchType;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].cmbLinkSetId = 0;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].isSTP                = 0;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].ssf                  = ssf;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].t6                   = 8;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].t8                   = 12;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].t10                  = 300;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].t11                  = 300;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].t15                  = 30;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].t16                  = 20;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].t18                  = 200;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].t19                  = 690;
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].t21                  = 650; 
+       g_ftdm_sngss7_data.cfg.mtpRoute[0].t25                  = 100;
+
+       return 0;
 }
 
 /******************************************************************************/
 static int ftmod_ss7_fill_in_circuits(char *ch_map, int cicbase, int typeCntrl, int isup_id, ftdm_span_t *span)
 {
-    sngss7_chan_data_t  *ss7_info = NULL;
-    ftdm_channel_t      *ftdmchan = NULL;
-    sng_timeslot_t      timeslot;
-    int                 count;
-    int                 i;
-    int                 x;
-
-    count = 1;
-
-    while (ch_map[0] != '\0') {
-
-         /* pull out the next timeslot */
-        if (ftmod_ss7_next_timeslot(ch_map, &timeslot)) {
-            SS7_ERROR("Failed to parse the channel map!\n");
-            return FTDM_FAIL;
-        }
-
-        if ((timeslot.siglink) || (timeslot.gap)) {
-            /* try to find the channel in the circuits structure*/
-            x = 1;
-            while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) {
-                if ((g_ftdm_sngss7_data.cfg.isupCircuit[x].chan == count) &&
-                    (g_ftdm_sngss7_data.cfg.isupCircuit[x].span == span->channels[1]->physical_span_id)) {
-
-                    SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is already exists...id=%d\n",
-                                span->channels[1]->physical_span_id,
-                                count,
-                                x);
-
-                    /* we have a match so this circuit already exists in the structure */
-                    break;
-                }
-                /* move to the next circuit */
-                x++;
-            } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) */
-
-                       /* check why we exited the while loop */
-            if (g_ftdm_sngss7_data.cfg.isupCircuit[x].id == 0) {
-                SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n",
-                span->channels[1]->physical_span_id,
-                count,
-                x);
-
-                /* prepare the global info sturcture */
-                ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t));
-                ss7_info->ftdmchan = NULL;
-                ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCircuit[x];
-
-                /* circuit is new so fill in the needed information */
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].id          = x;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].span        = span->channels[1]->physical_span_id;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].chan        = count;
-                if (timeslot.siglink) {
-                    g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink     = 1;
-                } else {
-                    g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink     = 0;
-                }
-                if (timeslot.channel) {
-                    g_ftdm_sngss7_data.cfg.isupCircuit[x].hole        = 0;
-                    g_ftdm_sngss7_data.cfg.isupCircuit[x].cic         = cicbase;
-                    cicbase++;
-                } else {
-                    g_ftdm_sngss7_data.cfg.isupCircuit[x].hole        = 1;
-                    g_ftdm_sngss7_data.cfg.isupCircuit[x].cic         = 0;
-                }
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].infId       = isup_id;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].typeCntrl   = typeCntrl;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t3          = 1200;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t12         = 300;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t13         = 3000;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t14         = 300;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t15         = 3000;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t16         = 300;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t17         = 3000;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].tval        = 10;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].obj         = ss7_info;
-
-            } /* if (g_ftdm_sngss7_data.cfg.isupCircuit[x].id == 0) */
-        } else { /* if ((timeslot.siglink) || (timeslot.gap)) */
-            /* find the ftdm the channel structure for this channel*/
-            i = 1;
-            while (span->channels[i] != NULL) {
-                if (span->channels[i]->physical_chan_id == timeslot.channel) {
-                    break;
-                }
-                i++;
-            } /* while (span->channels[i] != NULL) */
-
-            if (span->channels[i] == NULL) {
-                /* we weren't able to find the channel in the ftdm channels */
-                SS7_ERROR("Unable to find the requested channel %d in the FreeTDM channels!\n", timeslot.channel);
-                return FTDM_FAIL;
-            } else {
-                ftdmchan = span->channels[i];
-            }
-
-            /* try to find a match for the physical span and chan */
-            x = 1;
-            while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) {
-                if ((g_ftdm_sngss7_data.cfg.isupCircuit[x].chan == ftdmchan->physical_chan_id) 
-                    && (g_ftdm_sngss7_data.cfg.isupCircuit[x].span == ftdmchan->physical_span_id)) {
-
-                    /* we have a match so this circuit already exists in the structure */
-                    break;
-                }
-                /* move to the next circuit */
-                x++;
-            } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) */
-
-            /* check why we exited the while loop */
-            if (g_ftdm_sngss7_data.cfg.isupCircuit[x].id == 0) {
-                SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n",
-                ftdmchan->physical_span_id,
-                ftdmchan->physical_chan_id,
-                x);
-
-                /* prepare the global info sturcture */
-                ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t));
-                ss7_info->ftdmchan = ftdmchan;
-                ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCircuit[x];
-                ftdmchan->call_data = ss7_info;
-
-                /* prepare the timer structures */
-                ss7_info->t35.sched         = sngss7_sched;
-                ss7_info->t35.counter       = 1;
-                ss7_info->t35.beat          = g_ftdm_sngss7_data.cfg.isupInterface[isup_id].t35*100; /* beat is in ms, t35 is in 100ms */
-                ss7_info->t35.callback      = handle_isup_t35;
-                ss7_info->t35.sngss7_info   = ss7_info;
-
-                /* circuit is new so fill in the needed information */
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].id          = x;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].span        = ftdmchan->physical_span_id;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].chan        = ftdmchan->physical_chan_id;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink     = 0;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].hole        = 0;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].cic         = cicbase;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].infId       = isup_id;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].typeCntrl   = typeCntrl;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t3          = 1200;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t12         = 300;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t13         = 3000;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t14         = 300;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t15         = 3000;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t16         = 300;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].t17         = 3000;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].tval        = 10;
-                g_ftdm_sngss7_data.cfg.isupCircuit[x].obj         = ss7_info;
-
-                /* increment the cicbase */
-                cicbase++;
-            } else { /* if (g_ftdm_sngss7_data.cfg.isupCircuit[x].id == 0) */
-                SS7_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n",
-                                    ftdmchan->physical_span_id,
-                                    ftdmchan->physical_chan_id,
-                                    x);
-
-                /* for now make sure ss7_info is set to null */
-                ss7_info = NULL;
-
-                /* KONRAD FIX ME -> confirm that it is the same circuit */
-            }  /* if (g_ftdm_sngss7_data.cfg.isupCircuit[x].id == 0) */
-
-            /* increment the span channel count */
-            count++;
-        } /* if ((timeslot.siglink) || (timeslot.gap)) */
-
-        if (ss7_info == NULL) {
-            SS7_ERROR("KONRAD -> circuit was not configured !\n");
-            return FTDM_FAIL;
-        }
-
-        if (ss7_info->ftdmchan == NULL) {
-            SS7_INFO("Added span = %d, chan = %d, cic = %d, FTDM chan = %d, ISUP cirId = %d\n",
-                        g_ftdm_sngss7_data.cfg.isupCircuit[x].span,
-                        g_ftdm_sngss7_data.cfg.isupCircuit[x].chan,
-                        g_ftdm_sngss7_data.cfg.isupCircuit[x].cic,
-                        0,
-                        g_ftdm_sngss7_data.cfg.isupCircuit[x].id);
-        } else {
-            SS7_INFO("Added span = %d, chan = %d, cic = %d, FTDM chan = %d, ISUP cirId = %d\n",
-                        g_ftdm_sngss7_data.cfg.isupCircuit[x].span,
-                        g_ftdm_sngss7_data.cfg.isupCircuit[x].chan,
-                        g_ftdm_sngss7_data.cfg.isupCircuit[x].cic,
-                        ss7_info->ftdmchan->chan_id,
-                        g_ftdm_sngss7_data.cfg.isupCircuit[x].id);
-        }
-
-    } /* while (ch_map[0] != '\0') */
-
-    return 0;
+       sngss7_chan_data_t      *ss7_info = NULL;
+       ftdm_channel_t          *ftdmchan = NULL;
+       sng_timeslot_t          timeslot;
+       int                                     count;
+       int                                     i;
+       int                                     x;
+
+       count = 1;
+
+       while (ch_map[0] != '\0') {
+
+                /* pull out the next timeslot */
+               if (ftmod_ss7_next_timeslot(ch_map, &timeslot)) {
+                       SS7_ERROR("Failed to parse the channel map!\n");
+                       return FTDM_FAIL;
+               }
+
+               if ((timeslot.siglink) || (timeslot.gap)) {
+                       /* try to find the channel in the circuits structure*/
+                       x = 1;
+                       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+                               if ((g_ftdm_sngss7_data.cfg.isupCkt[x].chan == count) &&
+                                       (g_ftdm_sngss7_data.cfg.isupCkt[x].span == span->channels[1]->physical_span_id)) {
+
+                                       SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is already exists...id=%d\n",
+                                                               span->channels[1]->physical_span_id,
+                                                               count,
+                                                               x);
+
+                                       /* we have a match so this circuit already exists in the structure */
+                                       break;
+                               }
+                               /* move to the next circuit */
+                               x++;
+                       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
+
+                       /* check why we exited the while loop */
+                       if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) {
+                               SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n",
+                               span->channels[1]->physical_span_id,
+                               count,
+                               x);
+
+                               /* prepare the global info sturcture */
+                               ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t));
+                               ss7_info->ftdmchan = NULL;
+                               ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCkt[x];
+
+                               /* circuit is new so fill in the needed information */
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].id                    = x;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].span                  = span->channels[1]->physical_span_id;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].chan                  = count;
+                               if (timeslot.siglink) {
+                                       g_ftdm_sngss7_data.cfg.isupCkt[x].type          = SIG;
+                               } else if (timeslot.hole) {
+                                       g_ftdm_sngss7_data.cfg.isupCkt[x].type          = HOLE;
+                               } else {
+                                       g_ftdm_sngss7_data.cfg.isupCkt[x].type          = VOICE;
+                               }
+                               if (timeslot.channel) {
+                                       g_ftdm_sngss7_data.cfg.isupCkt[x].cic           = cicbase;
+                                       cicbase++;
+                               } else {
+                                       g_ftdm_sngss7_data.cfg.isupCkt[x].cic           = 0;
+                               }
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].infId                 = isup_id;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl     = typeCntrl;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t3                    = 1200;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t12                   = 300;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t13                   = 3000;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t14                   = 300;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t15                   = 3000;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t16                   = 300;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t17                   = 3000;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].tval                  = 10;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].ssf                   = g_ftdm_sngss7_data.cfg.isupIntf[isup_id].ssf;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].obj                   = ss7_info;
+
+                       } /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) */
+               } else { /* if ((timeslot.siglink) || (timeslot.gap)) */
+                       /* find the ftdm the channel structure for this channel*/
+                       i = 1;
+                       while (span->channels[i] != NULL) {
+                               if (span->channels[i]->physical_chan_id == timeslot.channel) {
+                                       break;
+                               }
+                               i++;
+                       } /* while (span->channels[i] != NULL) */
+
+                       if (span->channels[i] == NULL) {
+                               /* we weren't able to find the channel in the ftdm channels */
+                               SS7_ERROR("Unable to find the requested channel %d in the FreeTDM channels!\n", timeslot.channel);
+                               return FTDM_FAIL;
+                       } else {
+                               ftdmchan = span->channels[i];
+                       }
+
+                       /* try to find a match for the physical span and chan */
+                       x = 1;
+                       while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+                               if ((g_ftdm_sngss7_data.cfg.isupCkt[x].chan == ftdmchan->physical_chan_id) 
+                                       && (g_ftdm_sngss7_data.cfg.isupCkt[x].span == ftdmchan->physical_span_id)) {
+
+                                       /* we have a match so this circuit already exists in the structure */
+                                       break;
+                               }
+                               /* move to the next circuit */
+                               x++;
+                       } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */
+
+                       /* check why we exited the while loop */
+                       if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) {
+                               SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n",
+                               ftdmchan->physical_span_id,
+                               ftdmchan->physical_chan_id,
+                               x);
+
+                               /* prepare the global info sturcture */
+                               ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t));
+                               ss7_info->ftdmchan = ftdmchan;
+                               ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCkt[x];
+                               ftdmchan->call_data = ss7_info;
+
+                               /* prepare the timer structures */
+                               ss7_info->t35.sched                     = ((sngss7_span_data_t *)span->mod_data)->sched;
+                               ss7_info->t35.counter           = 1;
+                               ss7_info->t35.beat                      = g_ftdm_sngss7_data.cfg.isupIntf[isup_id].t35*100; /* beat is in ms, t35 is in 100ms */
+                               ss7_info->t35.callback          = handle_isup_t35;
+                               ss7_info->t35.sngss7_info       = ss7_info;
+
+                               /* circuit is new so fill in the needed information */
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].id              = x;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].span          = ftdmchan->physical_span_id;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].chan          = ftdmchan->physical_chan_id;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].type          = VOICE;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].cic           = cicbase;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].infId         = isup_id;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl     = typeCntrl;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t3            = 1200;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t12           = 300;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t13           = 3000;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t14           = 300;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t15           = 3000;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t16           = 300;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].t17           = 3000;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].tval          = 10;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].obj           = ss7_info;
+                               g_ftdm_sngss7_data.cfg.isupCkt[x].ssf           = g_ftdm_sngss7_data.cfg.isupIntf[isup_id].ssf;
+
+                               /* increment the cicbase */
+                               cicbase++;
+                       } else { /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) */
+                               SS7_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n",
+                                                                       ftdmchan->physical_span_id,
+                                                                       ftdmchan->physical_chan_id,
+                                                                       x);
+
+                               /* for now make sure ss7_info is set to null */
+                               ss7_info = NULL;
+
+                               /* KONRAD FIX ME -> confirm that it is the same circuit */
+                       }  /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) */
+
+                       /* increment the span channel count */
+                       count++;
+               } /* if ((timeslot.siglink) || (timeslot.gap)) */
+
+               if (ss7_info == NULL) {
+                       SS7_ERROR("KONRAD -> circuit was not configured !\n");
+                       return FTDM_FAIL;
+               }
+
+               if (ss7_info->ftdmchan == NULL) {
+                       SS7_INFO("Added span = %d, chan = %d, cic = %d, FTDM chan = %d, ISUP cirId = %d\n",
+                                               g_ftdm_sngss7_data.cfg.isupCkt[x].span,
+                                               g_ftdm_sngss7_data.cfg.isupCkt[x].chan,
+                                               g_ftdm_sngss7_data.cfg.isupCkt[x].cic,
+                                               0,
+                                               g_ftdm_sngss7_data.cfg.isupCkt[x].id);
+               } else {
+                       SS7_INFO("Added span = %d, chan = %d, cic = %d, FTDM chan = %d, ISUP cirId = %d\n",
+                                               g_ftdm_sngss7_data.cfg.isupCkt[x].span,
+                                               g_ftdm_sngss7_data.cfg.isupCkt[x].chan,
+                                               g_ftdm_sngss7_data.cfg.isupCkt[x].cic,
+                                               ss7_info->ftdmchan->chan_id,
+                                               g_ftdm_sngss7_data.cfg.isupCkt[x].id);
+               }
+
+       } /* while (ch_map[0] != '\0') */
+
+       return 0;
 }
 
 /******************************************************************************/
 static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
 {
-    int             i;
-    int             x;
-    int             lower;
-    int             upper;
-    char            tmp[5]; /*KONRAD FIX ME*/
-    char            new_ch_map[MAX_CIC_LENGTH];
-
-    memset(&tmp[0], '\0', sizeof(tmp));
-    memset(&new_ch_map[0], '\0', sizeof(new_ch_map));
-    memset(timeslot, 0x0, sizeof(sng_timeslot_t));
-
-    SS7_DEVEL_DEBUG("Old channel map = \"%s\"\n", ch_map);
-
-    /* start at the beginning of the ch_map */
-    x = 0;
-
-    switch (ch_map[x]) {
-    /**************************************************************************/
-    case 'S':
-    case 's':   /* we have a sig link */
-        timeslot->siglink = 1;
-
-        /* check what comes next either a comma or a number */
-        x++;
-        if (ch_map[x] == ',') {
-            timeslot->hole = 1;
-            SS7_DEVEL_DEBUG(" Found a siglink in the channel map with a hole in the cic map\n");
-        } else if (isdigit(ch_map[x])) {
-            /* consume all digits until a comma as this is the channel */
-            SS7_DEVEL_DEBUG(" Found a siglink in the channel map with out a hole in the cic map\n");
-        } else {
-            SS7_ERROR("Found an illegal channel map character after signal link flag = \"%c\"!\n", ch_map[x]);
-            return FTDM_FAIL;
-        }
-        break;
-    /**************************************************************************/
-    case 'G':
-    case 'g':   /* we have a channel gap */
-        timeslot->gap = 1;
-
-        /* check what comes next either a comma or a number */
-        x++;
-        if (ch_map[x] == ',') {
-            timeslot->hole = 1;
-            SS7_DEVEL_DEBUG(" Found a gap in the channel map with a hole in the cic map\n");
-        } else if (isdigit(ch_map[x])) {
-            SS7_DEVEL_DEBUG(" Found a gap in the channel map with out a hole in the cic map\n");
-            /* consume all digits until a comma as this is the channel */
-        } else {
-            SS7_ERROR("Found an illegal channel map character after signal link flag = \"%c\"!\n", ch_map[x]);
-            return FTDM_FAIL;
-        }
-        break;
-    /**************************************************************************/
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-    case '8':
-    case '9':   /* we have a channel */
-        /* consume all digits until a comma or a dash */
-        SS7_DEVEL_DEBUG("Found a starting channel in the channel map\n");
-        break;
-    /**************************************************************************/
-    default:
-        SS7_ERROR("Found an illegal channel map character = \"%c\"!\n", ch_map[x]);
-        return FTDM_FAIL;
-    /**************************************************************************/
-    } /* switch (ch_map[x]) */
-
-    /* grab the first number in the string */
-    i = 0;
-    while ((ch_map[x] != '\0') && (ch_map[x] != '-') && (ch_map[x] != ',')) {
-        tmp[i] = ch_map[x];
-        i++;
-        x++;
-    }
-    tmp[i] = '\0';
-    timeslot->channel = atoi(tmp);
-    lower = timeslot->channel + 1;
-
-    /* check the next value in the list */
-    if (ch_map[x] == '-') {
-        /* consume the number after the dash */
-        x++;
-        i = 0;
-        while ((ch_map[x] != '\0') && (ch_map[x] != '-') && (ch_map[x] != ',')) {
-            tmp[i] = ch_map[x];
-            i++;
-            x++;
-        }
-        tmp[i] = '\0';
-        upper = atoi(tmp);
-
-        /* check if the upper end of the range is the same as the lower end of the range */
-        if (upper == lower) {
-            /* the range is completed, eat the next comma or \0  and write it */
-            sprintf(new_ch_map, "%d", lower);
-        } else if ( upper > lower) {
-            /* the list continues, add 1 from the channel map value and re-insert it to the list */
-            sprintf(new_ch_map, "%d-%d", lower, upper);
-        } else {
-            SS7_ERROR("The upper is less then the lower end of the range...should not happen!\n");
-            return FTDM_FAIL;
-        }
-
-        /* the the rest of ch_map to new_ch_map */
-        strncat(new_ch_map, &ch_map[x], strlen(&ch_map[x]));
-
-        /* set the new cic map to ch_map*/
-        strcpy(ch_map, new_ch_map);
-
-    } else if (ch_map[x] == ',') {
-        /* move past the comma */
-        x++;
-
-        /* copy the rest of the list to new_ch_map */
-        strcpy(new_ch_map, &ch_map[x]);
-
-        /* copy the new_ch_map over the old one */
-        strcpy(ch_map, new_ch_map);
-
-    } else if (ch_map[x] == '\0') {
-        /* we're at the end of the string...copy the rest of the list to new_ch_map */
-        strcpy(new_ch_map, &ch_map[x]);
-
-        /* set the new cic map to ch_map*/
-        strcpy(ch_map, new_ch_map);
-    } else { 
-        /* nothing to do */
-    }
-
-    SS7_DEVEL_DEBUG("New channel map = \"%s\"\n", ch_map);
-
-    return FTDM_SUCCESS;
+       int                      i;
+       int                      x;
+       int                      lower;
+       int                      upper;
+       char                    tmp[5]; /*KONRAD FIX ME*/
+       char                    new_ch_map[MAX_CIC_LENGTH];
+
+       memset(&tmp[0], '\0', sizeof(tmp));
+       memset(&new_ch_map[0], '\0', sizeof(new_ch_map));
+       memset(timeslot, 0x0, sizeof(sng_timeslot_t));
+
+       SS7_DEVEL_DEBUG("Old channel map = \"%s\"\n", ch_map);
+
+       /* start at the beginning of the ch_map */
+       x = 0;
+
+       switch (ch_map[x]) {
+       /**************************************************************************/
+       case 'S':
+       case 's':   /* we have a sig link */
+               timeslot->siglink = 1;
+
+               /* check what comes next either a comma or a number */
+               x++;
+               if (ch_map[x] == ',') {
+                       timeslot->hole = 1;
+                       SS7_DEVEL_DEBUG(" Found a siglink in the channel map with a hole in the cic map\n");
+               } else if (isdigit(ch_map[x])) {
+                       /* consume all digits until a comma as this is the channel */
+                       SS7_DEVEL_DEBUG(" Found a siglink in the channel map with out a hole in the cic map\n");
+               } else {
+                       SS7_ERROR("Found an illegal channel map character after signal link flag = \"%c\"!\n", ch_map[x]);
+                       return FTDM_FAIL;
+               }
+               break;
+       /**************************************************************************/
+       case 'G':
+       case 'g':   /* we have a channel gap */
+               timeslot->gap = 1;
+
+               /* check what comes next either a comma or a number */
+               x++;
+               if (ch_map[x] == ',') {
+                       timeslot->hole = 1;
+                       SS7_DEVEL_DEBUG(" Found a gap in the channel map with a hole in the cic map\n");
+               } else if (isdigit(ch_map[x])) {
+                       SS7_DEVEL_DEBUG(" Found a gap in the channel map with out a hole in the cic map\n");
+                       /* consume all digits until a comma as this is the channel */
+               } else {
+                       SS7_ERROR("Found an illegal channel map character after signal link flag = \"%c\"!\n", ch_map[x]);
+                       return FTDM_FAIL;
+               }
+               break;
+       /**************************************************************************/
+       case '1':
+       case '2':
+       case '3':
+       case '4':
+       case '5':
+       case '6':
+       case '7':
+       case '8':
+       case '9':   /* we have a channel */
+               /* consume all digits until a comma or a dash */
+               SS7_DEVEL_DEBUG("Found a starting channel in the channel map\n");
+               break;
+       /**************************************************************************/
+       default:
+               SS7_ERROR("Found an illegal channel map character = \"%c\"!\n", ch_map[x]);
+               return FTDM_FAIL;
+       /**************************************************************************/
+       } /* switch (ch_map[x]) */
+
+       /* grab the first number in the string */
+       i = 0;
+       while ((ch_map[x] != '\0') && (ch_map[x] != '-') && (ch_map[x] != ',')) {
+               tmp[i] = ch_map[x];
+               i++;
+               x++;
+       }
+       tmp[i] = '\0';
+       timeslot->channel = atoi(tmp);
+       lower = timeslot->channel + 1;
+
+       /* check the next value in the list */
+       if (ch_map[x] == '-') {
+               /* consume the number after the dash */
+               x++;
+               i = 0;
+               while ((ch_map[x] != '\0') && (ch_map[x] != '-') && (ch_map[x] != ',')) {
+                       tmp[i] = ch_map[x];
+                       i++;
+                       x++;
+               }
+               tmp[i] = '\0';
+               upper = atoi(tmp);
+
+               /* check if the upper end of the range is the same as the lower end of the range */
+               if (upper == lower) {
+                       /* the range is completed, eat the next comma or \0  and write it */
+                       sprintf(new_ch_map, "%d", lower);
+               } else if ( upper > lower) {
+                       /* the list continues, add 1 from the channel map value and re-insert it to the list */
+                       sprintf(new_ch_map, "%d-%d", lower, upper);
+               } else {
+                       SS7_ERROR("The upper is less then the lower end of the range...should not happen!\n");
+                       return FTDM_FAIL;
+               }
+
+               /* the the rest of ch_map to new_ch_map */
+               strncat(new_ch_map, &ch_map[x], strlen(&ch_map[x]));
+
+               /* set the new cic map to ch_map*/
+               strcpy(ch_map, new_ch_map);
+
+       } else if (ch_map[x] == ',') {
+               /* move past the comma */
+               x++;
+
+               /* copy the rest of the list to new_ch_map */
+               strcpy(new_ch_map, &ch_map[x]);
+
+               /* copy the new_ch_map over the old one */
+               strcpy(ch_map, new_ch_map);
+
+       } else if (ch_map[x] == '\0') {
+               /* we're at the end of the string...copy the rest of the list to new_ch_map */
+               strcpy(new_ch_map, &ch_map[x]);
+
+               /* set the new cic map to ch_map*/
+               strcpy(ch_map, new_ch_map);
+       } else { 
+               /* nothing to do */
+       }
+
+       SS7_DEVEL_DEBUG("New channel map = \"%s\"\n", ch_map);
+
+       return FTDM_SUCCESS;
 }
 
 /******************************************************************************/
+
+/******************************************************************************/
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
+ */
+/******************************************************************************/