Replace direct access to channel name with accessor functions
[asterisk/asterisk.git] / channels / chan_misdn.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2004 - 2006, Christian Richter
5  *
6  * Christian Richter <crich@beronet.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 /*!
21  * \file
22  *
23  * \brief the chan_misdn channel driver for Asterisk
24  *
25  * \author Christian Richter <crich@beronet.com>
26  *
27  * \extref MISDN http://www.misdn.org/
28  *
29  * \ingroup channel_drivers
30  */
31
32 /*!
33  * \note
34  * To use the CCBS/CCNR supplementary service feature and other
35  * supplementary services using FACILITY messages requires a
36  * modified version of mISDN.
37  *
38  * \note
39  * The latest modified mISDN v1.1.x based version is available at:
40  * http://svn.digium.com/svn/thirdparty/mISDN/trunk
41  * http://svn.digium.com/svn/thirdparty/mISDNuser/trunk
42  *
43  * \note
44  * Taged versions of the modified mISDN code are available under:
45  * http://svn.digium.com/svn/thirdparty/mISDN/tags
46  * http://svn.digium.com/svn/thirdparty/mISDNuser/tags
47  */
48
49 /* Define to enable cli commands to generate canned CCBS messages. */
50 // #define CCBS_TEST_MESSAGES   1
51
52 /*** MODULEINFO
53         <depend>isdnnet</depend>
54         <depend>misdn</depend>
55         <depend>suppserv</depend>
56         <support_level>extended</support_level>
57  ***/
58 #include "asterisk.h"
59
60 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
61
62 #include <pthread.h>
63 #include <sys/socket.h>
64 #include <sys/time.h>
65 #include <arpa/inet.h>
66 #include <fcntl.h>
67 #include <sys/ioctl.h>
68 #include <signal.h>
69 #include <sys/file.h>
70 #include <semaphore.h>
71 #include <ctype.h>
72 #include <time.h>
73
74 #include "asterisk/channel.h"
75 #include "asterisk/config.h"
76 #include "asterisk/module.h"
77 #include "asterisk/pbx.h"
78 #include "asterisk/io.h"
79 #include "asterisk/frame.h"
80 #include "asterisk/translate.h"
81 #include "asterisk/cli.h"
82 #include "asterisk/musiconhold.h"
83 #include "asterisk/dsp.h"
84 #include "asterisk/file.h"
85 #include "asterisk/callerid.h"
86 #include "asterisk/indications.h"
87 #include "asterisk/app.h"
88 #include "asterisk/features.h"
89 #include "asterisk/term.h"
90 #include "asterisk/sched.h"
91 #include "asterisk/stringfields.h"
92 #include "asterisk/abstract_jb.h"
93 #include "asterisk/causes.h"
94 #include "asterisk/format.h"
95 #include "asterisk/format_cap.h"
96
97 #include "chan_misdn_config.h"
98 #include "isdn_lib.h"
99
100 static char global_tracefile[BUFFERSIZE + 1];
101
102 static int g_config_initialized = 0;
103
104 struct misdn_jb{
105         int size;
106         int upper_threshold;
107         char *samples, *ok;
108         int wp,rp;
109         int state_empty;
110         int state_full;
111         int state_buffer;
112         int bytes_wrote;
113         ast_mutex_t mutexjb;
114 };
115
116 /*! \brief allocates the jb-structure and initialize the elements */
117 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
118
119 /*! \brief frees the data and destroys the given jitterbuffer struct */
120 void misdn_jb_destroy(struct misdn_jb *jb);
121
122 /*! \brief fills the jitterbuffer with len data returns < 0 if there was an
123 error (buffer overrun). */
124 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
125
126 /*! \brief gets len bytes out of the jitterbuffer if available, else only the
127 available data is returned and the return value indicates the number
128 of data. */
129 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
130
131 static char *complete_ch(struct ast_cli_args *a);
132 static char *complete_debug_port(struct ast_cli_args *a);
133 static char *complete_show_config(struct ast_cli_args *a);
134
135 /* BEGIN: chan_misdn.h */
136
137 #if defined(AST_MISDN_ENHANCEMENTS)
138 /*
139  * This timeout duration is to clean up any call completion records that
140  * are forgotten about by the switch.
141  */
142 #define MISDN_CC_RECORD_AGE_MAX         (6UL * 60 * 60) /* seconds */
143
144 #define MISDN_CC_REQUEST_WAIT_MAX       5       /* seconds */
145
146 /*!
147  * \brief Caller that initialized call completion services
148  *
149  * \details
150  * This data is the payload for a datastore that is put on the channel that
151  * initializes call completion services.  This datastore is set to be inherited
152  * by the outbound mISDN channel.  When one of these channels hangs up, the
153  * channel pointer will be set to NULL.  That way, we can ensure that we do not
154  * touch this channel after it gets destroyed.
155  */
156 struct misdn_cc_caller {
157         /*! \brief The channel that initialized call completion services */
158         struct ast_channel *chan;
159 };
160
161 struct misdn_cc_notify {
162         /*! \brief Dialplan: Notify extension priority */
163         int priority;
164
165         /*! \brief Dialplan: Notify extension context */
166         char context[AST_MAX_CONTEXT];
167
168         /*! \brief Dialplan: Notify extension number (User-A) */
169         char exten[AST_MAX_EXTENSION];
170 };
171
172 /*! \brief mISDN call completion record */
173 struct misdn_cc_record {
174         /*! \brief Call completion record linked list */
175         AST_LIST_ENTRY(misdn_cc_record) list;
176
177         /*! \brief Time the record was created. */
178         time_t time_created;
179
180         /*! \brief MISDN_CC_RECORD_ID value */
181         long record_id;
182
183         /*!
184          * \brief Logical Layer 1 port associated with this
185          * call completion record
186          */
187         int port;
188
189         /*! \brief TRUE if point-to-point mode (CCBS-T/CCNR-T mode) */
190         int ptp;
191
192         /*! \brief Mode specific parameters */
193         union {
194                 /*! \brief point-to-point specific parameters. */
195                 struct {
196                         /*!
197                          * \brief Call-completion signaling link.
198                          * NULL if signaling link not established.
199                          */
200                         struct misdn_bchannel *bc;
201
202                         /*!
203                          * \brief TRUE if we requested the request retention option
204                          * to be enabled.
205                          */
206                         int requested_retention;
207
208                         /*!
209                          * \brief TRUE if the request retention option is enabled.
210                          */
211                         int retention_enabled;
212                 } ptp;
213
214                 /*! \brief point-to-multi-point specific parameters. */
215                 struct {
216                         /*! \brief CallLinkageID (valid when port determined) */
217                         int linkage_id;
218
219                         /*! \breif CCBSReference (valid when activated is TRUE) */
220                         int reference_id;
221
222                         /*! \brief globalRecall(0),     specificRecall(1) */
223                         int recall_mode;
224                 } ptmp;
225         } mode;
226
227         /*! \brief TRUE if call completion activated */
228         int activated;
229
230         /*! \brief Outstanding message ID (valid when outstanding_message) */
231         int invoke_id;
232
233         /*! \brief TRUE if waiting for a response from a message (invoke_id is valid) */
234         int outstanding_message;
235
236         /*! \brief TRUE if activation has been requested */
237         int activation_requested;
238
239         /*!
240          * \brief TRUE if User-A is free
241          * \note PTMP - Used to answer CCBSStatusRequest.
242          * PTP - Determines how to respond to CCBS_T_RemoteUserFree.
243          */
244         int party_a_free;
245
246         /*! \brief Error code received from last outstanding message. */
247         enum FacErrorCode error_code;
248
249         /*! \brief Reject code received from last outstanding message. */
250         enum FacRejectCode reject_code;
251
252         /*!
253          * \brief Saved struct misdn_bchannel call information when
254          * attempted to call User-B
255          */
256         struct {
257                 /*! \brief User-A caller id information */
258                 struct misdn_party_id caller;
259
260                 /*! \brief User-B number information */
261                 struct misdn_party_dialing dialed;
262
263                 /*! \brief The BC, HLC (optional) and LLC (optional) contents from the SETUP message. */
264                 struct Q931_Bc_Hlc_Llc setup_bc_hlc_llc;
265
266                 /*! \brief SETUP message bearer capability field code value */
267                 int capability;
268
269                 /*! \brief TRUE if call made in digital HDLC mode */
270                 int hdlc;
271         } redial;
272
273         /*! \brief Dialplan location to indicate User-B free and User-A is free */
274         struct misdn_cc_notify remote_user_free;
275
276         /*! \brief Dialplan location to indicate User-B free and User-A is busy */
277         struct misdn_cc_notify b_free;
278 };
279
280 /*! \brief mISDN call completion record database */
281 static AST_LIST_HEAD_STATIC(misdn_cc_records_db, misdn_cc_record);
282 /*! \brief Next call completion record ID to use */
283 static __u16 misdn_cc_record_id;
284 /*! \brief Next invoke ID to use */
285 static __s16 misdn_invoke_id;
286
287 static const char misdn_no_response_from_network[] = "No response from network";
288 static const char misdn_cc_record_not_found[] = "Call completion record not found";
289
290 /* mISDN channel variable names */
291 #define MISDN_CC_RECORD_ID      "MISDN_CC_RECORD_ID"
292 #define MISDN_CC_STATUS         "MISDN_CC_STATUS"
293 #define MISDN_ERROR_MSG         "MISDN_ERROR_MSG"
294 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
295
296 static ast_mutex_t release_lock;
297
298 enum misdn_chan_state {
299         MISDN_NOTHING = 0,         /*!< at beginning */
300         MISDN_WAITING4DIGS,        /*!< when waiting for info */
301         MISDN_EXTCANTMATCH,        /*!< when asterisk couldn't match our ext */
302         MISDN_INCOMING_SETUP,      /*!< for incoming setup */
303         MISDN_DIALING,             /*!< when pbx_start */
304         MISDN_PROGRESS,            /*!< we have progress */
305         MISDN_PROCEEDING,          /*!< we have progress */
306         MISDN_CALLING,             /*!< when misdn_call is called */
307         MISDN_CALLING_ACKNOWLEDGE, /*!< when we get SETUP_ACK */
308         MISDN_ALERTING,            /*!< when Alerting */
309         MISDN_BUSY,                /*!< when BUSY */
310         MISDN_CONNECTED,           /*!< when connected */
311         MISDN_DISCONNECTED,        /*!< when connected */
312         MISDN_CLEANING,            /*!< when hangup from * but we were connected before */
313 };
314
315 /*! Asterisk created the channel (outgoing call) */
316 #define ORG_AST 1
317 /*! mISDN created the channel (incoming call) */
318 #define ORG_MISDN 2
319
320 enum misdn_hold_state {
321         MISDN_HOLD_IDLE,                /*!< HOLD not active */
322         MISDN_HOLD_ACTIVE,              /*!< Call is held */
323         MISDN_HOLD_TRANSFER,    /*!< Held call is being transferred */
324         MISDN_HOLD_DISCONNECT,  /*!< Held call is being disconnected */
325 };
326 struct hold_info {
327         /*!
328          * \brief Call HOLD state.
329          */
330         enum misdn_hold_state state;
331         /*!
332          * \brief Logical port the channel call record is HELD on
333          * because the B channel is no longer associated.
334          */
335         int port;
336
337         /*!
338          * \brief Original B channel number the HELD call was using.
339          * \note Used only for debug display messages.
340          */
341         int channel;
342 };
343
344 #define chan_list_ref(obj, debug) (ao2_t_ref((obj), +1, (debug)), (obj))
345 #define chan_list_unref(obj, debug) (ao2_t_ref((obj), -1, (debug)), NULL)
346
347 /*!
348  * \brief Channel call record structure
349  */
350 struct chan_list {
351         /*!
352          * \brief The "allowed_bearers" string read in from /etc/asterisk/misdn.conf
353          */
354         char allowed_bearers[BUFFERSIZE + 1];
355
356         /*!
357          * \brief State of the channel
358          */
359         enum misdn_chan_state state;
360
361         /*!
362          * \brief TRUE if a hangup needs to be queued
363          * \note This is a debug flag only used to catch calls to hangup_chan() that are already hungup.
364          */
365         int need_queue_hangup;
366
367         /*!
368          * \brief TRUE if a channel can be hung up by calling asterisk directly when done.
369          */
370         int need_hangup;
371
372         /*!
373          * \brief TRUE if we could send an AST_CONTROL_BUSY if needed.
374          */
375         int need_busy;
376
377         /*!
378          * \brief Who originally created this channel. ORG_AST or ORG_MISDN
379          */
380         int originator;
381
382         /*!
383          * \brief TRUE of we are not to respond immediately to a SETUP message.  Check the dialplan first.
384          * \note The "noautorespond_on_setup" boolean read in from /etc/asterisk/misdn.conf
385          */
386         int noautorespond_on_setup;
387
388         int norxtone;   /*!< Boolean assigned values but the value is not used. */
389
390         /*!
391          * \brief TRUE if we are not to generate tones (Playtones)
392          */
393         int notxtone;
394
395         /*!
396          * \brief TRUE if echo canceller is enabled.  Value is toggled.
397          */
398         int toggle_ec;
399
400         /*!
401          * \brief TRUE if you want to send Tone Indications to an incoming
402          * ISDN channel on a TE Port.
403          * \note The "incoming_early_audio" boolean read in from /etc/asterisk/misdn.conf
404          */
405         int incoming_early_audio;
406
407         /*!
408          * \brief TRUE if DTMF digits are to be passed inband only.
409          * \note It is settable by the misdn_set_opt() application.
410          */
411         int ignore_dtmf;
412
413         /*!
414          * \brief Pipe file descriptor handles array.
415          * Read from pipe[0], write to pipe[1]
416          */
417         int pipe[2];
418
419         /*!
420          * \brief Read buffer for inbound audio from pipe[0]
421          */
422         char ast_rd_buf[4096];
423
424         /*!
425          * \brief Inbound audio frame returned by misdn_read().
426          */
427         struct ast_frame frame;
428
429         /*!
430          * \brief Fax detection option. (0:no 1:yes 2:yes+nojump)
431          * \note The "faxdetect" option string read in from /etc/asterisk/misdn.conf
432          * \note It is settable by the misdn_set_opt() application.
433          */
434         int faxdetect;
435
436         /*!
437          * \brief Number of seconds to detect a Fax machine when detection enabled.
438          * \note 0 disables the timeout.
439          * \note The "faxdetect_timeout" value read in from /etc/asterisk/misdn.conf
440          */
441         int faxdetect_timeout;
442
443         /*!
444          * \brief Starting time of fax detection with timeout when nonzero.
445          */
446         struct timeval faxdetect_tv;
447
448         /*!
449          * \brief TRUE if a fax has been detected.
450          */
451         int faxhandled;
452
453         /*!
454          * \brief TRUE if we will use the Asterisk DSP to detect DTMF/Fax
455          * \note The "astdtmf" boolean read in from /etc/asterisk/misdn.conf
456          */
457         int ast_dsp;
458
459         /*!
460          * \brief Jitterbuffer length
461          * \note The "jitterbuffer" value read in from /etc/asterisk/misdn.conf
462          */
463         int jb_len;
464
465         /*!
466          * \brief Jitterbuffer upper threshold
467          * \note The "jitterbuffer_upper_threshold" value read in from /etc/asterisk/misdn.conf
468          */
469         int jb_upper_threshold;
470
471         /*!
472          * \brief Allocated jitterbuffer controller
473          * \note misdn_jb_init() creates the jitterbuffer.
474          * \note Must use misdn_jb_destroy() to clean up.
475          */
476         struct misdn_jb *jb;
477
478         /*!
479          * \brief Allocated DSP controller
480          * \note ast_dsp_new() creates the DSP controller.
481          * \note Must use ast_dsp_free() to clean up.
482          */
483         struct ast_dsp *dsp;
484
485         /*!
486          * \brief Associated Asterisk channel structure.
487          */
488         struct ast_channel * ast;
489
490         /*!
491          * \brief Associated B channel structure.
492          */
493         struct misdn_bchannel *bc;
494
495 #if defined(AST_MISDN_ENHANCEMENTS)
496         /*!
497          * \brief Peer channel for which call completion was initialized.
498          */
499         struct misdn_cc_caller *peer;
500
501         /*! \brief Associated call completion record ID (-1 if not associated) */
502         long record_id;
503 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
504
505         /*!
506          * \brief HELD channel call information
507          */
508         struct hold_info hold;
509
510         /*!
511          * \brief From associated B channel: Layer 3 process ID
512          * \note Used to find the HELD channel call record when retrieving a call.
513          */
514         unsigned int l3id;
515
516         /*!
517          * \brief From associated B channel: B Channel mISDN driver layer ID from mISDN_get_layerid()
518          * \note Used only for debug display messages.
519          */
520         int addr;
521
522         /*!
523          * \brief Incoming call dialplan context identifier.
524          * \note The "context" string read in from /etc/asterisk/misdn.conf
525          */
526         char context[AST_MAX_CONTEXT];
527
528         /*!
529          * \brief The configured music-on-hold class to use for this call.
530          * \note The "musicclass" string read in from /etc/asterisk/misdn.conf
531          */
532         char mohinterpret[MAX_MUSICCLASS];
533
534         /*!
535          * \brief Number of outgoing audio frames dropped since last debug gripe message.
536          */
537         int dropped_frame_cnt;
538
539         /*!
540          * \brief TRUE if we must do the ringback tones.
541          * \note The "far_alerting" boolean read in from /etc/asterisk/misdn.conf
542          */
543         int far_alerting;
544
545         /*!
546          * \brief TRUE if NT should disconnect an overlap dialing call when a timeout occurs.
547          * \note The "nttimeout" boolean read in from /etc/asterisk/misdn.conf
548          */
549         int nttimeout;
550
551         /*!
552          * \brief Tone zone sound used for dialtone generation.
553          * \note Used as a boolean.  Non-NULL to prod generation if enabled.
554          */
555         struct ast_tone_zone_sound *ts;
556
557         /*!
558          * \brief Enables overlap dialing for the set amount of seconds.  (0 = Disabled)
559          * \note The "overlapdial" value read in from /etc/asterisk/misdn.conf
560          */
561         int overlap_dial;
562
563         /*!
564          * \brief Overlap dialing timeout Task ID.  -1 if not running.
565          */
566         int overlap_dial_task;
567
568         /*!
569          * \brief overlap_tv access lock.
570          */
571         ast_mutex_t overlap_tv_lock;
572
573         /*!
574          * \brief Overlap timer start time.  Timer restarted for every digit received.
575          */
576         struct timeval overlap_tv;
577
578         /*!
579          * \brief Next channel call record in the list.
580          */
581         struct chan_list *next;
582 };
583
584
585 int MAXTICS = 8;
586
587
588 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
589 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
590 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
591
592 struct robin_list {
593         char *group;
594         int port;
595         int channel;
596         struct robin_list *next;
597         struct robin_list *prev;
598 };
599 static struct robin_list *robin = NULL;
600
601
602 static void free_robin_list(void)
603 {
604         struct robin_list *r;
605         struct robin_list *next;
606
607         for (r = robin, robin = NULL; r; r = next) {
608                 next = r->next;
609                 ast_free(r->group);
610                 ast_free(r);
611         }
612 }
613
614 static struct robin_list *get_robin_position(char *group)
615 {
616         struct robin_list *new;
617         struct robin_list *iter = robin;
618         for (; iter; iter = iter->next) {
619                 if (!strcasecmp(iter->group, group)) {
620                         return iter;
621                 }
622         }
623         new = ast_calloc(1, sizeof(*new));
624         if (!new) {
625                 return NULL;
626         }
627         new->group = ast_strdup(group);
628         if (!new->group) {
629                 ast_free(new);
630                 return NULL;
631         }
632         new->channel = 1;
633         if (robin) {
634                 new->next = robin;
635                 robin->prev = new;
636         }
637         robin = new;
638         return robin;
639 }
640
641
642 /*! \brief the main schedule context for stuff like l1 watcher, overlap dial, ... */
643 static struct ast_sched_context *misdn_tasks = NULL;
644 static pthread_t misdn_tasks_thread;
645
646 static int *misdn_ports;
647
648 static void chan_misdn_log(int level, int port, char *tmpl, ...)
649         __attribute__((format(printf, 3, 4)));
650
651 static struct ast_channel *misdn_new(struct chan_list *cl, int state,  char *exten, char *callerid, struct ast_format_cap *cap, const char *linkedid, int port, int c);
652 static void send_digit_to_chan(struct chan_list *cl, char digit);
653
654 static int pbx_start_chan(struct chan_list *ch);
655
656 #define MISDN_ASTERISK_TECH_PVT(ast) ast->tech_pvt
657
658 #include "asterisk/strings.h"
659
660 /* #define MISDN_DEBUG 1 */
661
662 static const char misdn_type[] = "mISDN";
663
664 static int tracing = 0;
665
666 /*! \brief Only alaw and mulaw is allowed for now */
667 static struct ast_format prefformat; /*  AST_FORMAT_SLINEAR ;  AST_FORMAT_ULAW | */
668
669 static int *misdn_debug;
670 static int *misdn_debug_only;
671 static int max_ports;
672
673 static int *misdn_in_calls;
674 static int *misdn_out_calls;
675
676 /*!
677  * \brief Global channel call record list head.
678  */
679 static struct chan_list *cl_te=NULL;
680 static ast_mutex_t cl_te_lock;
681
682 static enum event_response_e
683 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
684
685 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch);
686
687 static void cl_queue_chan(struct chan_list *chan);
688
689 static int dialtone_indicate(struct chan_list *cl);
690 static void hanguptone_indicate(struct chan_list *cl);
691 static int stop_indicate(struct chan_list *cl);
692
693 static int start_bc_tones(struct chan_list *cl);
694 static int stop_bc_tones(struct chan_list *cl);
695 static void release_chan_early(struct chan_list *ch);
696 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc);
697
698 #if defined(AST_MISDN_ENHANCEMENTS)
699 static const char misdn_command_name[] = "misdn_command";
700 static int misdn_command_exec(struct ast_channel *chan, const char *data);
701 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
702 static int misdn_check_l2l1(struct ast_channel *chan, const char *data);
703 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data);
704 static int misdn_facility_exec(struct ast_channel *chan, const char *data);
705
706 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
707
708 void debug_numtype(int port, int numtype, char *type);
709
710 int add_out_calls(int port);
711 int add_in_calls(int port);
712
713
714 #ifdef MISDN_1_2
715 static int update_pipeline_config(struct misdn_bchannel *bc);
716 #else
717 static int update_ec_config(struct misdn_bchannel *bc);
718 #endif
719
720
721
722 /*************** Helpers *****************/
723
724 static int misdn_chan_is_valid(struct chan_list *ch)
725 {
726         struct chan_list *list;
727
728         ast_mutex_lock(&cl_te_lock);
729         for (list = cl_te; list; list = list->next) {
730                 if (list == ch) {
731                         ast_mutex_unlock(&cl_te_lock);
732                         return 1;
733                 }
734         }
735         ast_mutex_unlock(&cl_te_lock);
736
737         return 0;
738 }
739
740 /*! Returns a reference to the found chan_list. */
741 static struct chan_list *get_chan_by_ast(struct ast_channel *ast)
742 {
743         struct chan_list *tmp;
744
745         ast_mutex_lock(&cl_te_lock);
746         for (tmp = cl_te; tmp; tmp = tmp->next) {
747                 if (tmp->ast == ast) {
748                         chan_list_ref(tmp, "Found chan_list by ast");
749                         ast_mutex_unlock(&cl_te_lock);
750                         return tmp;
751                 }
752         }
753         ast_mutex_unlock(&cl_te_lock);
754
755         return NULL;
756 }
757
758 /*! Returns a reference to the found chan_list. */
759 static struct chan_list *get_chan_by_ast_name(const char *name)
760 {
761         struct chan_list *tmp;
762
763         ast_mutex_lock(&cl_te_lock);
764         for (tmp = cl_te; tmp; tmp = tmp->next) {
765                 if (tmp->ast && strcmp(ast_channel_name(tmp->ast), name) == 0) {
766                         chan_list_ref(tmp, "Found chan_list by ast name");
767                         ast_mutex_unlock(&cl_te_lock);
768                         return tmp;
769                 }
770         }
771         ast_mutex_unlock(&cl_te_lock);
772
773         return NULL;
774 }
775
776 #if defined(AST_MISDN_ENHANCEMENTS)
777 /*!
778  * \internal
779  * \brief Destroy the misdn_cc_ds_info datastore payload
780  *
781  * \param[in] data the datastore payload, a reference to an misdn_cc_caller
782  *
783  * \details
784  * Since the payload is a reference to an astobj2 object, we just decrement its
785  * reference count.  Before doing so, we NULL out the channel pointer inside of
786  * the misdn_cc_caller instance.  This function will be called in one of two
787  * cases.  In both cases, we no longer need the channel pointer:
788  *
789  *  - The original channel that initialized call completion services, the same
790  *    channel that is stored here, has been destroyed early.  This could happen
791  *    if it transferred the mISDN channel, for example.
792  *
793  *  - The mISDN channel that had this datastore inherited on to it is now being
794  *    destroyed.  If this is the case, then the call completion events have
795  *    already occurred and the appropriate channel variables have already been
796  *    set on the original channel that requested call completion services.
797  *
798  * \return Nothing
799  */
800 static void misdn_cc_ds_destroy(void *data)
801 {
802         struct misdn_cc_caller *cc_caller = data;
803
804         ao2_lock(cc_caller);
805         cc_caller->chan = NULL;
806         ao2_unlock(cc_caller);
807
808         ao2_ref(cc_caller, -1);
809 }
810 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
811
812 #if defined(AST_MISDN_ENHANCEMENTS)
813 /*!
814  * \internal
815  * \brief Duplicate the misdn_cc_ds_info datastore payload
816  *
817  * \param[in] data the datastore payload, a reference to an misdn_cc_caller
818  *
819  * \details
820  * All we need to do is bump the reference count and return the same instance.
821  *
822  * \return A reference to an instance of a misdn_cc_caller
823  */
824 static void *misdn_cc_ds_duplicate(void *data)
825 {
826         struct misdn_cc_caller *cc_caller = data;
827
828         ao2_ref(cc_caller, +1);
829
830         return cc_caller;
831 }
832 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
833
834 #if defined(AST_MISDN_ENHANCEMENTS)
835 static const struct ast_datastore_info misdn_cc_ds_info = {
836         .type      = "misdn_cc",
837         .destroy   = misdn_cc_ds_destroy,
838         .duplicate = misdn_cc_ds_duplicate,
839 };
840 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
841
842 #if defined(AST_MISDN_ENHANCEMENTS)
843 /*!
844  * \internal
845  * \brief Set a channel var on the peer channel for call completion services
846  *
847  * \param[in] peer The peer that initialized call completion services
848  * \param[in] var The variable name to set
849  * \param[in] value The variable value to set
850  *
851  * This function may be called from outside of the channel thread.  It handles
852  * the fact that the peer channel may be hung up and destroyed at any time.
853  *
854  * \return nothing
855  */
856 static void misdn_cc_set_peer_var(struct misdn_cc_caller *peer, const char *var,
857         const char *value)
858 {
859         ao2_lock(peer);
860
861         /*! \todo XXX This nastiness can go away once ast_channel is ref counted! */
862         while (peer->chan && ast_channel_trylock(peer->chan)) {
863                 ao2_unlock(peer);
864                 sched_yield();
865                 ao2_lock(peer);
866         }
867
868         if (peer->chan) {
869                 pbx_builtin_setvar_helper(peer->chan, var, value);
870                 ast_channel_unlock(peer->chan);
871         }
872
873         ao2_unlock(peer);
874 }
875 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
876
877 #if defined(AST_MISDN_ENHANCEMENTS)
878 /*!
879  * \internal
880  * \brief Get a reference to the CC caller if it exists
881  */
882 static struct misdn_cc_caller *misdn_cc_caller_get(struct ast_channel *chan)
883 {
884         struct ast_datastore *datastore;
885         struct misdn_cc_caller *cc_caller;
886
887         ast_channel_lock(chan);
888
889         if (!(datastore = ast_channel_datastore_find(chan, &misdn_cc_ds_info, NULL))) {
890                 ast_channel_unlock(chan);
891                 return NULL;
892         }
893
894         ao2_ref(datastore->data, +1);
895         cc_caller = datastore->data;
896
897         ast_channel_unlock(chan);
898
899         return cc_caller;
900 }
901 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
902
903 #if defined(AST_MISDN_ENHANCEMENTS)
904 /*!
905  * \internal
906  * \brief Find the call completion record given the record id.
907  *
908  * \param record_id
909  *
910  * \retval pointer to found call completion record
911  * \retval NULL if not found
912  *
913  * \note Assumes the misdn_cc_records_db lock is already obtained.
914  */
915 static struct misdn_cc_record *misdn_cc_find_by_id(long record_id)
916 {
917         struct misdn_cc_record *current;
918
919         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
920                 if (current->record_id == record_id) {
921                         /* Found the record */
922                         break;
923                 }
924         }
925
926         return current;
927 }
928 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
929
930 #if defined(AST_MISDN_ENHANCEMENTS)
931 /*!
932  * \internal
933  * \brief Find the call completion record given the port and call linkage id.
934  *
935  * \param port Logical port number
936  * \param linkage_id Call linkage ID number from switch.
937  *
938  * \retval pointer to found call completion record
939  * \retval NULL if not found
940  *
941  * \note Assumes the misdn_cc_records_db lock is already obtained.
942  */
943 static struct misdn_cc_record *misdn_cc_find_by_linkage(int port, int linkage_id)
944 {
945         struct misdn_cc_record *current;
946
947         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
948                 if (current->port == port
949                         && !current->ptp
950                         && current->mode.ptmp.linkage_id == linkage_id) {
951                         /* Found the record */
952                         break;
953                 }
954         }
955
956         return current;
957 }
958 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
959
960 #if defined(AST_MISDN_ENHANCEMENTS)
961 /*!
962  * \internal
963  * \brief Find the call completion record given the port and outstanding invocation id.
964  *
965  * \param port Logical port number
966  * \param invoke_id Outstanding message invocation ID number.
967  *
968  * \retval pointer to found call completion record
969  * \retval NULL if not found
970  *
971  * \note Assumes the misdn_cc_records_db lock is already obtained.
972  */
973 static struct misdn_cc_record *misdn_cc_find_by_invoke(int port, int invoke_id)
974 {
975         struct misdn_cc_record *current;
976
977         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
978                 if (current->outstanding_message
979                         && current->invoke_id == invoke_id
980                         && current->port == port) {
981                         /* Found the record */
982                         break;
983                 }
984         }
985
986         return current;
987 }
988 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
989
990 #if defined(AST_MISDN_ENHANCEMENTS)
991 /*!
992  * \internal
993  * \brief Find the call completion record given the port and CCBS reference id.
994  *
995  * \param port Logical port number
996  * \param reference_id CCBS reference ID number from switch.
997  *
998  * \retval pointer to found call completion record
999  * \retval NULL if not found
1000  *
1001  * \note Assumes the misdn_cc_records_db lock is already obtained.
1002  */
1003 static struct misdn_cc_record *misdn_cc_find_by_reference(int port, int reference_id)
1004 {
1005         struct misdn_cc_record *current;
1006
1007         AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1008                 if (current->activated
1009                         && current->port == port
1010                         && !current->ptp
1011                         && current->mode.ptmp.reference_id == reference_id) {
1012                         /* Found the record */
1013                         break;
1014                 }
1015         }
1016
1017         return current;
1018 }
1019 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1020
1021 #if defined(AST_MISDN_ENHANCEMENTS)
1022 /*!
1023  * \internal
1024  * \brief Find the call completion record given the B channel pointer
1025  *
1026  * \param bc B channel control structure pointer.
1027  *
1028  * \retval pointer to found call completion record
1029  * \retval NULL if not found
1030  *
1031  * \note Assumes the misdn_cc_records_db lock is already obtained.
1032  */
1033 static struct misdn_cc_record *misdn_cc_find_by_bc(const struct misdn_bchannel *bc)
1034 {
1035         struct misdn_cc_record *current;
1036
1037         if (bc) {
1038                 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
1039                         if (current->ptp
1040                                 && current->mode.ptp.bc == bc) {
1041                                 /* Found the record */
1042                                 break;
1043                         }
1044                 }
1045         } else {
1046                 current = NULL;
1047         }
1048
1049         return current;
1050 }
1051 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1052
1053 #if defined(AST_MISDN_ENHANCEMENTS)
1054 /*!
1055  * \internal
1056  * \brief Delete the given call completion record
1057  *
1058  * \param doomed Call completion record to destroy
1059  *
1060  * \return Nothing
1061  *
1062  * \note Assumes the misdn_cc_records_db lock is already obtained.
1063  */
1064 static void misdn_cc_delete(struct misdn_cc_record *doomed)
1065 {
1066         struct misdn_cc_record *current;
1067
1068         AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1069                 if (current == doomed) {
1070                         AST_LIST_REMOVE_CURRENT(list);
1071                         ast_free(current);
1072                         return;
1073                 }
1074         }
1075         AST_LIST_TRAVERSE_SAFE_END;
1076
1077         /* The doomed node is not in the call completion database */
1078 }
1079 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1080
1081 #if defined(AST_MISDN_ENHANCEMENTS)
1082 /*!
1083  * \internal
1084  * \brief Delete all old call completion records
1085  *
1086  * \return Nothing
1087  *
1088  * \note Assumes the misdn_cc_records_db lock is already obtained.
1089  */
1090 static void misdn_cc_remove_old(void)
1091 {
1092         struct misdn_cc_record *current;
1093         time_t now;
1094
1095         now = time(NULL);
1096         AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
1097                 if (MISDN_CC_RECORD_AGE_MAX < now - current->time_created) {
1098                         if (current->ptp && current->mode.ptp.bc) {
1099                                 /* Close the old call-completion signaling link */
1100                                 current->mode.ptp.bc->fac_out.Function = Fac_None;
1101                                 current->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
1102                                 misdn_lib_send_event(current->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
1103                         }
1104
1105                         /* Remove the old call completion record */
1106                         AST_LIST_REMOVE_CURRENT(list);
1107                         ast_free(current);
1108                 }
1109         }
1110         AST_LIST_TRAVERSE_SAFE_END;
1111 }
1112 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1113
1114 #if defined(AST_MISDN_ENHANCEMENTS)
1115 /*!
1116  * \internal
1117  * \brief Allocate the next record id.
1118  *
1119  * \retval New record id on success.
1120  * \retval -1 on error.
1121  *
1122  * \note Assumes the misdn_cc_records_db lock is already obtained.
1123  */
1124 static long misdn_cc_record_id_new(void)
1125 {
1126         long record_id;
1127         long first_id;
1128
1129         record_id = ++misdn_cc_record_id;
1130         first_id = record_id;
1131         while (misdn_cc_find_by_id(record_id)) {
1132                 record_id = ++misdn_cc_record_id;
1133                 if (record_id == first_id) {
1134                         /*
1135                          * We have a resource leak.
1136                          * We should never need to allocate 64k records.
1137                          */
1138                         chan_misdn_log(0, 0, " --> ERROR Too many call completion records!\n");
1139                         record_id = -1;
1140                         break;
1141                 }
1142         }
1143
1144         return record_id;
1145 }
1146 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1147
1148 #if defined(AST_MISDN_ENHANCEMENTS)
1149 /*!
1150  * \internal
1151  * \brief Create a new call completion record
1152  *
1153  * \retval pointer to new call completion record
1154  * \retval NULL if failed
1155  *
1156  * \note Assumes the misdn_cc_records_db lock is already obtained.
1157  */
1158 static struct misdn_cc_record *misdn_cc_new(void)
1159 {
1160         struct misdn_cc_record *cc_record;
1161         long record_id;
1162
1163         misdn_cc_remove_old();
1164
1165         cc_record = ast_calloc(1, sizeof(*cc_record));
1166         if (cc_record) {
1167                 record_id = misdn_cc_record_id_new();
1168                 if (record_id < 0) {
1169                         ast_free(cc_record);
1170                         return NULL;
1171                 }
1172
1173                 /* Initialize the new record */
1174                 cc_record->record_id = record_id;
1175                 cc_record->port = -1;/* Invalid port so it will never be found this way */
1176                 cc_record->invoke_id = ++misdn_invoke_id;
1177                 cc_record->party_a_free = 1;/* Default User-A as free */
1178                 cc_record->error_code = FacError_None;
1179                 cc_record->reject_code = FacReject_None;
1180                 cc_record->time_created = time(NULL);
1181
1182                 /* Insert the new record into the database */
1183                 AST_LIST_INSERT_HEAD(&misdn_cc_records_db, cc_record, list);
1184         }
1185         return cc_record;
1186 }
1187 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1188
1189 #if defined(AST_MISDN_ENHANCEMENTS)
1190 /*!
1191  * \internal
1192  * \brief Destroy the call completion record database
1193  *
1194  * \return Nothing
1195  */
1196 static void misdn_cc_destroy(void)
1197 {
1198         struct misdn_cc_record *current;
1199
1200         while ((current = AST_LIST_REMOVE_HEAD(&misdn_cc_records_db, list))) {
1201                 /* Do a misdn_cc_delete(current) inline */
1202                 ast_free(current);
1203         }
1204 }
1205 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1206
1207 #if defined(AST_MISDN_ENHANCEMENTS)
1208 /*!
1209  * \internal
1210  * \brief Initialize the call completion record database
1211  *
1212  * \return Nothing
1213  */
1214 static void misdn_cc_init(void)
1215 {
1216         misdn_cc_record_id = 0;
1217 }
1218 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1219
1220 #if defined(AST_MISDN_ENHANCEMENTS)
1221 /*!
1222  * \internal
1223  * \brief Check the status of an outstanding invocation request.
1224  *
1225  * \param data Points to an integer containing the call completion record id.
1226  *
1227  * \retval 0 if got a response.
1228  * \retval -1 if no response yet.
1229  */
1230 static int misdn_cc_response_check(void *data)
1231 {
1232         int not_responded;
1233         struct misdn_cc_record *cc_record;
1234
1235         AST_LIST_LOCK(&misdn_cc_records_db);
1236         cc_record = misdn_cc_find_by_id(*(long *) data);
1237         if (cc_record) {
1238                 if (cc_record->outstanding_message) {
1239                         not_responded = -1;
1240                 } else {
1241                         not_responded = 0;
1242                 }
1243         } else {
1244                 /* No record so there is no response to check. */
1245                 not_responded = 0;
1246         }
1247         AST_LIST_UNLOCK(&misdn_cc_records_db);
1248
1249         return not_responded;
1250 }
1251 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1252
1253 #if defined(AST_MISDN_ENHANCEMENTS)
1254 /*!
1255  * \internal
1256  * \brief Wait for a response from the switch for an outstanding
1257  * invocation request.
1258  *
1259  * \param chan Asterisk channel to operate upon.
1260  * \param wait_seconds Number of seconds to wait
1261  * \param record_id Call completion record ID.
1262  *
1263  * \return Nothing
1264  */
1265 static void misdn_cc_response_wait(struct ast_channel *chan, int wait_seconds, long record_id)
1266 {
1267         unsigned count;
1268
1269         for (count = 2 * MISDN_CC_REQUEST_WAIT_MAX; count--;) {
1270                 /* Sleep in 500 ms increments */
1271                 if (ast_safe_sleep_conditional(chan, 500, misdn_cc_response_check, &record_id) != 0) {
1272                         /* We got hung up or our response came in. */
1273                         break;
1274                 }
1275         }
1276 }
1277 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1278
1279 #if defined(AST_MISDN_ENHANCEMENTS)
1280 /*!
1281  * \internal
1282  * \brief Convert the mISDN reject code to a string
1283  *
1284  * \param code mISDN reject code.
1285  *
1286  * \return The mISDN reject code as a string
1287  */
1288 static const char *misdn_to_str_reject_code(enum FacRejectCode code)
1289 {
1290         static const struct {
1291                 enum FacRejectCode code;
1292                 char *name;
1293         } arr[] = {
1294 /* *INDENT-OFF* */
1295                 { FacReject_None,                           "No reject occurred" },
1296                 { FacReject_Unknown,                        "Unknown reject code" },
1297
1298                 { FacReject_Gen_UnrecognizedComponent,      "General: Unrecognized Component" },
1299                 { FacReject_Gen_MistypedComponent,          "General: Mistyped Component" },
1300                 { FacReject_Gen_BadlyStructuredComponent,   "General: Badly Structured Component" },
1301
1302                 { FacReject_Inv_DuplicateInvocation,        "Invoke: Duplicate Invocation" },
1303                 { FacReject_Inv_UnrecognizedOperation,      "Invoke: Unrecognized Operation" },
1304                 { FacReject_Inv_MistypedArgument,           "Invoke: Mistyped Argument" },
1305                 { FacReject_Inv_ResourceLimitation,         "Invoke: Resource Limitation" },
1306                 { FacReject_Inv_InitiatorReleasing,         "Invoke: Initiator Releasing" },
1307                 { FacReject_Inv_UnrecognizedLinkedID,       "Invoke: Unrecognized Linked ID" },
1308                 { FacReject_Inv_LinkedResponseUnexpected,   "Invoke: Linked Response Unexpected" },
1309                 { FacReject_Inv_UnexpectedChildOperation,   "Invoke: Unexpected Child Operation" },
1310
1311                 { FacReject_Res_UnrecognizedInvocation,     "Result: Unrecognized Invocation" },
1312                 { FacReject_Res_ResultResponseUnexpected,   "Result: Result Response Unexpected" },
1313                 { FacReject_Res_MistypedResult,             "Result: Mistyped Result" },
1314
1315                 { FacReject_Err_UnrecognizedInvocation,     "Error: Unrecognized Invocation" },
1316                 { FacReject_Err_ErrorResponseUnexpected,    "Error: Error Response Unexpected" },
1317                 { FacReject_Err_UnrecognizedError,          "Error: Unrecognized Error" },
1318                 { FacReject_Err_UnexpectedError,            "Error: Unexpected Error" },
1319                 { FacReject_Err_MistypedParameter,          "Error: Mistyped Parameter" },
1320 /* *INDENT-ON* */
1321         };
1322
1323         unsigned index;
1324
1325         for (index = 0; index < ARRAY_LEN(arr); ++index) {
1326                 if (arr[index].code == code) {
1327                         return arr[index].name;
1328                 }
1329         }
1330
1331         return "unknown";
1332 }
1333 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1334
1335 #if defined(AST_MISDN_ENHANCEMENTS)
1336 /*!
1337  * \internal
1338  * \brief Convert the mISDN error code to a string
1339  *
1340  * \param code mISDN error code.
1341  *
1342  * \return The mISDN error code as a string
1343  */
1344 static const char *misdn_to_str_error_code(enum FacErrorCode code)
1345 {
1346         static const struct {
1347                 enum FacErrorCode code;
1348                 char *name;
1349         } arr[] = {
1350 /* *INDENT-OFF* */
1351                 { FacError_None,                            "No error occurred" },
1352                 { FacError_Unknown,                         "Unknown OID error code" },
1353
1354                 { FacError_Gen_NotSubscribed,               "General: Not Subscribed" },
1355                 { FacError_Gen_NotAvailable,                "General: Not Available" },
1356                 { FacError_Gen_NotImplemented,              "General: Not Implemented" },
1357                 { FacError_Gen_InvalidServedUserNr,         "General: Invalid Served User Number" },
1358                 { FacError_Gen_InvalidCallState,            "General: Invalid Call State" },
1359                 { FacError_Gen_BasicServiceNotProvided,     "General: Basic Service Not Provided" },
1360                 { FacError_Gen_NotIncomingCall,             "General: Not Incoming Call" },
1361                 { FacError_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
1362                 { FacError_Gen_ResourceUnavailable,         "General: Resource Unavailable" },
1363
1364                 { FacError_Div_InvalidDivertedToNr,         "Diversion: Invalid Diverted To Number" },
1365                 { FacError_Div_SpecialServiceNr,            "Diversion: Special Service Number" },
1366                 { FacError_Div_DiversionToServedUserNr,     "Diversion: Diversion To Served User Number" },
1367                 { FacError_Div_IncomingCallAccepted,        "Diversion: Incoming Call Accepted" },
1368                 { FacError_Div_NumberOfDiversionsExceeded,  "Diversion: Number Of Diversions Exceeded" },
1369                 { FacError_Div_NotActivated,                "Diversion: Not Activated" },
1370                 { FacError_Div_RequestAlreadyAccepted,      "Diversion: Request Already Accepted" },
1371
1372                 { FacError_AOC_NoChargingInfoAvailable,     "AOC: No Charging Info Available" },
1373
1374                 { FacError_CCBS_InvalidCallLinkageID,       "CCBS: Invalid Call Linkage ID" },
1375                 { FacError_CCBS_InvalidCCBSReference,       "CCBS: Invalid CCBS Reference" },
1376                 { FacError_CCBS_LongTermDenial,             "CCBS: Long Term Denial" },
1377                 { FacError_CCBS_ShortTermDenial,            "CCBS: Short Term Denial" },
1378                 { FacError_CCBS_IsAlreadyActivated,         "CCBS: Is Already Activated" },
1379                 { FacError_CCBS_AlreadyAccepted,            "CCBS: Already Accepted" },
1380                 { FacError_CCBS_OutgoingCCBSQueueFull,      "CCBS: Outgoing CCBS Queue Full" },
1381                 { FacError_CCBS_CallFailureReasonNotBusy,   "CCBS: Call Failure Reason Not Busy" },
1382                 { FacError_CCBS_NotReadyForCall,            "CCBS: Not Ready For Call" },
1383
1384                 { FacError_CCBS_T_LongTermDenial,           "CCBS-T: Long Term Denial" },
1385                 { FacError_CCBS_T_ShortTermDenial,          "CCBS-T: Short Term Denial" },
1386
1387                 { FacError_ECT_LinkIdNotAssignedByNetwork,  "ECT: Link ID Not Assigned By Network" },
1388 /* *INDENT-ON* */
1389         };
1390
1391         unsigned index;
1392
1393         for (index = 0; index < ARRAY_LEN(arr); ++index) {
1394                 if (arr[index].code == code) {
1395                         return arr[index].name;
1396                 }
1397         }
1398
1399         return "unknown";
1400 }
1401 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1402
1403 #if defined(AST_MISDN_ENHANCEMENTS)
1404 /*!
1405  * \internal
1406  * \brief Convert mISDN redirecting reason to diversion reason.
1407  *
1408  * \param reason mISDN redirecting reason code.
1409  *
1410  * \return Supported diversion reason code.
1411  */
1412 static unsigned misdn_to_diversion_reason(enum mISDN_REDIRECTING_REASON reason)
1413 {
1414         unsigned diversion_reason;
1415
1416         switch (reason) {
1417         case mISDN_REDIRECTING_REASON_CALL_FWD:
1418                 diversion_reason = 1;/* cfu */
1419                 break;
1420         case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
1421                 diversion_reason = 2;/* cfb */
1422                 break;
1423         case mISDN_REDIRECTING_REASON_NO_REPLY:
1424                 diversion_reason = 3;/* cfnr */
1425                 break;
1426         default:
1427                 diversion_reason = 0;/* unknown */
1428                 break;
1429         }
1430
1431         return diversion_reason;
1432 }
1433 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1434
1435 #if defined(AST_MISDN_ENHANCEMENTS)
1436 /*!
1437  * \internal
1438  * \brief Convert diversion reason to mISDN redirecting reason
1439  *
1440  * \param diversion_reason Diversion reason to convert
1441  *
1442  * \return Supported redirecting reason code.
1443  */
1444 static enum mISDN_REDIRECTING_REASON diversion_reason_to_misdn(unsigned diversion_reason)
1445 {
1446         enum mISDN_REDIRECTING_REASON reason;
1447
1448         switch (diversion_reason) {
1449         case 1:/* cfu */
1450                 reason = mISDN_REDIRECTING_REASON_CALL_FWD;
1451                 break;
1452         case 2:/* cfb */
1453                 reason = mISDN_REDIRECTING_REASON_CALL_FWD_BUSY;
1454                 break;
1455         case 3:/* cfnr */
1456                 reason = mISDN_REDIRECTING_REASON_NO_REPLY;
1457                 break;
1458         default:
1459                 reason = mISDN_REDIRECTING_REASON_UNKNOWN;
1460                 break;
1461         }
1462
1463         return reason;
1464 }
1465 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1466
1467 #if defined(AST_MISDN_ENHANCEMENTS)
1468 /*!
1469  * \internal
1470  * \brief Convert the mISDN presentation to PresentedNumberUnscreened type
1471  *
1472  * \param presentation mISDN presentation to convert
1473  * \param number_present TRUE if the number is present
1474  *
1475  * \return PresentedNumberUnscreened type
1476  */
1477 static unsigned misdn_to_PresentedNumberUnscreened_type(int presentation, int number_present)
1478 {
1479         unsigned type;
1480
1481         switch (presentation) {
1482         case 0:/* allowed */
1483                 if (number_present) {
1484                         type = 0;/* presentationAllowedNumber */
1485                 } else {
1486                         type = 2;/* numberNotAvailableDueToInterworking */
1487                 }
1488                 break;
1489         case 1:/* restricted */
1490                 if (number_present) {
1491                         type = 3;/* presentationRestrictedNumber */
1492                 } else {
1493                         type = 1;/* presentationRestricted */
1494                 }
1495                 break;
1496         default:
1497                 type = 2;/* numberNotAvailableDueToInterworking */
1498                 break;
1499         }
1500
1501         return type;
1502 }
1503 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1504
1505 #if defined(AST_MISDN_ENHANCEMENTS)
1506 /*!
1507  * \internal
1508  * \brief Convert the PresentedNumberUnscreened type to mISDN presentation
1509  *
1510  * \param type PresentedNumberUnscreened type
1511  *
1512  * \return mISDN presentation
1513  */
1514 static int PresentedNumberUnscreened_to_misdn_pres(unsigned type)
1515 {
1516         int presentation;
1517
1518         switch (type) {
1519         default:
1520         case 0:/* presentationAllowedNumber */
1521                 presentation = 0;/* allowed */
1522                 break;
1523
1524         case 1:/* presentationRestricted */
1525         case 3:/* presentationRestrictedNumber */
1526                 presentation = 1;/* restricted */
1527                 break;
1528
1529         case 2:/* numberNotAvailableDueToInterworking */
1530                 presentation = 2;/* unavailable */
1531                 break;
1532         }
1533
1534         return presentation;
1535 }
1536 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1537
1538 #if defined(AST_MISDN_ENHANCEMENTS)
1539 /*!
1540  * \internal
1541  * \brief Convert the mISDN numbering plan to PartyNumber numbering plan
1542  *
1543  * \param number_plan mISDN numbering plan
1544  *
1545  * \return PartyNumber numbering plan
1546  */
1547 static unsigned misdn_to_PartyNumber_plan(enum mISDN_NUMBER_PLAN number_plan)
1548 {
1549         unsigned party_plan;
1550
1551         switch (number_plan) {
1552         default:
1553         case NUMPLAN_UNKNOWN:
1554                 party_plan = 0;/* unknown */
1555                 break;
1556
1557         case NUMPLAN_ISDN:
1558                 party_plan = 1;/* public */
1559                 break;
1560
1561         case NUMPLAN_DATA:
1562                 party_plan = 3;/* data */
1563                 break;
1564
1565         case NUMPLAN_TELEX:
1566                 party_plan = 4;/* telex */
1567                 break;
1568
1569         case NUMPLAN_NATIONAL:
1570                 party_plan = 8;/* nationalStandard */
1571                 break;
1572
1573         case NUMPLAN_PRIVATE:
1574                 party_plan = 5;/* private */
1575                 break;
1576         }
1577
1578         return party_plan;
1579 }
1580 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1581
1582 #if defined(AST_MISDN_ENHANCEMENTS)
1583 /*!
1584  * \internal
1585  * \brief Convert PartyNumber numbering plan to mISDN numbering plan
1586  *
1587  * \param party_plan PartyNumber numbering plan
1588  *
1589  * \return mISDN numbering plan
1590  */
1591 static enum mISDN_NUMBER_PLAN PartyNumber_to_misdn_plan(unsigned party_plan)
1592 {
1593         enum mISDN_NUMBER_PLAN number_plan;
1594
1595         switch (party_plan) {
1596         default:
1597         case 0:/* unknown */
1598                 number_plan = NUMPLAN_UNKNOWN;
1599                 break;
1600         case 1:/* public */
1601                 number_plan = NUMPLAN_ISDN;
1602                 break;
1603         case 3:/* data */
1604                 number_plan = NUMPLAN_DATA;
1605                 break;
1606         case 4:/* telex */
1607                 number_plan = NUMPLAN_TELEX;
1608                 break;
1609         case 8:/* nationalStandard */
1610                 number_plan = NUMPLAN_NATIONAL;
1611                 break;
1612         case 5:/* private */
1613                 number_plan = NUMPLAN_PRIVATE;
1614                 break;
1615         }
1616
1617         return number_plan;
1618 }
1619 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1620
1621 #if defined(AST_MISDN_ENHANCEMENTS)
1622 /*!
1623  * \internal
1624  * \brief Convert mISDN type-of-number to PartyNumber public type-of-number
1625  *
1626  * \param ton mISDN type-of-number
1627  *
1628  * \return PartyNumber public type-of-number
1629  */
1630 static unsigned misdn_to_PartyNumber_ton_public(enum mISDN_NUMBER_TYPE ton)
1631 {
1632         unsigned party_ton;
1633
1634         switch (ton) {
1635         default:
1636         case NUMTYPE_UNKNOWN:
1637                 party_ton = 0;/* unknown */
1638                 break;
1639
1640         case NUMTYPE_INTERNATIONAL:
1641                 party_ton = 1;/* internationalNumber */
1642                 break;
1643
1644         case NUMTYPE_NATIONAL:
1645                 party_ton = 2;/* nationalNumber */
1646                 break;
1647
1648         case NUMTYPE_NETWORK_SPECIFIC:
1649                 party_ton = 3;/* networkSpecificNumber */
1650                 break;
1651
1652         case NUMTYPE_SUBSCRIBER:
1653                 party_ton = 4;/* subscriberNumber */
1654                 break;
1655
1656         case NUMTYPE_ABBREVIATED:
1657                 party_ton = 6;/* abbreviatedNumber */
1658                 break;
1659         }
1660
1661         return party_ton;
1662 }
1663 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1664
1665 #if defined(AST_MISDN_ENHANCEMENTS)
1666 /*!
1667  * \internal
1668  * \brief Convert the PartyNumber public type-of-number to mISDN type-of-number
1669  *
1670  * \param party_ton PartyNumber public type-of-number
1671  *
1672  * \return mISDN type-of-number
1673  */
1674 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_public(unsigned party_ton)
1675 {
1676         enum mISDN_NUMBER_TYPE ton;
1677
1678         switch (party_ton) {
1679         default:
1680         case 0:/* unknown */
1681                 ton = NUMTYPE_UNKNOWN;
1682                 break;
1683
1684         case 1:/* internationalNumber */
1685                 ton = NUMTYPE_INTERNATIONAL;
1686                 break;
1687
1688         case 2:/* nationalNumber */
1689                 ton = NUMTYPE_NATIONAL;
1690                 break;
1691
1692         case 3:/* networkSpecificNumber */
1693                 ton = NUMTYPE_NETWORK_SPECIFIC;
1694                 break;
1695
1696         case 4:/* subscriberNumber */
1697                 ton = NUMTYPE_SUBSCRIBER;
1698                 break;
1699
1700         case 6:/* abbreviatedNumber */
1701                 ton = NUMTYPE_ABBREVIATED;
1702                 break;
1703         }
1704
1705         return ton;
1706 }
1707 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1708
1709 #if defined(AST_MISDN_ENHANCEMENTS)
1710 /*!
1711  * \internal
1712  * \brief Convert mISDN type-of-number to PartyNumber private type-of-number
1713  *
1714  * \param ton mISDN type-of-number
1715  *
1716  * \return PartyNumber private type-of-number
1717  */
1718 static unsigned misdn_to_PartyNumber_ton_private(enum mISDN_NUMBER_TYPE ton)
1719 {
1720         unsigned party_ton;
1721
1722         switch (ton) {
1723         default:
1724         case NUMTYPE_UNKNOWN:
1725                 party_ton = 0;/* unknown */
1726                 break;
1727
1728         case NUMTYPE_INTERNATIONAL:
1729                 party_ton = 1;/* level2RegionalNumber */
1730                 break;
1731
1732         case NUMTYPE_NATIONAL:
1733                 party_ton = 2;/* level1RegionalNumber */
1734                 break;
1735
1736         case NUMTYPE_NETWORK_SPECIFIC:
1737                 party_ton = 3;/* pTNSpecificNumber */
1738                 break;
1739
1740         case NUMTYPE_SUBSCRIBER:
1741                 party_ton = 4;/* localNumber */
1742                 break;
1743
1744         case NUMTYPE_ABBREVIATED:
1745                 party_ton = 6;/* abbreviatedNumber */
1746                 break;
1747         }
1748
1749         return party_ton;
1750 }
1751 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1752
1753 #if defined(AST_MISDN_ENHANCEMENTS)
1754 /*!
1755  * \internal
1756  * \brief Convert the PartyNumber private type-of-number to mISDN type-of-number
1757  *
1758  * \param party_ton PartyNumber private type-of-number
1759  *
1760  * \return mISDN type-of-number
1761  */
1762 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_private(unsigned party_ton)
1763 {
1764         enum mISDN_NUMBER_TYPE ton;
1765
1766         switch (party_ton) {
1767         default:
1768         case 0:/* unknown */
1769                 ton = NUMTYPE_UNKNOWN;
1770                 break;
1771
1772         case 1:/* level2RegionalNumber */
1773                 ton = NUMTYPE_INTERNATIONAL;
1774                 break;
1775
1776         case 2:/* level1RegionalNumber */
1777                 ton = NUMTYPE_NATIONAL;
1778                 break;
1779
1780         case 3:/* pTNSpecificNumber */
1781                 ton = NUMTYPE_NETWORK_SPECIFIC;
1782                 break;
1783
1784         case 4:/* localNumber */
1785                 ton = NUMTYPE_SUBSCRIBER;
1786                 break;
1787
1788         case 6:/* abbreviatedNumber */
1789                 ton = NUMTYPE_ABBREVIATED;
1790                 break;
1791         }
1792
1793         return ton;
1794 }
1795 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1796
1797 /*!
1798  * \internal
1799  * \brief Convert the mISDN type of number code to a string
1800  *
1801  * \param number_type mISDN type of number code.
1802  *
1803  * \return The mISDN type of number code as a string
1804  */
1805 static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
1806 {
1807         const char *str;
1808
1809         switch (number_type) {
1810         default:
1811         case NUMTYPE_UNKNOWN:
1812                 str = "Unknown";
1813                 break;
1814
1815         case NUMTYPE_INTERNATIONAL:
1816                 str = "International";
1817                 break;
1818
1819         case NUMTYPE_NATIONAL:
1820                 str = "National";
1821                 break;
1822
1823         case NUMTYPE_NETWORK_SPECIFIC:
1824                 str = "Network Specific";
1825                 break;
1826
1827         case NUMTYPE_SUBSCRIBER:
1828                 str = "Subscriber";
1829                 break;
1830
1831         case NUMTYPE_ABBREVIATED:
1832                 str = "Abbreviated";
1833                 break;
1834         }
1835
1836         return str;
1837 }
1838
1839 /*!
1840  * \internal
1841  * \brief Convert the mISDN type of number code to Asterisk type of number code
1842  *
1843  * \param number_type mISDN type of number code.
1844  *
1845  * \return Asterisk type of number code
1846  */
1847 static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
1848 {
1849         int ast_number_type;
1850
1851         switch (number_type) {
1852         default:
1853         case NUMTYPE_UNKNOWN:
1854                 ast_number_type = NUMTYPE_UNKNOWN << 4;
1855                 break;
1856
1857         case NUMTYPE_INTERNATIONAL:
1858                 ast_number_type = NUMTYPE_INTERNATIONAL << 4;
1859                 break;
1860
1861         case NUMTYPE_NATIONAL:
1862                 ast_number_type = NUMTYPE_NATIONAL << 4;
1863                 break;
1864
1865         case NUMTYPE_NETWORK_SPECIFIC:
1866                 ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
1867                 break;
1868
1869         case NUMTYPE_SUBSCRIBER:
1870                 ast_number_type = NUMTYPE_SUBSCRIBER << 4;
1871                 break;
1872
1873         case NUMTYPE_ABBREVIATED:
1874                 ast_number_type = NUMTYPE_ABBREVIATED << 4;
1875                 break;
1876         }
1877
1878         return ast_number_type;
1879 }
1880
1881 /*!
1882  * \internal
1883  * \brief Convert the Asterisk type of number code to mISDN type of number code
1884  *
1885  * \param ast_number_type Asterisk type of number code.
1886  *
1887  * \return mISDN type of number code
1888  */
1889 static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
1890 {
1891         enum mISDN_NUMBER_TYPE number_type;
1892
1893         switch ((ast_number_type >> 4) & 0x07) {
1894         default:
1895         case NUMTYPE_UNKNOWN:
1896                 number_type = NUMTYPE_UNKNOWN;
1897                 break;
1898
1899         case NUMTYPE_INTERNATIONAL:
1900                 number_type = NUMTYPE_INTERNATIONAL;
1901                 break;
1902
1903         case NUMTYPE_NATIONAL:
1904                 number_type = NUMTYPE_NATIONAL;
1905                 break;
1906
1907         case NUMTYPE_NETWORK_SPECIFIC:
1908                 number_type = NUMTYPE_NETWORK_SPECIFIC;
1909                 break;
1910
1911         case NUMTYPE_SUBSCRIBER:
1912                 number_type = NUMTYPE_SUBSCRIBER;
1913                 break;
1914
1915         case NUMTYPE_ABBREVIATED:
1916                 number_type = NUMTYPE_ABBREVIATED;
1917                 break;
1918         }
1919
1920         return number_type;
1921 }
1922
1923 /*!
1924  * \internal
1925  * \brief Convert the mISDN numbering plan code to a string
1926  *
1927  * \param number_plan mISDN numbering plan code.
1928  *
1929  * \return The mISDN numbering plan code as a string
1930  */
1931 static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
1932 {
1933         const char *str;
1934
1935         switch (number_plan) {
1936         default:
1937         case NUMPLAN_UNKNOWN:
1938                 str = "Unknown";
1939                 break;
1940
1941         case NUMPLAN_ISDN:
1942                 str = "ISDN";
1943                 break;
1944
1945         case NUMPLAN_DATA:
1946                 str = "Data";
1947                 break;
1948
1949         case NUMPLAN_TELEX:
1950                 str = "Telex";
1951                 break;
1952
1953         case NUMPLAN_NATIONAL:
1954                 str = "National";
1955                 break;
1956
1957         case NUMPLAN_PRIVATE:
1958                 str = "Private";
1959                 break;
1960         }
1961
1962         return str;
1963 }
1964
1965 /*!
1966  * \internal
1967  * \brief Convert the mISDN numbering plan code to Asterisk numbering plan code
1968  *
1969  * \param number_plan mISDN numbering plan code.
1970  *
1971  * \return Asterisk numbering plan code
1972  */
1973 static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
1974 {
1975         int ast_number_plan;
1976
1977         switch (number_plan) {
1978         default:
1979         case NUMPLAN_UNKNOWN:
1980                 ast_number_plan = NUMPLAN_UNKNOWN;
1981                 break;
1982
1983         case NUMPLAN_ISDN:
1984                 ast_number_plan = NUMPLAN_ISDN;
1985                 break;
1986
1987         case NUMPLAN_DATA:
1988                 ast_number_plan = NUMPLAN_DATA;
1989                 break;
1990
1991         case NUMPLAN_TELEX:
1992                 ast_number_plan = NUMPLAN_TELEX;
1993                 break;
1994
1995         case NUMPLAN_NATIONAL:
1996                 ast_number_plan = NUMPLAN_NATIONAL;
1997                 break;
1998
1999         case NUMPLAN_PRIVATE:
2000                 ast_number_plan = NUMPLAN_PRIVATE;
2001                 break;
2002         }
2003
2004         return ast_number_plan;
2005 }
2006
2007 /*!
2008  * \internal
2009  * \brief Convert the Asterisk numbering plan code to mISDN numbering plan code
2010  *
2011  * \param ast_number_plan Asterisk numbering plan code.
2012  *
2013  * \return mISDN numbering plan code
2014  */
2015 static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
2016 {
2017         enum mISDN_NUMBER_PLAN number_plan;
2018
2019         switch (ast_number_plan & 0x0F) {
2020         default:
2021         case NUMPLAN_UNKNOWN:
2022                 number_plan = NUMPLAN_UNKNOWN;
2023                 break;
2024
2025         case NUMPLAN_ISDN:
2026                 number_plan = NUMPLAN_ISDN;
2027                 break;
2028
2029         case NUMPLAN_DATA:
2030                 number_plan = NUMPLAN_DATA;
2031                 break;
2032
2033         case NUMPLAN_TELEX:
2034                 number_plan = NUMPLAN_TELEX;
2035                 break;
2036
2037         case NUMPLAN_NATIONAL:
2038                 number_plan = NUMPLAN_NATIONAL;
2039                 break;
2040
2041         case NUMPLAN_PRIVATE:
2042                 number_plan = NUMPLAN_PRIVATE;
2043                 break;
2044         }
2045
2046         return number_plan;
2047 }
2048
2049 /*!
2050  * \internal
2051  * \brief Convert the mISDN presentation code to a string
2052  *
2053  * \param presentation mISDN number presentation restriction code.
2054  *
2055  * \return The mISDN presentation code as a string
2056  */
2057 static const char *misdn_to_str_pres(int presentation)
2058 {
2059         const char *str;
2060
2061         switch (presentation) {
2062         case 0:
2063                 str = "Allowed";
2064                 break;
2065
2066         case 1:
2067                 str = "Restricted";
2068                 break;
2069
2070         case 2:
2071                 str = "Unavailable";
2072                 break;
2073
2074         default:
2075                 str = "Unknown";
2076                 break;
2077         }
2078
2079         return str;
2080 }
2081
2082 /*!
2083  * \internal
2084  * \brief Convert the mISDN presentation code to Asterisk presentation code
2085  *
2086  * \param presentation mISDN number presentation restriction code.
2087  *
2088  * \return Asterisk presentation code
2089  */
2090 static int misdn_to_ast_pres(int presentation)
2091 {
2092         switch (presentation) {
2093         default:
2094         case 0:
2095                 presentation = AST_PRES_ALLOWED;
2096                 break;
2097
2098         case 1:
2099                 presentation = AST_PRES_RESTRICTED;
2100                 break;
2101
2102         case 2:
2103                 presentation = AST_PRES_UNAVAILABLE;
2104                 break;
2105         }
2106
2107         return presentation;
2108 }
2109
2110 /*!
2111  * \internal
2112  * \brief Convert the Asterisk presentation code to mISDN presentation code
2113  *
2114  * \param presentation Asterisk number presentation restriction code.
2115  *
2116  * \return mISDN presentation code
2117  */
2118 static int ast_to_misdn_pres(int presentation)
2119 {
2120         switch (presentation & AST_PRES_RESTRICTION) {
2121         default:
2122         case AST_PRES_ALLOWED:
2123                 presentation = 0;
2124                 break;
2125
2126         case AST_PRES_RESTRICTED:
2127                 presentation = 1;
2128                 break;
2129
2130         case AST_PRES_UNAVAILABLE:
2131                 presentation = 2;
2132                 break;
2133         }
2134
2135         return presentation;
2136 }
2137
2138 /*!
2139  * \internal
2140  * \brief Convert the mISDN screening code to a string
2141  *
2142  * \param screening mISDN number screening code.
2143  *
2144  * \return The mISDN screening code as a string
2145  */
2146 static const char *misdn_to_str_screen(int screening)
2147 {
2148         const char *str;
2149
2150         switch (screening) {
2151         case 0:
2152                 str = "Unscreened";
2153                 break;
2154
2155         case 1:
2156                 str = "Passed Screen";
2157                 break;
2158
2159         case 2:
2160                 str = "Failed Screen";
2161                 break;
2162
2163         case 3:
2164                 str = "Network Number";
2165                 break;
2166
2167         default:
2168                 str = "Unknown";
2169                 break;
2170         }
2171
2172         return str;
2173 }
2174
2175 /*!
2176  * \internal
2177  * \brief Convert the mISDN screening code to Asterisk screening code
2178  *
2179  * \param screening mISDN number screening code.
2180  *
2181  * \return Asterisk screening code
2182  */
2183 static int misdn_to_ast_screen(int screening)
2184 {
2185         switch (screening) {
2186         default:
2187         case 0:
2188                 screening = AST_PRES_USER_NUMBER_UNSCREENED;
2189                 break;
2190
2191         case 1:
2192                 screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
2193                 break;
2194
2195         case 2:
2196                 screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
2197                 break;
2198
2199         case 3:
2200                 screening = AST_PRES_NETWORK_NUMBER;
2201                 break;
2202         }
2203
2204         return screening;
2205 }
2206
2207 /*!
2208  * \internal
2209  * \brief Convert the Asterisk screening code to mISDN screening code
2210  *
2211  * \param screening Asterisk number screening code.
2212  *
2213  * \return mISDN screening code
2214  */
2215 static int ast_to_misdn_screen(int screening)
2216 {
2217         switch (screening & AST_PRES_NUMBER_TYPE) {
2218         default:
2219         case AST_PRES_USER_NUMBER_UNSCREENED:
2220                 screening = 0;
2221                 break;
2222
2223         case AST_PRES_USER_NUMBER_PASSED_SCREEN:
2224                 screening = 1;
2225                 break;
2226
2227         case AST_PRES_USER_NUMBER_FAILED_SCREEN:
2228                 screening = 2;
2229                 break;
2230
2231         case AST_PRES_NETWORK_NUMBER:
2232                 screening = 3;
2233                 break;
2234         }
2235
2236         return screening;
2237 }
2238
2239 /*!
2240  * \internal
2241  * \brief Convert Asterisk redirecting reason to mISDN redirecting reason code.
2242  *
2243  * \param ast Asterisk redirecting reason code.
2244  *
2245  * \return mISDN reason code
2246  */
2247 static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
2248 {
2249         unsigned index;
2250
2251         static const struct misdn_reasons {
2252                 enum AST_REDIRECTING_REASON ast;
2253                 enum mISDN_REDIRECTING_REASON q931;
2254         } misdn_reason_table[] = {
2255         /* *INDENT-OFF* */
2256                 { AST_REDIRECTING_REASON_UNKNOWN,        mISDN_REDIRECTING_REASON_UNKNOWN },
2257                 { AST_REDIRECTING_REASON_USER_BUSY,      mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
2258                 { AST_REDIRECTING_REASON_NO_ANSWER,      mISDN_REDIRECTING_REASON_NO_REPLY },
2259                 { AST_REDIRECTING_REASON_UNAVAILABLE,    mISDN_REDIRECTING_REASON_NO_REPLY },
2260                 { AST_REDIRECTING_REASON_UNCONDITIONAL,  mISDN_REDIRECTING_REASON_CALL_FWD },
2261                 { AST_REDIRECTING_REASON_TIME_OF_DAY,    mISDN_REDIRECTING_REASON_UNKNOWN },
2262                 { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
2263                 { AST_REDIRECTING_REASON_DEFLECTION,     mISDN_REDIRECTING_REASON_DEFLECTION },
2264                 { AST_REDIRECTING_REASON_FOLLOW_ME,      mISDN_REDIRECTING_REASON_UNKNOWN },
2265                 { AST_REDIRECTING_REASON_OUT_OF_ORDER,   mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
2266                 { AST_REDIRECTING_REASON_AWAY,           mISDN_REDIRECTING_REASON_UNKNOWN },
2267                 { AST_REDIRECTING_REASON_CALL_FWD_DTE,   mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
2268         /* *INDENT-ON* */
2269         };
2270
2271         for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
2272                 if (misdn_reason_table[index].ast == ast) {
2273                         return misdn_reason_table[index].q931;
2274                 }
2275         }
2276         return mISDN_REDIRECTING_REASON_UNKNOWN;
2277 }
2278
2279 /*!
2280  * \internal
2281  * \brief Convert the mISDN redirecting reason to Asterisk redirecting reason code
2282  *
2283  * \param q931 mISDN redirecting reason code.
2284  *
2285  * \return Asterisk redirecting reason code
2286  */
2287 static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
2288 {
2289         enum AST_REDIRECTING_REASON ast;
2290
2291         switch (q931) {
2292         default:
2293         case mISDN_REDIRECTING_REASON_UNKNOWN:
2294                 ast = AST_REDIRECTING_REASON_UNKNOWN;
2295                 break;
2296
2297         case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
2298                 ast = AST_REDIRECTING_REASON_USER_BUSY;
2299                 break;
2300
2301         case mISDN_REDIRECTING_REASON_NO_REPLY:
2302                 ast = AST_REDIRECTING_REASON_NO_ANSWER;
2303                 break;
2304
2305         case mISDN_REDIRECTING_REASON_DEFLECTION:
2306                 ast = AST_REDIRECTING_REASON_DEFLECTION;
2307                 break;
2308
2309         case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
2310                 ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
2311                 break;
2312
2313         case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
2314                 ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
2315                 break;
2316
2317         case mISDN_REDIRECTING_REASON_CALL_FWD:
2318                 ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
2319                 break;
2320         }
2321
2322         return ast;
2323 }
2324
2325
2326
2327 struct allowed_bearers {
2328         char *name;         /*!< Bearer capability name string used in /etc/misdn.conf allowed_bearers */
2329         char *display;      /*!< Bearer capability displayable name */
2330         int cap;            /*!< SETUP message bearer capability field code value */
2331         int deprecated;     /*!< TRUE if this entry is deprecated. (Misspelled or bad name to use) */
2332 };
2333
2334 /* *INDENT-OFF* */
2335 static const struct allowed_bearers allowed_bearers_array[] = {
2336         /* Name,                      Displayable Name       Bearer Capability,                    Deprecated */
2337         { "speech",                  "Speech",               INFO_CAPABILITY_SPEECH,               0 },
2338         { "3_1khz",                  "3.1KHz Audio",         INFO_CAPABILITY_AUDIO_3_1K,           0 },
2339         { "digital_unrestricted",    "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED, 0 },
2340         { "digital_restricted",      "Restricted Digital",   INFO_CAPABILITY_DIGITAL_RESTRICTED,   0 },
2341         { "digital_restriced",       "Restricted Digital",   INFO_CAPABILITY_DIGITAL_RESTRICTED,   1 }, /* Allow misspelling for backwards compatibility */
2342         { "video",                   "Video",                INFO_CAPABILITY_VIDEO,                0 }
2343 };
2344 /* *INDENT-ON* */
2345
2346 static const char *bearer2str(int cap)
2347 {
2348         unsigned index;
2349
2350         for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
2351                 if (allowed_bearers_array[index].cap == cap) {
2352                         return allowed_bearers_array[index].display;
2353                 }
2354         }
2355
2356         return "Unknown Bearer";
2357 }
2358
2359 #if defined(AST_MISDN_ENHANCEMENTS)
2360 /*!
2361  * \internal
2362  * \brief Fill in facility PartyNumber information
2363  *
2364  * \param party PartyNumber structure to fill in.
2365  * \param id Information to put in PartyNumber structure.
2366  *
2367  * \return Nothing
2368  */
2369 static void misdn_PartyNumber_fill(struct FacPartyNumber *party, const struct misdn_party_id *id)
2370 {
2371         ast_copy_string((char *) party->Number, id->number, sizeof(party->Number));
2372         party->LengthOfNumber = strlen((char *) party->Number);
2373         party->Type = misdn_to_PartyNumber_plan(id->number_plan);
2374         switch (party->Type) {
2375         case 1:/* public */
2376                 party->TypeOfNumber = misdn_to_PartyNumber_ton_public(id->number_type);
2377                 break;
2378         case 5:/* private */
2379                 party->TypeOfNumber = misdn_to_PartyNumber_ton_private(id->number_type);
2380                 break;
2381         default:
2382                 party->TypeOfNumber = 0;/* Don't care */
2383                 break;
2384         }
2385 }
2386 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2387
2388 #if defined(AST_MISDN_ENHANCEMENTS)
2389 /*!
2390  * \internal
2391  * \brief Extract the information from PartyNumber
2392  *
2393  * \param id Where to put extracted PartyNumber information
2394  * \param party PartyNumber information to extract
2395  *
2396  * \return Nothing
2397  */
2398 static void misdn_PartyNumber_extract(struct misdn_party_id *id, const struct FacPartyNumber *party)
2399 {
2400         if (party->LengthOfNumber) {
2401                 ast_copy_string(id->number, (char *) party->Number, sizeof(id->number));
2402                 id->number_plan = PartyNumber_to_misdn_plan(party->Type);
2403                 switch (party->Type) {
2404                 case 1:/* public */
2405                         id->number_type = PartyNumber_to_misdn_ton_public(party->TypeOfNumber);
2406                         break;
2407                 case 5:/* private */
2408                         id->number_type = PartyNumber_to_misdn_ton_private(party->TypeOfNumber);
2409                         break;
2410                 default:
2411                         id->number_type = NUMTYPE_UNKNOWN;
2412                         break;
2413                 }
2414         } else {
2415                 /* Number not present */
2416                 id->number_type = NUMTYPE_UNKNOWN;
2417                 id->number_plan = NUMPLAN_ISDN;
2418                 id->number[0] = 0;
2419         }
2420 }
2421 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2422
2423 #if defined(AST_MISDN_ENHANCEMENTS)
2424 /*!
2425  * \internal
2426  * \brief Fill in facility Address information
2427  *
2428  * \param Address Address structure to fill in.
2429  * \param id Information to put in Address structure.
2430  *
2431  * \return Nothing
2432  */
2433 static void misdn_Address_fill(struct FacAddress *Address, const struct misdn_party_id *id)
2434 {
2435         misdn_PartyNumber_fill(&Address->Party, id);
2436
2437         /* Subaddresses are not supported yet */
2438         Address->Subaddress.Length = 0;
2439 }
2440 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2441
2442 #if defined(AST_MISDN_ENHANCEMENTS)
2443 /*!
2444  * \internal
2445  * \brief Fill in facility PresentedNumberUnscreened information
2446  *
2447  * \param presented PresentedNumberUnscreened structure to fill in.
2448  * \param id Information to put in PresentedNumberUnscreened structure.
2449  *
2450  * \return Nothing
2451  */
2452 static void misdn_PresentedNumberUnscreened_fill(struct FacPresentedNumberUnscreened *presented, const struct misdn_party_id *id)
2453 {
2454         presented->Type = misdn_to_PresentedNumberUnscreened_type(id->presentation, id->number[0] ? 1 : 0);
2455         misdn_PartyNumber_fill(&presented->Unscreened, id);
2456 }
2457 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2458
2459 #if defined(AST_MISDN_ENHANCEMENTS)
2460 /*!
2461  * \internal
2462  * \brief Extract the information from PartyNumber
2463  *
2464  * \param id Where to put extracted PresentedNumberUnscreened information
2465  * \param presented PresentedNumberUnscreened information to extract
2466  *
2467  * \return Nothing
2468  */
2469 static void misdn_PresentedNumberUnscreened_extract(struct misdn_party_id *id, const struct FacPresentedNumberUnscreened *presented)
2470 {
2471         id->presentation = PresentedNumberUnscreened_to_misdn_pres(presented->Type);
2472         id->screening = 0;/* unscreened */
2473         switch (presented->Type) {
2474         case 0:/* presentationAllowedNumber */
2475         case 3:/* presentationRestrictedNumber */
2476                 misdn_PartyNumber_extract(id, &presented->Unscreened);
2477                 break;
2478         case 1:/* presentationRestricted */
2479         case 2:/* numberNotAvailableDueToInterworking */
2480         default:
2481                 /* Number not present (And uninitialized so do not even look at it!) */
2482                 id->number_type = NUMTYPE_UNKNOWN;
2483                 id->number_plan = NUMPLAN_ISDN;
2484                 id->number[0] = 0;
2485                 break;
2486         }
2487 }
2488 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2489
2490 #if defined(AST_MISDN_ENHANCEMENTS)
2491 static const char Level_Spacing[] = "          ";/* Work for up to 10 levels */
2492 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2493
2494 #if defined(AST_MISDN_ENHANCEMENTS)
2495 static void print_facility_PartyNumber(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2496 {
2497         if (Party->LengthOfNumber) {
2498                 const char *Spacing;
2499
2500                 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2501                 chan_misdn_log(1, bc->port, " -->%s PartyNumber: Type:%d\n",
2502                         Spacing, Party->Type);
2503                 switch (Party->Type) {
2504                 case 0: /* Unknown PartyNumber */
2505                         chan_misdn_log(1, bc->port, " -->%s  Unknown: %s\n",
2506                                 Spacing, Party->Number);
2507                         break;
2508                 case 1: /* Public PartyNumber */
2509                         chan_misdn_log(1, bc->port, " -->%s  Public TON:%d %s\n",
2510                                 Spacing, Party->TypeOfNumber, Party->Number);
2511                         break;
2512                 case 2: /* NSAP encoded PartyNumber */
2513                         chan_misdn_log(1, bc->port, " -->%s  NSAP: %s\n",
2514                                 Spacing, Party->Number);
2515                         break;
2516                 case 3: /* Data PartyNumber (Not used) */
2517                         chan_misdn_log(1, bc->port, " -->%s  Data: %s\n",
2518                                 Spacing, Party->Number);
2519                         break;
2520                 case 4: /* Telex PartyNumber (Not used) */
2521                         chan_misdn_log(1, bc->port, " -->%s  Telex: %s\n",
2522                                 Spacing, Party->Number);
2523                         break;
2524                 case 5: /* Private PartyNumber */
2525                         chan_misdn_log(1, bc->port, " -->%s  Private TON:%d %s\n",
2526                                 Spacing, Party->TypeOfNumber, Party->Number);
2527                         break;
2528                 case 8: /* National Standard PartyNumber (Not used) */
2529                         chan_misdn_log(1, bc->port, " -->%s  National: %s\n",
2530                                 Spacing, Party->Number);
2531                         break;
2532                 default:
2533                         break;
2534                 }
2535         }
2536 }
2537 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2538
2539 #if defined(AST_MISDN_ENHANCEMENTS)
2540 static void print_facility_Subaddress(unsigned Level, const struct FacPartySubaddress *Subaddress, const struct misdn_bchannel *bc)
2541 {
2542         if (Subaddress->Length) {
2543                 const char *Spacing;
2544
2545                 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2546                 chan_misdn_log(1, bc->port, " -->%s Subaddress: Type:%d\n",
2547                         Spacing, Subaddress->Type);
2548                 switch (Subaddress->Type) {
2549                 case 0: /* UserSpecified */
2550                         if (Subaddress->u.UserSpecified.OddCountPresent) {
2551                                 chan_misdn_log(1, bc->port, " -->%s  User BCD OddCount:%d NumOctets:%d\n",
2552                                         Spacing, Subaddress->u.UserSpecified.OddCount, Subaddress->Length);
2553                         } else {
2554                                 chan_misdn_log(1, bc->port, " -->%s  User: %s\n",
2555                                         Spacing, Subaddress->u.UserSpecified.Information);
2556                         }
2557                         break;
2558                 case 1: /* NSAP */
2559                         chan_misdn_log(1, bc->port, " -->%s  NSAP: %s\n",
2560                                 Spacing, Subaddress->u.Nsap);
2561                         break;
2562                 default:
2563                         break;
2564                 }
2565         }
2566 }
2567 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2568
2569 #if defined(AST_MISDN_ENHANCEMENTS)
2570 static void print_facility_Address(unsigned Level, const struct FacAddress *Address, const struct misdn_bchannel *bc)
2571 {
2572         print_facility_PartyNumber(Level, &Address->Party, bc);
2573         print_facility_Subaddress(Level, &Address->Subaddress, bc);
2574 }
2575 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2576
2577 #if defined(AST_MISDN_ENHANCEMENTS)
2578 static void print_facility_PresentedNumberUnscreened(unsigned Level, const struct FacPresentedNumberUnscreened *Presented, const struct misdn_bchannel *bc)
2579 {
2580         const char *Spacing;
2581
2582         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2583         chan_misdn_log(1, bc->port, " -->%s Unscreened Type:%d\n", Spacing, Presented->Type);
2584         switch (Presented->Type) {
2585         case 0: /* presentationAllowedNumber */
2586                 chan_misdn_log(1, bc->port, " -->%s  Allowed:\n", Spacing);
2587                 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2588                 break;
2589         case 1: /* presentationRestricted */
2590                 chan_misdn_log(1, bc->port, " -->%s  Restricted\n", Spacing);
2591                 break;
2592         case 2: /* numberNotAvailableDueToInterworking */
2593                 chan_misdn_log(1, bc->port, " -->%s  Not Available\n", Spacing);
2594                 break;
2595         case 3: /* presentationRestrictedNumber */
2596                 chan_misdn_log(1, bc->port, " -->%s  Restricted:\n", Spacing);
2597                 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
2598                 break;
2599         default:
2600                 break;
2601         }
2602 }
2603 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2604
2605 #if defined(AST_MISDN_ENHANCEMENTS)
2606 static void print_facility_AddressScreened(unsigned Level, const struct FacAddressScreened *Address, const struct misdn_bchannel *bc)
2607 {
2608         const char *Spacing;
2609
2610         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2611         chan_misdn_log(1, bc->port, " -->%s ScreeningIndicator:%d\n", Spacing, Address->ScreeningIndicator);
2612         print_facility_PartyNumber(Level, &Address->Party, bc);
2613         print_facility_Subaddress(Level, &Address->Subaddress, bc);
2614 }
2615 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2616
2617 #if defined(AST_MISDN_ENHANCEMENTS)
2618 static void print_facility_PresentedAddressScreened(unsigned Level, const struct FacPresentedAddressScreened *Presented, const struct misdn_bchannel *bc)
2619 {
2620         const char *Spacing;
2621
2622         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2623         chan_misdn_log(1, bc->port, " -->%s Screened Type:%d\n", Spacing, Presented->Type);
2624         switch (Presented->Type) {
2625         case 0: /* presentationAllowedAddress */
2626                 chan_misdn_log(1, bc->port, " -->%s  Allowed:\n", Spacing);
2627                 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2628                 break;
2629         case 1: /* presentationRestricted */
2630                 chan_misdn_log(1, bc->port, " -->%s  Restricted\n", Spacing);
2631                 break;
2632         case 2: /* numberNotAvailableDueToInterworking */
2633                 chan_misdn_log(1, bc->port, " -->%s  Not Available\n", Spacing);
2634                 break;
2635         case 3: /* presentationRestrictedAddress */
2636                 chan_misdn_log(1, bc->port, " -->%s  Restricted:\n", Spacing);
2637                 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
2638                 break;
2639         default:
2640                 break;
2641         }
2642 }
2643 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2644
2645 #if defined(AST_MISDN_ENHANCEMENTS)
2646 static void print_facility_Q931_Bc_Hlc_Llc(unsigned Level, const struct Q931_Bc_Hlc_Llc *Q931ie, const struct misdn_bchannel *bc)
2647 {
2648         const char *Spacing;
2649
2650         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2651         chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2652         if (Q931ie->Bc.Length) {
2653                 chan_misdn_log(1, bc->port, " -->%s  Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2654         }
2655         if (Q931ie->Hlc.Length) {
2656                 chan_misdn_log(1, bc->port, " -->%s  Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2657         }
2658         if (Q931ie->Llc.Length) {
2659                 chan_misdn_log(1, bc->port, " -->%s  Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2660         }
2661 }
2662 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2663
2664 #if defined(AST_MISDN_ENHANCEMENTS)
2665 static void print_facility_Q931_Bc_Hlc_Llc_Uu(unsigned Level, const struct Q931_Bc_Hlc_Llc_Uu *Q931ie, const struct misdn_bchannel *bc)
2666 {
2667         const char *Spacing;
2668
2669         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2670         chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
2671         if (Q931ie->Bc.Length) {
2672                 chan_misdn_log(1, bc->port, " -->%s  Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
2673         }
2674         if (Q931ie->Hlc.Length) {
2675                 chan_misdn_log(1, bc->port, " -->%s  Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
2676         }
2677         if (Q931ie->Llc.Length) {
2678                 chan_misdn_log(1, bc->port, " -->%s  Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
2679         }
2680         if (Q931ie->UserInfo.Length) {
2681                 chan_misdn_log(1, bc->port, " -->%s  UserInfo Len:%d\n", Spacing, Q931ie->UserInfo.Length);
2682         }
2683 }
2684 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2685
2686 #if defined(AST_MISDN_ENHANCEMENTS)
2687 static void print_facility_CallInformation(unsigned Level, const struct FacCallInformation *CallInfo, const struct misdn_bchannel *bc)
2688 {
2689         const char *Spacing;
2690
2691         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2692         chan_misdn_log(1, bc->port, " -->%s CCBSReference:%d\n",
2693                 Spacing, CallInfo->CCBSReference);
2694         chan_misdn_log(1, bc->port, " -->%s AddressOfB:\n", Spacing);
2695         print_facility_Address(Level + 1, &CallInfo->AddressOfB, bc);
2696         print_facility_Q931_Bc_Hlc_Llc(Level, &CallInfo->Q931ie, bc);
2697         if (CallInfo->SubaddressOfA.Length) {
2698                 chan_misdn_log(1, bc->port, " -->%s SubaddressOfA:\n", Spacing);
2699                 print_facility_Subaddress(Level + 1, &CallInfo->SubaddressOfA, bc);
2700         }
2701 }
2702 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2703
2704 #if defined(AST_MISDN_ENHANCEMENTS)
2705 static void print_facility_ServedUserNr(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
2706 {
2707         const char *Spacing;
2708
2709         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2710         if (Party->LengthOfNumber) {
2711                 print_facility_PartyNumber(Level, Party, bc);
2712         } else {
2713                 chan_misdn_log(1, bc->port, " -->%s All Numbers\n", Spacing);
2714         }
2715 }
2716 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2717
2718 #if defined(AST_MISDN_ENHANCEMENTS)
2719 static void print_facility_IntResult(unsigned Level, const struct FacForwardingRecord *ForwardingRecord, const struct misdn_bchannel *bc)
2720 {
2721         const char *Spacing;
2722
2723         Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
2724         chan_misdn_log(1, bc->port, " -->%s Procedure:%d BasicService:%d\n",
2725                 Spacing,
2726                 ForwardingRecord->Procedure,
2727                 ForwardingRecord->BasicService);
2728         chan_misdn_log(1, bc->port, " -->%s ForwardedTo:\n", Spacing);
2729         print_facility_Address(Level + 1, &ForwardingRecord->ForwardedTo, bc);
2730         chan_misdn_log(1, bc->port, " -->%s ServedUserNr:\n", Spacing);
2731         print_facility_ServedUserNr(Level + 1, &ForwardingRecord->ServedUser, bc);
2732 }
2733 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2734
2735 static void print_facility(const struct FacParm *fac, const const struct misdn_bchannel *bc)
2736 {
2737 #if defined(AST_MISDN_ENHANCEMENTS)
2738         unsigned Index;
2739 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
2740
2741         switch (fac->Function) {
2742 #if defined(AST_MISDN_ENHANCEMENTS)
2743         case Fac_ActivationDiversion:
2744                 chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
2745                         fac->u.ActivationDiversion.InvokeID);
2746                 switch (fac->u.ActivationDiversion.ComponentType) {
2747                 case FacComponent_Invoke:
2748                         chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
2749                                 fac->u.ActivationDiversion.Component.Invoke.Procedure,
2750                                 fac->u.ActivationDiversion.Component.Invoke.BasicService);
2751                         chan_misdn_log(1, bc->port, " -->   ForwardedTo:\n");
2752                         print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
2753                         chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
2754                         print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
2755                         break;
2756                 case FacComponent_Result:
2757                         chan_misdn_log(1, bc->port, " -->  Result\n");
2758                         break;
2759                 default:
2760                         break;
2761                 }
2762                 break;
2763         case Fac_DeactivationDiversion:
2764                 chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
2765                         fac->u.DeactivationDiversion.InvokeID);
2766                 switch (fac->u.DeactivationDiversion.ComponentType) {
2767                 case FacComponent_Invoke:
2768                         chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
2769                                 fac->u.DeactivationDiversion.Component.Invoke.Procedure,
2770                                 fac->u.DeactivationDiversion.Component.Invoke.BasicService);
2771                         chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
2772                         print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
2773                         break;
2774                 case FacComponent_Result:
2775                         chan_misdn_log(1, bc->port, " -->  Result\n");
2776                         break;
2777                 default:
2778                         break;
2779                 }
2780                 break;
2781         case Fac_ActivationStatusNotificationDiv:
2782                 chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2783                         fac->u.ActivationStatusNotificationDiv.InvokeID,
2784                         fac->u.ActivationStatusNotificationDiv.Procedure,
2785                         fac->u.ActivationStatusNotificationDiv.BasicService);
2786                 chan_misdn_log(1, bc->port, " -->  ForwardedTo:\n");
2787                 print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
2788                 chan_misdn_log(1, bc->port, " -->  ServedUserNr:\n");
2789                 print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
2790                 break;
2791         case Fac_DeactivationStatusNotificationDiv:
2792                 chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
2793                         fac->u.DeactivationStatusNotificationDiv.InvokeID,
2794                         fac->u.DeactivationStatusNotificationDiv.Procedure,
2795                         fac->u.DeactivationStatusNotificationDiv.BasicService);
2796                 chan_misdn_log(1, bc->port, " -->  ServedUserNr:\n");
2797                 print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
2798                 break;
2799         case Fac_InterrogationDiversion:
2800                 chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
2801                         fac->u.InterrogationDiversion.InvokeID);
2802                 switch (fac->u.InterrogationDiversion.ComponentType) {
2803                 case FacComponent_Invoke:
2804                         chan_misdn_log(1, bc->port, " -->  Invoke: Procedure:%d BasicService:%d\n",
2805                                 fac->u.InterrogationDiversion.Component.Invoke.Procedure,
2806                                 fac->u.InterrogationDiversion.Component.Invoke.BasicService);
2807                         chan_misdn_log(1, bc->port, " -->   ServedUserNr:\n");
2808                         print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
2809                         break;
2810                 case FacComponent_Result:
2811                         chan_misdn_log(1, bc->port, " -->  Result:\n");
2812                         if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
2813                                 for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
2814                                         chan_misdn_log(1, bc->port, " -->   IntResult[%d]:\n", Index);
2815                                         print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
2816                                 }
2817                         }
2818                         break;
2819                 default:
2820                         break;
2821                 }
2822                 break;
2823         case Fac_DiversionInformation:
2824                 chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
2825                         fac->u.DiversionInformation.InvokeID,
2826                         fac->u.DiversionInformation.DiversionReason,
2827                         fac->u.DiversionInformation.BasicService);
2828                 if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
2829                         chan_misdn_log(1, bc->port, " -->  ServedUserSubaddress:\n");
2830                         print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
2831                 }
2832                 if (fac->u.DiversionInformation.CallingAddressPresent) {
2833                         chan_misdn_log(1, bc->port, " -->  CallingAddress:\n");
2834                         print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
2835                 }
2836                 if (fac->u.DiversionInformation.OriginalCalledPresent) {
2837                         chan_misdn_log(1, bc->port, " -->  OriginalCalledNr:\n");
2838                         print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
2839                 }
2840                 if (fac->u.DiversionInformation.LastDivertingPresent) {
2841                         chan_misdn_log(1, bc->port, " -->  LastDivertingNr:\n");
2842                         print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
2843                 }
2844                 if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
2845                         chan_misdn_log(1, bc->port, " -->  LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
2846                 }
2847                 if (fac->u.DiversionInformation.UserInfo.Length) {
2848                         chan_misdn_log(1, bc->port, " -->  UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
2849                 }
2850                 break;
2851         case Fac_CallDeflection:
2852                 chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
2853                         fac->u.CallDeflection.InvokeID);
2854                 switch (fac->u.CallDeflection.ComponentType) {
2855                 case FacComponent_Invoke:
2856                         chan_misdn_log(1, bc->port, " -->  Invoke:\n");
2857                         if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
2858                                 chan_misdn_log(1, bc->port, " -->   PresentationAllowed:%d\n",
2859                                         fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
2860                         }
2861                         chan_misdn_log(1, bc->port, " -->   DeflectionAddress:\n");
2862                         print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
2863                         break;
2864                 case FacComponent_Result:
2865                         chan_misdn_log(1, bc->port, " -->  Result\n");
2866                         break;
2867                 default:
2868                         break;
2869                 }
2870                 break;
2871         case Fac_CallRerouteing:
2872                 chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
2873                         fac->u.CallRerouteing.InvokeID);
2874                 switch (fac->u.CallRerouteing.ComponentType) {
2875                 case FacComponent_Invoke:
2876                         chan_misdn_log(1, bc->port, " -->  Invoke: Reason:%d Counter:%d\n",
2877                                 fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
2878                                 fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
2879                         chan_misdn_log(1, bc->port, " -->   CalledAddress:\n");
2880                         print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
2881                         print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
2882                         chan_misdn_log(1, bc->port, " -->   LastReroutingNr:\n");
2883                         print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
2884                         chan_misdn_log(1, bc->port, " -->   SubscriptionOption:%d\n",
2885                                 fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
2886                         if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
2887                                 chan_misdn_log(1, bc->port, " -->   CallingParty:\n");
2888                                 print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
2889                         }
2890                         break;
2891                 case FacComponent_Result:
2892                         chan_misdn_log(1, bc->port, " -->  Result\n");
2893                         break;
2894                 default:
2895                         break;
2896                 }
2897                 break;
2898         case Fac_InterrogateServedUserNumbers:
2899                 chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
2900                         fac->u.InterrogateServedUserNumbers.InvokeID);
2901                 switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
2902                 case FacComponent_Invoke:
2903                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
2904                         break;
2905                 case FacComponent_Result:
2906                         chan_misdn_log(1, bc->port, " -->  Result:\n");
2907                         if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
2908                                 for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
2909                                         chan_misdn_log(1, bc->port, " -->   ServedUserNr[%d]:\n", Index);
2910                                         print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
2911                                 }
2912                         }
2913                         break;
2914                 default:
2915                         break;
2916                 }
2917                 break;
2918         case Fac_DivertingLegInformation1:
2919                 chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
2920                         fac->u.DivertingLegInformation1.InvokeID,
2921                         fac->u.DivertingLegInformation1.DiversionReason,
2922                         fac->u.DivertingLegInformation1.SubscriptionOption);
2923                 if (fac->u.DivertingLegInformation1.DivertedToPresent) {
2924                         chan_misdn_log(1, bc->port, " -->  DivertedToNr:\n");
2925                         print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
2926                 }
2927                 break;
2928         case Fac_DivertingLegInformation2:
2929                 chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
2930                         fac->u.DivertingLegInformation2.InvokeID,
2931                         fac->u.DivertingLegInformation2.DiversionReason,
2932                         fac->u.DivertingLegInformation2.DiversionCounter);
2933                 if (fac->u.DivertingLegInformation2.DivertingPresent) {
2934                         chan_misdn_log(1, bc->port, " -->  DivertingNr:\n");
2935                         print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
2936                 }
2937                 if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
2938                         chan_misdn_log(1, bc->port, " -->  OriginalCalledNr:\n");
2939                         print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
2940                 }
2941                 break;
2942         case Fac_DivertingLegInformation3:
2943                 chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
2944                         fac->u.DivertingLegInformation3.InvokeID,
2945                         fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
2946                 break;
2947
2948 #else   /* !defined(AST_MISDN_ENHANCEMENTS) */
2949
2950         case Fac_CD:
2951                 chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
2952                         fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
2953                 break;
2954 #endif  /* !defined(AST_MISDN_ENHANCEMENTS) */
2955         case Fac_AOCDCurrency:
2956                 if (fac->u.AOCDcur.chargeNotAvailable) {
2957                         chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
2958                 } else if (fac->u.AOCDcur.freeOfCharge) {
2959                         chan_misdn_log(1, bc->port, " --> AOCD currency: free of charge\n");
2960                 } else if (fac->u.AOCDchu.billingId >= 0) {
2961                         chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
2962                                 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2963                                 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
2964                 } else {
2965                         chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
2966                                 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
2967                                 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
2968                 }
2969                 break;
2970         case Fac_AOCDChargingUnit:
2971                 if (fac->u.AOCDchu.chargeNotAvailable) {
2972                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: charge not available\n");
2973                 } else if (fac->u.AOCDchu.freeOfCharge) {
2974                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: free of charge\n");
2975                 } else if (fac->u.AOCDchu.billingId >= 0) {
2976                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
2977                                 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
2978                 } else {
2979                         chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
2980                                 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
2981                 }
2982                 break;
2983 #if defined(AST_MISDN_ENHANCEMENTS)
2984         case Fac_ERROR:
2985                 chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
2986                         fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
2987                 break;
2988         case Fac_RESULT:
2989                 chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
2990                         fac->u.RESULT.InvokeID);
2991                 break;
2992         case Fac_REJECT:
2993                 if (fac->u.REJECT.InvokeIDPresent) {
2994                         chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
2995                                 fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
2996                 } else {
2997                         chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
2998                                 fac->u.REJECT.Code);
2999                 }
3000                 break;
3001         case Fac_EctExecute:
3002                 chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
3003                         fac->u.EctExecute.InvokeID);
3004                 break;
3005         case Fac_ExplicitEctExecute:
3006                 chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
3007                         fac->u.ExplicitEctExecute.InvokeID,
3008                         fac->u.ExplicitEctExecute.LinkID);
3009                 break;
3010         case Fac_RequestSubaddress:
3011                 chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
3012                         fac->u.RequestSubaddress.InvokeID);
3013                 break;
3014         case Fac_SubaddressTransfer:
3015                 chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
3016                         fac->u.SubaddressTransfer.InvokeID);
3017                 print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
3018                 break;
3019         case Fac_EctLinkIdRequest:
3020                 chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
3021                         fac->u.EctLinkIdRequest.InvokeID);
3022                 switch (fac->u.EctLinkIdRequest.ComponentType) {
3023                 case FacComponent_Invoke:
3024                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3025                         break;
3026                 case FacComponent_Result:
3027                         chan_misdn_log(1, bc->port, " -->  Result: LinkID:%d\n",
3028                                 fac->u.EctLinkIdRequest.Component.Result.LinkID);
3029                         break;
3030                 default:
3031                         break;
3032                 }
3033                 break;
3034         case Fac_EctInform:
3035                 chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
3036                         fac->u.EctInform.InvokeID,
3037                         fac->u.EctInform.Status);
3038                 if (fac->u.EctInform.RedirectionPresent) {
3039                         chan_misdn_log(1, bc->port, " -->  Redirection Number\n");
3040                         print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
3041                 }
3042                 break;
3043         case Fac_EctLoopTest:
3044                 chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
3045                         fac->u.EctLoopTest.InvokeID);
3046                 switch (fac->u.EctLoopTest.ComponentType) {
3047                 case FacComponent_Invoke:
3048                         chan_misdn_log(1, bc->port, " -->  Invoke: CallTransferID:%d\n",
3049                                 fac->u.EctLoopTest.Component.Invoke.CallTransferID);
3050                         break;
3051                 case FacComponent_Result:
3052                         chan_misdn_log(1, bc->port, " -->  Result: LoopResult:%d\n",
3053                                 fac->u.EctLoopTest.Component.Result.LoopResult);
3054                         break;
3055                 default:
3056                         break;
3057                 }
3058                 break;
3059         case Fac_StatusRequest:
3060                 chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
3061                         fac->u.StatusRequest.InvokeID);
3062                 switch (fac->u.StatusRequest.ComponentType) {
3063                 case FacComponent_Invoke:
3064                         chan_misdn_log(1, bc->port, " -->  Invoke: Compatibility:%d\n",
3065                                 fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
3066                         break;
3067                 case FacComponent_Result:
3068                         chan_misdn_log(1, bc->port, " -->  Result: Status:%d\n",
3069                                 fac->u.StatusRequest.Component.Result.Status);
3070                         break;
3071                 default:
3072                         break;
3073                 }
3074                 break;
3075         case Fac_CallInfoRetain:
3076                 chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
3077                         fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
3078                 break;
3079         case Fac_CCBSDeactivate:
3080                 chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
3081                         fac->u.CCBSDeactivate.InvokeID);
3082                 switch (fac->u.CCBSDeactivate.ComponentType) {
3083                 case FacComponent_Invoke:
3084                         chan_misdn_log(1, bc->port, " -->  Invoke: CCBSReference:%d\n",
3085                                 fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
3086                         break;
3087                 case FacComponent_Result:
3088                         chan_misdn_log(1, bc->port, " -->  Result\n");
3089                         break;
3090                 default:
3091                         break;
3092                 }
3093                 break;
3094         case Fac_CCBSErase:
3095                 chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
3096                         fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
3097                         fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
3098                 chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
3099                 print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
3100                 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
3101                 break;
3102         case Fac_CCBSRemoteUserFree:
3103                 chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3104                         fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
3105                         fac->u.CCBSRemoteUserFree.RecallMode);
3106                 chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
3107                 print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
3108                 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
3109                 break;
3110         case Fac_CCBSCall:
3111                 chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
3112                         fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
3113                 break;
3114         case Fac_CCBSStatusRequest:
3115                 chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
3116                         fac->u.CCBSStatusRequest.InvokeID);
3117                 switch (fac->u.CCBSStatusRequest.ComponentType) {
3118                 case FacComponent_Invoke:
3119                         chan_misdn_log(1, bc->port, " -->  Invoke: CCBSReference:%d RecallMode:%d\n",
3120                                 fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
3121                                 fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
3122                         print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
3123                         break;
3124                 case FacComponent_Result:
3125                         chan_misdn_log(1, bc->port, " -->  Result: Free:%d\n",
3126                                 fac->u.CCBSStatusRequest.Component.Result.Free);
3127                         break;
3128                 default:
3129                         break;
3130                 }
3131                 break;
3132         case Fac_CCBSBFree:
3133                 chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
3134                         fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
3135                         fac->u.CCBSBFree.RecallMode);
3136                 chan_misdn_log(1, bc->port, " -->  AddressOfB\n");
3137                 print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
3138                 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
3139                 break;
3140         case Fac_EraseCallLinkageID:
3141                 chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
3142                         fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
3143                 break;
3144         case Fac_CCBSStopAlerting:
3145                 chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
3146                         fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
3147                 break;
3148         case Fac_CCBSRequest:
3149                 chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
3150                         fac->u.CCBSRequest.InvokeID);
3151                 switch (fac->u.CCBSRequest.ComponentType) {
3152                 case FacComponent_Invoke:
3153                         chan_misdn_log(1, bc->port, " -->  Invoke: LinkageID:%d\n",
3154                                 fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
3155                         break;
3156                 case FacComponent_Result:
3157                         chan_misdn_log(1, bc->port, " -->  Result: CCBSReference:%d RecallMode:%d\n",
3158                                 fac->u.CCBSRequest.Component.Result.CCBSReference,
3159                                 fac->u.CCBSRequest.Component.Result.RecallMode);
3160                         break;
3161                 default:
3162                         break;
3163                 }
3164                 break;
3165         case Fac_CCBSInterrogate:
3166                 chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
3167                         fac->u.CCBSInterrogate.InvokeID);
3168                 switch (fac->u.CCBSInterrogate.ComponentType) {
3169                 case FacComponent_Invoke:
3170                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3171                         if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
3172                                 chan_misdn_log(1, bc->port, " -->   CCBSReference:%d\n",
3173                                         fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
3174                         }
3175                         if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3176                                 chan_misdn_log(1, bc->port, " -->   AParty\n");
3177                                 print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
3178                         }
3179                         break;
3180                 case FacComponent_Result:
3181                         chan_misdn_log(1, bc->port, " -->  Result: RecallMode:%d\n",
3182                                 fac->u.CCBSInterrogate.Component.Result.RecallMode);
3183                         if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
3184                                 for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
3185                                         chan_misdn_log(1, bc->port, " -->   CallDetails[%d]:\n", Index);
3186                                         print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
3187                                 }
3188                         }
3189                         break;
3190                 default:
3191                         break;
3192                 }
3193                 break;
3194         case Fac_CCNRRequest:
3195                 chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
3196                         fac->u.CCNRRequest.InvokeID);
3197                 switch (fac->u.CCNRRequest.ComponentType) {
3198                 case FacComponent_Invoke:
3199                         chan_misdn_log(1, bc->port, " -->  Invoke: LinkageID:%d\n",
3200                                 fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
3201                         break;
3202                 case FacComponent_Result:
3203                         chan_misdn_log(1, bc->port, " -->  Result: CCBSReference:%d RecallMode:%d\n",
3204                                 fac->u.CCNRRequest.Component.Result.CCBSReference,
3205                                 fac->u.CCNRRequest.Component.Result.RecallMode);
3206                         break;
3207                 default:
3208                         break;
3209                 }
3210                 break;
3211         case Fac_CCNRInterrogate:
3212                 chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
3213                         fac->u.CCNRInterrogate.InvokeID);
3214                 switch (fac->u.CCNRInterrogate.ComponentType) {
3215                 case FacComponent_Invoke:
3216                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3217                         if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
3218                                 chan_misdn_log(1, bc->port, " -->   CCBSReference:%d\n",
3219                                         fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
3220                         }
3221                         if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
3222                                 chan_misdn_log(1, bc->port, " -->   AParty\n");
3223                                 print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
3224                         }
3225                         break;
3226                 case FacComponent_Result:
3227                         chan_misdn_log(1, bc->port, " -->  Result: RecallMode:%d\n",
3228                                 fac->u.CCNRInterrogate.Component.Result.RecallMode);
3229                         if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
3230                                 for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
3231                                         chan_misdn_log(1, bc->port, " -->   CallDetails[%d]:\n", Index);
3232                                         print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
3233                                 }
3234                         }
3235                         break;
3236                 default:
3237                         break;
3238                 }
3239                 break;
3240         case Fac_CCBS_T_Call:
3241                 chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
3242                         fac->u.CCBS_T_Call.InvokeID);
3243                 break;
3244         case Fac_CCBS_T_Suspend:
3245                 chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
3246                         fac->u.CCBS_T_Suspend.InvokeID);
3247                 break;
3248         case Fac_CCBS_T_Resume:
3249                 chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
3250                         fac->u.CCBS_T_Resume.InvokeID);
3251                 break;
3252         case Fac_CCBS_T_RemoteUserFree:
3253                 chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
3254                         fac->u.CCBS_T_RemoteUserFree.InvokeID);
3255                 break;
3256         case Fac_CCBS_T_Available:
3257                 chan_misdn_log(1, bc->port, " --> CCBS_T_Available: InvokeID:%d\n",
3258                         fac->u.CCBS_T_Available.InvokeID);
3259                 break;
3260         case Fac_CCBS_T_Request:
3261                 chan_misdn_log(1, bc->port, " --> CCBS_T_Request: InvokeID:%d\n",
3262                         fac->u.CCBS_T_Request.InvokeID);
3263                 switch (fac->u.CCBS_T_Request.ComponentType) {
3264                 case FacComponent_Invoke:
3265                         chan_misdn_log(1, bc->port, " -->  Invoke\n");
3266                         chan_misdn_log(1, bc->port, " -->   DestinationAddress:\n");
3267                         print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Destination, bc);
3268                         print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBS_T_Request.Component.Invoke.Q931ie, bc);
3269                         if (fac->u.CCBS_T_Request.Component.Invoke.RetentionSupported) {
3270                                 chan_misdn_log(1, bc->port, " -->   RetentionSupported:1\n");
3271                         }
3272                         if (fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
3273                                 chan_misdn_log(1, bc->port, " -->   PresentationAllowed:%d\n",
3274                                         fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator);
3275                         }