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