Asterisk - The Open Source Telephony Project  21.4.1
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/callerid.h"
45 #include "asterisk/transcap.h"
46 #include "asterisk/stasis_channels.h"
47 
48 #include "sig_ss7.h"
49 #if !defined(LIBSS7_ABI_COMPATIBILITY)
50 #error "Upgrade your libss7"
51 #elif LIBSS7_ABI_COMPATIBILITY != 2
52 #error "Your installed libss7 is not compatible"
53 #endif
54 
55 /* ------------------------------------------------------------------- */
56 
57 static const char *sig_ss7_call_level2str(enum sig_ss7_call_level level)
58 {
59  switch (level) {
61  return "Idle";
63  return "Allocated";
65  return "Continuity";
67  return "Setup";
69  return "Proceeding";
71  return "Alerting";
73  return "Connect";
74  }
75  return "Unknown";
76 }
77 
78 static void sig_ss7_unlock_private(struct sig_ss7_chan *p)
79 {
80  if (sig_ss7_callbacks.unlock_private) {
81  sig_ss7_callbacks.unlock_private(p->chan_pvt);
82  }
83 }
84 
85 static void sig_ss7_lock_private(struct sig_ss7_chan *p)
86 {
87  if (sig_ss7_callbacks.lock_private) {
88  sig_ss7_callbacks.lock_private(p->chan_pvt);
89  }
90 }
91 
92 static void sig_ss7_deadlock_avoidance_private(struct sig_ss7_chan *p)
93 {
94  if (sig_ss7_callbacks.deadlock_avoidance_private) {
95  sig_ss7_callbacks.deadlock_avoidance_private(p->chan_pvt);
96  } else {
97  /* Fallback to the old way if callback not present. */
98  sig_ss7_unlock_private(p);
99  sched_yield();
100  sig_ss7_lock_private(p);
101  }
102 }
103 
104 void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
105 {
106  p->inalarm = in_alarm;
107  if (sig_ss7_callbacks.set_alarm) {
108  sig_ss7_callbacks.set_alarm(p->chan_pvt, in_alarm);
109  }
110 }
111 
112 static void sig_ss7_set_dialing(struct sig_ss7_chan *p, int is_dialing)
113 {
114  if (sig_ss7_callbacks.set_dialing) {
115  sig_ss7_callbacks.set_dialing(p->chan_pvt, is_dialing);
116  }
117 }
118 
119 static void sig_ss7_set_digital(struct sig_ss7_chan *p, int is_digital)
120 {
121  if (sig_ss7_callbacks.set_digital) {
122  sig_ss7_callbacks.set_digital(p->chan_pvt, is_digital);
123  }
124 }
125 
126 static void sig_ss7_set_outgoing(struct sig_ss7_chan *p, int is_outgoing)
127 {
128  p->outgoing = is_outgoing;
129  if (sig_ss7_callbacks.set_outgoing) {
130  sig_ss7_callbacks.set_outgoing(p->chan_pvt, is_outgoing);
131  }
132 }
133 
134 static void sig_ss7_set_inservice(struct sig_ss7_chan *p, int is_inservice)
135 {
136  p->inservice = is_inservice;
137  if (sig_ss7_callbacks.set_inservice) {
138  sig_ss7_callbacks.set_inservice(p->chan_pvt, is_inservice);
139  }
140 }
141 
142 static void sig_ss7_set_locallyblocked(struct sig_ss7_chan *p, int is_blocked, int type)
143 {
144  if (is_blocked) {
145  p->locallyblocked |= type;
146  } else {
147  p->locallyblocked &= ~type;
148  }
149 
150  if (sig_ss7_callbacks.set_locallyblocked) {
151  sig_ss7_callbacks.set_locallyblocked(p->chan_pvt, p->locallyblocked);
152  }
153 }
154 
155 static void sig_ss7_set_remotelyblocked(struct sig_ss7_chan *p, int is_blocked, int type)
156 {
157  if (is_blocked) {
158  p->remotelyblocked |= type;
159  } else {
160  p->remotelyblocked &= ~type;
161  }
162 
163  if (sig_ss7_callbacks.set_remotelyblocked) {
164  sig_ss7_callbacks.set_remotelyblocked(p->chan_pvt, p->remotelyblocked);
165  }
166 }
167 
168 /*!
169  * \internal
170  * \brief Open the SS7 channel media path.
171  * \since 1.8.12
172  *
173  * \param p Channel private control structure.
174  */
175 static void sig_ss7_open_media(struct sig_ss7_chan *p)
176 {
177  if (sig_ss7_callbacks.open_media) {
178  sig_ss7_callbacks.open_media(p->chan_pvt);
179  }
180 }
181 
182 /*!
183  * \internal
184  * \brief Set the caller id information in the parent module.
185  * \since 1.8
186  *
187  * \param p sig_ss7 channel structure.
188  */
189 static void sig_ss7_set_caller_id(struct sig_ss7_chan *p)
190 {
191  struct ast_party_caller caller;
192 
193  if (sig_ss7_callbacks.set_callerid) {
194  ast_party_caller_init(&caller);
195 
196  caller.id.name.str = p->cid_name;
197  caller.id.name.presentation = p->callingpres;
198  caller.id.name.valid = 1;
199 
200  caller.id.number.str = p->cid_num;
201  caller.id.number.plan = p->cid_ton;
202  caller.id.number.presentation = p->callingpres;
203  caller.id.number.valid = 1;
204 
205  if (!ast_strlen_zero(p->cid_subaddr)) {
206  caller.id.subaddress.valid = 1;
207  //caller.id.subaddress.type = 0;/* nsap */
208  //caller.id.subaddress.odd_even_indicator = 0;
209  caller.id.subaddress.str = p->cid_subaddr;
210  }
211 
212  caller.ani.number.str = p->cid_ani;
213  //caller.ani.number.plan = p->xxx;
214  //caller.ani.number.presentation = p->xxx;
215  caller.ani.number.valid = 1;
216 
217  caller.ani2 = p->cid_ani2;
218  sig_ss7_callbacks.set_callerid(p->chan_pvt, &caller);
219  }
220 }
221 
222 /*!
223  * \internal
224  * \brief Set the Dialed Number Identifier.
225  * \since 1.8
226  *
227  * \param p sig_ss7 channel structure.
228  * \param dnid Dialed Number Identifier string.
229  */
230 static void sig_ss7_set_dnid(struct sig_ss7_chan *p, const char *dnid)
231 {
232  if (sig_ss7_callbacks.set_dnid) {
233  sig_ss7_callbacks.set_dnid(p->chan_pvt, dnid);
234  }
235 }
236 
237 static int sig_ss7_play_tone(struct sig_ss7_chan *p, enum sig_ss7_tone tone)
238 {
239  int res;
240 
241  if (sig_ss7_callbacks.play_tone) {
242  res = sig_ss7_callbacks.play_tone(p->chan_pvt, tone);
243  } else {
244  res = -1;
245  }
246  return res;
247 }
248 
249 static int sig_ss7_set_echocanceller(struct sig_ss7_chan *p, int enable)
250 {
251  if (sig_ss7_callbacks.set_echocanceller) {
252  return sig_ss7_callbacks.set_echocanceller(p->chan_pvt, enable);
253  }
254  return -1;
255 }
256 
257 static void sig_ss7_loopback(struct sig_ss7_chan *p, int enable)
258 {
259  if (p->loopedback != enable) {
260  p->loopedback = enable;
261  if (sig_ss7_callbacks.set_loopback) {
262  sig_ss7_callbacks.set_loopback(p->chan_pvt, enable);
263  }
264  }
265 }
266 
267 static struct ast_channel *sig_ss7_new_ast_channel(struct sig_ss7_chan *p, int state,
268  int ulaw, int transfercapability, char *exten,
269  const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
270 {
271  struct ast_channel *ast;
272 
273  if (sig_ss7_callbacks.new_ast_channel) {
274  ast = sig_ss7_callbacks.new_ast_channel(p->chan_pvt, state, ulaw, exten,
275  assignedids, requestor);
276  } else {
277  return NULL;
278  }
279  if (!ast) {
280  return NULL;
281  }
282 
283  if (!p->owner) {
284  p->owner = ast;
285  }
286 
287  if (p->outgoing) {
288  p->do_hangup = SS7_HANGUP_FREE_CALL;
289  } else {
290  p->do_hangup = SS7_HANGUP_SEND_REL;
291  }
292 
293  ast_channel_transfercapability_set(ast, transfercapability);
294  pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY",
295  ast_transfercapability2str(transfercapability));
296  if (transfercapability & AST_TRANS_CAP_DIGITAL) {
297  sig_ss7_set_digital(p, 1);
298  }
299 
300  return ast;
301 }
302 
303 static void sig_ss7_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
304 {
305  if (sig_ss7_callbacks.handle_link_exception) {
306  sig_ss7_callbacks.handle_link_exception(linkset, which);
307  }
308 }
309 
310 static struct sig_ss7_linkset *sig_ss7_find_linkset(struct ss7 *ss7)
311 {
312  if (sig_ss7_callbacks.find_linkset) {
313  return sig_ss7_callbacks.find_linkset(ss7);
314  }
315  return NULL;
316 }
317 
318 /*!
319  * \internal
320  * \brief Determine if a private channel structure is available.
321  *
322  * \param pvt Channel to determine if available.
323  *
324  * \retval TRUE if the channel is available.
325  */
326 static int sig_ss7_is_chan_available(struct sig_ss7_chan *pvt)
327 {
328  if (pvt->inservice && !pvt->inalarm && !pvt->owner && !pvt->ss7call
330  && !pvt->locallyblocked && !pvt->remotelyblocked) {
331  return 1;
332  }
333  return 0;
334 }
335 
336 /*!
337  * \internal
338  * \brief Obtain the sig_ss7 owner channel lock if the owner exists.
339  * \since 1.8
340  *
341  * \param ss7 SS7 linkset control structure.
342  * \param chanpos Channel position in the span.
343  *
344  * \note Assumes the ss7->lock is already obtained.
345  * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
346  */
347 static void sig_ss7_lock_owner(struct sig_ss7_linkset *ss7, int chanpos)
348 {
349  for (;;) {
350  if (!ss7->pvts[chanpos]->owner) {
351  /* There is no owner lock to get. */
352  break;
353  }
354  if (!ast_channel_trylock(ss7->pvts[chanpos]->owner)) {
355  /* We got the lock */
356  break;
357  }
358 
359  /* Avoid deadlock */
360  sig_ss7_unlock_private(ss7->pvts[chanpos]);
361  DEADLOCK_AVOIDANCE(&ss7->lock);
362  sig_ss7_lock_private(ss7->pvts[chanpos]);
363  }
364 }
365 
366 /*!
367  * \internal
368  * \brief Queue the given frame onto the owner channel.
369  * \since 1.8
370  *
371  * \param ss7 SS7 linkset control structure.
372  * \param chanpos Channel position in the span.
373  * \param frame Frame to queue onto the owner channel.
374  *
375  * \note Assumes the ss7->lock is already obtained.
376  * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
377  */
378 static void sig_ss7_queue_frame(struct sig_ss7_linkset *ss7, int chanpos, struct ast_frame *frame)
379 {
380  sig_ss7_lock_owner(ss7, chanpos);
381  if (ss7->pvts[chanpos]->owner) {
382  ast_queue_frame(ss7->pvts[chanpos]->owner, frame);
383  ast_channel_unlock(ss7->pvts[chanpos]->owner);
384  }
385 }
386 
387 /*!
388  * \internal
389  * \brief Queue a control frame of the specified subclass onto the owner channel.
390  * \since 1.8
391  *
392  * \param ss7 SS7 linkset control structure.
393  * \param chanpos Channel position in the span.
394  * \param subclass Control frame subclass to queue onto the owner channel.
395  *
396  * \note Assumes the ss7->lock is already obtained.
397  * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
398  */
399 static void sig_ss7_queue_control(struct sig_ss7_linkset *ss7, int chanpos, int subclass)
400 {
401  struct ast_frame f = {AST_FRAME_CONTROL, };
402  struct sig_ss7_chan *p = ss7->pvts[chanpos];
403 
404  if (sig_ss7_callbacks.queue_control) {
405  sig_ss7_callbacks.queue_control(p->chan_pvt, subclass);
406  }
407 
408  f.subclass.integer = subclass;
409  sig_ss7_queue_frame(ss7, chanpos, &f);
410 }
411 
412 /*!
413  * \internal
414  * \brief Queue a PVT_CAUSE_CODE frame onto the owner channel.
415  * \since 11.0
416  *
417  * \param owner Owner channel of the pvt.
418  * \param cause String describing the cause to be placed into the frame.
419  * \param ast_cause
420  *
421  * \note Assumes the linkset->lock is already obtained.
422  * \note Assumes the sig_ss7_lock_private(linkset->pvts[chanpos]) is already obtained.
423  * \note Assumes linkset->pvts[chanpos]->owner is non-NULL and its lock is already obtained.
424  */
425 static void ss7_queue_pvt_cause_data(struct ast_channel *owner, const char *cause, int ast_cause)
426 {
427  struct ast_control_pvt_cause_code *cause_code;
428  int datalen = sizeof(*cause_code) + strlen(cause);
429 
430  cause_code = ast_alloca(datalen);
431  memset(cause_code, 0, datalen);
432  cause_code->ast_cause = ast_cause;
433  ast_copy_string(cause_code->chan_name, ast_channel_name(owner), AST_CHANNEL_NAME);
434  ast_copy_string(cause_code->code, cause, datalen + 1 - sizeof(*cause_code));
435  ast_queue_control_data(owner, AST_CONTROL_PVT_CAUSE_CODE, cause_code, datalen);
436  ast_channel_hangupcause_hash_set(owner, cause_code, datalen);
437 }
438 
439 
440 /*!
441  * \brief Find the channel position by CIC/DPC.
442  *
443  * \param linkset SS7 linkset control structure.
444  * \param cic Circuit Identification Code
445  * \param dpc Destination Point Code
446  *
447  * \return chanpos on success.
448  * \retval -1 on error.
449  */
450 int sig_ss7_find_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
451 {
452  int i;
453  int winner = -1;
454  for (i = 0; i < linkset->numchans; i++) {
455  if (linkset->pvts[i] && (linkset->pvts[i]->dpc == dpc && linkset->pvts[i]->cic == cic)) {
456  winner = i;
457  break;
458  }
459  }
460  return winner;
461 }
462 
463 /*!
464  * \internal
465  * \brief Find the channel position by CIC/DPC and gripe if not found.
466  *
467  * \param linkset SS7 linkset control structure.
468  * \param cic Circuit Identification Code
469  * \param dpc Destination Point Code
470  * \param msg_name Message type name that failed.
471  *
472  * \return chanpos on success.
473  * \retval -1 on error.
474  */
475 static int ss7_find_cic_gripe(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc, const char *msg_name)
476 {
477  int chanpos;
478 
479  chanpos = sig_ss7_find_cic(linkset, cic, dpc);
480  if (chanpos < 0) {
481  ast_log(LOG_WARNING, "Linkset %d: SS7 %s requested on unconfigured CIC/DPC %d/%d.\n",
482  linkset->span, msg_name, cic, dpc);
483  return -1;
484  }
485  return chanpos;
486 }
487 
488 static struct sig_ss7_chan *ss7_find_pvt(struct ss7 *ss7, int cic, unsigned int dpc)
489 {
490  int chanpos;
491  struct sig_ss7_linkset *winner;
492 
493  winner = sig_ss7_find_linkset(ss7);
494  if (winner && (chanpos = sig_ss7_find_cic(winner, cic, dpc)) > -1) {
495  return winner->pvts[chanpos];
496  }
497  return NULL;
498 }
499 
500 int sig_ss7_cb_hangup(struct ss7 *ss7, int cic, unsigned int dpc, int cause, int do_hangup)
501 {
502  struct sig_ss7_chan *p;
503  int res;
504 
505  if (!(p = ss7_find_pvt(ss7, cic, dpc))) {
506  return SS7_CIC_NOT_EXISTS;
507  }
508 
509  sig_ss7_lock_private(p);
510  if (p->owner) {
511  ast_channel_hangupcause_set(p->owner, cause);
512  ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
513  p->do_hangup = do_hangup;
514  res = SS7_CIC_USED;
515  } else {
516  res = SS7_CIC_IDLE;
517  }
518  sig_ss7_unlock_private(p);
519 
520  return res;
521 }
522 
523 void sig_ss7_cb_call_null(struct ss7 *ss7, struct isup_call *call, int lock)
524 {
525  int i;
526  struct sig_ss7_linkset *winner;
527 
528  winner = sig_ss7_find_linkset(ss7);
529  if (!winner) {
530  return;
531  }
532  for (i = 0; i < winner->numchans; i++) {
533  if (winner->pvts[i] && (winner->pvts[i]->ss7call == call)) {
534  if (lock) {
535  sig_ss7_lock_private(winner->pvts[i]);
536  }
537  winner->pvts[i]->ss7call = NULL;
538  if (winner->pvts[i]->owner) {
539  ast_channel_hangupcause_set(winner->pvts[i]->owner, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
540  ast_channel_softhangup_internal_flag_add(winner->pvts[i]->owner, AST_SOFTHANGUP_DEV);
541  }
542  if (lock) {
543  sig_ss7_unlock_private(winner->pvts[i]);
544  }
545  ast_log(LOG_WARNING, "libss7 asked set ss7 call to NULL on CIC %d DPC %d\n", winner->pvts[i]->cic, winner->pvts[i]->dpc);
546  }
547  }
548 }
549 
550 void sig_ss7_cb_notinservice(struct ss7 *ss7, int cic, unsigned int dpc)
551 {
552  struct sig_ss7_chan *p;
553 
554  if (!(p = ss7_find_pvt(ss7, cic, dpc))) {
555  return;
556  }
557 
558  sig_ss7_lock_private(p);
559  sig_ss7_set_inservice(p, 0);
560  sig_ss7_unlock_private(p);
561 }
562 
563 /*!
564  * \internal
565  * \brief Check if CICs in a range belong to the linkset for a given DPC.
566  * \since 11.0
567  *
568  * \param linkset SS7 linkset control structure.
569  * \param startcic Circuit Identification Code to start from
570  * \param endcic Circuit Identification Code to search up-to
571  * \param dpc Destination Point Code
572  * \param state Array containing the status of the search
573  */
574 static void ss7_check_range(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc, unsigned char *state)
575 {
576  int cic;
577 
578  for (cic = startcic; cic <= endcic; cic++) {
579  if (state[cic - startcic] && sig_ss7_find_cic(linkset, cic, dpc) == -1) {
580  state[cic - startcic] = 0;
581  }
582  }
583 }
584 
585 static int ss7_match_range(struct sig_ss7_chan *pvt, int startcic, int endcic, unsigned int dpc)
586 {
587  if (pvt && pvt->dpc == dpc && pvt->cic >= startcic && pvt->cic <= endcic) {
588  return 1;
589  }
590 
591  return 0;
592 }
593 
594 /*!
595  * \internal
596  * \brief Check if a range is defined for the given DPC.
597  * \since 11.0
598  *
599  * \param linkset SS7 linkset control structure.
600  * \param startcic Start CIC of the range to clear.
601  * \param endcic End CIC of the range to clear.
602  * \param dpc Destination Point Code.
603  *
604  * \note Assumes the linkset->lock is already obtained.
605  *
606  * \retval TRUE if all CICs in the range are present
607  */
608 int sig_ss7_find_cic_range(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
609 {
610  int i, found = 0;
611 
612  for (i = 0; i < linkset->numchans; i++) {
613  if (ss7_match_range(linkset->pvts[i], startcic, endcic, dpc)) {
614  found++;
615  }
616  }
617 
618  if (found == endcic - startcic + 1) {
619  return 1;
620  }
621 
622  return 0;
623 }
624 
625 static void ss7_handle_cqm(struct sig_ss7_linkset *linkset, ss7_event *e)
626 {
627  unsigned char status[32];
628  struct sig_ss7_chan *p = NULL;
629  int i;
630  int offset;
631  int chanpos;
632 
633  memset(status, 0, sizeof(status));
634  for (i = 0; i < linkset->numchans; i++) {
635  if (ss7_match_range(linkset->pvts[i], e->cqm.startcic, e->cqm.endcic, e->cqm.opc)) {
636  p = linkset->pvts[i];
637  sig_ss7_lock_private(p);
638  offset = p->cic - e->cqm.startcic;
639  status[offset] = 0;
640  if (p->locallyblocked) {
641  status[offset] |= (1 << 0) | (1 << 4);
642  }
643  if (p->remotelyblocked) {
644  status[offset] |= (1 << 1) | (1 << 5);
645  }
646  if (p->ss7call) {
647  if (p->outgoing) {
648  status[offset] |= (1 << 3);
649  } else {
650  status[offset] |= (1 << 2);
651  }
652  } else {
653  status[offset] |= 0x3 << 2;
654  }
655  sig_ss7_unlock_private(p);
656  }
657  }
658 
659  if (p) {
660  isup_cqr(linkset->ss7, e->cqm.startcic, e->cqm.endcic, e->cqm.opc, status);
661  } else {
662  ast_log(LOG_WARNING, "Could not find any equipped circuits within CQM CICs\n");
663  }
664 
665  chanpos = sig_ss7_find_cic(linkset, e->cqm.startcic, e->cqm.opc);
666  if (chanpos < 0) {
667  isup_free_call(linkset->ss7, e->cqm.call);
668  return;
669  }
670  p = linkset->pvts[chanpos];
671  sig_ss7_lock_private(p);
672  p->ss7call = e->cqm.call;
673  if (!p->owner) {
674  p->ss7call = isup_free_call_if_clear(linkset->ss7, e->cqm.call);
675  }
676  sig_ss7_unlock_private(p);
677 }
678 
679 static inline void ss7_hangup_cics(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
680 {
681  int i;
682 
683  for (i = 0; i < linkset->numchans; i++) {
684  if (ss7_match_range(linkset->pvts[i], startcic, endcic, dpc)) {
685  sig_ss7_lock_private(linkset->pvts[i]);
686  sig_ss7_lock_owner(linkset, i);
687  if (linkset->pvts[i]->owner) {
688  ast_softhangup_nolock(linkset->pvts[i]->owner, AST_SOFTHANGUP_DEV);
689  ast_channel_unlock(linkset->pvts[i]->owner);
690  }
691  sig_ss7_unlock_private(linkset->pvts[i]);
692  }
693  }
694 }
695 
696 /*!
697  * \param linkset SS7 linkset control structure.
698  * \param startcic Start CIC of the range to clear.
699  * \param endcic End CIC of the range to clear.
700  * \param dpc Destination Point Code.
701  * \param state Affected CICs from the operation. NULL for all CICs in the range.
702  * \param block Operation to perform. TRUE to block.
703  * \param remotely Direction of the blocking. TRUE to block/unblock remotely.
704  * \param type Blocking type - hardware or maintenance.
705  *
706  * \note Assumes the linkset->lock is already obtained.
707  * \note Must be called without sig_ss7_lock_private() obtained.
708  */
709 static inline void ss7_block_cics(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc, unsigned char state[], int block, int remotely, int type)
710 {
711  int i;
712 
713  for (i = 0; i < linkset->numchans; i++) {
714  if (ss7_match_range(linkset->pvts[i], startcic, endcic, dpc)) {
715  sig_ss7_lock_private(linkset->pvts[i]);
716  if (state) {
717  if (state[linkset->pvts[i]->cic - startcic]) {
718 
719  if (remotely) {
720  sig_ss7_set_remotelyblocked(linkset->pvts[i], block, type);
721  } else {
722  sig_ss7_set_locallyblocked(linkset->pvts[i], block, type);
723  }
724 
725  sig_ss7_lock_owner(linkset, i);
726  if (linkset->pvts[i]->owner) {
727  if (ast_channel_state(linkset->pvts[i]->owner) == AST_STATE_DIALING
728  && linkset->pvts[i]->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING) {
729  ast_channel_hangupcause_set(linkset->pvts[i]->owner, SS7_CAUSE_TRY_AGAIN);
730  }
731  ast_channel_unlock(linkset->pvts[i]->owner);
732  }
733  }
734  } else {
735  if (remotely) {
736  sig_ss7_set_remotelyblocked(linkset->pvts[i], block, type);
737  } else {
738  sig_ss7_set_locallyblocked(linkset->pvts[i], block, type);
739  }
740  }
741  sig_ss7_unlock_private(linkset->pvts[i]);
742  }
743  }
744 }
745 
746 /*!
747  * \param linkset SS7 linkset control structure.
748  * \param startcic Start CIC of the range to set in service.
749  * \param endcic End CIC of the range to set in service.
750  * \param dpc Destination Point Code.
751  *
752  * \note Must be called without sig_ss7_lock_private() obtained.
753  */
754 static void ss7_inservice(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
755 {
756  int i;
757 
758  for (i = 0; i < linkset->numchans; i++) {
759  if (ss7_match_range(linkset->pvts[i], startcic, endcic, dpc)) {
760  sig_ss7_lock_private(linkset->pvts[i]);
761  sig_ss7_set_inservice(linkset->pvts[i], 1);
762  sig_ss7_unlock_private(linkset->pvts[i]);
763  }
764  }
765 }
766 
767 static int ss7_find_alloc_call(struct sig_ss7_chan *p)
768 {
769  if (!p) {
770  return 0;
771  }
772 
773  if (!p->ss7call) {
774  p->ss7call = isup_new_call(p->ss7->ss7, p->cic, p->dpc, 0);
775  if (!p->ss7call) {
776  return 0;
777  }
778  }
779  return 1;
780 }
781 
782 /*
783  * XXX This routine is not tolerant of holes in the pvts[] array.
784  * XXX This routine assumes the cic's in the pvts[] array are sorted.
785  *
786  * Probably the easiest way to deal with the invalid assumptions
787  * is to have a local pvts[] array and sort it by dpc and cic.
788  * Then the existing algorithm could work.
789  */
790 static void ss7_reset_linkset(struct sig_ss7_linkset *linkset)
791 {
792  int i, startcic, endcic, dpc;
793  struct sig_ss7_chan *p;
794 
795  if (linkset->numchans <= 0) {
796  return;
797  }
798 
799  startcic = linkset->pvts[0]->cic;
800  p = linkset->pvts[0];
801  /* DB: CIC's DPC fix */
802  dpc = linkset->pvts[0]->dpc;
803 
804  for (i = 0; i < linkset->numchans; i++) {
805  if (linkset->pvts[i+1]
806  && linkset->pvts[i+1]->dpc == dpc
807  && linkset->pvts[i+1]->cic - linkset->pvts[i]->cic == 1
808  && linkset->pvts[i]->cic - startcic < (linkset->type == SS7_ANSI ? 24 : 31)) {
809  continue;
810  } else {
811  endcic = linkset->pvts[i]->cic;
812  ast_verb(1, "Resetting CICs %d to %d\n", startcic, endcic);
813 
814  sig_ss7_lock_private(p);
815  if (!ss7_find_alloc_call(p)) {
816  ast_log(LOG_ERROR, "Unable to allocate new ss7call\n");
817  } else if (!(endcic - startcic)) { /* GRS range can not be 0 - use RSC instead */
818  isup_rsc(linkset->ss7, p->ss7call);
819  } else {
820  isup_grs(linkset->ss7, p->ss7call, endcic);
821  }
822  sig_ss7_unlock_private(p);
823 
824  /* DB: CIC's DPC fix */
825  if (linkset->pvts[i+1]) {
826  startcic = linkset->pvts[i+1]->cic;
827  dpc = linkset->pvts[i+1]->dpc;
828  p = linkset->pvts[i+1];
829  }
830  }
831  }
832 }
833 
834 /*!
835  * \internal
836  * \brief Complete the RSC procedure started earlier
837  * \since 11.0
838  *
839  * \param p Signaling private structure pointer.
840  *
841  * \note Assumes the ss7->lock is already obtained.
842  * \note Assumes sig_ss7_lock_private(p) is already obtained.
843  */
844 static void ss7_do_rsc(struct sig_ss7_chan *p)
845 {
846  if (!p || !p->ss7call) {
847  return;
848  }
849 
850  isup_rsc(p->ss7->ss7, p->ss7call);
851 
852  if (p->locallyblocked & SS7_BLOCKED_MAINTENANCE) {
853  isup_blo(p->ss7->ss7, p->ss7call);
854  } else {
855  sig_ss7_set_locallyblocked(p, 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
856  }
857 }
858 
859 /*!
860  * \internal
861  * \brief Start RSC procedure on a specific link
862  * \since 11.0
863  *
864  * \param linkset SS7 linkset control structure.
865  * \param which Channel position in the span.
866  *
867  * \note Assumes the ss7->lock is already obtained.
868  * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
869  *
870  * \retval TRUE on success
871  */
872 static int ss7_start_rsc(struct sig_ss7_linkset *linkset, int which)
873 {
874  if (!linkset->pvts[which]) {
875  return 0;
876  }
877 
878  if (!ss7_find_alloc_call(linkset->pvts[which])) {
879  return 0;
880  }
881 
882  sig_ss7_set_remotelyblocked(linkset->pvts[which], 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
883  sig_ss7_set_inservice(linkset->pvts[which], 0);
884  sig_ss7_loopback(linkset->pvts[which], 0);
885 
886  sig_ss7_lock_owner(linkset, which);
887  if (linkset->pvts[which]->owner) {
888  ast_channel_hangupcause_set(linkset->pvts[which]->owner, AST_CAUSE_NORMAL_CLEARING);
889  ast_softhangup_nolock(linkset->pvts[which]->owner, AST_SOFTHANGUP_DEV);
890  ast_channel_unlock(linkset->pvts[which]->owner);
891  linkset->pvts[which]->do_hangup = SS7_HANGUP_SEND_RSC;
892  } else {
893  ss7_do_rsc(linkset->pvts[which]);
894  }
895 
896  return 1;
897 }
898 
899 /*!
900  * \internal
901  * \brief Determine if a private channel structure is available.
902  * \since 11.0
903  *
904  * \param linkset SS7 linkset control structure.
905  * \param startcic Start CIC of the range to clear.
906  * \param endcic End CIC of the range to clear.
907  * \param dpc Destination Point Code.
908  * \param do_hangup What we have to do to clear the call.
909  *
910  * \note Assumes the linkset->lock is already obtained.
911  * \note Must be called without sig_ss7_lock_private() obtained.
912  */
913 static void ss7_clear_channels(struct sig_ss7_linkset *linkset, int startcic, int endcic, int dpc, int do_hangup)
914 {
915  int i;
916 
917  for (i = 0; i < linkset->numchans; i++) {
918  if (ss7_match_range(linkset->pvts[i], startcic, endcic, dpc)) {
919  sig_ss7_lock_private(linkset->pvts[i]);
920  sig_ss7_set_inservice(linkset->pvts[i], 0);
921  sig_ss7_lock_owner(linkset, i);
922  if (linkset->pvts[i]->owner) {
923  ast_channel_hangupcause_set(linkset->pvts[i]->owner,
924  AST_CAUSE_NORMAL_CLEARING);
925  ast_softhangup_nolock(linkset->pvts[i]->owner, AST_SOFTHANGUP_DEV);
926  ast_channel_unlock(linkset->pvts[i]->owner);
927  linkset->pvts[i]->do_hangup = (linkset->pvts[i]->cic != startcic) ?
928  do_hangup : SS7_HANGUP_DO_NOTHING;
929  } else if (linkset->pvts[i] && linkset->pvts[i]->cic != startcic) {
930  isup_free_call(linkset->pvts[i]->ss7->ss7, linkset->pvts[i]->ss7call);
931  linkset->pvts[i]->ss7call = NULL;
932  }
933  sig_ss7_unlock_private(linkset->pvts[i]);
934  }
935  }
936 }
937 
938 /*!
939  * \internal
940  *
941  * \param p Signaling private structure pointer.
942  * \param linkset SS7 linkset control structure.
943  *
944  * \note Assumes the linkset->lock is already obtained.
945  * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
946  */
947 static void ss7_start_call(struct sig_ss7_chan *p, struct sig_ss7_linkset *linkset)
948 {
949  struct ss7 *ss7 = linkset->ss7;
950  int law;
951  struct ast_channel *c;
952  char tmp[256];
953  char *strp;
954  ast_callid callid = 0;
955  int callid_created = ast_callid_threadstorage_auto(&callid);
956 
957  if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
959  isup_acm(ss7, p->ss7call);
960  } else {
962  }
963 
964  /* Companding law is determined by SS7 signaling type. */
965  if (linkset->type == SS7_ITU) {
966  law = SIG_SS7_ALAW;
967  } else {
968  law = SIG_SS7_ULAW;
969  }
970 
971  isup_set_echocontrol(p->ss7call, (linkset->flags & LINKSET_FLAG_DEFAULTECHOCONTROL) ? 1 : 0);
972 
973  /*
974  * Release the SS7 lock while we create the channel so other
975  * threads can send messages. We must also release the private
976  * lock to prevent deadlock while creating the channel.
977  */
978  ast_mutex_unlock(&linkset->lock);
979  sig_ss7_unlock_private(p);
980  c = sig_ss7_new_ast_channel(p, AST_STATE_RING, law, 0, p->exten, NULL, NULL);
981  if (!c) {
982  ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
983  ast_mutex_lock(&linkset->lock);
984  sig_ss7_lock_private(p);
985  isup_rel(linkset->ss7, p->ss7call, AST_CAUSE_SWITCH_CONGESTION);
987  ast_callid_threadstorage_auto_clean(callid, callid_created);
988  return;
989  }
990 
991  /* Hold the channel and private lock while we setup the channel. */
992  ast_channel_lock(c);
993  sig_ss7_lock_private(p);
994 
996 
997  /*
998  * It is reasonably safe to set the following
999  * channel variables while the channel private
1000  * structure is locked. The PBX has not been
1001  * started yet and it is unlikely that any other task
1002  * will do anything with the channel we have just
1003  * created.
1004  *
1005  * We only reference these variables in the context of the ss7_linkset function
1006  * when receiving either and IAM or a COT message.
1007  */
1008  if (!ast_strlen_zero(p->charge_number)) {
1009  pbx_builtin_setvar_helper(c, "SS7_CHARGE_NUMBER", p->charge_number);
1010  /* Clear this after we set it */
1011  p->charge_number[0] = 0;
1012  }
1013  if (!ast_strlen_zero(p->gen_add_number)) {
1014  pbx_builtin_setvar_helper(c, "SS7_GENERIC_ADDRESS", p->gen_add_number);
1015  /* Clear this after we set it */
1016  p->gen_add_number[0] = 0;
1017  }
1018  if (!ast_strlen_zero(p->jip_number)) {
1019  pbx_builtin_setvar_helper(c, "SS7_JIP", p->jip_number);
1020  /* Clear this after we set it */
1021  p->jip_number[0] = 0;
1022  }
1023  if (!ast_strlen_zero(p->gen_dig_number)) {
1024  pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGITS", p->gen_dig_number);
1025  /* Clear this after we set it */
1026  p->gen_dig_number[0] = 0;
1027  }
1028 
1029  snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_type);
1030  pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGTYPE", tmp);
1031  /* Clear this after we set it */
1032  p->gen_dig_type = 0;
1033 
1034  snprintf(tmp, sizeof(tmp), "%d", p->gen_dig_scheme);
1035  pbx_builtin_setvar_helper(c, "SS7_GENERIC_DIGSCHEME", tmp);
1036  /* Clear this after we set it */
1037  p->gen_dig_scheme = 0;
1038 
1039  if (!ast_strlen_zero(p->lspi_ident)) {
1040  pbx_builtin_setvar_helper(c, "SS7_LSPI_IDENT", p->lspi_ident);
1041  /* Clear this after we set it */
1042  p->lspi_ident[0] = 0;
1043  }
1044 
1045  snprintf(tmp, sizeof(tmp), "%d", p->call_ref_ident);
1046  pbx_builtin_setvar_helper(c, "SS7_CALLREF_IDENT", tmp);
1047  /* Clear this after we set it */
1048  p->call_ref_ident = 0;
1049 
1050  snprintf(tmp, sizeof(tmp), "%d", p->call_ref_pc);
1051  pbx_builtin_setvar_helper(c, "SS7_CALLREF_PC", tmp);
1052  /* Clear this after we set it */
1053  p->call_ref_pc = 0;
1054 
1055  snprintf(tmp, sizeof(tmp), "%d", p->calling_party_cat);
1056  pbx_builtin_setvar_helper(c, "SS7_CALLING_PARTY_CATEGORY", tmp);
1057  /* Clear this after we set it */
1058  p->calling_party_cat = 0;
1059 
1060  if (p->redirect_counter) {
1061  struct ast_party_redirecting redirecting;
1062 
1063  switch (p->redirect_info_ind) {
1064  case 0:
1065  strp = "NO_REDIRECTION";
1066  break;
1067  case 1:
1068  strp = "CALL_REROUTED_PRES_ALLOWED";
1069  break;
1070  case 2:
1071  strp = "CALL_REROUTED_INFO_RESTRICTED";
1072  break;
1073  case 3:
1074  strp = "CALL_DIVERTED_PRES_ALLOWED";
1075  break;
1076  case 4:
1077  strp = "CALL_DIVERTED_INFO_RESTRICTED";
1078  break;
1079  case 5:
1080  strp = "CALL_REROUTED_PRES_RESTRICTED";
1081  break;
1082  case 6:
1083  strp = "CALL_DIVERTED_PRES_RESTRICTED";
1084  break;
1085  case 7:
1086  strp = "SPARE";
1087  break;
1088  default:
1089  strp = "NO_REDIRECTION";
1090  break;
1091  }
1092  pbx_builtin_setvar_helper(c, "SS7_REDIRECT_INFO_IND", strp);
1093  /* Clear this after we set it */
1094  p->redirect_info_ind = 0;
1095 
1096  ast_party_redirecting_init(&redirecting);
1097 
1098  if (p->redirect_info_counter) {
1099  redirecting.count = p->redirect_info_counter;
1100  if (p->redirect_info_counter != p->redirect_counter) {
1101  if (p->redirect_info_counter < p->redirect_counter) {
1102  redirecting.count = p->redirect_counter;
1103  }
1104  ast_log(LOG_WARNING, "Redirect counters differ: %u while info says %u - using %u\n",
1105  p->redirect_counter, p->redirect_info_counter, redirecting.count);
1106  }
1107  /* Clear this after we set it */
1108  p->redirect_info_counter = 0;
1109  p->redirect_counter = 0;
1110  }
1111 
1112  if (p->redirect_counter) {
1113  redirecting.count = p->redirect_counter;
1114  /* Clear this after we set it */
1115  p->redirect_counter = 0;
1116  }
1117 
1118  switch (p->redirect_info_orig_reas) {
1119  case SS7_REDIRECTING_REASON_UNKNOWN:
1120  redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1121  break;
1122  case SS7_REDIRECTING_REASON_USER_BUSY:
1123  redirecting.orig_reason.code = AST_REDIRECTING_REASON_USER_BUSY;
1124  break;
1125  case SS7_REDIRECTING_REASON_NO_ANSWER:
1126  redirecting.orig_reason.code = AST_REDIRECTING_REASON_NO_ANSWER;
1127  break;
1128  case SS7_REDIRECTING_REASON_UNCONDITIONAL:
1129  redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNCONDITIONAL;
1130  break;
1131  default:
1132  redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1133  break;
1134  }
1135 
1136  switch (p->redirect_info_reas) {
1137  case SS7_REDIRECTING_REASON_UNKNOWN:
1138  redirecting.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1139  break;
1140  case SS7_REDIRECTING_REASON_USER_BUSY:
1141  redirecting.reason.code = AST_REDIRECTING_REASON_USER_BUSY;
1142  if (!p->redirect_info_orig_reas && redirecting.count == 1) {
1143  redirecting.orig_reason.code = AST_REDIRECTING_REASON_USER_BUSY;
1144  }
1145  break;
1146  case SS7_REDIRECTING_REASON_NO_ANSWER:
1147  redirecting.reason.code = AST_REDIRECTING_REASON_NO_ANSWER;
1148  if (!p->redirect_info_orig_reas && redirecting.count == 1) {
1149  redirecting.orig_reason.code = AST_REDIRECTING_REASON_NO_ANSWER;
1150  }
1151  break;
1152  case SS7_REDIRECTING_REASON_UNCONDITIONAL:
1153  redirecting.reason.code = AST_REDIRECTING_REASON_UNCONDITIONAL;
1154  if (!p->redirect_info_orig_reas && redirecting.count == 1) {
1155  redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNCONDITIONAL;
1156  }
1157  break;
1158  case SS7_REDIRECTING_REASON_DEFLECTION_DURING_ALERTING:
1159  case SS7_REDIRECTING_REASON_DEFLECTION_IMMEDIATE_RESPONSE:
1160  redirecting.reason.code = AST_REDIRECTING_REASON_DEFLECTION;
1161  break;
1162  case SS7_REDIRECTING_REASON_UNAVAILABLE:
1163  redirecting.reason.code = AST_REDIRECTING_REASON_UNAVAILABLE;
1164  break;
1165  default:
1166  redirecting.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1167  break;
1168  }
1169  /* Clear this after we set it */
1170  p->redirect_info_orig_reas = 0;
1171  p->redirect_info_reas = 0;
1172 
1173  if (!ast_strlen_zero(p->redirecting_num)) {
1174  redirecting.from.number.str = ast_strdup(p->redirecting_num);
1175  redirecting.from.number.presentation = p->redirecting_presentation;
1176  redirecting.from.number.valid = 1;
1177  /* Clear this after we set it */
1178  p->redirecting_num[0] = 0;
1179  }
1180 
1181  if (!ast_strlen_zero(p->generic_name)) {
1182  redirecting.from.name.str = ast_strdup(p->generic_name);
1183  redirecting.from.name.presentation = p->redirecting_presentation;
1184  redirecting.from.name.valid = 1;
1185  /* Clear this after we set it */
1186  p->generic_name[0] = 0;
1187  }
1188 
1189  if (!ast_strlen_zero(p->orig_called_num)) {
1190  redirecting.orig.number.str = ast_strdup(p->orig_called_num);
1191  redirecting.orig.number.presentation = p->orig_called_presentation;
1192  redirecting.orig.number.valid = 1;
1193  /* Clear this after we set it */
1194  p->orig_called_num[0] = 0;
1195  } else if (redirecting.count == 1) {
1196  ast_party_id_copy(&redirecting.orig, &redirecting.from);
1197  }
1198 
1199  ast_channel_update_redirecting(c, &redirecting, NULL);
1200  ast_party_redirecting_free(&redirecting);
1201  }
1202 
1203  if (p->cug_indicator != ISUP_CUG_NON) {
1204  sprintf(tmp, "%d", p->cug_interlock_code);
1205  pbx_builtin_setvar_helper(c, "SS7_CUG_INTERLOCK_CODE", tmp);
1206 
1207  switch (p->cug_indicator) {
1208  case ISUP_CUG_NON:
1209  strp = "NON_CUG";
1210  break;
1211  case ISUP_CUG_OUTGOING_ALLOWED:
1212  strp = "OUTGOING_ALLOWED";
1213  break;
1214  case ISUP_CUG_OUTGOING_NOT_ALLOWED:
1215  strp = "OUTGOING_NOT_ALLOWED";
1216  break;
1217  default:
1218  strp = "SPARE";
1219  break;
1220  }
1221  pbx_builtin_setvar_helper(c, "SS7_CUG_INDICATOR", strp);
1222 
1223  if (!ast_strlen_zero(p->cug_interlock_ni)) {
1224  pbx_builtin_setvar_helper(c, "SS7_CUG_INTERLOCK_NI", p->cug_interlock_ni);
1225  }
1226 
1227  p->cug_indicator = ISUP_CUG_NON;
1228  }
1229 
1231 
1232  sig_ss7_unlock_private(p);
1233  ast_channel_unlock(c);
1234 
1235  if (ast_pbx_start(c)) {
1236  ast_log(LOG_WARNING, "Unable to start PBX on %s (CIC %d)\n", ast_channel_name(c), p->cic);
1237  ast_hangup(c);
1238  } else {
1239  ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
1240  }
1241 
1242  /* Must return with linkset and private lock. */
1243  ast_mutex_lock(&linkset->lock);
1244  sig_ss7_lock_private(p);
1245  ast_callid_threadstorage_auto_clean(callid, callid_created);
1246 }
1247 
1248 static void ss7_apply_plan_to_number(char *buf, size_t size, const struct sig_ss7_linkset *ss7, const char *number, const unsigned nai)
1249 {
1250  if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
1251  if (size) {
1252  *buf = '\0';
1253  }
1254  return;
1255  }
1256  switch (nai) {
1257  case SS7_NAI_INTERNATIONAL:
1258  snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
1259  break;
1260  case SS7_NAI_NATIONAL:
1261  snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
1262  break;
1263  case SS7_NAI_SUBSCRIBER:
1264  snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
1265  break;
1266  case SS7_NAI_UNKNOWN:
1267  snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
1268  break;
1269  case SS7_NAI_NETWORKROUTED:
1270  snprintf(buf, size, "%s%s", ss7->networkroutedprefix, number);
1271  break;
1272  default:
1273  snprintf(buf, size, "%s", number);
1274  break;
1275  }
1276 }
1277 
1278 static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
1279 {
1280  return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
1281 }
1282 
1283 /*!
1284  * \internal
1285  * \brief Set callid threadstorage for the ss7_linkset thread to that of an existing channel
1286  *
1287  * \param linkset ss7 span control structure.
1288  * \param chanpos channel position in the span
1289  *
1290  * \note Assumes the ss7->lock is already obtained.
1291  * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
1292  *
1293  * \return The callid bound to the channel which has also been bound to threadstorage
1294  * if it exists. If this returns non-zero, the threadstorage should be unbound
1295  * before the while loop wraps in ss7_linkset.
1296  */
1297 static ast_callid func_ss7_linkset_callid(struct sig_ss7_linkset *linkset, int chanpos)
1298 {
1299  ast_callid callid = 0;
1300  sig_ss7_lock_owner(linkset, chanpos);
1301  if (linkset->pvts[chanpos]->owner) {
1302  callid = ast_channel_callid(linkset->pvts[chanpos]->owner);
1303  ast_channel_unlock(linkset->pvts[chanpos]->owner);
1304  if (callid) {
1306  }
1307  }
1308 
1309  return callid;
1310 }
1311 
1312 /*!
1313  * \internal
1314  * \brief Proceed with the call based on the extension matching status
1315  * is matching in the dialplan.
1316  * \since 11.0
1317  *
1318  * \param linkset ss7 span control structure.
1319  * \param p Signaling private structure pointer.
1320  * \param e Event causing the match.
1321  *
1322  * \note Assumes the linkset->lock is already obtained.
1323  * \note Assumes the sig_ss7_lock_private(ss7->pvts[chanpos]) is already obtained.
1324  */
1325 static void ss7_match_extension(struct sig_ss7_linkset *linkset, struct sig_ss7_chan *p, ss7_event *e)
1326 {
1327  ast_verb(3, "SS7 exten: %s complete: %d\n", p->exten, p->called_complete);
1328 
1329  if (!p->called_complete
1330  && linkset->type == SS7_ITU /* ANSI does not support overlap dialing. */
1331  && ast_matchmore_extension(NULL, p->context, p->exten, 1, p->cid_num)
1332  && !isup_start_digittimeout(linkset->ss7, p->ss7call)) {
1333  /* Wait for more digits. */
1334  return;
1335  }
1336  if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
1337  /* DNID is complete */
1338  p->called_complete = 1;
1339  sig_ss7_set_dnid(p, p->exten);
1340 
1341  /* If COT successful start call! */
1342  if ((e->e == ISUP_EVENT_IAM)
1343  ? !(e->iam.cot_check_required || e->iam.cot_performed_on_previous_cic)
1344  : (!(e->sam.cot_check_required || e->sam.cot_performed_on_previous_cic) || e->sam.cot_check_passed)) {
1345  ss7_start_call(p, linkset);
1346  }
1347  return;
1348  }
1349 
1350  ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
1351  isup_rel(linkset->ss7, (e->e == ISUP_EVENT_IAM) ? e->iam.call : e->sam.call, AST_CAUSE_UNALLOCATED);
1352 }
1353 
1354 /* This is a thread per linkset that handles all received events from libss7. */
1355 void *ss7_linkset(void *data)
1356 {
1357  int res, i;
1358  struct timeval *next = NULL, tv;
1359  struct sig_ss7_linkset *linkset = (struct sig_ss7_linkset *) data;
1360  struct ss7 *ss7 = linkset->ss7;
1361  ss7_event *e = NULL;
1362  struct sig_ss7_chan *p;
1363  struct pollfd pollers[SIG_SS7_NUM_DCHANS];
1364  unsigned char mb_state[255];
1365  int nextms;
1366 
1367 #define SS7_MAX_POLL 60000 /* Maximum poll time in ms. */
1368 
1369  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1370 
1371  ss7_set_debug(ss7, SIG_SS7_DEBUG_DEFAULT);
1372  ast_mutex_lock(&linkset->lock);
1373  ss7_start(ss7);
1374  ast_mutex_unlock(&linkset->lock);
1375 
1376  for (;;) {
1377  ast_mutex_lock(&linkset->lock);
1378  if ((next = ss7_schedule_next(ss7))) {
1379  tv = ast_tvnow();
1380  tv.tv_sec = next->tv_sec - tv.tv_sec;
1381  tv.tv_usec = next->tv_usec - tv.tv_usec;
1382  if (tv.tv_usec < 0) {
1383  tv.tv_usec += 1000000;
1384  tv.tv_sec -= 1;
1385  }
1386  if (tv.tv_sec < 0) {
1387  tv.tv_sec = 0;
1388  tv.tv_usec = 0;
1389  }
1390  nextms = tv.tv_sec * 1000;
1391  nextms += tv.tv_usec / 1000;
1392  if (SS7_MAX_POLL < nextms) {
1393  nextms = SS7_MAX_POLL;
1394  }
1395  } else {
1396  nextms = SS7_MAX_POLL;
1397  }
1398 
1399  for (i = 0; i < linkset->numsigchans; i++) {
1400  pollers[i].fd = linkset->fds[i];
1401  pollers[i].events = ss7_pollflags(ss7, linkset->fds[i]);
1402  pollers[i].revents = 0;
1403  }
1404  ast_mutex_unlock(&linkset->lock);
1405 
1406  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
1407  pthread_testcancel();
1408  res = poll(pollers, linkset->numsigchans, nextms);
1409  pthread_testcancel();
1410  pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
1411 
1412  ast_mutex_lock(&linkset->lock);
1413  if ((res < 0) && (errno != EINTR)) {
1414  ast_log(LOG_ERROR, "poll(%s)\n", strerror(errno));
1415  } else if (!res) {
1416  ss7_schedule_run(ss7);
1417  }
1418 
1419  for (i = 0; i < linkset->numsigchans; i++) {
1420  if (pollers[i].revents & POLLPRI) {
1421  sig_ss7_handle_link_exception(linkset, i);
1422  }
1423  if (pollers[i].revents & POLLIN) {
1424  res = ss7_read(ss7, pollers[i].fd);
1425  }
1426  if (pollers[i].revents & POLLOUT) {
1427  res = ss7_write(ss7, pollers[i].fd);
1428  if (res < 0) {
1429  ast_debug(1, "Error in write %s\n", strerror(errno));
1430  }
1431  }
1432  }
1433 
1434  while ((e = ss7_check_event(ss7))) {
1435  ast_callid callid = 0;
1436  int chanpos = -1;
1437  char cause_str[30];
1438 
1439  if (linkset->debug) {
1440  ast_verbose("Linkset %d: Processing event: %s\n",
1441  linkset->span, ss7_event2str(e->e));
1442  }
1443 
1444  switch (e->e) {
1445  case SS7_EVENT_UP:
1446  if (linkset->state != LINKSET_STATE_UP) {
1447  ast_verb(1, "--- SS7 Up ---\n");
1448  ss7_reset_linkset(linkset);
1449  }
1450  linkset->state = LINKSET_STATE_UP;
1451  break;
1452  case SS7_EVENT_DOWN:
1453  ast_verb(1, "--- SS7 Down ---\n");
1454  linkset->state = LINKSET_STATE_DOWN;
1455  for (i = 0; i < linkset->numchans; i++) {
1456  p = linkset->pvts[i];
1457  if (p) {
1458  sig_ss7_set_inservice(p, 0);
1459  if (linkset->flags & LINKSET_FLAG_INITIALHWBLO) {
1460  sig_ss7_set_remotelyblocked(p, 1, SS7_BLOCKED_HARDWARE);
1461  }
1462  }
1463  }
1464  break;
1465  case MTP2_LINK_UP:
1466  ast_verb(1, "MTP2 link up (SLC %d)\n", e->gen.data);
1467  break;
1468  case MTP2_LINK_DOWN:
1469  ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
1470  break;
1471  case ISUP_EVENT_CPG:
1472  chanpos = ss7_find_cic_gripe(linkset, e->cpg.cic, e->cpg.opc, "CPG");
1473  if (chanpos < 0) {
1474  isup_free_call(ss7, e->cpg.call);
1475  break;
1476  }
1477  p = linkset->pvts[chanpos];
1478  sig_ss7_lock_private(p);
1479  callid = func_ss7_linkset_callid(linkset, chanpos);
1480 
1481  switch (e->cpg.event) {
1482  case CPG_EVENT_ALERTING:
1485  }
1486  sig_ss7_lock_owner(linkset, chanpos);
1487  if (p->owner) {
1488  ast_setstate(p->owner, AST_STATE_RINGING);
1489  if (!ast_strlen_zero(e->cpg.connected_num)) {
1490  struct ast_party_connected_line ast_connected;
1491  char connected_num[AST_MAX_EXTENSION];
1492 
1493  ast_party_connected_line_init(&ast_connected);
1494  ast_connected.id.number.presentation =
1495  ss7_pres_scr2cid_pres(e->cpg.connected_presentation_ind,
1496  e->cpg.connected_screening_ind);
1497  ss7_apply_plan_to_number(connected_num, sizeof(connected_num),
1498  linkset, e->cpg.connected_num, e->cpg.connected_nai);
1499  ast_connected.id.number.str = ast_strdup(connected_num);
1500  ast_connected.id.number.valid = 1;
1501  ast_channel_queue_connected_line_update(p->owner, &ast_connected, NULL);
1502  ast_party_connected_line_free(&ast_connected);
1503  }
1504  ast_channel_unlock(p->owner);
1505  }
1506  sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING);
1507  break;
1508  case CPG_EVENT_PROGRESS:
1509  case CPG_EVENT_INBANDINFO:
1510  {
1511  ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
1512  sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROGRESS);
1513  p->progress = 1;
1514  sig_ss7_set_dialing(p, 0);
1515  sig_ss7_open_media(p);
1516  }
1517  break;
1518  default:
1519  ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
1520  break;
1521  }
1522 
1523  sig_ss7_unlock_private(p);
1524  break;
1525  case ISUP_EVENT_RSC:
1526  ast_verb(1, "Resetting CIC %d\n", e->rsc.cic);
1527  chanpos = ss7_find_cic_gripe(linkset, e->rsc.cic, e->rsc.opc, "RSC");
1528  if (chanpos < 0) {
1529  isup_free_call(ss7, e->rsc.call);
1530  break;
1531  }
1532  p = linkset->pvts[chanpos];
1533  sig_ss7_lock_private(p);
1534  p->ss7call = e->rsc.call;
1535  callid = func_ss7_linkset_callid(linkset, chanpos);
1536  sig_ss7_set_inservice(p, 1);
1537  sig_ss7_set_remotelyblocked(p, 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
1538 
1539  if (p->locallyblocked & SS7_BLOCKED_MAINTENANCE) {
1540  isup_blo(ss7, e->rsc.call);
1541  } else if (p->locallyblocked & SS7_BLOCKED_HARDWARE) {
1542  sig_ss7_set_locallyblocked(p, 0, SS7_BLOCKED_HARDWARE);
1543  }
1544 
1545  isup_set_call_dpc(e->rsc.call, p->dpc);
1546  sig_ss7_lock_owner(linkset, chanpos);
1547  if (p->owner) {
1548  p->do_hangup = SS7_HANGUP_SEND_RLC;
1549  if (!(e->rsc.got_sent_msg & ISUP_SENT_IAM)) {
1550  /* Q.784 6.2.3 */
1551  ast_channel_hangupcause_set(p->owner, AST_CAUSE_NORMAL_CLEARING);
1552  } else {
1553  ast_channel_hangupcause_set(p->owner, SS7_CAUSE_TRY_AGAIN);
1554  }
1555 
1556  ss7_queue_pvt_cause_data(p->owner, "SS7 ISUP_EVENT_RSC", AST_CAUSE_INTERWORKING);
1557 
1559  ast_channel_unlock(p->owner);
1560  } else {
1561  isup_rlc(ss7, e->rsc.call);
1562  p->ss7call = isup_free_call_if_clear(ss7, e->rsc.call);
1563  }
1564  /* End the loopback if we have one */
1565  sig_ss7_loopback(p, 0);
1566 
1567  sig_ss7_unlock_private(p);
1568  break;
1569  case ISUP_EVENT_GRS:
1570  if (!sig_ss7_find_cic_range(linkset, e->grs.startcic, e->grs.endcic,
1571  e->grs.opc)) {
1572  ast_log(LOG_WARNING, "GRS on unconfigured range CIC %d - %d PC %d\n",
1573  e->grs.startcic, e->grs.endcic, e->grs.opc);
1574  chanpos = sig_ss7_find_cic(linkset, e->grs.startcic, e->grs.opc);
1575  if (chanpos < 0) {
1576  isup_free_call(ss7, e->grs.call);
1577  break;
1578  }
1579  p = linkset->pvts[chanpos];
1580  sig_ss7_lock_private(p);
1581  p->ss7call = isup_free_call_if_clear(ss7, e->grs.call);
1582  sig_ss7_unlock_private(p);
1583  break;
1584  }
1585 
1586  /* Leave startcic last to collect all cics mb_state */
1587  for (i = e->grs.endcic - e->grs.startcic; 0 <= i; --i) {
1588  /*
1589  * We are guaranteed to find chanpos because
1590  * sig_ss7_find_cic_range() includes it.
1591  */
1592  chanpos = sig_ss7_find_cic(linkset, e->grs.startcic + i, e->grs.opc);
1593  p = linkset->pvts[chanpos];
1594  sig_ss7_lock_private(p);
1595 
1596  if (p->locallyblocked & SS7_BLOCKED_MAINTENANCE) {
1597  mb_state[i] = 1;
1598  } else {
1599  mb_state[i] = 0;
1600  sig_ss7_set_locallyblocked(p, 0, SS7_BLOCKED_HARDWARE);
1601  }
1602 
1603  sig_ss7_set_remotelyblocked(p, 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
1604 
1605  if (!i) {
1606  p->ss7call = e->grs.call;
1607  isup_gra(ss7, p->ss7call, e->grs.endcic, mb_state);
1608  }
1609 
1610  sig_ss7_lock_owner(linkset, chanpos);
1611  if (p->owner) {
1612  ast_channel_softhangup_internal_flag_add(p->owner, AST_SOFTHANGUP_DEV);
1613  if (ast_channel_state(p->owner) == AST_STATE_DIALING
1614  && linkset->pvts[i]->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING) {
1615  ast_channel_hangupcause_set(p->owner, SS7_CAUSE_TRY_AGAIN);
1616  } else {
1617  ast_channel_hangupcause_set(p->owner, AST_CAUSE_NORMAL_CLEARING);
1618  }
1619  p->do_hangup = SS7_HANGUP_FREE_CALL;
1620  ast_channel_unlock(p->owner);
1621  } else if (!i) {
1622  p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
1623  } else if (p->ss7call) {
1624  /* clear any other session */
1625  isup_free_call(ss7, p->ss7call);
1626  p->ss7call = NULL;
1627  }
1628  sig_ss7_set_inservice(p, 1);
1629  sig_ss7_unlock_private(p);
1630  }
1631  break;
1632  case ISUP_EVENT_CQM:
1633  ast_debug(1, "Got Circuit group query message from CICs %d to %d\n",
1634  e->cqm.startcic, e->cqm.endcic);
1635  ss7_handle_cqm(linkset, e);
1636  break;
1637  case ISUP_EVENT_GRA:
1638  if (!sig_ss7_find_cic_range(linkset, e->gra.startcic,
1639  e->gra.endcic, e->gra.opc)) { /* Never will be true */
1640  ast_log(LOG_WARNING, "GRA on unconfigured range CIC %d - %d PC %d\n",
1641  e->gra.startcic, e->gra.endcic, e->gra.opc);
1642  isup_free_call(ss7, e->gra.call);
1643  break;
1644  }
1645  ast_verb(1, "Got reset acknowledgement from CIC %d to %d DPC: %d\n",
1646  e->gra.startcic, e->gra.endcic, e->gra.opc);
1647  ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc,
1648  e->gra.status, 1, 1, SS7_BLOCKED_MAINTENANCE);
1649  ss7_inservice(linkset, e->gra.startcic, e->gra.endcic, e->gra.opc);
1650 
1651  chanpos = sig_ss7_find_cic(linkset, e->gra.startcic, e->gra.opc);
1652  if (chanpos < 0) {
1653  isup_free_call(ss7, e->gra.call);
1654  break;
1655  }
1656 
1657  p = linkset->pvts[chanpos];
1658  sig_ss7_lock_private(p);
1659 
1660  /* we may send a CBD with GRS! */
1661  p->ss7call = isup_free_call_if_clear(ss7, e->gra.call);
1662  sig_ss7_unlock_private(p);
1663  break;
1664  case ISUP_EVENT_SAM:
1665  chanpos = ss7_find_cic_gripe(linkset, e->sam.cic, e->sam.opc, "SAM");
1666  if (chanpos < 0) {
1667  isup_free_call(ss7, e->sam.call);
1668  break;
1669  }
1670  p = linkset->pvts[chanpos];
1671  sig_ss7_lock_private(p);
1672  sig_ss7_lock_owner(linkset, chanpos);
1673  if (p->owner) {
1674  ast_log(LOG_WARNING, "SAM on CIC %d PC %d already have call\n", e->sam.cic, e->sam.opc);
1675  ast_channel_unlock(p->owner);
1676  sig_ss7_unlock_private(p);
1677  break;
1678  }
1679  p->called_complete = 0;
1680  if (!ast_strlen_zero(e->sam.called_party_num)) {
1681  char *st;
1682  strncat(p->exten, e->sam.called_party_num, sizeof(p->exten) - strlen(p->exten) - 1);
1683  st = strchr(p->exten, '#');
1684  if (st) {
1685  *st = '\0';
1686  p->called_complete = 1;
1687  }
1688  ss7_match_extension(linkset, p, e);
1689  }
1690  sig_ss7_unlock_private(p);
1691  break;
1692  case ISUP_EVENT_IAM:
1693  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);
1694  chanpos = ss7_find_cic_gripe(linkset, e->iam.cic, e->iam.opc, "IAM");
1695  if (chanpos < 0) {
1696  isup_free_call(ss7, e->iam.call);
1697  break;
1698  }
1699  p = linkset->pvts[chanpos];
1700  sig_ss7_lock_private(p);
1701  /*
1702  * The channel should be idle and not have an owner at this point since we
1703  * are in the process of creating an owner for it.
1704  */
1705  ast_assert(!p->owner && p->call_level == SIG_SS7_CALL_LEVEL_IDLE);
1706 
1707  if (p->remotelyblocked) {
1708  ast_log(LOG_NOTICE, "Got IAM on remotely blocked CIC %d DPC %d remove blocking\n", e->iam.cic, e->iam.opc);
1709  sig_ss7_set_remotelyblocked(p, 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
1710  sig_ss7_set_inservice(p, 1);
1711  }
1712 
1713  if (!sig_ss7_is_chan_available(p)) {
1714  /* Circuit is likely blocked or in alarm. */
1715  isup_rel(ss7, e->iam.call, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
1716  if (p->locallyblocked) {
1717  isup_clear_callflags(ss7, e->iam.call, ISUP_GOT_IAM);
1718  p->ss7call = isup_free_call_if_clear(ss7, e->iam.call);
1719  ast_log(LOG_WARNING, "Got IAM on locally blocked CIC %d DPC %d, ignore\n", e->iam.cic, e->iam.opc);
1720  }
1721  sig_ss7_unlock_private(p);
1722  break;
1723  }
1724 
1725  /* Mark channel as in use so no outgoing call will steal it. */
1727  p->ss7call = e->iam.call;
1728 
1729  isup_set_call_dpc(p->ss7call, p->dpc);
1730 
1731  if ((p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num))) {
1732  ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
1733  p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
1734  } else {
1735  p->cid_num[0] = 0;
1736  if (e->iam.presentation_ind) {
1737  p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
1738  }
1739  }
1740 
1741  p->called_complete = 0;
1742  if (p->immediate) {
1743  p->exten[0] = 's';
1744  p->exten[1] = '\0';
1745  } else if (!ast_strlen_zero(e->iam.called_party_num)) {
1746  char *st;
1747  ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
1748  st = strchr(p->exten, '#');
1749  if (st) {
1750  *st = '\0';
1751  p->called_complete = 1;
1752  }
1753  } else {
1754  p->exten[0] = '\0';
1755  }
1756 
1757  p->cid_ani[0] = '\0';
1758  if ((p->use_callerid) && (!ast_strlen_zero(e->iam.generic_name))) {
1759  ast_copy_string(p->cid_name, e->iam.generic_name, sizeof(p->cid_name));
1760  } else {
1761  p->cid_name[0] = '\0';
1762  }
1763 
1764  p->cid_ani2 = e->iam.oli_ani2;
1765  p->cid_ton = 0;
1766  ast_copy_string(p->charge_number, e->iam.charge_number, sizeof(p->charge_number));
1767  ast_copy_string(p->gen_add_number, e->iam.gen_add_number, sizeof(p->gen_add_number));
1768  p->gen_add_type = e->iam.gen_add_type;
1769  p->gen_add_nai = e->iam.gen_add_nai;
1770  p->gen_add_pres_ind = e->iam.gen_add_pres_ind;
1771  p->gen_add_num_plan = e->iam.gen_add_num_plan;
1772  ast_copy_string(p->gen_dig_number, e->iam.gen_dig_number, sizeof(p->gen_dig_number));
1773  p->gen_dig_type = e->iam.gen_dig_type;
1774  p->gen_dig_scheme = e->iam.gen_dig_scheme;
1775  ast_copy_string(p->jip_number, e->iam.jip_number, sizeof(p->jip_number));
1776  if (!ast_strlen_zero(e->iam.orig_called_num)) {
1777  ss7_apply_plan_to_number(p->orig_called_num, sizeof(p->orig_called_num), linkset, e->iam.orig_called_num, e->iam.orig_called_nai);
1778  p->orig_called_presentation = ss7_pres_scr2cid_pres(e->iam.orig_called_pres_ind, e->iam.orig_called_screening_ind);
1779  }
1780  if (!ast_strlen_zero(e->iam.redirecting_num)) {
1781  ss7_apply_plan_to_number(p->redirecting_num, sizeof(p->redirecting_num), linkset, e->iam.redirecting_num, e->iam.redirecting_num_nai);
1782  p->redirecting_presentation = ss7_pres_scr2cid_pres(e->iam.redirecting_num_presentation_ind, e->iam.redirecting_num_screening_ind);
1783  }
1784  ast_copy_string(p->generic_name, e->iam.generic_name, sizeof(p->generic_name));
1785  p->calling_party_cat = e->iam.calling_party_cat;
1786  p->redirect_counter = e->iam.redirect_counter;
1787  p->redirect_info = e->iam.redirect_info;
1788  p->redirect_info_ind = e->iam.redirect_info_ind;
1789  p->redirect_info_orig_reas = e->iam.redirect_info_orig_reas;
1790  p->redirect_info_counter = e->iam.redirect_info_counter;
1791  if (p->redirect_info_counter && !p->redirect_counter) {
1792  p->redirect_counter = p->redirect_info_counter;
1793  }
1794  p->redirect_info_reas = e->iam.redirect_info_reas;
1795  p->cug_indicator = e->iam.cug_indicator;
1796  p->cug_interlock_code = e->iam.cug_interlock_code;
1797  ast_copy_string(p->cug_interlock_ni, e->iam.cug_interlock_ni, sizeof(p->cug_interlock_ni));
1798 
1799  if (e->iam.cot_check_required) {
1800  sig_ss7_loopback(p, 1);
1801  }
1802 
1803  p->echocontrol_ind = e->iam.echocontrol_ind;
1804  sig_ss7_set_caller_id(p);
1805  ss7_match_extension(linkset, p, e);
1806  sig_ss7_unlock_private(p);
1807 
1808  if (e->iam.cot_performed_on_previous_cic) {
1809  chanpos = sig_ss7_find_cic(linkset, (e->iam.cic - 1), e->iam.opc);
1810  if (chanpos < 0) {
1811  /* some stupid switch do this */
1812  ast_verb(1, "COT request on previous nonexistent CIC %d in IAM PC %d\n", (e->iam.cic - 1), e->iam.opc);
1813  break;
1814  }
1815  ast_verb(1, "COT request on previous CIC %d in IAM PC %d\n", (e->iam.cic - 1), e->iam.opc);
1816  p = linkset->pvts[chanpos];
1817  sig_ss7_lock_private(p);
1818  if (sig_ss7_is_chan_available(p)) {
1819  sig_ss7_set_inservice(p, 0); /* to prevent to use this circuit */
1820  sig_ss7_loopback(p, 1);
1821  } /* If already have a call don't loop */
1822  sig_ss7_unlock_private(p);
1823  }
1824  break;
1825  case ISUP_EVENT_DIGITTIMEOUT:
1826  chanpos = ss7_find_cic_gripe(linkset, e->digittimeout.cic, e->digittimeout.opc, "DIGITTIMEOUT");
1827  if (chanpos < 0) {
1828  isup_free_call(ss7, e->digittimeout.call);
1829  break;
1830  }
1831  p = linkset->pvts[chanpos];
1832  sig_ss7_lock_private(p);
1833  ast_debug(1, "Digittimeout on CIC: %d PC: %d\n", e->digittimeout.cic, e->digittimeout.opc);
1834  if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
1835  /* DNID is complete */
1836  p->called_complete = 1;
1837  sig_ss7_set_dnid(p, p->exten);
1838 
1839  /* If COT successful start call! */
1840  if (!(e->digittimeout.cot_check_required || e->digittimeout.cot_performed_on_previous_cic) || e->digittimeout.cot_check_passed) {
1841  ss7_start_call(p, linkset);
1842  }
1843  } else {
1844  ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
1845  isup_rel(linkset->ss7, e->digittimeout.call, AST_CAUSE_UNALLOCATED);
1846  }
1847  sig_ss7_unlock_private(p);
1848  break;
1849  case ISUP_EVENT_COT:
1850  if (e->cot.cot_performed_on_previous_cic) {
1851  chanpos = sig_ss7_find_cic(linkset, (e->cot.cic - 1), e->cot.opc);
1852  /* some stupid switches do this!!! */
1853  if (-1 < chanpos) {
1854  p = linkset->pvts[chanpos];
1855  sig_ss7_lock_private(p);
1856  sig_ss7_set_inservice(p, 1);
1857  sig_ss7_loopback(p, 0);
1858  sig_ss7_unlock_private(p);;
1859  ast_verb(1, "Loop turned off on CIC: %d PC: %d\n", (e->cot.cic - 1), e->cot.opc);
1860  }
1861  }
1862 
1863  chanpos = ss7_find_cic_gripe(linkset, e->cot.cic, e->cot.opc, "COT");
1864  if (chanpos < 0) {
1865  isup_free_call(ss7, e->cot.call);
1866  break;
1867  }
1868  p = linkset->pvts[chanpos];
1869 
1870  sig_ss7_lock_private(p);
1871  p->ss7call = e->cot.call;
1872 
1873  if (p->loopedback) {
1874  sig_ss7_loopback(p, 0);
1875  ast_verb(1, "Loop turned off on CIC: %d PC: %d\n", e->cot.cic, e->cot.opc);
1876  }
1877 
1878  /* Don't start call if we didn't get IAM or COT failed! */
1879  if ((e->cot.got_sent_msg & ISUP_GOT_IAM) && e->cot.passed && p->called_complete) {
1880  ss7_start_call(p, linkset);
1881  }
1882 
1883  p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
1884  sig_ss7_unlock_private(p);
1885  break;
1886  case ISUP_EVENT_CCR:
1887  ast_debug(1, "Got CCR request on CIC %d\n", e->ccr.cic);
1888  chanpos = ss7_find_cic_gripe(linkset, e->ccr.cic, e->ccr.opc, "CCR");
1889  if (chanpos < 0) {
1890  isup_free_call(ss7, e->ccr.call);
1891  break;
1892  }
1893 
1894  p = linkset->pvts[chanpos];
1895 
1896  sig_ss7_lock_private(p);
1897  p->ss7call = e->ccr.call;
1898  sig_ss7_loopback(p, 1);
1899  if (linkset->type == SS7_ANSI) {
1900  isup_lpa(linkset->ss7, e->ccr.cic, p->dpc);
1901  }
1902  sig_ss7_unlock_private(p);
1903  break;
1904  case ISUP_EVENT_CVT:
1905  ast_debug(1, "Got CVT request on CIC %d\n", e->cvt.cic);
1906  chanpos = ss7_find_cic_gripe(linkset, e->cvt.cic, e->cvt.opc, "CVT");
1907  if (chanpos < 0) {
1908  isup_free_call(ss7, e->cvt.call);
1909  break;
1910  }
1911 
1912  p = linkset->pvts[chanpos];
1913 
1914  sig_ss7_lock_private(p);
1915  p->ss7call = e->cvt.call;
1916  sig_ss7_loopback(p, 1);
1917  if (!p->owner) {
1918  p->ss7call = isup_free_call_if_clear(ss7, e->cvt.call);
1919  }
1920  isup_cvr(linkset->ss7, e->cvt.cic, p->dpc);
1921  sig_ss7_unlock_private(p);
1922  break;
1923  case ISUP_EVENT_REL:
1924  chanpos = ss7_find_cic_gripe(linkset, e->rel.cic, e->rel.opc, "REL");
1925  if (chanpos < 0) {
1926  isup_free_call(ss7, e->rel.call);
1927  break;
1928  }
1929  p = linkset->pvts[chanpos];
1930  sig_ss7_lock_private(p);
1931  p->ss7call = e->rel.call;
1932  callid = func_ss7_linkset_callid(linkset, chanpos);
1933  sig_ss7_lock_owner(linkset, chanpos);
1934  if (p->owner) {
1935  snprintf(cause_str, sizeof(cause_str), "SS7 ISUP_EVENT_REL (%d)", e->rel.cause);
1936  ss7_queue_pvt_cause_data(p->owner, cause_str, e->rel.cause);
1937 
1938  ast_channel_hangupcause_set(p->owner, e->rel.cause);
1940  p->do_hangup = SS7_HANGUP_SEND_RLC;
1941  ast_channel_unlock(p->owner);
1942  } else {
1943  ast_verb(1, "REL on CIC %d DPC %d without owner!\n", p->cic, p->dpc);
1944  isup_rlc(ss7, p->ss7call);
1945  p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
1946  }
1947 
1948  /* End the loopback if we have one */
1949  sig_ss7_loopback(p, 0);
1950 
1951  /* the rel is not complete here!!! */
1952  sig_ss7_unlock_private(p);
1953  break;
1954  case ISUP_EVENT_ACM:
1955  chanpos = ss7_find_cic_gripe(linkset, e->acm.cic, e->acm.opc, "ACM");
1956  if (chanpos < 0) {
1957  isup_free_call(ss7, e->acm.call);
1958  break;
1959  }
1960 
1961  p = linkset->pvts[chanpos];
1962 
1963  ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
1964 
1965  if (e->acm.call_ref_ident > 0) {
1966  p->rlt = 1; /* Setting it but not using it here*/
1967  }
1968 
1969  sig_ss7_lock_private(p);
1970  p->ss7call = e->acm.call;
1971  callid = func_ss7_linkset_callid(linkset, chanpos);
1972  sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_PROCEEDING);
1975  }
1976  sig_ss7_set_dialing(p, 0);
1977  /* Send alerting if subscriber is free */
1978  if (e->acm.called_party_status_ind == 1) {
1981  }
1982  sig_ss7_lock_owner(linkset, chanpos);
1983  if (p->owner) {
1984  ast_setstate(p->owner, AST_STATE_RINGING);
1985  ast_channel_unlock(p->owner);
1986  }
1987  sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_RINGING);
1988  }
1989  p->echocontrol_ind = e->acm.echocontrol_ind;
1990  sig_ss7_unlock_private(p);
1991  break;
1992  case ISUP_EVENT_CGB:
1993  chanpos = ss7_find_cic_gripe(linkset, e->cgb.startcic, e->cgb.opc, "CGB");
1994  if (chanpos < 0) {
1995  isup_free_call(ss7, e->cgb.call);
1996  break;
1997  }
1998  p = linkset->pvts[chanpos];
1999  ss7_check_range(linkset, e->cgb.startcic, e->cgb.endcic,
2000  e->cgb.opc, e->cgb.status);
2001  ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic,
2002  e->cgb.opc, e->cgb.status, 1, 1,
2003  (e->cgb.type) ? SS7_BLOCKED_HARDWARE : SS7_BLOCKED_MAINTENANCE);
2004 
2005  sig_ss7_lock_private(p);
2006  p->ss7call = e->cgb.call;
2007 
2008  isup_cgba(linkset->ss7, p->ss7call, e->cgb.endcic, e->cgb.status);
2009  if (!p->owner) {
2010  p->ss7call = isup_free_call_if_clear(ss7, e->cgb.call);
2011  }
2012  sig_ss7_unlock_private(p);
2013  break;
2014  case ISUP_EVENT_CGU:
2015  chanpos = ss7_find_cic_gripe(linkset, e->cgu.startcic, e->cgu.opc, "CGU");
2016  if (chanpos < 0) {
2017  isup_free_call(ss7, e->cgu.call);
2018  break;
2019  }
2020  p = linkset->pvts[chanpos];
2021  ss7_check_range(linkset, e->cgu.startcic, e->cgu.endcic,
2022  e->cgu.opc, e->cgu.status);
2023  ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic,
2024  e->cgu.opc, e->cgu.status, 0, 1,
2025  e->cgu.type ? SS7_BLOCKED_HARDWARE : SS7_BLOCKED_MAINTENANCE);
2026 
2027  sig_ss7_lock_private(p);
2028  p->ss7call = e->cgu.call;
2029 
2030  isup_cgua(linkset->ss7, p->ss7call, e->cgu.endcic, e->cgu.status);
2031  if (!p->owner) {
2032  p->ss7call = isup_free_call_if_clear(ss7, e->cgu.call);
2033  }
2034  sig_ss7_unlock_private(p);
2035  break;
2036  case ISUP_EVENT_UCIC:
2037  chanpos = ss7_find_cic_gripe(linkset, e->ucic.cic, e->ucic.opc, "UCIC");
2038  if (chanpos < 0) {
2039  isup_free_call(ss7, e->ucic.call);
2040  break;
2041  }
2042  p = linkset->pvts[chanpos];
2043  ast_debug(1, "Unequipped Circuit Id Code on CIC %d\n", e->ucic.cic);
2044  sig_ss7_lock_private(p);
2045  sig_ss7_lock_owner(linkset, chanpos);
2046  if (p->owner) {
2048  ast_channel_unlock(p->owner);
2049  }
2050  sig_ss7_set_remotelyblocked(p, 1, SS7_BLOCKED_MAINTENANCE);
2051  sig_ss7_set_inservice(p, 0);
2052  p->ss7call = NULL;
2053  isup_free_call(ss7, e->ucic.call);
2054  sig_ss7_unlock_private(p);/* doesn't require a SS7 acknowledgement */
2055  break;
2056  case ISUP_EVENT_BLO:
2057  chanpos = ss7_find_cic_gripe(linkset, e->blo.cic, e->blo.opc, "BLO");
2058  if (chanpos < 0) {
2059  isup_free_call(ss7, e->blo.call);
2060  break;
2061  }
2062  p = linkset->pvts[chanpos];
2063  ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
2064  sig_ss7_lock_private(p);
2065  p->ss7call = e->blo.call;
2066  sig_ss7_set_remotelyblocked(p, 1, SS7_BLOCKED_MAINTENANCE);
2067  isup_bla(linkset->ss7, e->blo.call);
2068  sig_ss7_lock_owner(linkset, chanpos);
2069  if (!p->owner) {
2070  p->ss7call = isup_free_call_if_clear(ss7, e->blo.call);
2071  } else {
2072  if (e->blo.got_sent_msg & ISUP_SENT_IAM) {
2073  /* Q.784 6.2.2 */
2074  ast_channel_hangupcause_set(p->owner, SS7_CAUSE_TRY_AGAIN);
2075  }
2076  ast_channel_unlock(p->owner);
2077  }
2078  sig_ss7_unlock_private(p);
2079  break;
2080  case ISUP_EVENT_BLA:
2081  chanpos = ss7_find_cic_gripe(linkset, e->bla.cic, e->bla.opc, "BLA");
2082  if (chanpos < 0) {
2083  isup_free_call(ss7, e->bla.call);
2084  break;
2085  }
2086  ast_debug(1, "Locally blocking CIC %d\n", e->bla.cic);
2087  p = linkset->pvts[chanpos];
2088  sig_ss7_lock_private(p);
2089  p->ss7call = e->bla.call;
2090  sig_ss7_set_locallyblocked(p, 1, SS7_BLOCKED_MAINTENANCE);
2091  if (!p->owner) {
2092  p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
2093  }
2094  sig_ss7_unlock_private(p);
2095  break;
2096  case ISUP_EVENT_UBL:
2097  chanpos = ss7_find_cic_gripe(linkset, e->ubl.cic, e->ubl.opc, "UBL");
2098  if (chanpos < 0) {
2099  isup_free_call(ss7, e->ubl.call);
2100  break;
2101  }
2102  p = linkset->pvts[chanpos];
2103  ast_debug(1, "Remotely unblocking CIC %d PC %d\n", e->ubl.cic, e->ubl.opc);
2104  sig_ss7_lock_private(p);
2105  p->ss7call = e->ubl.call;
2106  sig_ss7_set_remotelyblocked(p, 0, SS7_BLOCKED_MAINTENANCE);
2107  isup_uba(linkset->ss7, e->ubl.call);
2108  if (!p->owner) {
2109  p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
2110  }
2111  sig_ss7_unlock_private(p);
2112  break;
2113  case ISUP_EVENT_UBA:
2114  chanpos = ss7_find_cic_gripe(linkset, e->uba.cic, e->uba.opc, "UBA");
2115  if (chanpos < 0) {
2116  isup_free_call(ss7, e->uba.call);
2117  break;
2118  }
2119  p = linkset->pvts[chanpos];
2120  ast_debug(1, "Locally unblocking CIC %d PC %d\n", e->uba.cic, e->uba.opc);
2121  sig_ss7_lock_private(p);
2122  p->ss7call = e->uba.call;
2123  sig_ss7_set_locallyblocked(p, 0, SS7_BLOCKED_MAINTENANCE);
2124  if (!p->owner) {
2125  p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
2126  }
2127  sig_ss7_unlock_private(p);
2128  break;
2129  case ISUP_EVENT_CON:
2130  case ISUP_EVENT_ANM:
2131  if (e->e == ISUP_EVENT_CON) {
2132  chanpos = ss7_find_cic_gripe(linkset, e->con.cic, e->con.opc, "CON");
2133  if (chanpos < 0) {
2134  isup_free_call(ss7, e->con.call);
2135  break;
2136  }
2137  } else {
2138  chanpos = ss7_find_cic_gripe(linkset, e->anm.cic, e->anm.opc, "ANM");
2139  if (chanpos < 0) {
2140  isup_free_call(ss7, e->anm.call);
2141  break;
2142  }
2143  }
2144 
2145  p = linkset->pvts[chanpos];
2146  sig_ss7_lock_private(p);
2147  p->ss7call = (e->e == ISUP_EVENT_ANM) ? e->anm.call : e->con.call;
2148  callid = func_ss7_linkset_callid(linkset, chanpos);
2151  }
2152 
2153  if (!ast_strlen_zero((e->e == ISUP_EVENT_ANM)
2154  ? e->anm.connected_num : e->con.connected_num)) {
2155  sig_ss7_lock_owner(linkset, chanpos);
2156  if (p->owner) {
2157  struct ast_party_connected_line ast_connected;
2158  char connected_num[AST_MAX_EXTENSION];
2159 
2160  ast_party_connected_line_init(&ast_connected);
2161  if (e->e == ISUP_EVENT_ANM) {
2162  ast_connected.id.number.presentation = ss7_pres_scr2cid_pres(
2163  e->anm.connected_presentation_ind,
2164  e->anm.connected_screening_ind);
2165  ss7_apply_plan_to_number(connected_num, sizeof(connected_num),
2166  linkset, e->anm.connected_num, e->anm.connected_nai);
2167  ast_connected.id.number.str = ast_strdup(connected_num);
2168  } else {
2169  ast_connected.id.number.presentation = ss7_pres_scr2cid_pres(
2170  e->con.connected_presentation_ind,
2171  e->con.connected_screening_ind);
2172  ss7_apply_plan_to_number(connected_num, sizeof(connected_num),
2173  linkset, e->con.connected_num, e->con.connected_nai);
2174  ast_connected.id.number.str = ast_strdup(connected_num);
2175  }
2176  ast_connected.id.number.valid = 1;
2177  ast_connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
2178  ast_channel_queue_connected_line_update(p->owner, &ast_connected, NULL);
2179  ast_party_connected_line_free(&ast_connected);
2180  ast_channel_unlock(p->owner);
2181  }
2182  }
2183 
2184  sig_ss7_queue_control(linkset, chanpos, AST_CONTROL_ANSWER);
2185  sig_ss7_set_dialing(p, 0);
2186  sig_ss7_open_media(p);
2187  if (((e->e == ISUP_EVENT_ANM) ? !e->anm.echocontrol_ind :
2188  !e->con.echocontrol_ind) || !(linkset->flags & LINKSET_FLAG_USEECHOCONTROL)) {
2189  sig_ss7_set_echocanceller(p, 1);
2190  }
2191  sig_ss7_unlock_private(p);
2192  break;
2193  case ISUP_EVENT_RLC:
2194  chanpos = ss7_find_cic_gripe(linkset, e->rlc.cic, e->rlc.opc, "RLC");
2195  if (chanpos < 0) {
2196  isup_free_call(ss7, e->rlc.call);
2197  break;
2198  }
2199 
2200  p = linkset->pvts[chanpos];
2201  sig_ss7_lock_private(p);
2202  p->ss7call = e->rlc.call;
2203  callid = func_ss7_linkset_callid(linkset, chanpos);
2204  if (e->rlc.got_sent_msg & (ISUP_SENT_RSC | ISUP_SENT_REL)) {
2205  sig_ss7_loopback(p, 0);
2206  if (e->rlc.got_sent_msg & ISUP_SENT_RSC) {
2207  sig_ss7_set_inservice(p, 1);
2208  }
2209  }
2210  sig_ss7_lock_owner(linkset, chanpos);
2211  if (!p->owner) {
2212  p->ss7call = isup_free_call_if_clear(ss7, e->rlc.call);
2214  } else {
2215  p->do_hangup = SS7_HANGUP_DO_NOTHING;
2217  ast_channel_unlock(p->owner);
2218  }
2219  sig_ss7_unlock_private(p);
2220  break;
2221  case ISUP_EVENT_FAA:
2222  /*!
2223  * \todo The handling of the SS7 FAA message is not good and I
2224  * don't know enough to handle it correctly.
2225  */
2226  chanpos = ss7_find_cic_gripe(linkset, e->faa.cic, e->faa.opc, "FAA");
2227  if (chanpos < 0) {
2228  isup_free_call(ss7, e->faa.call);
2229  break;
2230  }
2231 
2232  /* XXX FAR and FAA used for something dealing with transfers? */
2233  p = linkset->pvts[chanpos];
2234  sig_ss7_lock_private(p);
2235  callid = func_ss7_linkset_callid(linkset, chanpos);
2236  ast_debug(1, "FAA received on CIC %d\n", e->faa.cic);
2237  p->ss7call = isup_free_call_if_clear(ss7, e->faa.call);
2238  sig_ss7_unlock_private(p);
2239  break;
2240  case ISUP_EVENT_CGBA:
2241  chanpos = ss7_find_cic_gripe(linkset, e->cgba.startcic, e->cgba.opc, "CGBA");
2242  if (chanpos < 0) { /* Never will be true */
2243  isup_free_call(ss7, e->cgba.call);
2244  break;
2245  }
2246 
2247  ss7_block_cics(linkset, e->cgba.startcic, e->cgba.endcic,
2248  e->cgba.opc, e->cgba.status, 1, 0,
2249  e->cgba.type ? SS7_BLOCKED_HARDWARE : SS7_BLOCKED_MAINTENANCE);
2250 
2251  p = linkset->pvts[chanpos];
2252  sig_ss7_lock_private(p);
2253  p->ss7call = e->cgba.call;
2254 
2255  if (!p->owner) {
2256  p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
2257  }
2258  sig_ss7_unlock_private(p);
2259  break;
2260  case ISUP_EVENT_CGUA:
2261  chanpos = ss7_find_cic_gripe(linkset, e->cgua.startcic, e->cgua.opc, "CGUA");
2262  if (chanpos < 0) { /* Never will be true */
2263  isup_free_call(ss7, e->cgua.call);
2264  break;
2265  }
2266 
2267  ss7_block_cics(linkset, e->cgua.startcic, e->cgua.endcic,
2268  e->cgua.opc, e->cgua.status, 0, 0,
2269  e->cgba.type ? SS7_BLOCKED_HARDWARE : SS7_BLOCKED_MAINTENANCE);
2270 
2271  p = linkset->pvts[chanpos];
2272  sig_ss7_lock_private(p);
2273  p->ss7call = e->cgua.call;
2274 
2275  if (!p->owner) {
2276  p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
2277  }
2278  sig_ss7_unlock_private(p);
2279  break;
2280  case ISUP_EVENT_SUS:
2281  chanpos = ss7_find_cic_gripe(linkset, e->sus.cic, e->sus.opc, "SUS");
2282  if (chanpos < 0) {
2283  isup_free_call(ss7, e->sus.call);
2284  break;
2285  }
2286 
2287  p = linkset->pvts[chanpos];
2288  sig_ss7_lock_private(p);
2289  p->ss7call = e->sus.call;
2290  if (!p->owner) {
2291  p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
2292  }
2293  sig_ss7_unlock_private(p);
2294  break;
2295  case ISUP_EVENT_RES:
2296  chanpos = ss7_find_cic_gripe(linkset, e->res.cic, e->res.opc, "RES");
2297  if (chanpos < 0) {
2298  isup_free_call(ss7, e->res.call);
2299  break;
2300  }
2301 
2302  p = linkset->pvts[chanpos];
2303  sig_ss7_lock_private(p);
2304  p->ss7call = e->res.call;
2305  if (!p->owner) {
2306  p->ss7call = isup_free_call_if_clear(ss7, p->ss7call);
2307  }
2308  sig_ss7_unlock_private(p);
2309  break;
2310  default:
2311  ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
2312  break;
2313  }
2314 
2315  /* Call ID stuff needs to be cleaned up here */
2316  if (callid) {
2318  }
2319  }
2320  ast_mutex_unlock(&linkset->lock);
2321  }
2322 
2323  return 0;
2324 }
2325 
2326 static void ss7_rel(struct sig_ss7_linkset *ss7)
2327 {
2328  /* Release the lock first */
2329  ast_mutex_unlock(&ss7->lock);
2330 
2331  /* Then break the poll to send our messages */
2332  if (ss7->master != AST_PTHREADT_NULL) {
2333  pthread_kill(ss7->master, SIGURG);
2334  }
2335 }
2336 
2337 static void ss7_grab(struct sig_ss7_chan *pvt, struct sig_ss7_linkset *ss7)
2338 {
2339  /* Grab the lock first */
2340  while (ast_mutex_trylock(&ss7->lock)) {
2341  /* Avoid deadlock */
2342  sig_ss7_deadlock_avoidance_private(pvt);
2343  }
2344 }
2345 
2346 /*!
2347  * \brief Reset a specific CIC.
2348  * \since 11.0
2349  *
2350  * \param linkset linkset control structure.
2351  * \param cic Circuit Identification Code
2352  * \param dpc Destination Point Code
2353  *
2354  * \retval TRUE on success
2355  */
2356 int sig_ss7_reset_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
2357 {
2358  int i;
2359 
2360  ast_mutex_lock(&linkset->lock);
2361  for (i = 0; i < linkset->numchans; i++) {
2362  if (linkset->pvts[i] && linkset->pvts[i]->cic == cic && linkset->pvts[i]->dpc == dpc) {
2363  int res;
2364 
2365  sig_ss7_lock_private(linkset->pvts[i]);
2366  sig_ss7_set_locallyblocked(linkset->pvts[i], 0, SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
2367  res = ss7_start_rsc(linkset, i);
2368  sig_ss7_unlock_private(linkset->pvts[i]);
2369  ss7_rel(linkset); /* Also breaks the poll to send our messages */
2370  return res;
2371  }
2372  }
2373  ss7_rel(linkset);
2374 
2375  return 0;
2376 }
2377 
2378 /*!
2379  * \brief Block or Unblock a specific CIC.
2380  * \since 11.0
2381  *
2382  * \param linkset linkset control structure.
2383  * \param do_block Action to perform. Block if TRUE.
2384  * \param which On which CIC to perform the operation.
2385  *
2386  * \retval 0 on success
2387  */
2388 int sig_ss7_cic_blocking(struct sig_ss7_linkset *linkset, int do_block, int which)
2389 {
2390  ast_mutex_lock(&linkset->lock);
2391  sig_ss7_lock_private(linkset->pvts[which]);
2392  if (!ss7_find_alloc_call(linkset->pvts[which])) {
2393  sig_ss7_unlock_private(linkset->pvts[which]);
2394  ss7_rel(linkset);
2395  return -1;
2396  }
2397 
2398  if (do_block) {
2399  isup_blo(linkset->ss7, linkset->pvts[which]->ss7call);
2400  } else {
2401  isup_ubl(linkset->ss7, linkset->pvts[which]->ss7call);
2402  }
2403 
2404  sig_ss7_unlock_private(linkset->pvts[which]);
2405  ss7_rel(linkset); /* Also breaks the poll to send our messages */
2406 
2407  return 0;
2408 }
2409 
2410 /*!
2411  * \brief Block or Unblock a range of CICs.
2412  * \since 11.0
2413  *
2414  * \param linkset linkset control structure.
2415  * \param do_block Action to perform. Block if TRUE.
2416  * \param chanpos Channel position to start from.
2417  * \param endcic Circuit Identification Code of the end of the range.
2418  * \param state Array of CIC blocking status.
2419  * \param type Type of the blocking - maintenance or hardware
2420  *
2421  * \note Assumes the linkset->lock is already obtained.
2422  *
2423  * \retval 0 on success
2424  */
2425 int sig_ss7_group_blocking(struct sig_ss7_linkset *linkset, int do_block, int chanpos, int endcic, unsigned char state[], int type)
2426 {
2427  sig_ss7_lock_private(linkset->pvts[chanpos]);
2428  if (!ss7_find_alloc_call(linkset->pvts[chanpos])) {
2429  sig_ss7_unlock_private(linkset->pvts[chanpos]);
2430  return -1;
2431  }
2432 
2433  if (do_block) {
2434  isup_cgb(linkset->ss7, linkset->pvts[chanpos]->ss7call, endcic, state, type);
2435  } else {
2436  isup_cgu(linkset->ss7, linkset->pvts[chanpos]->ss7call, endcic, state, type);
2437  }
2438 
2439  sig_ss7_unlock_private(linkset->pvts[chanpos]);
2440  return 0;
2441 }
2442 
2443 /*!
2444  * \brief Reset a group of CICs.
2445  * \since 11.0
2446  *
2447  * \param linkset linkset control structure.
2448  * \param cic Circuit Identification Code
2449  * \param dpc Destination Point Code
2450  * \param range Range of the CICs to reset
2451  *
2452  * \note Assumes the linkset->lock is already obtained.
2453  *
2454  * \retval 0 on success
2455  */
2456 int sig_ss7_reset_group(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc, int range)
2457 {
2458  int i;
2459 
2460  for (i = 0; i < linkset->numchans; i++) {
2461  if (linkset->pvts[i] && linkset->pvts[i]->cic == cic && linkset->pvts[i]->dpc == dpc) {
2462  ss7_clear_channels(linkset, cic, cic + range, dpc, SS7_HANGUP_FREE_CALL);
2463  ss7_block_cics(linkset, cic, cic + range, dpc, NULL, 0, 1,
2464  SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
2465  ss7_block_cics(linkset, cic, cic + range, dpc, NULL, 0, 0,
2466  SS7_BLOCKED_MAINTENANCE | SS7_BLOCKED_HARDWARE);
2467 
2468  sig_ss7_lock_private(linkset->pvts[i]);
2469  if (!ss7_find_alloc_call(linkset->pvts[i])) {
2470  sig_ss7_unlock_private(linkset->pvts[i]);
2471  return -1;
2472  }
2473  isup_grs(linkset->ss7, linkset->pvts[i]->ss7call, linkset->pvts[i]->cic + range);
2474  sig_ss7_unlock_private(linkset->pvts[i]);
2475  break;
2476  }
2477  }
2478  return 0;
2479 }
2480 
2481 void sig_ss7_free_isup_call(struct sig_ss7_linkset *linkset, int channel)
2482 {
2483  sig_ss7_lock_private(linkset->pvts[channel]);
2484  if (linkset->pvts[channel]->ss7call) {
2485  isup_free_call(linkset->ss7, linkset->pvts[channel]->ss7call);
2486  linkset->pvts[channel]->ss7call = NULL;
2487  }
2488  sig_ss7_unlock_private(linkset->pvts[channel]);
2489 }
2490 
2491 static int ss7_parse_prefix(struct sig_ss7_chan *p, const char *number, char *nai)
2492 {
2493  int strip = 0;
2494 
2495  if (strncmp(number, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
2496  strip = strlen(p->ss7->internationalprefix);
2497  *nai = SS7_NAI_INTERNATIONAL;
2498  } else if (strncmp(number, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
2499  strip = strlen(p->ss7->nationalprefix);
2500  *nai = SS7_NAI_NATIONAL;
2501  } else if (strncmp(number, p->ss7->networkroutedprefix, strlen(p->ss7->networkroutedprefix)) == 0) {
2502  strip = strlen(p->ss7->networkroutedprefix);
2503  *nai = SS7_NAI_NETWORKROUTED;
2504  } else if (strncmp(number, p->ss7->unknownprefix, strlen(p->ss7->unknownprefix)) == 0) {
2505  strip = strlen(p->ss7->unknownprefix);
2506  *nai = SS7_NAI_UNKNOWN;
2507  } else if (strncmp(number, p->ss7->subscriberprefix, strlen(p->ss7->subscriberprefix)) == 0) {
2508  strip = strlen(p->ss7->subscriberprefix);
2509  *nai = SS7_NAI_SUBSCRIBER;
2510  } else {
2511  *nai = SS7_NAI_SUBSCRIBER;
2512  }
2513 
2514  return strip;
2515 }
2516 
2517 /*!
2518  * \brief Notify the SS7 layer that the link is in alarm.
2519  * \since 1.8
2520  *
2521  * \param linkset Controlling linkset for the channel.
2522  * \param which Link index of the signaling channel.
2523  */
2524 void sig_ss7_link_alarm(struct sig_ss7_linkset *linkset, int which)
2525 {
2526  linkset->linkstate[which] |= (LINKSTATE_DOWN | LINKSTATE_INALARM);
2527  linkset->linkstate[which] &= ~LINKSTATE_UP;
2528  ss7_link_alarm(linkset->ss7, linkset->fds[which]);
2529 }
2530 
2531 /*!
2532  * \brief Notify the SS7 layer that the link is no longer in alarm.
2533  * \since 1.8
2534  *
2535  * \param linkset Controlling linkset for the channel.
2536  * \param which Link index of the signaling channel.
2537  */
2538 void sig_ss7_link_noalarm(struct sig_ss7_linkset *linkset, int which)
2539 {
2540  linkset->linkstate[which] &= ~(LINKSTATE_INALARM | LINKSTATE_DOWN);
2541  linkset->linkstate[which] |= LINKSTATE_STARTING;
2542  ss7_link_noalarm(linkset->ss7, linkset->fds[which]);
2543 }
2544 
2545 /*!
2546  * \brief Setup and add a SS7 link channel.
2547  * \since 1.8
2548  *
2549  * \param linkset Controlling linkset for the channel.
2550  * \param which Link index of the signaling channel.
2551  * \param ss7type Switch type of the linkset
2552  * \param transport Signaling transport of channel.
2553  * \param inalarm Non-zero if the channel is in alarm.
2554  * \param networkindicator User configuration parameter.
2555  * \param pointcode User configuration parameter.
2556  * \param adjpointcode User configuration parameter.
2557  * \param cur_slc
2558  *
2559  * \retval 0 on success.
2560  * \retval -1 on error.
2561  */
2562 int sig_ss7_add_sigchan(struct sig_ss7_linkset *linkset, int which, int ss7type, int transport, int inalarm, int networkindicator, int pointcode, int adjpointcode, int cur_slc)
2563 {
2564  if (!linkset->ss7) {
2565  linkset->type = ss7type;
2566  linkset->ss7 = ss7_new(ss7type);
2567  if (!linkset->ss7) {
2568  ast_log(LOG_ERROR, "Can't create new SS7!\n");
2569  return -1;
2570  }
2571  }
2572 
2573  ss7_set_network_ind(linkset->ss7, networkindicator);
2574  ss7_set_pc(linkset->ss7, pointcode);
2575 
2576  if (ss7_add_link(linkset->ss7, transport, linkset->fds[which], cur_slc, adjpointcode)) {
2577  ast_log(LOG_WARNING, "Could not add SS7 link!\n");
2578  }
2579 
2580  if (inalarm) {
2581  linkset->linkstate[which] = LINKSTATE_DOWN | LINKSTATE_INALARM;
2582  ss7_link_alarm(linkset->ss7, linkset->fds[which]);
2583  } else {
2584  linkset->linkstate[which] = LINKSTATE_DOWN;
2585  ss7_link_noalarm(linkset->ss7, linkset->fds[which]);
2586  }
2587 
2588  return 0;
2589 }
2590 
2591 /*!
2592  * \brief Determine if the specified channel is available for an outgoing call.
2593  * \since 1.8
2594  *
2595  * \param p Signaling private structure pointer.
2596  *
2597  * \retval TRUE if the channel is available.
2598  */
2599 int sig_ss7_available(struct sig_ss7_chan *p)
2600 {
2601  int available;
2602 
2603  if (!p->ss7) {
2604  /* Something is wrong here. A SS7 channel without the ss7 pointer? */
2605  return 0;
2606  }
2607 
2608  /* Only have to deal with the linkset lock. */
2609  ast_mutex_lock(&p->ss7->lock);
2610  available = sig_ss7_is_chan_available(p);
2611  if (available) {
2612  p->ss7call = isup_new_call(p->ss7->ss7, p->cic, p->dpc, 1);
2613  if (!p->ss7call) {
2614  ast_log(LOG_ERROR, "Unable to allocate new SS7 call!\n");
2615  available = 0;
2616  } else {
2618  }
2619  }
2620  ast_mutex_unlock(&p->ss7->lock);
2621 
2622  return available;
2623 }
2624 
2625 static unsigned char cid_pres2ss7pres(int cid_pres)
2626 {
2627  return (cid_pres >> 5) & 0x03;
2628 }
2629 
2630 static unsigned char cid_pres2ss7screen(int cid_pres)
2631 {
2632  return cid_pres & 0x03;
2633 }
2634 
2635 static void ss7_connected_line_update(struct sig_ss7_chan *p, struct ast_party_connected_line *connected)
2636 {
2637  int connected_strip = 0;
2638  char connected_nai;
2639  unsigned char connected_pres;
2640  unsigned char connected_screen;
2641  const char *connected_num;
2642 
2643  if (!connected->id.number.valid) {
2644  return;
2645  }
2646 
2647  connected_num = S_OR(connected->id.number.str, "");
2648  if (p->ss7->called_nai == SS7_NAI_DYNAMIC) {
2649  connected_strip = ss7_parse_prefix(p, connected_num, &connected_nai);
2650  } else {
2651  connected_nai = p->ss7->called_nai;
2652  }
2653 
2654  connected_pres = cid_pres2ss7pres(connected->id.number.presentation);
2655  connected_screen = cid_pres2ss7screen(connected->id.number.presentation);
2656 
2657  isup_set_connected(p->ss7call, connected_num + connected_strip, connected_nai, connected_pres, connected_screen);
2658 }
2659 
2660 static unsigned char ss7_redirect_reason(struct sig_ss7_chan *p, struct ast_party_redirecting *redirecting, int orig)
2661 {
2662  int reason = (orig) ? redirecting->orig_reason.code : redirecting->reason.code;
2663 
2664  switch (reason) {
2665  case AST_REDIRECTING_REASON_USER_BUSY:
2666  return SS7_REDIRECTING_REASON_USER_BUSY;
2667  case AST_REDIRECTING_REASON_NO_ANSWER:
2668  return SS7_REDIRECTING_REASON_NO_ANSWER;
2669  case AST_REDIRECTING_REASON_UNCONDITIONAL:
2670  return SS7_REDIRECTING_REASON_UNCONDITIONAL;
2671  }
2672 
2673  if (orig || reason == AST_REDIRECTING_REASON_UNKNOWN) {
2674  return SS7_REDIRECTING_REASON_UNKNOWN;
2675  }
2676 
2677  if (reason == AST_REDIRECTING_REASON_UNAVAILABLE) {
2678  return SS7_REDIRECTING_REASON_UNAVAILABLE;
2679  }
2680 
2681  if (reason == AST_REDIRECTING_REASON_DEFLECTION) {
2683  return SS7_REDIRECTING_REASON_DEFLECTION_DURING_ALERTING;
2684  }
2685  return SS7_REDIRECTING_REASON_DEFLECTION_IMMEDIATE_RESPONSE;
2686  }
2687 
2688  return SS7_REDIRECTING_REASON_UNKNOWN;
2689 }
2690 
2691 static unsigned char ss7_redirect_info_ind(struct ast_channel *ast)
2692 {
2693  const char *redirect_info_ind;
2694  struct ast_party_redirecting *redirecting = ast_channel_redirecting(ast);
2695 
2696  redirect_info_ind = pbx_builtin_getvar_helper(ast, "SS7_REDIRECT_INFO_IND");
2697  if (!ast_strlen_zero(redirect_info_ind)) {
2698  if (!strcasecmp(redirect_info_ind, "CALL_REROUTED_PRES_ALLOWED")) {
2699  return SS7_INDICATION_REROUTED_PRES_ALLOWED;
2700  }
2701  if (!strcasecmp(redirect_info_ind, "CALL_REROUTED_INFO_RESTRICTED")) {
2702  return SS7_INDICATION_REROUTED_INFO_RESTRICTED;
2703  }
2704  if (!strcasecmp(redirect_info_ind, "CALL_DIVERTED_PRES_ALLOWED")) {
2705  return SS7_INDICATION_DIVERTED_PRES_ALLOWED;
2706  }
2707  if (!strcasecmp(redirect_info_ind, "CALL_DIVERTED_INFO_RESTRICTED")) {
2708  return SS7_INDICATION_DIVERTED_INFO_RESTRICTED;
2709  }
2710  if (!strcasecmp(redirect_info_ind, "CALL_REROUTED_PRES_RESTRICTED")) {
2711  return SS7_INDICATION_REROUTED_PRES_RESTRICTED;
2712  }
2713  if (!strcasecmp(redirect_info_ind, "CALL_DIVERTED_PRES_RESTRICTED")) {
2714  return SS7_INDICATION_DIVERTED_PRES_RESTRICTED;
2715  }
2716  if (!strcasecmp(redirect_info_ind, "SPARE")) {
2717  return SS7_INDICATION_SPARE;
2718  }
2719  return SS7_INDICATION_NO_REDIRECTION;
2720  }
2721 
2722  if (redirecting->reason.code == AST_REDIRECTING_REASON_DEFLECTION) {
2723  if ((redirecting->to.number.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
2724  if ((redirecting->orig.number.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
2725  return SS7_INDICATION_DIVERTED_PRES_ALLOWED;
2726  }
2727  return SS7_INDICATION_DIVERTED_PRES_RESTRICTED;
2728  }
2729  return SS7_INDICATION_DIVERTED_INFO_RESTRICTED;
2730  }
2731 
2732  if ((redirecting->to.number.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
2733  if ((redirecting->orig.number.presentation & AST_PRES_RESTRICTION) == AST_PRES_ALLOWED) {
2734  return SS7_INDICATION_REROUTED_PRES_ALLOWED;
2735  }
2736  return SS7_INDICATION_REROUTED_PRES_RESTRICTED;
2737  }
2738  return SS7_INDICATION_REROUTED_INFO_RESTRICTED;
2739 }
2740 
2741 static void ss7_redirecting_update(struct sig_ss7_chan *p, struct ast_channel *ast)
2742 {
2743  int num_nai_strip = 0;
2744  struct ast_party_redirecting *redirecting = ast_channel_redirecting(ast);
2745 
2746  if (!redirecting->count) {
2747  return;
2748  }
2749 
2750  isup_set_redirect_counter(p->ss7call, redirecting->count);
2751 
2752  if (redirecting->orig.number.valid) {
2753  char ss7_orig_called_nai = p->ss7->called_nai;
2754  const char *ss7_orig_called_num = S_OR(redirecting->orig.number.str, "");
2755 
2756  if (ss7_orig_called_nai == SS7_NAI_DYNAMIC) {
2757  num_nai_strip = ss7_parse_prefix(p, ss7_orig_called_num, &ss7_orig_called_nai);
2758  } else {
2759  num_nai_strip = 0;
2760  }
2761  isup_set_orig_called_num(p->ss7call, ss7_orig_called_num + num_nai_strip,
2762  ss7_orig_called_nai,
2763  cid_pres2ss7pres(redirecting->orig.number.presentation),
2764  cid_pres2ss7screen(redirecting->orig.number.presentation));
2765  }
2766 
2767  if (redirecting->from.number.valid) {
2768  char ss7_redirecting_num_nai = p->ss7->calling_nai;
2769  const char *redirecting_number = S_OR(redirecting->from.number.str, "");
2770 
2771  if (ss7_redirecting_num_nai == SS7_NAI_DYNAMIC) {
2772  num_nai_strip = ss7_parse_prefix(p, redirecting_number, &ss7_redirecting_num_nai);
2773  } else {
2774  num_nai_strip = 0;
2775  }
2776 
2777  isup_set_redirecting_number(p->ss7call, redirecting_number + num_nai_strip,
2778  ss7_redirecting_num_nai,
2779  cid_pres2ss7pres(redirecting->from.number.presentation),
2780  cid_pres2ss7screen(redirecting->from.number.presentation));
2781  }
2782 
2783  isup_set_redirection_info(p->ss7call, ss7_redirect_info_ind(ast),
2784  ss7_redirect_reason(p, ast_channel_redirecting(ast), 1),
2785  redirecting->count, ss7_redirect_reason(p, ast_channel_redirecting(ast), 0));
2786 }
2787 
2788 /*!
2789  * \brief Dial out using the specified SS7 channel.
2790  * \since 1.8
2791  *
2792  * \param p Signaling private structure pointer.
2793  * \param ast Asterisk channel structure pointer.
2794  * \param rdest Dialstring.
2795  *
2796  * \retval 0 on success.
2797  * \retval -1 on error.
2798  */
2799 int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, const char *rdest)
2800 {
2801  char ss7_called_nai;
2802  int called_nai_strip;
2803  char ss7_calling_nai;
2804  int calling_nai_strip;
2805  const char *col_req = NULL;
2806  const char *ss7_cug_indicator_str;
2807  const char *ss7_cug_interlock_ni;
2808  const char *ss7_cug_interlock_code;
2809  const char *ss7_interworking_indicator;
2810  const char *ss7_forward_indicator_pmbits;
2811  unsigned char ss7_cug_indicator;
2812  const char *charge_str = NULL;
2813  const char *gen_address = NULL;
2814  const char *gen_digits = NULL;
2815  const char *gen_dig_type = NULL;
2816  const char *gen_dig_scheme = NULL;
2817  const char *gen_name = NULL;
2818  const char *jip_digits = NULL;
2819  const char *lspi_ident = NULL;
2820  const char *rlt_flag = NULL;
2821  const char *call_ref_id = NULL;
2822  const char *call_ref_pc = NULL;
2823  const char *send_far = NULL;
2824  const char *tmr = NULL;
2825  char *c;
2826  char *l;
2827  char dest[256];
2828 
2829  ast_copy_string(dest, rdest, sizeof(dest));
2830 
2831  c = strchr(dest, '/');
2832  if (c) {
2833  c++;
2834  } else {
2835  c = "";
2836  }
2837  if (strlen(c) < p->stripmsd) {
2838  ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
2839  return -1;
2840  }
2841 
2842  if (!p->hidecallerid) {
2843  l = ast_channel_connected(ast)->id.number.valid ? ast_channel_connected(ast)->id.number.str : NULL;
2844  } else {
2845  l = NULL;
2846  }
2847 
2848  ss7_grab(p, p->ss7);
2849 
2851  /* Call collision before sending IAM. Abort call. */
2852  ss7_rel(p->ss7);
2853  return -1;
2854  }
2855 
2856  called_nai_strip = 0;
2857  ss7_called_nai = p->ss7->called_nai;
2858  if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
2859  called_nai_strip = ss7_parse_prefix(p, c + p->stripmsd, &ss7_called_nai);
2860  }
2861  isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
2862 
2863  calling_nai_strip = 0;
2864  ss7_calling_nai = p->ss7->calling_nai;
2865  if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
2866  calling_nai_strip = ss7_parse_prefix(p, l, &ss7_calling_nai);
2867  }
2868 
2869  isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
2870  p->use_callingpres ? cid_pres2ss7pres(ast_channel_connected(ast)->id.number.presentation)
2871  : (l ? SS7_PRESENTATION_ALLOWED
2872  : (ast_channel_connected(ast)->id.number.presentation == AST_PRES_UNAVAILABLE
2873  ? SS7_PRESENTATION_ADDR_NOT_AVAILABLE : SS7_PRESENTATION_RESTRICTED)),
2874  p->use_callingpres ? cid_pres2ss7screen(ast_channel_connected(ast)->id.number.presentation) : SS7_SCREENING_USER_PROVIDED);
2875 
2876  isup_set_oli(p->ss7call, ast_channel_connected(ast)->ani2);
2877 
2878  /* Set the charge number if it is set */
2879  charge_str = pbx_builtin_getvar_helper(ast, "SS7_CHARGE_NUMBER");
2880  if (charge_str)
2881  isup_set_charge(p->ss7call, charge_str, SS7_ANI_CALLING_PARTY_SUB_NUMBER, 0x10);
2882 
2883  gen_address = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_ADDRESS");
2884  if (gen_address)
2885  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 */
2886 
2887  gen_digits = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGITS");
2888  gen_dig_type = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGTYPE");
2889  gen_dig_scheme = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_DIGSCHEME");
2890  if (gen_digits)
2891  isup_set_gen_digits(p->ss7call, gen_digits, atoi(gen_dig_type), atoi(gen_dig_scheme));
2892 
2893  gen_name = pbx_builtin_getvar_helper(ast, "SS7_GENERIC_NAME");
2894  if (gen_name)
2895  isup_set_generic_name(p->ss7call, gen_name, GEN_NAME_TYPE_CALLING_NAME, GEN_NAME_AVAIL_AVAILABLE, GEN_NAME_PRES_ALLOWED);
2896 
2897  jip_digits = pbx_builtin_getvar_helper(ast, "SS7_JIP");
2898  if (jip_digits)
2899  isup_set_jip_digits(p->ss7call, jip_digits);
2900 
2901  lspi_ident = pbx_builtin_getvar_helper(ast, "SS7_LSPI_IDENT");
2902  if (lspi_ident)
2903  isup_set_lspi(p->ss7call, lspi_ident, 0x18, 0x7, 0x00);
2904 
2905  rlt_flag = pbx_builtin_getvar_helper(ast, "SS7_RLT_ON");
2906  if ((rlt_flag) && ((strncmp("NO", rlt_flag, strlen(rlt_flag))) != 0 )) {
2907  isup_set_lspi(p->ss7call, rlt_flag, 0x18, 0x7, 0x00); /* Setting for Nortel DMS-250/500 */
2908  }
2909 
2910  call_ref_id = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_IDENT");
2911  call_ref_pc = pbx_builtin_getvar_helper(ast, "SS7_CALLREF_PC");
2912  if (call_ref_id && call_ref_pc) {
2913  isup_set_callref(p->ss7call, atoi(call_ref_id),
2914  call_ref_pc ? atoi(call_ref_pc) : 0);
2915  }
2916 
2917  send_far = pbx_builtin_getvar_helper(ast, "SS7_SEND_FAR");
2918  if (send_far && strncmp("NO", send_far, strlen(send_far)) != 0) {
2919  isup_far(p->ss7->ss7, p->ss7call);
2920  }
2921 
2922  tmr = pbx_builtin_getvar_helper(ast, "SS7_TMR_NUM");
2923  if (tmr) {
2924  isup_set_tmr(p->ss7call, atoi(tmr));
2925  } else if ((tmr = pbx_builtin_getvar_helper(ast, "SS7_TMR")) && tmr[0] != '\0') {
2926  if (!strcasecmp(tmr, "SPEECH")) {
2927  isup_set_tmr(p->ss7call, SS7_TMR_SPEECH);
2928  } else if (!strcasecmp(tmr, "SPARE")) {
2929  isup_set_tmr(p->ss7call, SS7_TMR_SPARE);
2930  } else if (!strcasecmp(tmr, "3K1_AUDIO")) {
2931  isup_set_tmr(p->ss7call, SS7_TMR_3K1_AUDIO);
2932  } else if (!strcasecmp(tmr, "64K_UNRESTRICTED")) {
2933  isup_set_tmr(p->ss7call, SS7_TMR_64K_UNRESTRICTED);
2934  } else {
2935  isup_set_tmr(p->ss7call, SS7_TMR_N64K_OR_SPARE);
2936  }
2937  }
2938 
2939  col_req = pbx_builtin_getvar_helper(ast, "SS7_COL_REQUEST");
2940  if (ast_true(col_req)) {
2941  isup_set_col_req(p->ss7call);
2942  }
2943 
2944  ss7_cug_indicator_str = pbx_builtin_getvar_helper(ast, "SS7_CUG_INDICATOR");
2945  if (!ast_strlen_zero(ss7_cug_indicator_str)) {
2946  if (!strcasecmp(ss7_cug_indicator_str, "OUTGOING_ALLOWED")) {
2947  ss7_cug_indicator = ISUP_CUG_OUTGOING_ALLOWED;
2948  } else if (!strcasecmp(ss7_cug_indicator_str, "OUTGOING_NOT_ALLOWED")) {
2949  ss7_cug_indicator = ISUP_CUG_OUTGOING_NOT_ALLOWED;
2950  } else {
2951  ss7_cug_indicator = ISUP_CUG_NON;
2952  }
2953 
2954  if (ss7_cug_indicator != ISUP_CUG_NON) {
2955  ss7_cug_interlock_code = pbx_builtin_getvar_helper(ast, "SS7_CUG_INTERLOCK_CODE");
2956  ss7_cug_interlock_ni = pbx_builtin_getvar_helper(ast, "SS7_CUG_INTERLOCK_NI");
2957  if (ss7_cug_interlock_code && ss7_cug_interlock_ni && strlen(ss7_cug_interlock_ni) == 4) {
2958  isup_set_cug(p->ss7call, ss7_cug_indicator, ss7_cug_interlock_ni, atoi(ss7_cug_interlock_code));
2959  }
2960  }
2961  }
2962 
2963  ss7_redirecting_update(p, ast);
2964 
2965  isup_set_echocontrol(p->ss7call, (p->ss7->flags & LINKSET_FLAG_DEFAULTECHOCONTROL) ? 1 : 0);
2966  ss7_interworking_indicator = pbx_builtin_getvar_helper(ast, "SS7_INTERWORKING_INDICATOR");
2967  if (ss7_interworking_indicator) {
2968  isup_set_interworking_indicator(p->ss7call, ast_true(ss7_interworking_indicator));
2969  }
2970 
2971  ss7_forward_indicator_pmbits = pbx_builtin_getvar_helper(ast, "SS7_FORWARD_INDICATOR_PMBITS");
2972  if (ss7_forward_indicator_pmbits) {
2973  isup_set_forward_indicator_pmbits(p->ss7call, atoi(ss7_forward_indicator_pmbits));
2974  }
2975 
2977  p->do_hangup = SS7_HANGUP_SEND_REL;
2978  isup_iam(p->ss7->ss7, p->ss7call);
2979  sig_ss7_set_dialing(p, 1);
2981  ss7_rel(p->ss7);
2982  return 0;
2983 }
2984 
2985 /*!
2986  * \brief SS7 hangup channel.
2987  * \since 1.8
2988  *
2989  * \param p Signaling private structure pointer.
2990  * \param ast Asterisk channel structure pointer.
2991  *
2992  * \retval 0 on success.
2993  * \retval -1 on error.
2994  */
2995 int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
2996 {
2997  if (!ast_channel_tech_pvt(ast)) {
2998  ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
2999  return 0;
3000  }
3001 
3002  p->owner = NULL;
3003  sig_ss7_set_dialing(p, 0);
3004  sig_ss7_set_outgoing(p, 0);
3005  p->progress = 0;
3006  p->rlt = 0;
3007  p->exten[0] = '\0';
3008  /* Perform low level hangup if no owner left */
3009  ss7_grab(p, p->ss7);
3011  if (p->ss7call) {
3012  switch (p->do_hangup) {
3013  case SS7_HANGUP_SEND_REL:
3014  {
3015  const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
3016  int icause = ast_channel_hangupcause(ast) ? ast_channel_hangupcause(ast) : -1;
3017 
3018  if (cause) {
3019  if (atoi(cause)) {
3020  icause = atoi(cause);
3021  }
3022  }
3023  if (icause > 255) {
3024  icause = 16;
3025  }
3026 
3027  isup_rel(p->ss7->ss7, p->ss7call, icause);
3028  p->do_hangup = SS7_HANGUP_DO_NOTHING;
3029  }
3030  break;
3031  case SS7_HANGUP_SEND_RSC:
3032  ss7_do_rsc(p);
3033  p->do_hangup = SS7_HANGUP_DO_NOTHING;
3034  break;
3035  case SS7_HANGUP_SEND_RLC:
3036  isup_rlc(p->ss7->ss7, p->ss7call);
3037  p->do_hangup = SS7_HANGUP_DO_NOTHING;
3038  p->ss7call = isup_free_call_if_clear(p->ss7->ss7, p->ss7call);
3039  break;
3040  case SS7_HANGUP_FREE_CALL:
3041  p->do_hangup = SS7_HANGUP_DO_NOTHING;
3042  isup_free_call(p->ss7->ss7, p->ss7call);
3043  p->ss7call = NULL;
3044  break;
3045  case SS7_HANGUP_REEVENT_IAM:
3046  isup_event_iam(p->ss7->ss7, p->ss7call, p->dpc);
3047  p->do_hangup = SS7_HANGUP_SEND_REL;
3048  break;
3049  case SS7_HANGUP_DO_NOTHING:
3050  p->ss7call = isup_free_call_if_clear(p->ss7->ss7, p->ss7call);
3051  break;
3052  }
3053  }
3054  ss7_rel(p->ss7);
3055 
3056  return 0;
3057 }
3058 
3059 /*!
3060  * \brief SS7 answer channel.
3061  * \since 1.8
3062  *
3063  * \param p Signaling private structure pointer.
3064  * \param ast Asterisk channel structure pointer.
3065  *
3066  * \retval 0 on success.
3067  * \retval -1 on error.
3068  */
3069 int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
3070 {
3071  int res;
3072 
3073  ss7_grab(p, p->ss7);
3075  if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING && (p->ss7->flags & LINKSET_FLAG_AUTOACM)) {
3076  isup_acm(p->ss7->ss7, p->ss7call);
3077  }
3079  }
3080 
3081  res = isup_anm(p->ss7->ss7, p->ss7call);
3082  sig_ss7_open_media(p);
3083  ss7_rel(p->ss7);
3084  return res;
3085 }
3086 
3087 /*!
3088  * \brief Fix up a channel: If a channel is consumed, this is called. Basically update any ->owner links.
3089  * \since 1.8
3090  *
3091  * \param oldchan Old channel pointer to replace.
3092  * \param newchan New channel pointer to set.
3093  * \param pchan Signaling private structure pointer.
3094  */
3095 void sig_ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan)
3096 {
3097  if (pchan->owner == oldchan) {
3098  pchan->owner = newchan;
3099  }
3100 }
3101 
3102 /*!
3103  * \brief SS7 indication.
3104  * \since 1.8
3105  *
3106  * \param p Signaling private structure pointer.
3107  * \param chan Asterisk channel structure pointer.
3108  * \param condition AST control frame subtype.
3109  * \param data AST control frame payload contents.
3110  * \param datalen Length of payload contents.
3111  *
3112  * \retval 0 on success.
3113  * \retval -1 on error or indication condition not handled.
3114  */
3115 int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
3116 {
3117  int res = -1;
3118 
3119  switch (condition) {
3120  case AST_CONTROL_BUSY:
3122  ast_channel_hangupcause_set(chan, AST_CAUSE_USER_BUSY);
3124  res = 0;
3125  break;
3126  }
3127  res = sig_ss7_play_tone(p, SIG_SS7_TONE_BUSY);
3128  break;
3129  case AST_CONTROL_RINGING:
3130  ss7_grab(p, p->ss7);
3132  if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) {
3133  p->rlt = 1;
3134  }
3135 
3136  if (p->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING && (p->ss7->flags & LINKSET_FLAG_AUTOACM)) {
3137  isup_acm(p->ss7->ss7, p->ss7call);
3138  }
3139 
3140  /* No need to send CPG if call will be RELEASE */
3141  if (p->rlt != 1) {
3142  isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
3143  }
3144 
3146  }
3147  ss7_rel(p->ss7);
3148 
3149  res = sig_ss7_play_tone(p, SIG_SS7_TONE_RINGTONE);
3150 
3153  }
3154  break;
3156  ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",ast_channel_name(chan));
3157  ss7_grab(p, p->ss7);
3158  /* This IF sends the FAR for an answered ALEG call */
3159  if (ast_channel_state(chan) == AST_STATE_UP && (p->rlt != 1)){
3160  if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) {
3161  p->rlt = 1;
3162  }
3163  }
3164 
3167  isup_acm(p->ss7->ss7, p->ss7call);
3168  }
3169  ss7_rel(p->ss7);
3170  /* don't continue in ast_indicate */
3171  res = 0;
3172  break;
3173  case AST_CONTROL_PROGRESS:
3174  ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",ast_channel_name(chan));
3175  ss7_grab(p, p->ss7);
3176  if (!p->progress && p->call_level < SIG_SS7_CALL_LEVEL_ALERTING && !p->outgoing) {
3177  p->progress = 1; /* No need to send inband-information progress again. */
3178  isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
3179 
3180  /* enable echo canceler here on SS7 calls */
3181  if (!p->echocontrol_ind || !(p->ss7->flags & LINKSET_FLAG_USEECHOCONTROL)) {
3182  sig_ss7_set_echocanceller(p, 1);
3183  }
3184  }
3185  ss7_rel(p->ss7);
3186  /* don't continue in ast_indicate */
3187  res = 0;
3188  break;
3191  ast_channel_hangupcause_set(chan, AST_CAUSE_INVALID_NUMBER_FORMAT);
3193  res = 0;
3194  break;
3195  }
3196  /* Wait for DTMF digits to complete the dialed number. */
3197  res = 0;
3198  break;
3201  ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
3203  res = 0;
3204  break;
3205  }
3206  res = sig_ss7_play_tone(p, SIG_SS7_TONE_CONGESTION);
3207  break;
3208  case AST_CONTROL_HOLD:
3209  ast_moh_start(chan, data, p->mohinterpret);
3210  break;
3211  case AST_CONTROL_UNHOLD:
3212  ast_moh_stop(chan);
3213  break;
3214  case AST_CONTROL_SRCUPDATE:
3215  res = 0;
3216  break;
3218  ss7_connected_line_update(p, ast_channel_connected(chan));
3219  res = 0;
3220  break;
3222  ss7_redirecting_update(p, chan);
3223  res = 0;
3224  break;
3225  case -1:
3226  res = sig_ss7_play_tone(p, -1);
3227  break;
3228  }
3229  return res;
3230 }
3231 
3232 /*!
3233  * \brief SS7 channel request.
3234  * \since 1.8
3235  *
3236  * \param p Signaling private structure pointer.
3237  * \param law Companding law preferred
3238  * \param requestor Asterisk channel requesting a channel to dial (Can be NULL)
3239  * \param assignedids, transfercapability
3240  *
3241  * \retval ast_channel on success.
3242  * \retval NULL on error.
3243  */
3244 struct ast_channel *sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law,
3245  const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor,
3246  int transfercapability)
3247 {
3248  struct ast_channel *ast;
3249 
3250  /* Companding law is determined by SS7 signaling type. */
3251  if (p->ss7->type == SS7_ITU) {
3252  law = SIG_SS7_ALAW;
3253  } else {
3254  law = SIG_SS7_ULAW;
3255  }
3256 
3257  sig_ss7_set_outgoing(p, 1);
3258  ast = sig_ss7_new_ast_channel(p, AST_STATE_RESERVED, law, transfercapability,
3259  p->exten, assignedids, requestor);
3260  if (!ast) {
3261  sig_ss7_set_outgoing(p, 0);
3262 
3263  /* Release the allocated channel. Only have to deal with the linkset lock. */
3264  ast_mutex_lock(&p->ss7->lock);
3266  isup_free_call(p->ss7->ss7, p->ss7call);
3267  ast_mutex_unlock(&p->ss7->lock);
3268  }
3269  return ast;
3270 }
3271 
3272 /*!
3273  * \brief Delete the sig_ss7 private channel structure.
3274  * \since 1.8
3275  *
3276  * \param doomed sig_ss7 private channel structure to delete.
3277  */
3278 void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
3279 {
3280  ast_free(doomed);
3281 }
3282 
3283 #define SIG_SS7_SC_HEADER "%-4s %4s %-4s %-3s %-3s %-10s %-4s %s\n"
3284 #define SIG_SS7_SC_LINE "%4d %4d %-4s %-3s %-3s %-10s %-4s %s"
3285 void sig_ss7_cli_show_channels_header(int fd)
3286 {
3287  ast_cli(fd, SIG_SS7_SC_HEADER, "link", "", "Chan", "Lcl", "Rem", "Call", "SS7", "Channel");
3288  ast_cli(fd, SIG_SS7_SC_HEADER, "set", "Chan", "Idle", "Blk", "Blk", "Level", "Call", "Name");
3289 }
3290 
3291 void sig_ss7_cli_show_channels(int fd, struct sig_ss7_linkset *linkset)
3292 {
3293  char line[256];
3294  int idx;
3295  struct sig_ss7_chan *pvt;
3296 
3297  ast_mutex_lock(&linkset->lock);
3298  for (idx = 0; idx < linkset->numchans; ++idx) {
3299  if (!linkset->pvts[idx]) {
3300  continue;
3301  }
3302  pvt = linkset->pvts[idx];
3303  sig_ss7_lock_private(pvt);
3304  sig_ss7_lock_owner(linkset, idx);
3305 
3306  snprintf(line, sizeof(line), SIG_SS7_SC_LINE,
3307  linkset->span,
3308  pvt->channel,
3309  sig_ss7_is_chan_available(pvt) ? "Yes" : "No",
3310  pvt->locallyblocked ? "Yes" : "No",
3311  pvt->remotelyblocked ? "Yes" : "No",
3312  sig_ss7_call_level2str(pvt->call_level),
3313  pvt->ss7call ? "Yes" : "No",
3314  pvt->owner ? ast_channel_name(pvt->owner) : "");
3315 
3316  if (pvt->owner) {
3317  ast_channel_unlock(pvt->owner);
3318  }
3319  sig_ss7_unlock_private(pvt);
3320 
3321  ast_mutex_unlock(&linkset->lock);
3322  ast_cli(fd, "%s\n", line);
3323  ast_mutex_lock(&linkset->lock);
3324  }
3325  ast_mutex_unlock(&linkset->lock);
3326 }
3327 
3328 /*!
3329  * \brief Create a new sig_ss7 private channel structure.
3330  * \since 1.8
3331  *
3332  * \param pvt_data Upper layer private data structure.
3333  * \param ss7 Controlling linkset for the channel.
3334  *
3335  * \retval sig_ss7_chan on success.
3336  * \retval NULL on error.
3337  */
3338 struct sig_ss7_chan *sig_ss7_chan_new(void *pvt_data, struct sig_ss7_linkset *ss7)
3339 {
3340  struct sig_ss7_chan *pvt;
3341 
3342  pvt = ast_calloc(1, sizeof(*pvt));
3343  if (!pvt) {
3344  return pvt;
3345  }
3346 
3347  pvt->chan_pvt = pvt_data;
3348  pvt->ss7 = ss7;
3349 
3350  return pvt;
3351 }
3352 
3353 /*!
3354  * \brief Initialize the SS7 linkset control.
3355  * \since 1.8
3356  *
3357  * \param ss7 SS7 linkset control structure.
3358  */
3359 void sig_ss7_init_linkset(struct sig_ss7_linkset *ss7)
3360 {
3361  int idx;
3362 
3363  memset(ss7, 0, sizeof(*ss7));
3364 
3365  ast_mutex_init(&ss7->lock);
3366 
3367  ss7->master = AST_PTHREADT_NULL;
3368  for (idx = 0; idx < ARRAY_LEN(ss7->fds); ++idx) {
3369  ss7->fds[idx] = -1;
3370  }
3371 }
3372 
3373 /* ------------------------------------------------------------------- */
3374 
3375 #endif /* defined(HAVE_SS7) */
3376 /* end sig_ss7.c */
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2022
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
Definition: pbx.c:4195
Main Channel structure associated with a channel.
Music on hold handling.
char calling_nai
Definition: sig_ss7.h:338
char * str
Subscriber phone number (Malloced)
Definition: channel.h:291
General Asterisk channel transcoding definitions.
int cid_ton
Definition: sig_ss7.h:242
enum sig_ss7_call_level call_level
Definition: sig_ss7.h:198
Asterisk main include file. File version handling, generic pbx functions.
char chan_name[AST_CHANNEL_NAME]
unsigned int outgoing
TRUE if this channel is being used for an outgoing call.
Definition: sig_ss7.h:292
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:295
unsigned int dpc
Definition: sig_ss7.h:202
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
struct ast_party_id id
Connected party ID.
Definition: channel.h:458
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: sig_ss7.h:213
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:527
void ast_channel_update_redirecting(struct ast_channel *chan, const struct ast_party_redirecting *redirecting, const struct ast_set_party_redirecting *update)
Indicate that the redirecting id has changed.
Definition: channel.c:10284
sig_ss7_call_level
Definition: sig_ss7.h:116
char unknownprefix[20]
Definition: sig_ss7.h:342
unsigned char cug_indicator
Indication of the call being a CUG call and its permissions.
Definition: sig_ss7.h:315
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708
char cug_interlock_ni[5]
Network Identify Code as per Q.763 3.15.a.
Definition: sig_ss7.h:306
unsigned short cug_interlock_code
Binari Code to uniquely identify a CUG inside the network.
Definition: sig_ss7.h:308
int callingpres
Definition: sig_ss7.h:243
int channel
Definition: sig_ss7.h:200
unsigned int loopedback
TRUE if this channel is in loopback.
Definition: sig_ss7.h:300
void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
Copy the source party id information to the destination party id.
Definition: channel.c:1765
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:604
struct sig_ss7_callback sig_ss7_callbacks
Interface header for SS7 signaling module.
ast_channel_state
ast_channel states
Definition: channelstate.h:35
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:2320
unsigned int inalarm
TRUE if channel is associated with a link that is down.
Definition: sig_ss7.h:288
pthread_t master
Definition: sig_ss7.h:319
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
unsigned short transfercapability
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2072
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7776
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:510
char cid_subaddr[AST_MAX_EXTENSION]
Definition: sig_ss7.h:245
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
struct ast_frame_subclass subclass
struct ast_party_id orig
Who originally redirected the call (Sent to the party the call is redirected toward) ...
Definition: channel.h:524
unsigned int use_callingpres
TRUE if we will use the calling presentation setting from the Asterisk channel for outgoing calls...
Definition: sig_ss7.h:220
Number structure.
Definition: app_followme.c:154
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked.
Definition: sig_ss7.h:235
ast_mutex_t lock
Definition: sig_ss7.h:320
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
Definition: logger.c:2339
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: sig_ss7.h:215
unsigned int progress
TRUE if the call has seen inband-information progress through the network.
Definition: sig_ss7.h:296
ast_mutex_t lock
void ast_channel_queue_connected_line_update(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Queue a connected line update frame on a channel.
Definition: channel.c:9106
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: sig_ss7.h:209
struct ast_party_redirecting_reason orig_reason
Reason for the redirection by the original party.
Definition: channel.h:545
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_callid_threadstorage_auto_clean(ast_callid callid, int callid_created)
Use in conjunction with ast_callid_threadstorage_auto. Cleans up the references and if the callid was...
Definition: logger.c:2378
#define AST_MAX_EXTENSION
Definition: channel.h:134
Caller Party information.
Definition: channel.h:418
void * chan_pvt
Definition: sig_ss7.h:190
#define ast_debug(level,...)
Log a DEBUG message.
unsigned int inservice
TRUE if channel is in service.
Definition: sig_ss7.h:290
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:4175
char subscriberprefix[20]
Definition: sig_ss7.h:341
int cid_ani2
Definition: sig_ss7.h:241
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's frame queue.
Definition: channel.c:1139
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
struct sig_ss7_chan * pvts[SIG_SS7_MAX_CHANNELS]
Definition: sig_ss7.h:322
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: utils.c:2199
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
Connected Line/Party information.
Definition: channel.h:456
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:7766
Redirecting Line information. RDNIS (Redirecting Directory Number Information Service) Where a call d...
Definition: channel.h:522
unsigned int rlt
XXX BOOLEAN Purpose???
Definition: sig_ss7.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_CHANNEL_NAME
Definition: channel.h:171
char called_nai
Definition: sig_ss7.h:337
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
#define SIG_SS7_DEBUG_DEFAULT
Definition: sig_ss7.h:51
struct ast_party_redirecting_reason reason
Reason for the redirection.
Definition: channel.h:542
char nationalprefix[10]
Definition: sig_ss7.h:340
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...
int ast_callid_threadstorage_auto(ast_callid *callid)
Checks thread storage for a callid and stores a reference if it exists. If not, then a new one will b...
Definition: logger.c:2356
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: sig_ss7.h:228
unsigned int immediate
Definition: sig_ss7.h:221
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
Definition: channel.c:2179
int count
Number of times the call was redirected.
Definition: channel.h:548
Standard Command Line Interface.
struct ast_party_id to
Call is redirecting to a new party (Sent to the caller)
Definition: channel.h:530
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:80
void ast_party_redirecting_init(struct ast_party_redirecting *init)
Initialize the given redirecting structure.
Definition: channel.c:2122
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7386
char * ast_transfercapability2str(int transfercapability) attribute_const
Gives the string form of a given transfer capability.
Definition: channel.c:672
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame with payload.
Definition: channel.c:1238
Data structure associated with a single frame of data.
Internal Asterisk hangup causes.
char internationalprefix[10]
Definition: sig_ss7.h:339
unsigned int called_complete
TRUE if the channel has completed collecting digits.
Definition: sig_ss7.h:294
struct isup_call * ss7call
Opaque libss7 call control structure.
Definition: sig_ss7.h:195
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
void ast_party_caller_init(struct ast_party_caller *init)
Initialize the given caller structure.
Definition: channel.c:1978
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:297
void ast_channel_hangupcause_hash_set(struct ast_channel *chan, const struct ast_control_pvt_cause_code *cause_code, int datalen)
Sets the HANGUPCAUSE hash and optionally the SIP_CAUSE hash on the given channel. ...
Definition: channel.c:4346
char exten[AST_MAX_EXTENSION]
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:342