diff options
Diffstat (limited to 'sys/i4b/layer3/i4b_q931.c')
-rw-r--r-- | sys/i4b/layer3/i4b_q931.c | 714 |
1 files changed, 0 insertions, 714 deletions
diff --git a/sys/i4b/layer3/i4b_q931.c b/sys/i4b/layer3/i4b_q931.c deleted file mode 100644 index 3f1eb2b..0000000 --- a/sys/i4b/layer3/i4b_q931.c +++ /dev/null @@ -1,714 +0,0 @@ -/*- - * Copyright (c) 1997, 2002 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 - * -------------------------------------------- - * last edit-date: [Sun Aug 11 19:18:08 2002] - * - *---------------------------------------------------------------------------*/ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/mbuf.h> - -#include <i4b/include/i4b_debug.h> -#include <i4b/include/i4b_ioctl.h> -#include <i4b/include/i4b_cause.h> - -#include <i4b/include/i4b_isdnq931.h> -#include <i4b/include/i4b_l3l4.h> -#include <i4b/include/i4b_global.h> - -#include <i4b/layer3/i4b_l3.h> -#include <i4b/layer3/i4b_l3fsm.h> -#include <i4b/layer3/i4b_q931.h> - -#include <i4b/layer4/i4b_l4.h> - -unsigned int i4b_l3_debug = L3_DEBUG_DEFAULT; - -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 -i4b_decode_q931(int unit, int msg_len, u_char *msg_ptr) -{ - 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--; - - s = SPLI4B(); /* this has to be protected ! */ - - /* 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 */ - - if((cd = cd_by_unitcr(unit, crval, - crflag == CRF_DEST ? CRF_ORIG : CRF_DEST)) == NULL) - { - if(*msg_ptr == SETUP) - { - /* get and init new calldescriptor */ - - cd = reserve_cd(); /* cdid filled in */ - cd->controller = utoc_tab[unit]; - 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 */ - - i4b_decode_q931_message(unit, cd, *msg_ptr); - 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: - offset = i4b_decode_q931_cs0_ie(unit, cd, msg_len, msg_ptr); - 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)) - { - if(ctrl_desc[cd->controller].bch_state[cd->channelid] == BCH_ST_FREE) - ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_RSVD; - 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; - } - - /* type of number (source) */ - switch ((msg_ptr[2] & 0x70) >> 4) - { - case 1: - cd->src_ton = TON_INTERNAT; - break; - case 2: - cd->src_ton = TON_NATIONAL; - break; - default: - cd->src_ton = TON_OTHER; - break; - } - NDBGL3(L3_P_MSG, "IEI_CALLINGPN = %s", cd->src_telno); - break; - - case IEI_CALLINGPS: /* calling party subaddress */ - memcpy(cd->src_subaddr, &msg_ptr[3], min(SUBADDR_MAX, msg_ptr[1]-1)); - cd->src_subaddr[min(SUBADDR_MAX, msg_ptr[1] - 1)] = '\0'; - NDBGL3(L3_P_MSG, "IEI_CALLINGPS = %s", cd->src_subaddr); - 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'; - - /* type of number (destination) */ - switch ((msg_ptr[2] & 0x70) >> 4) - { - case 1: - cd->dst_ton = TON_INTERNAT; - break; - case 2: - cd->dst_ton = TON_NATIONAL; - break; - default: - cd->dst_ton = TON_OTHER; - break; - } - - NDBGL3(L3_P_MSG, "IEI_CALLED = %s", cd->dst_telno); - break; - - case IEI_CALLEDPS: /* called party subaddress */ - memcpy(cd->dst_subaddr, &msg_ptr[3], min(SUBADDR_MAX, msg_ptr[1]-1)); - cd->dst_subaddr[min(SUBADDR_MAX, msg_ptr[1] - 1)] = '\0'; - NDBGL3(L3_P_MSG, "IEI_CALLEDPS = %s", cd->dst_subaddr); - 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); - } -} |