Asterisk - The Open Source Telephony Project GIT-master-a358458
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"
43#include "asterisk/cli.h"
44#include "asterisk/callerid.h"
45#include "asterisk/transcap.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
57static 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
78static void sig_ss7_unlock_private(struct sig_ss7_chan *p)
79{
82 }
83}
84
85static void sig_ss7_lock_private(struct sig_ss7_chan *p)
86{
89 }
90}
91
92static void sig_ss7_deadlock_avoidance_private(struct sig_ss7_chan *p)
93{
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
104void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
105{
106 p->inalarm = in_alarm;
109 }
110}
111
112static void sig_ss7_set_dialing(struct sig_ss7_chan *p, int is_dialing)
113{
115 sig_ss7_callbacks.set_dialing(p->chan_pvt, is_dialing);
116 }
117}
118
119static void sig_ss7_set_digital(struct sig_ss7_chan *p, int is_digital)
120{
122 sig_ss7_callbacks.set_digital(p->chan_pvt, is_digital);
123 }
124}
125
126static void sig_ss7_set_outgoing(struct sig_ss7_chan *p, int is_outgoing)
127{
128 p->outgoing = is_outgoing;
130 sig_ss7_callbacks.set_outgoing(p->chan_pvt, is_outgoing);
131 }
132}
133
134static void sig_ss7_set_inservice(struct sig_ss7_chan *p, int is_inservice)
135{
136 p->inservice = is_inservice;
138 sig_ss7_callbacks.set_inservice(p->chan_pvt, is_inservice);
139 }
140}
141
142static 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
152 }
153}
154
155static 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
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 */
175static void sig_ss7_open_media(struct sig_ss7_chan *p)
176{
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 */
189static void sig_ss7_set_caller_id(struct sig_ss7_chan *p)
190{
191 struct ast_party_caller caller;
192
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;
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 */
230static void sig_ss7_set_dnid(struct sig_ss7_chan *p, const char *dnid)
231{
234 }
235}
236
237static int sig_ss7_play_tone(struct sig_ss7_chan *p, enum sig_ss7_tone tone)
238{
239 int res;
240
242 res = sig_ss7_callbacks.play_tone(p->chan_pvt, tone);
243 } else {
244 res = -1;
245 }
246 return res;
247}
248
249static int sig_ss7_set_echocanceller(struct sig_ss7_chan *p, int enable)
250{
253 }
254 return -1;
255}
256
257static void sig_ss7_loopback(struct sig_ss7_chan *p, int enable)
258{
259 if (p->loopedback != enable) {
260 p->loopedback = enable;
263 }
264 }
265}
266
267static 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
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
294 pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY",
297 sig_ss7_set_digital(p, 1);
298 }
299
300 return ast;
301}
302
303static void sig_ss7_handle_link_exception(struct sig_ss7_linkset *linkset, int which)
304{
307 }
308}
309
310static struct sig_ss7_linkset *sig_ss7_find_linkset(struct ss7 *ss7)
311{
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 */
326static 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 */
347static 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 */
378static 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 */
399static 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
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 */
425static 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;
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 */
450int 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 */
475static 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
488static 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
500int 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) {
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
523void 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) {
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
550void 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 */
574static 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
585static 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 */
608int 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
625static 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
679static 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) {
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 */
709static 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
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 */
754static 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
767static 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 */
790static 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 */
844static 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
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 */
872static 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) {
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 */
913static 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) {
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 */
947static 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);
988 return;
989 }
990
991 /* Hold the channel and private lock while we setup the channel. */
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 }
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 }
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;
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) {
1120 redirecting.orig_reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1121 break;
1123 redirecting.orig_reason.code = AST_REDIRECTING_REASON_USER_BUSY;
1124 break;
1126 redirecting.orig_reason.code = AST_REDIRECTING_REASON_NO_ANSWER;
1127 break;
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) {
1138 redirecting.reason.code = AST_REDIRECTING_REASON_UNKNOWN;
1139 break;
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;
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;
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;
1160 redirecting.reason.code = AST_REDIRECTING_REASON_DEFLECTION;
1161 break;
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 */
1171 p->redirect_info_reas = 0;
1172
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
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
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);
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
1248static 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
1278static 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 */
1297static 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 */
1325static 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. */
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. */
1355void *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) {
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;
1502 ast_party_connected_line_free(&ast_connected);
1503 }
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
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 */
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
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
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) {
1614 && linkset->pvts[i]->call_level < SIG_SS7_CALL_LEVEL_PROCEEDING) {
1615 ast_channel_hangupcause_set(p->owner, SS7_CAUSE_TRY_AGAIN);
1616 } else {
1618 }
1619 p->do_hangup = SS7_HANGUP_FREE_CALL;
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);
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 */
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;
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;
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) {
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,
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,
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) {
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 }
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;
2179 ast_party_connected_line_free(&ast_connected);
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;
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,
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,
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
2326static 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
2337static 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 */
2356int 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 */
2388int 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 */
2425int 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 */
2456int 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,
2465 ss7_block_cics(linkset, cic, cic + range, dpc, NULL, 0, 0,
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
2481void 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
2491static 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 */
2524void 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 */
2538void 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 */
2562int 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 */
2599int 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 }
2621
2622 return available;
2623}
2624
2625static unsigned char cid_pres2ss7pres(int cid_pres)
2626{
2627 return (cid_pres >> 5) & 0x03;
2628}
2629
2630static unsigned char cid_pres2ss7screen(int cid_pres)
2631{
2632 return cid_pres & 0x03;
2633}
2634
2635static 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
2660static 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) {
2671 }
2672
2673 if (orig || reason == AST_REDIRECTING_REASON_UNKNOWN) {
2675 }
2676
2677 if (reason == AST_REDIRECTING_REASON_UNAVAILABLE) {
2679 }
2680
2681 if (reason == AST_REDIRECTING_REASON_DEFLECTION) {
2684 }
2686 }
2687
2689}
2690
2691static 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")) {
2700 }
2701 if (!strcasecmp(redirect_info_ind, "CALL_REROUTED_INFO_RESTRICTED")) {
2703 }
2704 if (!strcasecmp(redirect_info_ind, "CALL_DIVERTED_PRES_ALLOWED")) {
2706 }
2707 if (!strcasecmp(redirect_info_ind, "CALL_DIVERTED_INFO_RESTRICTED")) {
2709 }
2710 if (!strcasecmp(redirect_info_ind, "CALL_REROUTED_PRES_RESTRICTED")) {
2712 }
2713 if (!strcasecmp(redirect_info_ind, "CALL_DIVERTED_PRES_RESTRICTED")) {
2715 }
2716 if (!strcasecmp(redirect_info_ind, "SPARE")) {
2717 return SS7_INDICATION_SPARE;
2718 }
2720 }
2721
2722 if (redirecting->reason.code == AST_REDIRECTING_REASON_DEFLECTION) {
2726 }
2728 }
2730 }
2731
2735 }
2737 }
2739}
2740
2741static 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 */
2799int 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) {
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 */
2995int 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 */
3069int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
3070{
3071 int res;
3072
3073 ss7_grab(p, p->ss7);
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 */
3095void 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 */
3115int 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:
3124 res = 0;
3125 break;
3126 }
3127 res = sig_ss7_play_tone(p, SIG_SS7_TONE_BUSY);
3128 break;
3130 ss7_grab(p, p->ss7);
3132 if ((isup_far(p->ss7->ss7, p->ss7call)) != -1) {
3133 p->rlt = 1;
3134 }
3135
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;
3174 ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",ast_channel_name(chan));
3175 ss7_grab(p, p->ss7);
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 */
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;
3193 res = 0;
3194 break;
3195 }
3196 /* Wait for DTMF digits to complete the dialed number. */
3197 res = 0;
3198 break;
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;
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 */
3244struct 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,
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);
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 */
3278void 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"
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
3291void 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) {
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 */
3338struct 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 */
3360{
3361 int idx;
3362
3363 memset(ss7, 0, sizeof(*ss7));
3364
3366
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 */
jack_status_t status
Definition: app_jack.c:146
ast_mutex_t lock
Definition: app_sla.c:331
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
static int tmp()
Definition: bt_open.c:389
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
#define AST_PRES_UNAVAILABLE
Definition: callerid.h:420
#define AST_PRES_ALLOWED
Definition: callerid.h:418
@ AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER
Definition: callerid.h:540
@ AST_REDIRECTING_REASON_UNKNOWN
Definition: callerid.h:485
@ AST_REDIRECTING_REASON_NO_ANSWER
Definition: callerid.h:487
@ AST_REDIRECTING_REASON_DEFLECTION
Definition: callerid.h:492
@ AST_REDIRECTING_REASON_UNAVAILABLE
Definition: callerid.h:488
@ AST_REDIRECTING_REASON_UNCONDITIONAL
Definition: callerid.h:489
@ AST_REDIRECTING_REASON_USER_BUSY
Definition: callerid.h:486
#define AST_PRES_RESTRICTION
Definition: callerid.h:417
Internal Asterisk hangup causes.
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:123
#define AST_CAUSE_CONGESTION
Definition: causes.h:153
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:98
#define AST_CAUSE_INTERWORKING
Definition: causes.h:146
#define AST_CAUSE_INVALID_NUMBER_FORMAT
Definition: causes.h:116
#define AST_CAUSE_NORMAL_TEMPORARY_FAILURE
Definition: causes.h:122
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition: causes.h:120
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:106
#define AST_CAUSE_USER_BUSY
Definition: causes.h:107
static int available(struct dahdi_pvt **pvt, int is_specific_channel)
Definition: chan_dahdi.c:13460
static const char type[]
Definition: chan_ooh323.c:109
static int call(void *data)
Definition: chan_pjsip.c:2391
const char * ast_channel_name(const struct ast_channel *chan)
char * ast_transfercapability2str(int transfercapability) attribute_const
Gives the string form of a given transfer capability.
Definition: channel.c:672
void ast_party_redirecting_init(struct ast_party_redirecting *init)
Initialize the given redirecting structure.
Definition: channel.c:2122
void * ast_channel_tech_pvt(const struct ast_channel *chan)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2072
#define ast_channel_lock(chan)
Definition: channel.h:2922
struct ast_party_redirecting * ast_channel_redirecting(struct ast_channel *chan)
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
ast_callid ast_channel_callid(const struct ast_channel *chan)
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_channel_trylock(chan)
Definition: channel.h:2924
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
int ast_channel_hangupcause(const struct ast_channel *chan)
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
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
#define AST_CHANNEL_NAME
Definition: channel.h:171
void ast_channel_softhangup_internal_flag_add(struct ast_channel *chan, int value)
@ AST_SOFTHANGUP_DEV
Definition: channel.h:1121
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
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2022
void ast_party_redirecting_free(struct ast_party_redirecting *doomed)
Destroy the redirecting information contents.
Definition: channel.c:2179
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
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
void ast_channel_transfercapability_set(struct ast_channel *chan, unsigned short value)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
#define AST_MAX_EXTENSION
Definition: channel.h:134
void ast_party_caller_init(struct ast_party_caller *init)
Initialize the given caller structure.
Definition: channel.c:1978
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RING
Definition: channelstate.h:40
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_DIALING
Definition: channelstate.h:39
@ AST_STATE_UP
Definition: channelstate.h:42
@ AST_STATE_RESERVED
Definition: channelstate.h:37
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7386
Standard Command Line Interface.
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static struct ast_codec ulaw
char connected
Definition: eagi_proxy.c:82
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
@ AST_FRAME_CONTROL
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_BUSY
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_REDIRECTING
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HOLD
@ AST_CONTROL_CONNECTED_LINE
@ AST_CONTROL_INCOMPLETE
@ AST_CONTROL_PVT_CAUSE_CODE
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:2366
#define ast_debug(level,...)
Log a DEBUG message.
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:2308
unsigned int ast_callid
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
Definition: logger.c:2327
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:2344
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_NOTICE
#define LOG_WARNING
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_mutex_init(pmutex)
Definition: lock.h:186
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:479
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_trylock(a)
Definition: lock.h:191
#define ast_mutex_lock(a)
Definition: lock.h:189
int errno
Music on hold handling.
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
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7776
Core PBX routines and definitions.
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
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
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.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708
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
#define NULL
Definition: resample.c:96
Interface header for SS7 signaling module.
void sig_ss7_cb_call_null(struct ss7 *ss7, struct isup_call *c, int lock)
void sig_ss7_link_noalarm(struct sig_ss7_linkset *linkset, int which)
#define LINKSTATE_INALARM
Definition: sig_ss7.h:61
void sig_ss7_cli_show_channels_header(int fd)
#define SIG_SS7_DEBUG_DEFAULT
Definition: sig_ss7.h:51
struct ast_channel * sig_ss7_request(struct sig_ss7_chan *p, enum sig_ss7_law law, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, int transfercapability)
void sig_ss7_init_linkset(struct sig_ss7_linkset *ss7)
void sig_ss7_link_alarm(struct sig_ss7_linkset *linkset, int which)
#define LINKSET_FLAG_EXPLICITACM
Definition: sig_ss7.h:68
#define LINKSET_FLAG_AUTOACM
Definition: sig_ss7.h:72
int sig_ss7_reset_group(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc, int range)
int sig_ss7_available(struct sig_ss7_chan *p)
void sig_ss7_cb_notinservice(struct ss7 *ss7, int cic, unsigned int dpc)
@ SS7_INDICATION_SPARE
Definition: sig_ss7.h:102
@ SS7_INDICATION_DIVERTED_PRES_ALLOWED
Definition: sig_ss7.h:98
@ SS7_INDICATION_REROUTED_PRES_RESTRICTED
Definition: sig_ss7.h:100
@ SS7_INDICATION_NO_REDIRECTION
Definition: sig_ss7.h:95
@ SS7_INDICATION_DIVERTED_INFO_RESTRICTED
Definition: sig_ss7.h:99
@ SS7_INDICATION_REROUTED_INFO_RESTRICTED
Definition: sig_ss7.h:97
@ SS7_INDICATION_DIVERTED_PRES_RESTRICTED
Definition: sig_ss7.h:101
@ SS7_INDICATION_REROUTED_PRES_ALLOWED
Definition: sig_ss7.h:96
int sig_ss7_reset_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
int sig_ss7_call(struct sig_ss7_chan *p, struct ast_channel *ast, const char *rdest)
void * ss7_linkset(void *data)
int sig_ss7_indicate(struct sig_ss7_chan *p, struct ast_channel *chan, int condition, const void *data, size_t datalen)
#define SS7_BLOCKED_MAINTENANCE
Definition: sig_ss7.h:74
int sig_ss7_group_blocking(struct sig_ss7_linkset *linkset, int do_block, int startcic, int endcic, unsigned char state[], int type)
int sig_ss7_find_cic(struct sig_ss7_linkset *linkset, int cic, unsigned int dpc)
void sig_ss7_free_isup_call(struct sig_ss7_linkset *linkset, int channel)
struct sig_ss7_callback sig_ss7_callbacks
void sig_ss7_set_alarm(struct sig_ss7_chan *p, int in_alarm)
sig_ss7_tone
Definition: sig_ss7.h:78
@ SIG_SS7_TONE_RINGTONE
Definition: sig_ss7.h:79
@ SIG_SS7_TONE_CONGESTION
Definition: sig_ss7.h:81
@ SIG_SS7_TONE_BUSY
Definition: sig_ss7.h:85
struct sig_ss7_chan * sig_ss7_chan_new(void *pvt_data, struct sig_ss7_linkset *ss7)
void sig_ss7_cli_show_channels(int fd, struct sig_ss7_linkset *linkset)
sig_ss7_call_level
Definition: sig_ss7.h:116
@ SIG_SS7_CALL_LEVEL_PROCEEDING
Definition: sig_ss7.h:138
@ SIG_SS7_CALL_LEVEL_IDLE
Definition: sig_ss7.h:118
@ SIG_SS7_CALL_LEVEL_SETUP
Definition: sig_ss7.h:133
@ SIG_SS7_CALL_LEVEL_CONNECT
Definition: sig_ss7.h:148
@ SIG_SS7_CALL_LEVEL_ALLOCATED
Definition: sig_ss7.h:123
@ SIG_SS7_CALL_LEVEL_ALERTING
Definition: sig_ss7.h:143
@ SIG_SS7_CALL_LEVEL_CONTINUITY
Definition: sig_ss7.h:128
int sig_ss7_cic_blocking(struct sig_ss7_linkset *linkset, int do_block, int cic)
#define LINKSTATE_DOWN
Definition: sig_ss7.h:64
#define LINKSET_FLAG_DEFAULTECHOCONTROL
Definition: sig_ss7.h:71
#define LINKSTATE_STARTING
Definition: sig_ss7.h:62
sig_ss7_law
Definition: sig_ss7.h:88
@ SIG_SS7_ULAW
Definition: sig_ss7.h:90
@ SIG_SS7_ALAW
Definition: sig_ss7.h:91
#define LINKSET_FLAG_USEECHOCONTROL
Definition: sig_ss7.h:70
void sig_ss7_chan_delete(struct sig_ss7_chan *doomed)
#define LINKSET_FLAG_INITIALHWBLO
Definition: sig_ss7.h:69
int sig_ss7_cb_hangup(struct ss7 *ss7, int cic, unsigned int dpc, int cause, int do_hangup)
#define SS7_NAI_DYNAMIC
Definition: sig_ss7.h:66
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)
int sig_ss7_hangup(struct sig_ss7_chan *p, struct ast_channel *ast)
void sig_ss7_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, struct sig_ss7_chan *pchan)
#define SS7_BLOCKED_HARDWARE
Definition: sig_ss7.h:75
#define SIG_SS7_NUM_DCHANS
Definition: sig_ss7.h:56
int sig_ss7_answer(struct sig_ss7_chan *p, struct ast_channel *ast)
@ SS7_REDIRECTING_REASON_DEFLECTION_IMMEDIATE_RESPONSE
Definition: sig_ss7.h:111
@ SS7_REDIRECTING_REASON_DEFLECTION_DURING_ALERTING
Definition: sig_ss7.h:110
@ SS7_REDIRECTING_REASON_UNKNOWN
Definition: sig_ss7.h:106
@ SS7_REDIRECTING_REASON_NO_ANSWER
Definition: sig_ss7.h:108
@ SS7_REDIRECTING_REASON_USER_BUSY
Definition: sig_ss7.h:107
@ SS7_REDIRECTING_REASON_UNAVAILABLE
Definition: sig_ss7.h:112
@ SS7_REDIRECTING_REASON_UNCONDITIONAL
Definition: sig_ss7.h:109
int sig_ss7_find_cic_range(struct sig_ss7_linkset *linkset, int startcic, int endcic, unsigned int dpc)
#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
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:604
Main Channel structure associated with a channel.
unsigned short transfercapability
char exten[AST_MAX_EXTENSION]
char chan_name[AST_CHANNEL_NAME]
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
Caller Party information.
Definition: channel.h:418
Connected Line/Party information.
Definition: channel.h:456
struct ast_party_id id
Connected party ID.
Definition: channel.h:458
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:342
int presentation
Q.931 presentation-indicator and screening-indicator encoded fields.
Definition: channel.h:295
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:297
char * str
Subscriber phone number (Malloced)
Definition: channel.h:291
int code
enum AST_REDIRECTING_REASON value for redirection
Definition: channel.h:510
Redirecting Line information. RDNIS (Redirecting Directory Number Information Service) Where a call d...
Definition: channel.h:522
struct ast_party_redirecting_reason orig_reason
Reason for the redirection by the original party.
Definition: channel.h:545
struct ast_party_redirecting_reason reason
Reason for the redirection.
Definition: channel.h:542
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
Definition: channel.h:527
int count
Number of times the call was redirected.
Definition: channel.h:548
struct ast_party_id to
Call is redirecting to a new party (Sent to the caller)
Definition: channel.h:530
struct ast_party_id orig
Who originally redirected the call (Sent to the party the call is redirected toward)
Definition: channel.h:524
Number structure.
Definition: app_followme.c:154
int(*const set_echocanceller)(void *pvt, int enable)
Definition: sig_ss7.h:161
void(*const deadlock_avoidance_private)(void *pvt)
Definition: sig_ss7.h:159
void(*const set_digital)(void *pvt, int is_digital)
Definition: sig_ss7.h:172
struct sig_ss7_linkset *(*const find_linkset)(struct ss7 *ss7)
Definition: sig_ss7.h:183
void(*const set_loopback)(void *pvt, int enable)
Definition: sig_ss7.h:162
void(*const unlock_private)(void *pvt)
Definition: sig_ss7.h:155
void(*const set_callerid)(void *pvt, const struct ast_party_caller *caller)
Definition: sig_ss7.h:177
void(*const set_dnid)(void *pvt, const char *dnid)
Definition: sig_ss7.h:178
void(*const set_outgoing)(void *pvt, int is_outgoing)
Definition: sig_ss7.h:173
void(*const set_dialing)(void *pvt, int is_dialing)
Definition: sig_ss7.h:171
void(*const set_alarm)(void *pvt, int in_alarm)
Definition: sig_ss7.h:170
void(*const handle_link_exception)(struct sig_ss7_linkset *linkset, int which)
Definition: sig_ss7.h:169
void(*const queue_control)(void *pvt, int subclass)
Definition: sig_ss7.h:180
void(*const set_remotelyblocked)(void *pvt, int is_blocked)
Definition: sig_ss7.h:176
void(*const lock_private)(void *pvt)
Definition: sig_ss7.h:157
void(*const set_inservice)(void *pvt, int is_inservice)
Definition: sig_ss7.h:174
void(*const open_media)(void *pvt)
Definition: sig_ss7.h:181
struct ast_channel *(*const new_ast_channel)(void *pvt, int state, enum sig_ss7_law law, char *exten, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
Definition: sig_ss7.h:164
void(*const set_locallyblocked)(void *pvt, int is_blocked)
Definition: sig_ss7.h:175
int(*const play_tone)(void *pvt, enum sig_ss7_tone tone)
Definition: sig_ss7.h:167
unsigned int immediate
Definition: sig_ss7.h:221
char generic_name[50]
Definition: sig_ss7.h:264
char cid_subaddr[AST_MAX_EXTENSION]
Definition: sig_ss7.h:245
void * chan_pvt
Definition: sig_ss7.h:190
char lspi_ident[50]
Definition: sig_ss7.h:277
char jip_number[50]
Definition: sig_ss7.h:271
char cid_num[AST_MAX_EXTENSION]
Definition: sig_ss7.h:244
unsigned short cug_interlock_code
Binari Code to uniquely identify a CUG inside the network.
Definition: sig_ss7.h:308
unsigned int echocontrol_ind
Definition: sig_ss7.h:282
unsigned int outgoing
TRUE if this channel is being used for an outgoing call.
Definition: sig_ss7.h:292
char gen_add_number[50]
Definition: sig_ss7.h:252
unsigned int loopedback
TRUE if this channel is in loopback.
Definition: sig_ss7.h:300
unsigned int call_ref_ident
Definition: sig_ss7.h:278
unsigned int locallyblocked
Bitmask for the channel being locally blocked.
Definition: sig_ss7.h:228
unsigned int call_ref_pc
Definition: sig_ss7.h:279
unsigned char redirect_info_reas
Definition: sig_ss7.h:263
unsigned char redirect_info_orig_reas
Definition: sig_ss7.h:261
unsigned char redirect_info
Definition: sig_ss7.h:259
int redirecting_presentation
Definition: sig_ss7.h:257
unsigned char redirect_info_ind
Definition: sig_ss7.h:260
unsigned int dpc
Definition: sig_ss7.h:202
enum sig_ss7_call_level call_level
Definition: sig_ss7.h:198
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
unsigned char calling_party_cat
Definition: sig_ss7.h:280
char exten[AST_MAX_EXTENSION]
Definition: sig_ss7.h:248
unsigned int rlt
XXX BOOLEAN Purpose???
Definition: sig_ss7.h:298
char gen_dig_number[50]
Definition: sig_ss7.h:253
struct isup_call * ss7call
Opaque libss7 call control structure.
Definition: sig_ss7.h:195
char charge_number[50]
Definition: sig_ss7.h:251
char redirecting_num[50]
Definition: sig_ss7.h:256
unsigned int remotelyblocked
Bitmask for the channel being remotely blocked.
Definition: sig_ss7.h:235
unsigned int hidecallerid
TRUE if the outgoing caller ID is blocked/hidden.
Definition: sig_ss7.h:213
unsigned int progress
TRUE if the call has seen inband-information progress through the network.
Definition: sig_ss7.h:296
struct ast_channel * owner
Definition: sig_ss7.h:192
unsigned char gen_dig_scheme
Definition: sig_ss7.h:270
unsigned int called_complete
TRUE if the channel has completed collecting digits.
Definition: sig_ss7.h:294
int cid_ani2
Definition: sig_ss7.h:241
char cug_interlock_ni[5]
Network Identify Code as per Q.763 3.15.a.
Definition: sig_ss7.h:306
unsigned char gen_add_type
Definition: sig_ss7.h:268
unsigned char gen_add_pres_ind
Definition: sig_ss7.h:267
unsigned char gen_add_num_plan
Definition: sig_ss7.h:265
struct sig_ss7_linkset * ss7
Definition: sig_ss7.h:191
unsigned int do_hangup
Definition: sig_ss7.h:281
unsigned char cug_indicator
Indication of the call being a CUG call and its permissions.
Definition: sig_ss7.h:315
int callingpres
Definition: sig_ss7.h:243
char context[AST_MAX_CONTEXT]
Definition: sig_ss7.h:237
unsigned char redirect_counter
Definition: sig_ss7.h:258
unsigned int inalarm
TRUE if channel is associated with a link that is down.
Definition: sig_ss7.h:288
int orig_called_presentation
Definition: sig_ss7.h:255
char cid_name[AST_MAX_EXTENSION]
Definition: sig_ss7.h:246
unsigned int inservice
TRUE if channel is in service.
Definition: sig_ss7.h:290
unsigned char redirect_info_counter
Definition: sig_ss7.h:262
int channel
Definition: sig_ss7.h:200
int stripmsd
Number of most significant digits/characters to strip from the dialed number.
Definition: sig_ss7.h:209
unsigned char gen_add_nai
Definition: sig_ss7.h:266
unsigned int use_callerid
TRUE if caller ID is used on this channel.
Definition: sig_ss7.h:215
char cid_ani[AST_MAX_EXTENSION]
Definition: sig_ss7.h:247
char mohinterpret[MAX_MUSICCLASS]
Definition: sig_ss7.h:238
char orig_called_num[50]
Definition: sig_ss7.h:254
int cid_ton
Definition: sig_ss7.h:242
unsigned char gen_dig_type
Definition: sig_ss7.h:269
int fds[SIG_SS7_NUM_DCHANS]
Definition: sig_ss7.h:323
char unknownprefix[20]
Definition: sig_ss7.h:342
char subscriberprefix[20]
Definition: sig_ss7.h:341
enum sig_ss7_linkset::@143 state
char nationalprefix[10]
Definition: sig_ss7.h:340
int linkstate[SIG_SS7_NUM_DCHANS]
Definition: sig_ss7.h:325
pthread_t master
Definition: sig_ss7.h:319
char networkroutedprefix[20]
Definition: sig_ss7.h:343
struct ss7 * ss7
Definition: sig_ss7.h:321
char calling_nai
Definition: sig_ss7.h:338
char called_nai
Definition: sig_ss7.h:337
ast_mutex_t lock
Definition: sig_ss7.h:320
char internationalprefix[10]
Definition: sig_ss7.h:339
struct sig_ss7_chan * pvts[SIG_SS7_MAX_CHANNELS]
Definition: sig_ss7.h:322
static struct test_val c
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
General Asterisk channel transcoding definitions.
#define AST_TRANS_CAP_DIGITAL
Definition: transcap.h:36
#define ast_assert(a)
Definition: utils.h:739
#define ARRAY_LEN(a)
Definition: utils.h:666