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