1 /*
2  * Copyright (c) 2009, Konrad Hammel <konrad@sangoma.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of the original author; nor the names of any contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
25  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /* INCLUDE ********************************************************************/
35 #include "ftmod_sangoma_ss7_main.h"
36 #ifdef HAVE_ZLIB
37 #include <zlib.h>
38 #endif
39 /******************************************************************************/
40 
41 /* DEFINES ********************************************************************/
42 /******************************************************************************/
43 
44 /* GLOBALS ********************************************************************/
45 uint32_t sngss7_id;
46 /******************************************************************************/
47 
48 /* PROTOTYPES *****************************************************************/
49 int check_for_state_change(ftdm_channel_t *ftdmchan);
50 int check_for_reset(sngss7_chan_data_t *sngss7_info);
51 
52 unsigned long get_unique_id(void);
53 
54 ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
55 
56 ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan);
57 ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan);
58 ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan);
59 ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan);
60 
61 ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan);
62 
63 ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type);
64 ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type);
65 
66 int find_mtp2_error_type_in_map(const char *err_type);
67 int find_link_type_in_map(const char *linkType);
68 int find_switch_type_in_map(const char *switchType);
69 int find_ssf_type_in_map(const char *ssfType);
70 int find_cic_cntrl_in_map(const char *cntrlType);
71 
72 ftdm_status_t check_status_of_all_isup_intf(void);
73 ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan);
74 
75 void sngss7_send_signal(sngss7_chan_data_t *sngss7_info, ftdm_signal_event_t event_id);
76 void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_status_t status);
77 ftdm_status_t sngss7_add_var(sngss7_chan_data_t *ss7_info, const char* var, const char* val);
78 ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data, ftdm_size_t data_len);
79 /******************************************************************************/
80 
81 FTDM_ENUM_NAMES(CKT_FLAGS_NAMES, CKT_FLAGS_STRING)
82 FTDM_STR2ENUM(ftmod_ss7_ckt_state2flag, ftmod_ss7_ckt_flag2str, sng_ckt_flag_t, CKT_FLAGS_NAMES, 31)
83 
84 FTDM_ENUM_NAMES(BLK_FLAGS_NAMES, BLK_FLAGS_STRING)
85 FTDM_STR2ENUM(ftmod_ss7_blk_state2flag, ftmod_ss7_blk_flag2str, sng_ckt_block_flag_t, BLK_FLAGS_NAMES, 31)
86 
87 /* FUNCTIONS ******************************************************************/
88 static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val);
89 static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val);
90 ftdm_status_t four_char_to_hex(const char* in, uint16_t* out) ;
91 ftdm_status_t hex_to_four_char(uint16_t in, char* out);
92 
93 
94 ftdm_status_t hex_to_char(uint16_t in, char* out, int len);
95 ftdm_status_t char_to_hex(const char* in, uint16_t* out, int len);
96 
97 /* Maps generic FreeTDM CPC codes to SS7 CPC codes */
98 ftdm2trillium_t cpc_codes[] = {
99 	{FTDM_CPC_UNKNOWN,			CAT_UNKNOWN},
100 	{FTDM_CPC_OPERATOR_FRENCH,	CAT_OPLANGFR},
101 	{FTDM_CPC_OPERATOR_ENGLISH,	CAT_OPLANGENG},
102 	{FTDM_CPC_OPERATOR_GERMAN,	CAT_OPLANGGER},
103 	{FTDM_CPC_OPERATOR_RUSSIAN,	CAT_OPLANGRUS},
104 	{FTDM_CPC_OPERATOR_SPANISH,	CAT_OPLANGSP},
105 	{FTDM_CPC_ORDINARY,			CAT_ORD},
106 	{FTDM_CPC_PRIORITY,			CAT_PRIOR},
107 	{FTDM_CPC_DATA,				CAT_DATA},
108 	{FTDM_CPC_TEST,				CAT_TEST},
109 	{FTDM_CPC_PAYPHONE,			CAT_PAYPHONE},
110 };
111 
112 ftdm2trillium_t  bc_cap_codes[] = {
113 	{FTDM_BEARER_CAP_SPEECH,		ITC_SPEECH},	/* speech as per ATIS-1000113.3.2005 */
114 	{FTDM_BEARER_CAP_UNRESTRICTED,	ITC_UNRDIG},	/* unrestricted digital as per ATIS-1000113.3.2005 */
115 	{FTDM_BEARER_CAP_RESTRICTED,	ITC_UNRDIG},	/* Restricted Digital */
116 	{FTDM_BEARER_CAP_3_1KHZ_AUDIO,	ITC_A31KHZ},	/* 3.1kHz audio as per ATIS-1000113.3.2005 */
117 	{FTDM_BEARER_CAP_7KHZ_AUDIO,	ITC_A7KHZ},		/* 7Khz audio */
118 	{FTDM_BEARER_CAP_15KHZ_AUDIO,	ITC_A15KHZ},	/* 15Khz audio */
119 	{FTDM_BEARER_CAP_VIDEO,			ITC_VIDEO},		/* Video */
120 };
121 
get_trillium_val(ftdm2trillium_t * vals,uint8_t ftdm_val,uint8_t default_val)122 static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val)
123 {
124 	ftdm2trillium_t *val = vals;
125 	while(val++) {
126 		if (val->ftdm_val == ftdm_val) {
127 			return val->trillium_val;
128 		}
129 	}
130 	return default_val;
131 }
132 
get_ftdm_val(ftdm2trillium_t * vals,uint8_t trillium_val,uint8_t default_val)133 static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val)
134 {
135 	ftdm2trillium_t *val = vals;
136 	while(val++) {
137 		if (val->trillium_val == trillium_val) {
138 			return val->ftdm_val;
139 		}
140 	}
141 	return default_val;
142 }
143 
copy_cgPtyNum_from_sngss7(ftdm_channel_t * ftdmchan,SiCgPtyNum * cgPtyNum)144 ftdm_status_t copy_cgPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPtyNum)
145 {
146 	return FTDM_SUCCESS;
147 }
148 
copy_cgPtyNum_to_sngss7(ftdm_channel_t * ftdmchan,SiCgPtyNum * cgPtyNum)149 ftdm_status_t copy_cgPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPtyNum)
150 {
151 	const char *val = NULL;
152 	const char *clg_nadi = NULL;
153 
154 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
155 	ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
156 
157 	cgPtyNum->eh.pres		   = PRSNT_NODEF;
158 
159 	cgPtyNum->natAddrInd.pres   = PRSNT_NODEF;
160 	cgPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].clg_nadi;
161 
162 
163 	cgPtyNum->scrnInd.pres	  = PRSNT_NODEF;
164 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_screen_ind");
165 	if (!ftdm_strlen_zero(val)) {
166 		cgPtyNum->scrnInd.val	= atoi(val);
167 	} else {
168 		cgPtyNum->scrnInd.val	= caller_data->screen;
169 	}
170 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number Screening Ind %d\n", cgPtyNum->scrnInd.val);
171 
172 	cgPtyNum->presRest.pres	 = PRSNT_NODEF;
173 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_pres_ind");
174 	if (!ftdm_strlen_zero(val)) {
175 		cgPtyNum->presRest.val	= atoi(val);
176 	} else {
177 		cgPtyNum->presRest.val	= caller_data->pres;
178 	}
179 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number Presentation Ind %d\n", cgPtyNum->presRest.val);
180 
181 	cgPtyNum->numPlan.pres	  = PRSNT_NODEF;
182 	cgPtyNum->numPlan.val	   = 0x01;
183 
184 	cgPtyNum->niInd.pres		= PRSNT_NODEF;
185 	cgPtyNum->niInd.val		 = 0x00;
186 
187 	/* check if the user would like a custom NADI value for the calling Pty Num */
188 	clg_nadi = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_nadi");
189 	if (!ftdm_strlen_zero(clg_nadi)) {
190 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
191 		cgPtyNum->natAddrInd.val = atoi(clg_nadi);
192 	}
193 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number NADI value %d\n", cgPtyNum->natAddrInd.val);
194 
195 	return copy_tknStr_to_sngss7(caller_data->cid_num.digits, &cgPtyNum->addrSig, &cgPtyNum->oddEven);
196 }
197 
copy_cdPtyNum_from_sngss7(ftdm_channel_t * ftdmchan,SiCdPtyNum * cdPtyNum)198 ftdm_status_t copy_cdPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCdPtyNum *cdPtyNum)
199 {
200 	char var[FTDM_DIGITS_LIMIT];
201 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
202 
203 	if (cdPtyNum->eh.pres == PRSNT_NODEF &&
204 	    cdPtyNum->natAddrInd.pres 	== PRSNT_NODEF) {
205 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Called Party Number NADI %d\n", cdPtyNum->natAddrInd.val);
206 		sprintf(var, "%d", cdPtyNum->natAddrInd.val);
207 		sngss7_add_var(sngss7_info, "ss7_cld_nadi", var);
208 	}
209 
210 	return FTDM_SUCCESS;
211 }
212 
213 
copy_cdPtyNum_to_sngss7(ftdm_channel_t * ftdmchan,SiCdPtyNum * cdPtyNum)214 ftdm_status_t copy_cdPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCdPtyNum *cdPtyNum)
215 {
216 	const char	*val = NULL;
217 	ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
218 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
219 
220 	cdPtyNum->eh.pres		   = PRSNT_NODEF;
221 
222 	cdPtyNum->natAddrInd.pres   = PRSNT_NODEF;
223 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_nadi");
224 	if (!ftdm_strlen_zero(val)) {
225 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Called NADI value \"%s\"\n", val);
226 		cdPtyNum->natAddrInd.val	= atoi(val);
227 	} else {
228 		cdPtyNum->natAddrInd.val	= g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].cld_nadi;
229 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied NADI value found for CLD, using \"%d\"\n", cdPtyNum->natAddrInd.val);
230 	}
231 
232 	cdPtyNum->numPlan.pres	  = PRSNT_NODEF;
233 	cdPtyNum->numPlan.val	   = 0x01;
234 
235 	cdPtyNum->innInd.pres	   = PRSNT_NODEF;
236 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_inn");
237 	if (!ftdm_strlen_zero(val)) {
238 		cdPtyNum->innInd.val		= atoi(val);
239 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Called INN value \"%s\"\n", val);
240 	} else {
241 		cdPtyNum->innInd.val		= 0x01;
242 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Called INN value, set to default value 0x01\n");
243 	}
244 
245 	return copy_tknStr_to_sngss7(caller_data->dnis.digits, &cdPtyNum->addrSig, &cdPtyNum->oddEven);
246 }
247 
copy_locPtyNum_from_sngss7(ftdm_channel_t * ftdmchan,SiCgPtyNum * locPtyNum)248 ftdm_status_t copy_locPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *locPtyNum)
249 {
250 	return FTDM_SUCCESS;
251 }
252 
copy_locPtyNum_to_sngss7(ftdm_channel_t * ftdmchan,SiCgPtyNum * locPtyNum)253 ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *locPtyNum)
254 {
255         const char *val = NULL;
256         const char *loc_nadi = NULL;
257 	int pres_val = PRSNT_NODEF;
258 
259         sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
260         ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
261 
262 	if (!strcasecmp(caller_data->loc.digits, "NULL")) {
263 		pres_val = NOTPRSNT;
264 		return FTDM_SUCCESS;
265 	}
266 
267         locPtyNum->eh.pres = pres_val;
268         locPtyNum->natAddrInd.pres = pres_val;
269         locPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].loc_nadi;
270 
271         locPtyNum->scrnInd.pres = pres_val;
272 		val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_loc_screen_ind");
273         if (!ftdm_strlen_zero(val)) {
274 			locPtyNum->scrnInd.val = atoi(val);
275 			ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Location Screening Ind %d\n", locPtyNum->scrnInd.val);
276         } else {
277 			locPtyNum->scrnInd.val = caller_data->screen;
278         }
279 
280         locPtyNum->presRest.pres = pres_val;
281 		val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_loc_pres_ind");
282         if (!ftdm_strlen_zero(val)) {
283 			locPtyNum->presRest.val = atoi(val);
284 			ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Location Presentation Ind %d\n", locPtyNum->presRest.val);
285         } else {
286 			locPtyNum->presRest.val = caller_data->pres;
287         }
288 
289         locPtyNum->numPlan.pres	= pres_val;
290         locPtyNum->numPlan.val = 0x01;
291 
292         locPtyNum->niInd.pres = pres_val;
293         locPtyNum->niInd.val = 0x00;
294 
295 		/* check if the user would like a custom NADI value for the Location Reference */
296         loc_nadi = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_loc_nadi");
297         if (!ftdm_strlen_zero(loc_nadi)) {
298 			ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Location Reference NADI value \"%s\"\n", loc_nadi);
299 			locPtyNum->natAddrInd.val = atoi(loc_nadi);
300         } else {
301 			locPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].loc_nadi;
302 			ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied NADI value found for LOC, using \"%d\"\n", locPtyNum->natAddrInd.val);
303 	}
304 
305         return copy_tknStr_to_sngss7(caller_data->loc.digits, &locPtyNum->addrSig, &locPtyNum->oddEven);
306 }
307 
copy_genNmb_to_sngss7(ftdm_channel_t * ftdmchan,SiGenNum * genNmb)308 ftdm_status_t copy_genNmb_to_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb)
309 {
310 	const char *val = NULL;
311 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
312 
313 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_digits");
314 	if (!ftdm_strlen_zero(val)) {
315 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number qualifier \"%s\"\n", val);
316 		if (copy_tknStr_to_sngss7((char*)val, &genNmb->addrSig, &genNmb->oddEven) != FTDM_SUCCESS) {
317 			return FTDM_FAIL;
318 		}
319 	} else {
320 		return FTDM_SUCCESS;
321 	}
322 
323 	genNmb->eh.pres = PRSNT_NODEF;
324 	genNmb->addrSig.pres = PRSNT_NODEF;
325 
326 	genNmb->nmbQual.pres = PRSNT_NODEF;
327 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_numqual");
328 	if (!ftdm_strlen_zero(val)) {
329 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"%s\"\n", val);
330 		genNmb->nmbQual.val	= atoi(val);
331 	} else {
332 		genNmb->nmbQual.val	= g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_nmbqual;
333 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \n");
334 	}
335 	genNmb->natAddrInd.pres = PRSNT_NODEF;
336 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_nadi");
337 	if (!ftdm_strlen_zero(val)) {
338 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"nature of address\" \"%s\"\n", val);
339 		genNmb->natAddrInd.val	= atoi(val);
340 	} else {
341 		genNmb->natAddrInd.val	= g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_nadi;
342 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"nature of address\" \"%d\"\n", genNmb->natAddrInd.val);
343 	}
344 	genNmb->scrnInd.pres = PRSNT_NODEF;
345 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_screen_ind");
346 	if (!ftdm_strlen_zero(val)) {
347 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"screening indicator\" \"%s\"\n", val);
348 		genNmb->scrnInd.val	= atoi(val);
349 	} else {
350 		genNmb->natAddrInd.val	= g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_screen_ind;
351 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"screening indicator\" \"%d\"\n", genNmb->natAddrInd.val);
352 	}
353 	genNmb->presRest.pres = PRSNT_NODEF;
354 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_pres_ind");
355 	if (!ftdm_strlen_zero(val)) {
356 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"presentation indicator\" \"%s\"\n", val);
357 		genNmb->presRest.val	= atoi(val);
358 	} else {
359 		genNmb->presRest.val	= g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_pres_ind;
360 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"presentation indicator\" \"%d\"\n", genNmb->presRest.val);
361 	}
362 	genNmb->numPlan.pres = PRSNT_NODEF;
363 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_npi");
364 	if (!ftdm_strlen_zero(val)) {
365 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"numbering plan\" \"%s\"\n", val);
366 		genNmb->numPlan.val	= atoi(val);
367 	} else {
368 	genNmb->numPlan.val	= g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_npi;
369 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"numbering plan\" \"%d\"\n", genNmb->numPlan.val);
370 	}
371 	genNmb->niInd.pres = PRSNT_NODEF;
372 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_gn_num_inc_ind");
373 	if (!ftdm_strlen_zero(val)) {
374 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Generic Number \"number incomplete indicator\" \"%s\"\n", val);
375 		genNmb->niInd.val	= atoi(val);
376 	} else {
377 		genNmb->niInd.val	= g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].gn_num_inc_ind;
378 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Generic Number \"number incomplete indicator\" \"%d\"\n", genNmb->niInd.val);
379 	}
380 	return FTDM_SUCCESS;
381 }
382 
copy_genNmb_from_sngss7(ftdm_channel_t * ftdmchan,SiGenNum * genNmb)383 ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb)
384 {
385 	char val[64];
386 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
387 
388 	memset(val, 0, sizeof(val));
389 
390 	if (genNmb->eh.pres != PRSNT_NODEF || genNmb->addrSig.pres != PRSNT_NODEF) {
391 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Generic Number available\n");
392 		return FTDM_SUCCESS;
393 	}
394 
395 	copy_tknStr_from_sngss7(genNmb->addrSig, val, genNmb->oddEven);
396 
397 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number:%s\n", val);
398 	sngss7_add_var(sngss7_info, "ss7_gn_digits", val);
399 
400 	if (genNmb->nmbQual.pres == PRSNT_NODEF) {
401 		snprintf(val, sizeof(val), "%d", genNmb->nmbQual.val);
402 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"number qualifier\" \"%s\"\n", val);
403 		sngss7_add_var(sngss7_info, "ss7_gn_numqual", val);
404 	}
405 
406 	if (genNmb->natAddrInd.pres == PRSNT_NODEF) {
407 		snprintf(val, sizeof(val), "%d", genNmb->natAddrInd.val);
408 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"nature of address\" \"%s\"\n", val);
409 		sngss7_add_var(sngss7_info, "ss7_gn_nadi", val);
410 	}
411 
412 	if (genNmb->scrnInd.pres == PRSNT_NODEF) {
413 		snprintf(val, sizeof(val), "%d", genNmb->scrnInd.val);
414 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"screening indicator\" \"%s\"\n", val);
415 		sngss7_add_var(sngss7_info, "ss7_gn_screen_ind", val);
416 	}
417 
418 	if (genNmb->presRest.pres == PRSNT_NODEF) {
419 		snprintf(val, sizeof(val), "%d", genNmb->presRest.val);
420 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"presentation indicator\" \"%s\"\n", val);
421 		sngss7_add_var(sngss7_info, "ss7_gn_pres_ind", val);
422 	}
423 
424 	if (genNmb->numPlan.pres == PRSNT_NODEF) {
425 		snprintf(val, sizeof(val), "%d", genNmb->numPlan.val);
426 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"numbering plan\" \"%s\"\n", val);
427 		sngss7_add_var(sngss7_info, "ss7_gn_npi", val);
428 	}
429 
430 	if (genNmb->niInd.pres == PRSNT_NODEF) {
431 		snprintf(val, sizeof(val), "%d", genNmb->niInd.val);
432 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generic Number \"number incomplete indicator\" \"%s\"\n", val);
433 		sngss7_add_var(sngss7_info, "ss7_gn_num_inc_ind", val);
434 	}
435 
436 	return FTDM_SUCCESS;
437 }
438 
copy_redirgNum_to_sngss7(ftdm_channel_t * ftdmchan,SiRedirNum * redirgNum)439 ftdm_status_t copy_redirgNum_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum)
440 {
441 	const char* val = NULL;
442 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
443 	ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
444 
445 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_digits");
446 	if (!ftdm_strlen_zero(val)) {
447 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Redirection Number\"%s\"\n", val);
448 		if (copy_tknStr_to_sngss7((char*)val, &redirgNum->addrSig, &redirgNum->oddEven) != FTDM_SUCCESS) {
449 			return FTDM_FAIL;
450 		}
451 	} else if (!ftdm_strlen_zero(caller_data->rdnis.digits)) {
452 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Redirection Number\"%s\"\n", caller_data->rdnis.digits);
453 		if (copy_tknStr_to_sngss7(caller_data->rdnis.digits, &redirgNum->addrSig, &redirgNum->oddEven) != FTDM_SUCCESS) {
454 			return FTDM_FAIL;
455 		}
456 	} else {
457 
458 		val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_pres_ind");
459 		if (!ftdm_strlen_zero(val)) {
460 			redirgNum->presRest.val = atoi(val);
461 		}
462 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Address Presentation Restricted Ind:%d\n", redirgNum->presRest.val);
463 
464 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Number\n");
465 		return FTDM_SUCCESS;
466 	}
467 
468 	redirgNum->eh.pres = PRSNT_NODEF;
469 
470 	/* Nature of address indicator */
471 	redirgNum->natAddr.pres = PRSNT_NODEF;
472 
473 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_nadi");
474 	if (!ftdm_strlen_zero(val)) {
475 		redirgNum->natAddr.val = atoi(val);
476 	} else {
477 		redirgNum->natAddr.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].rdnis_nadi;
478 	}
479 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number NADI:%d\n", redirgNum->natAddr.val);
480 
481 	/* Screening indicator */
482 	redirgNum->scrInd.pres = PRSNT_NODEF;
483 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_screen_ind");
484 	if (!ftdm_strlen_zero(val)) {
485 		redirgNum->scrInd.val = atoi(val);
486 	} else {
487 		redirgNum->scrInd.val = FTDM_SCREENING_VERIFIED_PASSED;
488 	}
489 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Screening Ind:%d\n", redirgNum->scrInd.val);
490 
491 	/* Address presentation restricted ind */
492 	redirgNum->presRest.pres = PRSNT_NODEF;
493 
494 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_pres_ind");
495 	if (!ftdm_strlen_zero(val)) {
496 		redirgNum->presRest.val = atoi(val);
497 	} else {
498 		redirgNum->presRest.val =  FTDM_PRES_ALLOWED;
499 	}
500 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Address Presentation Restricted Ind:%d\n", redirgNum->presRest.val);
501 
502 	/* Numbering plan */
503 	redirgNum->numPlan.pres = PRSNT_NODEF;
504 
505 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_plan");
506 	if (!ftdm_strlen_zero(val)) {
507 		redirgNum->numPlan.val = atoi(val);
508 	} else {
509 		redirgNum->numPlan.val = caller_data->rdnis.plan;
510 	}
511 
512 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Numbering plan:%d\n", redirgNum->numPlan.val);
513 
514 	return copy_tknStr_to_sngss7(caller_data->rdnis.digits, &redirgNum->addrSig, &redirgNum->oddEven);
515 }
516 
copy_redirgNum_from_sngss7(ftdm_channel_t * ftdmchan,SiRedirNum * redirgNum)517 ftdm_status_t copy_redirgNum_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum)
518 {
519 	char val[20];
520 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
521 	ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
522 
523 	if (redirgNum->eh.pres != PRSNT_NODEF || redirgNum->addrSig.pres != PRSNT_NODEF) {
524 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Redirecting Number available\n");
525 		return FTDM_SUCCESS;
526 	}
527 
528 	copy_tknStr_from_sngss7(redirgNum->addrSig, ftdmchan->caller_data.rdnis.digits, redirgNum->oddEven);
529 
530 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number:%s\n", ftdmchan->caller_data.rdnis.digits);
531 	snprintf(val, sizeof(val), "%s", ftdmchan->caller_data.rdnis.digits);
532 	sngss7_add_var(sngss7_info, "ss7_rdnis_digits", val);
533 
534 
535 	if (redirgNum->natAddr.pres == PRSNT_NODEF) {
536 		snprintf(val, sizeof(val), "%d", redirgNum->natAddr.val);
537 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number NADI:%s\n", val);
538 		sngss7_add_var(sngss7_info, "ss7_rdnis_nadi", val);
539 		caller_data->rdnis.type = redirgNum->natAddr.val;
540 	}
541 
542 	if (redirgNum->scrInd.pres == PRSNT_NODEF) {
543 		snprintf(val, sizeof(val), "%d", redirgNum->scrInd.val);
544 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Screening Ind:%s\n", val);
545 		sngss7_add_var(sngss7_info, "ss7_rdnis_screen_ind", val);
546 	}
547 
548 	if (redirgNum->presRest.pres == PRSNT_NODEF) {
549 		snprintf(val, sizeof(val), "%d", redirgNum->presRest.val);
550 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Presentation Ind:%s\n", val);
551 		sngss7_add_var(sngss7_info, "ss7_rdnis_pres_ind", val);
552 	}
553 
554 	if (redirgNum->numPlan.pres == PRSNT_NODEF) {
555 		snprintf(val, sizeof(val), "%d", redirgNum->numPlan.val);
556 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Numbering plan:%s\n", val);
557 		sngss7_add_var(sngss7_info, "ss7_rdnis_plan", val);
558 		caller_data->rdnis.plan = redirgNum->numPlan.val;
559 	}
560 
561 	return FTDM_SUCCESS;
562 }
563 
copy_redirgInfo_from_sngss7(ftdm_channel_t * ftdmchan,SiRedirInfo * redirInfo)564 ftdm_status_t copy_redirgInfo_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *redirInfo)
565 {
566 	char val[20];
567 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
568 
569 	if (redirInfo->eh.pres != PRSNT_NODEF ) {
570 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Redirecting Information available\n");
571 		return FTDM_SUCCESS;
572 	}
573 
574 
575 	if (redirInfo->redirInd.pres == PRSNT_NODEF) {
576 		snprintf(val, sizeof(val), "%d", redirInfo->redirInd.val);
577 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirection Information - redirection indicator:%s\n", val);
578 		sngss7_add_var(sngss7_info, "ss7_rdinfo_indicator", val);
579 	}
580 
581 	if (redirInfo->origRedirReas.pres == PRSNT_NODEF) {
582 		snprintf(val, sizeof(val), "%d", redirInfo->origRedirReas.val);
583 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirection Information - original redirection reason:%s\n", val);
584 		sngss7_add_var(sngss7_info, "ss7_rdinfo_orig", val);
585 	}
586 
587 	if (redirInfo->redirCnt.pres == PRSNT_NODEF) {
588 		snprintf(val, sizeof(val), "%d", redirInfo->redirCnt.val);
589 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirection Information - redirection count:%s\n", val);
590 		sngss7_add_var(sngss7_info, "ss7_rdinfo_count", val);
591 	}
592 
593 	if (redirInfo->redirReas.pres == PRSNT_NODEF) {
594 		snprintf(val, sizeof(val), "%d", redirInfo->redirReas.val);
595 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirection Information - redirection reason:%s\n", val);
596 		sngss7_add_var(sngss7_info, "ss7_rdinfo_reason", val);
597 	}
598 
599 	return FTDM_SUCCESS;
600 }
601 
copy_redirgInfo_to_sngss7(ftdm_channel_t * ftdmchan,SiRedirInfo * redirInfo)602 ftdm_status_t copy_redirgInfo_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *redirInfo)
603 {
604 	const char* val = NULL;
605 	int bProceed = 0;
606 
607 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_indicator");
608 	if (!ftdm_strlen_zero(val)) {
609 		redirInfo->redirInd.val = atoi(val);
610 		redirInfo->redirInd.pres = 1;
611 		bProceed = 1;
612 	} else {
613 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Redirection Indicator\n");
614 	}
615 
616 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_orig");
617 	if (!ftdm_strlen_zero(val)) {
618 		redirInfo->origRedirReas.val = atoi(val);
619 		redirInfo->origRedirReas.pres = 1;
620 		bProceed = 1;
621 	} else {
622 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Original Reasons\n");
623 	}
624 
625 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_count");
626 	if (!ftdm_strlen_zero(val)) {
627 		redirInfo->redirCnt.val = atoi(val);
628 		redirInfo->redirCnt.pres= 1;
629 		bProceed = 1;
630 	} else {
631 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Redirection Count\n");
632 	}
633 
634 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_reason");
635 	if (!ftdm_strlen_zero(val)) {
636 		redirInfo->redirReas.val = atoi(val);
637 		redirInfo->redirReas.pres = 1;
638 		bProceed = 1;
639 	} else {
640 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Redirection Reasons\n");
641 	}
642 
643 	if( bProceed == 1 ) {
644 		redirInfo->eh.pres = PRSNT_NODEF;
645 	} else {
646 		redirInfo->eh.pres = NOTPRSNT;
647 	}
648 
649 	return FTDM_SUCCESS;
650 }
651 
copy_access_transport_from_sngss7(ftdm_channel_t * ftdmchan,SiAccTrnspt * accTrnspt)652 ftdm_status_t copy_access_transport_from_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt)
653 {
654 	char val[3*((MF_SIZE_TKNSTRE + 7) & 0xff8)];
655 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
656 
657 	if (accTrnspt->eh.pres != PRSNT_NODEF || accTrnspt->infoElmts.pres !=PRSNT_NODEF) {
658 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Access Transport IE available\n");
659 		return FTDM_SUCCESS;
660 	}
661 
662 	ftdm_url_encode((const char*)accTrnspt->infoElmts.val, val, accTrnspt->infoElmts.len);
663 	sngss7_add_var (sngss7_info, "ss7_access_transport_urlenc", val);
664 
665 	return FTDM_SUCCESS;
666 }
copy_access_transport_to_sngss7(ftdm_channel_t * ftdmchan,SiAccTrnspt * accTrnspt)667 ftdm_status_t copy_access_transport_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt)
668 {
669 	const char *val = NULL;
670 
671 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_access_transport_urlenc");
672 	if (ftdm_strlen_zero(val)) {
673 		accTrnspt->eh.pres = NOTPRSNT;
674 		accTrnspt->infoElmts.pres = NOTPRSNT;
675 	}
676 	else {
677 		char *val_dec = NULL;
678 		int val_len = strlen (val);
679 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found Access Transport IE encoded : %s\n", val);
680 
681 		accTrnspt->eh.pres = PRSNT_NODEF;
682 		accTrnspt->infoElmts.pres = PRSNT_NODEF;
683 
684 		val_dec = ftdm_strdup(val);
685 		ftdm_url_decode(val_dec, (ftdm_size_t*)&val_len);
686 		memcpy (accTrnspt->infoElmts.val, val_dec, val_len);
687 		accTrnspt->infoElmts.len = val_len;
688 		ftdm_safe_free(val_dec);
689 	}
690 	return FTDM_SUCCESS;
691 }
692 
copy_ocn_from_sngss7(ftdm_channel_t * ftdmchan,SiOrigCdNum * origCdNum)693 ftdm_status_t copy_ocn_from_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum)
694 {
695 	char val[20];
696 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
697 
698 	if (origCdNum->eh.pres != PRSNT_NODEF ) {
699 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Original Called Number available\n");
700 		return FTDM_SUCCESS;
701 	}
702 
703 	if (origCdNum->addrSig.pres == PRSNT_NODEF) {
704 		copy_tknStr_from_sngss7(origCdNum->addrSig, val, origCdNum->oddEven);
705 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number - Digits: %s\n", val);
706 		sngss7_add_var(sngss7_info, "ss7_ocn", val);
707 	}
708 
709 	if (origCdNum->natAddr.pres == PRSNT_NODEF) {
710 		snprintf(val, sizeof(val), "%d", origCdNum->natAddr.val);
711 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number - NADI: %s\n", val);
712 		sngss7_add_var(sngss7_info, "ss7_ocn_nadi", val);
713 	}
714 
715 	if (origCdNum->numPlan.pres == PRSNT_NODEF) {
716 		snprintf(val, sizeof(val), "%d", origCdNum->numPlan.val);
717 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number - Plan: %s\n", val);
718 		sngss7_add_var(sngss7_info, "ss7_ocn_plan", val);
719 	}
720 
721 	if (origCdNum->presRest.pres == PRSNT_NODEF) {
722 		snprintf(val, sizeof(val), "%d", origCdNum->presRest.val);
723 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number - Presentation: %s\n", val);
724 		sngss7_add_var(sngss7_info, "ss7_ocn_pres", val);
725 	}
726 
727 	return FTDM_SUCCESS;
728 }
729 
copy_ocn_to_sngss7(ftdm_channel_t * ftdmchan,SiOrigCdNum * origCdNum)730 ftdm_status_t copy_ocn_to_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum)
731 {
732 	const char *val = NULL;
733 	int bProceed = 0;
734 
735 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn");
736 	if (!ftdm_strlen_zero(val)) {
737 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number - Digits: %s\n", val);
738 		if (copy_tknStr_to_sngss7((char*)val, &origCdNum->addrSig, &origCdNum->oddEven) != FTDM_SUCCESS) {
739 			return FTDM_FAIL;
740 		}
741 		origCdNum->addrSig.pres = 1;
742 	} else {
743 		return FTDM_SUCCESS;
744 	}
745 
746 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn_nadi");
747 	if (!ftdm_strlen_zero(val)) {
748 		origCdNum->natAddr.val = atoi(val);
749 		origCdNum->natAddr.pres = 1;
750 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number - NADI: %s\n", val);
751 		bProceed = 1;
752 	} else {
753 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No  user supplied Original Called Number NADI value\n");
754 	}
755 
756 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn_plan");
757 	if (!ftdm_strlen_zero(val)) {
758 		origCdNum->numPlan.val = atoi(val);
759 		origCdNum->numPlan.pres = 1;
760 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number - Plan: %s\n", val);
761 		bProceed = 1;
762 	} else {
763 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No  user supplied Original Called Number Plan value\n");
764 	}
765 
766 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn_pres");
767 	if (!ftdm_strlen_zero(val)) {
768 		origCdNum->presRest.val = atoi(val);
769 		origCdNum->presRest.pres = 1;
770 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number - Presentation: %s\n", val);
771 		bProceed = 1;
772 	} else {
773 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No  user supplied Original Called Number Presentation value\n");
774 	}
775 
776 	if( bProceed == 1 ) {
777 		origCdNum->eh.pres = PRSNT_NODEF;
778 	} else {
779 		origCdNum->eh.pres = NOTPRSNT;
780 	}
781 
782 	return FTDM_SUCCESS;
783 }
784 
copy_cgPtyCat_to_sngss7(ftdm_channel_t * ftdmchan,SiCgPtyCat * cgPtyCat)785 ftdm_status_t copy_cgPtyCat_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat)
786 {
787 	ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
788 
789 	cgPtyCat->eh.pres 			= PRSNT_NODEF;
790 	cgPtyCat->cgPtyCat.pres 	= PRSNT_NODEF;
791 
792 	cgPtyCat->cgPtyCat.val = get_trillium_val(cpc_codes, caller_data->cpc, CAT_ORD);
793 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Category:0x%x\n",cgPtyCat->cgPtyCat.val);
794 	return FTDM_SUCCESS;
795 }
796 
copy_cgPtyCat_from_sngss7(ftdm_channel_t * ftdmchan,SiCgPtyCat * cgPtyCat)797 ftdm_status_t copy_cgPtyCat_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat)
798 {
799 	ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
800 
801 	if (cgPtyCat->eh.pres == PRSNT_NODEF &&
802 		cgPtyCat->cgPtyCat.pres 	== PRSNT_NODEF) {
803 
804 		caller_data->cpc = get_ftdm_val(cpc_codes, cgPtyCat->cgPtyCat.val, FTDM_CPC_UNKNOWN);
805 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Category:0x%x\n", cgPtyCat->cgPtyCat.val);
806 	}
807 	return FTDM_SUCCESS;
808 }
809 
810 
copy_accTrnspt_to_sngss7(ftdm_channel_t * ftdmchan,SiAccTrnspt * accTrnspt)811 ftdm_status_t copy_accTrnspt_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt)
812 {
813 	const char			*clg_subAddr = NULL;
814 	const char			*cld_subAddr = NULL;
815 	char 				subAddrIE[MAX_SIZEOF_SUBADDR_IE];
816 
817 	/* check if the user would like us to send a clg_sub-address */
818 	clg_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_subaddr");
819 	if (!ftdm_strlen_zero(clg_subAddr)) {
820 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr);
821 
822 		/* clean out the subAddrIE */
823 		memset(subAddrIE, 0x0, sizeof(subAddrIE));
824 
825 		/* check the first character in the sub-address to see what type of encoding to use */
826 		switch (clg_subAddr[0]) {
827 			case '0':						/* NSAP */
828 				encode_subAddrIE_nsap(&clg_subAddr[1], subAddrIE, SNG_CALLING);
829 				break;
830 				case '1':						/* national variant */
831 					encode_subAddrIE_nat(&clg_subAddr[1], subAddrIE, SNG_CALLING);
832 					break;
833 			default:
834 				ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid Calling Sub-Address encoding requested: %c\n", clg_subAddr[0]);
835 				break;
836 		} /* switch (cld_subAddr[0]) */
837 
838 
839 		/* if subaddIE is still empty don't copy it in */
840 		if (subAddrIE[0] != '0') {
841 			/* check if the clg_subAddr has already been added */
842 			if (accTrnspt->eh.pres == PRSNT_NODEF) {
843 				/* append the subAddrIE */
844 				memcpy(&accTrnspt->infoElmts.val[accTrnspt->infoElmts.len], subAddrIE, (subAddrIE[1] + 2));
845 				accTrnspt->infoElmts.len		= accTrnspt->infoElmts.len +subAddrIE[1] + 2;
846 			} else {
847 				/* fill in from the beginning */
848 				accTrnspt->eh.pres			= PRSNT_NODEF;
849 				accTrnspt->infoElmts.pres	= PRSNT_NODEF;
850 				memcpy(accTrnspt->infoElmts.val, subAddrIE, (subAddrIE[1] + 2));
851 				accTrnspt->infoElmts.len		= subAddrIE[1] + 2;
852 			}
853 		}
854 	}
855 
856 	/* check if the user would like us to send a cld_sub-address */
857 	cld_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_subaddr");
858 	if ((cld_subAddr != NULL) && (*cld_subAddr)) {
859 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr);
860 
861 		/* clean out the subAddrIE */
862 		memset(subAddrIE, 0x0, sizeof(subAddrIE));
863 
864 		/* check the first character in the sub-address to see what type of encoding to use */
865 		switch (cld_subAddr[0]) {
866 			case '0':						/* NSAP */
867 				encode_subAddrIE_nsap(&cld_subAddr[1], subAddrIE, SNG_CALLED);
868 				break;
869 				case '1':						/* national variant */
870 					encode_subAddrIE_nat(&cld_subAddr[1], subAddrIE, SNG_CALLED);
871 					break;
872 			default:
873 				ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid Called Sub-Address encoding requested: %c\n", cld_subAddr[0]);
874 				break;
875 		} /* switch (cld_subAddr[0]) */
876 
877 		/* if subaddIE is still empty don't copy it in */
878 		if (subAddrIE[0] != '0') {
879 			/* check if the cld_subAddr has already been added */
880 			if (accTrnspt->eh.pres == PRSNT_NODEF) {
881 				/* append the subAddrIE */
882 				memcpy(&accTrnspt->infoElmts.val[accTrnspt->infoElmts.len], subAddrIE, (subAddrIE[1] + 2));
883 				accTrnspt->infoElmts.len		= accTrnspt->infoElmts.len +subAddrIE[1] + 2;
884 			} else {
885 				/* fill in from the beginning */
886 				accTrnspt->eh.pres			= PRSNT_NODEF;
887 				accTrnspt->infoElmts.pres	= PRSNT_NODEF;
888 				memcpy(accTrnspt->infoElmts.val, subAddrIE, (subAddrIE[1] + 2));
889 				accTrnspt->infoElmts.len		= subAddrIE[1] + 2;
890 			}
891 		}
892 	} /* if ((cld_subAddr != NULL) && (*cld_subAddr)) */
893 	return FTDM_SUCCESS;
894 }
895 
copy_natConInd_to_sngss7(ftdm_channel_t * ftdmchan,SiNatConInd * natConInd)896 ftdm_status_t copy_natConInd_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd)
897 {
898 	/* copy down the nature of connection indicators */
899 	natConInd->eh.pres 				= PRSNT_NODEF;
900 	natConInd->satInd.pres 			= PRSNT_NODEF;
901 	natConInd->satInd.val 			= 0; /* no satellite circuit */
902 	natConInd->contChkInd.pres 		= PRSNT_NODEF;
903 	natConInd->contChkInd.val 		= CONTCHK_NOTREQ;
904 	natConInd->echoCntrlDevInd.pres	= PRSNT_NODEF;
905 	natConInd->echoCntrlDevInd.val 	= ECHOCDEV_INCL;
906 	return FTDM_SUCCESS;
907 }
908 
four_char_to_hex(const char * in,uint16_t * out)909 ftdm_status_t four_char_to_hex(const char* in, uint16_t* out)
910 {
911 	int i= 4;
912 	char a, b, c, d;
913 	if (!in || 4>strlen(in)) {
914 		return FTDM_FAIL;
915 	}
916 	while(i)
917 	{
918 		switch((char)*(in+(4-i))) {
919 		case '0':
920 		case '1':
921 		case '2':
922 		case '3':
923 		case '4':
924 		case '5':
925 		case '6':
926 		case '7':
927 		case '8':
928 		case '9':
929 			if (i==4) {
930 				d = *(in+(4-i)) - 48;
931 			} else if (i==3) {
932 				c = *(in+(4-i)) - 48;
933 			} else if (i==2) {
934 				b = *(in+(4-i)) - 48;
935 			} else {
936 				a = *(in+(4-i)) - 48;
937 			}
938 			break;
939 		case 'A':
940 		case 'B':
941 		case 'C':
942 		case 'D':
943 		case 'E':
944 		case 'F':
945 			if (i==4) {
946 				d = *(in+(4-i)) - 55;
947 			} else if (i==3) {
948 				c = *(in+(4-i)) - 55;
949 			} else if (i==2) {
950 				b = *(in+(4-i)) - 55;
951 			} else {
952 				a = *(in+(4-i)) - 55;
953 			}
954 			break;
955 		case 'a':
956 		case 'b':
957 		case 'c':
958 		case 'd':
959 		case 'e':
960 		case 'f':
961 			if (i==4) {
962 				d = *(in+(4-i)) - 87;
963 			} else if (i==3) {
964 				c = *(in+(4-i)) - 87;
965 			} else if (i==2) {
966 				b = *(in+(4-i)) - 87;
967 			} else {
968 				a = *(in+(4-i)) - 87;
969 			}
970 			break;
971 		default:
972 			SS7_ERROR("Invalid character found when decoding hex string, %c!\n", *(in+(4-i)) );
973 			break;
974 		}
975 		i--;
976 	};
977 
978 	*out |= d;
979 	*out = *out<<4;
980 	*out |= c;
981 	*out = *out<<4;
982 	*out |= b;
983 	*out = *out<<4;
984 	*out |= a;
985 
986 	return FTDM_SUCCESS;
987 }
988 
char_to_hex(const char * in,uint16_t * out,int len)989 ftdm_status_t char_to_hex(const char* in, uint16_t* out, int len)
990 {
991 	int i= len;
992 	char *val = ftdm_malloc(len*sizeof(char));
993 
994 	if (!val ||!in || len>strlen(in)) {
995 		return FTDM_FAIL;
996 	}
997 
998 	while(i)
999 	{
1000 		switch((char)*(in+(len-i))) {
1001 		case '0':
1002 		case '1':
1003 		case '2':
1004 		case '3':
1005 		case '4':
1006 		case '5':
1007 		case '6':
1008 		case '7':
1009 		case '8':
1010 		case '9':
1011 			*(val+(len-i)) = *(in+(len-i)) - 48;
1012 			break;
1013 		case 'A':
1014 		case 'B':
1015 		case 'C':
1016 		case 'D':
1017 		case 'E':
1018 		case 'F':
1019 			*(val+(len-i)) = *(in+(len-i)) - 55;
1020 			break;
1021 		case 'a':
1022 		case 'b':
1023 		case 'c':
1024 		case 'd':
1025 		case 'e':
1026 		case 'f':
1027 			*(val+(len-i)) = *(in+(len-i)) - 87;
1028 			break;
1029 		default:
1030 			SS7_ERROR("Invalid character found when decoding hex string, %c!\n", *(in+(len-i)) );
1031 			break;
1032 		}
1033 		i--;
1034 	};
1035 
1036 	for (i=0; i<=len-1; i++) {
1037 		*out = *out << 4;
1038 		*out |= *(val+i);
1039 	}
1040 
1041 	return FTDM_SUCCESS;
1042 }
1043 
1044 
1045 
hex_to_char(uint16_t in,char * out,int len)1046 ftdm_status_t hex_to_char(uint16_t in, char* out, int len)
1047 {
1048 	char val=0;
1049 	int mask = 0xf;
1050 	int i=0;
1051 	if (!out)  {
1052 		return FTDM_SUCCESS;
1053 	}
1054 
1055 	for (i=len-1; i>=0; i--) {
1056 		val = (in & (mask<<(4*i))) >> (4*i);
1057 		sprintf (out+(len-1-i), "%x", val);
1058 	}
1059 
1060 	return FTDM_SUCCESS;
1061 }
hex_to_four_char(uint16_t in,char * out)1062 ftdm_status_t hex_to_four_char(uint16_t in, char* out)
1063 {
1064 	char val=0;
1065 	int mask = 0xf;
1066 	int i=0;
1067 	if (!out)  {
1068 		return FTDM_SUCCESS;
1069 	}
1070 
1071 	for (i=3; i>=0; i--) {
1072 		val = (in & (mask<<(4*i))) >> (4*i);
1073 		sprintf (out+(3-i), "%x", val);
1074 	}
1075 
1076 	return FTDM_SUCCESS;
1077 }
1078 
copy_NatureOfConnection_to_sngss7(ftdm_channel_t * ftdmchan,SiNatConInd * natConInd)1079 ftdm_status_t copy_NatureOfConnection_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd)
1080 {
1081 	const char *val = NULL;
1082 
1083 	natConInd->eh.pres 				= PRSNT_NODEF;
1084 	natConInd->satInd.pres 			= PRSNT_NODEF;
1085 	natConInd->contChkInd.pres		= PRSNT_NODEF;;
1086 	natConInd->echoCntrlDevInd.pres 	= PRSNT_NODEF;
1087 
1088 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_nature_connection_hex");
1089 	if (!ftdm_strlen_zero(val)) {
1090 		uint16_t val_hex = 0;
1091 		if (char_to_hex (val, &val_hex, 2) == FTDM_FAIL) {
1092 			SS7_ERROR ("Wrong value set in ss7_iam_nature_connection_hex variable. Please correct the error. Setting to default values.\n" );
1093 		} else {
1094 			ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "hex =  0x%x\n", val_hex);
1095 			natConInd->satInd.val 			= (val_hex & 0x3);
1096 			natConInd->contChkInd.val		= (val_hex & 0xc)>>2;
1097 			natConInd->echoCntrlDevInd.val	= (val_hex & 0x10) >> 4;
1098 
1099 			return FTDM_SUCCESS;
1100 		}
1101 	}
1102 
1103 	natConInd->satInd.val 			= 0;
1104 	natConInd->contChkInd.val		= 0;
1105 	natConInd->echoCntrlDevInd.val 	= 0;
1106 
1107 	return FTDM_SUCCESS;
1108 }
1109 
copy_NatureOfConnection_from_sngss7(ftdm_channel_t * ftdmchan,SiNatConInd * natConInd)1110 ftdm_status_t copy_NatureOfConnection_from_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd )
1111 {
1112 	char val[3];
1113 	uint16_t val_hex = 0;
1114 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
1115 
1116 	memset (val, 0, 3*sizeof(char));
1117 	if (natConInd->eh.pres != PRSNT_NODEF ) {
1118 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No nature of connection indicator IE available\n");
1119 		return FTDM_SUCCESS;
1120 	}
1121 
1122 	val_hex |= natConInd->satInd.val;
1123 	val_hex |= natConInd->contChkInd.val << 2;
1124 	val_hex |= natConInd->echoCntrlDevInd.val <<4;
1125 	hex_to_char(val_hex, val, 2) ;
1126 
1127 	sngss7_add_var(sngss7_info, "ss7_iam_nature_connection_hex", val);
1128 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Nature of connection indicator Hex: 0x%s\n", val);
1129 
1130 	return FTDM_SUCCESS;
1131 }
1132 
copy_fwdCallInd_hex_from_sngss7(ftdm_channel_t * ftdmchan,SiFwdCallInd * fwdCallInd)1133 ftdm_status_t copy_fwdCallInd_hex_from_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd)
1134 {
1135 	char val[5];
1136 	uint16_t val_hex = 0;
1137 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
1138 
1139 	memset (val, 0, 5*sizeof(char));
1140 	if (fwdCallInd->eh.pres != PRSNT_NODEF ) {
1141 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No forward call indicator IE available\n");
1142 		return FTDM_SUCCESS;
1143 	}
1144 
1145 	val_hex |= fwdCallInd->natIntCallInd.val << 8;
1146 	val_hex |= (fwdCallInd->end2EndMethInd.val & 0x1) << 9;
1147 	val_hex |= ((fwdCallInd->end2EndMethInd.val & 0x2)>>1) << 10;
1148 	val_hex |= fwdCallInd->intInd.val << 11;
1149 	val_hex |= fwdCallInd->end2EndInfoInd.val << 12;
1150 	val_hex |= fwdCallInd->isdnUsrPrtInd.val << 13;
1151 	val_hex |= (fwdCallInd->isdnUsrPrtPrfInd.val & 0x1) << 14;
1152 	val_hex |= ((fwdCallInd->isdnUsrPrtPrfInd.val & 0x2)>>1) << 15;
1153 
1154 	val_hex |= fwdCallInd->isdnAccInd.val;
1155 	hex_to_four_char(val_hex, val) ;
1156 
1157 	sngss7_add_var(sngss7_info, "ss7_iam_fwd_ind_hex", val);
1158 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Forwad Call Indicator Hex: 0x%s\n", val);
1159 
1160 	return FTDM_SUCCESS;
1161 }
1162 
copy_fwdCallInd_to_sngss7(ftdm_channel_t * ftdmchan,SiFwdCallInd * fwdCallInd)1163 ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd)
1164 {
1165 	const char *val = NULL;
1166 	int acc_val = ISDNACC_ISDN;
1167 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
1168 
1169 	fwdCallInd->eh.pres 				= PRSNT_NODEF;
1170 	fwdCallInd->natIntCallInd.pres 		= PRSNT_NODEF;
1171 	fwdCallInd->end2EndMethInd.pres 	= PRSNT_NODEF;
1172 	fwdCallInd->intInd.pres 			= PRSNT_NODEF;
1173 	fwdCallInd->end2EndInfoInd.pres 	= PRSNT_NODEF;
1174 	fwdCallInd->isdnUsrPrtInd.pres 		= PRSNT_NODEF;
1175 	fwdCallInd->isdnUsrPrtPrfInd.pres 	= PRSNT_NODEF;
1176 	fwdCallInd->isdnAccInd.pres 		= PRSNT_NODEF;
1177 	fwdCallInd->sccpMethInd.pres 		= PRSNT_NODEF;
1178 	fwdCallInd->sccpMethInd.val 		= SCCPMTH_NOIND;
1179 
1180 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_fwd_ind_hex");
1181 	if (!ftdm_strlen_zero(val)) {
1182 		uint16_t val_hex = 0;
1183 		if (four_char_to_hex (val, &val_hex) == FTDM_FAIL) {
1184 			SS7_ERROR ("Wrong value set in iam_fwd_ind_HEX variable. Please correct the error. Setting to default values.\n" );
1185 		} else {
1186 			fwdCallInd->natIntCallInd.val 		= (val_hex & 0x100)>>8;
1187 			fwdCallInd->end2EndMethInd.val 	= (val_hex & 0x600)>>9;
1188 			fwdCallInd->intInd.val 			= (val_hex & 0x800)>>11;
1189 			fwdCallInd->end2EndInfoInd.val 	= (val_hex & 0x1000)>>12;
1190 			fwdCallInd->isdnUsrPrtInd.val 		= (val_hex & 0x2000)>>13;
1191 			fwdCallInd->isdnUsrPrtPrfInd.val 	= (val_hex & 0xC000)>>14;
1192 			fwdCallInd->isdnUsrPrtPrfInd.val 	= (fwdCallInd->isdnUsrPrtPrfInd.val==0x03)?0x0:fwdCallInd->isdnUsrPrtPrfInd.val;
1193 			fwdCallInd->isdnAccInd.val 		= val_hex & 0x1;
1194 
1195 			if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) ||
1196 				(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) ||
1197 				(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) {
1198 
1199 				/* include only if we're running ANSI */
1200 				fwdCallInd->transCallNInd.pres   = PRSNT_NODEF;
1201 				fwdCallInd->transCallNInd.val    = 0x0;
1202 			}
1203 
1204 			return FTDM_SUCCESS;
1205 		}
1206 	}
1207 
1208 	fwdCallInd->natIntCallInd.val 		= 0x00;
1209 	fwdCallInd->end2EndMethInd.val 	= E2EMTH_NOMETH;
1210 	fwdCallInd->intInd.val 			= INTIND_NOINTW;
1211 	fwdCallInd->end2EndInfoInd.val 	= E2EINF_NOINFO;
1212 	fwdCallInd->isdnUsrPrtInd.val 		= ISUP_USED;
1213 	fwdCallInd->isdnUsrPrtPrfInd.val 	= PREF_PREFAW;
1214 
1215 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_fwd_ind_isdn_access_ind");
1216 	if (ftdm_strlen_zero(val)) {
1217 		/* Kept for backward compatibility */
1218 		val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "iam_fwd_ind_isdn_access_ind");
1219 	}
1220 
1221 	if (!ftdm_strlen_zero(val)) {
1222 		acc_val = (int)atoi(val);
1223 	}
1224 
1225 	fwdCallInd->isdnAccInd.val 		= acc_val;
1226 
1227 	if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) ||
1228 		(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) ||
1229 		(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) {
1230 
1231 		/* include only if we're running ANSI */
1232 		fwdCallInd->transCallNInd.pres   = PRSNT_NODEF;
1233 		fwdCallInd->transCallNInd.val    = 0x0;
1234 	}
1235 
1236 	return FTDM_SUCCESS;
1237 }
1238 
copy_txMedReq_to_sngss7(ftdm_channel_t * ftdmchan,SiTxMedReq * txMedReq)1239 ftdm_status_t copy_txMedReq_to_sngss7(ftdm_channel_t *ftdmchan, SiTxMedReq *txMedReq)
1240 {
1241 	txMedReq->eh.pres 		= PRSNT_NODEF;
1242 	txMedReq->trMedReq.pres = PRSNT_NODEF;
1243 	txMedReq->trMedReq.val 	= ftdmchan->caller_data.bearer_capability;
1244 
1245 	return FTDM_SUCCESS;
1246 }
1247 
copy_usrServInfoA_to_sngss7(ftdm_channel_t * ftdmchan,SiUsrServInfo * usrServInfoA)1248 ftdm_status_t copy_usrServInfoA_to_sngss7(ftdm_channel_t *ftdmchan, SiUsrServInfo *usrServInfoA)
1249 {
1250 	int bProceed = 0;
1251 	const char *val = NULL;
1252 
1253 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_trans_cap");
1254 	if (!ftdm_strlen_zero(val)) {
1255 		int itc_type = 0;
1256 		if (!strcasecmp(val, "SPEECH")) {
1257 			itc_type = ITC_SPEECH;
1258 		} else if (!strcasecmp(val, "UNRESTRICTED")) {
1259 			itc_type = ITC_UNRDIG;
1260 		} else if (!strcasecmp(val, "RESTRICTED")) {
1261 			itc_type = ITC_RESDIG;
1262 		} else if (!strcasecmp(val, "31KHZ")) {
1263 			itc_type = ITC_A31KHZ;
1264 		} else if (!strcasecmp(val, "7KHZ")) {
1265 			itc_type = ITC_A7KHZ;
1266 		} else if (!strcasecmp(val, "15KHZ")) {
1267 			itc_type = ITC_A15KHZ;
1268 		} else if (!strcasecmp(val, "VIDEO")) {
1269 			itc_type = ITC_VIDEO;
1270 		} else {
1271 			itc_type = ITC_SPEECH;
1272 			ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI transmission capability parameter is wrong : %s. Setting to default SPEECH. \n", val );
1273 		}
1274 
1275 		usrServInfoA->infoTranCap.pres	= PRSNT_NODEF;
1276 		usrServInfoA->infoTranCap.val = get_trillium_val(bc_cap_codes, ftdmchan->caller_data.bearer_capability, itc_type);
1277 		bProceed = 1;
1278 	} else {
1279 		usrServInfoA->infoTranCap.pres	= NOTPRSNT;
1280 	}
1281 
1282 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_code_standard");
1283 	if (!ftdm_strlen_zero(val)) {
1284 		usrServInfoA->cdeStand.pres			= PRSNT_NODEF;
1285 		usrServInfoA->cdeStand.val			= (int)atoi(val);	/* default is 0x0 */
1286 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI coding standard = %d\n", usrServInfoA->cdeStand.val );
1287 		bProceed = 1;
1288 	} else {
1289 		usrServInfoA->cdeStand.pres			= NOTPRSNT;
1290 	}
1291 
1292 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_trans_mode");
1293 	if (!ftdm_strlen_zero(val)) {
1294 		usrServInfoA->tranMode.pres			= PRSNT_NODEF;
1295 		usrServInfoA->tranMode.val			= (int)atoi(val);				/* transfer mode, default is 0x0*/
1296 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI transfer mode = %d\n", usrServInfoA->tranMode.val );
1297 		bProceed = 1;
1298 	} else {
1299 		usrServInfoA->tranMode.pres			= NOTPRSNT;
1300 	}
1301 
1302 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_trans_rate_0");
1303 	if (!ftdm_strlen_zero(val)) {
1304 		usrServInfoA->infoTranRate0.pres		= PRSNT_NODEF;
1305 		usrServInfoA->infoTranRate0.val		= (int)atoi(val);			/* default is 0x10, 64kbps origination to destination*/
1306 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI trans rate 0 = %d\n", usrServInfoA->infoTranRate0.val );
1307 		bProceed = 1;
1308 	} else {
1309 		usrServInfoA->infoTranRate0.pres		= NOTPRSNT;
1310 	}
1311 
1312 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_trans_rate_1");
1313 	if (!ftdm_strlen_zero(val)) {
1314 		usrServInfoA->infoTranRate1.pres		= PRSNT_NODEF;
1315 		usrServInfoA->infoTranRate1.val		= (int)atoi(val);			/* 64kbps destination to origination, default is 0x10 */
1316 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI trans rate 1 = %d\n", usrServInfoA->infoTranRate1.val );
1317 		bProceed = 1;
1318 	} else {
1319 		usrServInfoA->infoTranRate1.pres		= NOTPRSNT;
1320 	}
1321 
1322 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer1_ident");
1323 	if (!ftdm_strlen_zero(val)) {
1324 		usrServInfoA->lyr1Ident.pres			= PRSNT_NODEF;
1325 		usrServInfoA->lyr1Ident.val			= (int)atoi(val);		/*default value is 0x01 */
1326 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 1 indentification = %d\n", usrServInfoA->lyr1Ident.val );
1327 		bProceed = 1;
1328 	} else {
1329 		usrServInfoA->lyr1Ident.pres			= NOTPRSNT;
1330 	}
1331 
1332 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer1_prot");
1333 	if (!ftdm_strlen_zero(val)) {
1334 		usrServInfoA->usrInfLyr1Prot.pres		= PRSNT_NODEF;
1335 		usrServInfoA->usrInfLyr1Prot.val		= (int)atoi(val);		/*default value is 0x02 */
1336 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 1 protocol = %d\n", usrServInfoA->usrInfLyr1Prot.val );
1337 		bProceed = 1;
1338 	} else {
1339 		usrServInfoA->usrInfLyr1Prot.pres		= NOTPRSNT;
1340 	}
1341 
1342 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer2_ident");
1343 	if (!ftdm_strlen_zero(val)) {
1344 		usrServInfoA->lyr2Ident.pres			= PRSNT_NODEF;
1345 		usrServInfoA->lyr2Ident.val			= (int)atoi(val);		/*default value is 0x01 */
1346 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 2 indentification = %d\n", usrServInfoA->lyr2Ident.val );
1347 		bProceed = 1;
1348 	} else {
1349 		usrServInfoA->lyr2Ident.pres			= NOTPRSNT;
1350 	}
1351 
1352 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer2_prot");
1353 	if (!ftdm_strlen_zero(val)) {
1354 		usrServInfoA->usrInfLyr2Prot.pres		= PRSNT_NODEF;
1355 		usrServInfoA->usrInfLyr2Prot.val		= (int)atoi(val);		/*default value is 0x02 */
1356 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 2 protocol = %d\n", usrServInfoA->usrInfLyr2Prot.val );
1357 		bProceed = 1;
1358 	} else {
1359 		usrServInfoA->usrInfLyr2Prot.pres		= NOTPRSNT;
1360 	}
1361 
1362 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer3_ident");
1363 	if (!ftdm_strlen_zero(val)) {
1364 		usrServInfoA->lyr3Ident.pres			= PRSNT_NODEF;
1365 		usrServInfoA->lyr3Ident.val			= (int)atoi(val);		/*default value is 0x01 */
1366 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 3 indentification = %d\n", usrServInfoA->lyr3Ident.val );
1367 		bProceed = 1;
1368 	} else {
1369 		usrServInfoA->lyr3Ident.pres			= NOTPRSNT;
1370 	}
1371 
1372 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_layer3_prot");
1373 	if (!ftdm_strlen_zero(val)) {
1374 		usrServInfoA->usrInfLyr3Prot.pres		= PRSNT_NODEF;
1375 		usrServInfoA->usrInfLyr3Prot.val		= (int)atoi(val);		/*default value is 0x02 */
1376 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI layer 3 protocol = %d\n", usrServInfoA->usrInfLyr3Prot.val );
1377 		bProceed = 1;
1378 	} else {
1379 		usrServInfoA->usrInfLyr3Prot.pres		= NOTPRSNT;
1380 	}
1381 
1382 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_chan_struct");
1383 	if (!ftdm_strlen_zero(val)) {
1384 		usrServInfoA->chanStruct.pres			= PRSNT_NODEF;
1385 		usrServInfoA->chanStruct.val			= (int)atoi(val);                          /* default value is 0x1, 8kHz integrity */
1386 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI channel structure = %d\n", usrServInfoA->chanStruct.val );
1387 		bProceed = 1;
1388 	} else {
1389 		usrServInfoA->chanStruct.pres			= NOTPRSNT;
1390 	}
1391 
1392 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_config");
1393 	if (!ftdm_strlen_zero(val)) {
1394 		usrServInfoA->config.pres				= PRSNT_NODEF;
1395 		usrServInfoA->config.val				= (int)atoi(val);                          /* default value is 0x0, point to point configuration */
1396 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI configuration = %d\n", usrServInfoA->config.val );
1397 		bProceed = 1;
1398 	} else {
1399 		usrServInfoA->config.pres				= NOTPRSNT;
1400 	}
1401 
1402 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_establish");
1403 	if (!ftdm_strlen_zero(val)) {
1404 		usrServInfoA->establish.pres			= PRSNT_NODEF;
1405 		usrServInfoA->establish.val			= (int)atoi(val);                           /* default value is 0x0, on demand */
1406 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI establishment = %d\n", usrServInfoA->establish.val );
1407 		bProceed = 1;
1408 	} else {
1409 		usrServInfoA->establish.pres			= NOTPRSNT;
1410 	}
1411 
1412 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_symmetry");
1413 	if (!ftdm_strlen_zero(val)) {
1414 		usrServInfoA->symmetry.pres			= PRSNT_NODEF;
1415 		usrServInfoA->symmetry.val			= (int)atoi(val);                           /* default value is 0x0, bi-directional symmetric */
1416 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI symmetry = %d\n", usrServInfoA->symmetry.val );
1417 		bProceed = 1;
1418 	} else {
1419 		usrServInfoA->symmetry.pres			= NOTPRSNT;
1420 	}
1421 
1422 	val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam_usi_rate_multiplier");
1423 	if (!ftdm_strlen_zero(val)) {
1424 		usrServInfoA->rateMultiplier.pres		= PRSNT_NODEF;
1425 		usrServInfoA->rateMultiplier.val		= (int)atoi(val);                           /* default value is 0x1, 1x rate multipler */
1426 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "USI rate multipier = %d\n", usrServInfoA->rateMultiplier.val );
1427 		bProceed = 1;
1428 	} else {
1429 		usrServInfoA->rateMultiplier.pres		= NOTPRSNT;
1430 	}
1431 
1432 	if (bProceed) {
1433 		usrServInfoA->eh.pres				= PRSNT_NODEF;
1434 	} else {
1435 		usrServInfoA->eh.pres				= NOTPRSNT;
1436 	}
1437 
1438 	return FTDM_SUCCESS;
1439 }
1440 
1441 
1442 
copy_tknStr_from_sngss7(TknStr str,char * ftdm,TknU8 oddEven)1443 ftdm_status_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven)
1444 {
1445 	uint8_t i;
1446 	uint8_t j;
1447 
1448 	/* check if the token string is present */
1449 	if (str.pres == 1) {
1450 		j = 0;
1451 
1452 		for (i = 0; i < str.len; i++) {
1453 			sprintf(&ftdm[j], "%X", (str.val[i] & 0x0F));
1454 			j++;
1455 			sprintf(&ftdm[j], "%X", ((str.val[i] & 0xF0) >> 4));
1456 			j++;
1457 		}
1458 
1459 		/* if the odd flag is up the last digit is a fake "0" */
1460 		if ((oddEven.pres == 1) && (oddEven.val == 1)) {
1461 			ftdm[j-1] = '\0';
1462 		} else {
1463 			ftdm[j] = '\0';
1464 		}
1465 
1466 
1467 	} else {
1468 		SS7_ERROR("Asked to copy tknStr that is not present!\n");
1469 		return FTDM_FAIL;
1470 	}
1471 
1472 	return FTDM_SUCCESS;
1473 }
1474 
1475 /******************************************************************************/
append_tknStr_from_sngss7(TknStr str,char * ftdm,TknU8 oddEven)1476 ftdm_status_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven)
1477 {
1478 	int i = 0;
1479 	int j = 0;
1480 
1481 	/* check if the token string is present */
1482 	if (str.pres == 1) {
1483 		/* find the length of the digits so far */
1484 		j = strlen(ftdm);
1485 
1486 		/* confirm that we found an acceptable length */
1487 		if ( j > 25 ) {
1488 			SS7_ERROR("string length exceeds maxium value...aborting append!\n");
1489 			return FTDM_FAIL;
1490 		} /* if ( j > 25 ) */
1491 
1492 		/* copy in digits */
1493 		for (i = 0; i < str.len; i++) {
1494 			/* convert 4 bit integer to char and copy into lower nibblet*/
1495 			sprintf(&ftdm[j], "%X", (str.val[i] & 0x0F));
1496 			/* move along */
1497 			j++;
1498 			/* convert 4 bit integer to char and copy into upper nibblet */
1499 			sprintf(&ftdm[j], "%X", ((str.val[i] & 0xF0) >> 4));
1500 			/* move along */
1501 			j++;
1502 		} /* for (i = 0; i < str.len; i++) */
1503 
1504 		/* if the odd flag is up the last digit is a fake "0" */
1505 		if ((oddEven.pres == 1) && (oddEven.val == 1)) {
1506 			ftdm[j-1] = '\0';
1507 		} else {
1508 			ftdm[j] = '\0';
1509 		} /* if ((oddEven.pres == 1) && (oddEven.val == 1)) */
1510 	} else {
1511 		SS7_ERROR("Asked to copy tknStr that is not present!\n");
1512 		return FTDM_FAIL;
1513 	} /* if (str.pres == 1) */
1514 
1515 	return FTDM_SUCCESS;
1516 }
1517 
1518 
copy_tknStr_to_sngss7(char * val,TknStr * tknStr,TknU8 * oddEven)1519 ftdm_status_t copy_tknStr_to_sngss7(char* val, TknStr *tknStr, TknU8 *oddEven)
1520 {
1521 	char tmp[2];
1522 	int k = 0;
1523 	int j = 0;
1524 	uint8_t flag = 0;
1525 	uint8_t odd = 0;
1526 
1527 	uint8_t lower = 0x0;
1528 	uint8_t upper = 0x0;
1529 
1530 	tknStr->pres = PRSNT_NODEF;
1531 
1532 	/* atoi will search through memory starting from the pointer it is given until
1533 	* it finds the \0...since tmp is on the stack it will start going through the
1534 	* possibly causing corruption.  Hard code a \0 to prevent this
1535 	*/
1536 	tmp[1] = '\0';
1537 
1538 	while (1) {
1539 		/* grab a digit from the ftdm digits */
1540 		tmp[0] = val[k];
1541 
1542 		/* check if the digit is a number and that is not null */
1543 		while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
1544 			if (tmp[0] == '*') {
1545 				/* Could not find a spec that specifies this , but on customer system, * was transmitted as 0x0b */
1546 				SS7_DEBUG("Replacing * with 0x0b");
1547 				k++;
1548 				tmp[0] = 0x0b;
1549 			} else {
1550 				SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
1551 				/* move on to the next value */
1552 				k++;
1553 				tmp[0] = val[k];
1554 			}
1555 		} /* while(!(isdigit(tmp))) */
1556 
1557 		/* check if tmp is null or a digit */
1558 		if (tmp[0] != '\0') {
1559 			/* push it into the lower nibble */
1560 			lower = strtol(&tmp[0], (char **)NULL, 16);
1561 			/* move to the next digit */
1562 			k++;
1563 			/* grab a digit from the ftdm digits */
1564 			tmp[0] = val[k];
1565 
1566 			/* check if the digit is a number and that is not null */
1567 			while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
1568 				SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
1569 				k++;
1570 				tmp[0] = val[k];
1571 			} /* while(!(isdigit(tmp))) */
1572 
1573 			/* check if tmp is null or a digit */
1574 			if (tmp[0] != '\0') {
1575 				/* push the digit into the upper nibble */
1576 				upper = (strtol(&tmp[0], (char **)NULL, 16)) << 4;
1577 			} else {
1578 				/* there is no upper ... fill in 0 */
1579 				upper = 0x0;
1580 				/* throw the odd flag */
1581 				odd = 1;
1582 				/* throw the end flag */
1583 				flag = 1;
1584 			} /* if (tmp != '\0') */
1585 		} else {
1586 			/* keep the odd flag down */
1587 			odd = 0;
1588 			/* break right away since we don't need to write the digits */
1589 			break;
1590 		}
1591 
1592 		/* push the digits into the trillium structure */
1593 		tknStr->val[j] = upper | lower;
1594 
1595 		/* increment the trillium pointer */
1596 		j++;
1597 
1598 		/* if the flag is up we're through all the digits */
1599 		if (flag) break;
1600 
1601 		/* move to the next digit */
1602 		k++;
1603 	} /* while(1) */
1604 
1605 	tknStr->len = j;
1606 	oddEven->pres = PRSNT_NODEF;
1607 	oddEven->val = odd;
1608 	return FTDM_SUCCESS;
1609 }
1610 
1611 
1612 
1613 /******************************************************************************/
check_for_state_change(ftdm_channel_t * ftdmchan)1614 int check_for_state_change(ftdm_channel_t *ftdmchan)
1615 {
1616 
1617 	/* check to see if there are any pending state changes on the channel and give them a sec to happen*/
1618 	ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 500);
1619 
1620 	/* check the flag to confirm it is clear now */
1621 
1622 	if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
1623 		/* the flag is still up...so we have a problem */
1624 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "FTDM_CHANNEL_STATE_CHANGE flag set for over 500ms, channel state = %s\n",
1625 									ftdm_channel_state2str (ftdmchan->state));
1626 
1627 		return 1;
1628 	}
1629 
1630 	return 0;
1631 }
1632 
1633 /******************************************************************************/
extract_chan_data(uint32_t circuit,sngss7_chan_data_t ** sngss7_info,ftdm_channel_t ** ftdmchan)1634 ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan)
1635 {
1636 	if (!g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj) {
1637 		SS7_ERROR("No ss7 info for circuit #%d\n", circuit);
1638 		return FTDM_FAIL;
1639 	}
1640 
1641 	*sngss7_info = g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj;
1642 
1643 	if (!(*sngss7_info)->ftdmchan) {
1644 		SS7_ERROR("No ftdmchan for circuit #%d\n", circuit);
1645 		return FTDM_FAIL;
1646 	}
1647 
1648 	if (!(*sngss7_info)->ftdmchan->span) {
1649 		SS7_CRITICAL("ftdmchan->span = NULL for circuit #%d\n",circuit);
1650 		return FTDM_FAIL;
1651 
1652 	}
1653 	if (!(*sngss7_info)->ftdmchan->span->signal_data) {
1654 		SS7_CRITICAL("ftdmchan->span->signal_data = NULL for circuit #%d\n",circuit);
1655 		return FTDM_FAIL;
1656 
1657 	}
1658 
1659 	*ftdmchan = (*sngss7_info)->ftdmchan;
1660 	return FTDM_SUCCESS;
1661 }
1662 
1663 /******************************************************************************/
check_for_reset(sngss7_chan_data_t * sngss7_info)1664 int check_for_reset(sngss7_chan_data_t *sngss7_info)
1665 {
1666 
1667 	if (sngss7_test_ckt_flag(sngss7_info,FLAG_RESET_RX)) {
1668 		return 1;
1669 	}
1670 
1671 	if (sngss7_test_ckt_flag(sngss7_info,FLAG_RESET_TX)) {
1672 		return 1;
1673 	}
1674 
1675 	if (sngss7_test_ckt_flag(sngss7_info,FLAG_GRP_RESET_RX)) {
1676 		return 1;
1677 	}
1678 
1679 	if (sngss7_test_ckt_flag(sngss7_info,FLAG_GRP_RESET_TX)) {
1680 		return 1;
1681 	}
1682 
1683 	return 0;
1684 
1685 }
1686 
1687 /******************************************************************************/
get_unique_id(void)1688 unsigned long get_unique_id(void)
1689 {
1690 	int	procId = sng_get_procId();
1691 
1692 	/* id values are between (procId * 1,000,000) and ((procId + 1) * 1,000,000) */
1693 	if (sngss7_id < ((procId + 1) * 1000000) ) {
1694 		sngss7_id++;
1695 	} else {
1696 		sngss7_id = procId * 1000000;
1697 	}
1698 
1699 	return(sngss7_id);
1700 }
1701 
1702 /******************************************************************************/
check_if_rx_grs_started(ftdm_span_t * ftdmspan)1703 ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan)
1704 {
1705 	ftdm_iterator_t *iter = NULL;
1706 	ftdm_iterator_t *curr = NULL;
1707 	ftdm_channel_t *ftdmchan = NULL;
1708 	sngss7_chan_data_t *sngss7_info = NULL;
1709 	sngss7_chan_data_t *cinfo = NULL;
1710 	int i = 0;
1711 
1712 	iter = ftdm_span_get_chan_iterator(ftdmspan, NULL);
1713 	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
1714 		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
1715 
1716 		ftdm_channel_lock(fchan);
1717 
1718 		cinfo = fchan->call_data;
1719 
1720 		if (!cinfo->rx_grs.range) {
1721 			ftdm_channel_unlock(fchan);
1722 			continue;
1723 		}
1724 
1725 		SS7_INFO("Rx GRS (%d:%d)\n",
1726 				g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_grs.circuit].cic,
1727 				(g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_grs.circuit].cic + cinfo->rx_grs.range));
1728 
1729 		for (i = cinfo->rx_grs.circuit; i < (cinfo->rx_grs.circuit + cinfo->rx_grs.range + 1); i++) {
1730 
1731 			/* confirm this is a voice channel, otherwise we do nothing */
1732 			if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
1733 				continue;
1734 			}
1735 
1736 			/* extract the channel in question */
1737 			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
1738 				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
1739 				continue;
1740 			}
1741 
1742 			/* check if the GRP_RESET_RX flag is already up */
1743 			if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) {
1744 				/* we have already processed this channel...move along */
1745 				continue;
1746 			}
1747 
1748 			/* lock the channel */
1749 			ftdm_channel_lock(ftdmchan);
1750 
1751 			/* clear up any pending state changes */
1752 			while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
1753 				ftdm_sangoma_ss7_process_state_change (ftdmchan);
1754 			}
1755 
1756 			/* flag the channel as having received a reset */
1757 			sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX);
1758 
1759 			switch (ftdmchan->state) {
1760 			/**************************************************************************/
1761 			case FTDM_CHANNEL_STATE_RESTART:
1762 
1763 				/* go to idle so that we can redo the restart state*/
1764 				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
1765 
1766 				break;
1767 			/**************************************************************************/
1768 			default:
1769 
1770 				/* set the state of the channel to restart...the rest is done by the chan monitor */
1771 				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
1772 				break;
1773 			/**************************************************************************/
1774 			}
1775 
1776 			/* unlock the channel again before we exit */
1777 			ftdm_channel_unlock(ftdmchan);
1778 
1779 		}
1780 
1781 		ftdm_channel_unlock(fchan);
1782 	}
1783 
1784 	ftdm_iterator_free(iter);
1785 
1786 	return FTDM_SUCCESS;
1787 }
1788 
1789 /******************************************************************************/
check_if_rx_grs_processed(ftdm_span_t * ftdmspan)1790 ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
1791 {
1792 	ftdm_iterator_t *iter = NULL;
1793 	ftdm_iterator_t *curr = NULL;
1794 	ftdm_channel_t *ftdmchan = NULL;
1795 	sngss7_chan_data_t *sngss7_info = NULL;
1796 	sngss7_chan_data_t *cinfo = NULL;
1797 	int i = 0, bn = 0;
1798 	int byte = 0, bit = 0;
1799 	int cic_start = 0, cic_end = 0, num_cics = 0;
1800 	ftdm_bitmap_t *lockmap = 0;
1801 	ftdm_size_t mapsize = 0;
1802 
1803 	iter = ftdm_span_get_chan_iterator(ftdmspan, NULL);
1804 	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
1805 		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
1806 
1807 		ftdm_channel_lock(fchan);
1808 
1809 		cinfo = fchan->call_data;
1810 
1811 		if (!cinfo->rx_grs.range) {
1812 
1813 			ftdm_channel_unlock(fchan);
1814 
1815 			continue;
1816 		}
1817 
1818 		cic_start = cinfo->rx_grs.circuit;
1819 		cic_end = cinfo->rx_grs.circuit + cinfo->rx_grs.range;
1820 		num_cics = cinfo->rx_grs.range + 1;
1821 		mapsize = (num_cics / FTDM_BITMAP_NBITS) + 1;
1822 
1823 		lockmap = ftdm_calloc(mapsize, sizeof(*lockmap));
1824 		if (!lockmap) {
1825 			ftdm_channel_unlock(fchan);
1826 			return FTDM_ENOMEM;
1827 		}
1828 
1829 		/* check all the circuits in the range to see if they are done resetting */
1830 		for (i = cic_start, bn = 0; i <= cic_end; i++, bn++) {
1831 
1832 			/* confirm this is a voice channel, otherwise we do nothing */
1833 			if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
1834 				continue;
1835 			}
1836 
1837 			/* extract the channel in question */
1838 			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
1839 				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
1840 				ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n");
1841 				continue;
1842 			}
1843 
1844 			/* lock the channel */
1845 			ftdm_channel_lock(ftdmchan);
1846 			ftdm_map_set_bit(lockmap, bn);
1847 
1848 			/* check if there is a state change pending on the channel */
1849 			if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
1850 				/* check the state to the GRP_RESET_RX_DN flag */
1851 				if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) {
1852 					/* this channel is still resetting...do nothing */
1853 					goto GRS_UNLOCK_ALL;
1854 				} /* if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */
1855 			} else {
1856 				/* state change pending */
1857 				goto GRS_UNLOCK_ALL;
1858 			}
1859 
1860 		}
1861 
1862 		SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n", cinfo->rx_grs.circuit, cinfo->rx_grs.range);
1863 		for (i = cic_start; i <= cic_end; i++) {
1864 
1865 			/* confirm this is a voice channel, otherwise we do nothing */
1866 			if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
1867 				continue;
1868 			}
1869 
1870 			/* extract the channel in question */
1871 			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
1872 				SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
1873 				ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n");
1874 				continue;
1875 			}
1876 
1877 			/* throw the GRP reset flag complete flag */
1878 			sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
1879 
1880 			/* move the channel to the down state */
1881 			ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
1882 
1883 			/* update the status map if the ckt is in blocked state */
1884 			if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
1885 				(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
1886 				(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) ||
1887 				(sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
1888 
1889 				cinfo->rx_grs.status[byte] = (cinfo->rx_grs.status[byte] | (1 << bit));
1890 			}
1891 
1892 			/* update the bit and byte counter*/
1893 			bit ++;
1894 			if (bit == 8) {
1895 				byte++;
1896 				bit = 0;
1897 			}
1898 
1899 		}
1900 GRS_UNLOCK_ALL:
1901 		for (i = cic_start, bn = 0; i <= cic_end; i++, bn++) {
1902 			/* confirm this is a voice channel, otherwise we do nothing */
1903 			if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
1904 				continue;
1905 			}
1906 
1907 			/* extract the channel in question */
1908 			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
1909 				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
1910 				ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n");
1911 				continue;
1912 			}
1913 			if (ftdm_map_test_bit(lockmap, bn)) {
1914 				/* unlock the channel */
1915 				ftdm_channel_unlock(ftdmchan);
1916 				ftdm_map_clear_bit(lockmap, bn);
1917 			}
1918 		}
1919 
1920 		ftdm_safe_free(lockmap);
1921 
1922 		ftdm_channel_unlock(fchan);
1923 	}
1924 
1925 	ftdm_iterator_free(iter);
1926 
1927 	return FTDM_SUCCESS;
1928 }
1929 
1930 /******************************************************************************/
check_if_rx_gra_started(ftdm_span_t * ftdmspan)1931 ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan)
1932 {
1933 	ftdm_iterator_t *iter = NULL;
1934 	ftdm_iterator_t *curr = NULL;
1935 	ftdm_channel_t *ftdmchan = NULL;
1936 	sngss7_chan_data_t *sngss7_info = NULL;
1937 	sngss7_chan_data_t *cinfo = NULL;
1938 	int i = 0;
1939 
1940 	iter = ftdm_span_get_chan_iterator(ftdmspan, NULL);
1941 
1942 	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
1943 		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
1944 		ftdm_channel_lock(fchan);
1945 
1946 		cinfo = fchan->call_data;
1947 
1948 		if (!cinfo->rx_gra.range) {
1949 
1950 			ftdm_channel_unlock(fchan);
1951 
1952 			continue;
1953 		}
1954 
1955 		SS7_INFO("Rx GRA (%d:%d)\n",
1956 				g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_gra.circuit].cic,
1957 				(g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_gra.circuit].cic + cinfo->rx_gra.range));
1958 
1959 		for (i = cinfo->rx_gra.circuit; i < (cinfo->rx_gra.circuit + cinfo->rx_gra.range + 1); i++) {
1960 
1961 			/* confirm this is a voice channel, otherwise we do nothing */
1962 			if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) {
1963 				continue;
1964 			}
1965 
1966 			/* extract the channel in question */
1967 			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
1968 				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
1969 				continue;
1970 			}
1971 
1972 			/* check if the channel is already processing the GRA */
1973 			if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
1974 				/* move along */
1975 				continue;
1976 			}
1977 
1978 			/* lock the channel */
1979 			ftdm_channel_lock(ftdmchan);
1980 
1981 			/* clear up any pending state changes */
1982 			while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
1983 				ftdm_sangoma_ss7_process_state_change (ftdmchan);
1984 			}
1985 
1986 			switch (ftdmchan->state) {
1987 			/**********************************************************************/
1988 			case FTDM_CHANNEL_STATE_RESTART:
1989 
1990 				/* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
1991 				sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
1992 
1993 				/* go to DOWN */
1994 				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
1995 
1996 				break;
1997 			/**********************************************************************/
1998 			case FTDM_CHANNEL_STATE_DOWN:
1999 
2000 				/* do nothing, just drop the message */
2001 				SS7_DEBUG("Receveived GRA in down state, dropping\n");
2002 
2003 				break;
2004 			/**********************************************************************/
2005 			case FTDM_CHANNEL_STATE_TERMINATING:
2006 			case FTDM_CHANNEL_STATE_HANGUP:
2007 			case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
2008 
2009 				/* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
2010 				sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
2011 
2012 				break;
2013 			/**********************************************************************/
2014 			default:
2015 				/* ITU Q764-2.9.5.1.c -> release the circuit */
2016 				if (cinfo->rx_gra.cause != 0) {
2017 					ftdmchan->caller_data.hangup_cause = cinfo->rx_gra.cause;
2018 				} else {
2019 					ftdmchan->caller_data.hangup_cause = 98;	/* Message not compatiable with call state */
2020 				}
2021 
2022 				/* go to terminating to hang up the call */
2023 				ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
2024 				break;
2025 			/**********************************************************************/
2026 			}
2027 
2028 			ftdm_channel_unlock(ftdmchan);
2029 		}
2030 
2031 		ftdm_channel_unlock(fchan);
2032 	}
2033 
2034 	ftdm_iterator_free(iter);
2035 
2036 	return FTDM_SUCCESS;
2037 }
2038 
2039 /******************************************************************************/
check_for_res_sus_flag(ftdm_span_t * ftdmspan)2040 ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan)
2041 {
2042 	ftdm_channel_t		*ftdmchan = NULL;
2043 	sngss7_chan_data_t	*sngss7_info = NULL;
2044 	ftdm_sigmsg_t 		sigev;
2045 	int 				x;
2046 
2047 	for (x = 1; x < (ftdmspan->chan_count + 1); x++) {
2048 
2049 		/* extract the channel structure and sngss7 channel data */
2050 		ftdmchan = ftdmspan->channels[x];
2051 
2052 		/* if the call data is NULL move on */
2053 		if (ftdmchan->call_data == NULL) continue;
2054 
2055 		sngss7_info = ftdmchan->call_data;
2056 
2057 		/* lock the channel */
2058 		ftdm_mutex_lock(ftdmchan->mutex);
2059 
2060 		memset (&sigev, 0, sizeof (sigev));
2061 
2062 		sigev.chan_id = ftdmchan->chan_id;
2063 		sigev.span_id = ftdmchan->span_id;
2064 		sigev.channel = ftdmchan;
2065 
2066 		/* if we have the PAUSED flag and the sig status is still UP */
2067 		if ((sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_PAUSED)) &&
2068 			(ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP))) {
2069 
2070 			/* clear up any pending state changes */
2071 			while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
2072 				ftdm_sangoma_ss7_process_state_change (ftdmchan);
2073 			}
2074 
2075 			/* throw the channel into SUSPENDED to process the flag */
2076 			/* after doing this once the sig status will be down */
2077 			ftdm_set_state (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
2078 		}
2079 
2080 		/* if the RESUME flag is up go to SUSPENDED to process the flag */
2081 		/* after doing this the flag will be cleared */
2082 		if (sngss7_test_ckt_flag(sngss7_info, FLAG_INFID_RESUME)) {
2083 
2084 			/* clear up any pending state changes */
2085 			while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
2086 				ftdm_sangoma_ss7_process_state_change (ftdmchan);
2087 			}
2088 
2089 			/* got SUSPENDED state to clear the flag */
2090 			ftdm_set_state (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
2091 		}
2092 
2093 		/* unlock the channel */
2094 		ftdm_mutex_unlock(ftdmchan->mutex);
2095 
2096 	} /* for (x = 1; x < (span->chan_count + 1); x++) */
2097 
2098 	/* signal the core that sig events are queued for processing */
2099 	ftdm_span_trigger_signals(ftdmspan);
2100 
2101 	return FTDM_SUCCESS;
2102 }
2103 
2104 /******************************************************************************/
process_span_ucic(ftdm_span_t * ftdmspan)2105 ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan)
2106 {
2107 	ftdm_iterator_t *iter = NULL;
2108 	ftdm_iterator_t *curr = NULL;
2109 	ftdm_channel_t *ftdmchan = NULL;
2110 	sngss7_chan_data_t *sngss7_info = NULL;
2111 	sngss7_chan_data_t *cinfo = NULL;
2112 	sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
2113 	int i = 0;
2114 
2115 	iter = ftdm_span_get_chan_iterator(ftdmspan, NULL);
2116 	curr = iter;
2117 	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
2118 		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
2119 
2120 		ftdm_channel_lock(fchan);
2121 
2122 		cinfo = fchan->call_data;
2123 
2124 		if (!cinfo->ucic.range) {
2125 
2126 			ftdm_channel_unlock(fchan);
2127 
2128 			continue;
2129 		}
2130 
2131 		for (i = cinfo->ucic.circuit; i < (cinfo->ucic.circuit + cinfo->ucic.range + 1); i++) {
2132 
2133 			/* extract the channel in question */
2134 			if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
2135 				SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
2136 				continue;
2137 			}
2138 
2139 			/* lock the channel */
2140 			ftdm_channel_lock(ftdmchan);
2141 
2142 			SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx Span UCIC\n", sngss7_info->circuit->cic);
2143 
2144 			/* clear up any pending state changes */
2145 			while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
2146 				ftdm_sangoma_ss7_process_state_change (ftdmchan);
2147 			}
2148 
2149 			/* throw the ckt block flag */
2150 			sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
2151 
2152 			/* set the channel to suspended state */
2153 			ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
2154 
2155 			/* unlock the channel again before we exit */
2156 			ftdm_channel_unlock(ftdmchan);
2157 		}
2158 		/* clear out the ucic data since we're done with it */
2159 		memset(&cinfo->ucic, 0, sizeof(cinfo->ucic));
2160 
2161 		ftdm_channel_unlock(fchan);
2162 	}
2163 
2164 	ftdm_clear_flag(sngss7_span, SNGSS7_UCIC_PENDING);
2165 
2166 	ftdm_iterator_free(iter);
2167 
2168 	return FTDM_SUCCESS;
2169 }
2170 
2171 /******************************************************************************/
clear_rx_grs_flags(sngss7_chan_data_t * sngss7_info)2172 ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info)
2173 {
2174 	/* clear all the flags related to an incoming GRS */
2175 	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX);
2176 	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN);
2177 	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT);
2178 
2179 	return FTDM_SUCCESS;
2180 }
2181 
2182 /******************************************************************************/
clear_rx_grs_data(sngss7_chan_data_t * sngss7_info)2183 ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info)
2184 {
2185 	ftdm_iterator_t *iter = NULL;
2186 	ftdm_iterator_t *curr = NULL;
2187 	sngss7_chan_data_t *cinfo = NULL;
2188 	ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
2189 	sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmchan->span->signal_data;
2190 
2191 	memset(&sngss7_info->rx_grs, 0, sizeof(sngss7_info->rx_grs));
2192 
2193 	iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL);
2194 	curr = iter;
2195 	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
2196 		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
2197 
2198 		ftdm_channel_lock(fchan);
2199 
2200 		cinfo = fchan->call_data;
2201 		if (cinfo->rx_grs.range) {
2202 			/* there is still another grs pending, do not clear the SNGSS7_RX_GRS_PENDING flag yet */
2203 			ftdm_channel_unlock(fchan);
2204 			goto done;
2205 		}
2206 
2207 		ftdm_channel_unlock(fchan);
2208 	}
2209 
2210 	/* if we're here is because there is no other grs going on now in this span */
2211 	ftdm_clear_flag(sngss7_span, SNGSS7_RX_GRS_PENDING);
2212 
2213 done:
2214 	ftdm_iterator_free(iter);
2215 
2216 	return FTDM_SUCCESS;
2217 }
2218 
2219 /******************************************************************************/
clear_rx_gra_data(sngss7_chan_data_t * sngss7_info)2220 ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info)
2221 {
2222 	ftdm_iterator_t *iter = NULL;
2223 	ftdm_iterator_t *curr = NULL;
2224 	sngss7_chan_data_t *cinfo = NULL;
2225 	ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
2226 	sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data;
2227 
2228 	/* clear the rx_grs data fields */
2229 	memset(&sngss7_info->rx_gra, 0, sizeof(sngss7_info->rx_gra));
2230 
2231 	iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL);
2232 	curr = iter;
2233 	for (curr = iter; curr; curr = ftdm_iterator_next(curr)) {
2234 		ftdm_channel_t *fchan = ftdm_iterator_current(curr);
2235 
2236 		ftdm_channel_lock(fchan);
2237 
2238 		cinfo = fchan->call_data;
2239 		if (cinfo->rx_gra.range) {
2240 			/* there is still another gra pending, do not clear the SNGSS7_RX_GRA_PENDING flag yet */
2241 			ftdm_channel_unlock(fchan);
2242 			goto done;
2243 		}
2244 
2245 		ftdm_channel_unlock(fchan);
2246 	}
2247 
2248 	/* if we're here is because there is no other gra pending in this span */
2249 	ftdm_clear_flag(sngss7_span, SNGSS7_RX_GRA_PENDING);
2250 
2251 done:
2252 
2253 	ftdm_iterator_free(iter);
2254 
2255 	return FTDM_SUCCESS;
2256 }
2257 /******************************************************************************/
clear_tx_grs_flags(sngss7_chan_data_t * sngss7_info)2258 ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info)
2259 {
2260 	/* clear all the flags related to an outgoing GRS */
2261 	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE);
2262 	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX);
2263 	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_SENT);
2264 	sngss7_clear_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
2265 
2266 	return FTDM_SUCCESS;
2267 }
2268 
2269 /******************************************************************************/
clear_tx_grs_data(sngss7_chan_data_t * sngss7_info)2270 ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info)
2271 {
2272 	/* clear everything up */
2273 	memset(&sngss7_info->tx_grs, 0, sizeof(sngss7_info->tx_grs));
2274 	return FTDM_SUCCESS;
2275 }
2276 
2277 /******************************************************************************/
2278 
2279 /******************************************************************************/
clear_rx_rsc_flags(sngss7_chan_data_t * sngss7_info)2280 ftdm_status_t clear_rx_rsc_flags(sngss7_chan_data_t *sngss7_info)
2281 {
2282 	/* clear all the flags related to an incoming RSC */
2283 	sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_RX);
2284 
2285 	return FTDM_SUCCESS;
2286 }
2287 
2288 /******************************************************************************/
clear_tx_rsc_flags(sngss7_chan_data_t * sngss7_info)2289 ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info)
2290 {
2291 	/* clear all the flags related to an outgoing RSC */
2292 	sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_TX);
2293 	sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_SENT);
2294 	sngss7_clear_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP);
2295 
2296 	return FTDM_SUCCESS;
2297 }
2298 
2299 /******************************************************************************/
encode_subAddrIE_nsap(const char * subAddr,char * subAddrIE,int type)2300 ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type)
2301 {
2302 	/* Q931 4.5.9
2303 	 * 8	7	6	5	4	3	2	1	(octet)
2304 	 *
2305 	 * 0	1	1	1	0	0	0	1	(spare 8) ( IE id 1-7)
2306 	 * X	X	X	X	X	X	X	X	(length of IE contents)
2307 	 * 1	0	0	0	Z	0	0	0	(ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3)
2308 	 * X	X	X	X	X	X	X	X	(sub address encoded in ia5)
2309 	 */
2310 
2311 	int	x = 0;
2312 	int p = 0;
2313 	int len = 0;
2314 	char tmp[2];
2315 
2316 	/* initalize the second element of tmp to \0 so that atoi doesn't go to far */
2317 	tmp[1]='\0';
2318 
2319 	/* set octet 1 aka IE id */
2320 	p = 0;
2321 	switch(type) {
2322 	/**************************************************************************/
2323 	case SNG_CALLED:						/* called party sub address */
2324 		subAddrIE[p] = 0x71;
2325 		break;
2326 	/**************************************************************************/
2327 	case SNG_CALLING:						/* calling party sub address */
2328 		subAddrIE[p] = 0x6d;
2329 		break;
2330 	/**************************************************************************/
2331 	default:								/* not good */
2332 		SS7_ERROR("Sub-Address type is invalid: %d\n", type);
2333 		return FTDM_FAIL;
2334 		break;
2335 	/**************************************************************************/
2336 	} /* switch(type) */
2337 
2338 	/* set octet 3 aka type and o/e */
2339 	p = 2;
2340 	subAddrIE[p] = 0x80;
2341 
2342 	/* set the subAddrIE pointer octet 4 */
2343 	p = 3;
2344 
2345 	/* loop through all digits in subAddr and insert them into subAddrIE */
2346 	while (subAddr[x] != '\0') {
2347 
2348 		/* grab a character */
2349 		tmp[0] = subAddr[x];
2350 
2351 		/* confirm it is a digit */
2352 		if (!isdigit(tmp[0])) {
2353 			SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
2354 			/* move to the next character in subAddr */
2355 			x++;
2356 
2357 			/* restart the loop */
2358 			continue;
2359 		}
2360 
2361 		/* convert the character to IA5 encoding and write into subAddrIE */
2362 		subAddrIE[p] = atoi(&tmp[0]);	/* lower nibble is the digit */
2363 		subAddrIE[p] |= 0x3 << 4;		/* upper nibble is 0x3 */
2364 
2365 		/* increment address length counter */
2366 		len++;
2367 
2368 		/* increment the subAddrIE pointer */
2369 		p++;
2370 
2371 		/* move to the next character in subAddr */
2372 		x++;
2373 
2374 	} /* while (subAddr[x] != '\0') */
2375 
2376 	/* set octet 2 aka length of subaddr */
2377 	p = 1;
2378 	subAddrIE[p] = len + 1;
2379 
2380 
2381 	return FTDM_SUCCESS;
2382 }
2383 
2384 /******************************************************************************/
encode_subAddrIE_nat(const char * subAddr,char * subAddrIE,int type)2385 ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type)
2386 {
2387 	/* Q931 4.5.9
2388 	 * 8	7	6	5	4	3	2	1	(octet)
2389 	 *
2390 	 * 0	1	1	1	0	0	0	1	(spare 8) ( IE id 1-7)
2391 	 * X	X	X	X	X	X	X	X	(length of IE contents)
2392 	 * 1	0	0	0	Z	0	0	0	(ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3)
2393 	 * X	X	X	X	X	X	X	X	(sub address encoded in ia5)
2394 	 */
2395 
2396 	int		x = 0;
2397 	int 	p = 0;
2398 	int 	len = 0;
2399 	char 	tmp[2];
2400 	int 	flag = 0;
2401 	int 	odd = 0;
2402 	uint8_t	lower = 0x0;
2403 	uint8_t upper = 0x0;
2404 
2405 	/* initalize the second element of tmp to \0 so that atoi doesn't go to far */
2406 	tmp[1]='\0';
2407 
2408 	/* set octet 1 aka IE id */
2409 	p = 0;
2410 	switch(type) {
2411 	/**************************************************************************/
2412 	case SNG_CALLED:						/* called party sub address */
2413 		subAddrIE[p] = 0x71;
2414 		break;
2415 	/**************************************************************************/
2416 	case SNG_CALLING:						/* calling party sub address */
2417 		subAddrIE[p] = 0x6d;
2418 		break;
2419 	/**************************************************************************/
2420 	default:								/* not good */
2421 		SS7_ERROR("Sub-Address type is invalid: %d\n", type);
2422 		return FTDM_FAIL;
2423 		break;
2424 	/**************************************************************************/
2425 	} /* switch(type) */
2426 
2427 	/* set the subAddrIE pointer octet 4 */
2428 	p = 3;
2429 
2430 	/* loop through all digits in subAddr and insert them into subAddrIE */
2431 	while (1) {
2432 
2433 		/* grab a character */
2434 		tmp[0] = subAddr[x];
2435 
2436 		/* confirm it is a hex digit */
2437 		while ((!isxdigit(tmp[0])) && (tmp[0] != '\0')) {
2438 			if (tmp[0] == '*') {
2439 				/* Could not find a spec that specifies this, but on customer system, * was transmitted as 0x0b */
2440 				SS7_DEBUG("Replacing * with 0x0b");
2441 				x++;
2442 				tmp[0] = 0x0b;
2443 			} else {
2444 				SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
2445 				/* move to the next character in subAddr */
2446 				x++;
2447 				tmp[0] = subAddr[x];
2448 			}
2449 		}
2450 
2451 		/* check if tmp is null or a digit */
2452 		if (tmp[0] != '\0') {
2453 			/* push it into the lower nibble using strtol to allow a-f chars */
2454 			lower = strtol(&tmp[0], (char **)NULL, 16);
2455 			/* move to the next digit */
2456 			x++;
2457 			/* grab a digit from the ftdm digits */
2458 			tmp[0] = subAddr[x];
2459 
2460 			/* check if the digit is a hex digit and that is not null */
2461 			while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
2462 				SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
2463 				x++;
2464 				tmp[0] = subAddr[x];
2465 			} /* while(!(isdigit(tmp))) */
2466 
2467 			/* check if tmp is null or a digit */
2468 			if (tmp[0] != '\0') {
2469 				/* push the digit into the upper nibble using strtol to allow a-f chars */
2470 				upper = (strtol(&tmp[0], (char **)NULL, 16)) << 4;
2471 			} else {
2472 				/* there is no upper ... fill in spare */
2473 				upper = 0x00;
2474 				/* throw the odd flag since we need to buffer */
2475 				odd = 1;
2476 				/* throw the end flag */
2477 				flag = 1;
2478 			} /* if (tmp != '\0') */
2479 		} else {
2480 			/* keep the odd flag down */
2481 			odd = 0;
2482 
2483 			/* throw the flag */
2484 			flag = 1;
2485 
2486 			/* bounce out right away */
2487 			break;
2488 		}
2489 
2490 		/* fill in the octet */
2491 		subAddrIE[p] = upper | lower;
2492 
2493 		/* increment address length counter */
2494 		len++;
2495 
2496 		/* if the flag is we're through all the digits */
2497 		if (flag) break;
2498 
2499 		/* increment the subAddrIE pointer */
2500 		p++;
2501 
2502 		/* move to the next character in subAddr */
2503 		x++;
2504 
2505 	} /* while (subAddr[x] != '\0') */
2506 
2507 	/* set octet 2 aka length of subaddr */
2508 	p = 1;
2509 	subAddrIE[p] = len + 1;
2510 
2511 	/* set octet 3 aka type and o/e */
2512 	p = 2;
2513 	subAddrIE[p] = 0xa0 | (odd << 3);
2514 
2515 
2516 	return FTDM_SUCCESS;
2517 }
2518 
2519 /******************************************************************************/
find_mtp2_error_type_in_map(const char * err_type)2520 int find_mtp2_error_type_in_map(const char *err_type)
2521 {
2522 	int i = 0;
2523 
2524 	while (sng_mtp2_error_type_map[i].init == 1) {
2525 		/* check if string matches the sng_type name */
2526 		if (!strcasecmp(err_type, sng_mtp2_error_type_map[i].sng_type)) {
2527 			/* we've found a match break from the loop */
2528 			break;
2529 		} else {
2530 			/* move on to the next on */
2531 			i++;
2532 		}
2533 	} /* while (sng_mtp2_error_type_map[i].init == 1) */
2534 
2535 	/* check how we exited the loop */
2536 	if (sng_mtp2_error_type_map[i].init == 0) {
2537 		return -1;
2538 	} else {
2539 		return i;
2540 	} /* if (sng_mtp2_error_type_map[i].init == 0) */
2541 }
2542 
2543 /******************************************************************************/
find_link_type_in_map(const char * linkType)2544 int find_link_type_in_map(const char *linkType)
2545 {
2546 	int i = 0;
2547 
2548 	while (sng_link_type_map[i].init == 1) {
2549 		/* check if string matches the sng_type name */
2550 		if (!strcasecmp(linkType, sng_link_type_map[i].sng_type)) {
2551 			/* we've found a match break from the loop */
2552 			break;
2553 		} else {
2554 			/* move on to the next on */
2555 			i++;
2556 		}
2557 	} /* while (sng_link_type_map[i].init == 1) */
2558 
2559 	/* check how we exited the loop */
2560 	if (sng_link_type_map[i].init == 0) {
2561 		return -1;
2562 	} else {
2563 		return i;
2564 	} /* if (sng_link_type_map[i].init == 0) */
2565 }
2566 
2567 /******************************************************************************/
find_switch_type_in_map(const char * switchType)2568 int find_switch_type_in_map(const char *switchType)
2569 {
2570 	int i = 0;
2571 
2572 	while (sng_switch_type_map[i].init == 1) {
2573 		/* check if string matches the sng_type name */
2574 		if (!strcasecmp(switchType, sng_switch_type_map[i].sng_type)) {
2575 			/* we've found a match break from the loop */
2576 			break;
2577 		} else {
2578 			/* move on to the next on */
2579 			i++;
2580 		}
2581 	} /* while (sng_switch_type_map[i].init == 1) */
2582 
2583 	/* check how we exited the loop */
2584 	if (sng_switch_type_map[i].init == 0) {
2585 		return -1;
2586 	} else {
2587 		return i;
2588 	} /* if (sng_switch_type_map[i].init == 0) */
2589 }
2590 
2591 /******************************************************************************/
find_ssf_type_in_map(const char * ssfType)2592 int find_ssf_type_in_map(const char *ssfType)
2593 {
2594 	int i = 0;
2595 
2596 	while (sng_ssf_type_map[i].init == 1) {
2597 		/* check if string matches the sng_type name */
2598 		if (!strcasecmp(ssfType, sng_ssf_type_map[i].sng_type)) {
2599 			/* we've found a match break from the loop */
2600 			break;
2601 		} else {
2602 			/* move on to the next on */
2603 			i++;
2604 		}
2605 	} /* while (sng_ssf_type_map[i].init == 1) */
2606 
2607 	/* check how we exited the loop */
2608 	if (sng_ssf_type_map[i].init == 0) {
2609 		return -1;
2610 	} else {
2611 		return i;
2612 	} /* if (sng_ssf_type_map[i].init == 0) */
2613 }
2614 
2615 /******************************************************************************/
find_cic_cntrl_in_map(const char * cntrlType)2616 int find_cic_cntrl_in_map(const char *cntrlType)
2617 {
2618 	int i = 0;
2619 
2620 	while (sng_cic_cntrl_type_map[i].init == 1) {
2621 		/* check if string matches the sng_type name */
2622 		if (!strcasecmp(cntrlType, sng_cic_cntrl_type_map[i].sng_type)) {
2623 			/* we've found a match break from the loop */
2624 			break;
2625 		} else {
2626 			/* move on to the next on */
2627 			i++;
2628 		}
2629 	} /* while (sng_cic_cntrl_type_map[i].init == 1) */
2630 
2631 	/* check how we exited the loop */
2632 	if (sng_cic_cntrl_type_map[i].init == 0) {
2633 		return -1;
2634 	} else {
2635 		return i;
2636 	} /* if (sng_cic_cntrl_type_map[i].init == 0) */
2637 }
2638 
2639 /******************************************************************************/
check_status_of_all_isup_intf(void)2640 ftdm_status_t check_status_of_all_isup_intf(void)
2641 {
2642 	sng_isup_inf_t		*sngss7_intf = NULL;
2643 	uint8_t				status = 0xff;
2644 	int					x;
2645 
2646 	/* go through all the isupIntfs and ask the stack to give their current state */
2647 	x = 1;
2648 	for (x = 1; x < (MAX_ISUP_INFS); x++) {
2649 	/**************************************************************************/
2650 
2651 		if (g_ftdm_sngss7_data.cfg.isupIntf[x].id == 0) continue;
2652 
2653 		sngss7_intf = &g_ftdm_sngss7_data.cfg.isupIntf[x];
2654 
2655 		if (ftmod_ss7_isup_intf_sta(sngss7_intf->id, &status)) {
2656 			SS7_ERROR("Failed to get status of ISUP intf %d\n", sngss7_intf->id);
2657 			sngss7_set_flag(sngss7_intf, SNGSS7_PAUSED);
2658 			continue;
2659 		}
2660 
2661 		switch (status){
2662 		/**********************************************************************/
2663 		case (SI_INTF_AVAIL):
2664 			SS7_DEBUG("State of ISUP intf %d = AVAIL\n", sngss7_intf->id);
2665 
2666 			/* check the current state for interface that we know */
2667 			if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) {
2668 				/* we thing the intf is paused...put into resume */
2669 				sngss7_clear_flag(sngss7_intf, SNGSS7_PAUSED);
2670 			} else {
2671 				/* nothing to since we already know that interface is active */
2672 			}
2673 			break;
2674 		/**********************************************************************/
2675 		case (SI_INTF_UNAVAIL):
2676 			SS7_DEBUG("State of ISUP intf %d = UNAVAIL\n", sngss7_intf->id);
2677 			/* check the current state for interface that we know */
2678 			if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) {
2679 				/* nothing to since we already know that interface is active */
2680 			} else {
2681 				/* put the interface into pause */
2682 				sngss7_set_flag(sngss7_intf, SNGSS7_PAUSED);
2683 			}
2684 			break;
2685 		/**********************************************************************/
2686 		case (SI_INTF_CONG1):
2687 			SS7_DEBUG("State of ISUP intf %d = Congestion 1\n", sngss7_intf->id);
2688 			break;
2689 		/**********************************************************************/
2690 		case (SI_INTF_CONG2):
2691 			SS7_DEBUG("State of ISUP intf %d = Congestion 2\n", sngss7_intf->id);
2692 			break;
2693 		/**********************************************************************/
2694 		case (SI_INTF_CONG3):
2695 			SS7_DEBUG("State of ISUP intf %d = Congestion 3\n", sngss7_intf->id);
2696 			break;
2697 		/**********************************************************************/
2698 		default:
2699 			/* should do something here to handle the possiblity of an unknown case */
2700 			SS7_ERROR("Unknown ISUP intf Status code (%d) for Intf = %d\n", status, sngss7_intf->id);
2701 			break;
2702 		/**********************************************************************/
2703 		} /* switch (status) */
2704 
2705 	/**************************************************************************/
2706 	} /* for (x = 1; x < MAX_ISUP_INFS); i++) */
2707 
2708 	return FTDM_SUCCESS;
2709 }
2710 
2711 /******************************************************************************/
sngss7_add_var(sngss7_chan_data_t * sngss7_info,const char * var,const char * val)2712 ftdm_status_t sngss7_add_var(sngss7_chan_data_t *sngss7_info, const char* var, const char* val)
2713 {
2714 	char	*t_name = 0;
2715 	char	*t_val = 0;
2716 
2717 	/* confirm the user has sent us a value */
2718 	if (!var || !val) {
2719 		return FTDM_FAIL;
2720 	}
2721 
2722 	if (!sngss7_info->variables) {
2723 		/* initialize on first use */
2724 		sngss7_info->variables = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
2725 		ftdm_assert_return(sngss7_info->variables, FTDM_FAIL, "Failed to create hash table\n");
2726 	}
2727 
2728 	t_name = ftdm_strdup(var);
2729 	t_val = ftdm_strdup(val);
2730 
2731 	hashtable_insert(sngss7_info->variables, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE);
2732 
2733 	return FTDM_SUCCESS;
2734 }
2735 
2736 /******************************************************************************/
sngss7_add_raw_data(sngss7_chan_data_t * sngss7_info,uint8_t * data,ftdm_size_t data_len)2737 ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data, ftdm_size_t data_len)
2738 {
2739 	ftdm_assert_return(!sngss7_info->raw_data, FTDM_FAIL, "Overwriting existing raw data\n");
2740 
2741 	sngss7_info->raw_data = ftdm_calloc(1, data_len);
2742 	ftdm_assert_return(sngss7_info->raw_data, FTDM_FAIL, "Failed to allocate raw data\n");
2743 
2744 	memcpy(sngss7_info->raw_data, data, data_len);
2745 	sngss7_info->raw_data_len = data_len;
2746 	return FTDM_SUCCESS;
2747 }
2748 
2749 /******************************************************************************/
sngss7_send_signal(sngss7_chan_data_t * sngss7_info,ftdm_signal_event_t event_id)2750 void sngss7_send_signal(sngss7_chan_data_t *sngss7_info, ftdm_signal_event_t event_id)
2751 {
2752 	ftdm_sigmsg_t	sigev;
2753 	ftdm_channel_t	*ftdmchan = sngss7_info->ftdmchan;
2754 
2755 	memset(&sigev, 0, sizeof(sigev));
2756 
2757 	sigev.chan_id = ftdmchan->chan_id;
2758 	sigev.span_id = ftdmchan->span_id;
2759 	sigev.channel = ftdmchan;
2760 	sigev.event_id = event_id;
2761 
2762 	if (sngss7_info->variables) {
2763 		/*
2764 		* variables now belongs to the ftdm core, and
2765 		* will be cleared after sigev is processed by user. Set
2766 		* local pointer to NULL so we do not attempt to
2767 		* destroy it */
2768 		sigev.variables = sngss7_info->variables;
2769 		sngss7_info->variables = NULL;
2770 	}
2771 
2772 	if (sngss7_info->raw_data) {
2773 		/*
2774 		* raw_data now belongs to the ftdm core, and
2775 		* will be cleared after sigev is processed by user. Set
2776 		* local pointer to NULL so we do not attempt to
2777 		* destroy it */
2778 
2779 		sigev.raw.data = sngss7_info->raw_data;
2780 		sigev.raw.len = sngss7_info->raw_data_len;
2781 
2782 		sngss7_info->raw_data = NULL;
2783 		sngss7_info->raw_data_len = 0;
2784 	}
2785 	ftdm_span_send_signal(ftdmchan->span, &sigev);
2786 }
2787 
2788 /******************************************************************************/
sngss7_set_sig_status(sngss7_chan_data_t * sngss7_info,ftdm_signaling_status_t status)2789 void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_status_t status)
2790 {
2791 	ftdm_sigmsg_t	sig;
2792 	ftdm_channel_t	*ftdmchan = sngss7_info->ftdmchan;
2793 
2794 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n",
2795 								ftdm_signaling_status2str(status));
2796 
2797 	memset(&sig, 0, sizeof(sig));
2798 
2799 	sig.chan_id = ftdmchan->chan_id;
2800 	sig.span_id = ftdmchan->span_id;
2801 	sig.channel = ftdmchan;
2802 	sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
2803 	sig.ev_data.sigstatus.status = status;
2804 
2805 	if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) {
2806 		ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR,  "Failed to change channel status to %s\n",
2807 									ftdm_signaling_status2str(status));
2808 	}
2809 	return;
2810 }
2811 
2812 #if 0
2813 ftdm_status_t check_for_invalid_states(ftdm_channel_t *ftmchan)
2814 {
2815 	sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
2816 
2817 	if (!sngss7_info) {
2818 			SS7_WARN_CHAN(ftdmchan, "Found ftdmchan with no sig module data!%s\n", " ");
2819 			return FTDM_FAIL;
2820 	}
2821 
2822 	if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) {
2823 		return FTDM_SUCCESS;
2824 	}
2825 
2826 	switch (ftdmchan->state) {
2827 	case UP:
2828 	case DOWN:
2829 		return FTDM_SUCCESS;
2830 
2831 	default:
2832 		if ((ftdm_current_time_in_ms() - ftdmchan->last_state_change_time) > 30000) {
2833 			SS7_WARN_CHAN(ftdmchan, "Circuite in state=%s too long - resetting!%s\n",
2834 								ftdm_channel_state2str(ftdmchan->state));
2835 
2836 			ftdm_channel_lock(ftdmchan);
2837 
2838 			if (sngss7_channel_status_clear(sngss7_info)) {
2839 				sngss7_tx_reset_restart(sngss7_info);
2840 
2841 				if (ftdmchan->state == FTDM_CHANNEL_STATE_RESTART) {
2842 					ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
2843 				} else {
2844 					ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
2845 				}
2846 			} else {
2847 
2848 			}
2849 
2850 
2851 
2852 			ftdm_channel_unlock(ftdmchan);
2853 		}
2854 	}
2855 
2856 	return FTDM_SUCCESS;
2857 }
2858 #endif
2859 
2860 
2861 /******************************************************************************/
check_for_reconfig_flag(ftdm_span_t * ftdmspan)2862 ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan)
2863 {
2864 	ftdm_channel_t		*ftdmchan = NULL;
2865 	sngss7_chan_data_t	*sngss7_info = NULL;
2866 	sng_isup_inf_t		*sngss7_intf = NULL;
2867 	uint8_t				state;
2868 	uint8_t				bits_ab = 0;
2869 	uint8_t				bits_cd = 0;
2870 	uint8_t				bits_ef = 0;
2871 	int 				x;
2872 	int					ret;
2873 	ret=0;
2874 
2875 	for (x = 1; x < (ftdmspan->chan_count + 1); x++) {
2876 	/**************************************************************************/
2877 		/* extract the channel structure and sngss7 channel data */
2878 		ftdmchan = ftdmspan->channels[x];
2879 
2880 		/* if the call data is NULL move on */
2881 		if (ftdmchan->call_data == NULL) {
2882 			SS7_WARN_CHAN(ftdmchan, "Found ftdmchan with no sig module data!%s\n", " ");
2883 			continue;
2884 		}
2885 
2886 		/* grab the private data */
2887 		sngss7_info = ftdmchan->call_data;
2888 
2889 		/* check the reconfig flag */
2890 		if (sngss7_test_ckt_flag(sngss7_info, FLAG_CKT_RECONFIG)) {
2891 			/* confirm the state of all isup interfaces*/
2892 			check_status_of_all_isup_intf();
2893 
2894 			sngss7_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
2895 
2896 			/* check if the interface is paused or resumed */
2897 			if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) {
2898 				ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Circuit set to PAUSED %s\n"," ");
2899 				/* throw the pause flag */
2900 				sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_RESUME);
2901 				sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_PAUSED);
2902 			} else {
2903 				ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Circuit set to RESUMED %s\n"," ");
2904 				/* throw the resume flag */
2905 				sngss7_clear_ckt_flag(sngss7_info, FLAG_INFID_PAUSED);
2906 				sngss7_set_ckt_flag(sngss7_info, FLAG_INFID_RESUME);
2907 			}
2908 
2909 			/* query for the status of the ckt */
2910 			if (ftmod_ss7_isup_ckt_sta(sngss7_info->circuit->id, &state)) {
2911 				/* NC: Circuit statistic failed: does not exist. Must re-configure circuit
2912 				       Reset the circuit CONFIGURED flag so that RESUME will reconfigure
2913 				       this circuit. */
2914 				sngss7_info->circuit->flags &= ~SNGSS7_CONFIGURED;
2915 				ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR,"Failed to read isup ckt = %d status\n", sngss7_info->circuit->id);
2916 				continue;
2917 			}
2918 
2919 			/* extract the bit sections */
2920 			bits_ab = (state & (SNG_BIT_A + SNG_BIT_B)) >> 0;
2921 			bits_cd = (state & (SNG_BIT_C + SNG_BIT_D)) >> 2;
2922 			bits_ef = (state & (SNG_BIT_E + SNG_BIT_F)) >> 4;
2923 
2924 			ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Circuit state=0x%X ab=0x%X cd=0x%X ef=0x%X\n",state,bits_ab,bits_cd,bits_ef);
2925 
2926 			if (bits_cd == 0x0) {
2927 				/* check if circuit is UCIC or transient */
2928 				if (bits_ab == 0x3) {
2929 					SS7_INFO("ISUP CKT %d re-configuration pending!\n", x);
2930 					sngss7_info->circuit->flags &= ~SNGSS7_CONFIGURED;
2931 					SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
2932 
2933 					/* NC: The code below should be deleted. Its here for hitorical
2934 					       reason. The RESUME code will reconfigure the channel since
2935 					       the CONFIGURED flag has been reset */
2936 #if 0
2937 					/* bit a and bit b are set, unequipped */
2938 					ret = ftmod_ss7_isup_ckt_config(sngss7_info->circuit->id);
2939 					if (ret) {
2940 						SS7_CRITICAL("ISUP CKT %d re-configuration FAILED!\n",x);
2941 					} else {
2942 						SS7_INFO("ISUP CKT %d re-configuration DONE!\n", x);
2943 					}
2944 
2945 					/* reset the circuit to sync states */
2946 					ftdm_mutex_lock(ftdmchan->mutex);
2947 
2948 					/* flag the circuit as active */
2949 					sngss7_set_flag(sngss7_info->circuit, SNGSS7_ACTIVE);
2950 
2951 					/* throw the channel into reset */
2952 					sngss7_set_ckt_flag(sngss7_info, FLAG_RESET_TX);
2953 
2954 					/* throw the channel to suspend */
2955 					ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
2956 
2957 					/* unlock the channel */
2958 					ftdm_mutex_unlock(ftdmchan->mutex);
2959 #endif
2960 
2961 				} else { /* if (bits_ab == 0x3) */
2962 					/* The stack status is not blocked.  However this is possible if
2963 					   the circuit state was UP. So even though Master sent out the BLO
2964 					   the status command is not showing it.
2965 
2966 					   As a kudge. We will try to send out an UBL even though the status
2967 					   indicates that there is no BLO.  */
2968 					if (!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) {
2969 						sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX);
2970 
2971 						/* set the channel to suspended state */
2972 						SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
2973 					}
2974 				}
2975 			} else {
2976 				/* check the maintenance block status in bits A and B */
2977 				switch (bits_ab) {
2978 				/**************************************************************************/
2979 				case (0):
2980 					/* no maintenace block...do nothing */
2981 					break;
2982 				/**************************************************************************/
2983 				case (1):
2984 					/* The stack status is Blocked.  Check if the block was sent
2985 					   by user via console.  If the block was not sent by user then, it
2986 					   was sent out by Master due to relay down.
2987 					   Therefore send out the unblock to clear it */
2988 					if (!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) {
2989 						sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX);
2990 
2991 						/* set the channel to suspended state */
2992 						SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
2993 					}
2994 
2995 					/* Only locally blocked, thus remove a remote block */
2996 					sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
2997 					sngss7_clear_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN);
2998 
2999 					break;
3000 				/**************************************************************************/
3001 				case (2):
3002 					/* remotely blocked */
3003 					sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
3004 					sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN);
3005 
3006 					/* set the channel to suspended state */
3007 					SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
3008 					break;
3009 				/**************************************************************************/
3010 				case (3):
3011 					/* both locally and remotely blocked */
3012 					if (!sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) {
3013 						sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX);
3014 					}
3015 					sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX);
3016 					sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX_DN);
3017 
3018 					/* set the channel to suspended state */
3019 					SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
3020 					break;
3021 				/**************************************************************************/
3022 				default:
3023 					break;
3024 				/**************************************************************************/
3025 				} /* switch (bits_ab) */
3026 
3027 				/* check the hardware block status in bits e and f */
3028 				switch (bits_ef) {
3029 				/**************************************************************************/
3030 				case (0):
3031 					/* no maintenace block...do nothing */
3032 					break;
3033 				/**************************************************************************/
3034 				case (1):
3035 					/* locally blocked */
3036 					sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX);
3037 
3038 					/* set the channel to suspended state */
3039 					SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
3040 					break;
3041 				/**************************************************************************/
3042 				case (2):
3043 					/* remotely blocked */
3044 					sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
3045 
3046 					/* set the channel to suspended state */
3047 					SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
3048 					break;
3049 				/**************************************************************************/
3050 				case (3):
3051 					/* both locally and remotely blocked */
3052 					sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX);
3053 					sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX);
3054 
3055 					/* set the channel to suspended state */
3056 					SS7_STATE_CHANGE(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
3057 					break;
3058 				/**************************************************************************/
3059 				default:
3060 					break;
3061 				/**************************************************************************/
3062 				} /* switch (bits_ef) */
3063 			}
3064 
3065 			/* clear the re-config flag ... no matter what */
3066 			sngss7_clear_ckt_flag(sngss7_info, FLAG_CKT_RECONFIG);
3067 
3068 		}
3069 	} /* for (x = 1; x < (span->chan_count + 1); x++) */
3070 
3071 	return FTDM_SUCCESS;
3072 }
3073 
sngss7_bufferzero_iam(SiConEvnt * siConEvnt)3074 ftdm_status_t sngss7_bufferzero_iam(SiConEvnt *siConEvnt)
3075 {
3076 	if (siConEvnt->natConInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natConInd, 0, sizeof(siConEvnt->natConInd));
3077 	if (siConEvnt->fwdCallInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->fwdCallInd, 0, sizeof(siConEvnt->fwdCallInd));
3078 	if (siConEvnt->cgPtyCat.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyCat, 0, sizeof(siConEvnt->cgPtyCat));
3079 	if (siConEvnt->txMedReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->txMedReq, 0, sizeof(siConEvnt->txMedReq));
3080 #if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL)
3081 	if (siConEvnt->usrServInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfoA, 0, sizeof(siConEvnt->usrServInfoA));
3082 #endif
3083 	if (siConEvnt->cdPtyNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cdPtyNum, 0, sizeof(siConEvnt->cdPtyNum));
3084 #if TNS_ANSI
3085 #if (SS7_ANS92 || SS7_ANS95 || SS7_BELL)
3086 	if (siConEvnt->tranNetSel1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->tranNetSel1, 0, sizeof(siConEvnt->tranNetSel1));
3087 #endif
3088 #endif
3089 	if (siConEvnt->tranNetSel.eh.pres != PRSNT_NODEF) memset(&siConEvnt->tranNetSel, 0, sizeof(siConEvnt->tranNetSel));
3090 #if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL || SS7_CHINA)
3091 	if (siConEvnt->callRefA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callRefA, 0, sizeof(siConEvnt->callRefA));
3092 #endif
3093 	if (siConEvnt->callRef.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callRef, 0, sizeof(siConEvnt->callRef));
3094 	if (siConEvnt->cgPtyNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNum, 0, sizeof(siConEvnt->cgPtyNum));
3095 #if SS7_BELL
3096 	if (siConEvnt->cgPtyNumB.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNumB, 0, sizeof(siConEvnt->cgPtyNumB));
3097 #endif
3098 	if (siConEvnt->opFwdCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalInd, 0, sizeof(siConEvnt->opFwdCalInd));
3099 #if (SS7_Q767 || SS7_RUSSIA || SS7_NTT)
3100 	if (siConEvnt->opFwdCalIndQ.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalIndQ, 0, sizeof(siConEvnt->opFwdCalIndQ));
3101 #endif
3102 #if SS7_Q767IT
3103 	if (siConEvnt->fwdVad.eh.pres != PRSNT_NODEF) memset(&siConEvnt->fwdVad, 0, sizeof(siConEvnt->fwdVad));
3104 #endif
3105 #if SS7_ANS88
3106 	if (siConEvnt->opFwdCalIndA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalIndA, 0, sizeof(siConEvnt->opFwdCalIndA));
3107 #endif
3108 	if (siConEvnt->redirgNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirgNum, 0, sizeof(siConEvnt->redirgNum));
3109 	if (siConEvnt->redirInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirInfo, 0, sizeof(siConEvnt->redirInfo));
3110 	if (siConEvnt->cugIntCode.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cugIntCode, 0, sizeof(siConEvnt->cugIntCode));
3111 #if SS7_ANS88
3112 	if (siConEvnt->cugIntCodeA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cugIntCodeA, 0, sizeof(siConEvnt->cugIntCodeA));
3113 #endif
3114 #if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL || SS7_CHINA)
3115 	if (siConEvnt->connReqA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connReqA, 0, sizeof(siConEvnt->connReqA));
3116 #endif
3117 #if SS7_ANS88
3118 	if (siConEvnt->usr2UsrInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInfoA, 0, sizeof(siConEvnt->usr2UsrInfoA));
3119 #endif
3120 	if (siConEvnt->connReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connReq, 0, sizeof(siConEvnt->connReq));
3121 	if (siConEvnt->origCdNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origCdNum, 0, sizeof(siConEvnt->origCdNum));
3122 	if (siConEvnt->usr2UsrInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInfo, 0, sizeof(siConEvnt->usr2UsrInfo));
3123 	if (siConEvnt->accTrnspt.eh.pres != PRSNT_NODEF) memset(&siConEvnt->accTrnspt, 0, sizeof(siConEvnt->accTrnspt));
3124 	if (siConEvnt->echoControl.eh.pres != PRSNT_NODEF) memset(&siConEvnt->echoControl, 0, sizeof(siConEvnt->echoControl));
3125 #if SS7_ANS88
3126 	if (siConEvnt->redirInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirInfoA, 0, sizeof(siConEvnt->redirInfoA));
3127 #endif
3128 #if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL)
3129 	if (siConEvnt->chargeNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->chargeNum, 0, sizeof(siConEvnt->chargeNum));
3130 	if (siConEvnt->origLineInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origLineInf, 0, sizeof(siConEvnt->origLineInf));
3131 #endif
3132 	if (siConEvnt->usrServInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfo, 0, sizeof(siConEvnt->usrServInfo));
3133 	if (siConEvnt->usr2UsrInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInd, 0, sizeof(siConEvnt->usr2UsrInd));
3134 	if (siConEvnt->propDly.eh.pres != PRSNT_NODEF) memset(&siConEvnt->propDly, 0, sizeof(siConEvnt->propDly));
3135 	if (siConEvnt->usrServInfo1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfo1, 0, sizeof(siConEvnt->usrServInfo1));
3136 	if (siConEvnt->netFac.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netFac, 0, sizeof(siConEvnt->netFac));
3137 #ifdef SS7_CHINA
3138 	if (siConEvnt->orgPteCdeA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->orgPteCdeA, 0, sizeof(siConEvnt->orgPteCdeA));
3139 #endif
3140 	if (siConEvnt->orgPteCde.eh.pres != PRSNT_NODEF) memset(&siConEvnt->orgPteCde, 0, sizeof(siConEvnt->orgPteCde));
3141 	if (siConEvnt->genDigits.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genDigits, 0, sizeof(siConEvnt->genDigits));
3142 	if (siConEvnt->genDigitsR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genDigitsR, 0, sizeof(siConEvnt->genDigitsR));
3143 	if (siConEvnt->usrTSrvInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrTSrvInfo, 0, sizeof(siConEvnt->usrTSrvInfo));
3144 	if (siConEvnt->remotOper.eh.pres != PRSNT_NODEF) memset(&siConEvnt->remotOper, 0, sizeof(siConEvnt->remotOper));
3145 	if (siConEvnt->parmCom.eh.pres != PRSNT_NODEF) memset(&siConEvnt->parmCom, 0, sizeof(siConEvnt->parmCom));
3146 #if (SS7_ANS92 || SS7_ANS95)
3147 	if (siConEvnt->servCode.eh.pres != PRSNT_NODEF) memset(&siConEvnt->servCode, 0, sizeof(siConEvnt->servCode));
3148 #endif
3149 #if SS7_ANS92
3150 	if (siConEvnt->serviceAct1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct1, 0, sizeof(siConEvnt->serviceAct1));
3151 #endif
3152 #if SS7_CHINA
3153 	if (siConEvnt->serviceAct2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct2, 0, sizeof(siConEvnt->serviceAct2));
3154 #endif
3155 	if (siConEvnt->serviceAct2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct2, 0, sizeof(siConEvnt->serviceAct2));
3156 	if (siConEvnt->serviceAct.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct, 0, sizeof(siConEvnt->serviceAct));
3157 	if (siConEvnt->mlppPrec.eh.pres != PRSNT_NODEF) memset(&siConEvnt->mlppPrec, 0, sizeof(siConEvnt->mlppPrec));
3158 #if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT))
3159 	if (siConEvnt->txMedUsPr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->txMedUsPr, 0, sizeof(siConEvnt->txMedUsPr));
3160 #endif
3161 	if (siConEvnt->bckCallInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->bckCallInd, 0, sizeof(siConEvnt->bckCallInd));
3162 	if (siConEvnt->cgPtyNum1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNum1, 0, sizeof(siConEvnt->cgPtyNum1));
3163 	if (siConEvnt->optBckCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optBckCalInd, 0, sizeof(siConEvnt->optBckCalInd));
3164 #if (SS7_Q767 || SS7_RUSSIA || SS7_NTT)
3165 	if (siConEvnt->optBckCalIndQ.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optBckCalIndQ, 0, sizeof(siConEvnt->optBckCalIndQ));
3166 #endif
3167 	if (siConEvnt->connNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connNum, 0, sizeof(siConEvnt->connNum));
3168 #if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT))
3169 	if (siConEvnt->connNum2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connNum2, 0, sizeof(siConEvnt->connNum2));
3170 #endif
3171 	if (siConEvnt->accDelInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->accDelInfo, 0, sizeof(siConEvnt->accDelInfo));
3172 	if (siConEvnt->notifInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifInd, 0, sizeof(siConEvnt->notifInd));
3173 	if (siConEvnt->notifIndR2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifIndR2, 0, sizeof(siConEvnt->notifIndR2));
3174 	if (siConEvnt->cllHstry.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cllHstry, 0, sizeof(siConEvnt->cllHstry));
3175 	if (siConEvnt->genNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genNmb, 0, sizeof(siConEvnt->genNmb));
3176 	if (siConEvnt->genNmbR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genNmbR, 0, sizeof(siConEvnt->genNmbR));
3177 	if (siConEvnt->redirNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirNum, 0, sizeof(siConEvnt->redirNum));
3178 	if (siConEvnt->redirRstr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirRstr, 0, sizeof(siConEvnt->redirRstr));
3179 
3180 #if SS7_Q767IT
3181 	if (siConEvnt->backVad.eh.pres != PRSNT_NODEF) memset(&siConEvnt->backVad, 0, sizeof(siConEvnt->backVad));
3182 #endif
3183 #if SS7_SINGTEL
3184 	if (siConEvnt->cgPtyNumS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNumS, 0, sizeof(siConEvnt->cgPtyNumS));
3185 #endif
3186 #if (SS7_ANS92 || SS7_ANS95 || SS7_BELL)
3187 	if (siConEvnt->businessGrp.eh.pres != PRSNT_NODEF) memset(&siConEvnt->businessGrp, 0, sizeof(siConEvnt->businessGrp));
3188 	if (siConEvnt->infoInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->infoInd, 0, sizeof(siConEvnt->infoInd));
3189 	if (siConEvnt->carrierId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carrierId, 0, sizeof(siConEvnt->carrierId));
3190 	if (siConEvnt->carSelInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carSelInf, 0, sizeof(siConEvnt->carSelInf));
3191 	if (siConEvnt->egress.eh.pres != PRSNT_NODEF) memset(&siConEvnt->egress, 0, sizeof(siConEvnt->egress));
3192 	if (siConEvnt->genAddr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genAddr, 0, sizeof(siConEvnt->genAddr));
3193 	if (siConEvnt->genAddrR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genAddrR, 0, sizeof(siConEvnt->genAddrR));
3194 	if (siConEvnt->infoReqInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->infoReqInd, 0, sizeof(siConEvnt->infoReqInd));
3195 	if (siConEvnt->jurisInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->jurisInf, 0, sizeof(siConEvnt->jurisInf));
3196 	if (siConEvnt->netTransport.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netTransport, 0, sizeof(siConEvnt->netTransport));
3197 	if (siConEvnt->specProcReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->specProcReq, 0, sizeof(siConEvnt->specProcReq));
3198 	if (siConEvnt->transReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->transReq, 0, sizeof(siConEvnt->transReq));
3199 #endif
3200 #if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT))
3201 #if (SS7_ANS92 || SS7_ANS95)
3202 	if (siConEvnt->notifInd1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifInd1, 0, sizeof(siConEvnt->notifInd1));
3203 	if (siConEvnt->notifIndR1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifIndR1, 0, sizeof(siConEvnt->notifIndR1));
3204 #endif /* SS7_ANS92 */
3205 #endif /* SIT_PARAMETER || TDS_ROLL_UPGRADE_SUPPORT */
3206 #if (SS7_BELL || SS7_ANS95)
3207 	if (siConEvnt->genName.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genName, 0, sizeof(siConEvnt->genName));
3208 #endif
3209 #if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_ETSIV3 || \
3210 	SS7_BELL || SS7_ANS95 || SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ)
3211 	if (siConEvnt->hopCounter.eh.pres != PRSNT_NODEF) memset(&siConEvnt->hopCounter, 0, sizeof(siConEvnt->hopCounter));
3212 #endif
3213 #if (SS7_BELL || SS7_ITU2000 || SS7_KZ)
3214 	if (siConEvnt->redirCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirCap, 0, sizeof(siConEvnt->redirCap));
3215 	if (siConEvnt->redirCntr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirCntr, 0, sizeof(siConEvnt->redirCntr));
3216 #endif
3217 #if (SS7_ETSI || SS7_FTZ)
3218 	if (siConEvnt->ccbsParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->ccbsParam, 0, sizeof(siConEvnt->ccbsParam));
3219 	if (siConEvnt->freePhParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->freePhParam, 0, sizeof(siConEvnt->freePhParam));
3220 #endif
3221 #ifdef SS7_FTZ
3222 	if (siConEvnt->naPaFF.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaFF, 0, sizeof(siConEvnt->naPaFF));
3223 	if (siConEvnt->naPaFE.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaFE, 0, sizeof(siConEvnt->naPaFE));
3224 	if (siConEvnt->naPaSSP.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaSSP, 0, sizeof(siConEvnt->naPaSSP));
3225 	if (siConEvnt->naPaCdPNO.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaCdPNO, 0, sizeof(siConEvnt->naPaCdPNO));
3226 	if (siConEvnt->naPaSPV.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaSPV, 0, sizeof(siConEvnt->naPaSPV));
3227 	if (siConEvnt->naPaUKK.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaUKK, 0, sizeof(siConEvnt->naPaUKK));
3228 #endif
3229 #if SS7_NTT
3230 	if (siConEvnt->msgAreaInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->msgAreaInfo, 0, sizeof(siConEvnt->msgAreaInfo));
3231 	if (siConEvnt->subsNumber.eh.pres != PRSNT_NODEF) memset(&siConEvnt->subsNumber, 0, sizeof(siConEvnt->subsNumber));
3232 	if (siConEvnt->rpCllngNo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->rpCllngNo, 0, sizeof(siConEvnt->rpCllngNo));
3233 	if (siConEvnt->supplUserType.eh.pres != PRSNT_NODEF) memset(&siConEvnt->supplUserType, 0, sizeof(siConEvnt->supplUserType));
3234 	if (siConEvnt->carrierInfoTrans.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carrierInfoTrans, 0, sizeof(siConEvnt->carrierInfoTrans));
3235 	if (siConEvnt->nwFuncType.eh.pres != PRSNT_NODEF) memset(&siConEvnt->nwFuncType, 0, sizeof(siConEvnt->nwFuncType));
3236 #endif
3237 #if SS7_ANS95
3238 	if (siConEvnt->optrServicesInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optrServicesInfo, 0, sizeof(siConEvnt->optrServicesInfo));
3239 #endif
3240 #if (SS7_ANS95 || SS7_ITU97  || SS7_RUSS2000|| SS7_ITU2000 || SS7_NZL || SS7_KZ)
3241 	if (siConEvnt->cirAsgnMap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cirAsgnMap, 0, sizeof(siConEvnt->cirAsgnMap));
3242 #endif
3243 #if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_ETSIV3 || \
3244 	SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ)
3245 	if (siConEvnt->displayInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->displayInfo, 0, sizeof(siConEvnt->displayInfo));
3246 	if (siConEvnt->confTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->confTrtInd, 0, sizeof(siConEvnt->confTrtInd));
3247 	if (siConEvnt->netMgmtControls.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netMgmtControls, 0, sizeof(siConEvnt->netMgmtControls));
3248 	if (siConEvnt->correlationId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->correlationId, 0, sizeof(siConEvnt->correlationId));
3249 	if (siConEvnt->callDivTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callDivTrtInd, 0, sizeof(siConEvnt->callDivTrtInd));
3250 	if (siConEvnt->callInNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callInNmb, 0, sizeof(siConEvnt->callInNmb));
3251 	if (siConEvnt->callOfferTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callOfferTrtInd, 0, sizeof(siConEvnt->callOfferTrtInd));
3252 	if (siConEvnt->scfId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->scfId, 0, sizeof(siConEvnt->scfId));
3253 	if (siConEvnt->uidCapInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->uidCapInd, 0, sizeof(siConEvnt->uidCapInd));
3254 	if (siConEvnt->collCallReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->collCallReq, 0, sizeof(siConEvnt->collCallReq));
3255 	if (siConEvnt->ccss.eh.pres != PRSNT_NODEF) memset(&siConEvnt->ccss, 0, sizeof(siConEvnt->ccss));
3256 #endif
3257 #if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_UK || SS7_NZL || SS7_KZ)
3258 	if (siConEvnt->backGVNS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->backGVNS, 0, sizeof(siConEvnt->backGVNS));
3259 	if (siConEvnt->forwardGVNS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->forwardGVNS, 0, sizeof(siConEvnt->forwardGVNS));
3260 #endif
3261 #if (SS7_ETSIV3 || SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || \
3262 	SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ)
3263 	if (siConEvnt->appTransParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->appTransParam, 0, sizeof(siConEvnt->appTransParam));
3264 #endif
3265 #if (SS7_ITU2000 || SS7_UK || SS7_NZL || SS7_KZ)
3266 	if (siConEvnt->htrInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->htrInfo, 0, sizeof(siConEvnt->htrInfo));
3267 	if (siConEvnt->pivotCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotCap, 0, sizeof(siConEvnt->pivotCap));
3268 	if (siConEvnt->cadDirNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cadDirNmb, 0, sizeof(siConEvnt->cadDirNmb));
3269 	if (siConEvnt->origCallInNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origCallInNum, 0, sizeof(siConEvnt->origCallInNum));
3270 	if (siConEvnt->calgGeoLoc.eh.pres != PRSNT_NODEF) memset(&siConEvnt->calgGeoLoc, 0, sizeof(siConEvnt->calgGeoLoc));
3271 	if (siConEvnt->netRoutNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netRoutNum, 0, sizeof(siConEvnt->netRoutNum));
3272 	if (siConEvnt->qonRelCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->qonRelCap, 0, sizeof(siConEvnt->qonRelCap));
3273 	if (siConEvnt->pivotCntr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotCntr, 0, sizeof(siConEvnt->pivotCntr));
3274 	if (siConEvnt->pivotRtgFwInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotRtgFwInfo, 0, sizeof(siConEvnt->pivotRtgFwInfo));
3275 	if (siConEvnt->pivotRtgBkInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotRtgBkInfo, 0, sizeof(siConEvnt->pivotRtgBkInfo));
3276 	if (siConEvnt->numPortFwdInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->numPortFwdInfo, 0, sizeof(siConEvnt->numPortFwdInfo));
3277 #endif
3278 #ifdef SS7_UK
3279 	if (siConEvnt->natFwdCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natFwdCalInd, 0, sizeof(siConEvnt->natFwdCalInd));
3280 	if (siConEvnt->presntNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->presntNum, 0, sizeof(siConEvnt->presntNum));
3281 	if (siConEvnt->lstDvrtLineId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->lstDvrtLineId, 0, sizeof(siConEvnt->lstDvrtLineId));
3282 	if (siConEvnt->pcgLineId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pcgLineId, 0, sizeof(siConEvnt->pcgLineId));
3283 	if (siConEvnt->natFwdCalIndLnk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natFwdCalIndLnk, 0, sizeof(siConEvnt->natFwdCalIndLnk));
3284 	if (siConEvnt->cdBascSrvcMrk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cdBascSrvcMrk, 0, sizeof(siConEvnt->cdBascSrvcMrk));
3285 #endif /* SS7_UK */
3286 #if (defined(CGPN_CHK))
3287 	if (siConEvnt->causeDgnCgPnChk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->causeDgnCgPnChk, 0, sizeof(siConEvnt->causeDgnCgPnChk));
3288 #endif
3289 	return FTDM_SUCCESS;
3290 }
3291 
sngss7_save_iam(ftdm_channel_t * ftdmchan,SiConEvnt * siConEvnt)3292 ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt)
3293 {
3294 #ifndef HAVE_ZLIB
3295 	ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Cannot perform transparent IAM because zlib is missing\n");
3296 	return FTDM_FAIL;
3297 #else
3298 	unsigned ret_val = FTDM_FAIL;
3299 	char *compressed_iam = NULL;
3300 	char *url_encoded_iam = NULL;
3301 	uLongf len = sizeof(*siConEvnt);
3302 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
3303 
3304 	/* By default, Trillium does not memset their whole structure to zero for
3305 	 * performance. But we want to memset all the IE's that are not present to
3306 	 * optimize compressed size */
3307 	sngss7_bufferzero_iam(siConEvnt);
3308 
3309 	compressed_iam = ftdm_malloc(sizeof(*siConEvnt));
3310 	if (!compressed_iam) {
3311 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to allocate buffer for compressed_iam\n");
3312 		goto done;
3313 	}
3314 
3315 	/* Compress IAM structure to minimize buffer size */
3316 	ret_val = compress((Bytef *)compressed_iam, &len, (const Bytef *)siConEvnt, (uLong)sizeof(*siConEvnt));
3317 	if (ret_val != Z_OK) {
3318 		ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Failed to compress IAM (error:%d)\n", ret_val);
3319 		ret_val = FTDM_FAIL;
3320 		goto done;
3321 	}
3322 
3323 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%lu\n", len);
3324 
3325 	/* Worst case: size will triple after url encode */
3326 	url_encoded_iam = ftdm_malloc(3*sizeof(*siConEvnt));
3327 	if (!url_encoded_iam) {
3328 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to allocated buffer for url_encoded_iam\n");
3329 		ret_val = FTDM_FAIL;
3330 		goto done;
3331 	}
3332 	memset(url_encoded_iam, 0, 2*sizeof(*siConEvnt));
3333 
3334 	/* URL encode buffer to that its safe to store it in a string */
3335 	ftdm_url_encode((const char*)compressed_iam, url_encoded_iam, len);
3336 
3337 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%"FTDM_SIZE_FMT"\n", strlen(url_encoded_iam));
3338 
3339 	if (strlen(url_encoded_iam) > sngss7_info->circuit->transparent_iam_max_size) {
3340 		ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "IAM variable length exceeds max size (len:%d max:%d) \n",
3341 			strlen(url_encoded_iam), sngss7_info->circuit->transparent_iam_max_size);
3342 		ret_val = FTDM_FAIL;
3343 		goto done;
3344 	}
3345 
3346 	sngss7_add_var(sngss7_info, "ss7_iam", url_encoded_iam);
3347 done:
3348 	ftdm_safe_free(compressed_iam);
3349 	ftdm_safe_free(url_encoded_iam);
3350 	return ret_val;
3351 #endif
3352 }
3353 
sngss7_retrieve_iam(ftdm_channel_t * ftdmchan,SiConEvnt * siConEvnt)3354 ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt)
3355 {
3356 #ifndef HAVE_ZLIB
3357 	ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Cannot perform transparent IAM because zlib is missing\n");
3358 	return FTDM_FAIL;
3359 #else
3360 	uLongf len = 3*sizeof(*siConEvnt); /* worst case: URL encoded buffer is 3x length of buffer */
3361 	char *val = NULL;
3362 	unsigned ret_val = FTDM_FAIL;
3363 	void *uncompressed_buffer = NULL;
3364 	char *url_encoded_iam = NULL;
3365 	ftdm_size_t url_encoded_iam_len;
3366 
3367 	val = (char*)ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam");
3368 	if (ftdm_strlen_zero(val)) {
3369 		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Transparent IAM info available\n");
3370 		return FTDM_FAIL;
3371 	}
3372 
3373 	url_encoded_iam = ftdm_strdup(val);
3374 
3375 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%"FTDM_SIZE_FMT"\n", strlen(val));
3376 	ftdm_url_decode(url_encoded_iam, &url_encoded_iam_len);
3377 
3378 	ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%"FTDM_SIZE_FMT"\n", url_encoded_iam_len);
3379 
3380 	uncompressed_buffer = ftdm_malloc(sizeof(*siConEvnt));
3381 	ftdm_assert_return(uncompressed_buffer, FTDM_FAIL, "Failed to allocate buffer for uncompressed buffer\n");
3382 
3383 	ret_val = uncompress(uncompressed_buffer, &len, (const Bytef *)url_encoded_iam, (uLong)url_encoded_iam_len);
3384 	if (ret_val != Z_OK) {
3385 		ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Failed to uncompress IAM (error:%d)\n", ret_val);
3386 		goto done;
3387 	}
3388 
3389 	if (len != sizeof(*siConEvnt)) {
3390 		ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible IAM structure size (expected:%"FTDM_SIZE_FMT" size:%"FTDM_SIZE_FMT")\n", sizeof(*siConEvnt), strlen(uncompressed_buffer));
3391 		goto done;
3392 	}
3393 
3394 	memcpy(siConEvnt, uncompressed_buffer, sizeof(*siConEvnt));
3395 	ret_val = FTDM_SUCCESS;
3396 
3397 done:
3398 	ftdm_safe_free(uncompressed_buffer);
3399 	ftdm_safe_free(url_encoded_iam);
3400 	return ret_val;
3401 #endif
3402 }
3403 
3404 /******************************************************************************/
3405 /* For Emacs:
3406  * Local Variables:
3407  * mode:c
3408  * indent-tabs-mode:t
3409  * tab-width:4
3410  * c-basic-offset:4
3411  * End:
3412  * For VIM:
3413  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3414  */
3415 /******************************************************************************/
3416