diff options
Diffstat (limited to 'sys/i4b/layer3/i4b_q932fac.c')
-rw-r--r-- | sys/i4b/layer3/i4b_q932fac.c | 569 |
1 files changed, 569 insertions, 0 deletions
diff --git a/sys/i4b/layer3/i4b_q932fac.c b/sys/i4b/layer3/i4b_q932fac.c new file mode 100644 index 0000000..487ce00 --- /dev/null +++ b/sys/i4b/layer3/i4b_q932fac.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 1997, 1998 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_q932fac.c - Q932 facility handling + * -------------------------------------- + * + * $Id: i4b_q932fac.c,v 1.5 1998/12/05 18:05:41 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:34:11 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq931.h" +#else +#define NI4BQ931 1 +#endif +#if NI4BQ931 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer3/i4b_l3.h> +#include <i4b/layer3/i4b_l3fsm.h> +#include <i4b/layer3/i4b_q931.h> +#include <i4b/layer3/i4b_q932fac.h> + +#include <i4b/layer4/i4b_l4.h> + +static int do_component(int length); +static void next_state(int class, int form, int code, int val); + +static int byte_len; +static unsigned char *byte_buf; +static int state; + +static int units; +static int operation_value; + +/*---------------------------------------------------------------------------* + * decode Q.931/Q.932 facility info element + *---------------------------------------------------------------------------*/ +int +i4b_aoc(unsigned char *buf, call_desc_t *cd) +{ + int len; + + cd->units_type = CHARGE_INVALID; + cd->units = -1; + + buf++; /* length */ + + len = *buf; + + buf++; /* protocol profile */ + + switch(*buf & 0x1f) + { + case FAC_PROTO_ROP: + break; + + case FAC_PROTO_CMIP: + DBGL3(L3_A_MSG, "i4b_facility", ("CMIP Protocol (Q.941), UNSUPPORTED\n")); + return(-1); + break; + + case FAC_PROTO_ACSE: + DBGL3(L3_A_MSG, "i4b_facility", ("ACSE Protocol (X.217/X.227), UNSUPPORTED!\n")); + return(-1); + break; + + default: + DBGL3(L3_A_ERR, "i4b_facility", ("Unknown Protocol, UNSUPPORTED!\n")); + return(-1); + break; + } + + DBGL3(L3_A_MSG, "i4b_facility", ("Remote Operations Protocol\n")); + + /* next byte */ + + buf++; + len--; + + /* initialize variables for do_component */ + + byte_len = 0; + byte_buf = buf; + state = ST_EXP_COMP_TYP; + + /* decode facility */ + + do_component(len); + + switch(operation_value) + { + case FAC_OPVAL_AOC_D_CUR: + cd->units_type = CHARGE_AOCD; + cd->units = 0; + return(0); + break; + + case FAC_OPVAL_AOC_D_UNIT: + cd->units_type = CHARGE_AOCD; + cd->units = units; + return(0); + break; + + case FAC_OPVAL_AOC_E_CUR: + cd->units_type = CHARGE_AOCE; + cd->units = 0; + return(0); + break; + + case FAC_OPVAL_AOC_E_UNIT: + cd->units_type = CHARGE_AOCE; + cd->units = units; + return(0); + break; + + default: + cd->units_type = CHARGE_INVALID; + cd->units = -1; + return(-1); + break; + } + return(-1); +} + +/*---------------------------------------------------------------------------* + * handle a component recursively + *---------------------------------------------------------------------------*/ +static int +do_component(int length) +{ + int comp_tag_class; /* component tag class */ + int comp_tag_form; /* component form: constructor or primitive */ + int comp_tag_code; /* component code depending on class */ + int comp_length = 0; /* component length */ + +again: + + /*----------------------------------------*/ + /* first component element: component tag */ + /*----------------------------------------*/ + + /* tag class bits */ + + comp_tag_class = (*byte_buf & 0xc0) >> 6; + + switch(comp_tag_class) + { + case FAC_TAGCLASS_UNI: + break; + case FAC_TAGCLASS_APW: + break; + case FAC_TAGCLASS_COS: + break; + case FAC_TAGCLASS_PRU: + break; + } + + /* tag form bit */ + + comp_tag_form = (*byte_buf & 0x20) > 5; + + /* tag code bits */ + + comp_tag_code = *byte_buf & 0x1f; + + if(comp_tag_code == 0x1f) + { + comp_tag_code = 0; + + byte_buf++; + byte_len++; + + while(*byte_buf & 0x80) + { + comp_tag_code += (*byte_buf & 0x7f); + byte_buf++; + byte_len++; + } + comp_tag_code += (*byte_buf & 0x7f); + } + else + { + comp_tag_code = (*byte_buf & 0x1f); + } + + byte_buf++; + byte_len++; + + /*--------------------------------------------*/ + /* second component element: component length */ + /*--------------------------------------------*/ + + comp_length = 0; + + if(*byte_buf & 0x80) + { + int i = *byte_buf & 0x7f; + + byte_len += i; + + for(;i > 0;i++) + { + byte_buf++; + comp_length += (*byte_buf * (i*256)); + } + } + else + { + comp_length = *byte_buf & 0x7f; + } + + next_state(comp_tag_class, comp_tag_form, comp_tag_code, -1); + + byte_len++; + byte_buf++; + + /*---------------------------------------------*/ + /* third component element: component contents */ + /*---------------------------------------------*/ + + if(comp_tag_form) /* == constructor */ + { + do_component(comp_length); + } + else + { + int val = 0; + if(comp_tag_class == FAC_TAGCLASS_UNI) + { + switch(comp_tag_code) + { + case FAC_CODEUNI_INT: + case FAC_CODEUNI_ENUM: + case FAC_CODEUNI_BOOL: + if(comp_length) + { + int i; + + for(i = comp_length-1; i >= 0; i--) + { + val += (*byte_buf + (i*255)); + byte_buf++; + byte_len++; + } + } + break; + default: + if(comp_length) + { + int i; + + for(i = comp_length-1; i >= 0; i--) + { + byte_buf++; + byte_len++; + } + } + break; + } + } + + else /* comp_tag_class != FAC_TAGCLASS_UNI */ + { + if(comp_length) + { + int i; + + for(i = comp_length-1; i >= 0; i--) + { + val += (*byte_buf + (i*255)); + byte_buf++; + byte_len++; + } + } + } + next_state(comp_tag_class, comp_tag_form, comp_tag_code, val); + } + + if(byte_len < length) + goto again; + + return(byte_len); +} + +/*---------------------------------------------------------------------------* + * invoke component + *---------------------------------------------------------------------------*/ +static void +F_1_1(int val) +{ + if(val == -1) + { + state = ST_EXP_INV_ID; + } +} + +/*---------------------------------------------------------------------------* + * return result + *---------------------------------------------------------------------------*/ +static void +F_1_2(int val) +{ + if(val == -1) + state = ST_EXP_NIX; +} +/*---------------------------------------------------------------------------* + * return error + *---------------------------------------------------------------------------*/ +static void +F_1_3(int val) +{ + if(val == -1) + state = ST_EXP_NIX; +} +/*---------------------------------------------------------------------------* + * reject + *---------------------------------------------------------------------------*/ +static void +F_1_4(int val) +{ + if(val == -1) + state = ST_EXP_NIX; +} + +/*---------------------------------------------------------------------------* + * invoke id + *---------------------------------------------------------------------------*/ +static void +F_2(int val) +{ + if(val != -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Invoke ID = %d\n", val)); + state = ST_EXP_OP_VAL; + } +} + +/*---------------------------------------------------------------------------* + * operation value + *---------------------------------------------------------------------------*/ +static void +F_3(int val) +{ + if(val != -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Operation Value = %d\n", val)); + + operation_value = val; + + if((val == FAC_OPVAL_AOC_D_UNIT) || (val == FAC_OPVAL_AOC_E_UNIT)) + { + units = 0; + state = ST_EXP_INFO; + } + else + { + state = ST_EXP_NIX; + } + } +} + +/*---------------------------------------------------------------------------* + * specific charging units + *---------------------------------------------------------------------------*/ +static void +F_4(int val) +{ + if(val == -1) + state = ST_EXP_RUL; +} + +/*---------------------------------------------------------------------------* + * free of charge + *---------------------------------------------------------------------------*/ +static void +F_4_1(int val) +{ + if(val == -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Free of Charge\n")); + /* units = 0; XXXX */ + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * charge not available + *---------------------------------------------------------------------------*/ +static void +F_4_2(int val) +{ + if(val == -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Charge not available\n")); + /* units = -1; XXXXXX ??? */ + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * recorded units list + *---------------------------------------------------------------------------*/ +static void +F_5(int val) +{ + if(val == -1) + state = ST_EXP_RU; +} + +/*---------------------------------------------------------------------------* + * recorded units + *---------------------------------------------------------------------------*/ +static void +F_6(int val) +{ + if(val == -1) + state = ST_EXP_RNOU; +} + +/*---------------------------------------------------------------------------* + * number of units + *---------------------------------------------------------------------------*/ +static void +F_7(int val) +{ + if(val != -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Number of Units = %d\n", val)); + units = val; + state = ST_EXP_TOCI; + } +} + +/*---------------------------------------------------------------------------* + * subtotal/total + *---------------------------------------------------------------------------*/ +static void +F_8(int val) +{ + if(val != -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Subtotal/Total = %d\n", val)); + /* type_of_charge = val; */ + state = ST_EXP_DBID; + } +} + +/*---------------------------------------------------------------------------* + * billing_id + *---------------------------------------------------------------------------*/ +static void +F_9(int val) +{ + if(val != -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Billing ID = %d\n", val)); + /* billing_id = val; */ + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static struct statetab { + int currstate; /* input: current state we are in */ + int form; /* input: current tag form */ + int class; /* input: current tag class */ + int code; /* input: current tag code */ + void (*func)(int); /* output: func to exec */ +} statetab[] = { + +/* current state tag form tag class tag code function */ +/* --------------------- ---------------------- ---------------------- ---------------------- ----------------*/ + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_1_1 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 2, F_1_2 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 3, F_1_3 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 4, F_1_4 }, + {ST_EXP_INV_ID, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_2 }, + {ST_EXP_OP_VAL, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_3 }, + {ST_EXP_INFO, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_4 }, + {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_NULL, F_4_1 }, + {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 1, F_4_2 }, + {ST_EXP_RUL, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_5 }, + {ST_EXP_RU, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_6 }, + {ST_EXP_RNOU, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_7 }, + {ST_EXP_TOCI, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 2, F_8 }, + {ST_EXP_DBID, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 3, F_9 }, + {-1, -1, -1, -1, NULL } +}; + +/*---------------------------------------------------------------------------* + * state decode for do_component + *---------------------------------------------------------------------------*/ +static void +next_state(int class, int form, int code, int val) +{ + int i; + + for(i=0; ; i++) + { + if((statetab[i].currstate > state) || + (statetab[i].currstate == -1)) + { + break; + } + + if((statetab[i].currstate == state) && + (statetab[i].form == form) && + (statetab[i].class == class) && + (statetab[i].code == code)) + { + (*statetab[i].func)(val); + break; + } + } +} + +#endif /* NI4BQ931 > 0 */ |