2001-01-05 15:49:52 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
*---------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* i4b_q931.c - Q931 received messages handling
|
|
|
|
* --------------------------------------------
|
|
|
|
*
|
2001-07-08 14:33:58 +04:00
|
|
|
* $Id: i4b_q931.c,v 1.4 2001/07/08 10:33:59 martin Exp $
|
2001-01-05 15:49:52 +03:00
|
|
|
*
|
|
|
|
* $FreeBSD$
|
|
|
|
*
|
|
|
|
* last edit-date: [Fri Jan 5 11:33:47 2001]
|
|
|
|
*
|
|
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
#ifdef __FreeBSD__
|
|
|
|
#include "i4bq931.h"
|
|
|
|
#else
|
|
|
|
#define NI4BQ931 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if NI4BQ931 > 0
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <net/if.h>
|
|
|
|
|
|
|
|
#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
|
|
|
|
#include <sys/callout.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __FreeBSD__
|
|
|
|
#include <machine/i4b_debug.h>
|
|
|
|
#include <machine/i4b_ioctl.h>
|
|
|
|
#include <machine/i4b_cause.h>
|
|
|
|
#else
|
|
|
|
#include <netisdn/i4b_debug.h>
|
|
|
|
#include <netisdn/i4b_ioctl.h>
|
|
|
|
#include <netisdn/i4b_cause.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <netisdn/i4b_isdnq931.h>
|
2001-03-24 15:40:29 +03:00
|
|
|
#include <netisdn/i4b_l2.h>
|
2001-01-05 15:49:52 +03:00
|
|
|
#include <netisdn/i4b_l3l4.h>
|
|
|
|
#include <netisdn/i4b_mbuf.h>
|
|
|
|
#include <netisdn/i4b_global.h>
|
|
|
|
|
|
|
|
#include <netisdn/i4b_l3.h>
|
|
|
|
#include <netisdn/i4b_l3fsm.h>
|
|
|
|
#include <netisdn/i4b_q931.h>
|
|
|
|
|
|
|
|
#include <netisdn/i4b_l4.h>
|
|
|
|
|
|
|
|
unsigned int i4b_l3_debug = L3_DEBUG_DEFAULT;
|
|
|
|
|
|
|
|
call_desc_t call_desc[N_CALL_DESC]; /* call descriptor array */
|
|
|
|
ctrl_desc_t ctrl_desc[MAX_CONTROLLERS]; /* controller description array */
|
|
|
|
int utoc_tab[MAX_CONTROLLERS]; /* unit to controller conversion */
|
|
|
|
|
|
|
|
/* protocol independent causes -> Q.931 causes */
|
|
|
|
|
|
|
|
unsigned char cause_tab_q931[CAUSE_I4B_MAX] = {
|
|
|
|
CAUSE_Q850_NCCLR, /* CAUSE_I4B_NORMAL -> normal call clearing */
|
|
|
|
CAUSE_Q850_USRBSY, /* CAUSE_I4B_BUSY -> user busy */
|
|
|
|
CAUSE_Q850_NOCAVAIL, /* CAUSE_I4B_NOCHAN -> no circuit/channel available*/
|
|
|
|
CAUSE_Q850_INCDEST, /* CAUSE_I4B_INCOMP -> incompatible destination */
|
|
|
|
CAUSE_Q850_CALLREJ, /* CAUSE_I4B_REJECT -> call rejected */
|
|
|
|
CAUSE_Q850_DSTOOORDR, /* CAUSE_I4B_OOO -> destination out of order */
|
|
|
|
CAUSE_Q850_TMPFAIL, /* CAUSE_I4B_TMPFAIL -> temporary failure */
|
|
|
|
CAUSE_Q850_USRBSY, /* CAUSE_I4B_L1ERROR -> L1 error / persistent deact XXX */
|
|
|
|
CAUSE_Q850_USRBSY, /* CAUSE_I4B_LLDIAL -> no dialout on leased line XXX */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
|
|
* setup cr ref flag according to direction
|
|
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
unsigned char
|
|
|
|
setup_cr(call_desc_t *cd, unsigned char cr)
|
|
|
|
{
|
|
|
|
if(cd->crflag == CRF_ORIG)
|
|
|
|
return(cr & 0x7f); /* clear cr ref flag */
|
|
|
|
else if(cd->crflag == CRF_DEST)
|
|
|
|
return(cr | 0x80); /* set cr ref flag */
|
|
|
|
else
|
|
|
|
panic("setup_cr: invalid crflag!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
|
|
* decode and process a Q.931 message
|
|
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
void
|
2001-03-24 15:40:29 +03:00
|
|
|
i4b_decode_q931(int bri, int msg_len, u_char *msg_ptr)
|
2001-01-05 15:49:52 +03:00
|
|
|
{
|
|
|
|
call_desc_t *cd;
|
|
|
|
int codeset = CODESET_0;
|
|
|
|
int old_codeset = CODESET_0;
|
|
|
|
int shift_flag = UNSHIFTED;
|
|
|
|
int crlen = 0;
|
|
|
|
int crval = 0;
|
|
|
|
int crflag = 0;
|
|
|
|
int i;
|
|
|
|
int offset;
|
|
|
|
int s;
|
|
|
|
|
|
|
|
/* check protocol discriminator */
|
|
|
|
|
|
|
|
if(*msg_ptr != PD_Q931)
|
|
|
|
{
|
|
|
|
static int protoflag = -1; /* print only once .. */
|
|
|
|
|
|
|
|
if(*msg_ptr != protoflag)
|
|
|
|
{
|
|
|
|
NDBGL3(L3_P_ERR, "unknown protocol discriminator 0x%x!", *msg_ptr);
|
|
|
|
protoflag = *msg_ptr;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg_ptr++;
|
|
|
|
msg_len--;
|
|
|
|
|
2001-01-19 15:44:44 +03:00
|
|
|
s = splnet(); /* this has to be protected ! */
|
2001-01-05 15:49:52 +03:00
|
|
|
|
|
|
|
/* extract call reference */
|
|
|
|
|
|
|
|
crlen = *msg_ptr & CRLENGTH_MASK;
|
|
|
|
msg_ptr++;
|
|
|
|
msg_len--;
|
|
|
|
|
|
|
|
if(crlen != 0)
|
|
|
|
{
|
|
|
|
crval += *msg_ptr & 0x7f;
|
|
|
|
crflag = (*msg_ptr >> 7) & 0x01;
|
|
|
|
msg_ptr++;
|
|
|
|
msg_len--;
|
|
|
|
|
|
|
|
for(i=1; i < crlen; i++)
|
|
|
|
{
|
|
|
|
crval += *msg_ptr;
|
|
|
|
msg_ptr++;
|
|
|
|
msg_len--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
crval = 0;
|
|
|
|
crflag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
NDBGL3(L3_P_MSG, "Call Ref, len %d, val %d, flag %d", crlen, crval, crflag);
|
|
|
|
|
|
|
|
/* find or allocate calldescriptor */
|
|
|
|
|
2001-03-24 15:40:29 +03:00
|
|
|
if((cd = cd_by_unitcr(bri, crval,
|
2001-01-05 15:49:52 +03:00
|
|
|
crflag == CRF_DEST ? CRF_ORIG : CRF_DEST)) == NULL)
|
|
|
|
{
|
|
|
|
if(*msg_ptr == SETUP)
|
|
|
|
{
|
|
|
|
/* get and init new calldescriptor */
|
|
|
|
|
|
|
|
cd = reserve_cd(); /* cdid filled in */
|
2001-03-24 15:40:29 +03:00
|
|
|
cd->bri = bri;
|
2001-01-05 15:49:52 +03:00
|
|
|
cd->cr = crval;
|
|
|
|
cd->crflag = CRF_DEST; /* we are the dest side */
|
|
|
|
cd->ilt = NULL; /* reset link tab ptrs */
|
|
|
|
cd->dlt = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*XXX*/ if(crval != 0) /* ignore global call references */
|
|
|
|
{
|
|
|
|
NDBGL3(L3_P_ERR, "cannot find calldescriptor for cr = 0x%x, crflag = 0x%x, msg = 0x%x, frame = ", crval, crflag, *msg_ptr);
|
|
|
|
i4b_print_frame(msg_len, msg_ptr);
|
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
splx(s);
|
|
|
|
|
|
|
|
/* decode and handle message type */
|
|
|
|
|
2001-03-24 15:40:29 +03:00
|
|
|
i4b_decode_q931_message(bri, cd, *msg_ptr);
|
2001-01-05 15:49:52 +03:00
|
|
|
msg_ptr++;
|
|
|
|
msg_len--;
|
|
|
|
|
|
|
|
/* process information elements */
|
|
|
|
|
|
|
|
while(msg_len > 0)
|
|
|
|
{
|
|
|
|
/* check for shift codeset IE */
|
|
|
|
|
|
|
|
if((*msg_ptr & 0x80) && ((*msg_ptr & 0xf0) == SOIE_SHIFT))
|
|
|
|
{
|
|
|
|
if(!(*msg_ptr & SHIFT_LOCK))
|
|
|
|
shift_flag = SHIFTED;
|
|
|
|
|
|
|
|
old_codeset = codeset;
|
|
|
|
codeset = *msg_ptr & CODESET_MASK;
|
|
|
|
|
|
|
|
if((shift_flag != SHIFTED) &&
|
|
|
|
(codeset <= old_codeset))
|
|
|
|
{
|
|
|
|
NDBGL3(L3_P_ERR, "Q.931 lockingshift proc violation, shift %d -> %d", old_codeset, codeset);
|
|
|
|
codeset = old_codeset;
|
|
|
|
}
|
|
|
|
msg_len--;
|
|
|
|
msg_ptr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* process one IE for selected codeset */
|
|
|
|
|
|
|
|
switch(codeset)
|
|
|
|
{
|
|
|
|
case CODESET_0:
|
2001-03-24 15:40:29 +03:00
|
|
|
offset = i4b_decode_q931_cs0_ie(bri, cd, msg_len, msg_ptr);
|
2001-01-05 15:49:52 +03:00
|
|
|
msg_len -= offset;
|
|
|
|
msg_ptr += offset;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
NDBGL3(L3_P_ERR, "unknown codeset %d, ", codeset);
|
|
|
|
i4b_print_frame(msg_len, msg_ptr);
|
|
|
|
msg_len = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for non-locking shifts */
|
|
|
|
|
|
|
|
if(shift_flag == SHIFTED)
|
|
|
|
{
|
|
|
|
shift_flag = UNSHIFTED;
|
|
|
|
codeset = old_codeset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
next_l3state(cd, cd->event);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
|
|
* decode and process one Q.931 codeset 0 information element
|
|
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
int
|
|
|
|
i4b_decode_q931_cs0_ie(int unit, call_desc_t *cd, int msg_len, u_char *msg_ptr)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
switch(*msg_ptr)
|
|
|
|
{
|
|
|
|
|
|
|
|
/*********/
|
|
|
|
/* Q.931 */
|
|
|
|
/*********/
|
|
|
|
/* single byte IE's */
|
|
|
|
|
|
|
|
case IEI_SENDCOMPL:
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_SENDCOMPL");
|
|
|
|
return(1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* multi byte IE's */
|
|
|
|
|
|
|
|
case IEI_SEGMMSG: /* segmented message */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_SEGMENTED_MESSAGE");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_BEARERCAP: /* bearer capability */
|
|
|
|
switch(msg_ptr[2])
|
|
|
|
{
|
|
|
|
case 0x80: /* speech */
|
|
|
|
case 0x89: /* restricted digital info */
|
|
|
|
case 0x90: /* 3.1KHz audio */
|
|
|
|
/* XXX */ cd->bprot = BPROT_NONE;
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_BEARERCAP - Telephony");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 0x88: /* unrestricted digital info */
|
|
|
|
/* XXX */ cd->bprot = BPROT_RHDLC;
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_BEARERCAP - Raw HDLC");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* XXX */ cd->bprot = BPROT_NONE;
|
|
|
|
NDBGL3(L3_P_ERR, "IEI_BEARERCAP - Unsupported B-Protocol 0x%x", msg_ptr[2]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_CAUSE: /* cause */
|
|
|
|
if(msg_ptr[2] & 0x80)
|
|
|
|
{
|
|
|
|
cd->cause_in = msg_ptr[3] & 0x7f;
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CAUSE = %d", msg_ptr[3] & 0x7f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cd->cause_in = msg_ptr[4] & 0x7f;
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CAUSE = %d", msg_ptr[4] & 0x7f);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_CALLID: /* call identity */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CALL_IDENTITY");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_CALLSTATE: /* call state */
|
|
|
|
cd->call_state = msg_ptr[2] & 0x3f;
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CALLSTATE = %d", cd->call_state);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_CHANNELID: /* channel id */
|
|
|
|
if((msg_ptr[2] & 0xf4) != 0x80)
|
|
|
|
{
|
|
|
|
cd->channelid = CHAN_NO;
|
|
|
|
NDBGL3(L3_P_ERR, "IEI_CHANNELID, unsupported value 0x%x", msg_ptr[2]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch(msg_ptr[2] & 0x03)
|
|
|
|
{
|
|
|
|
case IE_CHAN_ID_NO:
|
|
|
|
cd->channelid = CHAN_NO;
|
|
|
|
break;
|
|
|
|
case IE_CHAN_ID_B1:
|
|
|
|
cd->channelid = CHAN_B1;
|
|
|
|
break;
|
|
|
|
case IE_CHAN_ID_B2:
|
|
|
|
cd->channelid = CHAN_B2;
|
|
|
|
break;
|
|
|
|
case IE_CHAN_ID_ANY:
|
|
|
|
cd->channelid = CHAN_ANY;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cd->channelexcl = (msg_ptr[2] & 0x08) >> 3;
|
|
|
|
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CHANNELID - channel %d, exclusive = %d", cd->channelid, cd->channelexcl);
|
|
|
|
|
|
|
|
/* if this is a setup message, reserve channel */
|
|
|
|
|
|
|
|
if(cd->event == EV_SETUP)
|
|
|
|
{
|
|
|
|
if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2))
|
|
|
|
{
|
2001-03-24 15:40:29 +03:00
|
|
|
if (i4b_l2_channel_get_state(unit, cd->channelid) == BCH_ST_FREE)
|
|
|
|
i4b_l2_channel_set_state(unit, cd->channelid, BCH_ST_RSVD);
|
2001-01-05 15:49:52 +03:00
|
|
|
else
|
|
|
|
NDBGL3(L3_P_ERR, "IE ChannelID, Channel NOT free!!");
|
|
|
|
}
|
|
|
|
else if(cd->channelid == CHAN_NO)
|
|
|
|
{
|
|
|
|
NDBGL3(L3_P_MSG, "IE ChannelID, SETUP with channel = No channel (CW)");
|
|
|
|
}
|
|
|
|
else /* cd->channelid == CHAN_ANY */
|
|
|
|
{
|
|
|
|
NDBGL3(L3_P_ERR, "ERROR: IE ChannelID, SETUP with channel = Any channel!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_PROGRESSI: /* progress indicator */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_PROGRESSINDICATOR");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_NETSPCFAC: /* network specific fac */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_NETSPCFAC");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_NOTIFIND: /* notification indicator */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_NOTIFICATION_INDICATOR");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_DISPLAY: /* display */
|
|
|
|
memcpy(cd->display, &msg_ptr[2], min(DISPLAY_MAX, msg_ptr[1]));
|
|
|
|
cd->display[min(DISPLAY_MAX, msg_ptr[1])] = '\0';
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_DISPLAY = %s", cd->display);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_DATETIME: /* date/time */
|
|
|
|
i = 2;
|
|
|
|
j = msg_ptr[1];
|
|
|
|
p = &(cd->datetime[0]);
|
|
|
|
*p = '\0';
|
|
|
|
|
|
|
|
for(j = msg_ptr[1]; j > 0; j--, i++)
|
|
|
|
sprintf(p+strlen(p), "%02d", msg_ptr[i]);
|
|
|
|
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_DATETIME = %s", cd->datetime);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_KEYPAD: /* keypad facility */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_KEYPAD_FACILITY");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_SIGNAL: /* signal type */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_SIGNAL = %d", msg_ptr[2]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_INFRATE: /* information rate */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_INFORMATION_RATE");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_ETETDEL: /* end to end transit delay */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_END_TO_END_TRANSIT_DELAY");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_CUG: /* closed user group */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CLOSED_USER_GROUP");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_CALLINGPN: /* calling party no */
|
|
|
|
if(msg_ptr[2] & 0x80) /* no presentation/screening indicator ? */
|
|
|
|
{
|
|
|
|
memcpy(cd->src_telno, &msg_ptr[3], min(TELNO_MAX, msg_ptr[1]-1));
|
|
|
|
cd->src_telno[min(TELNO_MAX, msg_ptr[1] - 1)] = '\0';
|
|
|
|
cd->scr_ind = SCR_NONE;
|
|
|
|
cd->prs_ind = PRS_NONE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(cd->src_telno, &msg_ptr[4], min(TELNO_MAX, msg_ptr[1]-2));
|
|
|
|
cd->src_telno[min(TELNO_MAX, msg_ptr[1] - 2)] = '\0';
|
|
|
|
cd->scr_ind = (msg_ptr[3] & 0x03) + SCR_USR_NOSC;
|
|
|
|
cd->prs_ind = ((msg_ptr[3] >> 5) & 0x03) + PRS_ALLOWED;
|
|
|
|
}
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CALLINGPN = %s", cd->src_telno);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_CALLINGPS: /* calling party subaddress */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CALLINGPS");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_CALLEDPN: /* called party number */
|
|
|
|
memcpy(cd->dst_telno, &msg_ptr[3], min(TELNO_MAX, msg_ptr[1]-1));
|
|
|
|
cd->dst_telno[min(TELNO_MAX, msg_ptr [1] - 1)] = '\0';
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CALLED = %s", cd->dst_telno);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_CALLEDPS: /* called party subaddress */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CALLEDPS");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_REDIRNO: /* redirecting number */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_REDIRECTING_NUMBER");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_TRNSEL: /* transit network selection */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_TRANSIT_NETWORK_SELECTION");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_RESTARTI: /* restart indicator */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_RESTART_INDICATOR");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_LLCOMPAT: /* low layer compat */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_LLCOMPAT");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_HLCOMPAT: /* high layer compat */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_HLCOMPAT");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_USERUSER: /* user-user */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_USER_USER");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IEI_ESCAPE: /* escape for extension */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_ESCAPE");
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*********/
|
|
|
|
/* Q.932 */
|
|
|
|
/*********/
|
|
|
|
case IEI_FACILITY: /* facility */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_FACILITY");
|
|
|
|
if(i4b_aoc(msg_ptr, cd) > -1)
|
|
|
|
i4b_l4_charging_ind(cd);
|
|
|
|
break;
|
|
|
|
|
|
|
|
/*********/
|
|
|
|
/* Q.95x */
|
|
|
|
/*********/
|
|
|
|
case IEI_CONCTDNO: /* connected number */
|
|
|
|
NDBGL3(L3_P_MSG, "IEI_CONCTDNO");
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
NDBGL3(L3_P_ERR, "Unknown IE %d - ", *msg_ptr);
|
|
|
|
i4b_print_frame(msg_ptr[1]+2, msg_ptr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return(msg_ptr[1] + 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------*
|
|
|
|
* decode and process one Q.931 codeset 0 information element
|
|
|
|
*---------------------------------------------------------------------------*/
|
|
|
|
void
|
|
|
|
i4b_decode_q931_message(int unit, call_desc_t *cd, u_char message_type)
|
|
|
|
{
|
|
|
|
char *m = NULL;
|
|
|
|
|
|
|
|
cd->event = EV_ILL;
|
|
|
|
|
|
|
|
switch(message_type)
|
|
|
|
{
|
|
|
|
/* call establishment */
|
|
|
|
|
|
|
|
case ALERT:
|
|
|
|
cd->event = EV_ALERT;
|
|
|
|
m = "ALERT";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CALL_PROCEEDING:
|
|
|
|
cd->event = EV_CALLPRC;
|
|
|
|
m = "CALL_PROCEEDING";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PROGRESS:
|
|
|
|
cd->event = EV_PROGIND;
|
|
|
|
m = "PROGRESS";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SETUP:
|
|
|
|
m = "SETUP";
|
|
|
|
cd->bprot = BPROT_NONE;
|
|
|
|
cd->cause_in = 0;
|
|
|
|
cd->cause_out = 0;
|
|
|
|
cd->dst_telno[0] = '\0';
|
|
|
|
cd->src_telno[0] = '\0';
|
|
|
|
cd->channelid = CHAN_NO;
|
|
|
|
cd->channelexcl = 0;
|
|
|
|
cd->display[0] = '\0';
|
|
|
|
cd->datetime[0] = '\0';
|
|
|
|
cd->event = EV_SETUP;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONNECT:
|
|
|
|
m = "CONNECT";
|
|
|
|
cd->datetime[0] = '\0';
|
|
|
|
cd->event = EV_CONNECT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SETUP_ACKNOWLEDGE:
|
|
|
|
m = "SETUP_ACKNOWLEDGE";
|
|
|
|
cd->event = EV_SETUPAK;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONNECT_ACKNOWLEDGE:
|
|
|
|
m = "CONNECT_ACKNOWLEDGE";
|
|
|
|
cd->event = EV_CONACK;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* call information */
|
|
|
|
|
|
|
|
case USER_INFORMATION:
|
|
|
|
m = "USER_INFORMATION";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SUSPEND_REJECT:
|
|
|
|
m = "SUSPEND_REJECT";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESUME_REJECT:
|
|
|
|
m = "RESUME_REJECT";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HOLD:
|
|
|
|
m = "HOLD";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SUSPEND:
|
|
|
|
m = "SUSPEND";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESUME:
|
|
|
|
m = "RESUME";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HOLD_ACKNOWLEDGE:
|
|
|
|
m = "HOLD_ACKNOWLEDGE";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SUSPEND_ACKNOWLEDGE:
|
|
|
|
m = "SUSPEND_ACKNOWLEDGE";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESUME_ACKNOWLEDGE:
|
|
|
|
m = "RESUME_ACKNOWLEDGE";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case HOLD_REJECT:
|
|
|
|
m = "HOLD_REJECT";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RETRIEVE:
|
|
|
|
m = "RETRIEVE";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RETRIEVE_ACKNOWLEDGE:
|
|
|
|
m = "RETRIEVE_ACKNOWLEDGE";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RETRIEVE_REJECT:
|
|
|
|
m = "RETRIEVE_REJECT";
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* call clearing */
|
|
|
|
|
|
|
|
case DISCONNECT:
|
|
|
|
m = "DISCONNECT";
|
|
|
|
cd->event = EV_DISCONN;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESTART:
|
|
|
|
m = "RESTART";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RELEASE:
|
|
|
|
m = "RELEASE";
|
|
|
|
cd->event = EV_RELEASE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESTART_ACKNOWLEDGE:
|
|
|
|
m = "RESTART_ACKNOWLEDGE";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RELEASE_COMPLETE:
|
|
|
|
m = "RELEASE_COMPLETE";
|
|
|
|
cd->event = EV_RELCOMP;
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* misc messages */
|
|
|
|
|
|
|
|
case SEGMENT:
|
|
|
|
m = "SEGMENT";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FACILITY:
|
|
|
|
m = "FACILITY";
|
|
|
|
cd->event = EV_FACILITY;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REGISTER:
|
|
|
|
m = "REGISTER";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NOTIFY:
|
|
|
|
m = "NOTIFY";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATUS_ENQUIRY:
|
|
|
|
m = "STATUS_ENQUIRY";
|
|
|
|
cd->event = EV_STATENQ;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CONGESTION_CONTROL:
|
|
|
|
m = "CONGESTION_CONTROL";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case INFORMATION:
|
|
|
|
m = "INFORMATION";
|
|
|
|
cd->event = EV_INFO;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATUS:
|
|
|
|
m = "STATUS";
|
|
|
|
cd->event = EV_STATUS;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
NDBGL3(L3_P_ERR, "unit %d, cr = 0x%02x, msg = 0x%02x", unit, cd->cr, message_type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(m)
|
|
|
|
{
|
|
|
|
NDBGL3(L3_PRIM, "%s: unit %d, cr = 0x%02x\n", m, unit, cd->cr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* NI4BQ931 > 0 */
|