library_includedir = $(PREFIX)/include
INCS = -I$(FT_SRCDIR)/$(SRC)/include -I$(FT_SRCDIR)/$(SRC)/isdn/include -I$(FT_SRCDIR)/$(SRC)/include/private
-INCS += -I$(FT_SRCDIR)/$(SRC)/ftmod/ftmod_sangoma_boost
+INCS += -I$(FT_SRCDIR)/$(SRC)/ftmod/ftmod_sangoma_boost
+if SNGSS7
+INCS += -I/usr/include/wanpipe/sng_ss7/
+endif
MY_CFLAGS = $(INCS) $(FTDM_CFLAGS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_CFLAGS@ @DEFS@
COMPILE = $(CC) $(MY_CFLAGS) $(INCS)
LTCOMPILE = $(LIBTOOL) --mode=compile --tag=CC $(COMPILE)
mod_LTLIBRARIES += ftmod_libpri.la
endif
+if SNGSS7
+mod_LTLIBRARIES += ftmod_sangoma_ss7.la
+endif
+
if OPENR2
mod_LTLIBRARIES += ftmod_r2.la
endif
ftmod_libpri_la_LIBADD = $(MYLIB)
endif
+if SNGSS7
+ftmod_sangoma_ss7_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c \
+ $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c \
+ $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c \
+ $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c \
+ $(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
+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)
+endif
+
if OPENR2
ftmod_r2_la_SOURCES = $(SRC)/ftmod/ftmod_r2/ftmod_r2.c
ftmod_r2_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
AM_CONDITIONAL([LIBPRI],[test "${enable_libpri}" = "yes"])
+AC_CHECK_LIB([sng_ss7], [sng_isup_init], [have_sng_ss7="yes"])
+AM_CONDITIONAL([SNGSS7],[test "${have_sng_ss7}" = "yes"])
+
AC_CHECK_LIB([openr2], [openr2_context_set_io_type], [have_openr2="yes"])
AM_CONDITIONAL([OPENR2],[test "${have_openr2}" = "yes"])
--- /dev/null
+/*
+ * 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 *****************************************************************/
+ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data);
+
+static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream);
+
+static ftdm_status_t handle_set_function_trace(ftdm_stream_handle_t *stream, int on, int level);
+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_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);
+static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
+static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
+static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
+static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
+
+static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name);
+static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name);
+
+static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan);
+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;
+
+handle_cli_error_argc:
+ 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;
+
+handle_cli_error:
+ 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;
+}
+
+/******************************************************************************/
+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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ 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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+ }
+
+ /* 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;
+}
+
+/******************************************************************************/
+static ftdm_status_t check_arg_count(int args, int min)
+{
+ if ( args < min ) {
+ return FTDM_FAIL;
+ } else {
+ 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:
+ */
+/******************************************************************************/
--- /dev/null
+/*
+ * 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_alarm(sng_alrm_t t_alarm);
+
+static void handle_entsi_alarm(sng_alrm_t t_alarm);
+
+int ft_to_sngss7_cfg(void);
+int ft_to_sngss7_activate_all(void);
+
+static int ftmod_ss7_general_configuration(void);
+
+static int ftmod_ss7_configure_mtp1_link(int id);
+
+static int ftmod_ss7_configure_mtp2_link(int id);
+
+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);
+
+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);
+
+static int ftmod_ss7_configure_cc_isup(int id);
+
+/******************************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* 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;
+}
+
+/******************************************************************************/
+void handle_sng_alarm(sng_alrm_t t_alarm)
+{
+
+ 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;
+}
+
+/******************************************************************************/
+static void handle_entsi_alarm(sng_alrm_t alarm)
+{
+
+ 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[1] > 0 ) ? alarm.eventParm[1] : 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;
+}
+
+/* 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;
+}
+
+/* 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;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_general_configuration(void)
+{
+
+ 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;
+ }
+}
+
+/******************************************************************************/
+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;
+ }
+}
+
+/******************************************************************************/
+static int ftmod_ss7_configure_mtp3_link(int id)
+{
+ if(sng_cfg_mtp3_link(&g_ftdm_sngss7_data.cfg, id)){
+ return FTDM_FAIL;
+ } else {
+ return FTDM_SUCCESS;
+ }
+}
+
+/******************************************************************************/
+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;
+ }
+}
+
+/******************************************************************************/
+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;
+ }
+}
+
+/******************************************************************************/
+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;
+ }
+}
+
+/******************************************************************************/
+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;
+ }
+}
+
+/******************************************************************************/
+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;
+ }
+}
+
+/******************************************************************************/
+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;
+ }
+}
+
+/******************************************************************************/
+static int ftmod_ss7_configure_isup_cc(int id)
+{
+ if(sng_cfg_isup_cc_interface(&g_ftdm_sngss7_data.cfg, id)){
+ return FTDM_FAIL;
+ } else {
+ return FTDM_SUCCESS;
+ }
+}
+
+/******************************************************************************/
+static int ftmod_ss7_configure_cc_isup(int id)
+{
+ if(sng_cfg_cc_isup_interface(&g_ftdm_sngss7_data.cfg, id)){
+ return FTDM_FAIL;
+ } else {
+ 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:
+ */
+/******************************************************************************/
+
--- /dev/null
+/*
+ * 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 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);
+void sngss7_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt);
+void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType);
+void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt);
+void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt);
+void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt);
+void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
+void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
+void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit);
+
+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_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
+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_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
+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_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_rsc_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);
+
+
+
+/******************************************************************************/
+
+/* 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... queueing incoming call\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;
+
+ break;
+ /**************************************************************************/
+ default: /* should not have gotten an IAM while in this state */
+ SS7_ERROR("Got IAM in an invalid state!\n");
+
+ /* 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__);
+
+ 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 ANM 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_PROGRESS:
+ case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
+
+ /* go to UP */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
+
+ break;
+ /**************************************************************************/
+ default: /* incorrect state...reset the CIC */
+
+ /* go to RESTART */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
+
+ 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__);
+ 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;
+}
+
+/******************************************************************************/
+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__);
+ return;
+ };
+
+ SS7_MSG_TRACE("Received REL on CIC # %d\n", sngss7_info->circuit->cic);
+
+ /* 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_DIALING:
+ 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;
+ }
+
+ /* 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__);
+ 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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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)
+{
+ SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+ SS7_MSG_TRACE( "Received User to User message on circuit # %d\n", circuit);
+
+ 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)
+{
+ 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 */
+ SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));
+ 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;
+}
+
+/******************************************************************************/
+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__);
+ return FTDM_FAIL;
+ };
+
+
+ switch (ftdmchan->state) {
+ /**************************************************************************/
+ case FTDM_CHANNEL_STATE_DIALING:
+ /* glare, go to down state*/
+
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+
+ break;
+ /**************************************************************************/
+ default:
+ /* fuck...this shouldn't happen */
+ SS7_ERROR("Received reattempt indication on CIC %d in invalid state %s\n",
+ sngss7_info->circuit->cic,
+ ftdm_channel_state2str(ftdmchan->state));
+
+ /* throw the channel into reset */
+ sngss7_set_flag(sngss7_info, FLAG_RESET_TX);
+ 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_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.isupCircuit[circuit].infId;
+
+ /* 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);
+
+ /* 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;
+ };
+
+ /* 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.isupCircuit[i].infId == infId) */
+
+ /* move to the next circuit */
+ i++;
+
+ } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[i].id != 0) */
+
+ 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)
+{
+ 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.isupCircuit[circuit].infId;
+
+ /* 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);
+
+ /* 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;
+ };
+
+ /* 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);
+
+ } /* if (g_ftdm_sngss7_data.cfg.isupCircuit[i].infId == infId) */
+
+ /* move to the next circuit */
+ i++;
+
+ } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[i].id != 0) */
+
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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__);
+
+ 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;
+ };
+
+ /* 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 again before we exit */
+ ftdm_mutex_unlock(ftdmchan->mutex);
+
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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)
+{
+ 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;
+ };
+
+ /* the stack is sending out a RSC for us */
+ 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);
+
+ /* 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_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;
+}
+
+/******************************************************************************/
+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__);
+
+ 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;
+ };
+
+ /* 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_blo_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;
+ };
+
+ /* KONRAD FIX ME */
+
+ /* 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_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;
+
+ /* 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;
+ };
+
+ /* 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");
+ }
+
+ /* throw the unblock flag */
+ sngss7_set_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX);
+
+ /* clear the block flag */
+ sngss7_clear_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_ubl_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;
+ };
+
+ /* KONRAD FIX ME */
+
+ /* unlock the channel again before we exit */
+ ftdm_mutex_unlock(ftdmchan->mutex);
+
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+#if 0
+{
+ 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;
+ };
+
+ /* fill in here */
+
+ /* unlock the channel again before we exit */
+ ftdm_mutex_unlock(ftdmchan->mutex);
+
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+#endif
+/******************************************************************************/
+/******************************************************************************/
+/* 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:
+ */
+/******************************************************************************/
+
--- /dev/null
+/*
+ * 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 ********************************************************************/
+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;
+/******************************************************************************/
+
+/* PROTOTYPES *****************************************************************/
+static void *ftdm_ss7_run(ftdm_thread_t *me, void *obj);
+static void ftdm_ss7_process_state_change(ftdm_channel_t *ftdmchan);
+
+static ftdm_status_t ftdm_ss7_stop(ftdm_span_t *span);
+static ftdm_status_t ftdm_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_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_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},
+ }
+ }
+};
+/******************************************************************************/
+
+/* MONITIOR THREADS ***********************************************************/
+static void *ftdm_ss7_run(ftdm_thread_t *me, void *obj)
+{
+ ftdm_interrupt_t *ftdm_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_ss7_int) != FTDM_SUCCESS) {
+ SS7_CRITICAL("Failed to get a ftdm_interrupt for span = %d!\n", span->span_id);
+ goto ftdm_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_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_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->span_id,
+ ftdmchan->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_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_ss7_run_exit:
+
+ /* 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 due to error.\n", span->span_id);
+
+ ftdm_ss7_stop(span);
+
+ return NULL;
+}
+
+/******************************************************************************/
+static void ftdm_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;
+
+ 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->span_id,ftdmchan->chan_id);
+
+ if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+ SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+ break;
+ }
+
+ int i = 0;
+
+ 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->span_id,ftdmchan->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_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->span_id,ftdmchan->chan_id);
+
+ if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+ SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+ break;
+ }
+
+ /*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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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 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);
+
+ /* 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 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)) {
+ SS7_DEBUG("Glare flag is up....spoofing incoming call on span=%, chan=%d\n",
+ ftdmchan->span_id,ftdmchan->chan_id);
+ /* clear all the call specific data */
+ sngss7_info->suInstId = 0;
+ sngss7_info->spInstId = 0;
+ sngss7_info->globalFlg = 0;
+ sngss7_info->spId = 0;
+ sngss7_info->flags = 0;
+
+ /* 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 */
+ sngss7_con_ind(sngss7_info->glare.suInstId,
+ sngss7_info->glare.spInstId,
+ sngss7_info->glare.circuit,
+ &sngss7_info->glare.iam);
+ } 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->span_id,ftdmchan->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)) {
+ /* 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->span_id,ftdmchan->chan_id);
+
+ /**********************************************************************/
+ if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) {
+ SS7_DEBUG("processing pause for span = %, chan = %d\n",ftdmchan->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->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->span_id,ftdmchan->chan_id);
+ break;
+ } /*switch (ftdmchan->state)*/
+
+ /*unlock*/
+ ftdm_mutex_unlock(ftdmchan->mutex);
+
+ return;
+}
+/******************************************************************************/
+
+/******************************************************************************/
+static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_ss7_outgoing_call)
+{
+ sngss7_chan_data_t *sngss7_info;
+ int c;
+
+ /* lock the channel while we check whether it is availble */
+ ftdm_mutex_lock(ftdmchan->mutex);
+
+ 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);
+
+ /* 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 < 20) {
+
+ /* lock the channel while we check whether it is availble */
+ ftdm_mutex_lock(ftdmchan->mutex);
+
+ /* extract the sngss7_chan_data structure */
+ sngss7_info = (sngss7_chan_data_t *)ftdmchan->call_data;
+
+ if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
+ SS7_ERROR("Glare flag on span=%d, chan=%d\n",
+ ftdmchan->span_id,ftdmchan->chan_id);
+
+ /* move the channel to DOWN to clear the existing channel allocations */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+ 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:
+ SS7_DEBUG("Outgoing call request successful on span=%d, chan=%d\n",
+ ftdmchan->span_id,ftdmchan->chan_id);
+ goto outgoing_successful;
+ break;
+ /******************************************************************/
+ default:
+ SS7_ERROR("Channel in invalid state (%s) on span=%d, chan=%d...should not happen\n",
+ ftdm_channel_state2str(ftdmchan->state),
+ ftdmchan->span_id,
+ ftdmchan->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(50);
+
+ /* 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->span_id,ftdmchan->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->span_id,ftdmchan->chan_id);
+ goto outgoing_glare;
+ break;
+ /**************************************************************************/
+ }
+
+ /* we should not get to this here...all exit points above use goto */
+ SS7_ERROR("WE SHOULD NOT HERE HERE!!!!\n");
+
+outgoing_fail:
+ /* unlock the channel */
+ ftdm_mutex_unlock(ftdmchan->mutex);
+ return FTDM_FAIL;
+
+outgoing_glare:
+ /* unlock the channel */
+ ftdm_mutex_unlock(ftdmchan->mutex);
+ return FTDM_BREAK;
+
+outgoing_successful:
+ /* unlock the channel */
+ ftdm_mutex_unlock(ftdmchan->mutex);
+ return FTDM_SUCCESS;
+}
+/******************************************************************************/
+#if 0
+static FIO_CHANNEL_REQUEST_FUNCTION(ftdm_ss7_request_chan)
+{
+ SS7_INFO("KONRAD-> I got called %s\n",__FUNCTION__);
+ return FTDM_SUCCESS;
+}
+#endif
+
+/******************************************************************************/
+
+/* FT-CORE SIG STATUS FUNCTIONS ***********************************************/
+static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_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;
+}
+
+static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_ss7_set_sig_status)
+{
+ SS7_ERROR("Cannot set channel status in this module\n");
+
+ return FTDM_NOTIMPL;
+}
+
+/* FT-CORE SIG FUNCTIONS *******************************************************/
+static ftdm_status_t ftdm_ss7_start(ftdm_span_t *span)
+{
+ SS7_INFO("Starting span %s:%u.\n",span->name,span->span_id);
+
+ /* 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_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_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;
+}
+/******************************************************************************/
+
+/* SIG_FUNCTIONS ***************************************************************/
+static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_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_ss7_start;
+ span->stop = ftdm_ss7_stop;
+ span->signal_type = FTDM_SIGTYPE_SANGOMASS7;
+ span->signal_data = NULL;
+ span->outgoing_call = ftdm_ss7_outgoing_call;
+ span->channel_request = NULL;
+ span->signal_cb = sig_cb;
+ span->get_channel_sig_status = ftdm_ss7_get_sig_status;
+ span->set_channel_sig_status = ftdm_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_ss7_start(span);
+#endif
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static FIO_SIG_LOAD_FUNCTION(ftdm_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;
+}
+
+/******************************************************************************/
+static FIO_SIG_UNLOAD_FUNCTION(ftdm_ss7_unload)
+{
+ /*this function is called by the FT-core to unload the signaling module*/
+
+ ftdm_log(FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n");
+
+ sng_isup_free();
+
+ ftdm_log(FTDM_LOG_INFO, "Finished ftmod_sangoma_ss7 unload!\n");
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static FIO_API_FUNCTION(ftdm_ss7_api)
+{
+ /* 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_ss7_io_init)
+{
+ 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_ss7_api;
+
+ *fio = &g_ftdm_sngss7_interface;
+
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+
+
+/* START **********************************************************************/
+ftdm_module_t ftdm_module =
+{
+ "sangoma_ss7", /*char name[256]; */
+ ftdm_ss7_io_init, /*fio_io_load_t */
+ NULL, /*fio_io_unload_t */
+ ftdm_ss7_init, /*fio_sig_load_t */
+ NULL, /*fio_sig_configure_t */
+ ftdm_ss7_unload, /*fio_sig_unload_t */
+ ftdm_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:
+ */
+
+/******************************************************************************/
+
+
--- /dev/null
+/*
+ * 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.
+ */
+/******************************************************************************/
+#ifndef __FTMOD_SNG_SS7_H__
+#define __FTMOD_SNG_SS7_H__
+/******************************************************************************/
+
+/* INCLUDE ********************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#include "private/ftdm_core.h"
+
+#include "sng_sit.h"
+#include "sng_ss7.h"
+#include "sng_ss7_error.h"
+/******************************************************************************/
+
+/* DEFINES ********************************************************************/
+#define MAX_CIC_LENGTH 5
+#define MAX_CIC_MAP_LENGTH 256
+#define MAX_MTP_LINKS MAX_SN_LINKSETS
+
+#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;
+
+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;
+}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;
+}sngss7_timer_data_t;
+
+typedef struct sngss7_glare_data {
+ uint32_t suInstId;
+ uint32_t spInstId;
+ uint32_t circuit;
+ SiConEvnt iam;
+}sngss7_glare_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_chan_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_GLARE = (1 << 4),
+ 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_t;
+/******************************************************************************/
+
+/* GLOBALS ********************************************************************/
+extern ftdm_sngss7_data_t g_ftdm_sngss7_data;
+extern uint32_t sngss7_id;
+extern ftdm_sched_t *sngss7_sched;
+/******************************************************************************/
+
+/* PROTOTYPES *****************************************************************/
+extern void handle_sng_log(uint8_t level, char *fmt,...);
+extern void handle_sng_alarm(sng_alrm_t t_alarm);
+
+extern int ft_to_sngss7_cfg(void);
+extern int ft_to_sngss7_activate_all(void);
+
+extern void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_acm(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_anm(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_rel(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_rlc(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_rsc(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_rsca(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_blo(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_bla(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_ubl(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan);
+extern void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan);
+
+extern void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
+extern void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt);
+extern void sngss7_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt);
+extern void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType);
+extern void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt);
+extern void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt);
+extern void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt);
+extern void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
+extern void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt);
+extern void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
+extern void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit);
+
+extern uint8_t copy_cgPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum);
+extern uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum);
+extern uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum);
+extern uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum);
+extern uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
+extern int check_for_state_change(ftdm_channel_t *ftdmchan);
+extern ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
+extern unsigned long get_unique_id(void);
+
+extern int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span);
+
+extern void handle_isup_t35(void *userdata);
+
+extern ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data);
+/******************************************************************************/
+
+/* 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__ );
+
+#ifdef KONRAD_DEVEL
+#define SS7_DEVEL_DEBUG(a,...) ftdm_log(FTDM_LOG_DEBUG,a,##__VA_ARGS__ );
+#else
+#define SS7_DEVEL_DEBUG(a,...)
+#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) */
+
+#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) */
+
+#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))
+
+/******************************************************************************/
+
+/******************************************************************************/
+#endif /* __FTMOD_SNG_SS7_H__ */
+/******************************************************************************/
--- /dev/null
+/*
+ * 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 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_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);
+
+/* FUNCTIONS ******************************************************************/
+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;
+}
+/******************************************************************************/
+
+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;
+}
+/******************************************************************************/
+
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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_EXIT(__FUNCTION__);
+ 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:
+ */
+/******************************************************************************/
+
--- /dev/null
+/*
+ * 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 ********************************************************************/
+uint32_t sngss7_id;
+/******************************************************************************/
+
+/* PROTOTYPES *****************************************************************/
+uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
+uint8_t copy_cgPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum);
+uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum);
+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);
+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);
+
+/******************************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+uint8_t copy_cgPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
+{
+
+ 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;
+}
+
+/******************************************************************************/
+uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
+{
+
+ 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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+int check_for_state_change(ftdm_channel_t *ftdmchan)
+{
+
+#if 0
+ SS7_DEBUG("Checking for pending state change on span: %d, chan: %d\n!",
+ ftdmchan->physical_span_id,
+ ftdmchan->physical_chan_id);
+#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);
+
+ /* 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;
+}
+
+/******************************************************************************/
+ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan)
+{
+ SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+ 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.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;
+
+ 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;
+}
+
+/******************************************************************************/
+unsigned long get_unique_id(void)
+{
+
+ if (sngss7_id < 420000000) {
+ sngss7_id++;
+ } else {
+ sngss7_id = 1;
+ }
+
+ return(sngss7_id);
+}
+
+/******************************************************************************/
+
+/******************************************************************************/
+/* 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:
+ */
+/******************************************************************************/
--- /dev/null
+/*
+ * 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_isup_t35(void *userdata);
+/******************************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+void handle_isup_t35(void *userdata)
+{
+ SS7_FUNC_TRACE_ENTER(__FUNCTION__);
+
+ sngss7_timer_data_t *timer = userdata;
+ sngss7_chan_data_t *sngss7_info = timer->sngss7_info;
+ ftdm_channel_t *ftdmchan = sngss7_info->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);
+
+ SS7_ERROR("[Call-Control] Timer 35 expired on CIC = %d\n", sngss7_info->circuit->cic);
+
+ /* set the flag to indicate this hangup is started from the local side */
+ sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL);
+
+ /* hang up on timer expiry */
+ ftdmchan->caller_data.hangup_cause = 102;
+
+ /* end the call */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
+
+ /*unlock*/
+ ftdm_mutex_unlock(ftdmchan->mutex);
+
+ SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+ 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:
+ */
+/******************************************************************************/
+
--- /dev/null
+/*
+ * 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 ********************************************************************/
+typedef struct sng_timeslot
+{
+ int channel;
+ int siglink;
+ int gap;
+ int hole;
+}sng_timeslot_t;
+/******************************************************************************/
+
+/* PROTOTYPES *****************************************************************/
+int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span);
+
+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_routes(ftdm_conf_node_t *mtp_routes);
+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_self_route(int spc, int linkType, int switchType, int ssf);
+
+static int ftmod_ss7_fill_in_circuits(char *ch_map, int cicbase, int typeCntrl, int isup_id, ftdm_span_t *span);
+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(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;
+
+ftmod_ss7_parse_xml_error:
+ 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;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets)
+{
+ 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");
+ }
+
+ /* 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;
+ }
+
+ /* move on to the next linkset */
+ mtp_linkset = mtp_linkset->next;
+
+ } /* while (mtp_linkset != NULL) */
+
+ 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;
+}
+
+/******************************************************************************/
+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)
+{
+ 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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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")) {
+ g_ftdm_sngss7_data.cfg.spc = atoi(parm->val);
+ SS7_DEBUG("\tFound SPC = %d\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;
+ }
+ /**********************************************************************/
+ } 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_isup_interface(&sng_isup);
+
+ ftmod_ss7_fill_in_isup_cc_interface(&sng_cc);
+
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+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);
+}
+
+/******************************************************************************/
+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);
+}
+
+/******************************************************************************/
+static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3Link_t *mtp3_link)
+{
+ 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);
+}
+
+/******************************************************************************/
+static int ftmod_ss7_fill_in_mtp3_linkset(sng_mtp3LinkSet_t *mtp3_linkset)
+{
+ int count;
+ int i = mtp3_linkset->id;
+
+ strcpy((char *)g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].name, (char *)mtp3_linkset->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;
+
+ for (count = 0; count < mtp3_linkset->numLinks; count++) {
+ g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].links[count] = mtp3_linkset->links[count];
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_fill_in_mtp3_route(sng_mtp3Route_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;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_fill_in_mtp3_isup_interface(sng_mtp3Route_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;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_fill_in_isup_interface(sng_isupInterface_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;
+}
+
+/******************************************************************************/
+static int ftmod_ss7_fill_in_isup_cc_interface(sng_isup_cc_t *sng_cc)
+{
+
+ 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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/
+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, ×lot)) {
+ 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;
+}
+
+/******************************************************************************/
+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;
+}
+
+/******************************************************************************/