Wed Jan 8 2020 09:49:51

Asterisk developer's documentation


sig_ss7.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010 Digium, Inc.
5  *
6  * Richard Mudgett <rmudgett@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \brief SS7 signaling module.
22  *
23  * \author Matthew Fredrickson <creslin@digium.com>
24  * \author Richard Mudgett <rmudgett@digium.com>
25  *
26  * See Also:
27  * \arg \ref AstCREDITS
28  */
29 
30 /*** MODULEINFO
31  <support_level>core</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 #if defined(HAVE_SS7)
37 
38 #include <signal.h>
39 
40 #include "asterisk/pbx.h"
41 #include "asterisk/causes.h"
42 #include "asterisk/musiconhold.h"
43 #include "asterisk/cli.h"
44 #include "asterisk/transcap.h"
45 
46 #include "sig_ss7.h"
47 #if defined(LIBSS7_ABI_COMPATIBILITY)
48 #error "Your installed libss7 is not compatible"
49 #endif
50 
51 /* ------------------------------------------------------------------- */
52 
53 static const char *sig_ss7_call_level2str(enum sig_ss7_call_level level)
54 {
55  switch (level) {
57  return "Idle";
59  return "Allocated";
61  return "Continuity";
63  return "Setup";
65  return "Proceeding";
67  return "Alerting";
69  return "Connect";
71  return "Glare";
72  }
73  return "Unknown";
74 }
75 
76 static void sig_ss7_unlock_private(struct sig_ss7_chan *p)
77 {
78  if (p->calls->unlock_private) {
80  }
81 }
82 
83 static void sig_ss7_lock_private(struct sig_ss7_chan *p)
84 {
85  if (p->calls->lock_private) {
86  p->calls->lock_private(p->chan_pvt);
87  }
88 }
89 
90 void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
91 {
92  p->inalarm = in_alarm;
93  if (p->calls->set_alarm) {
94  p->calls->set_alarm(p->chan_pvt, in_alarm);
95  }
96 }
97 
98 static void sig_ss7_set_dialing(struct sig_ss7_chan *p, int is_dialing)
99 {
100  if (p->calls->set_dialing) {
101  p->calls->set_dialing(p->chan_pvt, is_dialing);
102  }
103 }
104 
105 static void sig_ss7_set_digital(struct sig_ss7_chan *p, int is_digital)
106 {
107  if (p->calls->set_digital) {
108  p->calls->set_digital(p->chan_pvt, is_digital);
109  }
110 }
111 
112 static void sig_ss7_set_outgoing(struct sig_ss7_chan *p, int is_outgoing)
113 {
114  p->outgoing = is_outgoing;
115  if (p->calls->set_outgoing) {
116  p->calls->set_outgoing(p->chan_pvt, is_outgoing);
117  }
118 }
119 
120 static void sig_ss7_set_inservice(struct sig_ss7_chan *p, int is_inservice)
121 {
122  if (p->calls->set_inservice) {
123  p->calls->set_inservice(p->chan_pvt, is_inservice);
124  }
125 }
126 
127 static void sig_ss7_set_locallyblocked(struct sig_ss7_chan *p, int is_blocked)
128 {
129  p->locallyblocked = is_blocked;
130  if (p->calls->set_locallyblocked) {
131  p->calls->set_locallyblocked(p->chan_pvt, is_blocked);
132  }
133 }
134 
135 static void sig_ss7_set_remotelyblocked(struct sig_ss7_chan *p, int is_blocked)
136 {
137  p->remotelyblocked = is_blocked;
138  if (p->calls->set_remotelyblocked) {
139  p->calls->set_remotelyblocked(p->chan_pvt, is_blocked);
140  }
141 }
142 
143 /*!
144  * \internal
145  * \brief Open the SS7 channel media path.
146  * \since 1.8.12
147  *
148  * \param p Channel private control structure.
149  *
150  * \return Nothing
151  */
152 static void sig_ss7_open_media(struct sig_ss7_chan *p)
153 {
154  if (p->calls->open_media) {
155  p->calls->open_media(p->chan_pvt);
156  }
157 }
158 
159 /*!
160  * \internal
161  * \brief Set the caller id information in the parent module.
162  * \since 1.8
163  *
164  * \param p sig_ss7 channel structure.
165  *
166  * \return Nothing
167  */
168 static void sig_ss7_set_caller_id(struct sig_ss7_chan *p)
169 {
170  struct ast_party_caller caller;
171 
172  if (p->calls->set_callerid) {
173  ast_party_caller_init(&caller);
174 
175  caller.id.name.str = p->cid_name;
176  caller.id.name.presentation = p->callingpres;
177  caller.id.name.valid = 1;
178 
179  caller.id.number.str = p->cid_num;
180  caller.id.number.plan = p->cid_ton;
181  caller.id.number.presentation = p->callingpres;
182  caller.id.number.valid = 1;
183 
184  if (!ast_strlen_zero(p->cid_subaddr)) {
185  caller.id.subaddress.valid = 1;
186  //caller.id.subaddress.type = 0;/* nsap */
187  //caller.id.subaddress.odd_even_indicator = 0;
188  caller.id.subaddress.str = p->cid_subaddr;
189  }
190 
191  caller.ani.number.str = p->cid_ani;
192  //caller.ani.number.plan = p->xxx;
193  //caller.ani.number.presentation = p->xxx;
194  caller.ani.number.valid = 1;
195 
196  caller.ani2 = p->cid_ani2;
197  p->calls->set_callerid(p->chan_pvt, &caller);
198  }
199 }
200 
201 /*!
202  * \internal
203  * \brief Set the Dialed Number Identifier.
204  * \since 1.8
205  *
206  * \param p sig_ss7 channel structure.
207  * \param dnid Dialed Number Identifier string.
208  *
209  * \return Nothing
210  */
211 static void sig_ss7_set_dnid(struct sig_ss7_chan *p, const char *dnid)
212 {
213  if (p->calls->set_dnid) {
214  p->calls->set_dnid(p->chan_pvt, dnid);
215  }
216 }
217 
218 static int sig_ss7_play_tone(struct sig_ss7_chan *p, enum sig_ss7_tone tone)
219 {
220  int res;
221 
222  if (p->calls->play_tone) {
223  res = p->calls->play_tone(p->chan_pvt, tone);
224  } else {
225  res = -1;
226  }
227  return res;
228 }
229 
230 static int sig_ss7_set_echocanceller(struct sig_ss7_chan *p, int enable)
231 {
232  if (p->calls->set_echocanceller) {
233  return p->calls->set_echocanceller(p->chan_pvt, enable);
234  }
235  return -1;
236 }
237 
238 static void sig_ss7_loopback(struct sig_ss7_chan *p, int enable)
239 {
240  if (p->loopedback != enable) {
241  p->loopedback = enable;
242  if (p->calls->set_loopback) {
243  p->calls->set_loopback(p->chan_pvt, enable);
244  }
245  }
246 }
247 
248 static struct ast_channel *sig_ss7_new_ast_channel(struct sig_ss7_chan *p, int state, int ulaw, int transfercapability, char *exten, const struct ast_channel *requestor)
249 {
250  struct ast_channel *ast;
251 
252  if (p->calls->new_ast_channel) {
253  ast = p->calls->new_ast_channel(p->chan_pvt, state, ulaw, exten, requestor);
254  } else {
255  return NULL;
256  }
257  if (!ast) {
258  return NULL;
259  }
260 
261  if (!p->owner) {
262  p->owner = ast;
263  }
264  p->alreadyhungup = 0;
266  pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY",
267  ast_transfercapability2str(transfercapability));
268  if (transfercapability & AST_TRANS_CAP_DIGITAL) {
269  sig_ss7_set_digital(p, 1);
270  }
271 
272  return ast;
273 }
274 
275 static void sig_ss7_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
276 {
277  if (linkset->calls->handle_link_exception) {
278  linkset->calls->handle_link_exception(linkset, which);
279  }
280 }
281 
282 /*!
283  * \internal
284  * \brief Determine if a private channel structure is available.
285  *
286  * \param pvt Channel to determine if available.
287  *
288  * \return TRUE if the channel is available.
289  */
290 static int sig_ss7_is_chan_available(struct sig_ss7_chan *pvt)
291 {
292  if (!pvt->inalarm && !pvt->owner && !pvt->ss7call
294  && !pvt->locallyblocked && !pvt->remotelyblocked) {
295  return 1;
296  }
297  return 0;
298 }
299 
300 /*!
301  * \internal
302  * \brief Obtain the sig_ss7 owner channel lock if the owner exists.
303  * \since 1.8
304  *
305  * \param ss7 SS7 linkset control structure.
306  * \param chanpos Channel position in the span.
307  *
308  * \note Assumes the ss7->lock is already obtained.
309  * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
310  *
311  * \return Nothing
312  */
313 static void sig_ss7_lock_owner(struct sig_ss7_linkset *ss7, int chanpos)
314 {
315  for (;;) {
316  if (!ss7->pvts[chanpos]->owner) {
317  /* There is no owner lock to get. */
318  break;
319  }
320  if (!ast_channel_trylock(ss7->pvts[chanpos]->owner)) {
321  /* We got the lock */
322  break;
323  }
324 
325  /* Avoid deadlock */
326  sig_ss7_unlock_private(ss7->pvts[chanpos]);
327  DEADLOCK_AVOIDANCE(&ss7->lock);
328  sig_ss7_lock_private(ss7->pvts[chanpos]);
329  }
330 }
331 
332 /*!
333  * \internal
334  * \brief Queue the given frame onto the owner channel.
335  * \since 1.8
336  *
337  * \param ss7 SS7 linkset control structure.
338  * \param chanpos Channel position in the span.
339  * \param frame Frame to queue onto the owner channel.
340  *
341  * \note Assumes the ss7->lock is already obtained.
342  * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
343  *
344  * \return Nothing
345  */
346 static void sig_ss7_queue_frame(struct sig_ss7_linkset *ss7, int chanpos, struct ast_frame *frame)
347 {
348  sig_ss7_lock_owner(ss7, chanpos);
349  if (ss7->pvts[chanpos]->owner) {
350  ast_queue_frame(ss7->pvts[chanpos]->owner, frame);
351  ast_channel_unlock(ss7->pvts[chanpos]->owner);
352  }
353 }
354 
355 /*!
356  * \internal
357  * \brief Queue a control frame of the specified subclass onto the owner channel.
358  * \since 1.8
359  *
360  * \param ss7 SS7 linkset control structure.
361  * \param chanpos Channel position in the span.
362  * \param subclass Control frame subclass to queue onto the owner channel.
363  *
364  * \note Assumes the ss7->lock is already obtained.
365  * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
366  *
367  * \return Nothing
368  */
369 static void sig_ss7_queue_control(struct sig_ss7_linkset *ss7, int chanpos, int subclass)
370 {
371  struct ast_frame f = {AST_FRAME_CONTROL, };
372  struct sig_ss7_chan *p = ss7->pvts[chanpos];
373 
374  if (p->calls->queue_control) {
375  p->calls->queue_control(p->chan_pvt, subclass);
376  }
377 
378  f.subclass.integer = subclass;
379  sig_ss7_queue_frame(ss7, chanpos, &f);
380 }
381 
382 /*!
383  * \internal
384  * \brief Find the channel position by CIC/DPC.
385  *
386  * \param linkset SS7 linkset control structure.
387  * \param cic Circuit Identification Code
388  * \param dpc Destination Point Code
389  *
390  * \retval chanpos on success.
391  * \retval -1 on error.
392  */
393 static int ss7_find_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
394 {
395  int i;
396  int winner = -1;
397  for (i = 0; i < linkset->numchans; i++) {
398  if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
399  winner = i;
400  break;
401  }
402  }
403  return winner;
404 }
405 
406 /*!
407  * \internal
408  * \brief Find the channel position by CIC/DPC and gripe if not found.
409  *
410  * \param linkset SS7 linkset control structure.
411  * \param cic Circuit Identification Code
412  * \param dpc Destination Point Code
413  * \param msg_name Message type name that failed.
414  *
415  * \retval chanpos on success.
416  * \retval -1 on error.
417  */
418 static int ss7_find_cic_gripe(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc, const char *msg_name)
419 {
420  int chanpos;
421 
422  chanpos = ss7_find_cic(linkset, cic, dpc);
423  if (chanpos < 0) {
424  ast_log(LOG_WARNING, "Linkset %d: SS7 %s requested unconfigured CIC/DPC %d/%d.\n",
425  linkset->span, msg_name, cic, dpc);
426  return -1;
427  }
428  return chanpos;
429 }
430 
431 static void ss7_handle_cqm(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
432 {
433  unsigned char status[32];
434  struct sig_ss7_chan *p = NULL;
435  int i, offset;
436 
437  for (i = 0; i < linkset->numchans; i++) {
438  if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
439  p = linkset->pvts[i];
440  offset = p->cic - startcic;
441  status[offset] = 0;
442  if (p->locallyblocked)
443  status[offset] |= (1 << 0) | (1 << 4);
444  if (p->remotelyblocked)
445  status[offset] |= (1 << 1) | (1 << 5);
446  if (p->ss7call) {
447  if (p->outgoing)
448  status[offset] |= (1 << 3);
449  else
450  status[offset] |= (1 << 2);
451  } else
452  status[offset] |= 0x3 << 2;
453  }
454  }
455 
456  if (p)
457  isup_cqr(linkset->ss7, startcic, endcic, dpc, status);
458  else
459  ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
460 
461 }
462 
463 static inline void ss7_hangup_cics(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
464 {
465  int i;
466 
467  for (i = 0; i < linkset->numchans; i++) {
468  if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
469  sig_ss7_lock_private(linkset->pvts[i]);
470  sig_ss7_lock_owner(linkset, i);
471  if (linkset->pvts[i]->owner) {
473  ast_channel_unlock(linkset->pvts[i]->owner);
474  }
475  sig_ss7_unlock_private(linkset->pvts[i]);
476  }
477  }
478 }
479 
480 static inline void ss7_block_cics(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block)
481 {
482  int i;
483 
484  /* XXX the use of state here seems questionable about matching up with the linkset channels */
485  for (i = 0; i < linkset->numchans; i++) {
486  if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic)))) {
487  if (state) {
488  if (state[i])
489  sig_ss7_set_remotelyblocked(linkset->pvts[i], block);
490  } else
491  sig_ss7_set_remotelyblocked(linkset->pvts[i], block);
492  }
493  }
494 }
495 
496 static void ss7_inservice(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
497 {
498  int i;
499 
500  for (i = 0; i < linkset->numchans; i++) {
501  if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && ((linkset->pvts[i]->cic >= startcic) && (linkset->pvts[i]->cic <= endcic))))
502  sig_ss7_set_inservice(linkset->pvts[i], 1);
503  }
504 }
505 
506 static void ss7_reset_linkset(struct sig_ss7_linkset *linkset)
507 {
508  int i, startcic = -1, endcic, dpc;
509 
510  if (linkset->numchans <= 0)
511  return;
512 
513  startcic = linkset->pvts[0]->cic;
514  /* DB: CIC's DPC fix */
515  dpc = linkset->pvts[0]->dpc;
516 
517  for (i = 0; i < linkset->numchans; i++) {
518  if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
519  continue;
520  } else {
521  endcic = linkset->pvts[i]->cic;
522  ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
523  isup_grs(linkset->ss7, startcic, endcic, dpc);
524 
525  /* DB: CIC's DPC fix */
526  if (linkset->pvts[i+1]) {
527  startcic = linkset->pvts[i+1]->cic;
528  dpc = linkset->pvts[i+1]->dpc;
529  }
530  }
531  }
532 }
533 
534 /* This function is assumed to be called with the private channel lock and linkset lock held */
535 static void ss7_start_call(struct sig_ss7_chan *p, struct sig_ss7_linkset *linkset)
536 {
537  struct ss7 *ss7 = linkset->ss7;
538  int law;
539  struct ast_channel *c;
540  char tmp[256];
541 
542  if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
544  isup_acm(ss7, p->ss7call);
545  } else {
547  }
548 
549  /* Companding law is determined by SS7 signaling type. */
550  if (linkset->type == SS7_ITU) {
551  law = SIG_SS7_ALAW;
552  } else {
553  law = SIG_SS7_ULAW;
554  }
555 
556  /*
557  * Release the SS7 lock while we create the channel so other
558  * threads can send messages. We must also release the private
559  * lock to prevent deadlock while creating the channel.
560  */
561  ast_mutex_unlock(&linkset->lock);
562  sig_ss7_unlock_private(p);
563  c = sig_ss7_new_ast_channel(p, AST_STATE_RING, law, 0, p->exten, NULL);
564  if (!c) {
565  ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
566  ast_mutex_lock(&linkset->lock);
567  sig_ss7_lock_private(p);
568  isup_rel(linkset->ss7, p->ss7call, AST_CAUSE_SWITCH_CONGESTION);
570  p->alreadyhungup = 1;
571  return;
572  }
573 
574  /* Hold the channel and private lock while we setup the channel. */
575  ast_channel_lock(c);
576  sig_ss7_lock_private(p);
577 
578  sig_ss7_set_echocanceller(p, 1);
579 
580  /*
581  * It is reasonably safe to set the following
582  * channel variables while the channel private
583  * structure is locked. The PBX has not been
584  * started yet and it is unlikely that any other task
585  * will do anything with the channel we have just
586  * created.
587  *
588  * We only reference these variables in the context of the ss7_linkset function
589  * when receiving either and IAM or a COT message.
590  */
591  if (!ast_strlen_zero(p->charge_number)) {
592  pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
593  /* Clear this after we set it */
594  p->charge_number[0] = 0;
595  }
596  if (!ast_strlen_zero(p->gen_add_number)) {
597  pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
598  /* Clear this after we set it */
599  p->gen_add_number[0] = 0;
600  }
601  if (!ast_strlen_zero(p->jip_number)) {
602  pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
603  /* Clear this after we set it */
604  p->jip_number[0] = 0;
605  }
606  if (!ast_strlen_zero(p->gen_dig_number)) {
607  pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
608  /* Clear this after we set it */
609  p->gen_dig_number[0] = 0;
610  }
611  if (!ast_strlen_zero(p->orig_called_num)) {
612  pbx_builtin_setvar_helper(c, "SS7_ORIG_CALLED_NUM", p->orig_called_num);
613  /* Clear this after we set it */
614  p->orig_called_num[0] = 0;
615  }
616 
617  snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
618  pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
619  /* Clear this after we set it */
620  p->gen_dig_type = 0;
621 
622  snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
623  pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
624  /* Clear this after we set it */
625  p->gen_dig_scheme = 0;
626 
627  if (!ast_strlen_zero(p->lspi_ident)) {
628  pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
629  /* Clear this after we set it */
630  p->lspi_ident[0] = 0;
631  }
632 
633  snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
634  pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
635  /* Clear this after we set it */
636  p->call_ref_ident = 0;
637 
638  snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
639  pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
640  /* Clear this after we set it */
641  p->call_ref_pc = 0;
642 
643  snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
644  pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
645  /* Clear this after we set it */
646  p->calling_party_cat = 0;
647 
648  if (!ast_strlen_zero(p->redirecting_num)) {
649  pbx_builtin_setvar_helper(c, "SS7_REDIRECTING_NUMBER", p->redirecting_num);
650  /* Clear this after we set it */
651  p->redirecting_num[0] = 0;
652  }
653  if (!ast_strlen_zero(p->generic_name)) {
654  pbx_builtin_setvar_helper(c, "SS7_GENERIC_NAME", p->generic_name);
655  /* Clear this after we set it */
656  p->generic_name[0] = 0;
657  }
658 
659  sig_ss7_unlock_private(p);
661 
662  if (ast_pbx_start(c)) {
663  ast_log(LOG_WARNING, "Unable to start PBX on %s (CIC %d)\n", c->name, p->cic);
664  ast_hangup(c);
665  } else {
666  ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
667  }
668 
669  /* Must return with linkset and private lock. */
670  ast_mutex_lock(&linkset->lock);
671  sig_ss7_lock_private(p);
672 }
673 
674 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct sig_ss7_linkset *ss7, const char *number, const unsigned nai)
675 {
676  if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
677  if (size) {
678  *buf = '\0';
679  }
680  return;
681  }
682  switch (nai) {
683  case SS7_NAI_INTERNATIONAL:
684  snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
685  break;
686  case SS7_NAI_NATIONAL:
687  snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
688  break;
689  case SS7_NAI_SUBSCRIBER:
690  snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
691  break;
692  case SS7_NAI_UNKNOWN:
693  snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
694  break;
695  default:
696  snprintf(buf, size, "%s", number);
697  break;
698  }
699 }
700 
701 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
702 {
703  return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
704 }
705 
706 /* This is a thread per linkset that handles all received events from libss7. */
707 void *ss7_linkset(void *data)
708 {
709  int res, i;
710  struct timeval *next = NULL, tv;
711  struct sig_ss7_linkset *linkset = (struct sig_ss7_linkset *) data;
712  struct ss7 *ss7 = linkset->ss7;
713  ss7_event *e = NULL;
714  struct sig_ss7_chan *p;
715  int chanpos;
716  struct pollfd pollers[SIG_SS7_NUM_DCHANS];
717  int nextms;
718 
719 #define SS7_MAX_POLL 60000 /* Maximum poll time in ms. */
720 
721  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
722 
723  ss7_set_debug(ss7, SIG_SS7_DEBUG_DEFAULT);
724  ast_mutex_lock(&linkset->lock);
725  ss7_start(ss7);
726  ast_mutex_unlock(&linkset->lock);
727 
728  for (;;) {
729  ast_mutex_lock(&linkset->lock);
730  if ((next = ss7_schedule_next(ss7))) {
731  tv = ast_tvnow();
732  tv.tv_sec = next->tv_sec - tv.tv_sec;
733  tv.tv_usec = next->tv_usec - tv.tv_usec;
734  if (tv.tv_usec < 0) {
735  tv.tv_usec += 1000000;
736  tv.tv_sec -= 1;
737  }
738  if (tv.tv_sec < 0) {
739  tv.tv_sec = 0;
740  tv.tv_usec = 0;
741  }
742  nextms = tv.tv_sec * 1000;
743  nextms += tv.tv_usec / 1000;
744  if (SS7_MAX_POLL < nextms) {
745  nextms = SS7_MAX_POLL;
746  }
747  } else {
748  nextms = SS7_MAX_POLL;
749  }
750 
751  for (i = 0; i < linkset->numsigchans; i++) {
752  pollers[i].fd = linkset->fds[i];
753  pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
754  pollers[i].revents = 0;
755  }
756  ast_mutex_unlock(&linkset->lock);
757 
758  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
759  pthread_testcancel();
760  res = poll(pollers, linkset->numsigchans, nextms);
761  pthread_testcancel();
762  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
763 
764  if ((res < 0) && (errno != EINTR)) {
765  ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
766  } else if (!res) {
767  ast_mutex_lock(&linkset->lock);
768  ss7_schedule_run(ss7);
769  ast_mutex_unlock(&linkset->lock);
770  continue;
771  }
772 
773  ast_mutex_lock(&linkset->lock);
774  for (i = 0; i < linkset->numsigchans; i++) {
775  if (pollers[i].revents & POLLPRI) {
776  sig_ss7_handle_link_exception(linkset, i);
777  }
778  if (pollers[i].revents & POLLIN) {
779  res = ss7_read(ss7, pollers[i].fd);
780  }
781  if (pollers[i].revents & POLLOUT) {
782  res = ss7_write(ss7, pollers[i].fd);
783  if (res < 0) {
784  ast_debug(1, "Error in write %s\n", strerror(errno));
785  }
786  }
787  }
788 
789  while ((e = ss7_check_event(ss7))) {
790  if (linkset->debug) {
791  ast_verbose("Linkset %d: Processing event: %s\n",
792  linkset->span, ss7_event2str(e->e));
793  }
794 
795  switch (e->e) {
796  case SS7_EVENT_UP:
797  if (linkset->state != LINKSET_STATE_UP) {
798  ast_verbose("--- SS7 Up ---\n");
799  ss7_reset_linkset(linkset);
800  }
801  linkset->state = LINKSET_STATE_UP;
802  break;
803  case SS7_EVENT_DOWN:
804  ast_verbose("--- SS7 Down ---\n");
805  linkset->state = LINKSET_STATE_DOWN;
806  for (i = 0; i < linkset->numchans; i++) {
807  p = linkset->pvts[i];
808  if (p) {
809  sig_ss7_set_alarm(p, 1);
810  }
811  }
812  break;
813  case MTP2_LINK_UP:
814  ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
815  break;
816  case MTP2_LINK_DOWN:
817  ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
818  break;
819  case ISUP_EVENT_CPG:
820  chanpos = ss7_find_cic_gripe(linkset, e->cpg.cic, e->cpg.opc, "CPG");
821  if (chanpos < 0) {
822  break;
823  }
824  p = linkset->pvts[chanpos];
825  sig_ss7_lock_private(p);
826  switch (e->cpg.event) {
827  case CPG_EVENT_ALERTING:
830  }
831  sig_ss7_lock_owner(linkset, chanpos);
832  if (p->owner) {
835  }
836  sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING);
837  break;
838  case CPG_EVENT_PROGRESS:
839  case CPG_EVENT_INBANDINFO:
840  {
841  ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
842  sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROGRESS);
843  p->progress = 1;
844  sig_ss7_set_dialing(p, 0);
845  sig_ss7_open_media(p);
846  }
847  break;
848  default:
849  ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
850  break;
851  }
852 
853  sig_ss7_unlock_private(p);
854  break;
855  case ISUP_EVENT_RSC:
856  ast_verbose("Resetting CIC %d\n", e->rsc.cic);
857  chanpos = ss7_find_cic_gripe(linkset, e->rsc.cic, e->rsc.opc, "RSC");
858  if (chanpos < 0) {
859  break;
860  }
861  p = linkset->pvts[chanpos];
862  sig_ss7_lock_private(p);
863  sig_ss7_set_inservice(p, 1);
864  sig_ss7_set_remotelyblocked(p, 0);
865  isup_set_call_dpc(e->rsc.call, p->dpc);
866  sig_ss7_lock_owner(linkset, chanpos);
867  p->ss7call = NULL;
868  if (p->owner) {
871  }
872  sig_ss7_unlock_private(p);
873  isup_rlc(ss7, e->rsc.call);
874  break;
875  case ISUP_EVENT_GRS:
876  ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
877  chanpos = ss7_find_cic_gripe(linkset, e->grs.startcic, e->grs.opc, "GRS");
878  if (chanpos < 0) {
879  break;
880  }
881  p = linkset->pvts[chanpos];
882  isup_gra(ss7, e->grs.startcic, e->grs.endcic, e->grs.opc);
883  ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc, NULL, 0);
884  ss7_hangup_cics(linkset, e->grs.startcic, e->grs.endcic, e->grs.opc);
885  break;
886  case ISUP_EVENT_CQM:
887  ast_debug(1, "Got Circuit group query message from CICs %d to %d\n", e->cqm.startcic, e->cqm.endcic);
888  ss7_handle_cqm(linkset, e->cqm.startcic, e->cqm.endcic, e->cqm.opc);
889  break;
890  case ISUP_EVENT_GRA:
891  ast_verbose("Got reset acknowledgement from CIC %d to %d.\n", e->gra.startcic, e->gra.endcic);
892  ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
893  ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc, e->gra.status, 1);
894  break;
895  case ISUP_EVENT_IAM:
896  ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
897  chanpos = ss7_find_cic_gripe(linkset, e->iam.cic, e->iam.opc, "IAM");
898  if (chanpos < 0) {
899  isup_rel(ss7, e->iam.call, -1);
900  break;
901  }
902  p = linkset->pvts[chanpos];
903  sig_ss7_lock_private(p);
904  sig_ss7_lock_owner(linkset, chanpos);
906  /*
907  * Detected glare/dual-seizure
908  *
909  * Always abort both calls since we can't implement the dual
910  * seizure procedures due to our channel assignment architecture
911  * and the fact that we cannot tell libss7 to discard its call
912  * structure to ignore the incoming IAM.
913  */
914  ast_debug(1,
915  "Linkset %d: SS7 IAM glare on CIC/DPC %d/%d. Dropping both calls.\n",
916  linkset->span, e->iam.cic, e->iam.opc);
918  /*
919  * We have not sent our IAM yet and we never will at this point.
920  */
921  p->alreadyhungup = 1;
922  isup_rel(ss7, e->iam.call, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
923  }
925  if (p->owner) {
929  }
930  sig_ss7_unlock_private(p);
931  break;
932  }
933  /*
934  * The channel should not have an owner at this point since we
935  * are in the process of creating an owner for it.
936  */
937  ast_assert(!p->owner);
938 
939  if (!sig_ss7_is_chan_available(p)) {
940  /* Circuit is likely blocked or in alarm. */
941  isup_rel(ss7, e->iam.call, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
942  sig_ss7_unlock_private(p);
943  break;
944  }
945 
946  /* Mark channel as in use so no outgoing call will steal it. */
948  p->ss7call = e->iam.call;
949 
950  isup_set_call_dpc(p->ss7call, p->dpc);
951 
952  if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
953  ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
954  p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
955  } else
956  p->cid_num[0] = 0;
957 
958  /* Set DNID */
959  if (!ast_strlen_zero(e->iam.called_party_num)) {
960  ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset,
961  e->iam.called_party_num, e->iam.called_nai);
962  } else {
963  p->exten[0] = '\0';
964  }
965  sig_ss7_set_dnid(p, p->exten);
966 
967  if (p->immediate) {
968  p->exten[0] = 's';
969  p->exten[1] = '\0';
970  } else if (!ast_strlen_zero(e->iam.called_party_num)) {
971  char *st;
972  ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
973  st = strchr(p->exten, '#');
974  if (st) {
975  *st = '\0';
976  }
977  } else {
978  p->exten[0] = '\0';
979  }
980 
981  p->cid_ani[0] = '\0';
982  if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name)))
983  ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
984  else
985  p->cid_name[0] = '\0';
986 
987  p->cid_ani2 = e->iam.oli_ani2;
988  p->cid_ton = 0;
989  ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
990  ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
991  p->gen_add_type = e->iam.gen_add_type;
992  p->gen_add_nai = e->iam.gen_add_nai;
993  p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
994  p->gen_add_num_plan = e->iam.gen_add_num_plan;
995  ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
996  p->gen_dig_type = e->iam.gen_dig_type;
997  p->gen_dig_scheme = e->iam.gen_dig_scheme;
998  ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
999  ast_copy_string(p->orig_called_num, e->iam.orig_called_num, sizeof(p->orig_called_num));
1000  ast_copy_string(p->redirecting_num, e->iam.redirecting_num, sizeof(p->redirecting_num));
1001  ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
1002  p->calling_party_cat = e->iam.calling_party_cat;
1003 
1004  sig_ss7_set_caller_id(p);
1005 
1006  if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
1007  if (e->iam.cot_check_required) {
1009  sig_ss7_loopback(p, 1);
1010  } else {
1011  ss7_start_call(p, linkset);
1012  }
1013  } else {
1014  ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
1015  p->alreadyhungup = 1;
1016  isup_rel(ss7, e->iam.call, AST_CAUSE_UNALLOCATED);
1017  }
1018  sig_ss7_unlock_private(p);
1019  break;
1020  case ISUP_EVENT_COT:
1021  chanpos = ss7_find_cic_gripe(linkset, e->cot.cic, e->cot.opc, "COT");
1022  if (chanpos < 0) {
1023  isup_rel(ss7, e->cot.call, -1);
1024  break;
1025  }
1026  p = linkset->pvts[chanpos];
1027 
1028  sig_ss7_lock_private(p);
1029  if (p->loopedback) {
1030  sig_ss7_loopback(p, 0);
1031  ss7_start_call(p, linkset);
1032  }
1033  sig_ss7_unlock_private(p);
1034  break;
1035  case ISUP_EVENT_CCR:
1036  ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
1037  chanpos = ss7_find_cic_gripe(linkset, e->ccr.cic, e->ccr.opc, "CCR");
1038  if (chanpos < 0) {
1039  break;
1040  }
1041 
1042  p = linkset->pvts[chanpos];
1043 
1044  sig_ss7_lock_private(p);
1045  sig_ss7_loopback(p, 1);
1046  sig_ss7_unlock_private(p);
1047 
1048  isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
1049  break;
1050  case ISUP_EVENT_CVT:
1051  ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
1052  chanpos = ss7_find_cic_gripe(linkset, e->cvt.cic, e->cvt.opc, "CVT");
1053  if (chanpos < 0) {
1054  break;
1055  }
1056 
1057  p = linkset->pvts[chanpos];
1058 
1059  sig_ss7_lock_private(p);
1060  sig_ss7_loopback(p, 1);
1061  sig_ss7_unlock_private(p);
1062 
1063  isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
1064  break;
1065  case ISUP_EVENT_REL:
1066  chanpos = ss7_find_cic_gripe(linkset, e->rel.cic, e->rel.opc, "REL");
1067  if (chanpos < 0) {
1068  /* Continue hanging up the call anyway. */
1069  isup_rlc(ss7, e->rel.call);
1070  break;
1071  }
1072  p = linkset->pvts[chanpos];
1073  sig_ss7_lock_private(p);
1074  sig_ss7_lock_owner(linkset, chanpos);
1075  if (p->owner) {
1076  p->owner->hangupcause = e->rel.cause;
1079  }
1080 
1081  /* End the loopback if we have one */
1082  sig_ss7_loopback(p, 0);
1083 
1084  isup_rlc(ss7, e->rel.call);
1085  p->ss7call = NULL;
1086 
1087  sig_ss7_unlock_private(p);
1088  break;
1089  case ISUP_EVENT_ACM:
1090  chanpos = ss7_find_cic_gripe(linkset, e->acm.cic, e->acm.opc, "ACM");
1091  if (chanpos < 0) {
1092  isup_rel(ss7, e->acm.call, -1);
1093  break;
1094  }
1095  {
1096  p = linkset->pvts[chanpos];
1097 
1098  ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
1099 
1100  if (e->acm.call_ref_ident > 0) {
1101  p->rlt = 1; /* Setting it but not using it here*/
1102  }
1103 
1104  sig_ss7_lock_private(p);
1105  sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROCEEDING);
1108  }
1109  sig_ss7_set_dialing(p, 0);
1110  /* Send alerting if subscriber is free */
1111  if (e->acm.called_party_status_ind == 1) {
1114  }
1115  sig_ss7_lock_owner(linkset, chanpos);
1116  if (p->owner) {
1119  }
1120  sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING);
1121  }
1122  sig_ss7_unlock_private(p);
1123  }
1124  break;
1125  case ISUP_EVENT_CGB:
1126  chanpos = ss7_find_cic_gripe(linkset, e->cgb.startcic, e->cgb.opc, "CGB");
1127  if (chanpos < 0) {
1128  break;
1129  }
1130  p = linkset->pvts[chanpos];
1131  ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, 1);
1132  isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.opc, e->cgb.status, e->cgb.type);
1133  break;
1134  case ISUP_EVENT_CGU:
1135  chanpos = ss7_find_cic_gripe(linkset, e->cgu.startcic, e->cgu.opc, "CGU");
1136  if (chanpos < 0) {
1137  break;
1138  }
1139  p = linkset->pvts[chanpos];
1140  ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, 0);
1141  isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgu.opc, e->cgu.status, e->cgu.type);
1142  break;
1143  case ISUP_EVENT_UCIC:
1144  chanpos = ss7_find_cic_gripe(linkset, e->ucic.cic, e->ucic.opc, "UCIC");
1145  if (chanpos < 0) {
1146  break;
1147  }
1148  p = linkset->pvts[chanpos];
1149  ast_debug(1, "Unequiped Circuit Id Code on CIC %d\n", e->ucic.cic);
1150  sig_ss7_lock_private(p);
1151  sig_ss7_set_remotelyblocked(p, 1);
1152  sig_ss7_set_inservice(p, 0);
1153  sig_ss7_unlock_private(p);/* doesn't require a SS7 acknowledgement */
1154  break;
1155  case ISUP_EVENT_BLO:
1156  chanpos = ss7_find_cic_gripe(linkset, e->blo.cic, e->blo.opc, "BLO");
1157  if (chanpos < 0) {
1158  break;
1159  }
1160  p = linkset->pvts[chanpos];
1161  ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
1162  sig_ss7_lock_private(p);
1163  sig_ss7_set_remotelyblocked(p, 1);
1164  sig_ss7_unlock_private(p);
1165  isup_bla(linkset->ss7, e->blo.cic, p->dpc);
1166  break;
1167  case ISUP_EVENT_BLA:
1168  chanpos = ss7_find_cic_gripe(linkset, e->bla.cic, e->bla.opc, "BLA");
1169  if (chanpos < 0) {
1170  break;
1171  }
1172  ast_debug(1, "Blocking CIC %d\n", e->bla.cic);
1173  p = linkset->pvts[chanpos];
1174  sig_ss7_lock_private(p);
1175  sig_ss7_set_locallyblocked(p, 1);
1176  sig_ss7_unlock_private(p);
1177  break;
1178  case ISUP_EVENT_UBL:
1179  chanpos = ss7_find_cic_gripe(linkset, e->ubl.cic, e->ubl.opc, "UBL");
1180  if (chanpos < 0) {
1181  break;
1182  }
1183  p = linkset->pvts[chanpos];
1184  ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
1185  sig_ss7_lock_private(p);
1186  sig_ss7_set_remotelyblocked(p, 0);
1187  sig_ss7_unlock_private(p);
1188  isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
1189  break;
1190  case ISUP_EVENT_UBA:
1191  chanpos = ss7_find_cic_gripe(linkset, e->uba.cic, e->uba.opc, "UBA");
1192  if (chanpos < 0) {
1193  break;
1194  }
1195  p = linkset->pvts[chanpos];
1196  ast_debug(1, "Unblocking CIC %d\n", e->uba.cic);
1197  sig_ss7_lock_private(p);
1198  sig_ss7_set_locallyblocked(p, 0);
1199  sig_ss7_unlock_private(p);
1200  break;
1201  case ISUP_EVENT_CON:
1202  case ISUP_EVENT_ANM:
1203  if (e->e == ISUP_EVENT_CON) {
1204  chanpos = ss7_find_cic_gripe(linkset, e->con.cic, e->con.opc, "CON");
1205  if (chanpos < 0) {
1206  isup_rel(ss7, e->con.call, -1);
1207  break;
1208  }
1209  } else {
1210  chanpos = ss7_find_cic_gripe(linkset, e->anm.cic, e->anm.opc, "ANM");
1211  if (chanpos < 0) {
1212  isup_rel(ss7, e->anm.call, -1);
1213  break;
1214  }
1215  }
1216 
1217  {
1218  p = linkset->pvts[chanpos];
1219  sig_ss7_lock_private(p);
1222  }
1223  sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_ANSWER);
1224  sig_ss7_set_dialing(p, 0);
1225  sig_ss7_open_media(p);
1226  sig_ss7_set_echocanceller(p, 1);
1227  sig_ss7_unlock_private(p);
1228  }
1229  break;
1230  case ISUP_EVENT_RLC:
1231  /* XXX Call ptr should be passed up from libss7! */
1232  chanpos = ss7_find_cic_gripe(linkset, e->rlc.cic, e->rlc.opc, "RLC");
1233  if (chanpos < 0) {
1234  break;
1235  }
1236  {
1237  p = linkset->pvts[chanpos];
1238  sig_ss7_lock_private(p);
1239  if (p->alreadyhungup) {
1240  if (!p->owner) {
1242  }
1243  p->ss7call = NULL;
1244  }
1245  sig_ss7_unlock_private(p);
1246  }
1247  break;
1248  case ISUP_EVENT_FAA:
1249  /*!
1250  * \todo The handling of the SS7 FAA message is not good and I
1251  * don't know enough to handle it correctly.
1252  */
1253  chanpos = ss7_find_cic_gripe(linkset, e->faa.cic, e->faa.opc, "FAA");
1254  if (chanpos < 0) {
1255  isup_rel(linkset->ss7, e->faa.call, -1);
1256  break;
1257  }
1258  {
1259  /* XXX FAR and FAA used for something dealing with transfers? */
1260  p = linkset->pvts[chanpos];
1261  ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
1262  sig_ss7_lock_private(p);
1263  if (p->alreadyhungup){
1264  if (!p->owner) {
1266  }
1267  /* XXX We seem to be leaking the isup call structure here. */
1268  p->ss7call = NULL;
1269  ast_log(LOG_NOTICE, "Received FAA and we haven't sent FAR. Ignoring.\n");
1270  }
1271  sig_ss7_unlock_private(p);
1272  }
1273  break;
1274  default:
1275  ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
1276  break;
1277  }
1278  }
1279  ast_mutex_unlock(&linkset->lock);
1280  }
1281 
1282  return 0;
1283 }
1284 
1285 static inline void ss7_rel(struct sig_ss7_linkset *ss7)
1286 {
1287  ast_mutex_unlock(&ss7->lock);
1288 }
1289 
1290 static void ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7)
1291 {
1292  /* Grab the lock first */
1293  while (ast_mutex_trylock(&ss7->lock)) {
1294  /* Avoid deadlock */
1295  sig_ss7_unlock_private(pvt);
1296  sched_yield();
1297  sig_ss7_lock_private(pvt);
1298  }
1299  /* Then break the poll */
1300  if (ss7->master != AST_PTHREADT_NULL) {
1301  pthread_kill(ss7->master, SIGURG);
1302  }
1303 }
1304 
1305 /*!
1306  * \brief Notify the SS7 layer that the link is in alarm.
1307  * \since 1.8
1308  *
1309  * \param linkset Controlling linkset for the channel.
1310  * \param which Link index of the signaling channel.
1311  *
1312  * \return Nothing
1313  */
1314 void sig_ss7_link_alarm(struct sig_ss7_linkset *linkset, int which)
1315 {
1316  linkset->linkstate[which] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
1317  linkset->linkstate[which] &= ~LINKSTATE_UP;
1318  ss7_link_alarm(linkset->ss7, linkset->fds[which]);
1319 }
1320 
1321 /*!
1322  * \brief Notify the SS7 layer that the link is no longer in alarm.
1323  * \since 1.8
1324  *
1325  * \param linkset Controlling linkset for the channel.
1326  * \param which Link index of the signaling channel.
1327  *
1328  * \return Nothing
1329  */
1330 void sig_ss7_link_noalarm(struct sig_ss7_linkset *linkset, int which)
1331 {
1332  linkset->linkstate[which] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
1333  linkset->linkstate[which] |= LINKSTATE_STARTING;
1334  ss7_link_noalarm(linkset->ss7, linkset->fds[which]);
1335 }
1336 
1337 /*!
1338  * \brief Setup and add a SS7 link channel.
1339  * \since 1.8
1340  *
1341  * \param linkset Controlling linkset for the channel.
1342  * \param which Link index of the signaling channel.
1343  * \param ss7type Switch type of the linkset
1344  * \param transport Signaling transport of channel.
1345  * \param inalarm Non-zero if the channel is in alarm.
1346  * \param networkindicator User configuration parameter.
1347  * \param pointcode User configuration parameter.
1348  * \param adjpointcode User configuration parameter.
1349  *
1350  * \retval 0 on success.
1351  * \retval -1 on error.
1352  */
1353 int sig_ss7_add_sigchan(struct sig_ss7_linkset *linkset, int which, int ss7type, int transport, int inalarm, int networkindicator, int pointcode, int adjpointcode)
1354 {
1355  if (!linkset->ss7) {
1356  linkset->type = ss7type;
1357  linkset->ss7 = ss7_new(ss7type);
1358  if (!linkset->ss7) {
1359  ast_log(LOG_ERROR, "Can't create new SS7!\n");
1360  return -1;
1361  }
1362  }
1363 
1364  ss7_set_network_ind(linkset->ss7, networkindicator);
1365  ss7_set_pc(linkset->ss7, pointcode);
1366 
1367  if (ss7_add_link(linkset->ss7, transport, linkset->fds[which])) {
1368  ast_log(LOG_WARNING, "Could not add SS7 link!\n");
1369  }
1370 
1371  if (inalarm) {
1372  linkset->linkstate[which] = LINKSTATE_DOWN | LINKSTATE_INALARM;
1373  ss7_link_alarm(linkset->ss7, linkset->fds[which]);
1374  } else {
1375  linkset->linkstate[which] = LINKSTATE_DOWN;
1376  ss7_link_noalarm(linkset->ss7, linkset->fds[which]);
1377  }
1378 
1379  ss7_set_adjpc(linkset->ss7, linkset->fds[which], adjpointcode);
1380 
1381  return 0;
1382 }
1383 
1384 /*!
1385  * \brief Determine if the specified channel is available for an outgoing call.
1386  * \since 1.8
1387  *
1388  * \param p Signaling private structure pointer.
1389  *
1390  * \retval TRUE if the channel is available.
1391  */
1392 int sig_ss7_available(struct sig_ss7_chan *p)
1393 {
1394  int available;
1395 
1396  if (!p->ss7) {
1397  /* Something is wrong here. A SS7 channel without the ss7 pointer? */
1398  return 0;
1399  }
1400 
1401  /* Only have to deal with the linkset lock. */
1402  ast_mutex_lock(&p->ss7->lock);
1403  available = sig_ss7_is_chan_available(p);
1404  if (available) {
1406  }
1407  ast_mutex_unlock(&p->ss7->lock);
1408 
1409  return available;
1410 }
1411 
1412 static unsigned char cid_pres2ss7pres(int cid_pres)
1413 {
1414  return (cid_pres >> 5) & 0x03;
1415 }
1416 
1417 static unsigned char cid_pres2ss7screen(int cid_pres)
1418 {
1419  return cid_pres & 0x03;
1420 }
1421 
1422 /*!
1423  * \brief Dial out using the specified SS7 channel.
1424  * \since 1.8
1425  *
1426  * \param p Signaling private structure pointer.
1427  * \param ast Asterisk channel structure pointer.
1428  * \param rdest Dialstring.
1429  *
1430  * \retval 0 on success.
1431  * \retval -1 on error.
1432  */
1433 int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest)
1434 {
1435  char ss7_called_nai;
1436  int called_nai_strip;
1437  char ss7_calling_nai;
1438  int calling_nai_strip;
1439  const char *charge_str = NULL;
1440  const char *gen_address = NULL;
1441  const char *gen_digits = NULL;
1442  const char *gen_dig_type = NULL;
1443  const char *gen_dig_scheme = NULL;
1444  const char *gen_name = NULL;
1445  const char *jip_digits = NULL;
1446  const char *lspi_ident = NULL;
1447  const char *rlt_flag = NULL;
1448  const char *call_ref_id = NULL;
1449  const char *call_ref_pc = NULL;
1450  const char *send_far = NULL;
1451  char *c;
1452  char *l;
1453  char dest[256];
1454 
1455  ast_copy_string(dest, rdest, sizeof(dest));
1456 
1457  c = strchr(dest, '/');
1458  if (c) {
1459  c++;
1460  } else {
1461  c = "";
1462  }
1463  if (strlen(c) < p->stripmsd) {
1464  ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
1465  return -1;
1466  }
1467 
1468  if (!p->hidecallerid) {
1469  l = ast->connected.id.number.valid ? ast->connected.id.number.str : NULL;
1470  } else {
1471  l = NULL;
1472  }
1473 
1474  ss7_grab(p, p->ss7);
1475 
1477  /* Call collision before sending IAM. Abort call. */
1478  ss7_rel(p->ss7);
1479  return -1;
1480  }
1481 
1482  p->ss7call = isup_new_call(p->ss7->ss7);
1483  if (!p->ss7call) {
1484  ss7_rel(p->ss7);
1485  ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
1486  return -1;
1487  }
1488 
1489  called_nai_strip = 0;
1490  ss7_called_nai = p->ss7->called_nai;
1491  if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
1492  if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
1493  called_nai_strip = strlen(p->ss7->internationalprefix);
1494  ss7_called_nai = SS7_NAI_INTERNATIONAL;
1495  } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
1496  called_nai_strip = strlen(p->ss7->nationalprefix);
1497  ss7_called_nai = SS7_NAI_NATIONAL;
1498  } else {
1499  ss7_called_nai = SS7_NAI_SUBSCRIBER;
1500  }
1501  }
1502  isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
1503 
1504  calling_nai_strip = 0;
1505  ss7_calling_nai = p->ss7->calling_nai;
1506  if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
1507  if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
1508  calling_nai_strip = strlen(p->ss7->internationalprefix);
1509  ss7_calling_nai = SS7_NAI_INTERNATIONAL;
1510  } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
1511  calling_nai_strip = strlen(p->ss7->nationalprefix);
1512  ss7_calling_nai = SS7_NAI_NATIONAL;
1513  } else {
1514  ss7_calling_nai = SS7_NAI_SUBSCRIBER;
1515  }
1516  }
1517  isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
1518  p->use_callingpres ? cid_pres2ss7pres(ast->connected.id.number.presentation) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
1519  p->use_callingpres ? cid_pres2ss7screen(ast->connected.id.number.presentation) : SS7_SCREENING_USER_PROVIDED);
1520 
1521  isup_set_oli(p->ss7call, ast->connected.ani2);
1522  isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
1523 
1524  /* Set the charge number if it is set */
1525  charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
1526  if (charge_str)
1527  isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
1528 
1529  gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
1530  if (gen_address)
1531  isup_set_gen_address(p->ss7call, gen_address, p->gen_add_nai,p->gen_add_pres_ind, p->gen_add_num_plan,p->gen_add_type); /* need to add some types here for NAI,PRES,TYPE */
1532 
1533  gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
1534  gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
1535  gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
1536  if (gen_digits)
1537  isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
1538 
1539  gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
1540  if (gen_name)
1541  isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
1542 
1543  jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
1544  if (jip_digits)
1545  isup_set_jip_digits(p->ss7call, jip_digits);
1546 
1547  lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
1548  if (lspi_ident)
1549  isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
1550 
1551  rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
1552  if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
1553  isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
1554  }
1555 
1556  call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
1557  call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
1558  if (call_ref_id && call_ref_pc) {
1559  isup_set_callref(p->ss7call, atoi(call_ref_id),
1560  call_ref_pc ? atoi(call_ref_pc) : 0);
1561  }
1562 
1563  send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
1564  if ((send_far) && ((strncmp("NO", send_far, strlen(send_far))) != 0 ))
1565  (isup_far(p->ss7->ss7, p->ss7call));
1566 
1568  isup_iam(p->ss7->ss7, p->ss7call);
1569  sig_ss7_set_dialing(p, 1);
1571  ss7_rel(p->ss7);
1572  return 0;
1573 }
1574 
1575 /*!
1576  * \brief SS7 hangup channel.
1577  * \since 1.8
1578  *
1579  * \param p Signaling private structure pointer.
1580  * \param ast Asterisk channel structure pointer.
1581  *
1582  * \retval 0 on success.
1583  * \retval -1 on error.
1584  */
1585 int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
1586 {
1587  int res = 0;
1588 
1589  if (!ast->tech_pvt) {
1590  ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
1591  return 0;
1592  }
1593 
1594  p->owner = NULL;
1595  sig_ss7_set_dialing(p, 0);
1596  sig_ss7_set_outgoing(p, 0);
1597  p->progress = 0;
1598  p->rlt = 0;
1599  p->exten[0] = '\0';
1600  /* Perform low level hangup if no owner left */
1601  ss7_grab(p, p->ss7);
1603  if (p->ss7call) {
1604  if (!p->alreadyhungup) {
1605  const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
1606  int icause = ast->hangupcause ? ast->hangupcause : -1;
1607 
1608  if (cause) {
1609  if (atoi(cause)) {
1610  icause = atoi(cause);
1611  }
1612  }
1613  isup_rel(p->ss7->ss7, p->ss7call, icause);
1614  p->alreadyhungup = 1;
1615  }
1616  }
1617  ss7_rel(p->ss7);
1618 
1619  return res;
1620 }
1621 
1622 /*!
1623  * \brief SS7 answer channel.
1624  * \since 1.8
1625  *
1626  * \param p Signaling private structure pointer.
1627  * \param ast Asterisk channel structure pointer.
1628  *
1629  * \retval 0 on success.
1630  * \retval -1 on error.
1631  */
1632 int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
1633 {
1634  int res;
1635 
1636  ss7_grab(p, p->ss7);
1639  }
1640  sig_ss7_open_media(p);
1641  res = isup_anm(p->ss7->ss7, p->ss7call);
1642  ss7_rel(p->ss7);
1643  return res;
1644 }
1645 
1646 /*!
1647  * \brief Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links.
1648  * \since 1.8
1649  *
1650  * \param oldchan Old channel pointer to replace.
1651  * \param newchan New channel pointer to set.
1652  * \param pchan Signaling private structure pointer.
1653  *
1654  * \return Nothing
1655  */
1656 void sig_ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan)
1657 {
1658  if (pchan->owner == oldchan) {
1659  pchan->owner = newchan;
1660  }
1661 }
1662 
1663 /*!
1664  * \brief SS7 answer channel.
1665  * \since 1.8
1666  *
1667  * \param p Signaling private structure pointer.
1668  * \param chan Asterisk channel structure pointer.
1669  * \param condition AST control frame subtype.
1670  * \param data AST control frame payload contents.
1671  * \param datalen Length of payload contents.
1672  *
1673  * \retval 0 on success.
1674  * \retval -1 on error or indication condition not handled.
1675  */
1676 int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
1677 {
1678  int res = -1;
1679 
1680  switch (condition) {
1681  case AST_CONTROL_BUSY:
1685  res = 0;
1686  break;
1687  }
1688  res = sig_ss7_play_tone(p, SIG_SS7_TONE_BUSY);
1689  break;
1690  case AST_CONTROL_RINGING:
1691  ss7_grab(p, p->ss7);
1694  if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) {
1695  p->rlt = 1;
1696  }
1697 
1698  /* No need to send CPG if call will be RELEASE */
1699  if (p->rlt != 1) {
1700  isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
1701  }
1702  }
1703  ss7_rel(p->ss7);
1704 
1705  res = sig_ss7_play_tone(p, SIG_SS7_TONE_RINGTONE);
1706 
1707  if (chan->_state != AST_STATE_UP && chan->_state != AST_STATE_RING) {
1709  }
1710  break;
1712  ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
1713  ss7_grab(p, p->ss7);
1714  /* This IF sends the FAR for an answered ALEG call */
1715  if (chan->_state == AST_STATE_UP && (p->rlt != 1)){
1716  if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) {
1717  p->rlt = 1;
1718  }
1719  }
1720 
1723  isup_acm(p->ss7->ss7, p->ss7call);
1724  }
1725  ss7_rel(p->ss7);
1726  /* don't continue in ast_indicate */
1727  res = 0;
1728  break;
1729  case AST_CONTROL_PROGRESS:
1730  ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
1731  ss7_grab(p, p->ss7);
1732  if (!p->progress && p->call_level < SIG_SS7_CALL_LEVEL_ALERTING && !p->outgoing) {
1733  p->progress = 1;/* No need to send inband-information progress again. */
1734  isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
1735  ss7_rel(p->ss7);
1736 
1737  /* enable echo canceler here on SS7 calls */
1738  sig_ss7_set_echocanceller(p, 1);
1739  } else {
1740  ss7_rel(p->ss7);
1741  }
1742  /* don't continue in ast_indicate */
1743  res = 0;
1744  break;
1749  res = 0;
1750  break;
1751  }
1752  /* Wait for DTMF digits to complete the dialed number. */
1753  res = 0;
1754  break;
1759  res = 0;
1760  break;
1761  }
1762  res = sig_ss7_play_tone(p, SIG_SS7_TONE_CONGESTION);
1763  break;
1764  case AST_CONTROL_HOLD:
1765  ast_moh_start(chan, data, p->mohinterpret);
1766  break;
1767  case AST_CONTROL_UNHOLD:
1768  ast_moh_stop(chan);
1769  break;
1770  case AST_CONTROL_SRCUPDATE:
1771  res = 0;
1772  break;
1773  case -1:
1774  res = sig_ss7_play_tone(p, -1);
1775  break;
1776  }
1777  return res;
1778 }
1779 
1780 /*!
1781  * \brief SS7 channel request.
1782  * \since 1.8
1783  *
1784  * \param p Signaling private structure pointer.
1785  * \param law Companding law preferred
1786  * \param requestor Asterisk channel requesting a channel to dial (Can be NULL)
1787  * \param transfercapability
1788  *
1789  * \retval ast_channel on success.
1790  * \retval NULL on error.
1791  */
1792 struct ast_channel *sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_channel *requestor, int transfercapability)
1793 {
1794  struct ast_channel *ast;
1795 
1796  /* Companding law is determined by SS7 signaling type. */
1797  if (p->ss7->type == SS7_ITU) {
1798  law = SIG_SS7_ALAW;
1799  } else {
1800  law = SIG_SS7_ULAW;
1801  }
1802 
1803  sig_ss7_set_outgoing(p, 1);
1804  ast = sig_ss7_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability, p->exten, requestor);
1805  if (!ast) {
1806  sig_ss7_set_outgoing(p, 0);
1807 
1808  /* Release the allocated channel. Only have to deal with the linkset lock. */
1809  ast_mutex_lock(&p->ss7->lock);
1811  ast_mutex_unlock(&p->ss7->lock);
1812  }
1813  return ast;
1814 }
1815 
1816 /*!
1817  * \brief Delete the sig_ss7 private channel structure.
1818  * \since 1.8
1819  *
1820  * \param doomed sig_ss7 private channel structure to delete.
1821  *
1822  * \return Nothing
1823  */
1824 void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
1825 {
1826  ast_free(doomed);
1827 }
1828 
1829 #define SIG_SS7_SC_HEADER "%-4s %4s %-4s %-3s %-3s %-10s %-4s %s\n"
1830 #define SIG_SS7_SC_LINE "%4d %4d %-4s %-3s %-3s %-10s %-4s %s"
1832 {
1833  ast_cli(fd, SIG_SS7_SC_HEADER, "link", "", "Chan", "Lcl", "Rem", "Call", "SS7", "Channel");
1834  ast_cli(fd, SIG_SS7_SC_HEADER, "set", "Chan", "Idle", "Blk", "Blk", "Level", "Call", "Name");
1835 }
1836 
1837 void sig_ss7_cli_show_channels(int fd, struct sig_ss7_linkset *linkset)
1838 {
1839  char line[256];
1840  int idx;
1841  struct sig_ss7_chan *pvt;
1842 
1843  ast_mutex_lock(&linkset->lock);
1844  for (idx = 0; idx < linkset->numchans; ++idx) {
1845  if (!linkset->pvts[idx]) {
1846  continue;
1847  }
1848  pvt = linkset->pvts[idx];
1849  sig_ss7_lock_private(pvt);
1850  sig_ss7_lock_owner(linkset, idx);
1851 
1852  snprintf(line, sizeof(line), SIG_SS7_SC_LINE,
1853  linkset->span,
1854  pvt->channel,
1855  sig_ss7_is_chan_available(pvt) ? "Yes" : "No",
1856  pvt->locallyblocked ? "Yes" : "No",
1857  pvt->remotelyblocked ? "Yes" : "No",
1858  sig_ss7_call_level2str(pvt->call_level),
1859  pvt->ss7call ? "Yes" : "No",
1860  pvt->owner ? pvt->owner->name : "");
1861 
1862  if (pvt->owner) {
1863  ast_channel_unlock(pvt->owner);
1864  }
1865  sig_ss7_unlock_private(pvt);
1866 
1867  ast_mutex_unlock(&linkset->lock);
1868  ast_cli(fd, "%s\n", line);
1869  ast_mutex_lock(&linkset->lock);
1870  }
1871  ast_mutex_unlock(&linkset->lock);
1872 }
1873 
1874 /*!
1875  * \brief Create a new sig_ss7 private channel structure.
1876  * \since 1.8
1877  *
1878  * \param pvt_data Upper layer private data structure.
1879  * \param callback Callbacks to the upper layer.
1880  * \param ss7 Controlling linkset for the channel.
1881  *
1882  * \retval sig_ss7_chan on success.
1883  * \retval NULL on error.
1884  */
1885 struct sig_ss7_chan *sig_ss7_chan_new(void *pvt_data, struct sig_ss7_callback *callback, struct sig_ss7_linkset *ss7)
1886 {
1887  struct sig_ss7_chan *pvt;
1888 
1889  pvt = ast_calloc(1, sizeof(*pvt));
1890  if (!pvt) {
1891  return pvt;
1892  }
1893 
1894  pvt->calls = callback;
1895  pvt->chan_pvt = pvt_data;
1896  pvt->ss7 = ss7;
1897 
1898  return pvt;
1899 }
1900 
1901 /*!
1902  * \brief Initialize the SS7 linkset control.
1903  * \since 1.8
1904  *
1905  * \param ss7 SS7 linkset control structure.
1906  *
1907  * \return Nothing
1908  */
1909 void sig_ss7_init_linkset(struct sig_ss7_linkset *ss7)
1910 {
1911  int idx;
1912 
1913  memset(ss7, 0, sizeof(*ss7));
1914 
1915  ast_mutex_init(&ss7->lock);
1916 
1917  ss7->master = AST_PTHREADT_NULL;
1918  for (idx = 0; idx < ARRAY_LEN(ss7->fds); ++idx) {
1919  ss7->fds[idx] = -1;
1920  }
1921 }
1922 
1923 /* ------------------------------------------------------------------- */
1924 
1925 #endif /* defined(HAVE_SS7) */
1926 /* end sig_ss7.c */
unsigned char gen_add_pres_ind
Definition: sig_ss7.h:216
union ast_frame_subclass subclass
Definition: frame.h:146
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
#define ast_channel_lock(chan)
Definition: channel.h:2466
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
Main Channel structure associated with a channel.
Definition: channel.h:742
void(*const set_callerid)(void *pvt, const struct ast_party_caller *caller)
Definition: sig_ss7.h:147
Music on hold handling.
char calling_nai
Definition: sig_ss7.h:269
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
struct sig_ss7_callback * calls
Definition: sig_ss7.h:251
General Asterisk channel transcoding definitions.
int cid_ton
Definition: sig_ss7.h:199
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
unsigned int call_ref_pc
Definition: sig_ss7.h:228
unsigned int alreadyhungup
TRUE if the call has already gone/hungup.
Definition: sig_ss7.h:241
enum sig_ss7_call_level call_level
Definition: sig_ss7.h:164
Asterisk main include file. File version handling, generic pbx functions.
int sig_ss7_available(struct sig_ss7_chan *p)
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
unsigned char gen_dig_type
Definition: sig_ss7.h:218
unsigned int outgoing
Definition: sig_ss7.h:237
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:245
unsigned int dpc
Definition: sig_ss7.h:168
int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
unsigned char gen_add_num_plan
Definition: sig_ss7.h:214
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
void sig_ss7_cli_show_channels(int fd, struct sig_ss7_linkset *linkset)
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: sig_ss7.h:179
void * tech_pvt
Definition: channel.h:744
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:97
sig_ss7_call_level
Definition: sig_ss7.h:88
char unknownprefix[20]
Definition: sig_ss7.h:273
void(*const unlock_private)(void *pvt)
Definition: sig_ss7.h:129
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:485
#define LOG_WARNING
Definition: logger.h:144
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
enum sig_ss7_linkset::@121 state
int callingpres
Definition: sig_ss7.h:200
int channel
Definition: sig_ss7.h:166
unsigned int loopedback
Definition: sig_ss7.h:245
struct sig_ss7_linkset * ss7
Definition: sig_ss7.h:157
char gen_add_number[50]
Definition: sig_ss7.h:209
Interface header for SS7 signaling module.
unsigned int inalarm
Definition: sig_ss7.h:235
pthread_t master
Definition: sig_ss7.h:249
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int ani2
Automatic Number Identification 2 (Info Digits)
Definition: channel.h:417
#define ast_assert(a)
Definition: utils.h:738
#define ast_mutex_lock(a)
Definition: lock.h:155
unsigned short transfercapability
Definition: channel.h:863
char redirecting_num[50]
Definition: sig_ss7.h:212
unsigned char gen_dig_scheme
Definition: sig_ss7.h:219
const char * data
Definition: channel.h:755
char exten[AST_MAX_EXTENSION]
Definition: sig_ss7.h:205
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition: causes.h:119
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int(*const set_echocanceller)(void *pvt, int enable)
Definition: sig_ss7.h:133
#define AST_CAUSE_INVALID_NUMBER_FORMAT
Definition: causes.h:115
char lspi_ident[50]
Definition: sig_ss7.h:226
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
void(*const open_media)(void *pvt)
Definition: sig_ss7.h:151
int(*const play_tone)(void *pvt, enum sig_ss7_tone tone)
Definition: sig_ss7.h:137
#define SS7_NAI_DYNAMIC
Definition: sig_ss7.h:66
#define ast_verb(level,...)
Definition: logger.h:243
struct sig_ss7_chan * sig_ss7_chan_new(void *pvt_data, struct sig_ss7_callback *callback, struct sig_ss7_linkset *ss7)
char cid_subaddr[AST_MAX_EXTENSION]
Definition: sig_ss7.h:202
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
char cid_name[AST_MAX_EXTENSION]
Definition: sig_ss7.h:203
struct sig_ss7_callback * calls
Definition: sig_ss7.h:155
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls...
Definition: sig_ss7.h:186
struct ss7 * ss7
Definition: sig_ss7.h:252
Number structure.
Definition: app_followme.c:109
unsigned int remotelyblocked
TRUE if the channel is remotely blocked. Set by user and link.
Definition: sig_ss7.h:192
#define LINKSTATE_INALARM
Definition: sig_ss7.h:61
ast_mutex_t lock
Definition: sig_ss7.h:250
char context[AST_MAX_CONTEXT]
Definition: sig_ss7.h:194
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: sig_ss7.h:181
unsigned int progress
TRUE if the call has seen inband-information progress through the network.
Definition: sig_ss7.h:239
void(*const set_dialing)(void *pvt, int is_dialing)
Definition: sig_ss7.h:141
#define LINKSTATE_STARTING
Definition: sig_ss7.h:62
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: sig_ss7.h:175
#define ast_mutex_trylock(a)
Definition: lock.h:157
#define LINKSTATE_UP
Definition: sig_ss7.h:63
#define AST_PTHREADT_NULL
Definition: lock.h:65
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
void(*const queue_control)(void *pvt, int subclass)
Definition: sig_ss7.h:150
void sig_ss7_link_noalarm(struct sig_ss7_linkset *linkset, int which)
#define LINKSET_FLAG_EXPLICITACM
Definition: sig_ss7.h:68
void(*const set_alarm)(void *pvt, int in_alarm)
Definition: sig_ss7.h:140
void sig_ss7_cli_show_channels_header(int fd)
Caller Party information.
Definition: channel.h:368
char generic_name[50]
Definition: sig_ss7.h:213
void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
void(*const set_loopback)(void *pvt, int enable)
Definition: sig_ss7.h:134
void * chan_pvt
Definition: sig_ss7.h:156
char mohinterpret[MAX_MUSICCLASS]
Definition: sig_ss7.h:195
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
void(*const set_locallyblocked)(void *pvt, int is_blocked)
Definition: sig_ss7.h:145
char subscriberprefix[20]
Definition: sig_ss7.h:272
int cid_ani2
Definition: sig_ss7.h:198
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1558
char charge_number[50]
Definition: sig_ss7.h:208
void(*const set_digital)(void *pvt, int is_digital)
Definition: sig_ss7.h:142
struct sig_ss7_chan * pvts[SIG_SS7_MAX_CHANNELS]
Definition: sig_ss7.h:253
#define LOG_ERROR
Definition: logger.h:155
int fds[SIG_SS7_NUM_DCHANS]
Definition: sig_ss7.h:254
char orig_called_num[50]
Definition: sig_ss7.h:211
void(*const handle_link_exception)(struct sig_ss7_linkset *linkset, int which)
Definition: sig_ss7.h:139
#define LINKSTATE_DOWN
Definition: sig_ss7.h:64
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
enum ast_channel_state _state
Definition: channel.h:839
void(*const set_remotelyblocked)(void *pvt, int is_blocked)
Definition: sig_ss7.h:146
const ast_string_field name
Definition: channel.h:787
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
unsigned int rlt
XXX BOOLEAN Purpose???
Definition: sig_ss7.h:243
sig_ss7_tone
Definition: sig_ss7.h:71
unsigned char gen_add_type
Definition: sig_ss7.h:217
int ast_softhangup_nolock(struct ast_channel *chan, int reason)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2733
int linkstate[SIG_SS7_NUM_DCHANS]
Definition: sig_ss7.h:256
void sig_ss7_init_linkset(struct sig_ss7_linkset *ss7)
#define ast_channel_unlock(chan)
Definition: channel.h:2467
int errno
unsigned int call_ref_ident
Definition: sig_ss7.h:227
#define ast_free(a)
Definition: astmm.h:97
char called_nai
Definition: sig_ss7.h:268
static struct ast_format f[]
Definition: format_g726.c:181
void(*const set_dnid)(void *pvt, const char *dnid)
Definition: sig_ss7.h:148
struct ast_channel * sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_channel *requestor, int transfercapability)
#define SIG_SS7_DEBUG_DEFAULT
Definition: sig_ss7.h:51
char jip_number[50]
Definition: sig_ss7.h:220
void sig_ss7_link_alarm(struct sig_ss7_linkset *linkset, int which)
char cid_num[AST_MAX_EXTENSION]
Definition: sig_ss7.h:201
char nationalprefix[10]
Definition: sig_ss7.h:271
int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, char *rdest)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
Definition: chan_dahdi.c:13288
unsigned int locallyblocked
TRUE if the channel is locally blocked. Set by user and link.
Definition: sig_ss7.h:190
unsigned int immediate
Definition: sig_ss7.h:187
void(*const set_inservice)(void *pvt, int is_inservice)
Definition: sig_ss7.h:144
void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
Standard Command Line Interface.
int sig_ss7_add_sigchan(struct sig_ss7_linkset *linkset, int which, int ss7type, int transport, int inalarm, int networkindicator, int pointcode, int adjpointcode)
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char gen_dig_number[50]
Definition: sig_ss7.h:210
#define AST_CAUSE_USER_BUSY
Definition: causes.h:106
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
char * ast_transfercapability2str(int transfercapability) attribute_const
Gives the string form of a given transfer capability.
Definition: channel.c:1041
Data structure associated with a single frame of data.
Definition: frame.h:142
int hangupcause
Definition: channel.h:849
Internal Asterisk hangup causes.
struct ast_channel * owner
Definition: sig_ss7.h:158
char internationalprefix[10]
Definition: sig_ss7.h:270
struct isup_call * ss7call
Opaque libss7 call control structure.
Definition: sig_ss7.h:161
int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
struct timeval tv
char cid_ani[AST_MAX_EXTENSION]
Definition: sig_ss7.h:204
struct ast_channel *(*const new_ast_channel)(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_channel *requestor)
Definition: sig_ss7.h:136
#define ast_mutex_init(pmutex)
Definition: lock.h:152
#define ast_channel_trylock(chan)
Definition: channel.h:2468
void sig_ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan)
unsigned char gen_add_nai
Definition: sig_ss7.h:215
void ast_party_caller_init(struct ast_party_caller *init)
Initialize the given caller structure.
Definition: channel.c:2269
void(*const lock_private)(void *pvt)
Definition: sig_ss7.h:131
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
sig_ss7_law
Definition: sig_ss7.h:81
void(*const set_outgoing)(void *pvt, int is_outgoing)
Definition: sig_ss7.h:143
#define AST_CAUSE_CONGESTION
Definition: causes.h:152
void * ss7_linkset(void *data)
#define AST_TRANS_CAP_DIGITAL
Definition: transcap.h:35
jack_status_t status
Definition: app_jack.c:143
unsigned char calling_party_cat
Definition: sig_ss7.h:229
#define ast_mutex_unlock(a)
Definition: lock.h:156
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292