]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Freetdm: Support for mapped raw traces
authorDavid Yat Sin <dyatsin@sangoma.com>
Mon, 20 Dec 2010 22:06:36 +0000 (17:06 -0500)
committerDavid Yat Sin <dyatsin@sangoma.com>
Mon, 20 Dec 2010 22:06:36 +0000 (17:06 -0500)
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.h

index 6a440e4f66a8c9187234cd1e13b07cf40d17b157..9e547884642eefaaf55251e0e85facd6f92a39be 100644 (file)
@@ -233,6 +233,7 @@ typedef struct sngisdn_chan_data {
     uint32_t                           flags;
        uint8_t                                 ces;            /* used only for BRI, otherwise always 0 */
        uint8_t                                 dchan_id;
+       uint16_t                                call_ref;       /* Q.931 call reference, only valid for ETSI/INSNET/QSIG */
        uint32_t                                suInstId;       /* instance ID generated locally */
        uint32_t                                spInstId;       /* instance ID generated by stack */
 
@@ -446,6 +447,9 @@ void sngisdn_rcv_cc_ind(CcMngmt *status);
 void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...);
 void sngisdn_rcv_sng_assert(char *message);
 
+#ifdef NETBORDER_CALL_REF
+ftdm_status_t get_callref(ftdm_channel_t *ftdmchan, BCCallRef* callRef);
+#endif
 ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
 ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
 ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
index 7e9e360c6daba3cedf46796cbab2c875d837760e..67bc6e96615ba02f68f16e8ed9a33c0c4b4ca23f 100644 (file)
@@ -71,13 +71,12 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
                                sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
                                sngisdn_info->glare.spInstId = spInstId;
                                sngisdn_info->glare.dChan = dChan;
-                               sngisdn_info->glare.ces = ces;
+                               sngisdn_info->glare.ces = ces;                          
                                break;
                        }
                        
                        sngisdn_info->suInstId = get_unique_suInstId(suId);
                        sngisdn_info->spInstId = spInstId;
-                       
 
                        if (conEvnt->cdPtyNmb.eh.pres && signal_data->num_local_numbers) {
                                uint8_t local_number_matched = 0;
@@ -125,6 +124,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
                        }
 
                        /* Fill in call information */
+#ifdef NETBORDER_CALL_REF
+                       get_callref(ftdmchan, &conEvnt->callRef);
+#endif
                        get_calling_num(ftdmchan, &conEvnt->cgPtyNmb);
                        get_calling_num2(ftdmchan, &conEvnt->cgPtyNmb2);
                        get_called_num(ftdmchan, &conEvnt->cdPtyNmb);
@@ -282,6 +284,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
                        case FTDM_CHANNEL_STATE_PROGRESS:
                        case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
                        case FTDM_CHANNEL_STATE_DIALING:
+                               get_callref(ftdmchan, &cnStEvnt->callRef);
                                get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd);
                                get_facility_ie(ftdmchan, &cnStEvnt->facilityStr);
                                ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
@@ -354,6 +357,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
                case MI_CALLPROC:                       
                case MI_PROGRESS:
                case MI_ALERTING:
+                       get_callref(ftdmchan, &cnStEvnt->callRef);
                        get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd);
                        get_facility_ie(ftdmchan, &cnStEvnt->facilityStr);
 
index 28768a1f09d66d9eaece7301b36327d1f4b56e16..6fd613b3068811d909611071a35ca39bbcbaf916 100644 (file)
@@ -161,6 +161,32 @@ ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t ava
        return FTDM_SUCCESS;
 }
 
+#ifdef NETBORDER_CALL_REF
+ftdm_status_t get_callref(ftdm_channel_t *ftdmchan, BCCallRef* callRef)
+{
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
+       sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
+
+       if (signal_data->raw_trace_q931) {
+               if (callRef->eh.pres != PRSNT_NODEF || callRef->reference.pres != PRSNT_NODEF) {
+                       /* Netborder only supports BRI, so we only care for BRI for now */
+                       if (FTDM_SPAN_IS_BRI(ftdmchan->span) && !sngisdn_info->call_ref) {
+                               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to obtain call reference\n");
+                       }
+                       return FTDM_FAIL;
+               }               
+               if (FTDM_SPAN_IS_BRI(ftdmchan->span)) {
+                       sngisdn_info->call_ref = 0x7F & callRef->reference.val;
+               } else {
+                       sngisdn_info->call_ref = 0x7FFF & callRef->reference.val;
+               }
+               
+               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Call reference:%04x\n", sngisdn_info->call_ref);
+       }
+       return FTDM_SUCCESS;
+}
+#endif
+
 ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
 {
        ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
index fd9edeba8dfa80b70181f9e045d924fa70cc7e97..e7488c72abd1b78ba3792bc794beb7561c42a61f 100644 (file)
 #define OCTET(x) (ieData[x-1] & 0xFF)
 #define MAX_DECODE_STR_LEN 2000
 
+typedef struct sngisdn_trace_info
+{
+       uint8_t call_ref_flag;
+       uint16_t call_ref;
+       uint8_t msgtype;
+       uint8_t bchan_no;
+       ftdm_trace_dir_t dir;
+} sngisdn_frame_info_t;
+
 void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end);
 uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start);
+static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found);
+static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *frame_info);
 
 uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi);
 char* get_code_2_str(int code, struct code2str *pCodeTable);
 void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len);
 void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len);
 
+
 char* get_code_2_str(int code, struct code2str *pCodeTable)
 {
        struct code2str* pCode2txt;
@@ -120,10 +132,7 @@ void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d
        
        sigev.ev_data.trace.dir = dir;
        sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q921;
-       
-       /* TODO: Map trace to call ID here */
-       sigev.call_id = 0;
-       
+
        raw_data = ftdm_malloc(data_len);
        ftdm_assert(raw_data, "Failed to malloc");
        
@@ -218,26 +227,33 @@ void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t d
 {
        uint8_t                         *raw_data;
        ftdm_sigmsg_t           sigev;
+       ftdm_channel_t *ftdmchan;
+       sngisdn_frame_info_t  frame_info;
 
        memset(&sigev, 0, sizeof(sigev));
 
-       sigev.span_id = signal_data->ftdm_span->span_id;
-       sigev.chan_id = signal_data->dchan->chan_id;
-       sigev.channel = signal_data->dchan;
-       sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
-
-       sigev.ev_data.trace.dir = dir;
-       sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q931;
-       
-       /* TODO: Map trace to call ID here */
+       /* Note: Mapped raw trace assume only exclusive b-channel selection is used. i.e the b-channel selected on outgoing SETUP is always used for the call */
        
-       raw_data = ftdm_malloc(data_len);
-       ftdm_assert(raw_data, "Failed to malloc");
-       
-       memcpy(raw_data, data, data_len);
-       sigev.raw_data = raw_data;
-       sigev.raw_data_len = data_len;
-       ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
+       if (sngisdn_get_frame_info(data, data_len, dir, &frame_info) == FTDM_SUCCESS) {
+               if (sngisdn_map_call(signal_data, frame_info, &ftdmchan) == FTDM_SUCCESS) {
+                       sigev.call_id = ftdmchan->caller_data.call_id;
+                       sigev.span_id = ftdmchan->physical_span_id;
+                       sigev.chan_id = ftdmchan->physical_chan_id;
+                       sigev.channel = ftdmchan;
+               }
+               sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
+
+               sigev.ev_data.trace.dir = dir;
+               sigev.ev_data.trace.type = FTDM_TRACE_TYPE_Q931;
+
+               raw_data = ftdm_malloc(data_len);
+               ftdm_assert(raw_data, "Failed to malloc");
+
+               memcpy(raw_data, data, data_len);
+               sigev.raw_data = raw_data;
+               sigev.raw_data_len = data_len;
+               ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
+       }
 }
 
 void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len)
@@ -253,9 +269,6 @@ void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len)
        prot_disc = (uint8_t)data[0];
        str_len += sprintf(&str[str_len], "  Prot Disc:%s (0x%02x)\n", get_code_2_str(prot_disc, dcodQ931ProtDiscTable), prot_disc);
        
-
-       
-
        /* Decode Call Reference */
        lenCallRef = (uint8_t) (data[1] & 0x0F);
 
@@ -747,4 +760,203 @@ void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_
        return;
 }
 
+static ftdm_status_t sngisdn_get_frame_info(uint8_t *data, uint32_t data_len, ftdm_trace_dir_t dir, sngisdn_frame_info_t *target)
+{
+       uint8_t pos = 0;
+       uint8_t flag;
+       uint16_t ref = 0;
+       uint8_t ref_len = 0;
+       uint8_t bchan_no = 0;
+       uint8_t msgtype;
+
+       /* First octet is protocol discriminator */
+       pos++;
+       /* Second octet contains length of call reference */
+       ref_len = data[pos++] & 0x0F;
+
+       /* third octet is call reference */
+       flag = (data[pos] & 0x80) >> 7;
+       if (ref_len == 2) {
+               ref = (data[pos++] & 0x7F) << 8;
+               ref |= (data[pos++] & 0xFF) ;
+       } else {
+               ref = (data[pos++] & 0x7F);
+       }
+
+       /* Next octet is the message type */
+       msgtype = data[pos++] & 0x7F;
+       
+       /*
+               ftdm_log(FTDM_LOG_DEBUG, "Raw frame:call_ref:0x%04x flag:%d msgtype:%d\n", ref, flag, msgtype);
+       */
+       if (!ref) {
+               /* This is not a call specific message (RESTART for example and we do not care about it) */
+               return FTDM_FAIL;
+       }
+
+       /* Look for the b-channel */
+       if (msgtype == PROT_Q931_MSGTYPE_SETUP) {
+               /* Try to find the b-channel no*/
+
+               for(; pos < data_len; pos++) {
+                       uint8_t ie_id = data[pos];
+                       uint8_t ie_len = data[pos+1];
+
+                       switch(ie_id) {
+                               case PROT_Q931_IE_SENDING_COMPLETE:
+                                       /* Single octet ie's do not have a length */
+                                       ie_len = 0;
+                                       break;
+                               case PROT_Q931_IE_CHANNEL_ID:
+                                       {
+                                               /* Try to obtain the b-channel */
+                                               uint8_t ie_pos = pos+2;                                 
+                                               //ifaceIdPresent = get_bits(OCTET(3),7,7);
+                                               if (data[ie_pos] & 0x20) {
+                                                       /* Interface type is Primary Rate */
+                                                       ie_pos+=2;
+                                                       bchan_no = data[ie_pos] & 0x7F;
+                                               } else {
+                                                       /* Interface type is Basic Interface */
+                                                       /* Get the channel number from info channel selection */
+                                                       bchan_no = data[ie_pos] & 0x03;
+                                               }
+                                               ftdm_log(FTDM_LOG_DEBUG, "Found b-channel:%d\n", bchan_no);
+                                               goto parse_ies_done;
+                                       }
+                                       break;
+                               default:
+                                       pos = pos+ie_len+1;
+                       }
+                       //ftdm_log(FTDM_LOG_DEBUG, "Decoded IE:%s\n", get_code_2_str(ie_id, dcodQ931IEIDTable));
+               }
+               if (!bchan_no) {
+                       char tmp[1000];
+                       print_hex_dump(tmp, 0, data, 0, data_len);                      
+                       ftdm_log(FTDM_LOG_WARNING, "Failed to determine b-channel on SETUP message\n%s\n", tmp);
+               }
+       }
+
+parse_ies_done:
+
+       target->call_ref = ref;
+       target->call_ref_flag = flag;
+       target->msgtype = msgtype;
+       target->bchan_no = bchan_no;
+       target->dir = dir;
+
+       return FTDM_SUCCESS;
+}
+
+static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_frame_info_t frame_info, ftdm_channel_t **found)
+{
+       ftdm_channel_t *ftdmchan;
+       sngisdn_chan_data_t *sngisdn_info;
+       ftdm_iterator_t *chaniter = NULL;
+       ftdm_iterator_t *curr = NULL;
+       ftdm_status_t status = FTDM_FAIL;
+       uint8_t outbound_call = 0;
+       
+       if ((!frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_OUTGOING) ||
+               (frame_info.call_ref_flag && frame_info.dir == FTDM_TRACE_DIR_INCOMING)) {
+
+               /* If this is an outgoing frame and this frame was sent by the originating side
+                       of the call (frame_info.call_ref_flag == 0), then this is an outbound call */
+               outbound_call = 1;
+       } else {
+               outbound_call = 0;
+       }
+
+       switch (frame_info.msgtype) {
+               case PROT_Q931_MSGTYPE_SETUP:
+                       /* We initiated this outgoing call try to match the call reference with our internal call-id*/
+                       if (!frame_info.bchan_no) {
+                               /* We were not able to determine the bchannel on this call, so we will not be able to match it anyway */
+                               status = FTDM_FAIL;
+                       }
+                       
+                       chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
+                       for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
+                               ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr));
+                               ftdm_channel_lock(ftdmchan);
+                               
+                               if (outbound_call) {
+                                       sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
+                                       if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+                                               if (ftdmchan->caller_data.call_id && ftdmchan->physical_chan_id == frame_info.bchan_no) {
+
+                                                       sngisdn_info->call_ref = frame_info.call_ref;
+                                                       *found = ftdmchan;
+                                                       status = FTDM_SUCCESS;
+                                               }
+                                       }
+                               } else {
+                                       if (ftdmchan->physical_chan_id == frame_info.bchan_no) {
+                                               *found = ftdmchan;
+                                               status = FTDM_SUCCESS;
+                                       }
+                               }
+                               ftdm_channel_unlock(ftdmchan);
+                       }
+                       ftdm_iterator_free(chaniter);
+                       break;
+               case PROT_Q931_MSGTYPE_ALERTING:
+               case PROT_Q931_MSGTYPE_PROCEEDING:
+               case PROT_Q931_MSGTYPE_PROGRESS:
+               case PROT_Q931_MSGTYPE_CONNECT:
+               case PROT_Q931_MSGTYPE_SETUP_ACK:
+               case PROT_Q931_MSGTYPE_CONNECT_ACK:
+               case PROT_Q931_MSGTYPE_USER_INFO:
+               case PROT_Q931_MSGTYPE_DISCONNECT:
+               case PROT_Q931_MSGTYPE_RELEASE:
+               case PROT_Q931_MSGTYPE_RELEASE_ACK:
+               case PROT_Q931_MSGTYPE_RELEASE_COMPLETE:
+               case PROT_Q931_MSGTYPE_FACILITY:
+               case PROT_Q931_MSGTYPE_NOTIFY:
+               case PROT_Q931_MSGTYPE_STATUS_ENQUIRY:
+               case PROT_Q931_MSGTYPE_INFORMATION:
+               case PROT_Q931_MSGTYPE_STATUS:
+                       /* Look for an outbound call on that span and and try to match the call-id */
+                       chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
+                       for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
+                               ftdmchan = (ftdm_channel_t*)(ftdm_iterator_current(curr));
+                               ftdm_channel_lock(ftdmchan);
+                               sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
+                               if (outbound_call) {
+                                       if (sngisdn_info && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+                                               if (sngisdn_info->call_ref == frame_info.call_ref) {
+
+                                                       *found = ftdmchan;
+                                                       status = FTDM_SUCCESS;
+                                               }
+                                       }
+                               } else {
+                                       if (sngisdn_info && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
+                                               if (sngisdn_info->call_ref && sngisdn_info->call_ref == frame_info.call_ref) {
+
+                                                       *found = ftdmchan;
+                                                       status = FTDM_SUCCESS;
+                                               }
+                                       }
+                               }
+                               ftdm_channel_unlock(ftdmchan);
+                       }
+                       ftdm_iterator_free(chaniter);
+                       break;
+               default:
+                       /* This frame is not call specific, ignore */
+                       break;
+       }
+       if (status == FTDM_SUCCESS) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Mapped %s with Call Ref:%04x to call-id:%d\n", get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref, (*found)->caller_data.call_id);
+       } else {
+               /* We could not map this frame to a call-id */
+               ftdm_log(FTDM_LOG_DEBUG, "Failed to map %s with Call Ref:%04x to local call\n",
+                                get_code_2_str(frame_info.msgtype, dcodQ931MsgTypeTable), frame_info.call_ref);
+       }
+
+       return status;
+}
+
+
 
index f054de937701c7f5521ed64768dc494c9074a3f5..db33cf8083b617c41053a6446bf45bddeef3b403 100644 (file)
@@ -191,37 +191,65 @@ struct code2str dcodQ931CallRefLoTable[] = {
        {13, "D"},
        {14, "E"},
        {15, "F"},
-       {-1,"?"},
+       {-1, "?"},
 };
 
+#define PROT_Q931_MSGTYPE_ALERTING                     1
+#define PROT_Q931_MSGTYPE_PROCEEDING           2
+#define PROT_Q931_MSGTYPE_PROGRESS                     3
+#define PROT_Q931_MSGTYPE_SETUP                                5
+#define PROT_Q931_MSGTYPE_CONNECT                      7
+#define PROT_Q931_MSGTYPE_SETUP_ACK                    13
+#define PROT_Q931_MSGTYPE_CONNECT_ACK          15
+#define PROT_Q931_MSGTYPE_USER_INFO                    32
+#define PROT_Q931_MSGTYPE_SUSPEND_REJ          33
+#define PROT_Q931_MSGTYPE_RESUME_REJ           34
+#define PROT_Q931_MSGTYPE_SUSPEND                      37
+#define PROT_Q931_MSGTYPE_RESUME                       38
+#define PROT_Q931_MSGTYPE_SUSPEND_ACK          45
+#define PROT_Q931_MSGTYPE_RESUME_ACK           46
+#define PROT_Q931_MSGTYPE_DISCONNECT           69
+#define PROT_Q931_MSGTYPE_RESTART                      70
+#define PROT_Q931_MSGTYPE_RELEASE                      77
+#define PROT_Q931_MSGTYPE_RELEASE_ACK          78
+#define PROT_Q931_MSGTYPE_RELEASE_COMPLETE     90
+#define PROT_Q931_MSGTYPE_SEGMENT                      96
+#define PROT_Q931_MSGTYPE_FACILITY                     98
+#define PROT_Q931_MSGTYPE_NOTIFY                       110
+#define PROT_Q931_MSGTYPE_STATUS_ENQUIRY       117
+#define PROT_Q931_MSGTYPE_CONGESTION_CNTRL     121
+#define PROT_Q931_MSGTYPE_INFORMATION          123
+#define PROT_Q931_MSGTYPE_STATUS                       125
+
+
 struct code2str dcodQ931MsgTypeTable[] = {
-       {1, "Alerting"},
-       {2, "Call Proceeding"},
-       {3, "Progress"},
-       {5, "Setup"},
-       {7, "Connect"},
-       {13, "Setup Ack"},
-       {15, "Connect Ack"},
-       {32, "User Info"},
-       {33, "Suspend Rej"},
-       {34, "Resume Rej"},
-       {37, "Suspend"},
-       {38, "Resume"},
-       {45, "Suspend Ack"},
-       {46, "Resume Ack"},
-       {69, "Disconnect"},
-       {70, "Restart"},
-       {77, "Release"},
-       {78, "Release Ack"},
-       {90, "Release Compl"},
-       {96, "Segment"},
-       {98, "Facility"},
-       {110, "Notify"},
-       {117, "Status Enquiry"},
-       {121, "Congest Cntrl"},
-       {123, "Information"},
-       {125, "Status"},
-       {-1, "Unknown"},
+       {PROT_Q931_MSGTYPE_ALERTING, "ALERT"},
+       {PROT_Q931_MSGTYPE_PROCEEDING, "PROCEED"},
+       {PROT_Q931_MSGTYPE_PROGRESS, "PROGRESS"},
+       {PROT_Q931_MSGTYPE_SETUP, "SETUP"},
+       {PROT_Q931_MSGTYPE_CONNECT, "CONNECT"},
+       {PROT_Q931_MSGTYPE_SETUP_ACK, "SETUP ACK"},
+       {PROT_Q931_MSGTYPE_CONNECT_ACK, "CONNECT ACK"},
+       {PROT_Q931_MSGTYPE_USER_INFO, "USER INFO"},
+       {PROT_Q931_MSGTYPE_SUSPEND_REJ, "SUSPEND REJ"},
+       {PROT_Q931_MSGTYPE_RESUME_REJ, "RESUME REJ"},
+       {PROT_Q931_MSGTYPE_SUSPEND, "SUSPEND"},
+       {PROT_Q931_MSGTYPE_RESUME, "RESUME"},
+       {PROT_Q931_MSGTYPE_SUSPEND_ACK, "SUSPEND ACK"},
+       {PROT_Q931_MSGTYPE_RESUME_ACK, "RESUME ACK"},
+       {PROT_Q931_MSGTYPE_DISCONNECT, "DISCONNECT"},
+       {PROT_Q931_MSGTYPE_RESTART, "RESTART"},
+       {PROT_Q931_MSGTYPE_RELEASE, "RELEASE"},
+       {PROT_Q931_MSGTYPE_RELEASE_ACK, "RELEASR ACK"},
+       {PROT_Q931_MSGTYPE_RELEASE_COMPLETE, "RELEASE COMPLETE"},
+       {PROT_Q931_MSGTYPE_SEGMENT, "SEGMENT"},
+       {PROT_Q931_MSGTYPE_FACILITY, "FACILITY"},
+       {PROT_Q931_MSGTYPE_NOTIFY, "NOTIFY"},
+       {PROT_Q931_MSGTYPE_STATUS_ENQUIRY, "STATUS ENQ"},
+       {PROT_Q931_MSGTYPE_CONGESTION_CNTRL, "CONGESTION CTRL"},
+       {PROT_Q931_MSGTYPE_INFORMATION, "INFO"},
+       {PROT_Q931_MSGTYPE_STATUS, "STATUS"},
+       {-1, "UNKNOWN"},
 };
 
 struct code2str dcodQ931CauseCodeTable[] = {