summaryrefslogtreecommitdiffstats
path: root/sys/i4b/layer3/i4b_q932fac.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/i4b/layer3/i4b_q932fac.c')
-rw-r--r--sys/i4b/layer3/i4b_q932fac.c569
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 */
OpenPOWER on IntegriCloud