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