1 /*
2  * Copyright (c) 2009, Konrad Hammel <konrad@sangoma.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of the original author; nor the names of any contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
25  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /* INCLUDE ********************************************************************/
35 #include "ftmod_sangoma_ss7_main.h"
36 /******************************************************************************/
37 
38 /* DEFINES ********************************************************************/
39 #define SNGSS7_EVNTINFO_IND_INBAND_AVAIL 0x03
40 /******************************************************************************/
41 
42 /* GLOBALS ********************************************************************/
43 
44 /* FUNCTIONS ******************************************************************/
ft_to_sngss7_iam(ftdm_channel_t * ftdmchan)45 void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
46 {
47 	const char *var = NULL;
48 	SiConEvnt 			iam;
49 	ftdm_bool_t         native_going_up = FTDM_FALSE;
50 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;;
51 	sngss7_event_data_t *event_clone = NULL;
52 
53 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
54 
55 	sngss7_info->suInstId 	= get_unique_id ();
56 	sngss7_info->spInstId 	= 0;
57 	sngss7_info->spId 		= 1;
58 
59 	memset (&iam, 0x0, sizeof (iam));
60 
61 	if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
62 		ftdm_span_t *peer_span = NULL;
63 		ftdm_channel_t *peer_chan = NULL;
64 		sngss7_chan_data_t *peer_info = NULL;
65 
66 		var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "sigbridge_peer");
67 		ftdm_get_channel_from_string(var, &peer_span, &peer_chan);
68 		if (!peer_chan) {
69 			SS7_ERROR_CHAN(ftdmchan, "Failed to find sigbridge peer from string '%s'\n", var);
70 		} else {
71 			if (peer_span->signal_type != FTDM_SIGTYPE_SS7) {
72 				SS7_ERROR_CHAN(ftdmchan, "Peer channel '%s' has different signaling type %d'\n",
73 						var, peer_span->signal_type);
74 			} else {
75 				peer_info = peer_chan->call_data;
76 				SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Starting native bridge with peer CIC %d\n",
77 						sngss7_info->circuit->cic, peer_info->circuit->cic);
78 
79 				/* retrieve only first message from the others guys queue (must be IAM) */
80 				event_clone = ftdm_queue_dequeue(peer_info->event_queue);
81 
82 				/* make each one of us aware of the native bridge */
83 				peer_info->peer_data = sngss7_info;
84 				sngss7_info->peer_data = peer_info;
85 
86 				/* Go to up until release comes, note that state processing is done different and much simpler when there is a peer,
87 				   We can't go to UP state right away yet though, so do not set the state to UP here, wait until the end of this function
88 				   because moving from one state to another causes the ftdmchan->usrmsg structure to be wiped
89 				   and we still need those variables for further IAM processing */
90 				native_going_up = FTDM_TRUE;
91 			}
92 		}
93 	}
94 
95 	if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
96 		if (!event_clone) {
97 			SS7_ERROR_CHAN(ftdmchan, "No IAM event clone in peer queue!%s\n", "");
98 		} else if (event_clone->event_id != SNGSS7_CON_IND_EVENT) {
99 			/* first message in the queue should ALWAYS be an IAM */
100 			SS7_ERROR_CHAN(ftdmchan, "Invalid initial peer message type '%d'\n", event_clone->event_id);
101 		} else {
102 			ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
103 
104 			SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged, dialing %s)\n", sngss7_info->circuit->cic, caller_data->dnis.digits);
105 
106 			/* copy original incoming IAM */
107 			memcpy(&iam, &event_clone->event.siConEvnt, sizeof(iam));
108 
109 			/* Change DNIS to whatever was specified, do not change NADI or anything else! */
110 			copy_tknStr_to_sngss7(caller_data->dnis.digits, &iam.cdPtyNum.addrSig, &iam.cdPtyNum.oddEven);
111 
112 			/* SPIROU certification hack
113 			   If the IAM already contain RDINF, just increment the count and set the RDNIS digits
114 			   otherwise, honor RDNIS and RDINF stuff coming from the user */
115 			if (iam.redirInfo.eh.pres == PRSNT_NODEF) {
116 				const char *val = NULL;
117 				if (iam.redirInfo.redirCnt.pres) {
118 					iam.redirInfo.redirCnt.val++;
119 					SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), redirect count incremented = %d\n", sngss7_info->circuit->cic, iam.redirInfo.redirCnt.val);
120 				}
121 				val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_digits");
122 				if (!ftdm_strlen_zero(val)) {
123 					SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), found user supplied RDNIS digits = %s\n", sngss7_info->circuit->cic, val);
124 					copy_tknStr_to_sngss7((char*)val, &iam.redirgNum.addrSig, &iam.redirgNum.oddEven);
125 				} else {
126 					SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), not found user supplied RDNIS digits\n", sngss7_info->circuit->cic);
127 				}
128 			} else {
129 				SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), redirect info not present, attempting to copy user supplied values\n", sngss7_info->circuit->cic);
130 				/* Redirecting Number */
131 				copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum);
132 
133 				/* Redirecting Information */
134 				copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo);
135 			}
136 
137 			if (iam.origCdNum.eh.pres != PRSNT_NODEF) {
138 				/* Original Called Number */
139 				copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum);
140 			}
141 			copy_access_transport_to_sngss7(ftdmchan, &iam.accTrnspt);
142 		}
143 	} else if (sngss7_info->circuit->transparent_iam &&
144 		sngss7_retrieve_iam(ftdmchan, &iam) == FTDM_SUCCESS) {
145 		SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Transparent)\n", sngss7_info->circuit->cic);
146 
147 		/* Called Number information */
148 		copy_cdPtyNum_to_sngss7(ftdmchan, &iam.cdPtyNum);
149 
150 		/* Redirecting Number */
151 		copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum);
152 
153 		/* Redirecting Information */
154 		copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo);
155 
156 		/* Location Number information */
157 		copy_locPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum1);
158 
159 		/* Forward Call Indicators */
160 		copy_fwdCallInd_to_sngss7(ftdmchan, &iam.fwdCallInd);
161 
162 		/* Original Called Number */
163 		copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum);
164 
165 		copy_access_transport_to_sngss7(ftdmchan, &iam.accTrnspt);
166 
167 		copy_NatureOfConnection_to_sngss7(ftdmchan, &iam.natConInd);
168 	} else {
169 		/* Nature of Connection Indicators */
170 		copy_natConInd_to_sngss7(ftdmchan, &iam.natConInd);
171 
172 		/* Forward Call Indicators */
173 		copy_fwdCallInd_to_sngss7(ftdmchan, &iam.fwdCallInd);
174 
175 		/* Transmission medium requirements */
176 		copy_txMedReq_to_sngss7(ftdmchan, &iam.txMedReq);
177 
178 		if (SNGSS7_SWITCHTYPE_ANSI(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType)) {
179 			/* User Service Info A */
180 			copy_usrServInfoA_to_sngss7(ftdmchan, &iam.usrServInfoA);
181 		}
182 
183 		/* Called Number information */
184 		copy_cdPtyNum_to_sngss7(ftdmchan, &iam.cdPtyNum);
185 
186 		/* Calling Number information */
187 		copy_cgPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum);
188 
189 		/* Location Number information */
190 		copy_locPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum1);
191 
192 		/* Generic Number information */
193 		copy_genNmb_to_sngss7(ftdmchan, &iam.genNmb);
194 
195 		/* Calling Party's Category */
196 		copy_cgPtyCat_to_sngss7(ftdmchan, &iam.cgPtyCat);
197 
198 		/* Redirecting Number */
199 		copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum);
200 
201 		/* Redirecting Information */
202 		copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo);
203 
204 		/* Original Called Number */
205 		copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum);
206 
207 		/* Access Transport - old implementation, taking from channel variable of ss7_clg_subaddr */
208 		copy_accTrnspt_to_sngss7(ftdmchan, &iam.accTrnspt);
209 
210 		/* Access Transport - taking from channel variable of ss7_access_transport_urlenc.
211 		    This will overwirte the IE value set be above old implementation.
212 		*/
213 		copy_access_transport_to_sngss7(ftdmchan, &iam.accTrnspt);
214 
215 		copy_NatureOfConnection_to_sngss7(ftdmchan, &iam.natConInd);
216 
217 		SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d), loc = %s (NADI=%d)\n",
218 									sngss7_info->circuit->cic,
219 									ftdmchan->caller_data.cid_num.digits,
220 									iam.cgPtyNum.natAddrInd.val,
221 									ftdmchan->caller_data.dnis.digits,
222 									iam.cdPtyNum.natAddrInd.val,
223 									ftdmchan->caller_data.loc.digits,
224 									iam.cgPtyNum1.natAddrInd.val);
225 	}
226 
227 	sng_cc_con_request (sngss7_info->spId,
228 						sngss7_info->suInstId,
229 						sngss7_info->spInstId,
230 						sngss7_info->circuit->id,
231 						&iam,
232 						0);
233 
234 	if (native_going_up) {
235 		/*
236 	      Note that this function (ft_to_sngss7_iam) is run within the main SS7 processing loop in
237 		  response to the DIALING state handler, we can set the state to UP here and that will
238 		  implicitly complete the DIALING state, but we *MUST* also advance the state handler
239 		  right away for a native bridge, otherwise, the processing state function (ftdm_sangoma_ss7_process_state_change)
240 		  will complete the state without having executed the handler for FTDM_CHANNEL_STATE_UP, and we won't notify
241 		  the user sending FTDM_SIGEVENT_UP which can cause the application to misbehave (ie, no audio) */
242 		ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
243 		ftdm_channel_advance_states(ftdmchan);
244 	}
245 
246 	ftdm_safe_free(event_clone);
247 
248 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
249 	return;
250 }
251 
ft_to_sngss7_inf(ftdm_channel_t * ftdmchan,SiCnStEvnt * inr)252 void ft_to_sngss7_inf(ftdm_channel_t *ftdmchan, SiCnStEvnt *inr)
253 {
254 	SiCnStEvnt evnt;
255 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
256 
257 	memset (&evnt, 0x0, sizeof (evnt));
258 
259 	evnt.infoInd.eh.pres	   = PRSNT_NODEF;
260 	evnt.infoInd.cgPtyAddrRespInd.pres = PRSNT_NODEF;
261 	evnt.infoInd.cgPtyCatRespInd.pres = PRSNT_NODEF;
262 
263 	evnt.infoInd.chrgInfoRespInd.pres =  PRSNT_NODEF;
264 	evnt.infoInd.chrgInfoRespInd.val = 0;
265 	evnt.infoInd.solInfoInd.pres = PRSNT_NODEF;
266 	evnt.infoInd.solInfoInd.val = 0;
267 	evnt.infoInd.holdProvInd.pres =  PRSNT_NODEF;
268 	evnt.infoInd.holdProvInd.val = 0;
269 	evnt.infoInd.spare.pres =  PRSNT_NODEF;
270 	evnt.infoInd.spare.val = 0;
271 
272 	if (inr->infoReqInd.eh.pres == PRSNT_NODEF) {
273 		if ((inr->infoReqInd.holdingInd.pres ==  PRSNT_NODEF) && (inr->infoReqInd.holdingInd.val == HOLD_REQ)) {
274 			SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting holding information. Holding is not supported in INF.\n", sngss7_info->circuit->cic);
275 		}
276 		if ((inr->infoReqInd.chrgInfoReqInd.pres ==  PRSNT_NODEF) && (inr->infoReqInd.chrgInfoReqInd.val == CHRGINFO_REQ)) {
277 			SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting charging information. Charging is not supported in INF.\n", sngss7_info->circuit->cic);
278 		}
279 		if ((inr->infoReqInd.malCaIdReqInd.pres ==  PRSNT_NODEF) && (inr->infoReqInd.malCaIdReqInd.val == CHRGINFO_REQ)) {
280 			SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting malicious call id. Malicious call id is not supported in INF.\n", sngss7_info->circuit->cic);
281 		}
282 
283 		if ((inr->infoReqInd.cgPtyAdReqInd.pres ==  PRSNT_NODEF) && (inr->infoReqInd.cgPtyAdReqInd.val == CGPRTYADDREQ_REQ)) {
284 			evnt.infoInd.cgPtyAddrRespInd.val=CGPRTYADDRESP_INCL;
285 			copy_cgPtyNum_to_sngss7 (ftdmchan, &evnt.cgPtyNum);
286 		} else {
287 			evnt.infoInd.cgPtyAddrRespInd.val=CGPRTYADDRESP_NOTINCL;
288 		}
289 
290 		if ((inr->infoReqInd.cgPtyCatReqInd.pres ==  PRSNT_NODEF) && (inr->infoReqInd.cgPtyCatReqInd.val == CGPRTYCATREQ_REQ)) {
291 			evnt.infoInd.cgPtyCatRespInd.val = CGPRTYCATRESP_INCL;
292 			copy_cgPtyCat_to_sngss7 (ftdmchan, &evnt.cgPtyCat);
293 		} else {
294 			evnt.infoInd.cgPtyCatRespInd.val = CGPRTYCATRESP_NOTINCL;
295 		}
296 	}
297 	else {
298 		SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR with no information request. Sending back default INF.\n", sngss7_info->circuit->cic);
299 	}
300 
301 	sng_cc_inf(1,
302 			  sngss7_info->suInstId,
303 			  sngss7_info->spInstId,
304 			  sngss7_info->circuit->id,
305 			  &evnt,
306 			  INFORMATION);
307 
308 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx INF\n", sngss7_info->circuit->cic);
309 
310 }
311 
ft_to_sngss7_inr(ftdm_channel_t * ftdmchan)312 void ft_to_sngss7_inr(ftdm_channel_t *ftdmchan)
313 {
314 	SiCnStEvnt evnt;
315 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
316 
317 	memset (&evnt, 0x0, sizeof (evnt));
318 
319 	evnt.infoReqInd.eh.pres	   = PRSNT_NODEF;
320 	evnt.infoReqInd.cgPtyAdReqInd.pres = PRSNT_NODEF;
321 	evnt.infoReqInd.cgPtyAdReqInd.val=CGPRTYADDREQ_REQ;
322 
323 	evnt.infoReqInd.holdingInd.pres =  PRSNT_NODEF;
324 	evnt.infoReqInd.holdingInd.val = HOLD_REQ;
325 
326 	evnt.infoReqInd.cgPtyCatReqInd.pres = PRSNT_NODEF;
327 	evnt.infoReqInd.cgPtyCatReqInd.val = CGPRTYCATREQ_REQ;
328 
329 	evnt.infoReqInd.chrgInfoReqInd.pres =  PRSNT_NODEF;
330 	evnt.infoReqInd.chrgInfoReqInd.val = CHRGINFO_REQ;
331 
332 	evnt.infoReqInd.malCaIdReqInd.pres =  PRSNT_NODEF;
333 	evnt.infoReqInd.malCaIdReqInd.val = MLBG_INFOREQ;
334 
335 	sng_cc_inr(1,
336 			  sngss7_info->suInstId,
337 			  sngss7_info->spInstId,
338 			  sngss7_info->circuit->id,
339 			  &evnt,
340 			  INFORMATREQ);
341 
342 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx INR\n", sngss7_info->circuit->cic);
343 }
344 
ft_to_sngss7_acm(ftdm_channel_t * ftdmchan)345 void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
346 {
347 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
348 
349 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
350 	SiCnStEvnt acm;
351 	const char *backwardInd = NULL;
352 
353 	memset (&acm, 0x0, sizeof (acm));
354 
355 	/* fill in the needed information for the ACM */
356 	acm.bckCallInd.eh.pres 				= PRSNT_NODEF;
357 	acm.bckCallInd.chrgInd.pres			= PRSNT_NODEF;
358 	acm.bckCallInd.chrgInd.val			= CHRG_CHRG;
359 	acm.bckCallInd.cadPtyStatInd.pres	= PRSNT_NODEF;
360 	acm.bckCallInd.cadPtyStatInd.val	= 0x01;
361 	acm.bckCallInd.cadPtyCatInd.pres	= PRSNT_NODEF;
362 	acm.bckCallInd.cadPtyCatInd.val		= CADCAT_ORDSUBS;
363 	acm.bckCallInd.end2EndMethInd.pres	= PRSNT_NODEF;
364 	acm.bckCallInd.end2EndMethInd.val	= E2EMTH_NOMETH;
365 	acm.bckCallInd.intInd.pres			= PRSNT_NODEF;
366 	acm.bckCallInd.intInd.val 			= INTIND_NOINTW;
367 	acm.bckCallInd.end2EndInfoInd.pres	= PRSNT_NODEF;
368 	acm.bckCallInd.end2EndInfoInd.val	= E2EINF_NOINFO;
369 
370 	acm.bckCallInd.isdnUsrPrtInd.pres	= PRSNT_NODEF;
371 	acm.bckCallInd.isdnUsrPrtInd.val	= ISUP_NOTUSED;
372 	backwardInd = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "acm_bi_iup");
373 	if (!ftdm_strlen_zero(backwardInd)) {
374 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied backward indicator ISDN user part indicator ACM, value \"%s\"\n", backwardInd);
375 		if (atoi(backwardInd) != 0 ) {
376 			acm.bckCallInd.isdnUsrPrtInd.val	= ISUP_USED;
377 		}
378 	}
379 	acm.bckCallInd.holdInd.pres			= PRSNT_NODEF;
380 	acm.bckCallInd.holdInd.val			= HOLD_NOTREQD;
381 	acm.bckCallInd.isdnAccInd.pres		= PRSNT_NODEF;
382 	acm.bckCallInd.isdnAccInd.val		= ISDNACC_NONISDN;
383 	acm.bckCallInd.echoCtrlDevInd.pres	= PRSNT_NODEF;
384 	switch (ftdmchan->caller_data.bearer_capability) {
385 	/**********************************************************************/
386 	case (FTDM_BEARER_CAP_SPEECH):
387 		acm.bckCallInd.echoCtrlDevInd.val	= 0x1;
388 		break;
389 	/**********************************************************************/
390 	case (FTDM_BEARER_CAP_UNRESTRICTED):
391 		acm.bckCallInd.echoCtrlDevInd.val	= 0x0;
392 		break;
393 	/**********************************************************************/
394 	case (FTDM_BEARER_CAP_3_1KHZ_AUDIO):
395 		acm.bckCallInd.echoCtrlDevInd.val	= 0x1;
396 		break;
397 	/**********************************************************************/
398 	default:
399 		SS7_ERROR_CHAN(ftdmchan, "Unknown Bearer capability falling back to speech%s\n", " ");
400 		acm.bckCallInd.echoCtrlDevInd.val	= 0x1;
401 		break;
402 	/**********************************************************************/
403 	} /* switch (ftdmchan->caller_data.bearer_capability) */
404 	acm.bckCallInd.sccpMethInd.pres		= PRSNT_NODEF;
405 	acm.bckCallInd.sccpMethInd.val		= SCCPMTH_NOIND;
406 
407 	/* fill in any optional parameters */
408 	if (sngss7_test_options(&g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id], SNGSS7_ACM_OBCI_BITA)) {
409 		SS7_DEBUG_CHAN(ftdmchan, "Found ACM_OBCI_BITA flag:0x%X\n", g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].options);
410 		acm.optBckCalInd.eh.pres				= PRSNT_NODEF;
411 		acm.optBckCalInd.inbndInfoInd.pres		= PRSNT_NODEF;
412 		acm.optBckCalInd.inbndInfoInd.val		= 0x1;
413 		acm.optBckCalInd.caFwdMayOcc.pres		= PRSNT_DEF;
414 		acm.optBckCalInd.simpleSegmInd.pres		= PRSNT_DEF;
415 		acm.optBckCalInd.mlppUserInd.pres		= PRSNT_DEF;
416 		acm.optBckCalInd.usrNetIneractInd.pres	= PRSNT_DEF;
417 		acm.optBckCalInd.netExcDelInd.pres		= PRSNT_DEF;
418 	} /* if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) */
419 
420 	/* send the ACM request to LibSngSS7 */
421 	sng_cc_con_status  (1,
422 						sngss7_info->suInstId,
423 						sngss7_info->spInstId,
424 						sngss7_info->circuit->id,
425 						&acm,
426 						ADDRCMPLT);
427 
428 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ACM\n", sngss7_info->circuit->cic);
429 
430 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
431 	return;
432 }
433 
ft_to_sngss7_cpg(ftdm_channel_t * ftdmchan)434 void ft_to_sngss7_cpg (ftdm_channel_t *ftdmchan)
435 {
436 	SiCnStEvnt cpg;
437 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
438 
439 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
440 
441 
442 	memset (&cpg, 0, sizeof (cpg));
443 
444 	cpg.evntInfo.eh.pres = PRSNT_NODEF;
445 
446 	cpg.evntInfo.evntInd.pres = PRSNT_NODEF;
447 	cpg.evntInfo.evntInd.val = SNGSS7_EVNTINFO_IND_INBAND_AVAIL; /* Event Indicator = In-band info is now available */
448 
449 	cpg.evntInfo.evntPresResInd.pres = PRSNT_NODEF;
450 	cpg.evntInfo.evntPresResInd.val = 0;	/* Event presentation restricted indicator = no indication */
451 
452 	/* send the CPG request to LibSngSS7 */
453 	sng_cc_con_status  (1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &cpg, PROGRESS);
454 
455 	ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "[CIC:%d]Tx CPG\n", sngss7_info->circuit->cic);
456 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
457 	return;
458 }
ft_to_sngss7_anm(ftdm_channel_t * ftdmchan)459 void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
460 {
461 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
462 
463 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
464 	SiConEvnt anm;
465 
466 	memset (&anm, 0x0, sizeof (anm));
467 
468 	/* send the ANM request to LibSngSS7 */
469 	sng_cc_con_response(1,
470 						sngss7_info->suInstId,
471 						sngss7_info->spInstId,
472 						sngss7_info->circuit->id,
473 						&anm,
474 						5);
475 
476   SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ANM\n", sngss7_info->circuit->cic);
477 
478   SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
479   return;
480 }
481 
482 /******************************************************************************/
ft_to_sngss7_rel(ftdm_channel_t * ftdmchan)483 void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
484 {
485 	const char *loc_ind = NULL;
486 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
487 
488 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
489 	SiRelEvnt rel;
490 
491 	memset (&rel, 0x0, sizeof (rel));
492 
493 	rel.causeDgn.eh.pres = PRSNT_NODEF;
494 	rel.causeDgn.location.pres = PRSNT_NODEF;
495 
496 	loc_ind = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rel_loc");
497 	if (!ftdm_strlen_zero(loc_ind)) {
498 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied location indicator in REL, value \"%s\"\n", loc_ind);
499 		rel.causeDgn.location.val = atoi(loc_ind);
500 	} else {
501 		rel.causeDgn.location.val = 0x01;
502 		ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied location indicator in REL, using 0x01\"%s\"\n", "");
503 	}
504 	rel.causeDgn.cdeStand.pres = PRSNT_NODEF;
505 	rel.causeDgn.cdeStand.val = 0x00;
506 	rel.causeDgn.recommend.pres = NOTPRSNT;
507 	rel.causeDgn.causeVal.pres = PRSNT_NODEF;
508 	rel.causeDgn.causeVal.val = (uint8_t) ftdmchan->caller_data.hangup_cause;
509 	rel.causeDgn.dgnVal.pres = NOTPRSNT;
510 
511 	/* send the REL request to LibSngSS7 */
512 	sng_cc_rel_request (1,
513 			sngss7_info->suInstId,
514 			sngss7_info->spInstId,
515 			sngss7_info->circuit->id,
516 			&rel);
517 
518 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
519 							sngss7_info->circuit->cic,
520 							ftdmchan->caller_data.hangup_cause );
521 
522 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
523 	return;
524 }
525 
526 /******************************************************************************/
ft_to_sngss7_rlc(ftdm_channel_t * ftdmchan)527 void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan)
528 {
529 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
530 
531 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
532 	SiRelEvnt rlc;
533 
534 	memset (&rlc, 0x0, sizeof (rlc));
535 
536 	/* send the RLC request to LibSngSS7 */
537 	sng_cc_rel_response (1,
538 						sngss7_info->suInstId,
539 						sngss7_info->spInstId,
540 						sngss7_info->circuit->id,
541 						&rlc);
542 
543 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RLC\n", sngss7_info->circuit->cic);
544 
545 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
546 	return;
547 }
548 
549 /******************************************************************************/
ft_to_sngss7_rsc(ftdm_channel_t * ftdmchan)550 void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan)
551 {
552 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
553 
554 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
555 
556 	sng_cc_sta_request (1,
557 						sngss7_info->suInstId,
558 						sngss7_info->spInstId,
559 						sngss7_info->circuit->id,
560 						sngss7_info->globalFlg,
561 						SIT_STA_CIRRESREQ,
562 						NULL);
563 
564 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC\n", sngss7_info->circuit->cic);
565 
566 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
567 	return;
568 }
569 
570 /******************************************************************************/
ft_to_sngss7_rsca(ftdm_channel_t * ftdmchan)571 void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan)
572 {
573 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
574 
575 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
576 
577 	sng_cc_sta_request (1,
578 						sngss7_info->suInstId,
579 						sngss7_info->spInstId,
580 						sngss7_info->circuit->id,
581 						sngss7_info->globalFlg,
582 						SIT_STA_CIRRESRSP,
583 						NULL);
584 
585 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC-RLC\n", sngss7_info->circuit->cic);
586 
587 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
588   return;
589 }
590 
591 /******************************************************************************/
ft_to_sngss7_blo(ftdm_channel_t * ftdmchan)592 void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan)
593 {
594 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
595 
596 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
597 
598 	sng_cc_sta_request (1,
599 						0,
600 						0,
601 						sngss7_info->circuit->id,
602 						sngss7_info->globalFlg,
603 						SIT_STA_CIRBLOREQ,
604 						NULL);
605 
606 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLO\n", sngss7_info->circuit->cic);
607 
608 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
609 	return;
610 }
611 
612 /******************************************************************************/
ft_to_sngss7_bla(ftdm_channel_t * ftdmchan)613 void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan)
614 {
615 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
616 
617 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
618 
619 	sng_cc_sta_request (1,
620 						0,
621 						0,
622 						sngss7_info->circuit->id,
623 						sngss7_info->globalFlg,
624 						SIT_STA_CIRBLORSP,
625 						NULL);
626 
627 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLA\n", sngss7_info->circuit->cic);
628 
629 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
630 	return;
631 }
632 
633 /******************************************************************************/
634 void
ft_to_sngss7_ubl(ftdm_channel_t * ftdmchan)635 ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan)
636 {
637 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
638 
639 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
640 
641 	sng_cc_sta_request (1,
642 						0,
643 						0,
644 						sngss7_info->circuit->id,
645 						sngss7_info->globalFlg,
646 						SIT_STA_CIRUBLREQ,
647 						NULL);
648 
649 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBL\n", sngss7_info->circuit->cic);
650 
651 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
652 	return;
653 }
654 
655 /******************************************************************************/
ft_to_sngss7_uba(ftdm_channel_t * ftdmchan)656 void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan)
657 {
658 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
659 
660 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
661 
662 	sng_cc_sta_request (1,
663 						0,
664 						0,
665 						sngss7_info->circuit->id,
666 						sngss7_info->globalFlg,
667 						SIT_STA_CIRUBLRSP,
668 						NULL);
669 
670 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBA\n", sngss7_info->circuit->cic);
671 
672 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
673 	return;
674 }
675 
676 /******************************************************************************/
ft_to_sngss7_lpa(ftdm_channel_t * ftdmchan)677 void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan)
678 {
679 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
680 
681 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
682 
683 	sng_cc_sta_request (1,
684 						sngss7_info->suInstId,
685 						sngss7_info->spInstId,
686 						sngss7_info->circuit->id,
687 						sngss7_info->globalFlg,
688 						SIT_STA_LOOPBACKACK,
689 						NULL);
690 
691 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx LPA\n", sngss7_info->circuit->cic);
692 
693 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
694 return;
695 }
696 
697 /******************************************************************************/
ft_to_sngss7_gra(ftdm_channel_t * ftdmchan)698 void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
699 {
700 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
701 
702 	sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
703 	SiStaEvnt	gra;
704 
705 	/* clean out the gra struct */
706 	memset (&gra, 0x0, sizeof (gra));
707 
708 	gra.rangStat.eh.pres = PRSNT_NODEF;
709 
710 	/* fill in the range */
711 	gra.rangStat.range.pres = PRSNT_NODEF;
712 	gra.rangStat.range.val = sngss7_info->rx_grs.range;
713 
714 	/* fill in the status */
715 	gra.rangStat.status.pres = PRSNT_NODEF;
716 	gra.rangStat.status.len = ((sngss7_info->rx_grs.range + 1) >> 3) + (((sngss7_info->rx_grs.range + 1) & 0x07) ? 1 : 0);
717 
718 	/* the status field should be 1 if blocked for maintenace reasons
719 	* and 0 is not blocked....since we memset the struct nothing to do
720 	*/
721 
722 	/* send the GRA to LibSng-SS7 */
723 	sng_cc_sta_request (1,
724 						0,
725 						0,
726 						sngss7_info->rx_grs.circuit,
727 						0,
728 						SIT_STA_GRSRSP,
729 						&gra);
730 
731 	SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Tx GRA (%d:%d)\n",
732 							sngss7_info->circuit->cic,
733 							sngss7_info->circuit->cic,
734 							(sngss7_info->circuit->cic + sngss7_info->rx_grs.range));
735 
736 
737 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
738 	return;
739 }
740 
741 /******************************************************************************/
ft_to_sngss7_grs(ftdm_channel_t * fchan)742 void ft_to_sngss7_grs (ftdm_channel_t *fchan)
743 {
744 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
745 
746 	sngss7_chan_data_t *cinfo = fchan->call_data;
747 
748 	SiStaEvnt grs;
749 
750 	ftdm_assert(sngss7_test_ckt_flag(cinfo, FLAG_GRP_RESET_TX) &&
751 		   !sngss7_test_ckt_flag(cinfo, FLAG_GRP_RESET_SENT), "Incorrect flags\n");
752 
753 	memset (&grs, 0x0, sizeof(grs));
754 	grs.rangStat.eh.pres    = PRSNT_NODEF;
755 	grs.rangStat.range.pres = PRSNT_NODEF;
756 	grs.rangStat.range.val  = cinfo->tx_grs.range;
757 
758 	sng_cc_sta_request (1,
759 		0,
760 		0,
761 		cinfo->tx_grs.circuit,
762 		0,
763 		SIT_STA_GRSREQ,
764 		&grs);
765 
766 	SS7_INFO_CHAN(fchan, "[CIC:%d]Tx GRS (%d:%d)\n",
767 		cinfo->circuit->cic,
768 		cinfo->circuit->cic,
769 		(cinfo->circuit->cic + cinfo->tx_grs.range));
770 
771 	sngss7_set_ckt_flag(cinfo, FLAG_GRP_RESET_SENT);
772 
773 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
774 }
775 
776 /******************************************************************************/
ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan)777 void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan)
778 {
779 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
780 
781 	sngss7_span_data_t 	*sngss7_span = ftdmchan->span->signal_data;
782 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
783 	int					x = 0;
784 
785 	SiStaEvnt cgba;
786 
787 	memset (&cgba, 0x0, sizeof(cgba));
788 
789 	/* fill in the circuit group supervisory message */
790 	cgba.cgsmti.eh.pres = PRSNT_NODEF;
791 	cgba.cgsmti.typeInd.pres = PRSNT_NODEF;
792 	cgba.cgsmti.typeInd.val = sngss7_span->rx_cgb.type;
793 
794 	cgba.rangStat.eh.pres = PRSNT_NODEF;
795 	/* fill in the range */
796 	cgba.rangStat.range.pres = PRSNT_NODEF;
797 	cgba.rangStat.range.val = sngss7_span->rx_cgb.range;
798 	/* fill in the status */
799 	cgba.rangStat.status.pres = PRSNT_NODEF;
800 	cgba.rangStat.status.len = ((sngss7_span->rx_cgb.range + 1) >> 3) + (((sngss7_span->rx_cgb.range + 1) & 0x07) ? 1 : 0);
801 	for(x = 0; x < cgba.rangStat.status.len; x++){
802 		cgba.rangStat.status.val[x] = sngss7_span->rx_cgb.status[x];
803 	}
804 
805 	sng_cc_sta_request (1,
806 						0,
807 						0,
808 						sngss7_span->rx_cgb.circuit,
809 						0,
810 						SIT_STA_CGBRSP,
811 						&cgba);
812 
813 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGBA (%d:%d)\n",
814 							sngss7_info->circuit->cic,
815 							sngss7_info->circuit->cic,
816 							(sngss7_info->circuit->cic + sngss7_span->rx_cgb.range));
817 
818 	/* clean out the saved data */
819 	memset(&sngss7_span->rx_cgb, 0x0, sizeof(sngss7_group_data_t));
820 
821 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
822 	return;
823 }
824 
825 /******************************************************************************/
ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan)826 void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan)
827 {
828 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
829 
830 	sngss7_span_data_t 	*sngss7_span = ftdmchan->span->signal_data;
831 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
832 	int					x = 0;
833 
834 	SiStaEvnt cgua;
835 
836 	memset (&cgua, 0x0, sizeof(cgua));
837 
838 	/* fill in the circuit group supervisory message */
839 	cgua.cgsmti.eh.pres = PRSNT_NODEF;
840 	cgua.cgsmti.typeInd.pres = PRSNT_NODEF;
841 	cgua.cgsmti.typeInd.val = sngss7_span->rx_cgu.type;
842 
843 	cgua.rangStat.eh.pres = PRSNT_NODEF;
844 	/* fill in the range */
845 	cgua.rangStat.range.pres = PRSNT_NODEF;
846 	cgua.rangStat.range.val = sngss7_span->rx_cgu.range;
847 	/* fill in the status */
848 	cgua.rangStat.status.pres = PRSNT_NODEF;
849 	cgua.rangStat.status.len = ((sngss7_span->rx_cgu.range + 1) >> 3) + (((sngss7_span->rx_cgu.range + 1) & 0x07) ? 1 : 0);
850 	for(x = 0; x < cgua.rangStat.status.len; x++){
851 		cgua.rangStat.status.val[x] = sngss7_span->rx_cgu.status[x];
852 	}
853 
854 	sng_cc_sta_request (1,
855 						0,
856 						0,
857 						sngss7_span->rx_cgu.circuit,
858 						0,
859 						SIT_STA_CGURSP,
860 						&cgua);
861 
862 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGUA (%d:%d)\n",
863 							sngss7_info->circuit->cic,
864 							sngss7_info->circuit->cic,
865 							(sngss7_info->circuit->cic + sngss7_span->rx_cgu.range));
866 
867 	/* clean out the saved data */
868 	memset(&sngss7_span->rx_cgu, 0x0, sizeof(sngss7_group_data_t));
869 
870 
871 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
872 	return;
873 }
874 
875 /******************************************************************************/
ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan)876 void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan)
877 {
878 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
879 
880 	sngss7_span_data_t 	*sngss7_span = ftdmchan->span->signal_data;
881 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
882 	SiStaEvnt 			cgb;
883 	int					x = 0;
884 
885 
886 	memset (&cgb, 0x0, sizeof(cgb));
887 
888 	/* fill in the circuit group supervisory message */
889 	cgb.cgsmti.eh.pres			= PRSNT_NODEF;
890 	cgb.cgsmti.typeInd.pres		= PRSNT_NODEF;
891 	cgb.cgsmti.typeInd.val		= sngss7_span->tx_cgb.type;
892 
893 	/* fill in the range */
894 	cgb.rangStat.eh.pres 		= PRSNT_NODEF;
895 	cgb.rangStat.range.pres		= PRSNT_NODEF;
896 	cgb.rangStat.range.val 		= sngss7_span->tx_cgb.range;
897 
898 	/* fill in the status */
899 	cgb.rangStat.status.pres	= PRSNT_NODEF;
900 	cgb.rangStat.status.len 	= ((sngss7_span->tx_cgb.range + 1) >> 3) + (((sngss7_span->tx_cgb.range + 1) & 0x07) ? 1 : 0);
901 	for(x = 0; x < cgb.rangStat.status.len; x++){
902 		cgb.rangStat.status.val[x] = sngss7_span->tx_cgb.status[x];
903 	}
904 
905 	sng_cc_sta_request (1,
906 						0,
907 						0,
908 						sngss7_span->tx_cgb.circuit,
909 						0,
910 						SIT_STA_CGBREQ,
911 						&cgb);
912 
913 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGB (%d:%d)\n",
914 							sngss7_info->circuit->cic,
915 							sngss7_info->circuit->cic,
916 							(sngss7_info->circuit->cic + sngss7_span->tx_cgb.range));
917 
918 	/* clean out the saved data */
919 	memset(&sngss7_span->tx_cgb, 0x0, sizeof(sngss7_group_data_t));
920 
921 
922 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
923 	return;
924 }
925 
926 /******************************************************************************/
ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan)927 void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan)
928 {
929 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
930 
931 	sngss7_span_data_t 	*sngss7_span = ftdmchan->span->signal_data;
932 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
933 	SiStaEvnt 			cgu;
934 	int					x = 0;
935 
936 
937 	memset (&cgu, 0x0, sizeof(cgu));
938 
939 	/* fill in the circuit group supervisory message */
940 	cgu.cgsmti.eh.pres			= PRSNT_NODEF;
941 	cgu.cgsmti.typeInd.pres		= PRSNT_NODEF;
942 	cgu.cgsmti.typeInd.val		= sngss7_span->tx_cgu.type;
943 
944 	/* fill in the range */
945 	cgu.rangStat.eh.pres 		= PRSNT_NODEF;
946 	cgu.rangStat.range.pres		= PRSNT_NODEF;
947 	cgu.rangStat.range.val 		= sngss7_span->tx_cgu.range;
948 
949 	/* fill in the status */
950 	cgu.rangStat.status.pres	= PRSNT_NODEF;
951 	cgu.rangStat.status.len 	= ((sngss7_span->tx_cgu.range + 1) >> 3) + (((sngss7_span->tx_cgu.range + 1) & 0x07) ? 1 : 0);
952 	for(x = 0; x < cgu.rangStat.status.len; x++){
953 		cgu.rangStat.status.val[x] = sngss7_span->tx_cgu.status[x];
954 	}
955 
956 	sng_cc_sta_request (1,
957 						0,
958 						0,
959 						sngss7_span->tx_cgu.circuit,
960 						0,
961 						SIT_STA_CGUREQ,
962 						&cgu);
963 
964 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx CGU (%d:%d)\n",
965 							sngss7_info->circuit->cic,
966 							sngss7_info->circuit->cic,
967 							(sngss7_info->circuit->cic + sngss7_span->tx_cgu.range));
968 
969 	/* clean out the saved data */
970 	memset(&sngss7_span->tx_cgu, 0x0, sizeof(sngss7_group_data_t));
971 
972 
973 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
974 	return;
975 }
976 
977 /* French SPIROU send Charge Unit */
978 /* No one calls this function yet, but it has been implemented to complement TXA messages */
ft_to_sngss7_itx(ftdm_channel_t * ftdmchan)979 void ft_to_sngss7_itx (ftdm_channel_t * ftdmchan)
980 {
981 #ifndef SANGOMA_SPIROU
982 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
983 	ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "ITX message not supported!, please update your libsng_ss7\n");
984 #else
985 	const char* var = NULL;
986 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
987 	SiCnStEvnt itx;
988 
989 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
990 
991 	memset (&itx, 0x0, sizeof (itx));
992 
993 	itx.msgNum.eh.pres = PRSNT_NODEF;
994 	itx.msgNum.msgNum.pres = PRSNT_NODEF;
995 	var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_itx_msg_num");
996 	if (!ftdm_strlen_zero(var)) {
997 		itx.msgNum.msgNum.val = atoi(var);
998 	} else {
999 		itx.msgNum.msgNum.val = 0x1;
1000 	}
1001 
1002 	itx.chargUnitNum.eh.pres = PRSNT_NODEF;
1003 	itx.chargUnitNum.chargUnitNum.pres = PRSNT_NODEF;
1004 	var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_itx_charge_unit");
1005 	if (!ftdm_strlen_zero(var)) {
1006 		itx.chargUnitNum.chargUnitNum.val = atoi(var);
1007 	} else {
1008 		itx.chargUnitNum.chargUnitNum.val = 0x1;
1009 	}
1010 
1011 	ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "ITX Charging Unit:%d Msg Num:%d\n", itx.chargUnitNum.chargUnitNum.val, itx.msgNum.msgNum.val);
1012 	sng_cc_con_status  (1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &itx, CHARGE_UNIT);
1013 
1014 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ITX\n", sngss7_info->circuit->cic);
1015 #endif
1016 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
1017 	return;
1018 }
1019 
1020 /* French SPIROU send Charging Acknowledgement */
ft_to_sngss7_txa(ftdm_channel_t * ftdmchan)1021 void ft_to_sngss7_txa (ftdm_channel_t * ftdmchan)
1022 {
1023 #ifndef SANGOMA_SPIROU
1024 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
1025 	ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "TXA message not supported!, please update your libsng_ss7\n");
1026 #else
1027 	SiCnStEvnt txa;
1028 	sngss7_chan_data_t	*sngss7_info = ftdmchan->call_data;
1029 	SS7_FUNC_TRACE_ENTER (__FTDM_FUNC__);
1030 
1031 	memset (&txa, 0x0, sizeof(txa));
1032 
1033 	sng_cc_con_status(1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &txa, CHARGE_ACK);
1034 
1035 	SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx TXA\n", sngss7_info->circuit->cic);
1036 #endif
1037 	SS7_FUNC_TRACE_EXIT (__FTDM_FUNC__);
1038 	return;
1039 }
1040 
1041 /******************************************************************************/
1042 /* For Emacs:
1043  * Local Variables:
1044  * mode:c
1045  * indent-tabs-mode:t
1046  * tab-width:4
1047  * c-basic-offset:4
1048  * End:
1049  * For VIM:
1050  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
1051  */
1052 /******************************************************************************/
1053