/* $Id: q931.c,v 1.12.2.3 2004/01/13 14:31:26 keil Exp $
*
* code to decode ITU Q.931 call control messages
*
* Author Jan den Ouden
* Copyright by Jan den Ouden
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* Changelog:
*
* Pauline Middelink general improvements
* Beat Doebeli cause texts, display information element
* Karsten Keil cause texts, display information element for 1TR6
*
*/
#include "hisax.h"
#include "l3_1tr6.h"
void
iecpy(u_char *dest, u_char *iestart, int ieoffset)
{
u_char *p;
int l;
p = iestart + ieoffset + 2;
l = iestart[1] - ieoffset;
while (l--)
*dest++ = *p++;
*dest++ = '\0';
}
/*
* According to Table 4-2/Q.931
*/
static
struct MessageType {
u_char nr;
char *descr;
} mtlist[] = {
{
0x1, "ALERTING"
},
{
0x2, "CALL PROCEEDING"
},
{
0x7, "CONNECT"
},
{
0xf, "CONNECT ACKNOWLEDGE"
},
{
0x3, "PROGRESS"
},
{
0x5, "SETUP"
},
{
0xd, "SETUP ACKNOWLEDGE"
},
{
0x24, "HOLD"
},
{
0x28, "HOLD ACKNOWLEDGE"
},
{
0x30, "HOLD REJECT"
},
{
0x31, "RETRIEVE"
},
{
0x33, "RETRIEVE ACKNOWLEDGE"
},
{
0x37, "RETRIEVE REJECT"
},
{
0x26, "RESUME"
},
{
0x2e, "RESUME ACKNOWLEDGE"
},
{
0x22, "RESUME REJECT"
},
{
0x25, "SUSPEND"
},
{
0x2d, "SUSPEND ACKNOWLEDGE"
},
{
0x21, "SUSPEND REJECT"
},
{
0x20, "USER INFORMATION"
},
{
0x45, "DISCONNECT"
},
{
0x4d, "RELEASE"
},
{
0x5a, "RELEASE COMPLETE"
},
{
0x46, "RESTART"
},
{
0x4e, "RESTART ACKNOWLEDGE"
},
{
0x60, "SEGMENT"
},
{
0x79, "CONGESTION CONTROL"
},
{
0x7b, "INFORMATION"
},
{
0x62, "FACILITY"
},
{
0x6e, "NOTIFY"
},
{
0x7d, "STATUS"
},
{
0x75, "STATUS ENQUIRY"
}
};
#define MTSIZE ARRAY_SIZE(mtlist)
static
struct MessageType mt_n0[] =
{
{MT_N0_REG_IND, "REGister INDication"},
{MT_N0_CANC_IND, "CANCel INDication"},
{MT_N0_FAC_STA, "FACility STAtus"},
{MT_N0_STA_ACK, "STAtus ACKnowledge"},
{MT_N0_STA_REJ, "STAtus REJect"},
{MT_N0_FAC_INF, "FACility INFormation"},
{MT_N0_INF_ACK, "INFormation ACKnowledge"},
{MT_N0_INF_REJ, "INFormation REJect"},
{MT_N0_CLOSE, "CLOSE"},
{MT_N0_CLO_ACK, "CLOse ACKnowledge"}
};
#define MT_N0_LEN ARRAY_SIZE(mt_n0)
static
struct MessageType mt_n1[] =
{
{MT_N1_ESC, "ESCape"},
{MT_N1_ALERT, "ALERT"},
{MT_N1_CALL_SENT, "CALL SENT"},
{MT_N1_CONN, "CONNect"},
{MT_N1_CONN_ACK, "CONNect ACKnowledge"},
{MT_N1_SETUP, "SETUP"},
{MT_N1_SETUP_ACK, "SETUP ACKnowledge"},
{MT_N1_RES, "RESume"},
{MT_N1_RES_ACK, "RESume ACKnowledge"},
{MT_N1_RES_REJ, "RESume REJect"},
{MT_N1_SUSP, "SUSPend"},
{MT_N1_SUSP_ACK, "SUSPend ACKnowledge"},
{MT_N1_SUSP_REJ, "SUSPend REJect"},
{MT_N1_USER_INFO, "USER INFO"},
{MT_N1_DET, "DETach"},
{MT_N1_DISC, "DISConnect"},
{MT_N1_REL, "RELease"},
{MT_N1_REL_ACK, "RELease ACKnowledge"},
{MT_N1_CANC_ACK, "CANCel ACKnowledge"},
{MT_N1_CANC_REJ, "CANCel REJect"},
{MT_N1_CON_CON, "CONgestion CONtrol"},
{MT_N1_FAC, "FACility"},
{MT_N1_FAC_ACK, "FACility ACKnowledge"},
{MT_N1_FAC_CAN, "FACility CANcel"},
{MT_N1_FAC_REG, "FACility REGister"},
{MT_N1_FAC_REJ, "FACility REJect"},
{MT_N1_INFO, "INFOrmation"},
{MT_N1_REG_ACK, "REGister ACKnowledge"},
{MT_N1_REG_REJ, "REGister REJect"},
{MT_N1_STAT, "STATus"}
};
#define MT_N1_LEN ARRAY_SIZE(mt_n1)
static int
prbits(char *dest, u_char b, int start, int len)
{
char *dp = dest;
b = b << (8 - start);
while (len--) {
if (b & 0x80)
*dp++ = '1';
else
*dp++ = '0';
b = b << 1;
}
return (dp - dest);
}
static
u_char *
skipext(u_char *p)
{
while (!(*p++ & 0x80));
return (p);
}
/*
* Cause Values According to Q.850
* edescr: English description
* ddescr: German description used by Swissnet II (Swiss Telecom
* not yet written...
*/
static
struct CauseValue {
u_char nr;
char *edescr;
char *ddescr;
} cvlist[] = {
{
0x01, "Unallocated (unassigned) number", "Nummer nicht zugeteilt"
},
{
0x02, "No route to specified transit network", ""
},
{
0x03, "No route to destination", ""
},
{
0x04, "Send special information tone", ""
},
{
0x05, "Misdialled trunk prefix", ""
},
{
0x06, "Channel unacceptable", "Kanal nicht akzeptierbar"
},
{
0x07, "Channel awarded and being delivered in an established channel", ""
},
{
0x08, "Preemption", ""
},
{
0x09, "Preemption - circuit reserved for reuse", ""
},
{
0x10, "Normal call clearing", "Normale Ausloesung"
},
{
0x11, "User busy", "TNB besetzt"
},
{
0x12, "No user responding", ""
},
{
0x13, "No answer from user (user alerted)", ""
},
{
0x14, "Subscriber absent", ""
},
{
0x15, "Call rejected", ""
},
{
0x16, "Number changed", ""
},
{
0x1a, "non-selected user clearing", ""
},
{
0x1b, "Destination out of order", ""
},
{
0x1c, "Invalid number format (address incomplete)", ""
},
{
0x1d, "Facility rejected", ""
},
{
0x1e, "Response to Status enquiry", ""
},
{
0x1f, "Normal, unspecified", ""
},
{
0x22, "No circuit/channel available", ""
},
{
0x26, "Network out of order", ""
},
{
0x27, "Permanent frame mode connection out-of-service", ""
},
{
0x28, "Permanent frame mode connection operational", ""
},
{
0x29, "Temporary failure", ""
},
{
0x2a, "Switching equipment congestion", ""
},
{
0x2b, "Access information discarded", ""
},
{
0x2c, "Requested circuit/channel not available", ""
},
{
0x2e, "Precedence call blocked", ""
},
{
0x2f, "Resource unavailable, unspecified", ""
},
{
0x31, "Quality of service unavailable", ""
},
{
0x32, "Requested facility not subscribed", ""
},
{
0x35, "Outgoing calls barred within CUG", ""
},
{
0x37, "Incoming calls barred within CUG", ""
},
{
0x39, "Bearer capability not authorized", ""
},
{
0x3a, "Bearer capability not presently available", ""
},
{
0x3e, "Inconsistency in designated outgoing access information and subscriber class ", " "
},
{
0x3f, "Service or option not available, unspecified", ""
},
{
0x41, "Bearer capability not implemented", ""
},
{
0x42, "Channel type not implemented", ""
},
{
0x43, "Requested facility not implemented", ""
},
{
0x44, "Only restricted digital information bearer capability is available", ""
},
{
0x4f, "Service or option not implemented", ""
},
{
0x51, "Invalid call reference value", ""
},
{
0x52, "Identified channel does not exist", ""
},
{
0x53, "A suspended call exists, but this call identity does not", ""
},
{
0x54, "Call identity in use", ""
},
{
0x55, "No call suspended", ""
},
{
0x56, "Call having the requested call identity has been cleared", ""
},
{
0x57, "User not member of CUG", ""
},
{
0x58, "Incompatible destination", ""
},
{
0x5a, "Non-existent CUG", ""
},
{
0x5b, "Invalid transit network selection", ""
},
{
0x5f, "Invalid message, unspecified", ""
},
{
0x60, "Mandatory information element is missing", ""
},
{
0x61, "Message type non-existent or not implemented", ""
},
{
0x62, "Message not compatible with call state or message type non-existent or not implemented ", " "
},
{
0x63, "Information element/parameter non-existent or not implemented", ""
},
{
0x64, "Invalid information element contents", ""
},
{
0x65, "Message not compatible with call state", ""
},
{
0x66, "Recovery on timer expiry", ""
},
{
0x67, "Parameter non-existent or not implemented - passed on", ""
},
{
0x6e, "Message with unrecognized parameter discarded", ""
},
{
0x6f, "Protocol error, unspecified", ""
},
{
0x7f, "Interworking, unspecified", ""
},
};
#define CVSIZE ARRAY_SIZE(cvlist)
static
int
prcause(char *dest, u_char *p)
{
u_char *end;
char *dp = dest;
int i, cause;
end = p + p[1] + 1;
p += 2;
dp += sprintf(dp, " coding ");
dp += prbits(dp, *p, 7, 2);
dp += sprintf(dp, " location ");
dp += prbits(dp, *p, 4, 4);
*dp++ = '\n';
p = skipext(p);
cause = 0x7f & *p++;
/* locate cause value */
for (i = 0; i < CVSIZE; i++)
if (cvlist[i].nr == cause)
|